做系统的时候,页面有时需要展示树状列表。在前端代码里构造有点麻烦,最好是后端构造好后直接给前端用。Hutool里有个TreeUtil 可以构造树状列表,这里简单记录一下使用。
参考ruoyi项目的部门表设计即可,字段有id,parent_id,ancestors这三个就可以了,其他的可以根据业务酌情添加。
先查询出集合来,然后使用TreeUtil来构造树状结构
public List> buildCombatTreeSelect(List list) {
if (CollUtil.isEmpty(list)) {
return CollUtil.newArrayList();
}
return TreeBuildUtils.build(list, 0L, (dept, tree) -> {
tree.setId(dept.getId());
tree.setParentId(dept.getParentId());
tree.setName(dept.getDeptName());
tree.setWeight(dept.getOrderNum());
tree.putExtra("total", dept.getUserCount());
});
}
SysDept中的userCount是每个部门的用户数量,可以查询用户表获得。
有时候需要展示子节点的数量,但是工具类中没有提供相关方法,所以需要我们自己计算
public List> updateTreeChildrenTotal(List> treeList) {
for(Tree tree : treeList) {
List> children = tree.getChildren();
if(CollectionUtil.isNotEmpty(children)) {
long total = 0;
for(Tree child : children) {
total += MapUtil.getLong(updateTreeCount(Collections.singletonList(child)).get(0), "total");
}
tree.putExtra("total", total);
updateTreeCount(children);
} else {
tree.putExtra("total", 0L);
}
}
return treeList;
}
如果字节点还区分类型,比如人员和部门,部门只计算子节点下人员的数量,不计算部门。那么在此代码上加上节点类型的判断即可
public List> updateTreeChilderTotal(List> treeList) {
for(Tree tree : treeList) {
List> children = tree.getChildren();
if(CollectionUtil.isNotEmpty(children)) {
long total = 0;
for(Tree child : children) {
String type = MapUtil.getStr(child, "type");
if (StringUtils.equals(type, "person")){
total ++;
}
total += MapUtil.getLong(updateTreeCount(Collections.singletonList(child)).get(0), "total");
}
tree.putExtra("total", total);
updateTreeCount(children);
} else {
tree.putExtra("total", 0L);
}
}
return treeList;
}
有时候树状结构里需要展示该条目下的数据总量,而不是子节点的数量
/**
* 计算父节点的数据量
*
* @param treeList 树列表
*/
public List> calculateParentTotal(List> treeList) {
if (CollUtil.isEmpty(treeList)) {
return treeList;
}
for(Tree node : treeList) {
calculateNodeTotal(node);
}
return treeList;
}
/**
* 计算子节点的数数量
*
* @param node 节点
*/
private void calculateNodeTotal(Tree node) {
if (CollUtil.isEmpty(node.getChildren())) {
return;
}
int total = MapUtil.getInt(node, Constants.TOTAL);
for (Tree child : node.getChildren()) {
if (Objects.nonNull(child.get(Constants.TOTAL))) {
// 递归计算子节点的 total
calculateNodeTotal(child);
total += MapUtil.getInt(child, Constants.TOTAL);
}
}
node.putExtra(Constants.TOTAL, total);
}
树状结构好构造,就是计算数据量有点绕,绕来绕去就晕了