手册
1. 表单扩展
1.1 表单设计时如何添加JS校验
1.2 【引入脚本】实现修改人与修改日期在编辑时更新
1.3 【引入脚本】字段值为空时不显示
1.4 表单列表数据导入jar包校验说明
1.5 通过表单js控制子表的显示或隐藏
1.6 主表汇总获取子表的描述信息
1.7 【初始赋值】如何对某个字段赋初始默认值
1.8 数字字段对比不允许大于另一个字段
1.9 【引入脚本】多选框的隐藏显示控制
1.10 PC表单隐藏控件内容
1.11 【引入脚本】通过表单参数判断来实现接口参数回填
1.12 【按钮前置事件】通过按钮事件来校验表单账号是否有邮箱
1.13 【引入脚本】通过调用本地关联查询的接口将第一行数据回填至表单
1.14 【编写公式】日期格式化
1.15 【子表回填】子表对话框数据根据主表选择的内容自动回填
1.16 【引入脚本】js调用接口执行一个脚本,获取数据后反填到表单上或者将结果与表单内容对比,可以做表单校验
1.17 【引入脚本】js将子表末行的数据更新
1.18 【引入脚本】控制子表回填按钮的隐藏
1.19 【引入脚本】通过表单参数判断来实现子表的只读和编辑效果
1.20 【引入脚本】隐藏子表的添加按钮
1.21 【引入脚本】隐藏子表每行复制、删除等按钮
1.22 【关联查询】自定义SQL过滤数据
1.23 【引入脚本】实现流程第二节点回传数据致表单
1.24 【引入脚本】js控制子表中单独一行的某个字段的显示隐藏
1.25 【引入脚本】js请求接口,获取数据后将数据push到子表上
1.26 通过字段控制其他字段的显隐读写
2. 门户扩展
3. 流程定义扩展
3.1 分支网关的变量如何获取子表数据
3.2 通过初始赋值获取多人会签节点的审批人并存储到某一字段
3.3 通过按钮控制工单状态
3.4 流程分支网关处用发起人所属角色判断走向
4. 人员脚本扩展
5. 常用脚本扩展
5.1 流程状态通知方案
5.2 节点按钮前置脚本
5.3 更新字段值
6. 表单列表扩展
6.1 如何格式化内容导出
6.2 如何格式化复选选项
6.3 【JS按钮】表单列表审批人通过js按钮跳转至对应的待办
6.4 【JS按钮】通过JS按钮点击发起流程,并将当前行某字段数据自动推送到发起流程的表单中
6.5 【数据过滤】表单列表中数据根据当前人过滤当前人审批过的数据
6.6 【js扩展】根据日期比较结果控制字段颜色
6.7 【前置js脚本】控制按钮显隐
7. 功能高级说明
7.1 流程按钮_加签/征询/流转
7.2 对话框/关联查询自定义SQL的使用
8. 典型场景应用
8.1 填报汇总功能
8.2 考勤审批管理
8.3 表单校验
8.4 绑定查询关联操作说明
8.5 快速批量添加数据,引入脚本
8.6 通过sql和数据列表的方式快速生成考勤统计报表
8.7 栏目中配置跳转地址

【子表回填】子表对话框数据根据主表选择的内容自动回填

1538
蔡廷安
2021-08-09 19:02:55
分享链接

方法一

  • 子表自动回填


场景:合同主表选择“合同模板”的主表数据,并且返回“合同模板”一对多子表的多行数据。

实现这个需求需要配置两个对话框

一.查询”合同模板“主表数据的对话框

注意返回字段这个地方要返回一个主表数据的主键

在数据库内主从表数据的关系如下

可以看到,主表的其中的一条数据的id等于子表的ref_id_,我们可以根据返回主表一条数据的id来筛选子表中ref_id_对应的数据

二.查询”合同模板“子表数据的对话框

要注意的是子表数据对话框中要加入一个条件字段,选择外键(ref_id_),选择条件为等于,值来源为参数传入

三.新建一个表单,主表中起码要有一个对话框,主表对话框绑定刚才配置好的,查询“合同模板”主表数据对话框,设定返回值中返回一个数据对应的主键id

