mirror of
https://gitee.com/dromara/RuoYi-Vue-Plus.git
synced 2026-03-14 18:02:01 +08:00
update 优化 使用动态规划优化菜单树的构建
This commit is contained in:
@@ -10,7 +10,9 @@ import lombok.NoArgsConstructor;
|
||||
import org.dromara.common.core.utils.reflect.ReflectUtils;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
@@ -28,6 +30,25 @@ public class TreeBuildUtils extends TreeUtil {
|
||||
*/
|
||||
public static final TreeNodeConfig DEFAULT_CONFIG = TreeNodeConfig.DEFAULT_CONFIG.setNameKey("label");
|
||||
|
||||
/**
|
||||
* 使用动态规划构建树形结构
|
||||
*
|
||||
* @param items 节点列表项
|
||||
* @param parentId 父节点ID
|
||||
* @param classifier 动态规划表分类函数
|
||||
* @param action 回溯动作
|
||||
* @param <K> 节点ID的类型
|
||||
* @param <T> 输入节点的类型
|
||||
* @return 构建好的树形结构列表
|
||||
*/
|
||||
public static <K, T> List<T> build(List<T> items, K parentId, Function<T, K> classifier, BiConsumer<T,Map<K, List<T>>> action) {
|
||||
// 构建动态规划表 (依据父ID分组)
|
||||
Map<K, List<T>> nodeTreeMaps = items.stream().collect(Collectors.groupingBy(classifier));
|
||||
// 回溯构建各级节点关系
|
||||
items.forEach(item -> action.accept(item, nodeTreeMaps));
|
||||
return nodeTreeMaps.get(parentId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建树形结构
|
||||
*
|
||||
|
||||
@@ -9,7 +9,6 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.dromara.common.core.constant.Constants;
|
||||
import org.dromara.common.core.constant.SystemConstants;
|
||||
import org.dromara.common.core.utils.MapstructUtils;
|
||||
import org.dromara.common.core.utils.StreamUtils;
|
||||
import org.dromara.common.core.utils.StringUtils;
|
||||
import org.dromara.common.core.utils.TreeBuildUtils;
|
||||
import org.dromara.common.satoken.utils.LoginHelper;
|
||||
@@ -27,11 +26,7 @@ import org.dromara.system.service.ISysMenuService;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* 菜单 业务层处理
|
||||
@@ -137,7 +132,17 @@ public class SysMenuServiceImpl implements ISysMenuService {
|
||||
.orderByAsc(SysMenu::getParentId)
|
||||
.orderByAsc(SysMenu::getOrderNum));
|
||||
}
|
||||
return getChildPerms(menus, Constants.TOP_PARENT_ID);
|
||||
|
||||
return TreeBuildUtils.build(menus, Constants.TOP_PARENT_ID, SysMenu::getParentId, (menu, nodeTreeMaps) -> {
|
||||
// 将当前节点的菜单ID用作父节点ID
|
||||
Long menuParentId = menu.getMenuId();
|
||||
// 从动态规划表中取出子节点列表
|
||||
// 如果不存在子节点,则返回一个空的列表,确保数据在进行JSON序列化时该字段的类型和结构是正确的
|
||||
List<SysMenu> childMenus = nodeTreeMaps.getOrDefault(menuParentId, Collections.emptyList());
|
||||
// 设置子节点
|
||||
// 如果存在根节点指向尾节点的情况,则会出现环形依赖。但在菜单表中基本不会出现这种情况...
|
||||
menu.setChildren(childMenus);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -382,38 +387,4 @@ public class SysMenuServiceImpl implements ISysMenuService {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据父节点的ID获取所有子节点
|
||||
*
|
||||
* @param list 分类表
|
||||
* @param parentId 传入的父节点ID
|
||||
* @return String
|
||||
*/
|
||||
private List<SysMenu> getChildPerms(List<SysMenu> list, Long parentId) {
|
||||
List<SysMenu> returnList = new ArrayList<>();
|
||||
for (SysMenu t : list) {
|
||||
// 一、根据传入的某个父节点ID,遍历该父节点的所有子节点
|
||||
if (t.getParentId().equals(parentId)) {
|
||||
recursionFn(list, t);
|
||||
returnList.add(t);
|
||||
}
|
||||
}
|
||||
return returnList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 递归列表
|
||||
*/
|
||||
private void recursionFn(List<SysMenu> list, SysMenu t) {
|
||||
// 得到子节点列表
|
||||
List<SysMenu> childList = StreamUtils.filter(list, n -> n.getParentId().equals(t.getMenuId()));
|
||||
t.setChildren(childList);
|
||||
for (SysMenu tChild : childList) {
|
||||
// 判断是否有子节点
|
||||
if (list.stream().anyMatch(n -> n.getParentId().equals(tChild.getMenuId()))) {
|
||||
recursionFn(list, tChild);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user