diff --git a/backend-java/src/main/java/com/nanri/aiimage/modules/admin/controller/AdminConsoleController.java b/backend-java/src/main/java/com/nanri/aiimage/modules/admin/controller/AdminConsoleController.java index b8e775f1..d672f08f 100644 --- a/backend-java/src/main/java/com/nanri/aiimage/modules/admin/controller/AdminConsoleController.java +++ b/backend-java/src/main/java/com/nanri/aiimage/modules/admin/controller/AdminConsoleController.java @@ -13,6 +13,8 @@ import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import java.util.ArrayList; +import java.util.Comparator; +import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -35,13 +37,13 @@ public class AdminConsoleController { @GetMapping("/") @Operation(summary = "根路径跳管理后台", hidden = true) public String root() { - return "redirect:/admin.html"; + return "redirect:/admin-vue/"; } @GetMapping("/admin") @Operation(summary = "管理后台入口", hidden = true) public String adminPage() { - return "redirect:/admin.html"; + return "redirect:/admin-vue/"; } @GetMapping("/login") @@ -68,21 +70,84 @@ public class AdminConsoleController { } @GetMapping("/api/admin/current-user/menus") - @Operation(summary = "当前登录管理员的可见菜单(扁平 route_path/name 列表)") + @Operation(summary = "当前登录管理员的可见后台菜单树") public ApiResponse> currentUserMenus(HttpServletRequest request) { AdminUserEntity operator = adminAuthSupport.requireAdminOrInternal(request); List menus = permissionMenuService.getUserColumnPermissions( operator, operator.getId(), PermissionMenuService.MENU_TYPE_ADMIN); - List> items = new ArrayList<>(menus.size()); + return ApiResponse.success(Map.of("items", buildAdminMenuTree(menus))); + } + + /** + * 将 columns 的有效权限项转换为新版后台菜单树。权限 key 使用 column_key, + * 页面地址单独使用 route;这样后续调整 Vue URL 时不会改变授权标识。 + */ + private List> buildAdminMenuTree(List menus) { + Map> nodes = new HashMap<>(); for (PermissionMenuItemVo menu : menus) { - if (menu.getRoutePath() == null || menu.getRoutePath().isBlank()) { + if (menu.getId() == null) { continue; } - Map item = new LinkedHashMap<>(); - item.put("route_path", menu.getRoutePath()); - item.put("name", menu.getName() == null ? menu.getRoutePath() : menu.getName()); - items.add(item); + Map node = new LinkedHashMap<>(); + node.put("key", menu.getColumnKey() == null ? String.valueOf(menu.getId()) : menu.getColumnKey()); + node.put("name", menu.getName() == null ? "未命名菜单" : menu.getName()); + node.put("sort", menu.getSortOrder() == null ? 0 : menu.getSortOrder()); + String route = adminRoute(menu.getColumnKey(), menu.getRoutePath()); + if (route != null && !route.isBlank() && !route.startsWith("group-")) { + node.put("route", "/" + route.replaceFirst("^/", "")); + } + node.put("children", new ArrayList>()); + nodes.put(menu.getId(), node); } - return ApiResponse.success(Map.of("items", items)); + List> roots = new ArrayList<>(); + for (PermissionMenuItemVo menu : menus) { + Map node = nodes.get(menu.getId()); + if (node == null) continue; + @SuppressWarnings("unchecked") + List> children = (List>) node.get("children"); + if (menu.getParentId() != null && nodes.containsKey(menu.getParentId())) { + @SuppressWarnings("unchecked") + List> parentChildren = (List>) nodes.get(menu.getParentId()).get("children"); + parentChildren.add(node); + } else { + roots.add(node); + } + } + Comparator> order = Comparator + .comparingInt((Map node) -> ((Number) node.get("sort")).intValue()) + .thenComparing(node -> String.valueOf(node.get("key"))); + sortMenuTree(roots, order); + stripSort(roots); + return roots; + } + + private void sortMenuTree(List> nodes, + Comparator> order) { + nodes.sort(order); + for (Map node : nodes) { + @SuppressWarnings("unchecked") + List> children = (List>) node.get("children"); + sortMenuTree(children, order); + } + } + + private void stripSort(List> nodes) { + for (Map node : nodes) { + node.remove("sort"); + @SuppressWarnings("unchecked") + List> children = (List>) node.get("children"); + if (children.isEmpty()) node.remove("children"); + else stripSort(children); + } + } + + private String adminRoute(String columnKey, String storedRoute) { + if (columnKey == null) return storedRoute; + return switch (columnKey) { + case "admin_users" -> "account/users"; + case "admin_columns" -> "account/menus"; + case "admin_group_manage" -> "account/groups"; + default -> storedRoute; + }; } }