docs: 更新自动拆分组件和二开文档

fix: 修复响应式换行失效的bug
fix: 修复下拉框staticOptions会生成无用代码的bug
This commit is contained in:
gaoyunqi
2024-06-13 13:47:01 +08:00
parent c0b51c4e20
commit 1ed4b6f5d4
5 changed files with 198 additions and 8 deletions

View File

@ -1,10 +1,60 @@
const formProps = require('./formProps');
const fs = require('fs');
const path = require('path');
const filePath = path.join(process.cwd(), 'config.ts');
if (fs.existsSync(filePath)) {
console.log('Reading ' + filePath);
const file = fs.readFileSync(filePath, 'utf-8');
const fileArr = file.split('\n');
const confArr = [];
let parseStart = false;
fileArr.forEach((row) => {
if (!parseStart && row.indexOf('export const formProps: FormProps =') >= 0) {
parseStart = true;
confArr.push('{');
return;
}
if (parseStart) {
if (row.indexOf('};') === 0) {
confArr.push('}');
parseStart = false;
return;
}
confArr.push(row);
}
});
console.log('total rows: ' + confArr.length);
formProps = eval('(' + confArr.join('\n') + ')');
} else {
process.exit(0);
}
let tmpl = '';
let tabCount = 0;
const refList = [];
// 用于将config的表单格式展开成字段以便二开
formProps.schemas.forEach((prop) => {
appendTmpl(prop);
});
function appendTmpl(prop) {
let schema = `schemaMap['${prop.key}']`;
// 栅格布局
if (prop.component == 'Grid') {
prop.children.forEach((child) => {
child.list.forEach((listChild) => {
appendTmpl(listChild);
});
});
return;
} else if (prop.component == 'Tab') {
appendTabTmpl(prop);
} else if (prop.component == 'TableLayout') {
appendTableLayoutTmpl(prop);
} else if (prop.component == 'Card') {
appendCardTmpl(prop);
}
tmpl += `
<!-- ${prop.label || prop.field || prop.component} -->
<Col v-if="getIfShow2('${prop.key}')" v-show="getIsShow2('${prop.key}')" :span="getColWidth(${schema})">
@ -13,12 +63,144 @@ formProps.schemas.forEach((prop) => {
</template>
</Col>
`;
});
}
//write to file
const fs = require('fs');
function appendTabTmpl(prop) {
let schema = `schemaMap['${prop.key}']`;
tabCount += 1;
refList.push(`const activeKey${tabCount} = ref(0);`);
tmpl += `<Tabs v-model:activeKey="activeKey${tabCount}" v-bind="getTabProps('${prop.key}')">\n`;
prop.children.forEach((tabChild) => {
tmpl += `<TabPane :forceRender="true" tab="${tabChild.name}">\n`;
tabChild.list.forEach((listChild) => {
appendTmpl(listChild);
});
tmpl += `</TabPane>\n`;
});
tmpl += `</Tabs>\n`;
}
fs.writeFile('./template.txt', tmpl, (err) => {
function appendTableLayoutTmpl(prop) {
let schema = `schemaMap['${prop.key}']`;
tmpl += `<TableLayoutPreview :element="${schema}">`;
tmpl += ` <template #tdElement="{ tdElement }">`;
tmpl += ` <div class="h-full">`;
tmpl += `<div style="getTdStyle(tdElement)">`;
prop.children.forEach((child) => {
let childSchema = `schemaMap['${child.key}']`;
tmpl += `<SimpleFormItem v-if="getIfShow2(${childSchema})" v-show="getIsShow2(${childSchema})" v-model:value="formModel[${childSchema}.field]" :form-api="formApi" :isWorkFlow="isWorkFlow" :refreshFieldObj="refreshFieldObj" :schema="${childSchema}" />`;
});
tmpl += `</div>`;
tmpl += ` </div>`;
tmpl += ` </template>`;
tmpl += `</TableLayoutPreview>`;
}
function appendCardTmpl(prop) {
let schema = `schemaMap['${prop.key}']`;
tmpl += `<CollapseContainer :bordered="false" :hasLeftBorder="true" title="${prop.componentProps.title}">`;
prop.children[0].list.forEach((lChild) => {
const childSchema = `schemaMap['${lChild.key}']`;
tmpl += ` <SimpleFormItem v-model:value="formModel[${childSchema}.field]" :form-api="formApi" :isWorkFlow="isWorkFlow" :refreshFieldObj="refreshFieldObj" :schema="${childSchema}" />`;
});
tmpl += `</CollapseContainer>`;
}
const fullVue = `
<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">
${tmpl}
<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';
import { ref } from 'vue';
import { CheckCircleOutlined } from '@ant-design/icons-vue';
const FormItem = Form.Item;
export default {
components: { CheckCircleOutlined, Form, Col, SimpleFormItem, Row, FormItem },
mixins: [SimpleFormSetup],
setup(props, ctx) {
const ret = SimpleFormSetup.setup(props, ctx);
const expose = ctx.expose;
${refList.join('\n')}
expose({
...ret.formApi,
});
return {
...ret
};
},
computed: {
// 这里需要增加一个计算属性 否则流程关联时字段读写状态会失效
schemaMap() {
const schemaMap = {};
this.getSchemas.forEach((schema) => {
schemaMap[schema.key] = schema;
if(schema.children) {
schema.children.forEach(sChild=>{
if(sChild.list){
sChild.list.forEach(lChild=>{
schemaMap[lChild.key] = lChild;
});
}
});
}
});
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]);
},
getTabProps(key) {
const schema = this.schemaMap[key];
return {
size: schema.componentProps.tabSize,
tabPosition: schema.componentProps.tabPosition,
type: schema.componentProps.type
}
},
getTdStyle(tdElement) {
return {
height: tdElement.height ? tdElement.height + 'px' : '',
minHeight: (tdElement.height || '42') + 'px',
overflow: 'hidden',
padding: '10px'
}
}
}
};
</script>
`;
fs.writeFile('./template.vue', fullVue, (err) => {
if (err) throw err;
console.log('The file has been saved!');
});

View File

@ -2,6 +2,15 @@
**注意框架的部分模版部分用了非空断言如formModel![xxx]编译器报错可以去掉叹号或者在script上加上lang="ts"**
---
如果你使用了最新版的代码可以直接生成拆分后的表单文件进入页面的components目录执行
```bash
node ..\..\..\..\..\dev_tools\template_extend.js
```
目录下生成的template.vue就是可以二开的表单。自动拆分目前对于Tab、TableLayout等组件的显隐并不完善需要自己补充。
---
默认情况下生成的表单以JSON存储每个字段都是由循环产生因此在二开之前需要将每个字段拆开以便进行二开。
首先打开项目dev_tools/formprops.js将其中的内容替换为

View File

@ -194,7 +194,7 @@
</a-modal>
<a-modal v-model:visible="showCompReadme" title="注意事项" @ok="closeCompReadme">
<div class="comp-readme-content">
因为组件封装的限制当使用表格布局选项卡卡片布局栅格布局时会带来一些问题包括二开嵌套问题移动端生成代码无法适配等<br/>
因为组件封装的限制当使用表格布局选项卡卡片布局栅格布局时会带来一些问题包括二开拆分不完全移动端生成代码无法适配等<br/>
无特殊需求时应该优先使用设计器提供的响应式布局或者进行源码二开<br/>
源码二开可以复用设计器生成的代码调整布局显隐权限更加方便
</div>

View File

@ -200,7 +200,6 @@
}
if (props.datasourceType === 'api') {
options.value = await apiConfigFunc(props.apiConfig, isCamelCase, formModel, props.index);
props.staticOptions.splice(0, props.staticOptions.length, options.value);
}
} else {
api = props.api;

View File

@ -3,8 +3,8 @@
<Form ref="formRef" :label-col="getProps?.labelCol" :labelAlign="getProps?.labelAlign" :layout="getProps?.layout" :model="formModel" :wrapper-col="getProps?.wrapperCol" @keypress.enter="handleEnterPress">
<Row v-bind="getRow">
<template v-for="schema in getSchemas" :key="schema.field">
<div v-if="schema?.componentProps.respBreakLine" style="width: 100%; height: 1px"></div>
<Col v-if="getIfShow(schema, formModel[schema.field])" v-show="getIsShow(schema, formModel[schema.field])" :span="getColWidth(schema)">
<div v-if="schema?.componentProps.respBreakLine" style="width: 100%; height: 1px"></div>
<template v-if="showComponent(schema) && schema.type !== 'slot'">
<SimpleFormItem v-model:value="formModel[schema.field]" :form-api="formApi" :isWorkFlow="isWorkFlow" :refreshFieldObj="refreshFieldObj" :schema="schema" />
</template>