Custom Pages implement tree data display and asynchronous data loading
1. Usage scenarios
In some ERP systems, we need to display the BOM list of products, but we don't know how to design forms and process data. With the help of this case, we will discuss how to realize this requirement.
2. Implement functions
2.1. Use in tree controls
2.1.1. Create a form page to store node data
2.1.2. Create a custom page
2.1.3. Configure data sources and variables
2.1.4. Obtain node data and render tree controls
export async function didMount() {
// console.log(`「页面 JS」:当前页面 id 参数为 ${this.state.urlParams.id}`);
// 更多 this 相关 API 请参考:https://www.yuque.com/yida/support/ocmxyv#OCEXd
// document.title = window.loginUser.userName + ' | 宜搭';
const treeData = await this.getTreeData('root');
this.setState({
treeData,
loading: false,
});
}
// 获取树形控件数据
// parentId 父级编号,默认值:root,默认查询根节点数据
export function getTreeData(parentId = '') {
return this.dataSourceMap.getData.load({
formUuid: 'FORM-UP966371FFRDSTELD76KQAL0TG5A2NHOSKULL0',
pageSize: 100,
searchFieldJson: JSON.stringify({
textField_llul76ou: parentId, // 父级编号
}),
}).then((res) => {
const { data = [] } = res;
return data.map(({ formData, formInstId }) => {
return {
formInstId, // 节点实例 id
nodeId: formData.serialNumberField_llw1e7qs, // 节点编号
label: formData.textField_lfduy8nw, // 节点名称
parentId: formData.textField_llul76ou, // 父级编号
};
});
}).catch((error) => {
this.utils.toast({
title: error.message,
type: 'error',
});
return [];
});
}
2.1.5. Configure asynchronous loading of tree controls
// 树形控件异步加载数据请求函数
export async function asyncLoadData(node) {
const treeFind = (tree, nodeId, data, falg) => {
if (tree.nodeId === nodeId) {
if (falg) {
// 没有下一级加上标识代表是尾节点
tree.isLeaf = true;
} else {
// 如果找到节点就把数据加入 children
tree.children = data;
}
return;
}
if (tree.children) {
for (const child of tree.children) {
treeFind(child, nodeId, data, falg); // 递归判断
}
}
};
const { nodeId, parentId } = node.props || node;
const { treeData } = this.state;
const cloneData = {
children: treeData,
};
const childNodeList = await this.getTreeData(nodeId);
const falg = childNodeList.length === 0; // 是否有下一级数据
treeFind(cloneData, nodeId, childNodeList, falg);
this.setState({
treeData: cloneData.children,
});
}
2.1.6. Configure node data operation functions
// 更新节点
export function updateNode(treeData, selectedNodeId, updateNodeName) {
for (let i = 0; i < treeData.length; i++) {
if (treeData[i].nodeId === selectedNodeId) {
treeData[i].label = updateNodeName;
return treeData;
} else if (treeData[i].children) {
this.updateNode(treeData[i].children, selectedNodeId, updateNodeName);
}
}
return treeData;
}
// 新增节点
export function addChildrenNode(treeData, selectedNodeId, addNodeData) {
for (let i = 0; i < treeData.length; i++) {
if (treeData[i].nodeId === selectedNodeId) {
if (!treeData[i].children) {
treeData[i].children = [];
}
treeData[i].isLeaf = false;
treeData[i].children.push(addNodeData);
return treeData;
} else if (treeData[i].children) {
this.addChildrenNode(treeData[i].children, selectedNodeId, addNodeData);
}
}
return treeData;
}
// 删除节点
export function deleteNode(treeData, selectedNodeId) {
return treeData.filter((item) => {
if (item.nodeId === selectedNodeId) {
return false;
}
if (item.children) {
item.children = this.deleteNode(item.children, selectedNodeId);
}
return true;
});
}
2.1.7. Configure node operations
// 节点编辑
// 第一次点击时是选中,第二次点击时是取消选中,取消选中时没有节点信息,所以不触发节点编辑弹窗
export function onSelect(selectedKeys, extra) {
if (selectedKeys.length) {
const { selectedNodes = [] } = extra;
const { props = {} } = selectedNodes[0];
this.$('dialog_llpz2tm6').show(() => {
this.setState({
editType: 'updateNowNode',
selectedNode: props,
});
});
}
}
2.1.8. Configure node edit dialog box and Operation callback function
// 确定编辑
export function onEditOk() {
const { editType, selectedNode, treeData } = this.state;
switch (editType) {
case 'updateNowNode':
// 更新当前节点
this.$('textField_llpz2tm8').validate();
const updateNodeName = this.$('textField_llpz2tm8').getValue();
if (!updateNodeName) {
return;
}
if (updateNodeName === selectedNode.label) {
this.$('dialog_llpz2tm6').hide();
return;
}
this.dataSourceMap.updateData.load({
formInstId: selectedNode.formInstId,
updateFormDataJson: JSON.stringify({
textField_lfduy8nw: updateNodeName,
}),
}).then(() => {
this.utils.toast({
title: '更新成功',
type: 'success',
});
this.$('dialog_llpz2tm6').hide();
const result = this.updateNode(treeData, selectedNode.nodeId, updateNodeName);
this.setState({
treeData: result,
});
this.$('tree_llp0327v').forceUpdate();
}).catch(({ message }) => {
this.utils.toast({
title: message,
type: 'error',
});
});
break;
case 'addChildrenNode':
// 新增子节点
this.$('textField_llpz2tmg').validate();
const addNodeName = this.$('textField_llpz2tmg').getValue();
if (!addNodeName) {
return;
}
this.dataSourceMap.saveData.load({
formUuid: 'FORM-UP966371FFRDSTELD76KQAL0TG5A2NHOSKULL0',
appType: window.pageConfig.appType || window.g_config.appKey,
formDataJson: JSON.stringify({
textField_lfduy8nw: addNodeName, // 节点名称
textField_llul76ou: selectedNode.nodeId, // 父级编号
}),
}).then((res) => {
this.dataSourceMap.getDataById.load({
formInstId: res,
}).then((newNode) => {
const { formData = {} } = newNode;
this.utils.toast({
title: '新增成功',
type: 'success',
});
this.$('dialog_llpz2tm6').hide();
const result = this.addChildrenNode(treeData, selectedNode.nodeId, {
formInstId: res, // 实例 id
label: formData.textField_lfduy8nw, // 节点名称
nodeId: formData.serialNumberField_llw1e7qs, // 节点编号
parentId: formData.textField_llul76ou, // 父级编号
});
this.setState({
treeData: result,
});
this.$('tree_llp0327v').forceUpdate();
});
}).catch(({ message }) => {
this.utils.toast({
title: message,
type: 'error',
});
});
break;
default:
// 删除当前节点
this.dataSourceMap.deleteData.load({
formInstId: selectedNode.formInstId,
}).then(() => {
this.utils.toast({
title: '删除成功',
type: 'success',
});
this.$('dialog_llpz2tm6').hide();
const result = this.deleteNode(treeData, selectedNode.nodeId);
this.setState({
treeData: result,
selectedNode: {},
});
this.$('tree_llp0327v').forceUpdate();
});
break;
}
}
2.2. Use in tables
2.2.1. Create a form page to store node data
2.2.2. Create a custom page
2.2.3. Configure data sources and variables
2.2.4. Obtain node data and render tables
2.2.5. Configure enable tree tables and asynchronous loading functions
2.3. Use in the organization chart
2.3.1. Create a form page to store data nodes
2.3.2. Create a custom page
2.3.3. Configure data sources and variables
2.3.4. Introduce a third-party Chart Library
For more information about introducing third-party resources, see:示例中心 | 开发者赋能平台
CDN address:https://unpkg.com/@ant-design/graphs@1.4.2/dist/graphs.min.js
Reference documents:Organization Chart
2.3.5. Write chart rendering functions
2.3.6. Add rendering functions to custom page JSX
2.3.7. Get data rendering charts
3. Effect
3.1. Tree control
3.2. Table
3.3. Organization Chart
4. Try it online
This doc is generated using machine translation. Any discrepancies or differences created in the translation are not binding and have no legal effect for compliance or enforcement purposes.
本文档对您是否有帮助?