diff --git a/src/components/Form/src/Form copy.vue b/src/components/Form/src/Form copy.vue new file mode 100644 index 0000000..94fe848 --- /dev/null +++ b/src/components/Form/src/Form copy.vue @@ -0,0 +1,302 @@ + + + diff --git a/src/components/Form/src/Form.vue b/src/components/Form/src/Form.vue index 5686668..0ce1af2 100644 --- a/src/components/Form/src/Form.vue +++ b/src/components/Form/src/Form.vue @@ -21,6 +21,7 @@ import { set } from 'lodash-es' import { FormProps } from './types' import { Icon } from '@/components/Icon' import { FormSchema, FormSetPropsType } from '@/types/form' +import { ComponentNameEnum } from '@/types/components.d' const { getPrefixCls } = useDesign() @@ -172,46 +173,55 @@ export default defineComponent({ // 渲染formItem const renderFormItem = (item: FormSchema) => { // 单独给只有options属性的组件做判断 - const notRenderOptions = ['SelectV2', 'Cascader', 'Transfer'] + // const notRenderOptions = ['SelectV2', 'Cascader', 'Transfer'] + const componentSlots = (item?.componentProps as any)?.slots || {} const slotsMap: Recordable = { - ...setItemComponentSlots(unref(formModel), item?.componentProps?.slots) + ...setItemComponentSlots(unref(formModel), componentSlots) } - if ( - item?.component !== 'SelectV2' && - item?.component !== 'Cascader' && - item?.componentProps?.options - ) { - slotsMap.default = () => renderOptions(item) + // 如果是select组件,并且没有自定义模板,自动渲染options + if (item.component === ComponentNameEnum.SELECT) { + slotsMap.default = !componentSlots.default + ? () => renderOptions(item) + : (option: any) => { + console.log(option) + return componentSlots.default(option) + } } + // if ( + // item?.component !== 'SelectV2' && + // item?.component !== 'Cascader' && + // item?.componentProps?.options + // ) { + // slotsMap.default = () => renderOptions(item) + // } - const formItemSlots: Recordable = setFormItemSlots(slots, item.field) + // const formItemSlots: Recordable = setFormItemSlots(slots, item.field) // 如果有 labelMessage,自动使用插槽渲染 - if (item?.labelMessage) { - formItemSlots.label = () => { - return ( - <> - {item.label} - - {{ - content: () => , - default: () => ( - - ) - }} - - - ) - } - } + // if (item?.labelMessage) { + // formItemSlots.label = () => { + // return ( + // <> + // {item.label} + // + // {{ + // content: () => , + // default: () => ( + // + // ) + // }} + // + // + // ) + // } + // } return ( {{ - ...formItemSlots, default: () => { const Com = componentMap[item.component as string] as ReturnType< typeof defineComponent @@ -227,10 +237,6 @@ export default defineComponent({ {...(autoSetPlaceholder && setTextPlaceholder(item))} {...setComponentProps(item)} style={item.componentProps?.style} - {...(notRenderOptions.includes(item?.component as string) && - item?.componentProps?.options - ? { options: item?.componentProps?.options || [] } - : {})} > {{ ...slotsMap }} @@ -244,7 +250,7 @@ export default defineComponent({ // 渲染options const renderOptions = (item: FormSchema) => { switch (item.component) { - case 'Select': + case ComponentNameEnum.SELECT: const { renderSelectOptions } = useRenderSelect(slots) return renderSelectOptions(item) case 'Radio': diff --git a/src/components/Form/src/components/useRenderSelect.tsx b/src/components/Form/src/components/useRenderSelect.tsx index e4b5a26..9421c0e 100644 --- a/src/components/Form/src/components/useRenderSelect.tsx +++ b/src/components/Form/src/components/useRenderSelect.tsx @@ -2,14 +2,15 @@ import { ElOption, ElOptionGroup } from 'element-plus' import { getSlot } from '@/utils/tsxHelper' import { Slots } from 'vue' import { FormSchema } from '@/types/form' -import { ComponentOptions } from '@/types/components' +import { SelectComponentProps, SelectOption } from '@/types/components' export const useRenderSelect = (slots: Slots) => { // 渲染 select options const renderSelectOptions = (item: FormSchema) => { + const componentsProps = item.componentProps as SelectComponentProps // 如果有别名,就取别名 - const labelAlias = item?.componentProps?.optionsAlias?.labelField - return item?.componentProps?.options?.map((option) => { + const labelAlias = componentsProps?.labelAlias + return componentsProps?.options?.map((option) => { if (option?.options?.length) { return ( @@ -27,10 +28,11 @@ export const useRenderSelect = (slots: Slots) => { } // 渲染 select option item - const renderSelectOptionItem = (item: FormSchema, option: ComponentOptions) => { + const renderSelectOptionItem = (item: FormSchema, option: SelectOption) => { // 如果有别名,就取别名 - const labelAlias = item?.componentProps?.optionsAlias?.labelField - const valueAlias = item?.componentProps?.optionsAlias?.valueField + const componentsProps = item.componentProps as SelectComponentProps + const labelAlias = componentsProps?.labelAlias + const valueAlias = componentsProps?.valueAlias const { label, value, ...other } = option @@ -43,7 +45,7 @@ export const useRenderSelect = (slots: Slots) => { {{ default: () => // option 插槽名规则,{field}-option - item?.componentProps?.optionsSlot + componentsProps?.optionsSlot ? getSlot(slots, `${item.field}-option`, { item: option }) : undefined }} diff --git a/src/types/components.d.ts b/src/types/components.d.ts index 05bb0bb..e132fad 100644 --- a/src/types/components.d.ts +++ b/src/types/components.d.ts @@ -78,6 +78,7 @@ export interface InputComponentProps { prepend?: JSX.Element | ((item: any, data: any) => JSX.Element) append?: JSX.Element | ((item: any, data: any) => JSX.Element) } + style?: CSSProperties } export interface AutocompleteComponentProps { @@ -110,6 +111,7 @@ export interface AutocompleteComponentProps { prepend?: JSX.Element | ((item: any, data: any) => JSX.Element) append?: JSX.Element | ((item: any, data: any) => JSX.Element) } + style?: CSSProperties } export interface InputNumberComponentProps { @@ -135,6 +137,102 @@ export interface InputNumberComponentProps { blur?: (event: FocusEvent) => void focus?: (event: FocusEvent) => void } + style?: CSSProperties +} + +interface SelectOption { + label?: string + disabled?: boolean + value?: any + key?: string | number + options?: SelectOption[] + [key: string]: any +} + +export interface SelectComponentProps { + value?: Array | string | number | boolean | Object + multiple?: boolean + disabled?: boolean + valueKey?: string + size?: InputNumberProps['size'] + clearable?: boolean + collapseTags?: boolean + collapseTagsTooltip?: number + multipleLimit?: number + name?: string + effect?: string + autocomplete?: string + placeholder?: string + filterable?: boolean + allowCreate?: boolean + filterMethod?: (query: string, item: any) => boolean + remote?: boolean + remoteMethod?: (query: string) => void + remoteShowSuffix?: boolean + loading?: boolean + loadingText?: string + noMatchText?: string + noDataText?: string + popperClass?: string + reserveKeyword?: boolean + defaultFirstOption?: boolean + popperAppendToBody?: boolean + teleported?: boolean + persistent?: boolean + automaticDropdown?: boolean + clearIcon?: string | JSX.Element | ((item: any, data: any) => string | JSX.Element) + fitInputWidth?: boolean + suffixIcon?: string | JSX.Element | ((item: any, data: any) => string | JSX.Element) + tagType?: 'success' | 'info' | 'warning' | 'danger' + validateEvent?: boolean + placement?: + | 'top' + | 'top-start' + | 'top-end' + | 'bottom' + | 'bottom-start' + | 'bottom-end' + | 'left' + | 'left-start' + | 'left-end' + | 'right' + | 'right-start' + | 'right-end' + maxCollapseTags?: number + /** + * label别名 + */ + labelAlias?: string + + /** + * value别名 + */ + valueAlias?: string + + /** + * key别名 + */ + keyAlias?: string + + /** + * option是否禁用的统一拦截 + */ + optionDisabled?: (optin: any, data: any) => boolean + on?: { + change?: (value: string | number | boolean | Object) => void + visibleChange?: (visible: boolean) => void + removeTag?: (tag: any) => void + clear?: () => void + blur?: (event: FocusEvent) => void + focus?: (event: FocusEvent) => void + } + slots?: { + default?: (item: any) => JSX.Element + prefix?: JSX.Element | ((item: any, data: any) => JSX.Element) + empty?: JSX.Element | ((item: any, data: any) => JSX.Element) + } + options?: SelectOption[] + style?: CSSProperties } export interface ColProps { @@ -149,7 +247,7 @@ export interface ColProps { export interface ComponentOptions extends Recordable { label?: string - value?: FormValueType + value?: any disabled?: boolean key?: string | number children?: ComponentOptions[] diff --git a/src/types/form.d.ts b/src/types/form.d.ts index 131a161..5530c99 100644 --- a/src/types/form.d.ts +++ b/src/types/form.d.ts @@ -5,7 +5,8 @@ import { ComponentName, InputComponentProps, AutocompleteComponentProps, - InputNumberComponentProps + InputNumberComponentProps, + SelectComponentProps } from '@/types/components' import { FormValueType, FormValueType } from '@/types/form' import type { AxiosPromise } from 'axios' @@ -52,7 +53,11 @@ export interface FormSchema { /** * 表单组件属性,具体可以查看element-plus文档 */ - componentProps?: InputComponentProps | AutocompleteComponentProps | InputNumberComponentProps + componentProps?: + | InputComponentProps + | AutocompleteComponentProps + | InputNumberComponentProps + | SelectComponentProps /** * formItem组件属性,具体可以查看element-plus文档 diff --git a/src/views/Components/Form/DefaultForm.vue b/src/views/Components/Form/DefaultForm.vue index 5670add..3902705 100644 --- a/src/views/Components/Form/DefaultForm.vue +++ b/src/views/Components/Form/DefaultForm.vue @@ -499,49 +499,65 @@ const schema = reactive([ controlsPosition: 'right' }, value: 10 + }, + { + field: 'field13', + label: t('formDemo.select'), + component: 'Divider' + }, + { + field: 'field14', + label: t('formDemo.default'), + component: 'Select', + componentProps: { + optionDisabled: (item: any, data: any) => { + console.log(item, data) + return false + }, + options: [ + { + disabled: true, + label: 'option1', + value: '1' + }, + { + label: 'option2', + value: '2' + } + ] + } + }, + { + field: 'field15', + label: t('formDemo.slot'), + component: 'Select', + componentProps: { + options: [ + { + label: 'option1', + value: '1' + }, + { + label: 'option2', + value: '2' + } + ], + slots: { + default: (item) => { + console.log(item) + return ( + <> + {item.label} + + {item.value} + + + ) + } + } + } } // { - // field: 'field13', - // label: t('formDemo.select'), - // component: 'Divider' - // }, - // { - // field: 'field14', - // label: t('formDemo.default'), - // component: 'Select', - // componentProps: { - // options: [ - // { - // disabled: true, - // label: 'option1', - // value: '1' - // }, - // { - // label: 'option2', - // value: '2' - // } - // ] - // } - // }, - // { - // field: 'field15', - // label: t('formDemo.slot'), - // component: 'Select', - // componentProps: { - // options: [ - // { - // label: 'option1', - // value: '1' - // }, - // { - // label: 'option2', - // value: '2' - // } - // ], - // optionsSlot: true - // } - // }, - // { // field: 'field16', // label: t('formDemo.selectGroup'), // component: 'Select',