diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/TreeUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/TreeUtils.java index c145b4d71..73246dbe4 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/TreeUtils.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/TreeUtils.java @@ -1,11 +1,15 @@ package com.ruoyi.common.utils; +import cn.hutool.core.collection.CollUtil; import cn.hutool.core.lang.tree.Tree; import cn.hutool.core.lang.tree.TreeNodeConfig; import cn.hutool.core.lang.tree.TreeUtil; import cn.hutool.core.lang.tree.parser.NodeParser; +import cn.hutool.core.util.ObjectUtil; +import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; import java.util.List; +import java.util.stream.Collectors; /** * 树结构工具类 @@ -13,18 +17,116 @@ import java.util.List; * @author Wenchao Gong * @date 2021-09-08 */ -public class TreeUtils { +public class TreeUtils +{ public static final TreeNodeConfig DEFAULT_TREE_NODE_CONFIG = new TreeNodeConfig(); + public static final long DEFAULT_PARENT_ID = 0L; + public static final String FIELD_NODE_EXIST = "exist"; - static - { + static { DEFAULT_TREE_NODE_CONFIG.setNameKey("label"); } + /** + * 设置默认 parentId + * + * @param list + * @param nodeParser + * @param + * @return + */ public static List> build(List list, NodeParser nodeParser) { - Long parentId = 0L; - return TreeUtil.build(list, parentId, DEFAULT_TREE_NODE_CONFIG, nodeParser); + return TreeUtil.build(list, DEFAULT_PARENT_ID, DEFAULT_TREE_NODE_CONFIG, nodeParser); + } + + + /** + * 树构建 + * + * @param 转换的实体 为数据源里的对象类型 + * @param ID类型 + * @param list 源数据集合 + * @param parentId 最顶层父id值 一般为 0 之类 + * @param nodeParser 转换器 + * @param needExistField 是否需要 已存在字段 + * @return List + */ + public static List> build(List list, E parentId, NodeParser nodeParser, + boolean needExistField) + { + final List> treeList = CollUtil.newArrayList(); + final TreeNodeConfig treeNodeConfig = DEFAULT_TREE_NODE_CONFIG; + Tree tree; + for (T obj : list) { + tree = new Tree<>(treeNodeConfig); + nodeParser.parse(obj, tree); + treeList.add(tree); + } + + List> finalTreeList = CollUtil.newArrayList(); + for (Tree node : treeList) { + if (ObjectUtil.equals(parentId, node.getParentId())) { + finalTreeList.add(node); + innerBuild(treeList, node, 0, treeNodeConfig.getDeep(), needExistField); + } + } + // 内存每层已经排过了 这是最外层排序 + finalTreeList = finalTreeList.stream().sorted().collect(Collectors.toList()); + return finalTreeList; + } + + /** + * 递归处理 + * + * @param treeNodes 数据集合 + * @param parentNode 当前节点 + * @param deep 已递归深度 + * @param maxDeep 最大递归深度 可能为null即不限制 + * @param needExistField 是否需要 已存在字段 + */ + private static void innerBuild(List> treeNodes, Tree parentNode, int deep, Integer maxDeep, + boolean needExistField) + { + if (CollUtil.isEmpty(treeNodes)) { + return; + } + //maxDeep 可能为空 + if (maxDeep != null && deep >= maxDeep) { + return; + } + // 每层排序 TreeNodeMap 实现了Comparable接口 + treeNodes = treeNodes.stream().sorted().collect(Collectors.toList()); + for (Tree childNode : treeNodes) { + if (parentNode.getId().equals(childNode.getParentId())) { + List> children = parentNode.getChildren(); + if (children == null) { + children = CollUtil.newArrayList(); + parentNode.setChildren(children); + } + children.add(childNode); + childNode.setParent(parentNode); + if (needExistField) { + Object pobj = parentNode.get(FIELD_NODE_EXIST); + boolean exist = pobj == null ? true : (boolean) pobj; + if (exist && !CollectionUtils.isEmpty(children)) { + long count = children.stream().filter(t -> { + Object obj = t.get(FIELD_NODE_EXIST); + if (obj != null) { + return !(boolean) obj; + } else { + return false; + } + }).count(); + if (count > 0) { + exist = false; + } + } + parentNode.put(FIELD_NODE_EXIST, exist); + } + innerBuild(treeNodes, childNode, deep + 1, maxDeep, needExistField); + } + } } } diff --git a/ruoyi-isc/src/main/java/com/ruoyi/isc/service/impl/IscServiceCateServiceImpl.java b/ruoyi-isc/src/main/java/com/ruoyi/isc/service/impl/IscServiceCateServiceImpl.java index 64ec9ecb6..ec38e68c6 100644 --- a/ruoyi-isc/src/main/java/com/ruoyi/isc/service/impl/IscServiceCateServiceImpl.java +++ b/ruoyi-isc/src/main/java/com/ruoyi/isc/service/impl/IscServiceCateServiceImpl.java @@ -3,21 +3,22 @@ package com.ruoyi.isc.service.impl; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.lang.tree.Tree; +import cn.hutool.core.lang.tree.parser.NodeParser; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.ruoyi.common.constant.UserConstants; +import com.ruoyi.common.core.mybatisplus.core.ServicePlusImpl; import com.ruoyi.common.utils.FullPathUtils; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.TreeUtils; import com.ruoyi.isc.domain.IscService; -import org.springframework.stereotype.Service; -import com.ruoyi.common.core.mybatisplus.core.ServicePlusImpl; -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.ruoyi.isc.domain.IscServiceCate; import com.ruoyi.isc.domain.bo.IscServiceCateBo; import com.ruoyi.isc.domain.vo.IscServiceCateVo; -import com.ruoyi.isc.domain.IscServiceCate; import com.ruoyi.isc.mapper.IscServiceCateMapper; import com.ruoyi.isc.service.IIscServiceCateService; +import org.springframework.stereotype.Service; import java.util.*; import java.util.stream.Collectors; @@ -35,7 +36,6 @@ public class IscServiceCateServiceImpl extends ServicePlusImpl> cateServiceMap = isServiceTree ? serviceList.stream() .collect(Collectors.groupingBy(IscService::getCateFullPath)) : null; - return TreeUtils.build(cates, (cate, tree) -> { + NodeParser parser = (cate, tree) -> { tree.setId(cate.getCateId()); tree.setParentId(cate.getParentId()); tree.setName(cate.getCateName()); @@ -166,8 +166,10 @@ public class IscServiceCateServiceImpl extends ServicePlusImpl services = cateServiceMap.get(cate.getFullPath()); if(CollectionUtil.isEmpty(services)) { + tree.putExtra(TreeUtils.FIELD_NODE_EXIST, true); return; } for (int index = 0; index < services.size(); index++) @@ -182,14 +184,18 @@ public class IscServiceCateServiceImpl extends ServicePlusImpl batchCateName(List list) { diff --git a/ruoyi-ui/src/views/isc/application/index.vue b/ruoyi-ui/src/views/isc/application/index.vue index 3d64af5c1..02b337d36 100644 --- a/ruoyi-ui/src/views/isc/application/index.vue +++ b/ruoyi-ui/src/views/isc/application/index.vue @@ -74,7 +74,7 @@ - +