目录
- [1 创建APIs](#1 创建APIs)
- [2 完整代码](#2 完整代码)
- [3 代码解释](#3 代码解释)
-
- [3.1 获取原始数据](#3.1 获取原始数据)
- [3.2 平铺数据](#3.2 平铺数据)
- [3.3 构建树形结构](#3.3 构建树形结构)
- [3.4 组装树形结构](#3.4 组装树形结构)
- [3.5 数据返回](#3.5 数据返回)
- [4 执行测试](#4 执行测试)
- 总结
我们现在已经调用了antd实现了前端的界面,光有界面还是不够的,还需要和数据源进行交互,本节介绍后端API的搭建过程。
1 创建APIs
打开应用,在侧边栏点击APIs。
选择自定义代码
输入API的名称和标识
修改方法的名称和标识
2 完整代码
加入如下代码
bash
module.exports = async function (params, context) {
const result = await context.callModel({
name: 'bmb', // 数据模型标识,可以前往「数据源 - 数据模型」列表页查看
methodName: 'wedaGetRecordsV2', // 数据模型方法标识
params: {
// 排序
orderBy: [
{
createdAt: "desc", // 创建时间,倒序
},
],
// 返回字段选择
select: {
_id: true, // 返回主表中的字段
bmmc: true,
xh: true,
fbm: true, // 需要返回 fbm 字段
},
// 返回total字段
getCount: true,
// 页面大小
pageSize: 200,
// 当前页面
pageNumber: 1,
},
});
// 平铺数据
const flatData = result.records;
// 构建树形结构
function buildTree(data) {
const idMap = {}; // 用于存储所有节点
const tree = []; // 树形结构的根节点
// 初始化每个节点
data.forEach((item) => {
idMap[item._id] = {
id: item._id,
name: item.bmmc, // 部门名称
parentId: item.fbm ? item.fbm._id : undefined, // 使用三元表达式处理 fbm 和 parentId
children: [],
};
});
// 组装树形结构
Object.values(idMap).forEach((node) => {
if (node.parentId === undefined) {
// 如果没有父节点,则为根节点
tree.push(node);
} else {
// 如果有父节点,加入父节点的 children
if (idMap[node.parentId]) {
// 确保父节点存在
idMap[node.parentId].children.push(node);
}
}
});
return tree;
}
// 转换为树形结构
const treeData = buildTree(flatData);
// 返回树形数据
return {
success: true,
data: treeData, // 直接返回树形数据
};
};
3 代码解释
我们要将平铺的部门数据转换成树形结构,其中每个节点代表一个部门,每个部门可能有子部门(即 children)。同时,我们要确保在处理过程中,对于没有父节点的部门(根部门),我们能够正确标记其 parentId 为 undefined,并且对于每个节点的父部门(fbm),我们要检查其是否存在并处理相应的关系。
3.1 获取原始数据
在我们的例子中,数据来自 context.callModel 方法。这个方法返回了一个扁平化的部门数据列表,包含了每个部门的信息和可能存在的父部门 fbm 信息。
bash
const result = await context.callModel({
name: 'bmb', // 数据模型标识
methodName: 'wedaGetRecordsV2', // 方法标识
params: {
// 排序
orderBy: [
{
createdAt: "desc", // 按照创建时间倒序排序
},
],
// 返回字段选择
select: {
_id: true, // 返回部门 ID
bmmc: true, // 部门名称
xh: true, // 部门序号
fbm: true, // 父部门字段
},
// 返回记录总数
getCount: true,
pageSize: 200, // 每页返回 200 条数据
pageNumber: 1, // 当前页码
},
});
这里的name需要从数据库里粘贴对应的标识,点击云数据库,复制对应的标识
3.2 平铺数据
flatData 即为从 API 获取到的平铺数据,是一个部门的扁平化数组。每一项代表一个部门,包含 _id(部门 ID)、bmmc(部门名称)、xh(部门序号)以及可能存在的 fbm(父部门)。如果一个部门没有父部门,在微搭中fbm这个属性将不存在,后续需要考虑这种不存在的情况。
3.3 构建树形结构
树形结构的核心思想是:每个节点可以包含多个子节点(children)。在这个例子中,parentId 用于标识父子关系。如果一个部门没有父部门,那么它是根节点(parentId 为 undefined)。
bash
function buildTree(data) {
const idMap = {}; // 用于存储所有节点,使用 ID 作为键
const tree = []; // 树形结构的根节点数组
// 初始化每个节点
data.forEach((item) => {
idMap[item._id] = {
id: item._id,
name: item.bmmc, // 部门名称
parentId: item.fbm ? item.fbm._id : undefined, // 获取父节点 ID,若无则为 undefined
children: [], // 初始化子节点为空数组
};
});
初始化 idMap:我们通过 item._id 来为每个部门创建一个独立的节点对象,并在 idMap 中存储这些节点。每个节点都有 id(部门 ID)、name(部门名称)、parentId(父节点 ID,可能为 undefined)和 children(子部门)等属性。
处理 parentId:parentId 是通过 item.fbm ? item.fbm._id : undefined 获取的。这里我们使用了三元表达式:如果 item.fbm 存在,并且是一个对象(即有 _id 属性),那么 parentId 就是 fbm._id。如果 item.fbm 不存在,parentId 就是 undefined,表示该部门是根部门。
3.4 组装树形结构
我们遍历 idMap 中的每一个节点。如果 parentId 为 undefined,表示该节点是根节点,我们将其推入 tree 数组。否则,如果节点有父节点(通过 parentId 查找),则将该节点添加到父节点的 children 数组中,形成树形结构。
bash
// 组装树形结构
Object.values(idMap).forEach((node) => {
if (node.parentId === undefined) {
// 如果没有父节点,则为根节点
tree.push(node);
} else {
// 如果有父节点,加入父节点的 children
if (idMap[node.parentId]) {
// 确保父节点存在
idMap[node.parentId].children.push(node);
}
}
});
return tree;
}
3.5 数据返回
最终,我们通过 buildTree 函数将平铺的 flatData 转换成了树形结构的数据。在返回数据时,我们确保数据中没有 undefined 值。
bash
const treeData = buildTree(flatData);
// 返回树形数据
return {
success: true,
data: treeData, // 返回构建的树形数据
};
4 执行测试
代码写好了之后要看结果是否符合我们的预期,点击方法测试
点击运行测试
当看到成功之后,点击出参自动映射就完成了API的编制
总结
我们本篇介绍了后端API的编写过程,在低代码开发的过程中也是遵循前后端分离的原则。前端我们使用官方自带的组件或者引入第三方组件库完成页面的编写,所需的数据按照一定的格式通过编写API获取到,下一篇我们就讲解如何让前端和后端协同工作完成需要的具体功能。