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 org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -35,13 +37,13 @@ public class AdminConsoleController {
|
|||||||
@GetMapping("/")
|
@GetMapping("/")
|
||||||
@Operation(summary = "根路径跳管理后台", hidden = true)
|
@Operation(summary = "根路径跳管理后台", hidden = true)
|
||||||
public String root() {
|
public String root() {
|
||||||
return "redirect:/admin.html";
|
return "redirect:/admin-vue/";
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/admin")
|
@GetMapping("/admin")
|
||||||
@Operation(summary = "管理后台入口", hidden = true)
|
@Operation(summary = "管理后台入口", hidden = true)
|
||||||
public String adminPage() {
|
public String adminPage() {
|
||||||
return "redirect:/admin.html";
|
return "redirect:/admin-vue/";
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/login")
|
@GetMapping("/login")
|
||||||
@@ -68,21 +70,84 @@ public class AdminConsoleController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/api/admin/current-user/menus")
|
@GetMapping("/api/admin/current-user/menus")
|
||||||
@Operation(summary = "当前登录管理员的可见菜单(扁平 route_path/name 列表)")
|
@Operation(summary = "当前登录管理员的可见后台菜单树")
|
||||||
public ApiResponse<Map<String, Object>> currentUserMenus(HttpServletRequest request) {
|
public ApiResponse<Map<String, Object>> currentUserMenus(HttpServletRequest request) {
|
||||||
AdminUserEntity operator = adminAuthSupport.requireAdminOrInternal(request);
|
AdminUserEntity operator = adminAuthSupport.requireAdminOrInternal(request);
|
||||||
List<PermissionMenuItemVo> menus = permissionMenuService.getUserColumnPermissions(
|
List<PermissionMenuItemVo> menus = permissionMenuService.getUserColumnPermissions(
|
||||||
operator, operator.getId(), PermissionMenuService.MENU_TYPE_ADMIN);
|
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) {
|
for (PermissionMenuItemVo menu : menus) {
|
||||||
if (menu.getRoutePath() == null || menu.getRoutePath().isBlank()) {
|
if (menu.getId() == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Map<String, String> item = new LinkedHashMap<>();
|
Map<String, Object> node = new LinkedHashMap<>();
|
||||||
item.put("route_path", menu.getRoutePath());
|
node.put("key", menu.getColumnKey() == null ? String.valueOf(menu.getId()) : menu.getColumnKey());
|
||||||
item.put("name", menu.getName() == null ? menu.getRoutePath() : menu.getName());
|
node.put("name", menu.getName() == null ? "未命名菜单" : menu.getName());
|
||||||
items.add(item);
|
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