package com.iailab.module.system.convert.app; import cn.hutool.core.collection.CollUtil; import com.iailab.module.system.api.app.dto.AppMenuRespDTO; import com.iailab.module.system.dal.dataobject.app.AppMenuDO; import com.iailab.module.system.enums.permission.MenuTypeEnum; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; import org.slf4j.LoggerFactory; import java.util.*; import static com.iailab.framework.common.util.collection.CollectionUtils.filterList; @Mapper public interface AppConvert { AppConvert INSTANCE = Mappers.getMapper(AppConvert.class); AppMenuRespDTO convertTreeNode(AppMenuDO menu); /** * 将菜单列表,构建成菜单树 * * @param menuList 菜单列表 * @return 菜单树 */ default List buildMenuTree(Long id, List menuList) { if (CollUtil.isEmpty(menuList)) { return Collections.emptyList(); } // 移除按钮 menuList.removeIf(menu -> menu.getType().equals(MenuTypeEnum.BUTTON.getType())); // 排序,保证菜单的有序性 menuList.sort(Comparator.comparing(AppMenuDO::getSort)); // 构建菜单树 // 使用 LinkedHashMap 的原因,是为了排序 。实际也可以用 Stream API ,就是太丑了。 Map treeNodeMap = new LinkedHashMap<>(); menuList.forEach(menu -> treeNodeMap.put(menu.getId(), AppConvert.INSTANCE.convertTreeNode(menu))); // 处理父子关系 treeNodeMap.values().stream().filter(node -> !node.getParentId().equals(id)).forEach(childNode -> { // 获得父节点 AppMenuRespDTO parentNode = treeNodeMap.get(childNode.getParentId()); if (parentNode == null) { LoggerFactory.getLogger(getClass()).error("[buildRouterTree][resource({}) 找不到父资源({})]", childNode.getId(), childNode.getParentId()); return; } // 将自己添加到父节点中 if (parentNode.getChildren() == null) { parentNode.setChildren(new ArrayList<>()); } parentNode.getChildren().add(childNode); }); // 获得到所有的根节点 return filterList(treeNodeMap.values(), node -> id.equals(node.getParentId())); } }