在处理根据所选数据不同,呈现不同表单的时候,通常我们会创建多个功能来动态调用,但是这个需要将所有情况都考虑,将每一种情况都设计一个功能,这种实现方式比较麻烦,会重复大量工作,且无法满足动态调取多个功能表单一起呈现的需求。例如,在产品组合bom的场景中,需要根据所选的bom类型集合,列出所有对应需要填写的bom规格表单。下面讲解如何实现该种需求。
设计思路:
在白码低代码开发平台上分别将不同类型bom对应的表单功能创建出来,作为子功能,再创建一个主体功能,根据用户选择的bom清单,动态将其对应的子表单调取呈现到主体功能表单中,当主体表单功能提交后,将所有子表单功能提交。
准备工作:
1、bom类型表,并添加几个类型数据。
2、创建产品表,记录产品的主题信息
3、针对不同类型bom创建对应的规格表,表中必须包含“产品-关联-产品表”字段。
4、创建各bom规格表的新建功能,以钢板类型为例:
1) 创建“数据-选择-产品表”步骤
2) 获取选择产品步骤id
3) 将子功能表单加载到主功能表单时,不希望“选择产品”步骤也显示出来,因此添加预处理步骤,将该步隐藏
编写以下代码:
function prepare($programStore, $form, vue) {
let procedure = "60d54fb612849c106b6739b9";//选择产品步骤id
$programStore.dispatch("helper/hide", { procedure });
}
4) 添加“数据-新增-高板规格表”步骤,将“产品”字段设为“选择产品”并隐藏,其余字段根据需求设为填写。
5) 将功能发布,并获取功能id,备用
其他bom规格功能以此类推。
5、创建新增产品功能:
1) 添加“数据-新增-产品表”步骤
2) 添加“集合-选择-bom规格”步骤
3) 获取“选择bom规格”步骤id、“类型”id
4) 添加“交互-预处理”步骤
编写以下代码:
function prepare($programStore, $form, vue) {
//bom规格对应功能id
let flowMap = {
"钢化玻璃": "60d552910d777b106434024c",
"钢板": "60d54fb1bfea51105dfbd4e2",
}
let flowList = []; //需要调用的功能
let programMap = {};//子功能
let programElements = [];//子功能元素
let proProcedure = "60d5530c87c96b1063ffc75f"; //产品信息步骤id
let bomTypesProcedure = "60d55352bfea51105dfbd4ff";//选择bom规格步骤id
let typeField = "60d54c7a0d777b10643401ff";//类型id
//子表单插入到该步骤后
let insertProcedure = "60d55352bfea51105dfbd4ff";//选择bom规格步骤id
//监控选择bom规格
vue.$watch(() => { return programStore.getters["getFormValue"](bomTypesProcedure) },
function (value, oldValue) {
if (!_.isEqual(value, oldValue)) {//数据变动
// 清空旧的子表单
for (let i = 0; i < programElements.length; i++) {
let el = programElements[i];
if (el) {
el.remove();
if (el.__vue__) {
el.__vue__.$destroy();
}
}
}
flowList = [];
programMap = {};
programElements = [];
//选择bom规格步骤数据
let bomTypes = value.data || [];
for (let i = 0; i < bomTypes.length; i++) {
let type = bomTypes[i][typeField] || ""; //类型
if (flowMap[type]) {
flowList.push(flowMap[type]);//添加需要调用的功能id
}
}
//插入子功能表单
run(programElements, programMap, flowList, insertProcedure).then(() => {
let pro = programStore.getters["getFormValue"](proProcedure);//选择产品数据
let children = Object.values(programMap);
for (let i = 0; i < children.length; i++) {
let child = children[i];
//更新子功能的表单-选择产品
child.dispatch("set", {
index: 0,//第一个步骤
value: pro
});
}
});
//本功能提交钩子
$programStore.dispatch("handler/set", {
//提交后
after: async function (store, result) {
let children = Object.values(programMap);
for (let i = 0; i < children.length; i++) {
let child = children[i];
//提交子表单
await child.dispatch("submit");
}
}
})
}
}
);
//生成表单组件的方法
const createProgram = async (flow) => {
//获取功能
let program = await vue.$store.dispatch("program/display", { flow });
// 生成组件
let view = await vue.$store.dispatch("component/build", function (h) {
//参考vue createElement
return h("BmProgram", {
props: {
program
}
})
});
//组件element
let $el = view.$el;
//子功能的view
let childView = view.view;
//子功能的store
let childStore = childView.programStore;
return {
view: childView,
store: childStore,
$el: $el
}
}
//插入表单组件的方法
let run = async (children, childrenMap, list, procedure) => {
for (let i = 0; i < list.length; i++) {
let flow = list[i];
//生成功能
let program = await createProgram(flow);
//element插入到列表
children.push(program.$el);
//设定映射关系
childrenMap[flow] = program.store;
}
//插入到对应位置
let processElement = document.querySelector(`.bm-process.process-procedure-${procedure}`);
//插入到步骤后面
for (let i = 0; i < children.length; i++) {
processElement.append(children[i]);
}
}
}
5) 将功能保存发布。