表单中关联表单填充关联表单
本案例来自三方开发者「Jing」
1. 使用场景
宜搭目前关联表单组件无法填充关联表单组件,借助此例我们可以探讨一下如何去实现相应的功能。
等效于:
![](https://yida-support.oss-cn-shanghai.aliyuncs.com/static/png/1706001009566-f922e65b-6c8f-454f-aa8e-b68461e869eb.png)
目前仅支持关联表单组件在主表中使用的场景,暂不支持在子表单中使用的场景。
若包含数据填充,关联表单需使用新版数据填充,旧版数据填充不支持触发,具体可见下述更新公告。
升级新版数据填充可参考目录【5.升级新版数据填充】(2023.10.30 后配置的关联表单无需操作)。
2. 实现功能
2.1. 配置关联表单数据表 1
用于后续关联表单关联数据。
![](https://yida-support.oss-cn-shanghai.aliyuncs.com/static/png/1706000599541-c7a851eb-c470-409f-a8f7-d5e0663df610.png)
2.2. 配置关联表单数据表 2
关联表单数据表 2 中放置一个关联表单关联数据表 1。
![](https://yida-support.oss-cn-shanghai.aliyuncs.com/static/png/1706000688290-37cd0196-78c7-41ee-a588-4f36944e6035.png)
![](https://yida-support.oss-cn-shanghai.aliyuncs.com/static/png/1706000736699-4441d13b-6816-4136-a119-c526fe8b55f5.png)
2.3. 不包含被填充关联表单的数据填充
2.3.1. 配置页面
![](https://yida-support.oss-cn-shanghai.aliyuncs.com/static/png/1706000801403-d4e99124-1287-4738-a45b-1dd62e03808d.png)
2.3.2. 配置关联表单
关联 2.2 中配置的表单并设置显示字段。
![](https://yida-support.oss-cn-shanghai.aliyuncs.com/static/png/1706000827960-9e6ba5d6-c0e5-4ddd-a535-0d47679ab18c.png)
![](https://yida-support.oss-cn-shanghai.aliyuncs.com/static/png/1706000849560-97d61871-8d8e-49a6-99a7-e4abe27aed5a.png)
关联 2.1 中配置的表单并设置显示字段。
![](https://yida-support.oss-cn-shanghai.aliyuncs.com/static/png/1706000888571-31781245-eeff-44a5-b859-1c00aa63cbb3.png)
![](https://yida-support.oss-cn-shanghai.aliyuncs.com/static/png/1706000918998-4c90d77e-bee2-4403-b163-12a19dcc5258.png)
2.3.3. 将下述代码拷贝至页面 JS 中
无需做任何修改。
![](https://yida-support.oss-cn-shanghai.aliyuncs.com/static/png/1706000960893-6846d8a3-1224-4777-bf35-b7bc7d8e58c3.png)
/**
* 关联表单填充关联表单
* @param sourceAssociationFormFieldId 关联表单主表字段-关联表单组件唯一标识
* @param fillAssociationFormFieldId 当前表单字段-关联表单组件唯一标识
* @param value 关联表单实例数据
*/
export function associationFormFillAssociationForm(sourceAssociationFormFieldId = '', fillAssociationFormFieldId = '', value = []) {
if (sourceAssociationFormFieldId && fillAssociationFormFieldId) {
if (value && value.length) {
const { rawData = {} } = value[0];
const { instValue = [] } = rawData;
const sourceAssociationFormFieldData = instValue.filter((item) => {
return item.fieldId === sourceAssociationFormFieldId;
});
if (sourceAssociationFormFieldData.length) {
const fillData = (((sourceAssociationFormFieldData[0] || {}).fieldData || {}).value || []);
this.$(fillAssociationFormFieldId).setValue(fillData);
}
} else {
this.$(fillAssociationFormFieldId).reset();
}
}
}
2.3.4. onChange 中调用函数
注意修改括号内的唯一标识。
关联表单主表字段(sourceAssociationFormFieldId)的值填充到 当前表单字段(fillAssociationFormFieldId)。
![](https://yida-support.oss-cn-shanghai.aliyuncs.com/static/png/1706001176127-b8d52547-2074-4102-a9a1-1dab329ee49c.png)
![](https://yida-support.oss-cn-shanghai.aliyuncs.com/static/png/1706001066545-e33e1a3c-169b-491e-9aaf-038f4922c2cd.png)
![](https://yida-support.oss-cn-shanghai.aliyuncs.com/static/png/1706001115553-d9b39abd-e782-4bc8-ac3c-66309a752693.png)
/**
* 关联表单-数据表2 onChange
* @param value 当前值
*/
export function onChange({ value }) {
this.associationFormFillAssociationForm('associationFormField_lrolefps', 'associationFormField_lrolnvkw', value);
}
2.4. 包含被填充关联表单的数据填充
2.4.1. 配置页面
![](https://yida-support.oss-cn-shanghai.aliyuncs.com/static/png/1706001314765-1e0ec533-bd34-4779-9208-4da072b39d31.png)
2.4.2. 配置关联表单
关联 2.2 中配置的表单并设置显示字段。
![](https://yida-support.oss-cn-shanghai.aliyuncs.com/static/png/1706001332011-12da3599-3524-4133-bcc2-7830980e5f79.png)
![](https://yida-support.oss-cn-shanghai.aliyuncs.com/static/png/1706001349092-e6314547-c616-4b1f-a02c-89d954342426.png)
关联 2.1 中配置的表单并设置显示字段。
![](https://yida-support.oss-cn-shanghai.aliyuncs.com/static/png/1706001362927-388e1ee2-247a-4ceb-9be7-58df669aff20.png)
![](https://yida-support.oss-cn-shanghai.aliyuncs.com/static/png/1706001413094-d41612eb-86e0-4790-b57d-b012230f5770.png)
2.4.3. 配置数据填充
按需配置数据填充。
![](https://yida-support.oss-cn-shanghai.aliyuncs.com/static/png/1706001436814-4c0630d8-07b5-408c-89df-d5ead9142b81.png)
![](https://yida-support.oss-cn-shanghai.aliyuncs.com/static/png/1706001452234-32270298-3f5b-4039-90d5-4dd243a82ad2.png)
![](https://yida-support.oss-cn-shanghai.aliyuncs.com/static/png/1706001468878-148f5047-927b-4ef8-b415-97de84e55f58.png)
2.4.4. 将下述代码拷贝至页面 JS 中
无需做任何修改。
![](https://yida-support.oss-cn-shanghai.aliyuncs.com/static/png/1706001513798-7edb1e9c-e097-4531-8dcf-c1aff2f2e407.png)
/**
* 关联表单填充关联表单
* @param sourceAssociationFormFieldId 关联表单主表字段-关联表单组件唯一标识
* @param fillAssociationFormFieldId 当前表单字段-关联表单组件唯一标识
* @param value 关联表单实例数据
*/
export function associationFormFillAssociationForm(sourceAssociationFormFieldId = '', fillAssociationFormFieldId = '', value = []) {
if (sourceAssociationFormFieldId && fillAssociationFormFieldId) {
if (value && value.length) {
const { rawData = {} } = value[0];
const { instValue = [] } = rawData;
const sourceAssociationFormFieldData = instValue.filter((item) => {
return item.fieldId === sourceAssociationFormFieldId;
});
if (sourceAssociationFormFieldData.length) {
const fillData = (((sourceAssociationFormFieldData[0] || {}).fieldData || {}).value || []);
this.$(fillAssociationFormFieldId).setValue(fillData);
}
} else {
this.$(fillAssociationFormFieldId).reset();
}
}
}
/**
* 触发关联表单数据填充
* @param associationFormFieldId 需要数据填充的关联表单组件唯一标识
*/
export function associationFormDataFilling(associationFormFieldId = '') {
if (associationFormFieldId) {
const associationFormValue = this.$(associationFormFieldId).getValue();
if (associationFormValue && associationFormValue.length) {
const { appType = '', formType = '', formUuid = '', instanceId = '' } = associationFormValue[0] || {};
if (appType && formType && formUuid && instanceId) {
const dataFillingRules = this.$(associationFormFieldId).get('dataFillingRules') || {}; // 关联表单填充条件
const { mainRules = [], tableRules = [] } = dataFillingRules;
if (mainRules.length) {
// 主表字段数据填充
if (formType === 'receipt') {
// 表单
fetch(`/${appType}/v1/form/getFormDataById.json?_csrf_token=${this.getCsrfToken()}&formInstId=${instanceId}`, {
headers: {
'Content-Type': 'application/json;charset=UTF-8',
},
})
.then((data) => {
return data.json();
}).then(({ content }) => {
const { formData = {} } = (content || {});
this.mainDataFilling(formData, mainRules);
}).catch(() => {
this.utils.toast({
title: '数据获取失败',
type: 'error',
});
});
}
if (formType === 'process') {
// 流程
fetch(`/${appType}/v1/process/getInstanceById.json?_csrf_token=${this.getCsrfToken()}&processInstanceId=${instanceId}`, {
headers: {
'Content-Type': 'application/json;charset=UTF-8',
},
})
.then((data) => {
return data.json();
}).then(({ content }) => {
const { data = {} } = (content || {});
this.mainDataFilling(data, mainRules);
}).catch(() => {
this.utils.toast({
title: '数据获取失败',
type: 'error',
});
});
}
}
if (tableRules.length) {
// 子表字段数据填充
const body = new URLSearchParams();
const searchBody = tableRules.map((item) => {
return {
page: 1,
limit: 500,
fieldId: item.tableId,
resultGroupKey: item.tableId,
searchField: (((item.filters || {}).rules) || []).map((i) => {
return {
key: i.id,
value: i.extValue === 'value' ? i.value : this.$(i.value).getValue(),
type: this.getType(i.componentType),
componentName: i.componentType,
operator: i.op,
};
}),
logicOperator: (item.filters || {}).condition,
}
});
body.append('_csrf_token', this.getCsrfToken());
body.append('formUuid', formUuid);
body.append('formInstId', instanceId);
body.append('instSubTableDataParamListStr', JSON.stringify(searchBody));
fetch(`/${appType}/query/formProcInstData/getInstMultiSubTableDatas.json`, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body,
})
.then((data) => {
return data.json();
}).then(({ content }) => {
// this.utils.__getFlowMaps().tableFieldIdMap 为非官方提供标准 API,有失效风险,谨慎使用
const targetTableFieldIdMap = this.utils.__getFlowMaps().tableFieldIdMap; // 获取当前页面子表单字段映射
const childDataFillingRules = {}; // 子表字段填充规则
tableRules.forEach((item) => {
if (!childDataFillingRules[item.tableId]) {
childDataFillingRules[item.tableId] = [];
}
const childRules = (item.rules || []).map((i) => {
return {
...i,
sourceTableField: item.tableId, // 目标子表单
targetTableField: targetTableFieldIdMap[i.target], // 当前页面子表单
};
});
childDataFillingRules[item.tableId] = childRules;
});
this.childDataFilling(content, childDataFillingRules);
}).catch(() => {
this.utils.toast({
title: '数据获取失败',
type: 'error',
});
});
}
}
}
}
}
/**
* 主表字段数据填充处理函数
* @param dataMap 源数据
* @param mainRules 主表字段填充规则
*/
export function mainDataFilling(dataMap = {}, mainRules = []) {
try {
mainRules.forEach((item) => {
this.$(item.target).setValue(this.mainDataSolve(dataMap, item.source, item.sourceType));
});
} catch (error) {
console.error(error);
this.utils.toast({
title: '主表字段数据填充错误',
type: 'error',
});
}
}
/**
* 主表数据处理函数
* @param dataMap 源数据
* @param source 源字段唯一标识
* @param sourceType 源字段类型
*/
export function mainDataSolve(dataMap = {}, source = '', sourceType = '') {
try {
if (dataMap[source]) {
switch (sourceType) {
case 'AttachmentField': // 附件
case 'ImageField': // 图片
case 'AddressField': // 地址
return dataMap[source] ? JSON.parse(dataMap[source]) : [];
case 'RadioField': // 单选
case 'CheckboxField': // 复选
case 'SelectField': // 下拉单选
case 'MultiSelectField': // 下拉复选
return dataMap[`${source}_id`];
case 'CascadeSelectField': // 级联选择
return (dataMap[`${source}_id`] || []).at(-1);
case 'EmployeeField': // 成员
return (dataMap[source] || []).map((item, index) => {
return {
label: item,
value: dataMap[`${source}_id`][index],
};
});
case 'DepartmentSelectField': // 部门
case 'CountrySelectField': // 国家 / 地区
return (dataMap[source] || []).map((item, index) => {
return {
text: item,
value: dataMap[`${source}_id`][index],
};
});
case 'DateField': // 日期
return Number(dataMap[source]);
case 'CascadeDateField': // 日期区间
return [Number(dataMap[source][0]), Number(dataMap[source][1])];
default:
return dataMap[source];
}
}
} catch (error) {
console.error(error);
this.utils.toast({
title: '数据填充处理错误',
type: 'error',
});
}
}
/**
* 子表字段数据填充处理函数
* @param dataMap 源数据
* @param childDataFillingRules 子表字段填充规则
*/
export function childDataFilling(dataMap = {}, childDataFillingRules = {}) {
try {
const tableDataResult = {};
Object.keys(dataMap).forEach((tableKey) => {
const items = [];
if (!tableDataResult[tableKey]) {
tableDataResult[tableKey] = [];
}
const tableDataItem = (dataMap[tableKey].values || []).map((item) => {
return item.instValue ? JSON.parse(JSON.parse(item.instValue)) : [];
});
tableDataItem.forEach((i) => {
const objItem = {};
i.forEach((j) => {
objItem[j.fieldId] = this.childDataSolve(j.fieldData, j.componentName);
});
items.push(objItem);
});
tableDataResult[tableKey] = items;
});
Object.keys(childDataFillingRules).forEach((key) => {
if (key && childDataFillingRules[key] && childDataFillingRules[key].length) {
const result = []; // 数据处理结果
tableDataResult[key].forEach((i) => {
const objItem = {};
childDataFillingRules[key].forEach((j) => {
objItem[j.target] = i[j.source];
});
result.push(objItem);
});
this.$(childDataFillingRules[key][0].targetTableField).setValue(result);
}
});
} catch (error) {
console.error(error);
this.utils.toast({
title: '子表单数据填充错误',
type: 'error',
});
}
}
/**
* 子表数据处理函数
* @param fieldData 源数据
* @param componentName 源字段类型
*/
export function childDataSolve(fieldData = {}, componentName = '') {
try {
if (componentName) {
switch (componentName) {
case 'CascadeSelectField': // 级联选择
return ((fieldData.value || []).at(-1) || {}).value;
default:
return fieldData.value;
}
}
} catch (error) {
console.error(error);
this.utils.toast({
title: '数据填充处理错误',
type: 'error',
});
}
}
/**
* 获取数据筛选的类型
* @param componentName 字段类型
*/
export function getType(componentName = '') {
if (componentName) {
switch (componentName) {
case 'RadioField': // 单选
case 'CheckboxField': // 复选
case 'SelectField': // 下拉单选
case 'MultiSelectField': // 下拉复选
case 'DepartmentSelectField': // 部门
case 'CountrySelectField': // 国家地区
return 'ARRAY';
case 'NumberField': // 数值
case 'RateField': // 评分
case 'DateField': // 日期
case 'CascadeDateField': // 日期区间
return 'DOUBLE';
default:
return 'TEXT';
}
}
}
/**
* 获取 csrfToken
*/
export function getCsrfToken() {
const tokenDom = document.getElementsByName('_csrf_token');
const csrfToken = tokenDom && tokenDom.length ? (tokenDom[0] || {}).value : '';
return csrfToken;
}
2.4.5. onChange 中调用函数
关联表单主表字段(sourceAssociationFormFieldId)的值填充到 当前表单字段(fillAssociationFormFieldId)。
需要数据填充的关联表单组件唯一标识(associationFormFieldId)。
![](https://yida-support.oss-cn-shanghai.aliyuncs.com/static/png/1706001176127-b8d52547-2074-4102-a9a1-1dab329ee49c.png)
![](https://yida-support.oss-cn-shanghai.aliyuncs.com/static/png/1706001604156-85525943-6202-402f-84eb-2e8b1898f6c3.png)
![](https://yida-support.oss-cn-shanghai.aliyuncs.com/static/png/1706001577210-806b27b5-5705-4d9b-95c0-7c0d7d93e510.png)
/**
* 关联表单-数据表2 onChange
* @param value 当前值
*/
export function onChange({ value }) {
this.associationFormFillAssociationForm('associationFormField_lrolefps', 'associationFormField_lrolnvkw', value);
this.associationFormDataFilling('associationFormField_lrolnvkw');
}
3. 实现效果
3.1. 不包含被填充关联表单的数据填充
![](https://yida-support.oss-cn-shanghai.aliyuncs.com/static/png/1706001686664-033182c3-a640-4177-8627-540a937696b9.png)
3.2. 包含被填充关联表单的数据填充
![](https://yida-support.oss-cn-shanghai.aliyuncs.com/static/png/1706001736816-06e8302d-cc40-4d7b-982b-d3725a0069d5.png)
4. 在线试玩
5. 升级新版数据填充
将关联表单的填充条件重新保存即可升级到新版数据填充(下述操作后页面也需重新保存下)。
![](https://yida-support.oss-cn-shanghai.aliyuncs.com/static/png/1706061364067-8c22a285-24c5-4586-8db5-c74bfd58d171.png)
![](https://yida-support.oss-cn-shanghai.aliyuncs.com/static/png/1706062816446-62fa75d8-4b48-45fc-bd7d-4d09dca47a51.png)
本文档对您是否有帮助?