浏览代码

wip: 表单BUG修复中

kailong321200875 1 年之前
父节点
当前提交
289c1c2cf5

+ 1 - 1
.env.base

@@ -2,7 +2,7 @@
 NODE_ENV=development
 
 # 接口前缀
-VITE_API_BASEPATH=base
+VITE_API_BASE_PATH=base
 
 # 打包路径
 VITE_BASE_PATH=/

+ 1 - 1
.env.dev

@@ -2,7 +2,7 @@
 NODE_ENV=production
 
 # 接口前缀
-VITE_API_BASEPATH=dev
+VITE_API_BASE_PATH=dev
 
 # 打包路径
 VITE_BASE_PATH=/dist-dev/

+ 1 - 1
.env.gitee

@@ -2,7 +2,7 @@
 NODE_ENV=production
 
 # 接口前缀
-VITE_API_BASEPATH=pro
+VITE_API_BASE_PATH=pro
 
 # 打包路径
 VITE_BASE_PATH=/vue-element-plus-admin/

+ 1 - 1
.env.pro

@@ -2,7 +2,7 @@
 NODE_ENV=production
 
 # 接口前缀
-VITE_API_BASEPATH=pro
+VITE_API_BASE_PATH=pro
 
 # 打包路径
 VITE_BASE_PATH=/

+ 1 - 1
.env.test

@@ -2,7 +2,7 @@
 NODE_ENV=production
 
 # 接口前缀
-VITE_API_BASEPATH=test
+VITE_API_BASE_PATH=test
 
 # 打包路径
 VITE_BASE_PATH=/dist-test/

+ 1 - 1
package.json

@@ -10,7 +10,7 @@
     "ts:check": "vue-tsc --noEmit",
     "build:pro": "vite build --mode pro",
     "build:gitee": "vite build --mode gitee",
-    "build:dev": "npm run ts:check && vite build --mode dev",
+    "build:dev": "vite build --mode dev",
     "build:test": "npm run ts:check && vite build --mode test",
     "serve:pro": "vite preview --mode pro",
     "serve:dev": "vite preview --mode dev",

+ 2 - 2
src/api/common/index.ts

@@ -1,11 +1,11 @@
 import request from '@/config/axios'
 
 // 获取所有字典
