Browse Source

feat: improve element plus form component (#5072)

Netfan 3 months ago
parent
commit
305549e7f2

+ 59 - 3
apps/web-ele/src/adapter/component/index.ts

@@ -15,12 +15,16 @@ import { $t } from '@vben/locales';
 import {
   ElButton,
   ElCheckbox,
+  ElCheckboxButton,
   ElCheckboxGroup,
   ElDatePicker,
   ElDivider,
   ElInput,
   ElInputNumber,
   ElNotification,
+  ElOption,
+  ElRadio,
+  ElRadioButton,
   ElRadioGroup,
   ElSelect,
   ElSelectV2,
@@ -79,7 +83,25 @@ async function initComponentAdapter() {
       );
     },
     Checkbox: ElCheckbox,
-    CheckboxGroup: ElCheckboxGroup,
+    CheckboxGroup: (props, { attrs, slots }) => {
+      let defaultSlot;
+      if (Reflect.has(slots, 'default')) {
+        defaultSlot = slots.default;
+      } else {
+        const { options, isButton } = attrs;
+        if (Array.isArray(options)) {
+          defaultSlot = () =>
+            options.map((option) =>
+              h(isButton ? ElCheckboxButton : ElCheckbox, option),
+            );
+        }
+      }
+      return h(
+        ElCheckboxGroup,
+        { ...props, ...attrs },
+        { ...slots, default: defaultSlot },
+      );
+    },
     // 自定义默认按钮
     DefaultButton: (props, { attrs, slots }) => {
       return h(ElButton, { ...props, attrs, type: 'info' }, slots);
@@ -104,8 +126,42 @@ async function initComponentAdapter() {
     },
     Input: withDefaultPlaceholder(ElInput, 'input'),
     InputNumber: withDefaultPlaceholder(ElInputNumber, 'input'),
-    RadioGroup: ElRadioGroup,
-    Select: withDefaultPlaceholder(ElSelect, 'select'),
+    RadioGroup: (props, { attrs, slots }) => {
+      let defaultSlot;
+      if (Reflect.has(slots, 'default')) {
+        defaultSlot = slots.default;
+      } else {
+        const { options } = attrs;
+        if (Array.isArray(options)) {
+          defaultSlot = () =>
+            options.map((option) =>
+              h(attrs.isButton ? ElRadioButton : ElRadio, option),
+            );
+        }
+      }
+      return h(
+        ElRadioGroup,
+        { ...props, ...attrs },
+        { ...slots, default: defaultSlot },
+      );
+    },
+    Select: (props, { attrs, slots }) => {
+      let defaultSlot;
+      if (Reflect.has(slots, 'default')) {
+        defaultSlot = slots.default;
+      } else {
+        const { options } = attrs;
+        if (Array.isArray(options)) {
+          defaultSlot = () => options.map((option) => h(ElOption, option));
+        }
+      }
+      const placeholder = props?.placeholder || $t(`ui.placeholder.select`);
+      return h(
+        ElSelect,
+        { ...props, ...attrs, placeholder },
+        { ...slots, default: defaultSlot },
+      );
+    },
     Space: ElSpace,
     Switch: ElSwitch,
     TimePicker: (props, { attrs, slots }) => {

+ 1 - 0
apps/web-ele/src/adapter/form.ts

@@ -12,6 +12,7 @@ setupVbenForm<ComponentType>({
   config: {
     modelPropNameMap: {
       Upload: 'fileList',
+      CheckboxGroup: 'model-value',
     },
   },
   defineRules: {

+ 1 - 0
apps/web-ele/src/locales/langs/en-US/demos.json

@@ -1,6 +1,7 @@
 {
   "title": "Demos",
   "elementPlus": "Element Plus",
+  "form": "Form",
   "vben": {
     "title": "Project",
     "about": "About",

+ 1 - 0
apps/web-ele/src/locales/langs/zh-CN/demos.json

@@ -1,6 +1,7 @@
 {
   "title": "演示",
   "elementPlus": "Element Plus",
+  "form": "表单演示",
   "vben": {
     "title": "项目",
     "about": "关于",

+ 8 - 0
apps/web-ele/src/router/routes/modules/demos.ts

@@ -23,6 +23,14 @@ const routes: RouteRecordRaw[] = [
         path: '/demos/element',
         component: () => import('#/views/demos/element/index.vue'),
       },
+      {
+        meta: {
+          title: $t('demos.form'),
+        },
+        name: 'BasicForm',
+        path: '/demos/form',
+        component: () => import('#/views/demos/form/basic.vue'),
+      },
     ],
   },
 ];

+ 143 - 0
apps/web-ele/src/views/demos/form/basic.vue

@@ -0,0 +1,143 @@
+<script lang="ts" setup>
+import { h } from 'vue';
+
+import { Page } from '@vben/common-ui';
+
+import { ElButton, ElCard, ElCheckbox, ElMessage } from 'element-plus';
+
+import { useVbenForm } from '#/adapter/form';
+
+const [Form, formApi] = useVbenForm({
+  commonConfig: {
+    // 所有表单项
+    componentProps: {
+      class: 'w-full',
+    },
+  },
+  layout: 'horizontal',
+  // 大屏一行显示3个,中屏一行显示2个,小屏一行显示1个
+  wrapperClass: 'grid-cols-1 md:grid-cols-2 lg:grid-cols-3',
+  handleSubmit: (values) => {
+    ElMessage.success(`表单数据:${JSON.stringify(values)}`);
+  },
+  schema: [
+    {
+      component: 'Input',
+      fieldName: 'string',
+      label: 'String',
+    },
+    {
+      component: 'InputNumber',
+      fieldName: 'number',
+      label: 'Number',
+    },
+    {
+      component: 'RadioGroup',
+      fieldName: 'radio',
+      label: 'Radio',
+      componentProps: {
+        options: [
+          { value: 'A', label: 'A' },
+          { value: 'B', label: 'B' },
+          { value: 'C', label: 'C' },
+          { value: 'D', label: 'D' },
+          { value: 'E', label: 'E' },
+        ],
+      },
+    },
+    {
+      component: 'RadioGroup',
+      fieldName: 'radioButton',
+      label: 'RadioButton',
+      componentProps: {
+        isButton: true,
+        options: ['A', 'B', 'C', 'D', 'E', 'F'].map((v) => ({
+          value: v,
+          label: `选项${v}`,
+        })),
+      },
+    },
+    {
+      component: 'CheckboxGroup',
+      fieldName: 'checkbox',
+      label: 'Checkbox',
+      componentProps: {
+        options: ['A', 'B', 'C'].map((v) => ({ value: v, label: `选项${v}` })),
+      },
+    },
+    {
+      component: 'CheckboxGroup',
+      fieldName: 'checkbox1',
+      label: 'Checkbox1',
+      renderComponentContent: () => {
+        return {
+          default: () => {
+            return ['A', 'B', 'C', 'D'].map((v) =>
+              h(ElCheckbox, { label: v, value: v }),
+            );
+          },
+        };
+      },
+    },
+    {
+      component: 'CheckboxGroup',
+      fieldName: 'checkbotton',
+      label: 'CheckBotton',
+      componentProps: {
+        isButton: true,
+        options: [
+          { value: 'A', label: '选项A' },
+          { value: 'B', label: '选项B' },
+          { value: 'C', label: '选项C' },
+        ],
+      },
+    },
+    {
+      component: 'DatePicker',
+      fieldName: 'date',
+      label: 'Date',
+    },
+    {
+      component: 'Select',
+      fieldName: 'select',
+      label: 'Select',
+      componentProps: {
+        options: [
+          { value: 'A', label: '选项A' },
+          { value: 'B', label: '选项B' },
+          { value: 'C', label: '选项C' },
+        ],
+      },
+    },
+  ],
+});
+function setFormValues() {
+  formApi.setValues({
+    string: 'string',
+    number: 123,
+    radio: 'B',
+    radioButton: 'C',
+    checkbox: ['A', 'C'],
+    checkbotton: ['B', 'C'],
+    checkbox1: ['A', 'B'],
+    date: new Date(),
+    select: 'B',
+  });
+}
+</script>
+<template>
+  <Page
+    description="我们重新包装了CheckboxGroup、RadioGroup、Select,可以通过options属性传入选项属性数组以自动生成选项"
+    title="表单演示"
+  >
+    <ElCard>
+      <template #header>
+        <div class="flex items-center">
+          <span class="flex-auto">基础表单演示</span>
+          <ElButton type="primary" @click="setFormValues">设置表单值</ElButton>
+        </div>
+      </template>
+      <Form />
+    </ElCard>
+  </Page>
+</template>