# 03 账号与权限页面 ## 模块职责 覆盖首批账号与权限页面:用户管理、菜单管理、数据权限分组。负责列表、筛选、分页、编辑/新增入口、菜单树展示和分组管理入口,但权限粒度仍只到页面菜单。 ## 依赖关系 上游:`02-session-menu-permission.md` 的用户和菜单状态;Java `AdminUserController`、`PermissionMenuController`、分组相关管理接口。 下游:`AdminLayout` 路由;后续业务页面使用用户选择器、分组数据。 旧页面来源: - `admin.html#panel-users` - `admin.html#panel-columns` - `admin.html#panel-group-manage` - `admin.js:loadUsers`、`bindUserActions` - `admin.js:loadColumns`、`bindColumnActions` - `admin.js:loadShopManageGroups`、`initShopManageGroupPanel` ## 核心接口:原实现 → 目标实现 | 功能 | 原实现 | 目标实现 | |---|---|---| | 用户列表 | Flask `list_users` / Java `AdminUserController.listUsers` | `UsersPage.vue` 调用 `GET /api/admin/users` | | 新建用户 | `create_user` / `AdminUserController.createUser` | `UsersPage` 的 Element Plus Dialog + `POST /api/admin/user` | | 编辑用户 | `update_user` / `AdminUserController.updateUser` | Dialog 表单 + `PUT /api/admin/user/{uid}` | | 删除用户 | `delete_user` / `AdminUserController.deleteUser` | `ElMessageBox` 确认 + `DELETE /api/admin/user/{uid}` | | 菜单列表 | `admin.js:loadColumns` | `MenusPage.vue` + `GET /api/admin/permission-menus?menuType=admin` | | 菜单新增/编辑/删除 | Flask/Java 菜单 CRUD | Element Plus Dialog/Tree + 对应 `permission-menus` API | | 菜单排序 | `bindColumnDragSort`、`persistColumnOrder` | 菜单树同级排序组件 + `POST /api/admin/column/reorder` | | 用户菜单授权 | 旧用户编辑中的权限树 | 用户编辑时调用 `GET/PUT /api/admin/permission-users/{uid}/column-permissions` | | 分组列表 | `loadShopManageGroups` | `GroupsPage.vue` + `/api/admin/shop-manage-groups` | ## 内部结构 ```text AccountPageGroup ├── UsersPage │ ├── UserFilterBar │ ├── UserTable │ ├── UserEditorDialog │ └── UserPermissionTree ├── MenusPage │ ├── MenuTreeTable │ ├── MenuEditorDialog │ └── SameLevelSortInteraction └── GroupsPage ├── GroupFilter/summary ├── GroupTable └── GroupEditorDialog ``` 页面级状态必须局部化: - 当前页数据。 - 筛选条件。 - 分页。 - Dialog/Drawer 可见状态。 - 表单草稿。 - 保存中的 loading。 Pinia 不保存这些业务表格状态。 ## 类型映射 | 原字段/概念 | 目标类型 | |---|---| | `userListBody` | `AdminUser[]` | | `userPagination` | `PaginationState` | | `columnTree` | `AdminMenuNode[]` / `PermissionMenuItem[]` | | `column_id` | `number` | | `created_by_id` | `number | null` | | `role` | 联合字面量或后端枚举映射 | | `grant_menu_routes` | `number[]` 的菜单 ID 授权请求 | ## 迁移/实现注意事项 1. 用户接口分页字段要按 Java 实际 VO 归一化,不能直接假设 Flask 字段命名。 2. 删除、创建、编辑继续保留后端权限校验;前端不添加按钮级权限体系。 3. 菜单管理必须区分 admin 菜单和 app 菜单,默认只操作 `menuType=admin`。 4. 菜单分组节点不应被当作可进入页面;叶子页面才产生 Router route。 5. 用户授权更新必须提交菜单 ID,而不是前端路由字符串,除非后端 API 明确支持 route。 6. 菜单迁移后 `column_key` 保持稳定,页面 URL 通过 `route_path` 变化。 7. 数据权限分组的业务 API 若仍以旧字段返回,必须在 `api/groups.ts` 适配为稳定的前端 DTO,禁止把兼容逻辑散落在表格模板中。