Files
geg-gas-web/docs/表单二开/1_拆分表单.md
gaoyunqi 1ed4b6f5d4 docs: 更新自动拆分组件和二开文档
fix: 修复响应式换行失效的bug
fix: 修复下拉框staticOptions会生成无用代码的bug
2024-06-13 13:47:01 +08:00

5.6 KiB
Raw Blame History

如何拆分表单

注意框架的部分模版部分用了非空断言如formModel![xxx]编译器报错可以去掉叹号或者在script上加上lang="ts"


如果你使用了最新版的代码可以直接生成拆分后的表单文件进入页面的components目录执行

node ..\..\..\..\..\dev_tools\template_extend.js

目录下生成的template.vue就是可以二开的表单。自动拆分目前对于Tab、TableLayout等组件的显隐并不完善需要自己补充。


默认情况下生成的表单以JSON存储每个字段都是由循环产生因此在二开之前需要将每个字段拆开以便进行二开。

首先打开项目dev_tools/formprops.js将其中的内容替换为

/views/模块类别/模块名/components/config.ts

中的表单配置注意nodejs不加参数必须用module.exports不能用export default写法因此formprops只需要替换赋值的对象即可。config.ts中有三部分组成前两部分为表头搜索定义和列表页定义不要替换错了。

然后使用nodejs执行template_extend.js会在同目录生成template.txt这个文件就是将config文件在第一层展开的模版内容。生成的文件包含一系列字段

<!-- 附加字段3  -->
<Col v-if="getIfShow2('591a8bd0051b4ea2bac87e91f32beca9')" v-show="getIsShow2('591a8bd0051b4ea2bac87e91f32beca9')" :span="getColWidth(schemaMap['591a8bd0051b4ea2bac87e91f32beca9'])">
    <template v-if="showComponent(schemaMap['591a8bd0051b4ea2bac87e91f32beca9'])">
        <SimpleFormItem
          v-model:value="formModel[schemaMap['591a8bd0051b4ea2bac87e91f32beca9'].field]"
          :form-api="formApi"
          :isWorkFlow="isWorkFlow"
          :refreshFieldObj="refreshFieldObj"
          :schema="schemaMap['591a8bd0051b4ea2bac87e91f32beca9']"
        />
    </template>
</Col>

可以看到,每个字段的显隐由三个函数控制,这三个函数为:

  • showComponent某些组件只在工作流或者非工作流内展示
  • getIfShow2对应原来的getIfShow读取的是字段的ifShow参数
  • getIsShow2对应原来的getIsShow读取的是字段的show参数由流程权限控制。字段本身的isShow也会控制显隐这部分在SimpleFormItem中控制。

接下来找到要二开的表单在components目录里定义新建一个vue文件这个文件用来写二开的表单假设模块名叫CascadeDemo这个文件就可以起名CascadeDemoForm.vue然后用下面的内容初始化。

这个文件实际上就是SimpleForm的继承保留了script部分只修改模板我们要用自己的模版覆盖掉原来的循环。由于不是每个字段都有dataIndex如布局类、标题为了保证生成代码的整洁此处定义了映射表可以通过key找到组件同时简化了原来的两个函数。

<template>
<div ref="formWrap">
    <Form ref="formRef" :label-col="getProps?.labelCol" :labelAlign="getProps?.labelAlign" :layout="getProps?.layout" :model="formModel" :wrapper-col="getProps?.wrapperCol" @keypress.enter="handleEnterPress">
        <Row>
            <!-- 把刚才template.txt的内容放到这里 -->
        </Row>

        <div :style="{ textAlign: getProps.buttonLocation }">
            <slot name="buttonBefore"></slot>
            <a-button v-if="getProps.showSubmitButton" type="primary" @click="handleSubmit">
                {{ t('提交') }}
            </a-button>
            <a-button v-if="getProps.showResetButton" style="margin-left: 10px" @click="handleReset">
                {{ t('重置') }}
            </a-button>
            <slot name="buttonAfter"></slot>
        </div>
    </Form>
</div>
</template>

<script>
// 注意这里继承的是SimpleFormSetup使用script setup写法的组件无法继承必须使用特别的版本
import SimpleFormSetup from '/@/components/SimpleForm/src/SimpleFormSetup.vue';
import { Col, Form, Row } from 'ant-design-vue';
import SimpleFormItem from '/@/components/SimpleForm/src/components/SimpleFormItem.vue';

const FormItem = Form.Item;

export default {
    components: { Form, Col, SimpleFormItem, Row, FormItem },
    mixins: [SimpleFormSetup],
    setup(props, ctx) {
        const ret = SimpleFormSetup.setup(props, ctx);
        return {
            ...ret
        };
    },
    computed: {
        // 这里需要增加一个计算属性 否则流程关联时字段读写状态会失效
        schemaMap() {
            const schemaMap = {};
            this.getSchemas.forEach((schema) => {
                schemaMap[schema.key] = schema;
            });
            return schemaMap;
        }
    },
    methods: {
        getIfShow2: function (key) {
            return this.getIfShow(this.schemaMap[key], this.formModel[this.schemaMap[key].field]);
        },

        getIsShow2: function (key) {
            return this.getIsShow(this.schemaMap[key], this.formModel[this.schemaMap[key].field]);
        }
    }
};
</script>

找到模块目录/components下的Form.vue用我们自己的表单需要引用替换掉原来的SimpleForm假设我们的文件为CascadeDemoForm.vue

<template>
    <CascadedemoForm
        ref="systemFormRef"
        :formProps="data.formDataProps"
        :formModel="{}"
        :isWorkFlow="props.fromPage!=FromPageType.MENU"
    />
</template>

展开后的文件和原有表单一致每个字段都已经拆开因此可以自由使用v-if/v-show等进行显隐控制以及在字段之间插入内容、做自动计算等。

该展开方法不能用Grid、Tab等布局嵌套如果需要建议自行写代码套容器不要用编辑器自带的布局组件。