-export const getDictApi = (): Promise<IResponse> => {
+export const getDictApi = () => {
   return request.get({ url: '/dict/list' })
 }
 
 // 模拟获取某个字典
-export const getDictOneApi = async (): Promise<IResponse> => {
+export const getDictOneApi = async () => {
   return request.get({ url: '/dict/one' })
 }

+ 104 - 78
src/components/Form/src/Form.vue

@@ -1,6 +1,15 @@
 <script lang="tsx">
-import { PropType, defineComponent, ref, computed, unref, watch, onMounted } from 'vue'
-import { ElForm, ElFormItem, ElRow, ElCol, ElTooltip } from 'element-plus'
+import {
+  PropType,
+  defineComponent,
+  ref,
+  computed,
+  unref,
+  watch,
+  onMounted,
+  defineAsyncComponent
+} from 'vue'
+import { ElForm, ElFormItem, ElRow, ElCol } from 'element-plus'
 import { componentMap } from './helper/componentMap'
 import { propTypes } from '@/utils/propTypes'
 import { getSlot } from '@/utils/tsxHelper'
@@ -9,8 +18,7 @@ import {
   setGridProp,
   setComponentProps,
   setItemComponentSlots,
-  initModel,
-  setFormItemSlots
+  initModel
 } from './helper'
 import { useRenderSelect } from './components/useRenderSelect'
 import { useRenderRadio } from './components/useRenderRadio'
@@ -19,7 +27,6 @@ import { useDesign } from '@/hooks/web/useDesign'
 import { findIndex } from '@/utils'
 import { set } from 'lodash-es'
 import { FormProps } from './types'
-import { Icon } from '@/components/Icon'
 import {
   FormSchema,
   FormSetProps,
@@ -125,6 +132,11 @@ export default defineComponent({
       return unref(elFormRef) as ComponentRef<typeof ElForm>
     }
 
+    const getOptions = async (fn: Function) => {
+      const options = await fn()
+      console.log('=====:', options)
+    }
+
     expose({
       setValues,
       formModel,
@@ -139,6 +151,7 @@ export default defineComponent({
     watch(
       () => unref(getProps).schema,
       (schema = []) => {
+        console.log('@@####')
         formModel.value = initModel(schema, unref(formModel))
       },
       {
@@ -182,95 +195,108 @@ export default defineComponent({
 
     // 渲染formItem
     const renderFormItem = (item: FormSchema) => {
-      const formItemSlots = {
+      const formItemSlots: Recordable = {
         default: () => {
-              if (slots[item.field]) {
-                return getSlot(slots, item.field, formModel.value)
-              } else {
-                const Com = componentMap[item.component as string] as ReturnType<
-                  typeof defineComponent
-                >
+          if (slots[item.field]) {
+            return getSlot(slots, item.field, formModel.value)
+          } else {
+            console.log(item.field)
+            const Com = componentMap[item.component as string] as ReturnType<typeof defineComponent>
+
+            const { autoSetPlaceholder } = unref(getProps)
 
-                const { autoSetPlaceholder } = unref(getProps)
-
-                const componentSlots = (item?.componentProps as any)?.slots || {}
-                const slotsMap: Recordable = {
-                  ...setItemComponentSlots(componentSlots)
-                }
-                // 如果是select组件,并且没有自定义模板,自动渲染options
-                if (item.component === ComponentNameEnum.SELECT) {
-                  slotsMap.default = !componentSlots.default
-                    ? () => renderSelectOptions(item)
-                    : () => {
-                        return componentSlots.default(
-                          unref((item?.componentProps as SelectComponentProps)?.options)
-                        )
-                      }
-                }
-
-                // 虚拟列表
-                if (item.component === ComponentNameEnum.SELECT_V2 && componentSlots.default) {
-                  slotsMap.default = ({ item }) => {
-                    return componentSlots.default(item)
+            const componentSlots = (item?.componentProps as any)?.slots || {}
+            const slotsMap: Recordable = {
+              ...setItemComponentSlots(componentSlots)
+            }
+            // // 如果是select组件,并且没有自定义模板,自动渲染options
+            if (item.component === ComponentNameEnum.SELECT) {
+              // 如果有optionApi,优先使用optionApi
+              if (item.optionApi) {
+                // 内部自动调用接口,不影响其他渲染
+                getOptions(item.optionApi)
+              }
+              slotsMap.default = !componentSlots.default
+                ? () => renderSelectOptions(item)
+                : () => {
+                    return componentSlots.default(
+                      unref((item?.componentProps as SelectComponentProps)?.options)
+                    )
                   }
-                }
-
-                // 单选框组和按钮样式
-                if (
-                  item.component === ComponentNameEnum.RADIO_GROUP ||
-                  item.component === ComponentNameEnum.RADIO_BUTTON
-                ) {
-                  slotsMap.default = !componentSlots.default
-                    ? () => renderRadioOptions(item)
-                    : () => {
-                        return componentSlots.default(
-                          unref((item?.componentProps as CheckboxGroupComponentProps)?.options)
-                        )
-                      }
-                }
-
-                // 多选框组和按钮样式
-                if (
-                  item.component === ComponentNameEnum.CHECKBOX_GROUP ||
-                  item.component === ComponentNameEnum.CHECKBOX_BUTTON
-                ) {
-                  slotsMap.default = !componentSlots.default
-                    ? () => renderCheckboxOptions(item)
-                    : () => {
-                        return componentSlots.default(
-                          unref((item?.componentProps as RadioGroupComponentProps)?.options)
-                        )
-                      }
-                }
-
-                return (
-                  <Com
-                    vModel={formModel.value[item.field]}
-                    {...(autoSetPlaceholder && setTextPlaceholder(item))}
-                    {...setComponentProps(item)}
-                    style={item.componentProps?.style || {}}
-                  >
-                    {{ ...slotsMap }}
-                  </Com>
-                )
+            }
+
+            // 虚拟列表
+            if (item.component === ComponentNameEnum.SELECT_V2 && componentSlots.default) {
+              slotsMap.default = ({ item }) => {
+                return componentSlots.default(item)
               }
             }
+
+            // 单选框组和按钮样式
+            if (
+              item.component === ComponentNameEnum.RADIO_GROUP ||
+              item.component === ComponentNameEnum.RADIO_BUTTON
+            ) {
+              slotsMap.default = !componentSlots.default
+                ? () => renderRadioOptions(item)
+                : () => {
+                    return componentSlots.default(
+                      unref((item?.componentProps as CheckboxGroupComponentProps)?.options)
+                    )
+                  }
+            }
+
+            // 多选框组和按钮样式
+            if (
+              item.component === ComponentNameEnum.CHECKBOX_GROUP ||
+              item.component === ComponentNameEnum.CHECKBOX_BUTTON
+            ) {
+              slotsMap.default = !componentSlots.default
+                ? () => renderCheckboxOptions(item)
+                : () => {
+                    return componentSlots.default(
+                      unref((item?.componentProps as RadioGroupComponentProps)?.options)
+                    )
+                  }
+            }
+
+            const Comp = () => {
+              return (
+                <Com
+                  vModel={formModel.value[item.field]}
+                  {...(autoSetPlaceholder && setTextPlaceholder(item))}
+                  {...setComponentProps(item)}
+                  style={item.componentProps?.style || {}}
+                >
+                  {{ ...slotsMap }}
+                </Com>
+              )
+            }
+
+            return <>{Comp()}</>
+          }
+        }
       }
       if (item?.formItemProps?.slots?.label) {
         formItemSlots.label = (...args: any[]) => {
-          return item.formItemProps.slots.label(...args)
+          return (item?.formItemProps?.slots as any)?.label(...args)
         }
       }
       if (item?.formItemProps?.slots?.error) {
         formItemSlots.error = (...args: any[]) => {
-          return item.formItemProps.slots.error(...args)
+          return (item?.formItemProps?.slots as any)?.error(...args)
         }
       }
       return (
         <ElFormItem {...(item.formItemProps || {})} prop={item.field} label={item.label || ''}>
-          {{
-            ...formItemSlots
-          }}
+          {formItemSlots}
+          {/* {{
+            default: () => {
+              console.log(item.field)
+
+              return '2222'
+            }
+          }} */}
         </ElFormItem>
       )
     }

+ 1 - 1
src/components/Form/src/types/index.ts

@@ -820,7 +820,7 @@ export interface FormSchema {
   /**
    * @returns 远程加载下拉项
    */
-  api?: <T = any>() => AxiosPromise<T>
+  optionApi?: any
 }
 
 export interface FormProps {

+ 0 - 4
src/components/InputPassword/src/InputPassword.vue

@@ -32,10 +32,6 @@ const emit = defineEmits(['update:modelValue'])
 // 设置input的type属性
 const textType = ref<'password' | 'text'>('password')
 
-const changeTextType = () => {
-  textType.value = unref(textType) === 'text' ? 'password' : 'text'
-}
-
 // 输入框的值
 const valueRef = ref(props.modelValue)
 

+ 1 - 1
src/config/axios/config.ts

@@ -4,7 +4,7 @@ import {
   AxiosRequestHeaders,
   AxiosError,
   InternalAxiosRequestConfig
-} from './type'
+} from './types'
 import { ElMessage } from 'element-plus'
 import qs from 'qs'
 

+ 9 - 9
src/config/axios/index.ts

@@ -4,7 +4,7 @@ import config from './config'
 
 const { defaultHeaders } = config
 
-const request = (option: any) => {
+const request = (option: AxiosConfig) => {
   const { url, method, params, data, headersType, responseType } = option
   return service.request({
     url: url,
@@ -19,17 +19,17 @@ const request = (option: any) => {
 }
 
 export default {
-  get: <T = any>(option: any) => {
-    return request({ method: 'get', ...option }) as unknown as T
+  get: <T = any>(option: AxiosConfig) => {
+    return request({ method: 'get', ...option }) as Promise<IResponse<T>>
   },
-  post: <T = any>(option: any) => {
-    return request({ method: 'post', ...option }) as unknown as T
+  post: <T = any>(option: AxiosConfig) => {
+    return request({ method: 'post', ...option }) as Promise<IResponse<T>>
   },
-  delete: <T = any>(option: any) => {
-    return request({ method: 'delete', ...option }) as unknown as T
+  delete: <T = any>(option: AxiosConfig) => {
+    return request({ method: 'delete', ...option }) as Promise<IResponse<T>>
   },
-  put: <T = any>(option: any) => {
-    return request({ method: 'put', ...option }) as unknown as T
+  put: <T = any>(option: AxiosConfig) => {
+    return request({ method: 'put', ...option }) as Promise<IResponse<T>>
   },
   cancelRequest: (url: string | string[]) => {
     return service.cancelRequest(url)

+ 2 - 2
src/config/axios/service.ts

@@ -1,10 +1,10 @@
 import axios from 'axios'
 import config, { defaultRequestInterceptors, defaultResponseInterceptors } from './config'
 
-import { AxiosInstance, InternalAxiosRequestConfig, RequestConfig, AxiosResponse } from './type'
+import { AxiosInstance, InternalAxiosRequestConfig, RequestConfig, AxiosResponse } from './types'
 
 const { interceptors, baseUrl } = config
-export const PATH_URL = baseUrl[import.meta.env.VITE_API_BASEPATH]
+export const PATH_URL = baseUrl[import.meta.env.VITE_API_BASE_PATH]
 
 const { requestInterceptors, responseInterceptors } = interceptors
 

+ 0 - 0
src/config/axios/type.ts → src/config/axios/types/index.ts


+ 3 - 1
src/locales/en.ts

@@ -283,7 +283,9 @@ export default {
     verifyReset: 'Verify reset',
     // 富文本编辑器
     richText: 'Rich text',
-    form: 'Form'
+    form: 'Form',
+    // 远程加载
+    remoteLoading: 'Remote loading'
   },
   guideDemo: {
     guide: 'Guide',

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

@@ -282,7 +282,9 @@ export default {
     verifyReset: '验证重置',
     // 富文本编辑器
     richText: '富文本编辑器',
-    form: '表单'
+    form: '表单',
+    // 远程加载
+    remoteLoading: '远程加载'
   },
   guideDemo: {
     guide: '引导页',

+ 1016 - 999
src/views/Components/Form/DefaultForm.vue

@@ -16,6 +16,7 @@ import {
   ElCheckbox,
   ElCheckboxButton
 } from 'element-plus'
+import { getDictOneApi } from '@/api/common'
 
 const appStore = useAppStore()
 
@@ -382,1018 +383,1034 @@ const schema = reactive<FormSchema[]>([
       parser: (value) => value.replace(/\$\s?|(,*)/g, '')
     }
   },
-  {
-    field: 'field3',
-    label: `${t('formDemo.icon')}1`,
-    component: 'Input',
-    componentProps: {
-      suffixIcon: useIcon({ icon: 'ep:calendar' }),
-      prefixIcon: useIcon({ icon: 'ep:share' })
-    }
-  },
-  {
-    field: 'field4',
-    label: `${t('formDemo.icon')}2`,
-    component: 'Input',
-    componentProps: {
-      slots: {
-        suffix: () => {
-          return useIcon({ icon: 'ep:share' })
-        },
-        prefix: () => useIcon({ icon: 'ep:calendar' })
-      }
-    }
-  },
-  {
-    field: 'field5',
-    label: t('formDemo.mixed'),
-    component: 'Input',
-    componentProps: {
-      slots: {
-        prepend: () => useIcon({ icon: 'ep:calendar' }),
-        append: () => useIcon({ icon: 'ep:share' })
-      }
-    }
-  },
-  {
-    field: 'input-field7',
-    label: t('formDemo.password'),
-    component: 'Input',
-    componentProps: {
-      showPassword: true
-    }
-  },
-  {
-    field: 'field6',
-    label: t('formDemo.textarea'),
-    component: 'Input',
-    componentProps: {
-      type: 'textarea',
-      rows: 2
-    }
-  },
-  {
-    field: 'field7',
-    label: t('formDemo.autocomplete'),
-    component: 'Divider'
-  },
-  {
-    field: 'field8',
-    label: t('formDemo.default'),
-    component: 'Autocomplete',
-    componentProps: {
-      fetchSuggestions: querySearch,
-      on: {
-        select: handleSelect
-      }
-    }
-  },
-  {
-    field: 'field9',
-    label: t('formDemo.slot'),
-    component: 'Autocomplete',
-    componentProps: {
-      fetchSuggestions: querySearch,
-      on: {
-        select: handleSelect
-      },
-      slots: {
-        default: ({ item }) => {
-          return (
-            <>
-              <div class="value">{item?.value}</div>
-              <span class="link">{item?.link}</span>
-            </>
-          )
-        }
-      }
-    }
-  },
-  {
-    field: 'autocomplete-field10',
-    label: t('formDemo.remoteSearch'),
-    component: 'Autocomplete',
-    componentProps: {
-      fetchSuggestions: querySearchAsync,
-      on: {
-        select: handleSelect
-      }
-    }
-  },
-  {
-    field: 'field10',
+  // {
+  //   field: 'field3',
+  //   label: `${t('formDemo.icon')}1`,
+  //   component: 'Input',
+  //   componentProps: {
+  //     suffixIcon: useIcon({ icon: 'ep:calendar' }),
+  //     prefixIcon: useIcon({ icon: 'ep:share' })
+  //   }
+  // },
+  // {
+  //   field: 'field4',
+  //   label: `${t('formDemo.icon')}2`,
+  //   component: 'Input',
+  //   componentProps: {
+  //     slots: {
+  //       suffix: () => {
+  //         return useIcon({ icon: 'ep:share' })
+  //       },
+  //       prefix: () => useIcon({ icon: 'ep:calendar' })
+  //     }
+  //   }
+  // },
+  // {
+  //   field: 'field5',
+  //   label: t('formDemo.mixed'),
+  //   component: 'Input',
+  //   componentProps: {
+  //     slots: {
+  //       prepend: () => useIcon({ icon: 'ep:calendar' }),
+  //       append: () => useIcon({ icon: 'ep:share' })
+  //     }
+  //   }
+  // },
+  // {
+  //   field: 'input-field7',
+  //   label: t('formDemo.password'),
+  //   component: 'Input',
+  //   componentProps: {
+  //     showPassword: true
+  //   }
+  // },
+  // {
+  //   field: 'field6',
+  //   label: t('formDemo.textarea'),
+  //   component: 'Input',
+  //   componentProps: {
+  //     type: 'textarea',
+  //     rows: 2
+  //   }
+  // },
+  // {
+  //   field: 'field7',
+  //   label: t('formDemo.autocomplete'),
+  //   component: 'Divider'
+  // },
+  // {
+  //   field: 'field8',
+  //   label: t('formDemo.default'),
+  //   component: 'Autocomplete',
+  //   componentProps: {
+  //     fetchSuggestions: querySearch,
+  //     on: {
+  //       select: handleSelect
+  //     }
+  //   }
+  // },
+  // {
+  //   field: 'field9',
+  //   label: t('formDemo.slot'),
+  //   component: 'Autocomplete',
+  //   componentProps: {
+  //     fetchSuggestions: querySearch,
+  //     on: {
+  //       select: handleSelect
+  //     },
+  //     slots: {
+  //       default: ({ item }) => {
+  //         return (
+  //           <>
+  //             <div class="value">{item?.value}</div>
+  //             <span class="link">{item?.link}</span>
+  //           </>
+  //         )
+  //       }
+  //     }
+  //   }
+  // },
+  // {
+  //   field: 'autocomplete-field10',
+  //   label: t('formDemo.remoteSearch'),
+  //   component: 'Autocomplete',
+  //   componentProps: {
+  //     fetchSuggestions: querySearchAsync,
+  //     on: {
+  //       select: handleSelect
+  //     }
+  //   }
+  // },
+  // {
+  //   field: 'field10',
+  //   component: 'Divider',
+  //   label: t('formDemo.inputNumber')
+  // },
+  // {
+  //   field: 'field11',
+  //   label: t('formDemo.default'),
+  //   component: 'InputNumber',
+  //   value: 0
+  // },
+  // {
+  //   field: 'field12',
+  //   label: t('formDemo.position'),
+  //   component: 'InputNumber',
+  //   componentProps: {
+  //     controlsPosition: 'right'
+  //   },
+  //   value: 10
+  // },
+  // {
+  //   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'
+  //       }
+  //     ],
+  //     slots: {
+  //       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: () => {
+  //         return 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">{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} label={v.label} value={v.value} />
+  //             })}
+  //           </ElOptionGroup>
+  //         )
+  //       }
+  //     }
+  //   }
+  // },
+  // {
+  //   field: 'field18',
+  //   label: `${t('formDemo.selectV2')}`,
+  //   component: 'Divider'
+  // },
+  // {
+  //   field: 'field19',
+  //   label: t('formDemo.default'),
+  //   component: 'SelectV2',
+  //   componentProps: {
+  //     value: undefined,
+  //     options: options.value
+  //   }
+  // },
+  // {
+  //   field: 'field20',
+  //   label: t('formDemo.slot'),
+  //   component: 'SelectV2',
+  //   componentProps: {
+  //     options: options.value,
+  //     slots: {
+  //       default: (option: SelectOption) => {
+  //         return (
+  //           <>
+  //             <span style="margin-right: 8px">{option?.label}</span>
+  //             <span style="color: var(--el-text-color-secondary); font-size: 13px">
+  //               {option?.value}
+  //             </span>
+  //           </>
+  //         )
+  //       }
+  //     }
+  //   }
+  // },
+  // {
+  //   field: 'field21',
+  //   label: t('formDemo.selectGroup'),
+  //   component: 'SelectV2',
+  //   componentProps: {
+  //     options: options2.value
+  //   }
+  // },
+  // {
+  //   field: 'field22',
+  //   label: `${t('formDemo.selectGroup')} ${t('formDemo.slot')}`,
+  //   component: 'SelectV2',
+  //   componentProps: {
+  //     options: options2.value,
+  //     slots: {
+  //       default: (option: SelectOption) => {
+  //         return (
+  //           <>
+  //             <span style="margin-right: 8px">{option?.label}</span>
+  //             <span style="color: var(--el-text-color-secondary); font-size: 13px">
+  //               {option?.value}
+  //             </span>
+  //           </>
+  //         )
+  //       }
+  //     }
+  //   }
+  // },
+  // {
+  //   field: 'field23',
+  //   label: t('formDemo.cascader'),
+  //   component: 'Divider'
+  // },
+  // {
+  //   field: 'field24',
+  //   label: t('formDemo.default'),
+  //   component: 'Cascader',
+  //   componentProps: {
+  //     options: options3,
+  //     props: {
+  //       multiple: true
+  //     }
+  //   }
+  // },
+  // {
+  //   field: 'field25',
+  //   label: t('formDemo.slot'),
+  //   component: 'Cascader',
+  //   componentProps: {
+  //     options: options3,
+  //     slots: {
+  //       default: ({ data, node }) => {
+  //         return (
+  //           <>
+  //             <span>{data.label}</span>
+  //             {!node.isLeaf ? <span> ({data.children.length}) </span> : null}
+  //           </>
+  //         )
+  //       }
+  //     }
+  //   }
+  // },
+  // {
+  //   field: 'field26',
+  //   label: t('formDemo.switch'),
+  //   component: 'Divider'
+  // },
+  // {
+  //   field: 'field27',
+  //   label: t('formDemo.default'),
+  //   component: 'Switch',
+  //   value: false
+  // },
+  // {
+  //   field: 'field28',
+  //   label: t('formDemo.icon'),
+  //   component: 'Switch',
+  //   value: false,
+  //   componentProps: {
+  //     activeIcon: useIcon({ icon: 'ep:check' }),
+  //     inactiveIcon: useIcon({ icon: 'ep:close' })
+  //   }
+  // },
+  // {
+  //   field: 'field29',
+  //   label: t('formDemo.rate'),
+  //   component: 'Divider'
+  // },
+  // {
+  //   field: 'field30',
+  //   label: t('formDemo.default'),
+  //   component: 'Rate',
+  //   value: 0
+  // },
+  // {
+  //   field: 'field31',
+  //   label: t('formDemo.icon'),
+  //   component: 'Rate',
+  //   value: null,
+  //   componentProps: {
+  //     voidIcon: useIcon({ icon: 'ep:chat-round' }),
+  //     icons: [
+  //       useIcon({ icon: 'ep:chat-round' }),
+  //       useIcon({ icon: 'ep:chat-line-round' }),
+  //       useIcon({ icon: 'ep:chat-dot-round' })
+  //     ]
+  //   }
+  // },
+  // {
+  //   field: 'field32',
+  //   label: t('formDemo.colorPicker'),
+  //   component: 'Divider'
+  // },
+  // {
+  //   field: 'field33',
+  //   label: t('formDemo.default'),
+  //   component: 'ColorPicker'
+  // },
+  // {
+  //   field: 'field34',
+  //   label: t('formDemo.transfer'),
+  //   component: 'Divider'
+  // },
+  // {
+  //   field: 'field35',
+  //   label: t('formDemo.default'),
+  //   component: 'Transfer',
+  //   componentProps: {
+  //     props: {
+  //       key: 'value',
+  //       label: 'desc'
+  //     },
+  //     data: generateData()
+  //   },
+  //   value: [],
+  //   colProps: {
+  //     span: 24
+  //   }
+  // },
+  // {
+  //   field: 'field36',
+  //   label: t('formDemo.slot'),
+  //   component: 'Transfer',
+  //   componentProps: {
+  //     props: {
+  //       key: 'value',
+  //       label: 'desc'
+  //     },
+  //     filterable: true,
+  //     leftDefaultChecked: [2, 3],
+  //     rightDefaultChecked: [1],
+  //     titles: ['Source', 'Target'],
+  //     buttonTexts: ['To Left', 'To Right'],
+  //     format: {
+  //       noChecked: '${total}',
+  //       hasChecked: '${checked}/${total}'
+  //     },
+  //     data: generateData(),
+  //     slots: {
+  //       default: ({ option }) => {
+  //         return (
+  //           <span>
+  //             {option.value} - {option.desc}
+  //           </span>
+  //         )
+  //       },
+  //       leftFooter: () => {
+  //         return (
+  //           <ElButton class="transfer-footer" size="small">
+  //             Operation
+  //           </ElButton>
+  //         )
+  //       },
+  //       rightFooter: () => {
+  //         return (
+  //           <ElButton class="transfer-footer" size="small">
+  //             Operation
+  //           </ElButton>
+  //         )
+  //       }
+  //     }
+  //   },
+  //   value: [1],
+  //   colProps: {
+  //     span: 24
+  //   }
+  // },
+  // {
+  //   field: 'field37',
+  //   label: `${t('formDemo.render')}`,
+  //   component: 'Transfer',
+  //   componentProps: {
+  //     props: {
+  //       key: 'value',
+  //       label: 'desc',
+  //       disabled: 'disabled'
+  //     },
+  //     leftDefaultChecked: [2, 3],
+  //     rightDefaultChecked: [1],
+  //     data: generateData(),
+  //     renderContent: (h, option) => {
+  //       return h('span', null, `${option.value} - ${option.desc}`)
+  //     }
+  //   },
+  //   value: [1],
+  //   colProps: {
+  //     span: 24
+  //   }
+  // },
+  // {
+  //   field: 'field38',
+  //   label: t('formDemo.radio'),
+  //   component: 'Divider'
+  // },
+  // {
+  //   field: 'field39-2',
+  //   label: t('formDemo.radioGroup'),
+  //   component: 'RadioGroup',
+  //   componentProps: {
+  //     options: [
+  //       {
+  //         // disabled: true,
+  //         label: 'option-1',
+  //         value: '1'
+  //       },
+  //       {
+  //         label: 'option-2',
+  //         value: '2'
+  //       }
+  //     ]
+  //   }
+  // },
+  // {
+  //   field: 'field39-3',
+  //   label: `${t('formDemo.radioGroup')} ${t('formDemo.slot')}`,
+  //   component: 'RadioGroup',
+  //   componentProps: {
+  //     options: [
+  //       {
+  //         // disabled: true,
+  //         label: 'option-1',
+  //         value: '1'
+  //       },
+  //       {
+  //         label: 'option-2',
+  //         value: '2'
+  //       }
+  //     ],
+  //     slots: {
+  //       default: (options: RadioOption[]) => {
+  //         return options?.map((v) => {
+  //           return (
+  //             <ElRadio label={v.value}>
+  //               {v.label}({v.value})
+  //             </ElRadio>
+  //           )
+  //         })
+  //       }
+  //     }
+  //   }
+  // },
+  // {
+  //   field: 'field40',
+  //   label: t('formDemo.button'),
+  //   component: 'RadioButton',
+  //   componentProps: {
+  //     options: [
+  //       {
+  //         label: 'option-1',
+  //         value: '1'
+  //       },
+  //       {
+  //         label: 'option-2',
+  //         value: '2'
+  //       }
+  //     ]
+  //   }
+  // },
+  // {
+  //   field: 'field40-1',
+  //   label: `${t('formDemo.button')} ${t('formDemo.slot')}`,
+  //   component: 'RadioButton',
+  //   componentProps: {
+  //     options: [
+  //       {
+  //         label: 'option-1',
+  //         value: '1'
+  //       },
+  //       {
+  //         label: 'option-2',
+  //         value: '2'
+  //       }
+  //     ],
+  //     slots: {
+  //       default: (options: RadioOption[]) => {
+  //         return options?.map((v) => {
+  //           return (
+  //             <ElRadioButton label={v.value}>
+  //               {v.label}({v.value})
+  //             </ElRadioButton>
+  //           )
+  //         })
+  //       }
+  //     }
+  //   }
+  // },
+  // {
+  //   field: 'field41',
+  //   label: t('formDemo.checkbox'),
+  //   component: 'Divider'
+  // },
+  // {
+  //   field: 'field42-2',
+  //   label: t('formDemo.checkboxGroup'),
+  //   component: 'CheckboxGroup',
+  //   value: [],
+  //   componentProps: {
+  //     options: [
+  //       {
+  //         label: 'option-1',
+  //         value: '1'
+  //       },
+  //       {
+  //         label: 'option-2',
+  //         value: '2'
+  //       },
+  //       {
+  //         label: 'option-3',
+  //         value: '3'
+  //       }
+  //     ]
+  //   }
+  // },
+  // {
+  //   field: 'field42-3',
+  //   label: `${t('formDemo.checkboxGroup')} ${t('formDemo.slot')}`,
+  //   component: 'CheckboxGroup',
+  //   value: [],
+  //   componentProps: {
+  //     options: [
+  //       {
+  //         label: 'option-1',
+  //         value: '1'
+  //       },
+  //       {
+  //         label: 'option-2',
+  //         value: '2'
+  //       },
+  //       {
+  //         label: 'option-3',
+  //         value: '3'
+  //       }
+  //     ],
+  //     slots: {
+  //       default: (options: CheckboxOption[]) => {
+  //         return options?.map((v) => {
+  //           return (
+  //             <ElCheckbox label={v.value}>
+  //               {v.label}({v.value})
+  //             </ElCheckbox>
+  //           )
+  //         })
+  //       }
+  //     }
+  //   }
+  // },
+  // {
+  //   field: 'field43',
+  //   label: t('formDemo.button'),
+  //   component: 'CheckboxButton',
+  //   value: [],
+  //   componentProps: {
+  //     options: [
+  //       {
+  //         disabled: true,
+  //         label: 'option-1',
+  //         value: '1'
+  //       },
+  //       {
+  //         label: 'option-2',
+  //         value: '2'
+  //       },
+  //       {
+  //         label: 'option-3',
+  //         value: '23'
+  //       }
+  //     ]
+  //   }
+  // },
+  // {
+  //   field: 'field43-1',
+  //   label: `${t('formDemo.button')} ${t('formDemo.slot')}`,
+  //   component: 'CheckboxButton',
+  //   value: [],
+  //   componentProps: {
+  //     options: [
+  //       {
+  //         disabled: true,
+  //         label: 'option-1',
+  //         value: '1'
+  //       },
+  //       {
+  //         label: 'option-2',
+  //         value: '2'
+  //       },
+  //       {
+  //         label: 'option-3',
+  //         value: '23'
+  //       }
+  //     ],
+  //     slots: {
+  //       default: (options: CheckboxOption[]) => {
+  //         return options?.map((v) => {
+  //           return (
+  //             <ElCheckboxButton label={v.value}>
+  //               {v.label}({v.value})
+  //             </ElCheckboxButton>
+  //           )
+  //         })
+  //       }
+  //     }
+  //   }
+  // },
+  // {
+  //   field: 'field44',
+  //   component: 'Divider',
+  //   label: t('formDemo.slider')
+  // },
+  // {
+  //   field: 'field45',
+  //   component: 'Slider',
+  //   label: t('formDemo.default'),
+  //   value: 0
+  // },
+  // {
+  //   field: 'field46',
+  //   component: 'Divider',
+  //   label: t('formDemo.datePicker')
+  // },
+  // {
+  //   field: 'field47',
+  //   component: 'DatePicker',
+  //   label: t('formDemo.default'),
+  //   componentProps: {
+  //     type: 'date'
+  //   }
+  // },
+  // {
+  //   field: 'field48',
+  //   component: 'DatePicker',
+  //   label: t('formDemo.shortcuts'),
+  //   componentProps: {
+  //     type: 'date',
+  //     disabledDate: (time: Date) => {
+  //       return time.getTime() > Date.now()
+  //     },
+  //     shortcuts: [
+  //       {
+  //         text: t('formDemo.today'),
+  //         value: new Date()
+  //       },
+  //       {
+  //         text: t('formDemo.yesterday'),
+  //         value: () => {
+  //           const date = new Date()
+  //           date.setTime(date.getTime() - 3600 * 1000 * 24)
+  //           return date
+  //         }
+  //       },
+  //       {
+  //         text: t('formDemo.aWeekAgo'),
+  //         value: () => {
+  //           const date = new Date()
+  //           date.setTime(date.getTime() - 3600 * 1000 * 24 * 7)
+  //           return date
+  //         }
+  //       }
+  //     ]
+  //   }
+  // },
+  // {
+  //   field: 'field47-1',
+  //   component: 'DatePicker',
+  //   label: t('formDemo.slot'),
+  //   value: '2021-10-29',
+  //   componentProps: {
+  //     type: 'date',
+  //     slots: {
+  //       default: (cell: any) => {
+  //         return (
+  //           <div class={{ cell: true, current: cell.isCurrent }}>
+  //             <span class="text">{cell.text}</span>
+  //             {isHoliday(cell) ? <span class="holiday" /> : null}
+  //           </div>
+  //         )
+  //       }
+  //     }
+  //   }
+  // },
+  // {
+  //   field: 'field49',
+  //   component: 'DatePicker',
+  //   label: t('formDemo.week'),
+  //   componentProps: {
+  //     type: 'week',
+  //     format: `[${t('formDemo.week')}]`
+  //   }
+  // },
+  // {
+  //   field: 'field50',
+  //   component: 'DatePicker',
+  //   label: t('formDemo.year'),
+  //   componentProps: {
+  //     type: 'year'
+  //   }
+  // },
+  // {
+  //   field: 'field51',
+  //   component: 'DatePicker',
+  //   label: t('formDemo.month'),
+  //   componentProps: {
+  //     type: 'month'
+  //   }
+  // },
+  // {
+  //   field: 'field52',
+  //   component: 'DatePicker',
+  //   label: t('formDemo.dates'),
+  //   componentProps: {
+  //     type: 'dates'
+  //   }
+  // },
+  // {
+  //   field: 'field53',
+  //   component: 'DatePicker',
+  //   label: t('formDemo.daterange'),
+  //   componentProps: {
+  //     type: 'daterange'
+  //   }
+  // },
+  // {
+  //   field: 'field54',
+  //   component: 'DatePicker',
+  //   label: t('formDemo.monthrange'),
+  //   componentProps: {
+  //     type: 'monthrange'
+  //   }
+  // },
+  // {
+  //   field: 'field56',
+  //   component: 'Divider',
+  //   label: t('formDemo.dateTimePicker')
+  // },
+  // {
+  //   field: 'field57',
+  //   component: 'DatePicker',
+  //   label: t('formDemo.default'),
+  //   componentProps: {
+  //     type: 'datetime'
+  //   }
+  // },
+  // {
+  //   field: 'field58',
+  //   component: 'DatePicker',
+  //   label: t('formDemo.shortcuts'),
+  //   componentProps: {
+  //     type: 'datetime',
+  //     shortcuts: [
+  //       {
+  //         text: t('formDemo.today'),
+  //         value: new Date()
+  //       },
+  //       {
+  //         text: t('formDemo.yesterday'),
+  //         value: () => {
+  //           const date = new Date()
+  //           date.setTime(date.getTime() - 3600 * 1000 * 24)
+  //           return date
+  //         }
+  //       },
+  //       {
+  //         text: t('formDemo.aWeekAgo'),
+  //         value: () => {
+  //           const date = new Date()
+  //           date.setTime(date.getTime() - 3600 * 1000 * 24 * 7)
+  //           return date
+  //         }
+  //       }
+  //     ]
+  //   }
+  // },
+  // {
+  //   field: 'field59',
+  //   component: 'DatePicker',
+  //   label: t('formDemo.dateTimerange'),
+  //   componentProps: {
+  //     type: 'datetimerange'
+  //   }
+  // },
+  // {
+  //   field: 'field60',
+  //   component: 'Divider',
+  //   label: t('formDemo.timePicker')
+  // },
+  // {
+  //   field: 'field61',
+  //   component: 'TimePicker',
+  //   label: t('formDemo.default')
+  // },
+  // {
+  //   field: 'field62',
+  //   component: 'Divider',
+  //   label: t('formDemo.timeSelect')
+  // },
+  // {
+  //   field: 'field63',
+  //   component: 'TimeSelect',
+  //   label: t('formDemo.default')
+  // },
+  // {
+  //   field: 'field64',
+  //   component: 'Divider',
+  //   label: t('formDemo.richText')
+  // },
+  // {
+  //   field: 'field65',
+  //   component: 'Editor',
+  //   value: 'hello world',
+  //   label: t('formDemo.default'),
+  //   colProps: {
+  //     span: 24
+  //   }
+  // },
+  // {
+  //   field: 'field66',
+  //   component: 'Divider',
+  //   label: t('formDemo.inputPassword')
+  // },
+  // {
+  //   field: 'field67',
+  //   component: 'InputPassword',
+  //   label: t('formDemo.default'),
+  //   componentProps: {
+  //     strength: true
+  //   }
+  // },
+  // {
+  //   field: 'field68',
+  //   component: 'Divider',
+  //   label: `${t('formDemo.form')} ${t('formDemo.slot')}`
+  // },
+  // {
+  //   field: 'field69',
+  //   component: 'Input',
+  //   label: `label`,
+  //   formItemProps: {
+  //     slots: {
+  //       label: ({ label }) => {
+  //         return (
+  //           <div class="custom-label">
+  //             <span class="label-text">custom {label}</span>
+  //           </div>
+  //         )
+  //       }
+  //     }
+  //   }
+  // },
+  {
+    field: 'field70',
     component: 'Divider',
-    label: t('formDemo.inputNumber')
-  },
-  {
-    field: 'field11',
-    label: t('formDemo.default'),
-    component: 'InputNumber',
-    value: 0
-  },
-  {
-    field: 'field12',
-    label: t('formDemo.position'),
-    component: 'InputNumber',
-    componentProps: {
-      controlsPosition: 'right'
-    },
-    value: 10
-  },
-  {
-    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'
-        }
-      ],
-      slots: {
-        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: () => {
-          return 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">{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'
-            }
-          ]
-        }
-      ]
-    }
+    label: `${t('formDemo.remoteLoading')}`
   },
   {
-    field: 'field17',
-    label: `${t('formDemo.selectGroup')}${t('formDemo.slot')}`,
+    field: 'field71',
+    label: `${t('formDemo.select')}`,
     component: 'Select',
     componentProps: {
       options: [
         {
-          label: 'option1',
-          options: [
-            {
-              label: 'option1-1',
-              value: '1-1'
-            },
-            {
-              label: 'option1-2',
-              value: '1-2'
-            }
-          ]
+          label: 'option1-1',
+          value: '1-1'
         },
         {
-          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}
-                    label={v.label}
-                    value={v.value}
-                  />
-                )
-              })}
-            </ElOptionGroup>
-          )
-        }
-      }
-    }
-  },
-  {
-    field: 'field18',
-    label: `${t('formDemo.selectV2')}`,
-    component: 'Divider'
-  },
-  {
-    field: 'field19',
-    label: t('formDemo.default'),
-    component: 'SelectV2',
-    componentProps: {
-      value: undefined,
-      options: options.value
-    }
-  },
-  {
-    field: 'field20',
-    label: t('formDemo.slot'),
-    component: 'SelectV2',
-    componentProps: {
-      options: options.value,
-      slots: {
-        default: (option: SelectOption) => {
-          return (
-            <>
-              <span style="margin-right: 8px">{option?.label}</span>
-              <span style="color: var(--el-text-color-secondary); font-size: 13px">
-                {option?.value}
-              </span>
-            </>
-          )
-        }
-      }
-    }
-  },
-  {
-    field: 'field21',
-    label: t('formDemo.selectGroup'),
-    component: 'SelectV2',
-    componentProps: {
-      options: options2.value
-    }
-  },
-  {
-    field: 'field22',
-    label: `${t('formDemo.selectGroup')}${t('formDemo.slot')}`,
-    component: 'SelectV2',
-    componentProps: {
-      options: options2.value,
-      slots: {
-        default: (option: SelectOption) => {
-          return (
-            <>
-              <span style="margin-right: 8px">{option?.label}</span>
-              <span style="color: var(--el-text-color-secondary); font-size: 13px">
-                {option?.value}
-              </span>
-            </>
-          )
+          label: 'option1-2',
+          value: '1-2'
         }
-      }
-    }
-  },
-  {
-    field: 'field23',
-    label: t('formDemo.cascader'),
-    component: 'Divider'
-  },
-  {
-    field: 'field24',
-    label: t('formDemo.default'),
-    component: 'Cascader',
-    componentProps: {
-      options: options3,
-      props: {
-        multiple: true
-      }
-    }
-  },
-  {
-    field: 'field25',
-    label: t('formDemo.slot'),
-    component: 'Cascader',
-    componentProps: {
-      options: options3,
-      slots: {
-        default: ({ data, node }) => {
-          return (
-            <>
-              <span>{data.label}</span>
-              {!node.isLeaf ? <span> ({data.children.length}) </span> : null}
-            </>
-          )
-        }
-      }
-    }
-  },
-  {
-    field: 'field26',
-    label: t('formDemo.switch'),
-    component: 'Divider'
-  },
-  {
-    field: 'field27',
-    label: t('formDemo.default'),
-    component: 'Switch',
-    value: false
-  },
-  {
-    field: 'field28',
-    label: t('formDemo.icon'),
-    component: 'Switch',
-    value: false,
-    componentProps: {
-      activeIcon: useIcon({ icon: 'ep:check' }),
-      inactiveIcon: useIcon({ icon: 'ep:close' })
-    }
-  },
-  {
-    field: 'field29',
-    label: t('formDemo.rate'),
-    component: 'Divider'
-  },
-  {
-    field: 'field30',
-    label: t('formDemo.default'),
-    component: 'Rate',
-    value: 0
-  },
-  {
-    field: 'field31',
-    label: t('formDemo.icon'),
-    component: 'Rate',
-    value: null,
-    componentProps: {
-      voidIcon: useIcon({ icon: 'ep:chat-round' }),
-      icons: [
-        useIcon({ icon: 'ep:chat-round' }),
-        useIcon({ icon: 'ep:chat-line-round' }),
-        useIcon({ icon: 'ep:chat-dot-round' })
       ]
-    }
-  },
-  {
-    field: 'field32',
-    label: t('formDemo.colorPicker'),
-    component: 'Divider'
-  },
-  {
-    field: 'field33',
-    label: t('formDemo.default'),
-    component: 'ColorPicker'
-  },
-  {
-    field: 'field34',
-    label: t('formDemo.transfer'),
-    component: 'Divider'
-  },
-  {
-    field: 'field35',
-    label: t('formDemo.default'),
-    component: 'Transfer',
-    componentProps: {
-      props: {
-        key: 'value',
-        label: 'desc'
-      },
-      data: generateData()
     },
-    value: [],
-    colProps: {
-      span: 24
+    // 远程加载option
+    optionApi: async () => {
+      const res = await getDictOneApi()
+      return res.data
     }
-  },
-  {
-    field: 'field36',
-    label: t('formDemo.slot'),
-    component: 'Transfer',
-    componentProps: {
-      props: {
-        key: 'value',
-        label: 'desc'
-      },
-      filterable: true,
-      leftDefaultChecked: [2, 3],
-      rightDefaultChecked: [1],
-      titles: ['Source', 'Target'],
-      buttonTexts: ['To Left', 'To Right'],
-      format: {
-        noChecked: '${total}',
-        hasChecked: '${checked}/${total}'
-      },
-      data: generateData(),
-      slots: {
-        default: ({ option }) => {
-          return (
-            <span>
-              {option.value} - {option.desc}
-            </span>
-          )
-        },
-        leftFooter: () => {
-          return (
-            <ElButton class="transfer-footer" size="small">
-              Operation
-            </ElButton>
-          )
-        },
-        rightFooter: () => {
-          return (
-            <ElButton class="transfer-footer" size="small">
-              Operation
-            </ElButton>
-          )
-        }
-      }
-    },
-    value: [1],
-    colProps: {
-      span: 24
-    }
-  },
-  {
-    field: 'field37',
-    label: `${t('formDemo.render')}`,
-    component: 'Transfer',
-    componentProps: {
-      props: {
-        key: 'value',
-        label: 'desc',
-        disabled: 'disabled'
-      },
-      leftDefaultChecked: [2, 3],
-      rightDefaultChecked: [1],
-      data: generateData(),
-      renderContent: (h, option) => {
-        return h('span', null, `${option.value} - ${option.desc}`)
-      }
-    },
-    value: [1],
-    colProps: {
-      span: 24
-    }
-  },
-  {
-    field: 'field38',
-    label: t('formDemo.radio'),
-    component: 'Divider'
-  },
-  {
-    field: 'field39-2',
-    label: t('formDemo.radioGroup'),
-    component: 'RadioGroup',
-    componentProps: {
-      options: [
-        {
-          // disabled: true,
-          label: 'option-1',
-          value: '1'
-        },
-        {
-          label: 'option-2',
-          value: '2'
-        }
-      ]
-    }
-  },
-  {
-    field: 'field39-3',
-    label: `${t('formDemo.radioGroup')} ${t('formDemo.slot')}`,
-    component: 'RadioGroup',
-    componentProps: {
-      options: [
-        {
-          // disabled: true,
-          label: 'option-1',
-          value: '1'
-        },
-        {
-          label: 'option-2',
-          value: '2'
-        }
-      ],
-      slots: {
-        default: (options: RadioOption[]) => {
-          return options?.map((v) => {
-            return (
-              <ElRadio label={v.value}>
-                {v.label}({v.value})
-              </ElRadio>
-            )
-          })
-        }
-      }
-    }
-  },
-  {
-    field: 'field40',
-    label: t('formDemo.button'),
-    component: 'RadioButton',
-    componentProps: {
-      options: [
-        {
-          label: 'option-1',
-          value: '1'
-        },
-        {
-          label: 'option-2',
-          value: '2'
-        }
-      ]
-    }
-  },
-  {
-    field: 'field40-1',
-    label: `${t('formDemo.button')} ${t('formDemo.slot')}`,
-    component: 'RadioButton',
-    componentProps: {
-      options: [
-        {
-          label: 'option-1',
-          value: '1'
-        },
-        {
-          label: 'option-2',
-          value: '2'
-        }
-      ],
-      slots: {
-        default: (options: RadioOption[]) => {
-          return options?.map((v) => {
-            return (
-              <ElRadioButton label={v.value}>
-                {v.label}({v.value})
-              </ElRadioButton>
-            )
-          })
-        }
-      }
-    }
-  },
-  {
-    field: 'field41',
-    label: t('formDemo.checkbox'),
-    component: 'Divider'
-  },
-  {
-    field: 'field42-2',
-    label: t('formDemo.checkboxGroup'),
-    component: 'CheckboxGroup',
-    value: [],
-    componentProps: {
-      options: [
-        {
-          label: 'option-1',
-          value: '1'
-        },
-        {
-          label: 'option-2',
-          value: '2'
-        },
-        {
-          label: 'option-3',
-          value: '3'
-        }
-      ]
-    }
-  },
-  {
-    field: 'field42-3',
-    label: `${t('formDemo.checkboxGroup')} ${t('formDemo.slot')}`,
-    component: 'CheckboxGroup',
-    value: [],
-    componentProps: {
-      options: [
-        {
-          label: 'option-1',
-          value: '1'
-        },
-        {
-          label: 'option-2',
-          value: '2'
-        },
-        {
-          label: 'option-3',
-          value: '3'
-        }
-      ],
-      slots: {
-        default: (options: CheckboxOption[]) => {
-          return options?.map((v) => {
-            return (
-              <ElCheckbox label={v.value}>
-                {v.label}({v.value})
-              </ElCheckbox>
-            )
-          })
-        }
-      }
-    }
-  },
-  {
-    field: 'field43',
-    label: t('formDemo.button'),
-    component: 'CheckboxButton',
-    value: [],
-    componentProps: {
-      options: [
-        {
-          disabled: true,
-          label: 'option-1',
-          value: '1'
-        },
-        {
-          label: 'option-2',
-          value: '2'
-        },
-        {
-          label: 'option-3',
-          value: '23'
-        }
-      ]
-    }
-  },
-  {
-    field: 'field43-1',
-    label: `${t('formDemo.button')} ${t('formDemo.slot')}`,
-    component: 'CheckboxButton',
-    value: [],
-    componentProps: {
-      options: [
-        {
-          disabled: true,
-          label: 'option-1',
-          value: '1'
-        },
-        {
-          label: 'option-2',
-          value: '2'
-        },
-        {
-          label: 'option-3',
-          value: '23'
-        }
-      ],
-      slots: {
-        default: (options: CheckboxOption[]) => {
-          return options?.map((v) => {
-            return (
-              <ElCheckboxButton label={v.value}>
-                {v.label}({v.value})
-              </ElCheckboxButton>
-            )
-          })
-        }
-      }
-    }
-  },
-  {
-    field: 'field44',
-    component: 'Divider',
-    label: t('formDemo.slider')
-  },
-  {
-    field: 'field45',
-    component: 'Slider',
-    label: t('formDemo.default'),
-    value: 0
-  },
-  {
-    field: 'field46',
-    component: 'Divider',
-    label: t('formDemo.datePicker')
-  },
-  {
-    field: 'field47',
-    component: 'DatePicker',
-    label: t('formDemo.default'),
-    componentProps: {
-      type: 'date'
-    }
-  },
-  {
-    field: 'field48',
-    component: 'DatePicker',
-    label: t('formDemo.shortcuts'),
-    componentProps: {
-      type: 'date',
-      disabledDate: (time: Date) => {
-        return time.getTime() > Date.now()
-      },
-      shortcuts: [
-        {
-          text: t('formDemo.today'),
-          value: new Date()
-        },
-        {
-          text: t('formDemo.yesterday'),
-          value: () => {
-            const date = new Date()
-            date.setTime(date.getTime() - 3600 * 1000 * 24)
-            return date
-          }
-        },
-        {
-          text: t('formDemo.aWeekAgo'),
-          value: () => {
-            const date = new Date()
-            date.setTime(date.getTime() - 3600 * 1000 * 24 * 7)
-            return date
-          }
-        }
-      ]
-    }
-  },
-  {
-    field: 'field47-1',
-    component: 'DatePicker',
-    label: t('formDemo.slot'),
-    value: '2021-10-29',
-    componentProps: {
-      type: 'date',
-      slots: {
-        default: (cell: any) => {
-          return (
-            <div class={{ cell: true, current: cell.isCurrent }}>
-              <span class="text">{cell.text}</span>
-              {isHoliday(cell) ? <span class="holiday" /> : null}
-            </div>
-          )
-        }
-      }
-    }
-  },
-  {
-    field: 'field49',
-    component: 'DatePicker',
-    label: t('formDemo.week'),
-    componentProps: {
-      type: 'week',
-      format: `[${t('formDemo.week')}]`
-    }
-  },
-  {
-    field: 'field50',
-    component: 'DatePicker',
-    label: t('formDemo.year'),
-    componentProps: {
-      type: 'year'
-    }
-  },
-  {
-    field: 'field51',
-    component: 'DatePicker',
-    label: t('formDemo.month'),
-    componentProps: {
-      type: 'month'
-    }
-  },
-  {
-    field: 'field52',
-    component: 'DatePicker',
-    label: t('formDemo.dates'),
-    componentProps: {
-      type: 'dates'
-    }
-  },
-  {
-    field: 'field53',
-    component: 'DatePicker',
-    label: t('formDemo.daterange'),
-    componentProps: {
-      type: 'daterange'
-    }
-  },
-  {
-    field: 'field54',
-    component: 'DatePicker',
-    label: t('formDemo.monthrange'),
-    componentProps: {
-      type: 'monthrange'
-    }
-  },
-  {
-    field: 'field56',
-    component: 'Divider',
-    label: t('formDemo.dateTimePicker')
-  },
-  {
-    field: 'field57',
-    component: 'DatePicker',
-    label: t('formDemo.default'),
-    componentProps: {
-      type: 'datetime'
-    }
-  },
-  {
-    field: 'field58',
-    component: 'DatePicker',
-    label: t('formDemo.shortcuts'),
-    componentProps: {
-      type: 'datetime',
-      shortcuts: [
-        {
-          text: t('formDemo.today'),
-          value: new Date()
-        },
-        {
-          text: t('formDemo.yesterday'),
-          value: () => {
-            const date = new Date()
-            date.setTime(date.getTime() - 3600 * 1000 * 24)
-            return date
-          }
-        },
-        {
-          text: t('formDemo.aWeekAgo'),
-          value: () => {
-            const date = new Date()
-            date.setTime(date.getTime() - 3600 * 1000 * 24 * 7)
-            return date
-          }
-        }
-      ]
-    }
-  },
-  {
-    field: 'field59',
-    component: 'DatePicker',
-    label: t('formDemo.dateTimerange'),
-    componentProps: {
-      type: 'datetimerange'
-    }
-  },
-  {
-    field: 'field60',
-    component: 'Divider',
-    label: t('formDemo.timePicker')
-  },
-  {
-    field: 'field61',
-    component: 'TimePicker',
-    label: t('formDemo.default')
-  },
-  {
-    field: 'field62',
-    component: 'Divider',
-    label: t('formDemo.timeSelect')
-  },
-  {
-    field: 'field63',
-    component: 'TimeSelect',
-    label: t('formDemo.default')
-  },
-  {
-    field: 'field64',
-    component: 'Divider',
-    label: t('formDemo.richText')
-  },
-  {
-    field: 'field65',
-    component: 'Editor',
-    value: 'hello world',
-    label: t('formDemo.default'),
-    componentProps: {
-      editorConfig: {
-        placeholder: '请输入内容...'
-      }
-    },
-    colProps: {
-      span: 24
-    }
-  },
-  {
-    field: 'field66',
-    component: 'Divider',
-    label: t('formDemo.inputPassword')
-  },
-  {
-    field: 'field67',
-    component: 'InputPassword',
-    label: t('formDemo.default'),
-    componentProps: {
-      strength: true
-    }
-  },
-  {
-    field: 'field68',
-    component: 'Divider',
-    label: `${t('formDemo.form')} ${t('formDemo.slot')}`,
-  },
-  {
-    field: 'field69',
-    component: 'Input',
-    label: `label`,
-    formItemProps: {
-      slots: {
-        label: ({ label }) => {
-          return (
-            <div class="custom-label">
-              <span class="label-text">custom {label}</span>
-            </div>
-          )
-        }
-      }
-    }
-  },
+  }
 ])
 
 const { register, formRef, methods } = useForm()

+ 1 - 1
types/env.d.ts

@@ -9,7 +9,7 @@ declare module '*.vue' {
 
 interface ImportMetaEnv {
   readonly VITE_APP_TITLE: string
-  readonly VITE_API_BASEPATH: string
+  readonly VITE_API_BASE_PATH: string
   readonly VITE_BASE_PATH: string
   readonly VITE_DROP_DEBUGGER: string
   readonly VITE_DROP_CONSOLE: string