拉入子表,选中子表点击子表回填,绑定刚刚配置好的”合同模板“子表对话框

刚刚在设置子表对话框的时候加入了一个条件字段,这里我们绑定主表对话框返回主键id的字段

这样配置我们就可以做到根据主表返回的主键id来筛选对应的子表数据


  • js代码实现


四.我们在表单引入脚本中加入js当主表对话框选择了数据之后,子表对话框根据自己绑定的参数(如图,现在绑定的是主表主键id)并自动回填数据,js代码如下:


/**
     * 获取子表回填的数据
     */
    async function getFillBackSubTabData(){
        //获取表单信息
        let form = await getForm();
        let expand = JSON.parse(form.expand);
        if(!expand || !expand.list){
            return ;
        }
        let fillBackSubTabs = new Array();
        for(let i = 0;i < expand.list.length; i++ ){
            let ctrl = expand.list[i];
            if(ctrl && ctrl.ctrlType && ctrl.ctrlType == "subtable"
            && ctrl.customDialogjson && ctrl.customDialogjson.custDialog
            && ctrl.customDialogjson.custDialog.alias){
                fillBackSubTabs.push(ctrl);
            }
        }
        let subTabMap = {};
        for(let i = 0 ; i < fillBackSubTabs.length ; i++){
            subTabMap[fillBackSubTabs[i].name] = await getDatas(fillBackSubTabs[i]);
        }
        return subTabMap;
        
    }
 
    async function getForm(){
        //预览页面
        if(window.app.$route.name == 'previewForm'){
            let formId = window.app.$route.params.formId;
            return new Promise((resolve,reject)=>{
                window.app.$http.get("${form}/form/form/v1/getFormById?id="+formId).then(resp=>{
                    resolve(resp.data);
                })
            })
        }else{
            //启动、审批页面,有formContent
            let formContent = getByComponentsName("formContent");
            if(!formContent || !formContent.formKey){
                window.app.$message.warning("获取表单信息失败");
                return null;
            }
            let formKey = formContent.formKey;
            return new Promise((resolve,reject)=>{
                window.app.$http.get("${form}/form/formServiceController/v1/getByFormKey?formKey="+formKey).then(resp=>{
                    resolve(resp.data);
                })
            })
        }
    }
 
    async function getDatas(ctrl){
        let data = getOnlineFormData();
        let condition = ctrl.customDialogjson.custDialog.conditions;
        let param = {
            pageBean:{
                page:1,
                pageSize:-1,
                showTotal:false
            },
            querys:[]
        }
        for(let i = 0; i < condition.length ;i++){
            let bind = condition[i].bind;
            let bindData = data[bind.split(".")[2]];
            if(!bindData){
                continue;
            }
            let operation = "";
            if(condition[i].condition == "EQ"){
                operation = "EQUAL"
            }else if(condition[i].condition == "LK"){
                operation = "LIKE"
            }else{
                operation = condition[i].condition;
            }
            param.querys.push({
                group:"subTabDialog",
                operation:operation,
                property:condition[i].field,
                relation:"OR",
                value:bindData
            })
        }
        if(param.querys.length == 0){
            return new Promise((resolve,reject)=>{
                resolve([]);
            })
        }
        let resp = await window.app.$http.get(`${window.context.form}/form/customDialog/v1/getByAlias?alias=${ctrl.customDialogjson.custDialog.alias}`);
        if(!resp || !resp.data || !resp.data.resultfield){
            return new Promise((resolve,reject)=>{
                resolve([]);
            })
        }
        let dialogDef = resp.data;
        let mappingConf = ctrl.customDialogjson.custDialog.mappingConf;
        let resultField = JSON.parse(dialogDef.resultfield);
        let map = {}; //对话框返回值的字段名和target的映射
        for(let i = 0;i<mappingConf.length ;i++){
            let from = mappingConf[i].from;
            for(let j = 0;j<resultField.length ; j++){
                if(resultField[j].comment == from){
                    map[resultField[j].field] = mappingConf[i].target;
                    break;
                }
            }
        }
        let dialogDataResp = await window.app.$http.post(`${window.context.form}/form/customDialog/v1/getListData?mapParam=&alias=${ctrl.customDialogjson.custDialog.alias}`,param);
        if(!dialogDataResp || !dialogDataResp.data || !dialogDataResp.data.rows || dialogDataResp.data.rows.length == 0){
            return new Promise((resolve,reject)=>{
                resolve([]);
            })
        }
        let rows = dialogDataResp.data.rows;
        let subTabDataList = [];
        rows.forEach(row=>{
            let subTabDataOne = {}
            for(let key in row){
                if(map.hasOwnProperty(key)){
                    let target = map[key];
                    for(let i = 0;i<target.length;i++){
                        if(target[i]){
                            subTabDataOne[target[i].split(".")[2]] = row[key];
                        }
                    }
                }
            }
            subTabDataList.push(subTabDataOne);
        })
        return new Promise((resolve,reject)=>{
            resolve(subTabDataList);
        })
    }
    function getByComponentsName(name) {
        function innerGetter(node) {
            if (node.$vnode && node.$vnode.tag && node.$vnode.tag.replace(/^vue-component-\d*-/g, "") == name) {
                return node;
            }
            if (node.$children && node.$children.length > 0) {
                for (let i = 0; i < node.$children.length; i++) {
                    let rtn = innerGetter(node.$children[i]);
                    if (rtn) return rtn;
                }
            }
        }
 
        return innerGetter(window.app)
    }
 
    function getOnlineFormData(){
        let onlineForm = document.querySelector("[name='online-form']").__vue__;
        return onlineForm.data[Object.keys(onlineForm.data)[0]]
    }
 
    let dialog  = document.querySelector("[model-name='data.zbjssj.dhk']").__vue__;
    let target = dialog.dialogConfirm;
    let data = getOnlineFormData();
    dialog.dialogConfirm = function(){
        target();
        setTimeout(()=>{
            getFillBackSubTabData().then(resp=>{
                for(let key in resp){
                    window.app.$set(data,"sub_"+key,resp[key])
                }
            })
        },100)
}


  • 注意事项


