Browse Source

feat: 新增TreeSelect表单项

kailong321200875 1 year ago
parent
commit
de0cb43566

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

@@ -125,12 +125,15 @@ export default defineComponent({
       }
     }
 
-    const getOptions = async (fn: Function, field: string) => {
+    const getOptions = async (fn: Function, item: FormSchema) => {
       const options = await fn()
       setSchema([
         {
-          field,
-          path: 'componentProps.options',
+          field: item.field,
+          path:
+            item.component === ComponentNameEnum.TREE_SELECT
+              ? 'componentProps.data'
+              : 'componentProps.options',
           value: options
         }
       ])
@@ -221,7 +224,7 @@ export default defineComponent({
       // 如果有optionApi,优先使用optionApi
       if (item.optionApi) {
         // 内部自动调用接口,不影响其他渲染
-        getOptions(item.optionApi, item.field)
+        getOptions(item.optionApi, item)
       }
       const formItemSlots: Recordable = {
         default: () => {

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

@@ -16,7 +16,8 @@ import {
   ElTimeSelect,
   ElTransfer,
   ElAutocomplete,
-  ElDivider
+  ElDivider,
+  ElTreeSelect
 } from 'element-plus'
 import { InputPassword } from '@/components/InputPassword'
 import { Editor } from '@/components/Editor'
@@ -43,7 +44,8 @@ const componentMap: Recordable<Component, ComponentName> = {
   TimeSelect: ElTimeSelect,
   SelectV2: ElSelectV2,
   InputPassword: InputPassword,
-  Editor: Editor
+  Editor: Editor,
+  TreeSelect: ElTreeSelect
 }
 
 export { componentMap }

+ 2 - 21
src/components/Form/src/types/index.ts

@@ -38,7 +38,8 @@ export enum ComponentNameEnum {
   TIME_SELECT = 'TimeSelect',
   SELECT_V2 = 'SelectV2',
   INPUT_PASSWORD = 'InputPassword',
-  EDITOR = 'Editor'
+  EDITOR = 'Editor',
+  TREE_SELECT = 'TreeSelect'
 }
 
 type CamelCaseComponentName = keyof typeof ComponentNameEnum extends infer K
@@ -52,7 +53,6 @@ type CamelCaseComponentName = keyof typeof ComponentNameEnum extends infer K
 export type ComponentName = CamelCaseComponentName
 
 export interface InputComponentProps {
-  ref?: any
   maxlength?: number | string
   minlength?: number | string
   showWordLimit?: boolean
@@ -98,7 +98,6 @@ export interface InputComponentProps {
 }
 
 export interface AutocompleteComponentProps {
-  ref?: any
   placeholder?: string
   clearable?: boolean
   disabled?: boolean
@@ -131,7 +130,6 @@ export interface AutocompleteComponentProps {
 }
 
 export interface InputNumberComponentProps {
-  ref?: any
   min?: number
   max?: number
   step?: number
@@ -166,7 +164,6 @@ export interface SelectOption {
 }
 
 export interface SelectComponentProps {
-  ref?: any
   multiple?: boolean
   disabled?: boolean
   valueKey?: string
@@ -244,7 +241,6 @@ export interface SelectComponentProps {
 }
 
 export interface SelectV2ComponentProps {
-  ref?: any
   multiple?: boolean
   disabled?: boolean
   valueKey?: string
@@ -289,7 +285,6 @@ export interface SelectV2ComponentProps {
 }
 
 export interface CascaderComponentProps {
-  ref?: any
   options?: Record<string, unknown>[]
   props?: CascaderProps
   size?: ElementPlusSize
@@ -324,7 +319,6 @@ export interface CascaderComponentProps {
 }
 
 export interface SwitchComponentProps {
-  ref?: any
   disabled?: boolean
   loading?: boolean
   size?: ElementPlusSize
@@ -346,7 +340,6 @@ export interface SwitchComponentProps {
 }
 
 export interface RateComponentProps {
-  ref?: any
   max?: number
   size?: ElementPlusSize
   disabled?: boolean
@@ -374,7 +367,6 @@ export interface RateComponentProps {
 }
 
 export interface ColorPickerComponentProps {
-  ref?: any
   disabled?: boolean
   size?: ElementPlusSize
   showAlpha?: boolean
@@ -392,7 +384,6 @@ export interface ColorPickerComponentProps {
 }
 
 export interface TransferComponentProps {
-  ref?: any
   data?: any[]
   filterable?: boolean
   filterPlaceholder?: string
@@ -443,7 +434,6 @@ export interface RadioOption {
   [key: string]: any
 }
 export interface RadioGroupComponentProps {
-  ref?: any
   size?: ElementPlusSize
   disabled?: boolean
   textColor?: string
@@ -471,7 +461,6 @@ export interface RadioGroupComponentProps {
 }
 
 export interface RadioButtonComponentProps {
-  ref?: any
   size?: ElementPlusSize
   disabled?: boolean
   textColor?: string
@@ -517,7 +506,6 @@ export interface CheckboxOption {
 }
 
 export interface CheckboxGroupComponentProps {
-  ref?: any
   size?: ElementPlusSize
   disabled?: boolean
   min?: number
@@ -546,7 +534,6 @@ export interface CheckboxGroupComponentProps {
 }
 
 export interface DividerComponentProps {
-  ref?: any
   min?: number
   max?: number
   disabled?: boolean
@@ -578,7 +565,6 @@ export interface DividerComponentProps {
 }
 
 export interface DatePickerComponentProps {
-  ref?: any
   readonly?: boolean
   disabled?: boolean
   size?: ElementPlusSize
@@ -630,7 +616,6 @@ export interface DatePickerComponentProps {
 }
 
 export interface DateTimePickerComponentProps {
-  ref?: any
   readonly?: boolean
   disabled?: boolean
   editable?: boolean
@@ -671,7 +656,6 @@ export interface DateTimePickerComponentProps {
 }
 
 export interface TimePickerComponentProps {
-  ref?: any
   readonly?: boolean
   disabled?: boolean
   editable?: boolean
@@ -708,7 +692,6 @@ export interface TimePickerComponentProps {
 }
 
 export interface TimeSelectComponentProps {
-  ref?: any
   disabled?: boolean
   editable?: boolean
   clearable?: boolean
@@ -733,7 +716,6 @@ export interface TimeSelectComponentProps {
 }
 
 export interface EditorComponentProps {
-  ref?: any
   editorConfig?: IEditorConfig
   style?: CSSProperties
 }
@@ -755,7 +737,6 @@ export interface FormSetProps {
 }
 
 export interface FormItemProps {
-  ref?: any
   labelWidth?: string | number
   required?: boolean
   rules?: FormItemRule | FormItemRule[]

+ 10 - 1
src/locales/en.ts

@@ -287,7 +287,16 @@ export default {
     // 远程加载
     remoteLoading: 'Remote loading',
     // 聚焦
-    focus: 'Focus'
+    focus: 'Focus',
+    treeSelect: 'Tree Select',
+    showCheckbox: 'Show Checkbox',
+    selectAnyLevel: 'Select Any Level',
+    multiple: 'Multiple',
+    filterable: 'Filterable',
+    // 自定义节点内容
+    customContent: 'Custom content',
+    // 懒加载
+    lazyLoad: 'Lazy load'
   },
   guideDemo: {
     guide: 'Guide',

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

@@ -286,7 +286,14 @@ export default {
     // 远程加载
     remoteLoading: '远程加载',
     // 聚焦
-    focus: '聚焦'
+    focus: '聚焦',
+    treeSelect: '树形选择器',
+    showCheckbox: '显示复选框',
+    selectAnyLevel: '选择任意级别',
+    multiple: '多选',
+    filterable: '可筛选',
+    customContent: '自定义内容',
+    lazyLoad: '懒加载'
   },
   guideDemo: {
     guide: '引导页',

+ 214 - 0
src/views/Components/Form/DefaultForm.vue

@@ -368,6 +368,79 @@ const isHoliday = ({ dayjs }) => {
   return holidays.includes(dayjs.format('YYYY-MM-DD'))
 }
 
+const treeSelectData = [
+  {
+    value: '1',
+    label: 'Level one 1',
+    children: [
+      {
+        value: '1-1',
+        label: 'Level two 1-1',
+        children: [
+          {
+            value: '1-1-1',
+            label: 'Level three 1-1-1'
+          }
+        ]
+      }
+    ]
+  },
+  {
+    value: '2',
+    label: 'Level one 2',
+    children: [
+      {
+        value: '2-1',
+        label: 'Level two 2-1',
+        children: [
+          {
+            value: '2-1-1',
+            label: 'Level three 2-1-1'
+          }
+        ]
+      },
+      {
+        value: '2-2',
+        label: 'Level two 2-2',
+        children: [
+          {
+            value: '2-2-1',
+            label: 'Level three 2-2-1'
+          }
+        ]
+      }
+    ]
+  },
+  {
+    value: '3',
+    label: 'Level one 3',
+    children: [
+      {
+        value: '3-1',
+        label: 'Level two 3-1',
+        children: [
+          {
+            value: '3-1-1',
+            label: 'Level three 3-1-1'
+          }
+        ]
+      },
+      {
+        value: '3-2',
+        label: 'Level two 3-2',
+        children: [
+          {
+            value: '3-2-1',
+            label: 'Level three 3-2-1'
+          }
+        ]
+      }
+    ]
+  }
+]
+
+let id = 0
+
 const schema = reactive<FormSchema[]>([
   {
     field: 'field1',
@@ -1452,6 +1525,147 @@ const schema = reactive<FormSchema[]>([
       const res = await getDictOneApi()
       return res.data
     }
+  },
+  {
+    field: 'field82',
+    label: `${t('formDemo.treeSelect')}`,
+    component: 'TreeSelect',
+    // 远程加载option
+    optionApi: () => {
+      return treeSelectData
+    }
+  },
+  {
+    field: 'field75',
+    component: 'Divider',
+    label: `${t('formDemo.treeSelect')}`
+  },
+  {
+    field: 'field76',
+    component: 'TreeSelect',
+    label: `${t('formDemo.default')}`,
+    componentProps: {
+      renderAfterExpand: false,
+      data: treeSelectData
+    }
+  },
+  {
+    field: 'field76',
+    component: 'TreeSelect',
+    label: `${t('formDemo.showCheckbox')}`,
+    componentProps: {
+      renderAfterExpand: false,
+      showCheckbox: true,
+      data: treeSelectData
+    }
+  },
+  {
+    field: 'field77',
+    component: 'TreeSelect',
+    label: `${t('formDemo.selectAnyLevel')}`,
+    componentProps: {
+      renderAfterExpand: false,
+      showCheckbox: true,
+      checkStrictly: true,
+      checkOnClickNode: true,
+      data: treeSelectData
+    }
+  },
+  {
+    field: 'field78',
+    component: 'TreeSelect',
+    label: `${t('formDemo.multiple')}`,
+    componentProps: {
+      renderAfterExpand: false,
+      multiple: true,
+      showCheckbox: true,
+      checkStrictly: true,
+      checkOnClickNode: true,
+      data: treeSelectData
+    }
+  },
+  {
+    field: 'field79',
+    component: 'TreeSelect',
+    label: `${t('formDemo.filterable')}`,
+    componentProps: {
+      renderAfterExpand: false,
+      multiple: true,
+      filterable: true,
+      showCheckbox: true,
+      checkStrictly: true,
+      checkOnClickNode: true,
+      filterNodeMethod: (value, data) => data.label.includes(value),
+      data: treeSelectData
+    }
+  },
+  {
+    field: 'field80',
+    component: 'TreeSelect',
+    label: `${t('formDemo.customContent')}`,
+    componentProps: {
+      renderAfterExpand: false,
+      multiple: true,
+      filterable: true,
+      showCheckbox: true,
+      checkStrictly: true,
+      checkOnClickNode: true,
+      filterNodeMethod: (value, data) => data.label.includes(value),
+      slots: {
+        default: ({ data: { label } }) => {
+          return (
+            <>
+              {label}
+              <span style="color: gray">(suffix)</span>
+            </>
+          )
+        }
+      },
+      data: treeSelectData
+    }
+  },
+  {
+    field: 'field81',
+    component: 'TreeSelect',
+    label: `${t('formDemo.lazyLoad')}`,
+    componentProps: {
+      renderAfterExpand: false,
+      lazy: true,
+      load: (node, resolve) => {
+        if (node.isLeaf) return resolve([])
+
+        setTimeout(() => {
+          resolve([
+            {
+              value: ++id,
+              label: `lazy load node${id}`
+            },
+            {
+              value: ++id,
+              label: `lazy load node${id}`,
+              isLeaf: true
+            }
+          ])
+        }, 400)
+      },
+      multiple: true,
+      filterable: true,
+      showCheckbox: true,
+      checkStrictly: true,
+      checkOnClickNode: true,
+      filterNodeMethod: (value, data) => data.label.includes(value),
+      slots: {
+        default: ({ data: { label } }) => {
+          return (
+            <>
+              {label}
+              <span style="color: gray">(suffix)</span>
+            </>
+          )
+        }
+      },
+      data: treeSelectData
+    }
   }
 ])
 </script>