方法一
- 子表自动回填
场景:合同主表选择“合同模板”的主表数据,并且返回“合同模板”一对多子表的多行数据。
实现这个需求需要配置两个对话框
一.查询”合同模板“主表数据的对话框
注意返回字段这个地方要返回一个主表数据的主键
在数据库内主从表数据的关系如下
可以看到,主表的其中的一条数据的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. 子表名称
方法二
- 补充其他写法
若上面的不生效,可以使用下面这种方法
- 配置关联查询,需要配置条件字段,作为入参的参数
- 点击预览关联查询,此时用开发者工具能看到请求的接口地址以及参数
- 获取到接口地址以及参数后,就可以开始编写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(`清空成功!`); } });