自动回填的Js可复用,到js的最下层,按照图片部分修改,目前是取当前表单上的所有子表

1. 主表对话框绑定的字段

2. 如果多个子表,可以只反填其中一个,子表名称要用英文双引号括起来

示例:

3. 子表名称


方法二

  • 补充其他写法

若上面的不生效,可以使用下面这种方法


  1. 配置关联查询,需要配置条件字段,作为入参的参数
  2. 点击预览关联查询,此时用开发者工具能看到请求的接口地址以及参数
  3. 获取到接口地址以及参数后,就可以开始编写js代码,参考代码如下,其中post请求就是用关联查询获取数据
    let vm = document.getElementsByName("online-form")[0].__vue__;
    vm.$watch("data.zbsjzddc.djbh", function (newV) {
      if (newV) {
        //清空子表
        vm.data.zbsjzddc.sub_zddcxx = [];
        //请求子表数据
        let params = [{ key: "F_xmmc", value: newV }];
        let url = `${window.context.form}/form/customQuery/v1/doQuery?alias=xmcyda&page=1`;
        
        vm.$http.post(url, params).then((resp) => {
          debugger;
          if (resp.data.rows.length > 0) {
            resp.data.rows.forEach((item, index) => {
              //初始化子表,每次循环都先放入一条空的子表行数据
              let subinit = { ...vm.data.zbsjzddc.initData.zddcxx };
              vm.data.zbsjzddc.sub_zddcxx.push(subinit);
              //对应子表字段
              vm.data.zbsjzddc.sub_zddcxx[index].xx1 = item.F_xmmc;
              vm.data.zbsjzddc.sub_zddcxx[index].xx2 = item.F_xm;
              vm.data.zbsjzddc.sub_zddcxx[index].xx3 = item.F_js;
            });
            vm.$message.success(`获取子表数据成功!`);
          } else {
            vm.$message.success(`无相关数据!`);
          }
        });
      } else {
        //newV为空时清空子表
        vm.data.zbsjzddc.sub_zddcxx = [];
        vm.$message.success(`清空成功!`);
      }
    });
注:具体的子表名称以及子表字段需要按实际使用的更换!
发表评论
评论通过审核后显示。