Browse Source

wip: Form改造中

kailong321200875 1 year ago
parent
commit
6f1a94809e

+ 39 - 22
src/components/Form/src/Form.vue

@@ -183,27 +183,7 @@ export default defineComponent({
     const renderFormItem = (item: FormSchema) => {
       // 单独给只有options属性的组件做判断
       // const notRenderOptions = ['SelectV2', 'Cascader', 'Transfer']
-      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 }: any) => {
-          return componentSlots.default(item)
-        }
-      }
       // if (
       //   item?.component !== 'SelectV2' &&
       //   item?.component !== 'Cascader' &&
@@ -268,19 +248,56 @@ export default defineComponent({
                             label={v[valueAlias]}
                             disabled={v[disabledAlias]}
                           >
-                            {v[labelAlias]}
+                            {() =>
+                              componentProps?.slots?.default
+                                ? componentProps?.slots?.default({ option: v })
+                                : v[labelAlias]
+                            }
                           </Com>
                         )
                       })
                   }
                 }
 
+                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)
+                  }
+                }
+
+                // 单选框组
+                if (item.component === ComponentNameEnum.RADIO_GROUP) {
+                  slotsMap.default = !componentSlots.default
+                    ? () => renderRadioOptions(item)
+                    : () => {
+                        return componentSlots.default(
+                          unref((item?.componentProps as RadioComponentProps)?.options)
+                        )
+                      }
+                }
+
                 return (
                   <Com
                     vModel={formModel.value[item.field]}
                     {...(autoSetPlaceholder && setTextPlaceholder(item))}
                     {...setComponentProps(item)}
-                    style={item.componentProps?.style}
+                    style={item.componentProps?.style || {}}
                   >
                     {{ ...slotsMap }}
                   </Com>

+ 1 - 1
src/components/Form/src/componentMap.ts

@@ -25,7 +25,7 @@ import { ComponentName } from '@/types/components'
 
 const componentMap: Recordable<Component, ComponentName> = {
   Radio: ElRadio,
-  // RadioGroup: ElRadioGroup,
+  RadioGroup: ElRadioGroup,
   Checkbox: ElCheckboxGroup,
   CheckboxButton: ElCheckboxGroup,
   Input: ElInput,

+ 15 - 12
src/components/Form/src/components/useRenderRadio.tsx

@@ -1,23 +1,26 @@
 import { FormSchema } from '@/types/form'
 import { ElRadio, ElRadioButton } from 'element-plus'
 import { defineComponent } from 'vue'
-import { ComponentNameEnum } from '@/types/components.d'
+import { ComponentNameEnum, RadioGroupComponentProps } from '@/types/components.d'
 
 export const useRenderRadio = () => {
-  const renderRadioOptions = (
-    item: FormSchema,
-    type?: ComponentNameEnum.RADIO | ComponentNameEnum.RADIO_BUTTON = ComponentNameEnum.RADIO
-  ) => {
+  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) => {
+    const componentProps = item.componentProps as RadioGroupComponentProps
+    const valueAlias = componentProps?.props?.value || 'value'
+    const labelAlias = componentProps?.props?.label || 'label'
+    const disabledAlias = componentProps?.props?.disabled || 'disabled'
+    const Com = (
+      item.component === ComponentNameEnum.RADIO_GROUP ? ElRadio : ElRadioButton
+    ) as ReturnType<typeof defineComponent>
+    return componentProps?.options?.map((option) => {
       const { value, ...other } = option
       return (
-        <Com {...other} label={option[valueAlias || 'value']}>
+        <Com
+          {...other}
+          disabled={option[disabledAlias || 'disabled']}
+          label={option[valueAlias || 'value']}
+        >
           {option[labelAlias || 'label']}
         </Com>
       )

+ 1 - 0
src/locales/en.ts

@@ -241,6 +241,7 @@ export default {
     transfer: 'Transfer',
     render: 'Render',
     radio: 'Radio',
+    radioGroup: 'Radio Group',
     button: 'Button',
     checkbox: 'Checkbox',
     slider: 'Slider',

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

@@ -241,6 +241,7 @@ export default {
     transfer: '穿梭框',
     render: '渲染器',
     radio: '单选框',
+    radioGroup: '单选框组',
     button: '按钮',
     checkbox: '多选框',
     slider: '滑块',

+ 30 - 0
src/types/components.d.ts

@@ -11,6 +11,7 @@ import { ElementPlusSize, ElementPlusInfoType } from './elementPlus.d'
 
 export enum ComponentNameEnum {
   RADIO = 'Radio',
+  RADIO_GROUP = 'RadioGroup',
   RADIO_BUTTON = 'RadioButton',
   CHECKBOX = 'Checkbox',
   CHECKBOX_BUTTON = 'CheckboxButton',
@@ -453,6 +454,35 @@ export interface RadioComponentProps {
   slots?: {
     default?: (...args: any[]) => JSX.Element | null
   }
+  style?: CSSProperties
+}
+
+export interface RadioGroupComponentProps {
+  value?: string | number | boolean
+  size?: ElementPlusSize
+  disabled?: boolean
+  textColor?: string
+  fill?: string
+  validateEvent?: boolean
+  label?: string
+  name?: string
+  id?: string
+  options?: RadioOption[]
+  /**
+   * 数据源的字段别名
+   */
+  props: {
+    label?: string
+    value?: string
+    disabled?: string
+  }
+  on?: {
+    change?: (value: string | number | boolean) => void
+  }
+  slots?: {
+    default?: (...args: any[]) => JSX.Element | null
+  }
+  style?: CSSProperties
 }
 
 export interface ColProps {

+ 3 - 26
src/types/form.d.ts

@@ -13,7 +13,8 @@ import {
   RateComponentProps,
   ColorPickerComponentProps,
   TransferComponentProps,
-  RadioComponentProps
+  RadioComponentProps,
+  RadioGroupComponentProps
 } from '@/types/components'
 import { FormValueType, FormValueType } from '@/types/form'
 import type { AxiosPromise } from 'axios'
@@ -36,31 +37,6 @@ export type FormItemProps = {
   style?: CSSProperties
 }
 
-// 定义联合类型和条件类型
-type ComponentPropsForComponent<T extends ComponentName> = T extends 'Input'
-  ? InputComponentProps
-  : T extends 'Autocomplete'
-  ? AutocompleteComponentProps
-  : T extends 'InputNumber'
-  ? InputNumberComponentProps
-  : T extends 'Select'
-  ? SelectComponentProps
-  : T extends 'SelectV2'
-  ? SelectV2ComponentProps
-  : T extends 'Cascader'
-  ? CascaderComponentProps
-  : T extends 'Switch'
-  ? SwitchComponentProps
-  : T extends 'Rate'
-  ? RateComponentProps
-  : T extends 'ColorPicker'
-  ? ColorPickerComponentProps
-  : T extends 'Transfer'
-  ? TransferComponentProps
-  : T extends 'Radio'
-  ? RadioComponentProps
-  : any
-
 export interface FormSchema {
   /**
    * 唯一标识
@@ -97,6 +73,7 @@ export interface FormSchema {
     | ColorPickerComponentProps
     | TransferComponentProps
     | RadioComponentProps
+    | RadioGroupComponentProps
 
   /**
    * formItem组件属性,具体可以查看element-plus文档

+ 82 - 2
src/views/Components/Form/DefaultForm.vue

@@ -6,9 +6,14 @@ import { useIcon } from '@/hooks/web/useIcon'
 import { ContentWrap } from '@/components/ContentWrap'
 import { useAppStore } from '@/store/modules/app'
 import { FormSchema } from '@/types/form'
-import { ComponentOptions, SelectOption, SelectComponentProps } from '@/types/components'
+import {
+  ComponentOptions,
+  SelectOption,
+  SelectComponentProps,
+  RadioOption
+} from '@/types/components'
 import { useForm } from '@/hooks/web/useForm'
-import { ElOption, ElOptionGroup, ElButton } from 'element-plus'
+import { ElOption, ElOptionGroup, ElButton, ElRadio } from 'element-plus'
 
 const appStore = useAppStore()
 
@@ -949,6 +954,81 @@ const schema = reactive<FormSchema[]>([
         }
       ]
     }
+  },
+  {
+    field: 'field39-1',
+    label: t('formDemo.slot'),
+    component: 'Radio',
+    componentProps: {
+      options: [
+        {
+          // disabled: true,
+          label: 'option-1',
+          value: '1'
+        },
+        {
+          label: 'option-2',
+          value: '2'
+        }
+      ],
+      slots: {
+        default: ({ option }) => {
+          return (
+            <>
+              <span>{option.label}</span>
+              <span> ({option.value}) </span>
+            </>
+          )
+        }
+      }
+    }
+  },
+  {
+    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',