84 lines
4.0 KiB
Markdown
84 lines
4.0 KiB
Markdown
# 08 Java 菜单树与 Flyway 权限迁移
|
||
|
||
## 模块职责
|
||
|
||
将 Java 权限模型作为后台菜单唯一来源,继续使用 `columns` 和 `user_column_permission`,把现有扁平有效菜单转换为后端维护的树形菜单,并通过 Flyway 把旧 route_path 迁移到新版 History 路由。
|
||
|
||
本模块不引入按钮级权限,不新增 action 表。
|
||
|
||
## 依赖关系
|
||
|
||
上游:现有数据库 `columns`、`user_column_permission`、`users`;`PermissionMenuService`。
|
||
|
||
下游:`AdminConsoleController.currentUserMenus`、Vue `fetchAdminMenuTree`、`MenusPage`。
|
||
|
||
相关文件和符号:
|
||
|
||
- `backend-java/.../permission/service/PermissionMenuService.java:getUserColumnPermissions`
|
||
- `backend-java/.../permission/controller/PermissionMenuController.java:listMenus/createMenu/updateMenu/deleteMenu/reorderColumns`
|
||
- `backend-java/.../permission/model/entity/PermissionMenuEntity.java`
|
||
- `backend-java/.../permission/model/entity/UserColumnPermissionEntity.java`
|
||
- `backend-java/.../admin/controller/AdminConsoleController.java:currentUserMenus`
|
||
- `backend-java/src/main/resources/db/V100__admin_menu_frontend_routes.sql`(目标迁移文件)
|
||
|
||
## 核心接口:原实现 → 目标实现
|
||
|
||
| 内容 | 原实现 | 目标实现 |
|
||
|---|---|---|
|
||
| 当前用户菜单 | `List<PermissionMenuItemVo>` 扁平列表 | 树形 `items`,页面节点含 `key/name/route` |
|
||
| 有效权限展开 | `PermissionMenuService.getUserColumnPermissions` | 保留,作为树输入;不在 Controller 重新实现授权规则 |
|
||
| 菜单存储 | `columns.column_key` + `route_path` | `column_key` 保持稳定;`route_path` 改为 Vue path |
|
||
| 用户授权 | `user_column_permission` | 保持不变 |
|
||
| 菜单迁移 | 运行时 initializer 的默认菜单补齐 | Flyway 正式更新既有 admin route_path |
|
||
| 权限菜单 CRUD | 旧 API 字段 | API 路径保持;页面使用树/表格适配器 |
|
||
|
||
## 内部结构\n\n`PermissionMenuService` 负责有效权限集合,`AdminConsoleController` 负责 DTO 树组装,Flyway 负责 route_path 数据迁移,`PermissionMenuController` 负责菜单管理 CRUD。\n\n## 目标树组装规则
|
||
|
||
1. 先由 `PermissionMenuService` 得到当前用户有效菜单集合。
|
||
2. 以 `id` 建立节点索引。
|
||
3. 用 `parent_id` 将子节点挂到父节点。
|
||
4. 按 `sort_order`、再按稳定 key 排序。
|
||
5. 分组节点可以无 route;页面节点带 route。
|
||
6. 只返回当前用户有效节点,禁止返回全量菜单后由前端过滤。
|
||
|
||
## 类型映射
|
||
|
||
| 数据库/旧 DTO | 目标菜单 DTO |
|
||
|---|---|
|
||
| `column_key` | `key` |
|
||
| `name` | `name` |
|
||
| `route_path` | `route` |
|
||
| `parent_id` | `children` 关系 |
|
||
| `sort_order` | 后端排序值 |
|
||
| `menu_type=admin` | 后台菜单域 |
|
||
|
||
## Flyway 迁移内容
|
||
|
||
目标迁移按 `column_key` 更新 `route_path`,示例:
|
||
|
||
- `admin_users` → `account/users`
|
||
- `admin_columns` → `account/menus`
|
||
- `admin_group_manage` → `account/groups`
|
||
- `admin_dedupe_total_data` → `asin-center/registry`
|
||
- `admin_shop_manage` → `shop-center/shops`
|
||
- `admin_history` → `records/history`
|
||
- `admin_version` → `records/software-version`
|
||
|
||
迁移必须:
|
||
|
||
- 可重复执行或由 Flyway 保证版本只执行一次。
|
||
- 不删除 `user_column_permission`。
|
||
- 不修改既有 `column_key`,避免 Java 业务鉴权常量失效。
|
||
- 迁移前后对比每个用户的有效菜单 key 集合。
|
||
- 检查 `(menu_type, route_path)` 唯一约束。
|
||
|
||
## 迁移/实现注意事项
|
||
|
||
1. `PermissionMenuSchemaInitializer` 仍可负责缺失基础表/默认数据兜底,但不能取代一次性数据迁移。
|
||
2. Controller 不得根据当前请求头、User-Agent 或查询参数返回不同菜单结构。
|
||
3. 树构造不能把同一个节点挂到多个父节点;发现脏数据应记录错误并阻止上线。
|
||
4. 菜单分组虚拟 route 不能被当作页面路由。
|
||
5. 新版前端不再兼容旧 route/hash,但权限 key 保持稳定,这两件事必须区分。
|
||
6. 菜单 CRUD 新增页面时必须同时提供稳定 `column_key` 和 Vue `route_path`。
|
||
|