feat(admin): 管理后台页面同源托管到 Java(classpath:/static)并接入 Java 登录

把 Flask web_source/admin.html 与 static/* 拷入 backend-java resources/static,
经 Spring 默认静态映射同源服务于 api.aishufu.top:18080;/static 根相对引用通过
static/static 子目录镜像零改动保持。页面登录改直连 Java POST /login(cookie+
浏览器持久 deviceId),登出走 Java POST /logout。新增 AdminConsoleController:
GET /、/admin、/login、/logout 页面转发,及 /api/admin/current-user、
/current-user/menus(管理员角色,返回旧前端契约的 item/items 形状)。admin.js
增加全局 fetch 响应解包(ApiResponse data 展开且保留 data 键,401 跳登录)与
URL 兼容映射层(把 Flask 别名统一到 Java 规范路径)。
This commit is contained in:
2026-09-04 10:21:24 +08:00
parent e5909c9977
commit bc5d5b3d2e
8 changed files with 15032 additions and 0 deletions
@@ -0,0 +1,88 @@
package com.nanri.aiimage.modules.admin.controller;
import com.nanri.aiimage.common.api.ApiResponse;
import com.nanri.aiimage.modules.admin.support.AdminAuthSupport;
import com.nanri.aiimage.modules.permission.model.entity.AdminUserEntity;
import com.nanri.aiimage.modules.permission.model.vo.PermissionMenuItemVo;
import com.nanri.aiimage.modules.permission.service.PermissionMenuService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
* 管理后台页面与"当前管理员"自描述接口(Java 收敛自 Flask 侧 web_source/admin.html 的依赖)。
*
* <p>页面经静态资源托管于同源(classpath:/static 下的 admin.html / login.html),
* 登录/登出沿用 auth 模块(POST /login、POST /logout)。这里提供 GET 页面转发与
* /api/admin/current-user、/current-user/menus,保持与旧前端契约一致({item}、{items})。
*/
@RestController
@RequiredArgsConstructor
@Tag(name = "管理后台页面", description = "管理后台静态页路由与当前管理员信息")
public class AdminConsoleController {
private final AdminAuthSupport adminAuthSupport;
private final PermissionMenuService permissionMenuService;
@GetMapping("/")
@Operation(summary = "根路径跳管理后台", hidden = true)
public String root() {
return "redirect:/admin.html";
}
@GetMapping("/admin")
@Operation(summary = "管理后台入口", hidden = true)
public String adminPage() {
return "redirect:/admin.html";
}
@GetMapping("/login")
@Operation(summary = "登录页入口", hidden = true)
public String loginPage() {
return "forward:/login.html";
}
@GetMapping("/logout")
@Operation(summary = "登出 GET 兜底(POST 走 auth 模块)", hidden = true)
public String logoutPage() {
return "redirect:/login.html";
}
@GetMapping("/api/admin/current-user")
@Operation(summary = "当前登录管理员概要")
public ApiResponse<Map<String, Object>> currentUser(HttpServletRequest request) {
AdminUserEntity operator = adminAuthSupport.requireAdminOrInternal(request);
Map<String, Object> item = new LinkedHashMap<>();
item.put("id", operator.getId());
item.put("username", operator.getUsername() == null ? "" : operator.getUsername());
item.put("role", adminAuthSupport.currentRole(operator));
return ApiResponse.success(Map.of("item", item));
}
@GetMapping("/api/admin/current-user/menus")
@Operation(summary = "当前登录管理员的可见菜单(扁平 route_path/name 列表)")
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());
for (PermissionMenuItemVo menu : menus) {
if (menu.getRoutePath() == null || menu.getRoutePath().isBlank()) {
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);
}
return ApiResponse.success(Map.of("items", items));
}
}