| | |
| | | import com.xiaopeng.api.feignClient.account.SysGroupMenuClient; |
| | | import com.xiaopeng.api.feignClient.account.SysRoleClient; |
| | | import com.xiaopeng.api.feignClient.account.SysUserRoleClient; |
| | | import com.xiaopeng.api.feignClient.account.XpOperationsRoleClient; |
| | | import com.xiaopeng.api.model.account.SysRole; |
| | | import com.xiaopeng.api.model.account.SysUserRole; |
| | | import com.xiaopeng.api.model.account.XpOperationsRole; |
| | | import com.xiaopeng.api.model.operation.SysMenu; |
| | | import com.xiaopeng.common.core.domain.R; |
| | | import com.xiaopeng.common.security.service.TokenService; |
| | |
| | | @Autowired |
| | | private SysGroupMenuClient sysGroupMenuClient; |
| | | |
| | | @Autowired |
| | | private XpOperationsRoleClient xpOperationsRoleClient; |
| | | |
| | | /** |
| | | * 根据菜单ID列表查询菜单列表 |
| | | * |
| | |
| | | } |
| | | |
| | | @Override |
| | | public List<SysMenu> getMenuTree() { |
| | | List<SysMenu> all = list(); |
| | | public List<SysMenu> getMenuTree(Integer type) { |
| | | List<SysMenu> all = lambdaQuery().eq(SysMenu::getGroupType, type).list(); |
| | | if (all == null || all.isEmpty()) { |
| | | return Collections.emptyList(); |
| | | } |
| | |
| | | return Collections.emptyList(); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public List<SysMenu> getAppPermission() { |
| | | // 1. 获取当前登录用户ID |
| | | Long operationUserId = tokenService.getLoginOperationUser().getId(); |
| | | if (operationUserId == null) { |
| | | log.warn("获取当前登录用户ID失败"); |
| | | return Collections.emptyList(); |
| | | } |
| | | |
| | | // 2. 查询运维APP菜单(group_type=2) |
| | | List<SysMenu> appMenus = this.lambdaQuery() |
| | | .eq(SysMenu::getGroupType, 2) |
| | | .list(); |
| | | if (appMenus == null || appMenus.isEmpty()) { |
| | | return Collections.emptyList(); |
| | | } |
| | | |
| | | // 3. 查询运维人员关联的角色(一个用户可多个角色) |
| | | Set<Long> roleIds = new HashSet<>(); |
| | | try { |
| | | R<List<XpOperationsRole>> rolesResult = xpOperationsRoleClient.listByOperationUserId(operationUserId); |
| | | if (rolesResult != null && rolesResult.getData() != null) { |
| | | for (XpOperationsRole r : rolesResult.getData()) { |
| | | if (r != null && r.getRoleId() != null) { |
| | | roleIds.add(r.getRoleId()); |
| | | } |
| | | } |
| | | } |
| | | } catch (Exception e) { |
| | | log.error("查询运维人员角色关联异常, operationUserId={}", operationUserId, e); |
| | | } |
| | | |
| | | // 4. 通过 role -> groupId -> group_menu 获取允许的菜单ID集合 |
| | | Set<Long> allowedMenuIds = new HashSet<>(); |
| | | if (!roleIds.isEmpty()) { |
| | | Set<Long> groupIds = new HashSet<>(); |
| | | for (Long roleId : roleIds) { |
| | | try { |
| | | R<SysRole> roleResult = sysRoleClient.getRoleById(roleId); |
| | | if (roleResult != null && roleResult.getData() != null && roleResult.getData().getGroupId() != null) { |
| | | groupIds.add(roleResult.getData().getGroupId()); |
| | | } |
| | | } catch (Exception e) { |
| | | log.error("查询角色信息异常, roleId={}", roleId, e); |
| | | } |
| | | } |
| | | |
| | | for (Long groupId : groupIds) { |
| | | try { |
| | | R<List<Long>> menuIdsResult = sysGroupMenuClient.selectMenuIdsByGroupId(groupId); |
| | | if (menuIdsResult != null && menuIdsResult.getData() != null) { |
| | | allowedMenuIds.addAll(menuIdsResult.getData()); |
| | | } |
| | | } catch (Exception e) { |
| | | log.error("查询权限组菜单ID异常, groupId={}", groupId, e); |
| | | } |
| | | } |
| | | } |
| | | |
| | | // 5. 仅保留运维APP的菜单ID,避免无关ID影响 visible |
| | | Set<Long> appMenuIds = appMenus.stream() |
| | | .filter(Objects::nonNull) |
| | | .map(SysMenu::getId) |
| | | .filter(Objects::nonNull) |
| | | .collect(Collectors.toSet()); |
| | | allowedMenuIds.retainAll(appMenuIds); |
| | | |
| | | // 6. 组装树形结构,并用 visible 体现权限可见性(0可见 1不可见) |
| | | return buildAppMenuTreeWithVisible(appMenus, allowedMenuIds); |
| | | } |
| | | |
| | | private List<SysMenu> buildAppMenuTreeWithVisible(List<SysMenu> menus, Set<Long> allowedMenuIds) { |
| | | Map<Long, SysMenu> idMap = new HashMap<>(); |
| | | for (SysMenu m : menus) { |
| | | if (m != null && m.getId() != null) { |
| | | idMap.put(m.getId(), m); |
| | | } |
| | | } |
| | | |
| | | Map<Long, List<SysMenu>> childrenMap = menus.stream() |
| | | .filter(Objects::nonNull) |
| | | .filter(m -> m.getId() != null) |
| | | .collect(Collectors.groupingBy(m -> { |
| | | Long pid = m.getParentId(); |
| | | return pid == null ? 0L : pid; |
| | | })); |
| | | |
| | | // 根节点:parentId 为 0/null,或父节点不在当前 group_type=2 集合内 |
| | | List<SysMenu> roots = menus.stream() |
| | | .filter(Objects::nonNull) |
| | | .filter(m -> m.getId() != null) |
| | | .filter(m -> { |
| | | Long pid = m.getParentId(); |
| | | if (pid == null || pid == 0L) { |
| | | return true; |
| | | } |
| | | return !idMap.containsKey(pid); |
| | | }) |
| | | .sorted(Comparator.comparing(SysMenu::getOrderNum, Comparator.nullsLast(Integer::compareTo))) |
| | | .collect(Collectors.toList()); |
| | | |
| | | for (SysMenu root : roots) { |
| | | fillChildrenAndVisible(root, childrenMap, allowedMenuIds, new HashSet<>()); |
| | | } |
| | | return roots; |
| | | } |
| | | |
| | | private boolean fillChildrenAndVisible(SysMenu node, Map<Long, List<SysMenu>> childrenMap, Set<Long> allowedMenuIds, Set<Long> path) { |
| | | Long id = node.getId(); |
| | | if (id != null && !path.add(id)) { |
| | | boolean visible = allowedMenuIds.contains(id); |
| | | node.setChildren(Collections.emptyList()); |
| | | node.setVisible(visible ? "0" : "1"); |
| | | return visible; |
| | | } |
| | | List<SysMenu> children = childrenMap.getOrDefault(id == null ? 0L : id, Collections.emptyList()).stream() |
| | | .filter(Objects::nonNull) |
| | | .sorted(Comparator.comparing(SysMenu::getOrderNum, Comparator.nullsLast(Integer::compareTo))) |
| | | .collect(Collectors.toList()); |
| | | |
| | | boolean anyChildVisible = false; |
| | | for (SysMenu child : children) { |
| | | anyChildVisible |= fillChildrenAndVisible(child, childrenMap, allowedMenuIds, path); |
| | | } |
| | | node.setChildren(children); |
| | | |
| | | boolean selfVisible = id != null && allowedMenuIds.contains(id); |
| | | boolean visible = selfVisible || anyChildVisible; |
| | | node.setVisible(visible ? "0" : "1"); |
| | | if (id != null) { |
| | | path.remove(id); |
| | | } |
| | | return visible; |
| | | } |
| | | } |