跳到主要内容

表单中级联组件配置表单数据源

本案例来自三方开发者「苏灏」

1. 使用场景

宜搭级联组件不支持关联其他表单选项,本例我们学习一下如何通过宜搭 OpenAPI 实现这个效果。

2. 实现功能

2.1 常规使用

(1)数据底表配置

若有更多的级可继续配置,本例以四级为例。

默认取底表第一条实例中的子表单数据为选项。

(2)使用页面配置

(3)配置变量并绑定

(4)配置数据源

参考文档:根据搜索条件获取实例详情列表

接口配置如图:

(5)配置获取级联选项函数封装并调用

// 当页面渲染完毕后马上调用下面的函数,这个函数是在当前页面 - 设置 - 生命周期 - 页面加载完成时中被关联的。
export function didMount() {
console.log(`「页面 JS」:当前页面地址 ${location.href}`);
// console.log(`「页面 JS」:当前页面 id 参数为 ${this.state.urlParams.id}`);
// 更多 this 相关 API 请参考:https://www.yuque.com/yida/support/ocmxyv#OCEXd
// document.title = window.loginUser.userName + ' | 宜搭';
this.fetchData();
}

// 获取级联选项
export function fetchData() {
const loading = this.utils.toast({
title: '级联选项获取中...',
type: 'loading'
});
this.dataSourceMap.getData.load({
formUuid,
}).then(res => {
loading();
const { totalCount, data } = res;
if (!totalCount) { return };
const { formData, instValue } = data[0];
const tableData = this.formatTableData(instValue, tableField);
const result = this.transformData(tableData);
this.setState({
dataSource: result
});
}).catch(error => {
loading();
this.utils.toast({
title: error.message,
type: 'error'
});
});
}

(6)配置级联组件选项值处理函数

// 级联选项数据处理
export function transformData(inputStr) {
const rows = inputStr.map(item => {
return dataSourceList.map(_item => {
return item[_item]
}).filter(item => {
return !!item
});
});
const res = {
children: {}
};
rows.forEach(row => {
row.reduce((pre, cur) => {
if (!pre.children[cur]) {
pre.children[cur] = {
label: cur,
value: pre.value ? `${pre.value}_${cur}` : cur,
children: {}
}
}
return pre.children[cur];
}, res);
});
const mapToArray = (map) => {
return Object.values(map).map(item => {
if (item.children) {
item.children = mapToArray(item.children);
}
if (Object.keys(item.children).length === 0) {
delete item.children;
}
return item;
});
};
return mapToArray(res.children);
}

(7)配置子表单数据格式化函数

// 格式化子表单数据
// instValue 接口返回,tableFieldId:需要获取的子表单唯一标识
export function formatTableData(instValue = '', tableFieldId = '') {
const tableData = [];
if (!instValue || !tableFieldId) {
return tableData;
};
const initInstValue = JSON.parse(instValue);
const tableInstValue = (((initInstValue.filter(item => {
return item.fieldId === tableFieldId;
})[0] || {}).fieldData || {}).value || []);
for (let i = 0; i < tableInstValue.length; i++) {
let tableObj = {};
for (let j = 0; j < tableInstValue[i].length; j++) {
tableObj[tableInstValue[i][j].fieldId] = tableInstValue[i][j].fieldData.value;
};
tableData.push(tableObj);
};
return tableData;
}

(8)配置固定参数

注意:级联选项对应各级的唯一标识,需要按照一级 ~ n级的顺序。

const formUuid = 'FORM-XXXXXXXXXXXXXXXXX'; // 级联选项数据底表
const tableField = 'tableField_lf7mskog'; // 级联选项数据底表子表单唯一标识
const dataSourceList = [
'textField_lf7mskoh', // 一级
'textField_lf7mskoi', // 二级
'textField_lf7mskoj', // 三级
'textField_lf7mskok' // 四级
]; // 级联选项对应各级的唯一标识,注意需要按照一级 ~ n级的顺序

2.2 异步加载

(1)数据底表配置

配置数据源:

配置级别字段 onChange 事件:

const formUuid = 'FORM-RS966T81PG09H7S26RWSGDFW1VVC2QPDMKGFLP'; // 当前表 formUuid

// 循环调用,适用于请求全量数据(单次数据量大于100)的场景,调用后,请在then方法里面查看请求结果。
// dpName:String,数据源名称(必填),formUuid:String,查询目标表的formUuid(必填),searchFieldJson:Object,查询条件(非必填)。
export async function loopLoad(dpName, formUuid, searchFieldJson = {}) {
const result = []; // 最终数据集合
const errorPages = []; // 错误请求页码
await this.dataSourceMap[dpName].load({
formUuid,
searchFieldJson: JSON.stringify(searchFieldJson),
pageSize: 100
}).catch(error => {
this.utils.toast({
title: error.message,
type: 'error',
});
errorPages.push(1);
});
if (!this.state[dpName]) { return result };
if (this.state[dpName].totalCount <= 100) {
//当实例总数不大于100时
result.push(...this.state[dpName].data); //归整数据
} else {
//当实例总数大于100时
for (let i = 0; i < Math.ceil(this.state[dpName].totalCount / 100); i++) {
const delay = i === 0 ? 0 : 200;
await new Promise((resolve => {
// 注意节流,每次请求间隔 200 ms
setTimeout(async () => {
await this.dataSourceMap[dpName].load({
formUuid,
searchFieldJson: JSON.stringify(searchFieldJson),
pageSize: 100,
currentPage: i + 1
}).then(res => {
if (!res) { return };
result.push(...res.data);
}).catch(error => {
errorPages.push(i + 1);
});
resolve();
}, delay);
}));
};
};
return { result, errorPages };
}

