diff --git a/src/components/Form/src/helper.ts b/src/components/Form/src/helper.ts index f58b7f1..f8c3a64 100644 --- a/src/components/Form/src/helper.ts +++ b/src/components/Form/src/helper.ts @@ -1,5 +1,5 @@ import { useI18n } from '@/hooks/web/useI18n' -import type { Slots } from 'vue' +import { unref, type Slots } from 'vue' import { getSlot } from '@/utils/tsxHelper' import { PlaceholderMoel } from './types' import { FormSchema } from '@/types/form' @@ -74,12 +74,14 @@ export const setGridProp = (col: ColProps = {}): ColProps => { */ export const setComponentProps = (item: FormSchema): Recordable => { // const notNeedClearable = ['ColorPicker'] - const componentProps = { + const componentProps: Recordable = { clearable: true, ...item.componentProps } // 需要删除额外的属性 - delete componentProps?.slots + if (componentProps.slots) { + delete componentProps.slots + } return componentProps } @@ -93,8 +95,8 @@ export const setItemComponentSlots = (formModel: any, slotsProps: Recordable = { for (const key in slotsProps) { if (slotsProps[key]) { if (isFunction(slotsProps[key])) { - slotObj[key] = () => { - return slotsProps[key]?.(formModel) + slotObj[key] = (item: any) => { + return slotsProps[key]?.(unref(item?.item) || undefined, formModel) } } else { slotObj[key] = () => { diff --git a/src/locales/en.ts b/src/locales/en.ts index 6f097b6..26a9a02 100644 --- a/src/locales/en.ts +++ b/src/locales/en.ts @@ -214,7 +214,9 @@ export default { default: 'Default', icon: 'Icon', mixed: 'Mixed', + password: 'Password', textarea: 'Textarea', + remoteSearch: 'Remote search', slot: 'Slot', position: 'Position', autocomplete: 'Autocomplete', diff --git a/src/locales/zh-CN.ts b/src/locales/zh-CN.ts index 6fa0531..165e268 100644 --- a/src/locales/zh-CN.ts +++ b/src/locales/zh-CN.ts @@ -214,7 +214,9 @@ export default { default: '默认', icon: '图标', mixed: '复合型', + password: '密码框', textarea: '多行文本', + remoteSearch: '远程搜索', slot: '插槽', position: '位置', autocomplete: '自动补全', diff --git a/src/types/components.d.ts b/src/types/components.d.ts index fbc7c49..05bb0bb 100644 --- a/src/types/components.d.ts +++ b/src/types/components.d.ts @@ -1,5 +1,5 @@ import { CSSProperties } from 'vue' -import { InputProps } from 'element-plus' +import { InputProps, AutocompleteProps, InputNumberProps } from 'element-plus' export enum ComponentNameEnum { RADIO = 'Radio', @@ -25,6 +25,16 @@ export enum ComponentNameEnum { EDITOR = 'Editor' } +type CamelCaseComponentName = keyof typeof ComponentNameEnum extends infer K + ? K extends string + ? K extends `${infer A}_${infer B}` + ? `${Capitalize>}${Capitalize>}` + : Capitalize> + : never + : never + +export type ComponentName = CamelCaseComponentName + export interface InputComponentProps { value?: string | number maxlength?: number | string @@ -37,8 +47,8 @@ export interface InputComponentProps { showPassword?: boolean disabled?: boolean size?: InputProps['size'] - prefixIcon?: string | JSX.Element | ((data: T | any) => string | JSX.Element) - suffixIcon?: string | JSX.Element | ((data: T | any) => string | JSX.Element) + prefixIcon?: string | JSX.Element | ((item: any, data: any) => string | JSX.Element) + suffixIcon?: string | JSX.Element | ((item: any, data: any) => string | JSX.Element) type?: InputProps['type'] rows?: number autosize?: boolean | { Pows?: numer; maxRows?: number } @@ -63,22 +73,69 @@ export interface InputComponentProps { input?: (value: string | number) => void } slots?: { - prefix?: JSX.Element | ((data: T | any) => JSX.Element) - suffix?: JSX.Element | ((data: T | any) => JSX.Element) - prepend?: JSX.Element | ((data: T | any) => JSX.Element) - append?: JSX.Element | ((data: T | any) => JSX.Element) + prefix?: JSX.Element | ((item: any, data: any) => JSX.Element) + suffix?: JSX.Element | ((item: any, data: any) => JSX.Element) + prepend?: JSX.Element | ((item: any, data: any) => JSX.Element) + append?: JSX.Element | ((item: any, data: any) => JSX.Element) } } -type CamelCaseComponentName = keyof typeof ComponentNameEnum extends infer K - ? K extends string - ? K extends `${infer A}_${infer B}` - ? `${Capitalize>}${Capitalize>}` - : Capitalize> - : never - : never +export interface AutocompleteComponentProps { + value?: string + placeholder?: string + clearable?: boolean + disabled?: boolean + valueKey?: string + debounce?: number + placement?: AutocompleteProps['placement'] + fetchSuggestions?: (queryString: string, callback: (data: string[]) => void) => void + triggerOnFocus?: boolean + selectWhenUnmatched?: boolean + name?: string + label?: string + hideLoading?: boolean + popperClass?: string + popperAppendToBody?: boolean + teleported?: boolean + highlightFirstItem?: boolean + fitInputWidth?: boolean + on?: { + select?: (item: any) => void + change?: (value: string | number) => void + } + slots?: { + default?: JSX.Element | ((item: any, data: any) => JSX.Element) + prefix?: JSX.Element | ((item: any, data: any) => JSX.Element) + suffix?: JSX.Element | ((item: any, data: any) => JSX.Element) + prepend?: JSX.Element | ((item: any, data: any) => JSX.Element) + append?: JSX.Element | ((item: any, data: any) => JSX.Element) + } +} -export type ComponentName = CamelCaseComponentName +export interface InputNumberComponentProps { + value?: number + min?: number + max?: number + step?: number + stepStrictly?: boolean + precision?: number + size?: InputNumberProps['size'] + readonly?: boolean + disabled?: boolean + controls?: boolean + controlsPosition?: InputNumberProps['controlsPosition'] + name?: string + label?: string + placeholder?: string + id?: string + valueOnClear?: number | null | 'min' | 'max' + validateEvent?: boolean + on?: { + change?: (currentValue: number | undefined, oldValue: number | undefined) => void + blur?: (event: FocusEvent) => void + focus?: (event: FocusEvent) => void + } +} export interface ColProps { span?: number diff --git a/src/types/form.d.ts b/src/types/form.d.ts index ee38385..131a161 100644 --- a/src/types/form.d.ts +++ b/src/types/form.d.ts @@ -3,8 +3,9 @@ import { ColProps, ComponentProps, ComponentName, - ComponentNameEnum, - InputComponentProps + InputComponentProps, + AutocompleteComponentProps, + InputNumberComponentProps } from '@/types/components' import { FormValueType, FormValueType } from '@/types/form' import type { AxiosPromise } from 'axios' @@ -28,29 +29,53 @@ export type FormItemProps = { } export interface FormSchema { - // 唯一值 + /** + * 唯一标识 + */ field: string - // 标题 - label?: string - // 提示 - labelMessage?: string - // col组件属性 - colProps?: ColProps - // 表单组件属性,slots对应的是表单组件的插槽,规则:${field}-xxx,具体可以查看element-plus文档 - // componentProps?: { slots?: Recordable } & ComponentProps /** - * 表单组件属性,slots对应的是表单组件的插槽,规则:${field}-xxx,具体可以查看element-plus文档 + * 标题 + */ + label?: string + + /** + * 提示信息 + */ + labelMessage?: string + + /** + * col组件属性 + */ + colProps?: ColProps + + /** + * 表单组件属性,具体可以查看element-plus文档 + */ + componentProps?: InputComponentProps | AutocompleteComponentProps | InputNumberComponentProps + + /** + * formItem组件属性,具体可以查看element-plus文档 */ - componentProps?: InputComponentProps - // formItem组件属性 formItemProps?: FormItemProps - // 渲染的组件 + + /** + * 渲染的组件名称 + */ component?: ComponentName - // 初始值 + + /** + * 初始值 + */ value?: FormValueType - // 是否隐藏 + + /** + * 是否隐藏 + */ hidden?: boolean - // 远程加载下拉项 + + /** + * @returns 远程加载下拉项 + */ api?: () => AxiosPromise } diff --git a/src/views/Components/Form/DefaultForm.vue b/src/views/Components/Form/DefaultForm.vue index 7415bb3..5670add 100644 --- a/src/views/Components/Form/DefaultForm.vue +++ b/src/views/Components/Form/DefaultForm.vue @@ -1,4 +1,4 @@ -