| | |
| | | package com.ruoyi.system.service.impl; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.Arrays; |
| | | import java.util.HashSet; |
| | | import java.util.Iterator; |
| | | import java.util.LinkedList; |
| | | import java.util.List; |
| | | import java.util.Set; |
| | | import java.util.*; |
| | | import java.util.stream.Collectors; |
| | | |
| | | import com.ruoyi.system.pojo.vo.MenuTreeVO; |
| | | import org.springframework.beans.BeanUtils; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Service; |
| | | import com.ruoyi.common.constant.Constants; |
| | |
| | | return StringUtils.replaceEach(path, new String[] { Constants.HTTP, Constants.HTTPS, Constants.WWW, ".", ":" }, |
| | | new String[] { "", "", "", "/", "/" }); |
| | | } |
| | | |
| | | @Override |
| | | public List<MenuTreeVO> tree(Long userId) { |
| | | // 构建菜单树 |
| | | return buildMenuTree(userId); |
| | | } |
| | | |
| | | /** |
| | | * 构建菜单树(递归实现) |
| | | * @return 菜单树列表 |
| | | */ |
| | | public List<MenuTreeVO> buildMenuTree(Long userId) { |
| | | // 1. 根据用户ID查询角色ID集合 |
| | | List<Long> roleList = roleMapper.selectRoleListByUserId(userId); |
| | | // 2. 查询角色关联的菜单ID |
| | | List<Long> menuIds = roleMenuMapper.selectMenuIdsByRoleIds(roleList); |
| | | // 获取所有菜单 |
| | | List<MenuTreeVO> rootMenus = menuMapper.getAllRootMenu(); |
| | | // 递归构建子菜单 |
| | | List<MenuTreeVO> list = rootMenus.stream() |
| | | .map(x -> convertToMenuTreeVO(x,menuIds)) |
| | | .collect(Collectors.toList()); |
| | | return list.stream().filter(this::shouldIncludeMenu).collect(Collectors.toList()); |
| | | |
| | | } |
| | | |
| | | /** |
| | | * 递归转换菜单并构建子菜单树 |
| | | */ |
| | | private MenuTreeVO convertToMenuTreeVO(MenuTreeVO menu,List<Long> menuIds) { |
| | | MenuTreeVO vo = new MenuTreeVO(); |
| | | BeanUtils.copyProperties(menu, vo, "children"); // 复制基本属性,忽略children字段 |
| | | |
| | | // 获取当前菜单的子菜单 |
| | | List<MenuTreeVO> childMenus = menuMapper.selectMenusByParentId(menu.getMenuId()); |
| | | |
| | | // 递归处理子菜单 |
| | | if (!childMenus.isEmpty()) { |
| | | childMenus = childMenus.stream() |
| | | .filter(x -> !("C".equals(x.getMenuType()) && !menuIds.contains(x.getMenuId()))) |
| | | .collect(Collectors.toList()); |
| | | |
| | | List<MenuTreeVO> filteredChildren = childMenus.stream() |
| | | .map(x -> convertToMenuTreeVO(x,menuIds)) |
| | | .filter(this::shouldIncludeMenu) // 过滤子菜单 |
| | | .collect(Collectors.toList()); |
| | | |
| | | vo.setChildren(filteredChildren); |
| | | } |
| | | |
| | | return vo; |
| | | } |
| | | |
| | | /** |
| | | * 判断菜单是否应该被包含在结果中 |
| | | * - 如果是M类型且没有子菜单,则不包含 |
| | | * - 否则包含 |
| | | */ |
| | | private boolean shouldIncludeMenu(MenuTreeVO menu) { |
| | | // 如果菜单类型是M(目录)且没有子菜单,则过滤掉 |
| | | return !("M".equals(menu.getMenuType()) && (menu.getChildren() == null || menu.getChildren().isEmpty())); |
| | | } |
| | | } |