107 lines
5.1 KiB
Markdown
107 lines
5.1 KiB
Markdown
## 如何拆分表单
|
||
|
||
**注意:框架的部分模版部分用了非空断言,如formModel![xxx],编译器报错可以去掉叹号,或者在script上加上lang="ts"**
|
||
|
||
默认情况下,生成的表单以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找到组件,同时简化了原来的两个函数。
|
||
```vue
|
||
<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 = SimpleForm.setup(props, ctx);
|
||
const schemaMap = {};
|
||
ret.getSchemas._value.forEach((schema) => {
|
||
schemaMap[schema.key] = schema;
|
||
});
|
||
return {
|
||
schemaMap,
|
||
...ret
|
||
};
|
||
},
|
||
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):
|
||
```vue
|
||
<template>
|
||
<CascadedemoForm
|
||
ref="systemFormRef"
|
||
:formProps="data.formDataProps"
|
||
:formModel="{}"
|
||
:isWorkFlow="props.fromPage!=FromPageType.MENU"
|
||
/>
|
||
</template>
|
||
```
|
||
展开后的文件和原有表单一致,每个字段都已经拆开,因此可以自由使用v-if/v-show等进行显隐控制,以及在字段之间插入内容、做自动计算等。
|
||
|
||
**注:该展开方法不能用Grid、Tab等布局嵌套,如果需要,建议自行写代码套容器,不要用编辑器自带的布局组件。**
|