/**
* selectField onChange
* @param value: {mixed} 选中的值
* @param actionType: {String} 触发的方式, 'itemClick', 'enter', 'change'
* @param item: {mixed} 选中的值的对象数据
*/
export function onChange({ value, actionType, item }) {
if (value === "1") {
return;
}; // 顶级名称过滤
this.loopLoad("getData", formUuid, {
selectField_lfduy8ny: value - 1
}).then(res => {
const { result = [] } = res;
let resultArr = result.map(({ formData }) => {
return {
text: formData.textField_lfduy8nw,
value: formData.textField_lfduy8nw
};
})
this.$('selectField_lfdv3l58').set('dataSource', resultArr); //赋值父级名称
});
}

(2)使用页面配置

(3)配置变量并绑定

(4)配置数据源

参考文档:根据搜索条件获取实例详情列表

接口配置如图:

(5)配置获取级联选项函数封装并调用

export function didMount() {
console.log(`「页面 JS」:当前页面地址 ${location.href}`);
// console.log(`「页面 JS」:当前页面 id 参数为 ${this.state.urlParams.id}`);
// 更多 this 相关 API 请参考:https://www.yuque.com/yida/support/ocmxyv#OCEXd
// document.title = window.loginUser.userName + ' | 宜搭';
this.fetchData();
}

const formUuid = 'FORM-RS966T81PG09H7S26RWSGDFW1VVC2QPDMKGFLP'; // 级联选项数据底表

// 获取级联选项
export function fetchData() {
const loading = this.utils.toast({
title: '级联选项获取中...',
type: 'loading'
});
this.dataSourceMap.getData.load({
formUuid,
pageSize: 100,
searchFieldJson: JSON.stringify({
selectField_lfduy8ny: 1, //初始化查找等级为1的顶级名称
})
}).then(({ data }) => {
let arr = data.map(({ formData }) => {
return {
value: formData.textField_lfduy8nw, // 地区名称
label: formData.textField_lfduy8nw, // 地区名称
level: formData.selectField_lfduy8ny, // 级别
}
})
loading();
this.setState({
dataSource: arr
})
}).catch(error => {
loading();
console.log(error)
this.utils.toast({
title: error.message,
type: 'error'
});
});
}

(6)配置级联异步加载函数

// 级联异步加载数据请求函数
export async function asyncLoadData(node) {
const treeFind = (tree, nodeId, data, falg) => {
if (tree.label === nodeId) {
if (falg) {
// 没有下一级加上标识代表是尾节点
tree.isLeaf = true;
} else {
// 如果找到节点就把数据加入children
tree.children = data;
}
return;
}
if (tree.children) {
for (let child of tree.children) {
treeFind(child, nodeId, data, falg); // 递归判断
}
}
};

const deepClone = (obj) => {
if (obj === null || typeof obj !== "object") {
return obj;
};
const copy = Array.isArray(obj) ? [] : {};
Object.keys(obj).forEach((key) => {
copy[key] = deepClone(obj[key]);
});
return copy;
};

const { dataSource } = this.state;
let cloneData = {
children: deepClone(dataSource)
}; //拷贝数据

try {
const result = await this.dataSourceMap.getData.load({
formUuid,
pageSize: 100,
searchFieldJson: JSON.stringify({
selectField_lfduy8ny: +node.level + 1, //查找当前的等级
selectField_lfdv3l58: node.label, // 父级名称
}),
});

let childList = result.data.map(({ formData }) => {
return {
label: formData.textField_lfduy8nw,
value: formData.textField_lfduy8nw,
level: +node.level + 1,
parent: node.label,
};
});
const falg = childList.length === 0; //是否有下一级数据
treeFind(cloneData, node.label, childList, falg);
this.setState({
dataSource: cloneData.children,
});
} catch (error) {
// 错误提示
this.utils.toast({
title: error.message,
type: "error",
});
}
}

(7)配置固定参数

(8)自定义页面中使用

async function loadData(node) {
await this.asyncLoadData(node);
}

(9)表单中使用

注意修改唯一标识。

this.$('cascadeSelectField_lfhkoxd3').set('isLoadData', true);
this.$('cascadeSelectField_lfhkoxd3').set('loadData', async (node) => {
await this.asyncLoadData(node);
});

3. 实现效果

3.1 常规使用

3.2 异步加载

4. 在线试玩

Copyright © 2024钉钉(中国)信息技术有限公司和/或其关联公司浙ICP备18037475号-4