Browse Source

wip: Form改造中

kailong321200875 1 year ago
parent
commit
998d9f3eeb

+ 5 - 4
src/components/Form/src/Form.vue

@@ -21,7 +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'
+import { ComponentNameEnum, SelectComponentProps } from '@/types/components.d'
 
 const { getPrefixCls } = useDesign()
 
@@ -182,9 +182,10 @@ export default defineComponent({
       if (item.component === ComponentNameEnum.SELECT) {
         slotsMap.default = !componentSlots.default
           ? () => renderOptions(item)
-          : (option: any) => {
-              console.log(option)
-              return componentSlots.default(option)
+          : () => {
+              return componentSlots.default(
+                unref((item?.componentProps as SelectComponentProps)?.options)
+              )
             }
       }
       // if (

+ 11 - 10
src/components/Form/src/components/useRenderSelect.tsx

@@ -8,16 +8,20 @@ export const useRenderSelect = (slots: Slots) => {
   // 渲染 select options
   const renderSelectOptions = (item: FormSchema) => {
     const componentsProps = item.componentProps as SelectComponentProps
+    const optionGroupDefaultSlot = componentsProps.slots?.optionGroupDefault
     // 如果有别名,就取别名
     const labelAlias = componentsProps?.labelAlias
     return componentsProps?.options?.map((option) => {
       if (option?.options?.length) {
-        return (
+        return optionGroupDefaultSlot ? (
+          optionGroupDefaultSlot(option)
+        ) : (
           <ElOptionGroup label={option[labelAlias || 'label']}>
-            {() => {
-              return option?.options?.map((v) => {
-                return renderSelectOptionItem(item, v)
-              })
+            {{
+              default: () =>
+                option?.options?.map((v) => {
+                  return renderSelectOptionItem(item, v)
+                })
             }}
           </ElOptionGroup>
         )
@@ -33,6 +37,7 @@ export const useRenderSelect = (slots: Slots) => {
     const componentsProps = item.componentProps as SelectComponentProps
     const labelAlias = componentsProps?.labelAlias
     const valueAlias = componentsProps?.valueAlias
+    const optionDefaultSlot = componentsProps.slots?.optionDefault
 
     const { label, value, ...other } = option
 
@@ -43,11 +48,7 @@ export const useRenderSelect = (slots: Slots) => {
         value={valueAlias ? option[valueAlias] : value}
       >
         {{
-          default: () =>
-            // option 插槽名规则,{field}-option
-            componentsProps?.optionsSlot
-              ? getSlot(slots, `${item.field}-option`, { item: option })
-              : undefined
+          default: () => (optionDefaultSlot ? optionDefaultSlot(option) : undefined)
         }}
       </ElOption>
     )

+ 2 - 2
src/components/Form/src/helper.ts

@@ -95,8 +95,8 @@ export const setItemComponentSlots = (formModel: any, slotsProps: Recordable = {
   for (const key in slotsProps) {
     if (slotsProps[key]) {
       if (isFunction(slotsProps[key])) {
-        slotObj[key] = (item: any) => {
-          return slotsProps[key]?.(unref(item?.item) || undefined, formModel)
+        slotObj[key] = () => {
+          return slotsProps[key]?.(formModel)
         }
       } else {
         slotObj[key] = () => {

+ 1 - 1
src/components/Setting/src/Setting.vue

@@ -202,7 +202,7 @@ const clear = () => {
 <template>
   <div
     :class="prefixCls"
-    class="fixed top-[45%] right-0 w-40px h-40px text-center leading-40px bg-[var(--el-color-primary)] cursor-pointer"
+    class="fixed top-[45%] right-0 w-40px h-40px flex items-center justify-center bg-[var(--el-color-primary)] cursor-pointer"
     @click="drawer = true"
   >
     <Icon icon="ant-design:setting-outlined" color="#fff" />

+ 1 - 0
src/locales/en.ts

@@ -221,6 +221,7 @@ export default {
     position: 'Position',
     autocomplete: 'Autocomplete',
     select: 'Select',
+    optionSlot: 'Option Slot',
     selectGroup: 'Select Group',
     selectV2: 'SelectV2',
     cascader: 'Cascader',

+ 1 - 0
src/locales/zh-CN.ts

@@ -221,6 +221,7 @@ export default {
     position: '位置',
     autocomplete: '自动补全',
     select: '选择器',
+    optionSlot: '选项插槽',
     selectGroup: '选项分组',
     selectV2: '虚拟列表选择器',
     cascader: '级联选择器',

+ 18 - 21
src/types/components.d.ts

@@ -47,8 +47,8 @@ export interface InputComponentProps {
   showPassword?: boolean
   disabled?: boolean
   size?: InputProps['size']
-  prefixIcon?: string | JSX.Element | ((item: any, data: any) => string | JSX.Element)
-  suffixIcon?: string | JSX.Element | ((item: any, data: any) => string | JSX.Element)
+  prefixIcon?: string | JSX.Element | ((formData: any) => string | JSX.Element)
+  suffixIcon?: string | JSX.Element | ((formData: any) => string | JSX.Element)
   type?: InputProps['type']
   rows?: number
   autosize?: boolean | { Pows?: numer; maxRows?: number }
@@ -73,10 +73,10 @@ export interface InputComponentProps {
     input?: (value: string | number) => void
   }
   slots?: {
-    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)
+    prefix?: JSX.Element | null | ((formData: any) => JSX.Element | null)
+    suffix?: JSX.Element | null | ((formData: any) => JSX.Element | null)
+    prepend?: JSX.Element | null | ((formData: any) => JSX.Element | null)
+    append?: JSX.Element | null | ((formData: any) => JSX.Element | null)
   }
   style?: CSSProperties
 }
@@ -105,11 +105,11 @@ export interface AutocompleteComponentProps {
     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)
+    default?: JSX.Element | null | ((formData: any) => JSX.Element | null)
+    prefix?: JSX.Element | null | ((formData: any) => JSX.Element | null)
+    suffix?: JSX.Element | null | ((formData: any) => JSX.Element | null)
+    prepend?: JSX.Element | null | ((formData: any) => JSX.Element | null)
+    append?: JSX.Element | null | ((formData: any) => JSX.Element | null)
   }
   style?: CSSProperties
 }
@@ -180,9 +180,9 @@ export interface SelectComponentProps {
   teleported?: boolean
   persistent?: boolean
   automaticDropdown?: boolean
-  clearIcon?: string | JSX.Element | ((item: any, data: any) => string | JSX.Element)
+  clearIcon?: string | JSX.Element | ((formData: any) => string | JSX.Element)
   fitInputWidth?: boolean
-  suffixIcon?: string | JSX.Element | ((item: any, data: any) => string | JSX.Element)
+  suffixIcon?: string | JSX.Element | ((formData: any) => string | JSX.Element)
   tagType?: 'success' | 'info' | 'warning' | 'danger'
   validateEvent?: boolean
   placement?:
@@ -213,11 +213,6 @@ export interface SelectComponentProps {
    * key别名
    */
   keyAlias?: string
-
-  /**
-   * option是否禁用的统一拦截
-   */
-  optionDisabled?: (optin: any, data: any) => boolean
   on?: {
     change?: (value: string | number | boolean | Object) => void
     visibleChange?: (visible: boolean) => void
@@ -227,9 +222,11 @@ export interface SelectComponentProps {
     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)
+    default?: (options: SelectOption[]) => JSX.Element[] | null
+    optionGroupDefault?: (item: SelectOption) => JSX.Element
+    optionDefault?: (option: SelectOption) => JSX.Element | null
+    prefix?: JSX.Element | null | ((formData: any) => JSX.Element | null)
+    empty?: JSX.Element | null | ((formData: any) => JSX.Element | null)
   }
   options?: SelectOption[]
   style?: CSSProperties

+ 145 - 85
src/views/Components/Form/DefaultForm.vue

@@ -6,8 +6,9 @@ import { useIcon } from '@/hooks/web/useIcon'
 import { ContentWrap } from '@/components/ContentWrap'
 import { useAppStore } from '@/store/modules/app'
 import { FormSchema } from '@/types/form'
-import { ComponentOptions } from '@/types/components'
+import { ComponentOptions, SelectOption, SelectComponentProps } from '@/types/components'
 import { useForm } from '@/hooks/web/useForm'
+import { ElOption, ElOptionGroup } from 'element-plus'
 
 const appStore = useAppStore()
 
@@ -393,7 +394,7 @@ const schema = reactive<FormSchema[]>([
     component: 'Input',
     componentProps: {
       slots: {
-        suffix: (_, data: any) => {
+        suffix: (data: any) => {
           return unref(toggle) && data.field4
             ? useIcon({ icon: 'ep:calendar' })
             : useIcon({ icon: 'ep:share' })
@@ -409,7 +410,7 @@ const schema = reactive<FormSchema[]>([
     componentProps: {
       slots: {
         prepend: useIcon({ icon: 'ep:calendar' }),
-        append: (_, data: any) => {
+        append: (data: any) => {
           return data.field5 ? useIcon({ icon: 'ep:calendar' }) : useIcon({ icon: 'ep:share' })
         }
       }
@@ -510,10 +511,6 @@ const schema = reactive<FormSchema[]>([
     label: t('formDemo.default'),
     component: 'Select',
     componentProps: {
-      optionDisabled: (item: any, data: any) => {
-        console.log(item, data)
-        return false
-      },
       options: [
         {
           disabled: true,
@@ -543,94 +540,157 @@ const schema = reactive<FormSchema[]>([
         }
       ],
       slots: {
-        default: (item) => {
-          console.log(item)
+        default: (options: SelectOption[]) => {
+          if (options.length) {
+            return options?.map((v) => {
+              return <ElOption key={v.value} label={v.label} value={v.value} />
+            })
+          } else {
+            return null
+          }
+        },
+        prefix: useIcon({ icon: 'ep:calendar' }),
+        empty: (data: any) => {
+          return data.field5 ? useIcon({ icon: 'ep:calendar' }) : useIcon({ icon: 'ep:share' })
+        }
+      }
+    }
+  },
+  {
+    field: 'select-field18',
+    label: t('formDemo.optionSlot'),
+    component: 'Select',
+    componentProps: {
+      options: [
+        {
+          value: 'Beijing',
+          label: 'Beijing'
+        },
+        {
+          value: 'Shanghai',
+          label: 'Shanghai'
+        },
+        {
+          value: 'Nanjing',
+          label: 'Nanjing'
+        },
+        {
+          value: 'Chengdu',
+          label: 'Chengdu'
+        },
+        {
+          value: 'Shenzhen',
+          label: 'Shenzhen'
+        },
+        {
+          value: 'Guangzhou',
+          label: 'Guangzhou'
+        }
+      ],
+      slots: {
+        optionDefault: (option: SelectOption) => {
           return (
             <>
-              <span style="float: left">{item.label}</span>
-              <span style=" float: right; color: var(--el-text-color-secondary); font-size: 13px;">
-                {item.value}
+              <span style="float: left">{option.label}</span>
+              <span style="float: right; color: var(--el-text-color-secondary); font-size: 13px;">
+                {option.value}
               </span>
             </>
           )
         }
       }
     }
+  },
+  {
+    field: 'field16',
+    label: t('formDemo.selectGroup'),
+    component: 'Select',
+    componentProps: {
+      options: [
+        {
+          label: 'option1',
+          options: [
+            {
+              disabled: true,
+              label: 'option1-1',
+              value: '1-1'
+            },
+            {
+              label: 'option1-2',
+              value: '1-2'
+            }
+          ]
+        },
+        {
+          label: 'option2',
+          options: [
+            {
+              label: 'option2-1',
+              value: '2-1'
+            },
+            {
+              label: 'option2-2',
+              value: '2-2'
+            }
+          ]
+        }
+      ]
+    }
+  },
+  {
+    field: 'field17',
+    label: `${t('formDemo.selectGroup')}${t('formDemo.slot')}`,
+    component: 'Select',
+    componentProps: {
+      options: [
+        {
+          label: 'option1',
+          options: [
+            {
+              label: 'option1-1',
+              value: '1-1'
+            },
+            {
+              label: 'option1-2',
+              value: '1-2'
+            }
+          ]
+        },
+        {
+          label: 'option2',
+          options: [
+            {
+              label: 'option2-1',
+              value: '2-1'
+            },
+            {
+              label: 'option2-2',
+              value: '2-2'
+            }
+          ]
+        }
+      ],
+      slots: {
+        optionGroupDefault: (option: SelectOption) => {
+          return (
+            <ElOptionGroup key={option.label} label={`${option.label} ${option.label}`}>
+              {option?.options?.map((v) => {
+                return (
+                  <ElOption
+                    key={v.value}
+                    disabled={unref(toggle)}
+                    label={v.label}
+                    value={v.value}
+                  />
+                )
+              })}
+            </ElOptionGroup>
+          )
+        }
+      }
+    }
   }
   // {
-  //   field: 'field16',
-  //   label: t('formDemo.selectGroup'),
-  //   component: 'Select',
-  //   componentProps: {
-  //     options: [
-  //       {
-  //         label: 'option1',
-  //         options: [
-  //           {
-  //             disabled: true,
-  //             label: 'option1-1',
-  //             value: '1-1'
-  //           },
-  //           {
-  //             label: 'option1-2',
-  //             value: '1-2'
-  //           }
-  //         ]
-  //       },
-  //       {
-  //         label: 'option2',
-  //         options: [
-  //           {
-  //             label: 'option2-1',
-  //             value: '2-1'
-  //           },
-  //           {
-  //             label: 'option2-2',
-  //             value: '2-2'
-  //           }
-  //         ]
-  //       }
-  //     ]
-  //   }
-  // },
-  // {
-  //   field: 'field17',
-  //   label: `${t('formDemo.selectGroup')}${t('formDemo.slot')}`,
-  //   component: 'Select',
-  //   componentProps: {
-  //     options: [
-  //       {
-  //         label: 'option1',
-  //         options: [
-  //           {
-  //             label: 'option1-1',
-  //             value: '1-1',
-  //             disabled: true
-  //           },
-  //           {
-  //             label: 'option1-2',
-  //             value: '1-2'
-  //           }
-  //         ]
-  //       },
-  //       {
-  //         label: 'option2',
-  //         options: [
-  //           {
-  //             label: 'option2-1',
-  //             value: '2-1'
-  //           },
-  //           {
-  //             label: 'option2-2',
-  //             value: '2-2'
-  //           }
-  //         ]
-  //       }
-  //     ],
-  //     optionsSlot: true
-  //   }
-  // },
-  // {
   //   field: 'field18',
   //   label: `${t('formDemo.selectV2')}`,
   //   component: 'Divider'