feat(backend-java): 后台菜单接口改为返回菜单树并适配 admin-vue
菜单接口 /api/admin/current-user/menus 由扁平 route 列表改为含父子 层级的菜单树;权限标识用 column_key,页面地址用 route 单独下发; /admin 与 / 入口重定向到 admin-vue。
This commit is contained in:
+75
-10
@@ -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<Map<String, Object>> currentUserMenus(HttpServletRequest request) {
|
||||
AdminUserEntity operator = adminAuthSupport.requireAdminOrInternal(request);
|
||||
List<PermissionMenuItemVo> menus = permissionMenuService.getUserColumnPermissions(
|
||||
operator, operator.getId(), PermissionMenuService.MENU_TYPE_ADMIN);
|
||||
List<Map<String, String>> items = new ArrayList<>(menus.size());
|
||||
return ApiResponse.success(Map.of("items", buildAdminMenuTree(menus)));
|
||||
}
|
||||
|
||||
/**
|
||||
* 将 columns 的有效权限项转换为新版后台菜单树。权限 key 使用 column_key,
|
||||
* 页面地址单独使用 route;这样后续调整 Vue URL 时不会改变授权标识。
|
||||
*/
|
||||
private List<Map<String, Object>> buildAdminMenuTree(List<PermissionMenuItemVo> menus) {
|
||||
Map<Long, Map<String, Object>> nodes = new HashMap<>();
|
||||
for (PermissionMenuItemVo menu : menus) {
|
||||
if (menu.getRoutePath() == null || menu.getRoutePath().isBlank()) {
|
||||
if (menu.getId() == null) {
|
||||
continue;
|
||||
}
|
||||
Map<String, String> item = new LinkedHashMap<>();
|
||||
item.put("route_path", menu.getRoutePath());
|
||||
item.put("name", menu.getName() == null ? menu.getRoutePath() : menu.getName());
|
||||
items.add(item);
|
||||
Map<String, Object> 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<Map<String, Object>>());
|
||||
nodes.put(menu.getId(), node);
|
||||
}
|
||||
return ApiResponse.success(Map.of("items", items));
|
||||
List<Map<String, Object>> roots = new ArrayList<>();
|
||||
for (PermissionMenuItemVo menu : menus) {
|
||||
Map<String, Object> node = nodes.get(menu.getId());
|
||||
if (node == null) continue;
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Map<String, Object>> children = (List<Map<String, Object>>) node.get("children");
|
||||
if (menu.getParentId() != null && nodes.containsKey(menu.getParentId())) {
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Map<String, Object>> parentChildren = (List<Map<String, Object>>) nodes.get(menu.getParentId()).get("children");
|
||||
parentChildren.add(node);
|
||||
} else {
|
||||
roots.add(node);
|
||||
}
|
||||
}
|
||||
Comparator<Map<String, Object>> order = Comparator
|
||||
.comparingInt((Map<String, Object> node) -> ((Number) node.get("sort")).intValue())
|
||||
.thenComparing(node -> String.valueOf(node.get("key")));
|
||||
sortMenuTree(roots, order);
|
||||
stripSort(roots);
|
||||
return roots;
|
||||
}
|
||||
|
||||
private void sortMenuTree(List<Map<String, Object>> nodes,
|
||||
Comparator<Map<String, Object>> order) {
|
||||
nodes.sort(order);
|
||||
for (Map<String, Object> node : nodes) {
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Map<String, Object>> children = (List<Map<String, Object>>) node.get("children");
|
||||
sortMenuTree(children, order);
|
||||
}
|
||||
}
|
||||
|
||||
private void stripSort(List<Map<String, Object>> nodes) {
|
||||
for (Map<String, Object> node : nodes) {
|
||||
node.remove("sort");
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Map<String, Object>> children = (List<Map<String, Object>>) 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;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user