diff --git a/client-api/src/main/java/org/jiayunet/pojo/vo/RouteMenuVo.java b/client-api/src/main/java/org/jiayunet/pojo/vo/RouteMenuVo.java
index 3234af4..a13fa6e 100644
--- a/client-api/src/main/java/org/jiayunet/pojo/vo/RouteMenuVo.java
+++ b/client-api/src/main/java/org/jiayunet/pojo/vo/RouteMenuVo.java
@@ -52,6 +52,11 @@ public class RouteMenuVo {
*/
private Integer sortOrder;
+ /**
+ * 是否有使用权限:true=可用 false=无权限
+ */
+ private Boolean accessible;
+
/**
* 子菜单
*/
diff --git a/client-api/src/main/java/org/jiayunet/service/RouteMenuService.java b/client-api/src/main/java/org/jiayunet/service/RouteMenuService.java
index ab5c2b1..200cae9 100644
--- a/client-api/src/main/java/org/jiayunet/service/RouteMenuService.java
+++ b/client-api/src/main/java/org/jiayunet/service/RouteMenuService.java
@@ -92,77 +92,37 @@ public class RouteMenuService {
}
/**
- * 获取用户有效路由菜单(树形结构,支持多级菜单)
- *
1. 查询所有启用菜单 2. 收集公开免费菜单ID 3. 查询用户有效库存合并菜单ID 4. 补充父节点 5. 转VO构建树形结构
+ * 获取用户路由菜单(树形结构,全量返回,标记权限状态)
+ * 1. 查询所有启用菜单 2. 查询用户有效库存转为ID集合 3. 遍历菜单判断accessible 4. 构建树形结构
*
* @param userId 用户ID
- * @return 树形路由菜单
+ * @return 树形路由菜单(含权限标记)
*/
public List getUserRoutes(Long userId) {
- // 一次查出所有启用的菜单
- List allMenus = routeMenuMapper.selectList(
- new LambdaQueryWrapper().eq(RouteMenu::getStatus, 1));
-
+ // 1. 查所有启用菜单
+ List allMenus = routeMenuMapper.selectList(new LambdaQueryWrapper().eq(RouteMenu::getStatus, 1));
if (allMenus.isEmpty()) {
return Collections.emptyList();
}
- Map menuMap = allMenus.stream()
- .collect(Collectors.toMap(RouteMenu::getId, m -> m));
-
- // 收集公开菜单ID
- Set needIds = allMenus.stream()
- .filter(m -> m.getOpenAccess() != null && m.getOpenAccess() == 1)
- .map(RouteMenu::getId)
- .collect(Collectors.toSet());
-
- // 查询用户有效库存(不限时 或 未过期)
+ // 2. 查用户有效库存,转为 routeId 集合
Instant now = Instant.now();
List stocks = userRouteMenuStockMapper.selectList(
new LambdaQueryWrapper()
.eq(UserRouteMenuStock::getUserId, userId)
- .and(w -> w
- .eq(UserRouteMenuStock::getTimeLimit, 0)
- .or()
- .gt(UserRouteMenuStock::getExpireTime, now)
- )
- );
+ .and(w -> w.eq(UserRouteMenuStock::getTimeLimit, 0).or().gt(UserRouteMenuStock::getExpireTime, now)));
+ Set stockRouteIds = stocks == null ? Collections.emptySet() : stocks.stream().map(UserRouteMenuStock::getRouteId).collect(Collectors.toSet());
- // 合并库存中有权限的菜单ID
- if (stocks != null && !stocks.isEmpty()) {
- stocks.stream()
- .map(UserRouteMenuStock::getRouteId)
- .forEach(needIds::add);
- }
-
- if (needIds.isEmpty()) {
- return Collections.emptyList();
- }
-
- // 补充父节点
- Set allNeedIds = new HashSet<>(needIds);
- for (Long routeId : needIds) {
- RouteMenu current = menuMap.get(routeId);
- while (current != null && current.getParentId() != 0) {
- allNeedIds.add(current.getParentId());
- current = menuMap.get(current.getParentId());
- }
- }
-
- // 转VO
- List voList = allMenus.stream()
- .filter(menu -> allNeedIds.contains(menu.getId()))
- .map(menu -> {
- RouteMenuVo vo = new RouteMenuVo();
- BeanUtils.copyProperties(menu, vo);
- return vo;
- })
- .toList();
-
- // 构建树形结构
- Map> parentMap = voList.stream()
- .collect(Collectors.groupingBy(RouteMenuVo::getParentId));
+ // 3. 遍历菜单,判断 accessible
+ List voList = allMenus.stream().map(menu -> {
+ RouteMenuVo vo = new RouteMenuVo();
+ BeanUtils.copyProperties(menu, vo);
+ vo.setAccessible(menu.getOpenAccess() != null && menu.getOpenAccess() == 1 || stockRouteIds.contains(menu.getId()));
+ return vo;
+ }).toList();
+ // 4. 构建树形结构
+ Map> parentMap = voList.stream().collect(Collectors.groupingBy(RouteMenuVo::getParentId));
voList.forEach(vo -> {
List children = parentMap.get(vo.getId());
if (children != null) {
@@ -170,10 +130,6 @@ public class RouteMenuService {
vo.setChildren(children);
}
});
-
- return voList.stream()
- .filter(vo -> vo.getParentId() == 0)
- .sorted(Comparator.comparingInt(RouteMenuVo::getSortOrder))
- .collect(Collectors.toList());
+ return voList.stream().filter(vo -> vo.getParentId() == 0).sorted(Comparator.comparingInt(RouteMenuVo::getSortOrder)).collect(Collectors.toList());
}
}