Browse Source

feat: imporve naive form component (#5071)

Netfan 3 months ago
parent
commit
958c8b4f21

+ 40 - 2
apps/web-naive/src/adapter/component/index.ts

@@ -19,6 +19,8 @@ import {
   NDivider,
   NInput,
   NInputNumber,
+  NRadio,
+  NRadioButton,
   NRadioGroup,
   NSelect,
   NSpace,
@@ -78,7 +80,22 @@ async function initComponentAdapter() {
       );
     },
     Checkbox: NCheckbox,
-    CheckboxGroup: NCheckboxGroup,
+    CheckboxGroup: (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(NCheckbox, option));
+        }
+      }
+      return h(
+        NCheckboxGroup,
+        { ...props, ...attrs },
+        { default: defaultSlot },
+      );
+    },
     DatePicker: NDatePicker,
     // 自定义默认按钮
     DefaultButton: (props, { attrs, slots }) => {
@@ -98,7 +115,28 @@ async function initComponentAdapter() {
     },
     Input: withDefaultPlaceholder(NInput, 'input'),
     InputNumber: withDefaultPlaceholder(NInputNumber, 'input'),
-    RadioGroup: NRadioGroup,
+    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 ? NRadioButton : NRadio, option),
+            );
+        }
+      }
+      const groupRender = h(
+        NRadioGroup,
+        { ...props, ...attrs },
+        { default: defaultSlot },
+      );
+      return attrs.isButton
+        ? h(NSpace, { vertical: true }, () => groupRender)
+        : groupRender;
+    },
     Select: withDefaultPlaceholder(NSelect, 'select'),
     Space: NSpace,
     Switch: NSwitch,

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

@@ -2,6 +2,7 @@
   "title": "Demos",
   "naive": "Naive UI",
   "table": "Table",
+  "form": "Form",
   "vben": {
     "title": "Project",
     "about": "About",

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

@@ -2,6 +2,7 @@
   "title": "演示",
   "naive": "Naive UI",
   "table": "Table",
+  "form": "表单",
   "vben": {
     "title": "项目",
     "about": "关于",

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

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

+ 106 - 0
apps/web-naive/src/views/demos/form/basic.vue

@@ -0,0 +1,106 @@
+<script lang="ts" setup>
+import { Page } from '@vben/common-ui';
+
+import { NButton, NCard, useMessage } from 'naive-ui';
+
+import { useVbenForm } from '#/adapter/form';
+
+const message = useMessage();
+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) => {
+    message.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,
+        class: 'flex flex-wrap', // 如果选项过多,可以添加class来自动折叠
+        options: [
+          { value: 'A', label: '选项A' },
+          { value: 'B', label: '选项B' },
+          { value: 'C', label: '选项C' },
+          { value: 'D', label: '选项D' },
+          { value: 'E', label: '选项E' },
+          { value: 'F', label: '选项F' },
+        ],
+      },
+    },
+    {
+      component: 'CheckboxGroup',
+      fieldName: 'checkbox',
+      label: 'Checkbox',
+      componentProps: {
+        options: [
+          { value: 'A', label: '选项A' },
+          { value: 'B', label: '选项B' },
+          { value: 'C', label: '选项C' },
+        ],
+      },
+    },
+    {
+      component: 'DatePicker',
+      fieldName: 'date',
+      label: 'Date',
+    },
+  ],
+});
+function setFormValues() {
+  formApi.setValues({
+    string: 'string',
+    number: 123,
+    radio: 'B',
+    radioButton: 'C',
+    checkbox: ['A', 'C'],
+    date: Date.now(),
+  });
+}
+</script>
+<template>
+  <Page
+    description="表单适配器重新包装了CheckboxGroup和RadioGroup,可以通过options属性传递选项数据(选项数据将作为子组件的属性)"
+    title="表单演示"
+  >
+    <NCard title="基础表单">
+      <template #header-extra>
+        <NButton type="primary" @click="setFormValues">设置表单值</NButton>
+      </template>
+      <Form />
+    </NCard>
+  </Page>
+</template>