Pārlūkot izejas kodu

add TabsForm demo (#1914)

* chore: table size放到settings

* chore(TableAction): 操作确认框增加placement属性支持

* chore(Form): 表单field支持a.b.c嵌套写法

* feat(Form): add TabsForm demo

Co-authored-by: jinmao88 <50581550+jinmao88@users.noreply.github.com>
Joyboo 2 gadi atpakaļ
vecāks
revīzija
42908a4535

+ 1 - 0
src/locales/lang/en/routes/demo.ts

@@ -111,6 +111,7 @@ export default {
     dynamicForm: 'Dynamic',
     customerForm: 'Custom',
     appendForm: 'Append',
+    tabsForm: 'TabsForm',
   },
   iframe: {
     frame: 'External',

+ 1 - 0
src/locales/lang/zh-CN/routes/demo.ts

@@ -107,6 +107,7 @@ export default {
     dynamicForm: '动态表单',
     customerForm: '自定义组件',
     appendForm: '表单增删示例',
+    tabsForm: '标签页+多级field',
   },
   iframe: {
     frame: '外部页面',

+ 8 - 0
src/router/routes/modules/demo/comp.ts

@@ -98,6 +98,14 @@ const comp: AppRouteModule = {
             title: t('routes.demo.form.appendForm'),
           },
         },
+        {
+          path: 'tabsForm',
+          name: 'tabsFormDemo',
+          component: () => import('/@/views/demo/form/TabsForm.vue'),
+          meta: {
+            title: t('routes.demo.form.tabsForm'),
+          },
+        },
       ],
     },
     {

+ 136 - 0
src/views/demo/form/TabsForm.vue

@@ -0,0 +1,136 @@
+<template>
+  <PageWrapper title="标签页+多级field表单" v-loading="loading">
+    <div class="mb-4">
+      <a-button @click="handleReset" class="mr-2"> 重置表单 </a-button>
+      <a-button @click="handleSetValues" class="mr-2"> 设置默认值 </a-button>
+      <a-button @click="handleSubmit" class="mr-2" type="primary"> 提交表单 </a-button>
+    </div>
+    <CollapseContainer title="标签页+多级field表单">
+      <Tabs v-model:activeKey="activeKey">
+        <TabPane
+          v-for="item in tabsFormSchema"
+          :key="item.key"
+          v-bind="omit(item, ['Form', 'key'])"
+        >
+          <BasicForm @register="item.Form[0]" />
+        </TabPane>
+      </Tabs>
+    </CollapseContainer>
+  </PageWrapper>
+</template>
+
+<script lang="ts">
+  import { ref, defineComponent } from 'vue';
+  import { Tabs } from 'ant-design-vue';
+  import { PageWrapper } from '/@/components/Page';
+  import { CollapseContainer } from '/@/components/Container';
+  import { useMessage } from '/@/hooks/web/useMessage';
+  import { omit } from 'lodash-es';
+  import { deepMerge } from '/@/utils';
+  import { BasicForm, FormSchema, useForm, FormProps, UseFormReturnType } from '/@/components/Form';
+
+  export default defineComponent({
+    name: 'TabsFormDemo',
+    components: { Tabs, TabPane: Tabs.TabPane, PageWrapper, CollapseContainer, BasicForm },
+    setup() {
+      type TabsFormType = {
+        key: string;
+        tab: string;
+        forceRender?: boolean;
+        Form: UseFormReturnType;
+      };
+
+      const { createMessage } = useMessage();
+      const activeKey = ref('tabs2');
+      const loading = ref(false);
+      const tabsFormSchema: TabsFormType[] = [];
+
+      // 公共属性
+      const baseFormConfig: Partial<FormProps> = {
+        showActionButtonGroup: false,
+        labelWidth: 100,
+      };
+
+      // 为每个字段模拟默认值, { tabs1: { field1: '', field2: '' }, tabs2: { field1: '' }, ... }
+      const mockDefaultValue: Recordable = {};
+
+      // 模拟5个标签页
+      for (let i = 1; i <= 5; ++i) {
+        const tabsKey = `tabs${i}`;
+
+        // 每个标签页8个字段
+        const schemas: FormSchema[] = [];
+        const row: Recordable = {};
+
+        for (let j = 1; j <= 8; ++j) {
+          schemas.push({
+            field: `${tabsKey}.field${j}`,
+            label: `${tabsKey}-field${j}`,
+            component: 'Input',
+            colProps: { span: 24 },
+          });
+          row[`field${j}`] = `field: ${tabsKey}.field${j}, default value`;
+        }
+
+        mockDefaultValue[tabsKey] = row;
+
+        tabsFormSchema.push({
+          key: tabsKey,
+          tab: tabsKey,
+          forceRender: true,
+          Form: useForm(Object.assign({ schemas }, baseFormConfig) as FormProps),
+        });
+      }
+
+      async function handleReset() {
+        for (const item of tabsFormSchema) {
+          const { resetFields } = item.Form[1];
+          await resetFields();
+        }
+      }
+
+      async function handleSubmit() {
+        let lastKey = '';
+        loading.value = true;
+        try {
+          const values: Recordable = {};
+          for (const item of tabsFormSchema) {
+            lastKey = item.key;
+            const { validate, getFieldsValue } = item.Form[1];
+            await validate();
+            // 表单已支持多级key
+            deepMerge(values, getFieldsValue());
+          }
+
+          console.log('submit values: ', values);
+          createMessage.success('提交成功!请打开控制台查看');
+        } catch (e) {
+          // 验证失败或出错,切换到对应标签页
+          activeKey.value = lastKey;
+          console.log(e);
+        } finally {
+          loading.value = false;
+        }
+      }
+
+      async function handleSetValues() {
+        console.log('默认值为: ', mockDefaultValue);
+        for (const item of tabsFormSchema) {
+          const { setFieldsValue } = item.Form[1];
+          await setFieldsValue(mockDefaultValue);
+        }
+      }
+      return {
+        omit,
+        loading,
+        activeKey,
+        tabsFormSchema,
+        handleReset,
+        handleSubmit,
+        handleSetValues,
+      };
+    },
+  });
+</script>
+
+<style scoped></style>