mirror of
				https://gitee.com/hhyykk/ipms-sjy.git
				synced 2025-11-01 02:38:43 +08:00 
			
		
		
		
	feat: add vue3(element-plus)
This commit is contained in:
		
							
								
								
									
										14
									
								
								yudao-ui-admin-vue3/src/components/Form/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								yudao-ui-admin-vue3/src/components/Form/index.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | ||||
| import Form from './src/Form.vue' | ||||
| import { ElForm } from 'element-plus' | ||||
|  | ||||
| export interface FormExpose { | ||||
|   setValues: (data: Recordable) => void | ||||
|   setProps: (props: Recordable) => void | ||||
|   delSchema: (field: string) => void | ||||
|   addSchema: (formSchema: FormSchema, index?: number) => void | ||||
|   setSchema: (schemaProps: FormSetPropsType[]) => void | ||||
|   formModel: Recordable | ||||
|   getElFormRef: () => ComponentRef<typeof ElForm> | ||||
| } | ||||
|  | ||||
| export { Form } | ||||
							
								
								
									
										299
									
								
								yudao-ui-admin-vue3/src/components/Form/src/Form.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										299
									
								
								yudao-ui-admin-vue3/src/components/Form/src/Form.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,299 @@ | ||||
| <script lang="tsx"> | ||||
| import { PropType, defineComponent, ref, computed, unref, watch, onMounted } from 'vue' | ||||
| import { ElForm, ElFormItem, ElRow, ElCol, ElTooltip } from 'element-plus' | ||||
| import { componentMap } from './componentMap' | ||||
| import { propTypes } from '@/utils/propTypes' | ||||
| import { getSlot } from '@/utils/tsxHelper' | ||||
| import { | ||||
|   setTextPlaceholder, | ||||
|   setGridProp, | ||||
|   setComponentProps, | ||||
|   setItemComponentSlots, | ||||
|   initModel, | ||||
|   setFormItemSlots | ||||
| } from './helper' | ||||
| import { useRenderSelect } from './components/useRenderSelect' | ||||
| import { useRenderRadio } from './components/useRenderRadio' | ||||
| import { useRenderCheckbox } from './components/useRenderCheckbox' | ||||
| import { useDesign } from '@/hooks/web/useDesign' | ||||
| import { findIndex } from '@/utils' | ||||
| import { set } from 'lodash-es' | ||||
| import { FormProps } from './types' | ||||
| import { Icon } from '@/components/Icon' | ||||
|  | ||||
| const { getPrefixCls } = useDesign() | ||||
|  | ||||
| const prefixCls = getPrefixCls('form') | ||||
|  | ||||
| export default defineComponent({ | ||||
|   name: 'Form', | ||||
|   props: { | ||||
|     // 生成Form的布局结构数组 | ||||
|     schema: { | ||||
|       type: Array as PropType<FormSchema[]>, | ||||
|       default: () => [] | ||||
|     }, | ||||
|     // 是否需要栅格布局 | ||||
|     isCol: propTypes.bool.def(true), | ||||
|     // 表单数据对象 | ||||
|     model: { | ||||
|       type: Object as PropType<Recordable>, | ||||
|       default: () => ({}) | ||||
|     }, | ||||
|     // 是否自动设置placeholder | ||||
|     autoSetPlaceholder: propTypes.bool.def(true), | ||||
|     // 是否自定义内容 | ||||
|     isCustom: propTypes.bool.def(false), | ||||
|     // 表单label宽度 | ||||
|     labelWidth: propTypes.oneOfType([String, Number]).def('auto') | ||||
|   }, | ||||
|   emits: ['register'], | ||||
|   setup(props, { slots, expose, emit }) { | ||||
|     // element form 实例 | ||||
|     const elFormRef = ref<ComponentRef<typeof ElForm>>() | ||||
|  | ||||
|     // useForm传入的props | ||||
|     const outsideProps = ref<FormProps>({}) | ||||
|  | ||||
|     const mergeProps = ref<FormProps>({}) | ||||
|  | ||||
|     const getProps = computed(() => { | ||||
|       const propsObj = { ...props } | ||||
|       Object.assign(propsObj, unref(mergeProps)) | ||||
|       return propsObj | ||||
|     }) | ||||
|  | ||||
|     // 表单数据 | ||||
|     const formModel = ref<Recordable>({}) | ||||
|  | ||||
|     onMounted(() => { | ||||
|       emit('register', unref(elFormRef)?.$parent, unref(elFormRef)) | ||||
|     }) | ||||
|  | ||||
|     // 对表单赋值 | ||||
|     const setValues = (data: Recordable = {}) => { | ||||
|       formModel.value = Object.assign(unref(formModel), data) | ||||
|     } | ||||
|  | ||||
|     const setProps = (props: FormProps = {}) => { | ||||
|       mergeProps.value = Object.assign(unref(mergeProps), props) | ||||
|       outsideProps.value = props | ||||
|     } | ||||
|  | ||||
|     const delSchema = (field: string) => { | ||||
|       const { schema } = unref(getProps) | ||||
|  | ||||
|       const index = findIndex(schema, (v: FormSchema) => v.field === field) | ||||
|       if (index > -1) { | ||||
|         schema.splice(index, 1) | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     const addSchema = (formSchema: FormSchema, index?: number) => { | ||||
|       const { schema } = unref(getProps) | ||||
|       if (index !== void 0) { | ||||
|         schema.splice(index, 0, formSchema) | ||||
|         return | ||||
|       } | ||||
|       schema.push(formSchema) | ||||
|     } | ||||
|  | ||||
|     const setSchema = (schemaProps: FormSetPropsType[]) => { | ||||
|       const { schema } = unref(getProps) | ||||
|       for (const v of schema) { | ||||
|         for (const item of schemaProps) { | ||||
|           if (v.field === item.field) { | ||||
|             set(v, item.path, item.value) | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     const getElFormRef = (): ComponentRef<typeof ElForm> => { | ||||
|       return unref(elFormRef) as ComponentRef<typeof ElForm> | ||||
|     } | ||||
|  | ||||
|     expose({ | ||||
|       setValues, | ||||
|       formModel, | ||||
|       setProps, | ||||
|       delSchema, | ||||
|       addSchema, | ||||
|       setSchema, | ||||
|       getElFormRef | ||||
|     }) | ||||
|  | ||||
|     // 监听表单结构化数组,重新生成formModel | ||||
|     watch( | ||||
|       () => unref(getProps).schema, | ||||
|       (schema = []) => { | ||||
|         formModel.value = initModel(schema, unref(formModel)) | ||||
|       }, | ||||
|       { | ||||
|         immediate: true, | ||||
|         deep: true | ||||
|       } | ||||
|     ) | ||||
|  | ||||
|     // 渲染包裹标签,是否使用栅格布局 | ||||
|     const renderWrap = () => { | ||||
|       const { isCol } = unref(getProps) | ||||
|       const content = isCol ? ( | ||||
|         <ElRow gutter={20}>{renderFormItemWrap()}</ElRow> | ||||
|       ) : ( | ||||
|         renderFormItemWrap() | ||||
|       ) | ||||
|       return content | ||||
|     } | ||||
|  | ||||
|     // 是否要渲染el-col | ||||
|     const renderFormItemWrap = () => { | ||||
|       // hidden属性表示隐藏,不做渲染 | ||||
|       const { schema = [], isCol } = unref(getProps) | ||||
|  | ||||
|       return schema | ||||
|         .filter((v) => !v.hidden) | ||||
|         .map((item) => { | ||||
|           // 如果是 Divider 组件,需要自己占用一行 | ||||
|           const isDivider = item.component === 'Divider' | ||||
|           const Com = componentMap['Divider'] as ReturnType<typeof defineComponent> | ||||
|           return isDivider ? ( | ||||
|             <Com {...{ contentPosition: 'left', ...item.componentProps }}>{item?.label}</Com> | ||||
|           ) : isCol ? ( | ||||
|             // 如果需要栅格,需要包裹 ElCol | ||||
|             <ElCol {...setGridProp(item.colProps)}>{renderFormItem(item)}</ElCol> | ||||
|           ) : ( | ||||
|             renderFormItem(item) | ||||
|           ) | ||||
|         }) | ||||
|     } | ||||
|  | ||||
|     // 渲染formItem | ||||
|     const renderFormItem = (item: FormSchema) => { | ||||
|       // 单独给只有options属性的组件做判断 | ||||
|       const notRenderOptions = ['SelectV2', 'Cascader', 'Transfer'] | ||||
|       const slotsMap: Recordable = { | ||||
|         ...setItemComponentSlots(slots, item?.componentProps?.slots, item.field) | ||||
|       } | ||||
|       if ( | ||||
|         item?.component !== 'SelectV2' && | ||||
|         item?.component !== 'Cascader' && | ||||
|         item?.componentProps?.options | ||||
|       ) { | ||||
|         slotsMap.default = () => renderOptions(item) | ||||
|       } | ||||
|  | ||||
|       const formItemSlots: Recordable = setFormItemSlots(slots, item.field) | ||||
|       // 如果有 labelMessage,自动使用插槽渲染 | ||||
|       if (item?.labelMessage) { | ||||
|         formItemSlots.label = () => { | ||||
|           return ( | ||||
|             <> | ||||
|               <span>{item.label}</span> | ||||
|               <ElTooltip placement="right" raw-content> | ||||
|                 {{ | ||||
|                   content: () => <span v-html={item.labelMessage}></span>, | ||||
|                   default: () => ( | ||||
|                     <Icon | ||||
|                       icon="ep:warning" | ||||
|                       size={16} | ||||
|                       color="var(--el-color-primary)" | ||||
|                       class="ml-2px relative top-1px" | ||||
|                     ></Icon> | ||||
|                   ) | ||||
|                 }} | ||||
|               </ElTooltip> | ||||
|             </> | ||||
|           ) | ||||
|         } | ||||
|       } | ||||
|       return ( | ||||
|         <ElFormItem {...(item.formItemProps || {})} prop={item.field} label={item.label || ''}> | ||||
|           {{ | ||||
|             ...formItemSlots, | ||||
|             default: () => { | ||||
|               const Com = componentMap[item.component as string] as ReturnType< | ||||
|                 typeof defineComponent | ||||
|               > | ||||
|  | ||||
|               const { autoSetPlaceholder } = unref(getProps) | ||||
|  | ||||
|               return slots[item.field] ? ( | ||||
|                 getSlot(slots, item.field, formModel.value) | ||||
|               ) : ( | ||||
|                 <Com | ||||
|                   vModel={formModel.value[item.field]} | ||||
|                   {...(autoSetPlaceholder && setTextPlaceholder(item))} | ||||
|                   {...setComponentProps(item)} | ||||
|                   {...(notRenderOptions.includes(item?.component as string) && | ||||
|                   item?.componentProps?.options | ||||
|                     ? { options: item?.componentProps?.options || [] } | ||||
|                     : {})} | ||||
|                 > | ||||
|                   {{ ...slotsMap }} | ||||
|                 </Com> | ||||
|               ) | ||||
|             } | ||||
|           }} | ||||
|         </ElFormItem> | ||||
|       ) | ||||
|     } | ||||
|  | ||||
|     // 渲染options | ||||
|     const renderOptions = (item: FormSchema) => { | ||||
|       switch (item.component) { | ||||
|         case 'Select': | ||||
|           const { renderSelectOptions } = useRenderSelect(slots) | ||||
|           return renderSelectOptions(item) | ||||
|         case 'Radio': | ||||
|         case 'RadioButton': | ||||
|           const { renderRadioOptions } = useRenderRadio() | ||||
|           return renderRadioOptions(item) | ||||
|         case 'Checkbox': | ||||
|         case 'CheckboxButton': | ||||
|           const { renderChcekboxOptions } = useRenderCheckbox() | ||||
|           return renderChcekboxOptions(item) | ||||
|         default: | ||||
|           break | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     // 过滤传入Form组件的属性 | ||||
|     const getFormBindValue = () => { | ||||
|       // 避免在标签上出现多余的属性 | ||||
|       const delKeys = ['schema', 'isCol', 'autoSetPlaceholder', 'isCustom', 'model'] | ||||
|       const props = { ...unref(getProps) } | ||||
|       for (const key in props) { | ||||
|         if (delKeys.indexOf(key) !== -1) { | ||||
|           delete props[key] | ||||
|         } | ||||
|       } | ||||
|       return props | ||||
|     } | ||||
|  | ||||
|     return () => ( | ||||
|       <ElForm | ||||
|         ref={elFormRef} | ||||
|         {...getFormBindValue()} | ||||
|         model={props.isCustom ? props.model : formModel} | ||||
|         class={prefixCls} | ||||
|       > | ||||
|         {{ | ||||
|           // 如果需要自定义,就什么都不渲染,而是提供默认插槽 | ||||
|           default: () => { | ||||
|             const { isCustom } = unref(getProps) | ||||
|             return isCustom ? getSlot(slots, 'default') : renderWrap() | ||||
|           } | ||||
|         }} | ||||
|       </ElForm> | ||||
|     ) | ||||
|   } | ||||
| }) | ||||
| </script> | ||||
|  | ||||
| <style lang="less" scoped> | ||||
| .@{elNamespace}-form.@{namespace}-form .@{elNamespace}-row { | ||||
|   margin-left: 0 !important; | ||||
|   margin-right: 0 !important; | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										48
									
								
								yudao-ui-admin-vue3/src/components/Form/src/componentMap.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								yudao-ui-admin-vue3/src/components/Form/src/componentMap.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,48 @@ | ||||
| import type { Component } from 'vue' | ||||
| import { | ||||
|   ElCascader, | ||||
|   ElCheckboxGroup, | ||||
|   ElColorPicker, | ||||
|   ElDatePicker, | ||||
|   ElInput, | ||||
|   ElInputNumber, | ||||
|   ElRadioGroup, | ||||
|   ElRate, | ||||
|   ElSelect, | ||||
|   ElSelectV2, | ||||
|   ElSlider, | ||||
|   ElSwitch, | ||||
|   ElTimePicker, | ||||
|   ElTimeSelect, | ||||
|   ElTransfer, | ||||
|   ElAutocomplete, | ||||
|   ElDivider | ||||
| } from 'element-plus' | ||||
| import { InputPassword } from '@/components/InputPassword' | ||||
| import { Editor } from '@/components/Editor' | ||||
|  | ||||
| const componentMap: Recordable<Component, ComponentName> = { | ||||
|   Radio: ElRadioGroup, | ||||
|   Checkbox: ElCheckboxGroup, | ||||
|   CheckboxButton: ElCheckboxGroup, | ||||
|   Input: ElInput, | ||||
|   Autocomplete: ElAutocomplete, | ||||
|   InputNumber: ElInputNumber, | ||||
|   Select: ElSelect, | ||||
|   Cascader: ElCascader, | ||||
|   Switch: ElSwitch, | ||||
|   Slider: ElSlider, | ||||
|   TimePicker: ElTimePicker, | ||||
|   DatePicker: ElDatePicker, | ||||
|   Rate: ElRate, | ||||
|   ColorPicker: ElColorPicker, | ||||
|   Transfer: ElTransfer, | ||||
|   Divider: ElDivider, | ||||
|   TimeSelect: ElTimeSelect, | ||||
|   SelectV2: ElSelectV2, | ||||
|   RadioButton: ElRadioGroup, | ||||
|   InputPassword: InputPassword, | ||||
|   Editor: Editor | ||||
| } | ||||
|  | ||||
| export { componentMap } | ||||
| @@ -0,0 +1,20 @@ | ||||
| import { ElCheckbox, ElCheckboxButton } from 'element-plus' | ||||
| import { defineComponent } from 'vue' | ||||
|  | ||||
| export const useRenderCheckbox = () => { | ||||
|   const renderChcekboxOptions = (item: FormSchema) => { | ||||
|     // 如果有别名,就取别名 | ||||
|     const labelAlias = item?.componentProps?.optionsAlias?.labelField | ||||
|     const valueAlias = item?.componentProps?.optionsAlias?.valueField | ||||
|     const Com = (item.component === 'Checkbox' ? ElCheckbox : ElCheckboxButton) as ReturnType< | ||||
|       typeof defineComponent | ||||
|     > | ||||
|     return item?.componentProps?.options?.map((option) => { | ||||
|       return <Com label={option[labelAlias || 'value']}>{option[valueAlias || 'label']}</Com> | ||||
|     }) | ||||
|   } | ||||
|  | ||||
|   return { | ||||
|     renderChcekboxOptions | ||||
|   } | ||||
| } | ||||
| @@ -0,0 +1,20 @@ | ||||
| import { ElRadio, ElRadioButton } from 'element-plus' | ||||
| import { defineComponent } from 'vue' | ||||
|  | ||||
| export const useRenderRadio = () => { | ||||
|   const renderRadioOptions = (item: FormSchema) => { | ||||
|     // 如果有别名,就取别名 | ||||
|     const labelAlias = item?.componentProps?.optionsAlias?.labelField | ||||
|     const valueAlias = item?.componentProps?.optionsAlias?.valueField | ||||
|     const Com = (item.component === 'Radio' ? ElRadio : ElRadioButton) as ReturnType< | ||||
|       typeof defineComponent | ||||
|     > | ||||
|     return item?.componentProps?.options?.map((option) => { | ||||
|       return <Com label={option[labelAlias || 'value']}>{option[valueAlias || 'label']}</Com> | ||||
|     }) | ||||
|   } | ||||
|  | ||||
|   return { | ||||
|     renderRadioOptions | ||||
|   } | ||||
| } | ||||
| @@ -0,0 +1,48 @@ | ||||
| import { ElOption, ElOptionGroup } from 'element-plus' | ||||
| import { getSlot } from '@/utils/tsxHelper' | ||||
| import { Slots } from 'vue' | ||||
|  | ||||
| export const useRenderSelect = (slots: Slots) => { | ||||
|   // 渲染 select options | ||||
|   const renderSelectOptions = (item: FormSchema) => { | ||||
|     // 如果有别名,就取别名 | ||||
|     const labelAlias = item?.componentProps?.optionsAlias?.labelField | ||||
|     return item?.componentProps?.options?.map((option) => { | ||||
|       if (option?.options?.length) { | ||||
|         return ( | ||||
|           <ElOptionGroup label={option[labelAlias || 'label']}> | ||||
|             {() => { | ||||
|               return option?.options?.map((v) => { | ||||
|                 return renderSelectOptionItem(item, v) | ||||
|               }) | ||||
|             }} | ||||
|           </ElOptionGroup> | ||||
|         ) | ||||
|       } else { | ||||
|         return renderSelectOptionItem(item, option) | ||||
|       } | ||||
|     }) | ||||
|   } | ||||
|  | ||||
|   // 渲染 select option item | ||||
|   const renderSelectOptionItem = (item: FormSchema, option: ComponentOptions) => { | ||||
|     // 如果有别名,就取别名 | ||||
|     const labelAlias = item?.componentProps?.optionsAlias?.labelField | ||||
|     const valueAlias = item?.componentProps?.optionsAlias?.valueField | ||||
|     return ( | ||||
|       <ElOption label={option[labelAlias || 'label']} value={option[valueAlias || 'value']}> | ||||
|         {{ | ||||
|           default: () => | ||||
|             // option 插槽名规则,{field}-option | ||||
|             item?.componentProps?.optionsSlot | ||||
|               ? getSlot(slots, `${item.field}-option`, { item: option }) | ||||
|               : undefined | ||||
|         }} | ||||
|       </ElOption> | ||||
|     ) | ||||
|   } | ||||
|  | ||||
|   return { | ||||
|     renderSelectOptions | ||||
|   } | ||||
| } | ||||
							
								
								
									
										152
									
								
								yudao-ui-admin-vue3/src/components/Form/src/helper.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										152
									
								
								yudao-ui-admin-vue3/src/components/Form/src/helper.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,152 @@ | ||||
| // import { useI18n } from '@/hooks/web/useI18n' | ||||
| import type { Slots } from 'vue' | ||||
| import { getSlot } from '@/utils/tsxHelper' | ||||
| import { PlaceholderMoel } from './types' | ||||
|  | ||||
| // const { t } = useI18n() | ||||
|  | ||||
| /** | ||||
|  * | ||||
|  * @param schema 对应组件数据 | ||||
|  * @returns 返回提示信息对象 | ||||
|  * @description 用于自动设置placeholder | ||||
|  */ | ||||
| export const setTextPlaceholder = (schema: FormSchema): PlaceholderMoel => { | ||||
|   const textMap = ['Input', 'Autocomplete', 'InputNumber', 'InputPassword'] | ||||
|   const selectMap = ['Select', 'TimePicker', 'DatePicker', 'TimeSelect', 'TimeSelect'] | ||||
|   if (textMap.includes(schema?.component as string)) { | ||||
|     return { | ||||
|       // placeholder: t('common.inputText') | ||||
|       placeholder: '请输入' | ||||
|     } | ||||
|   } | ||||
|   if (selectMap.includes(schema?.component as string)) { | ||||
|     // 一些范围选择器 | ||||
|     const twoTextMap = ['datetimerange', 'daterange', 'monthrange', 'datetimerange', 'daterange'] | ||||
|     if ( | ||||
|       twoTextMap.includes( | ||||
|         (schema?.componentProps?.type || schema?.componentProps?.isRange) as string | ||||
|       ) | ||||
|     ) { | ||||
|       return { | ||||
|         // startPlaceholder: t('common.startTimeText'), | ||||
|         // endPlaceholder: t('common.endTimeText'), | ||||
|         startPlaceholder: '开始时间', | ||||
|         endPlaceholder: '结束时间', | ||||
|         rangeSeparator: '-' | ||||
|       } | ||||
|     } else { | ||||
|       return { | ||||
|         // placeholder: t('common.selectText') | ||||
|         placeholder: '请选择' | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|   return {} | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * | ||||
|  * @param col 内置栅格 | ||||
|  * @returns 返回栅格属性 | ||||
|  * @description 合并传入进来的栅格属性 | ||||
|  */ | ||||
| export const setGridProp = (col: ColProps = {}): ColProps => { | ||||
|   const colProps: ColProps = { | ||||
|     // 如果有span,代表用户优先级更高,所以不需要默认栅格 | ||||
|     ...(col.span | ||||
|       ? {} | ||||
|       : { | ||||
|           xs: 24, | ||||
|           sm: 12, | ||||
|           md: 12, | ||||
|           lg: 12, | ||||
|           xl: 12 | ||||
|         }), | ||||
|     ...col | ||||
|   } | ||||
|   return colProps | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * | ||||
|  * @param item 传入的组件属性 | ||||
|  * @returns 默认添加 clearable 属性 | ||||
|  */ | ||||
| export const setComponentProps = (item: FormSchema): Recordable => { | ||||
|   const notNeedClearable = ['ColorPicker'] | ||||
|   const componentProps: Recordable = notNeedClearable.includes(item.component as string) | ||||
|     ? { ...item.componentProps } | ||||
|     : { | ||||
|         clearable: true, | ||||
|         ...item.componentProps | ||||
|       } | ||||
|   // 需要删除额外的属性 | ||||
|   delete componentProps?.slots | ||||
|   return componentProps | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * | ||||
|  * @param slots 插槽 | ||||
|  * @param slotsProps 插槽属性 | ||||
|  * @param field 字段名 | ||||
|  */ | ||||
| export const setItemComponentSlots = ( | ||||
|   slots: Slots, | ||||
|   slotsProps: Recordable = {}, | ||||
|   field: string | ||||
| ): Recordable => { | ||||
|   const slotObj: Recordable = {} | ||||
|   for (const key in slotsProps) { | ||||
|     if (slotsProps[key]) { | ||||
|       // 由于组件有可能重复,需要有一个唯一的前缀 | ||||
|       slotObj[key] = (data: Recordable) => { | ||||
|         return getSlot(slots, `${field}-${key}`, data) | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|   return slotObj | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * | ||||
|  * @param schema Form表单结构化数组 | ||||
|  * @param formModel FormMoel | ||||
|  * @returns FormMoel | ||||
|  * @description 生成对应的formModel | ||||
|  */ | ||||
| export const initModel = (schema: FormSchema[], formModel: Recordable) => { | ||||
|   const model: Recordable = { ...formModel } | ||||
|   schema.map((v) => { | ||||
|     // 如果是hidden,就删除对应的值 | ||||
|     if (v.hidden) { | ||||
|       delete model[v.field] | ||||
|     } else if (v.component && v.component !== 'Divider') { | ||||
|       const hasField = Reflect.has(model, v.field) | ||||
|       // 如果先前已经有值存在,则不进行重新赋值,而是采用现有的值 | ||||
|       model[v.field] = hasField ? model[v.field] : v.value !== void 0 ? v.value : '' | ||||
|     } | ||||
|   }) | ||||
|   return model | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * @param slots 插槽 | ||||
|  * @param field 字段名 | ||||
|  * @returns 返回FormIiem插槽 | ||||
|  */ | ||||
| export const setFormItemSlots = (slots: Slots, field: string): Recordable => { | ||||
|   const slotObj: Recordable = {} | ||||
|   if (slots[`${field}-error`]) { | ||||
|     slotObj['error'] = (data: Recordable) => { | ||||
|       return getSlot(slots, `${field}-error`, data) | ||||
|     } | ||||
|   } | ||||
|   if (slots[`${field}-label`]) { | ||||
|     slotObj['label'] = (data: Recordable) => { | ||||
|       return getSlot(slots, `${field}-label`, data) | ||||
|     } | ||||
|   } | ||||
|   return slotObj | ||||
| } | ||||
							
								
								
									
										15
									
								
								yudao-ui-admin-vue3/src/components/Form/src/types.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								yudao-ui-admin-vue3/src/components/Form/src/types.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | ||||
| export interface PlaceholderMoel { | ||||
|   placeholder?: string | ||||
|   startPlaceholder?: string | ||||
|   endPlaceholder?: string | ||||
|   rangeSeparator?: string | ||||
| } | ||||
|  | ||||
| export type FormProps = { | ||||
|   schema?: FormSchema[] | ||||
|   isCol?: boolean | ||||
|   model?: Recordable | ||||
|   autoSetPlaceholder?: boolean | ||||
|   isCustom?: boolean | ||||
|   labelWidth?: string | number | ||||
| } & Recordable | ||||
		Reference in New Issue
	
	Block a user
	 xingyu
					xingyu