# 角色/用户/菜单管理详细设计文档 ## 1. 目标 基于当前项目已有的分层框架(model / dao / service / controller / views)新增以下能力: 1. 角色管理 - 角色表 - 权限表 - 用户角色关联表 - 角色权限关联能力 2. 用户管理 - 用户表 - 用户与角色分配 3. 菜单管理 - 菜单表 - 角色分配菜单 本次仅输出详细设计,不直接改业务代码。 --- ## 2. 当前项目框架观察 ### 2.1 现有分层风格 当前项目采用如下结构: - `app/api/model/*.py` - `app/api/dao/*.py` - `app/api/service/*.py` - `app/api/controller/*.py` - `app/api/views.py` ### 2.2 当前职责边界 #### model - 定义 SQLAlchemy 表模型 - 每个领域通常独立一个 model 文件 #### dao - 负责数据库增删改查 - 已有通用风格: - `create` - `update_by_id` - `get_by_id` - `list_by_filters` - `delete_by_id` #### service - 作为 controller 与 dao 之间的业务入口 - 目前多数是对 dao 的薄封装 - 适合放跨表组合查询、业务校验、聚合逻辑 #### controller - 负责参数获取、必填校验、字段映射、返回结构拼装 - 不应直接 `session.query(...)` #### views - Flask 路由层 - 负责 request 参数读取、ApiResponse 包装、session 生命周期控制 ### 2.3 当前接口命名风格 已有接口风格: - `/project/list` - `/project/detail` - `/project/create` - `/project/update` - `/project/delete` - `/product/list` - `/product/detail` - `/product/create` - `/product/update` - `/product/delete` 建议新增模块保持一致: - `/role/list` - `/role/detail` - `/role/create` - `/role/update` - `/role/delete` - `/user/list` - `/user/detail` - `/user/create` - `/user/update` - `/user/delete` - `/menu/tree` - `/menu/create` - `/menu/update` - `/menu/delete` - `/role/permission/*` - `/role/menu/*` - `/user/role/*` --- ## 3. 总体设计原则 1. 严格按当前框架分层 2. controller 不直接查数据库 3. 跨表聚合通过 service + dao 实现 4. 保持与现有字段风格一致: - 主键 `id` - 软删字段 `is_delete` - 时间字段 `created_time` / `updated_time` 5. 优先支持后台管理能力,不先引入复杂 RBAC 继承体系 6. 菜单、权限、角色、用户四个域解耦,但通过关联表关联 --- ## 4. 业务对象与关系 ### 4.1 核心对象 1. 用户 `user` 2. 角色 `role` 3. 权限 `permission` 4. 菜单 `menu` ### 4.2 关联对象 1. 用户角色关联 `user_role` 2. 角色权限关联 `role_permission` 3. 角色菜单关联 `role_menu` ### 4.3 关系说明 - 用户 : 角色 = 多对多 - 角色 : 权限 = 多对多 - 角色 : 菜单 = 多对多 - 菜单自身 = 树形父子关系 ### 4.4 推荐鉴权思路 后续登录后: - 用户拥有多个角色 - 角色聚合出权限集合 - 角色聚合出菜单集合 - 前端基于菜单渲染导航 - 后端基于权限点做接口校验 --- ## 5. 数据库表结构设计 以下采用 PostgreSQL 风格,保持与现有模型一致。 --- ## 5.1 用户表 `user` ### 用途 存储后台系统用户基础信息。 ### 建表字段 | 字段 | 类型 | 约束 | 说明 | |---|---|---|---| | id | BIGSERIAL | PK | 主键 | | username | VARCHAR(64) | UNIQUE NOT NULL | 登录用户名 | | real_name | VARCHAR(64) | | 真实姓名 | | password_hash | VARCHAR(255) | NOT NULL | 密码哈希 | | mobile | VARCHAR(32) | | 手机号 | | email | VARCHAR(128) | | 邮箱 | | avatar | VARCHAR(255) | | 头像地址 | | status | SMALLINT | DEFAULT 1 | 1启用 0禁用 | | last_login_time | TIMESTAMP | | 最后登录时间 | | created_by | BIGINT | | 创建人 | | is_delete | INTEGER | DEFAULT 0 | 软删标识 | | created_time | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | 创建时间 | | updated_time | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | 更新时间 | ### 索引建议 - unique(username) - index(status) - index(is_delete) --- ## 5.2 角色表 `role` ### 用途 定义系统角色。 ### 建表字段 | 字段 | 类型 | 约束 | 说明 | |---|---|---|---| | id | BIGSERIAL | PK | 主键 | | code | VARCHAR(64) | UNIQUE NOT NULL | 角色编码,如 admin/test_manager | | name | VARCHAR(64) | NOT NULL | 角色名称 | | description | TEXT | | 角色描述 | | status | SMALLINT | DEFAULT 1 | 1启用 0禁用 | | is_system | SMALLINT | DEFAULT 0 | 是否系统内置角色 | | created_by | BIGINT | | 创建人 | | is_delete | INTEGER | DEFAULT 0 | 软删标识 | | created_time | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | 创建时间 | | updated_time | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | 更新时间 | ### 索引建议 - unique(code) - index(status) - index(is_delete) --- ## 5.3 权限表 `permission` ### 用途 定义后端权限点。 ### 建表字段 | 字段 | 类型 | 约束 | 说明 | |---|---|---|---| | id | BIGSERIAL | PK | 主键 | | code | VARCHAR(128) | UNIQUE NOT NULL | 权限编码,如 project:create | | name | VARCHAR(128) | NOT NULL | 权限名称 | | module | VARCHAR(64) | | 所属模块,如 project/user/menu | | action | VARCHAR(64) | | 动作,如 list/create/update/delete | | description | TEXT | | 描述 | | status | SMALLINT | DEFAULT 1 | 1启用 0禁用 | | is_delete | INTEGER | DEFAULT 0 | 软删标识 | | created_time | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | 创建时间 | | updated_time | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | 更新时间 | ### 索引建议 - unique(code) - index(module) - index(status) --- ## 5.4 菜单表 `menu` ### 用途 定义前端菜单树。 ### 建表字段 | 字段 | 类型 | 约束 | 说明 | |---|---|---|---| | id | BIGSERIAL | PK | 主键 | | parent_id | BIGINT | DEFAULT 0 | 父菜单ID,0表示根节点 | | name | VARCHAR(64) | NOT NULL | 菜单名称 | | code | VARCHAR(64) | UNIQUE | 菜单编码 | | type | SMALLINT | DEFAULT 1 | 1目录 2菜单 3按钮 | | path | VARCHAR(255) | | 路由路径 | | component | VARCHAR(255) | | 前端组件路径 | | icon | VARCHAR(64) | | 图标 | | permission_code | VARCHAR(128) | | 对应权限编码,可选 | | sort | INTEGER | DEFAULT 0 | 排序 | | visible | SMALLINT | DEFAULT 1 | 1显示 0隐藏 | | status | SMALLINT | DEFAULT 1 | 1启用 0禁用 | | is_delete | INTEGER | DEFAULT 0 | 软删标识 | | created_time | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | 创建时间 | | updated_time | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | 更新时间 | ### 索引建议 - index(parent_id) - unique(code) - index(sort) --- ## 5.5 用户角色关联表 `user_role` ### 用途 维护用户与角色多对多关系。 ### 建表字段 | 字段 | 类型 | 约束 | 说明 | |---|---|---|---| | id | BIGSERIAL | PK | 主键 | | user_id | BIGINT | NOT NULL | 用户ID | | role_id | BIGINT | NOT NULL | 角色ID | | is_delete | INTEGER | DEFAULT 0 | 软删标识 | | created_time | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | 创建时间 | ### 约束建议 - unique(user_id, role_id) - index(user_id) - index(role_id) --- ## 5.6 角色权限关联表 `role_permission` ### 用途 维护角色与权限多对多关系。 ### 建表字段 | 字段 | 类型 | 约束 | 说明 | |---|---|---|---| | id | BIGSERIAL | PK | 主键 | | role_id | BIGINT | NOT NULL | 角色ID | | permission_id | BIGINT | NOT NULL | 权限ID | | is_delete | INTEGER | DEFAULT 0 | 软删标识 | | created_time | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | 创建时间 | ### 约束建议 - unique(role_id, permission_id) - index(role_id) - index(permission_id) --- ## 5.7 角色菜单关联表 `role_menu` ### 用途 维护角色与菜单多对多关系。 ### 建表字段 | 字段 | 类型 | 约束 | 说明 | |---|---|---|---| | id | BIGSERIAL | PK | 主键 | | role_id | BIGINT | NOT NULL | 角色ID | | menu_id | BIGINT | NOT NULL | 菜单ID | | is_delete | INTEGER | DEFAULT 0 | 软删标识 | | created_time | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | 创建时间 | ### 约束建议 - unique(role_id, menu_id) - index(role_id) - index(menu_id) --- ## 6. Model 设计 建议新增单独 model 文件: ### 6.1 `app/api/model/userModel.py` 包含: - `User` - `UserRole` ### 6.2 `app/api/model/rbacModel.py` 包含: - `Role` - `Permission` - `RolePermission` - `Menu` - `RoleMenu` > 也可以拆成 `roleModel.py` / `menuModel.py`,但按当前项目规模,两个文件足够。 ### 6.3 Model 设计原则 - 继承与现有一致:`declarative_base()` + `to_dict` - 字段命名与数据库列一致 - 关联关系不强制写 SQLAlchemy relationship,保持当前项目风格简洁 --- ## 7. DAO 设计 --- ## 7.1 `app/api/dao/userDao.py` ### 基础方法 - `create(session, model_cls, add_info)` - `update_by_id(session, model_cls, obj_id, update_info, soft_delete=True)` - `get_by_id(session, model_cls, obj_id, soft_delete=True)` - `list_by_filters(session, model_cls, filter_list, page=1, limit=20, order_column=None)` - `delete_by_id(session, model_cls, obj_id)` ### 用户专项方法 - `get_user_role_ids(session, user_id)` - `replace_user_roles(session, user_id, role_ids)` - `get_user_roles(session, user_ids)` --- ## 7.2 `app/api/dao/rbacDao.py` ### 基础方法 同现有通用 DAO 风格。 ### 角色/权限/菜单专项方法 - `get_role_permission_ids(session, role_id)` - `replace_role_permissions(session, role_id, permission_ids)` - `get_role_menu_ids(session, role_id)` - `replace_role_menus(session, role_id, menu_ids)` - `get_role_names_map(session, role_ids)` - `get_menu_tree_items(session, filter_list)` - `get_permission_list(session, filter_list, page, limit)` --- ## 8. Service 设计 --- ## 8.1 `app/api/service/userService.py` ### 职责 - 用户基本 CRUD - 用户与角色分配 - 聚合用户角色名称 ### 方法建议 - `create(session, model_cls, add_info)` - `update_by_id(session, model_cls, obj_id, update_info, soft_delete=True)` - `get_by_id(session, model_cls, obj_id, soft_delete=True)` - `list_by_filters(session, model_cls, filter_list, page_num=1, page_size=20, order_column=None)` - `delete_by_id(session, model_cls, obj_id)` - `assign_roles(session, user_id, role_ids)` - `get_user_role_ids(session, user_id)` - `get_user_roles_map(session, user_ids)` --- ## 8.2 `app/api/service/rbacService.py` ### 职责 - 角色 CRUD - 权限 CRUD - 菜单 CRUD - 角色绑定权限 - 角色绑定菜单 - 菜单树构建 ### 方法建议 - `create(session, model_cls, add_info)` - `update_by_id(session, model_cls, obj_id, update_info, soft_delete=True)` - `get_by_id(session, model_cls, obj_id, soft_delete=True)` - `list_by_filters(session, model_cls, filter_list, page_num=1, page_size=20, order_column=None)` - `delete_by_id(session, model_cls, obj_id)` - `assign_permissions(session, role_id, permission_ids)` - `assign_menus(session, role_id, menu_ids)` - `get_role_permission_ids(session, role_id)` - `get_role_menu_ids(session, role_id)` - `build_menu_tree(session, filters)` --- ## 9. Controller 设计 controller 仅负责: - 参数获取 `_get(...)` - 必填校验 - 字段映射 - 调用 service - 序列化返回 不得直接 `session.query(...)` --- ## 9.1 `app/api/controller/userController.py` ### 建议方法 - `user_list` - `user_detail` - `user_create` - `user_update` - `user_delete` - `user_role_assign` - `user_role_list` ### 返回增强建议 `user_list` 每项增加: - `role_ids` - `role_names` --- ## 9.2 `app/api/controller/rbacController.py` ### 角色相关 - `role_list` - `role_detail` - `role_create` - `role_update` - `role_delete` - `role_permission_assign` - `role_permission_list` - `role_menu_assign` - `role_menu_list` ### 权限相关 - `permission_list` - `permission_detail` - `permission_create` - `permission_update` - `permission_delete` ### 菜单相关 - `menu_tree` - `menu_detail` - `menu_create` - `menu_update` - `menu_delete` --- ## 10. 接口清单设计 以下接口路径保持当前项目风格。 --- ## 10.1 角色管理接口 ### 角色列表 - `GET /role/list` - 参数:`keyword`, `status`, `pageNo`, `pageSize` - 返回:角色分页列表 ### 角色详情 - `GET /role/detail` - 参数:`roleId` ### 创建角色 - `POST /role/create` - 参数: - `code` - `name` - `description` - `status` - `isSystem` ### 更新角色 - `POST /role/update` - 参数: - `roleId` - 可选更新字段 ### 删除角色 - `POST /role/delete` - 参数:`roleId` --- ## 10.2 权限管理接口 ### 权限列表 - `GET /permission/list` - 参数:`keyword`, `module`, `status`, `pageNo`, `pageSize` ### 权限详情 - `GET /permission/detail` - 参数:`permissionId` ### 创建权限 - `POST /permission/create` ### 更新权限 - `POST /permission/update` ### 删除权限 - `POST /permission/delete` --- ## 10.3 菜单管理接口 ### 菜单树 - `GET /menu/tree` - 参数:可选 `status` - 返回树形结构 ### 菜单详情 - `GET /menu/detail` - 参数:`menuId` ### 创建菜单 - `POST /menu/create` ### 更新菜单 - `POST /menu/update` ### 删除菜单 - `POST /menu/delete` --- ## 10.4 角色权限分配接口 ### 查询角色权限 - `GET /role/permission/list` - 参数:`roleId` - 返回:`permissionIds` + 权限明细列表 ### 分配角色权限 - `POST /role/permission/assign` - 参数: - `roleId` - `permissionIds: []` 建议语义:覆盖式保存 --- ## 10.5 角色菜单分配接口 ### 查询角色菜单 - `GET /role/menu/list` - 参数:`roleId` - 返回:`menuIds` + 菜单树 ### 分配角色菜单 - `POST /role/menu/assign` - 参数: - `roleId` - `menuIds: []` 建议语义:覆盖式保存 --- ## 10.6 用户管理接口 ### 用户列表 - `GET /user/list` - 参数:`keyword`, `status`, `pageNo`, `pageSize` ### 用户详情 - `GET /user/detail` - 参数:`userId` ### 创建用户 - `POST /user/create` - 参数: - `username` - `realName` - `password` - `mobile` - `email` - `status` ### 更新用户 - `POST /user/update` - 参数: - `userId` - 可选更新字段 ### 删除用户 - `POST /user/delete` - 参数:`userId` --- ## 10.7 用户角色分配接口 ### 查询用户角色 - `GET /user/role/list` - 参数:`userId` - 返回:`roleIds` + 角色列表 ### 分配用户角色 - `POST /user/role/assign` - 参数: - `userId` - `roleIds: []` 建议语义:覆盖式保存 --- ## 11. 返回结构建议 ### 11.1 角色列表项 ```json { "id": 1, "code": "admin", "name": "管理员", "description": "系统管理员", "status": 1, "is_system": 1, "created_time": "2025-01-01 10:00:00" } ``` ### 11.2 用户列表项 ```json { "id": 1, "username": "zhangsan", "real_name": "张三", "mobile": "13800000000", "email": "a@test.com", "status": 1, "role_ids": [1, 2], "role_names": ["管理员", "测试经理"] } ``` ### 11.3 菜单树项 ```json { "id": 1, "parent_id": 0, "name": "系统管理", "code": "system", "type": 1, "path": "/system", "component": "Layout", "icon": "setting", "sort": 1, "children": [] } ``` --- ## 12. 文件清单 本次功能落地预计新增/修改以下文件。 ### 12.1 新增 model - `app/api/model/userModel.py` - `app/api/model/rbacModel.py` ### 12.2 新增 dao - `app/api/dao/userDao.py` - `app/api/dao/rbacDao.py` ### 12.3 新增 service - `app/api/service/userService.py` - `app/api/service/rbacService.py` ### 12.4 新增 controller - `app/api/controller/userController.py` - `app/api/controller/rbacController.py` ### 12.5 修改 views - `app/api/views.py` ### 12.6 可能新增 SQL 脚本(如果你需要) - 数据库建表 SQL - 初始化菜单/权限/角色种子数据 SQL --- ## 13. 分层职责清单 ### model - 只定义表结构 ### dao - 只做数据库查询/写入 - 负责关联表的增删查 ### service - 负责组合查询、覆盖式分配逻辑、聚合返回结构前的数据准备 ### controller - 参数校验、字段映射、调用 service、返回结构组装 ### views - 路由注册、request/response 包装 --- ## 14. 推荐实现顺序 ### 第一阶段:基础 RBAC 数据层 1. 建表 SQL 2. model 3. dao 4. service ### 第二阶段:角色/权限/菜单接口 1. role CRUD 2. permission CRUD 3. menu CRUD 4. role-permission assign 5. role-menu assign ### 第三阶段:用户接口 1. user CRUD 2. user-role assign 3. user list/detail 聚合角色信息 ### 第四阶段:初始化与联调 1. 初始化菜单 2. 初始化权限 3. 初始化管理员角色 4. 初始化管理员用户 --- ## 15. 关键设计决策 ### 15.1 分配类接口采用覆盖式保存 原因: - 前端实现简单 - 后端一致性更好 - 避免增删混合接口过多 ### 15.2 菜单与权限分离 原因: - 菜单是导航资源 - 权限是操作资源 - 一些按钮权限不一定出现在菜单树中 ### 15.3 用户表单独建设,不复用现有 project_member 原因: - `project_member` 是项目成员关系,不是系统账户主表 - 用户管理需要登录凭据、状态、手机号、邮箱等字段 ### 15.4 先不引入复杂组织架构 原因: - 当前需求聚焦 RBAC + 用户 + 菜单 - 可后续扩展部门/租户/产品维度数据权限 --- ## 16. 后续可扩展项 1. 登录认证 - JWT / Session 2. 密码重置 3. 数据权限 - 按产品/项目/部门的数据访问范围 4. 操作审计日志 5. 菜单与接口权限自动同步 6. 超级管理员保护机制 --- ## 17. 需要你确认的点 请你确认以下设计取舍: 1. 用户表是否需要登录密码字段(默认:需要) 2. 权限是否按 `module:action` 编码(默认:是) 3. 菜单是否需要按钮类型 `type=3`(默认:需要) 4. 分配接口是否采用覆盖式保存(默认:是) 5. 是否需要初始化内置角色: - 超级管理员 - 测试经理 - 测试工程师 6. 用户是否允许多角色(默认:允许) 7. 菜单是否只做系统后台菜单,不含项目业务模块动态菜单(默认:只做后台菜单) --- ## 18. 下一步建议 如果你确认这份设计,我下一步可以继续给你输出两部分: 1. **完整建表 SQL** 2. **按当前项目风格拆好的代码落地清单** - 每个文件该写哪些类、哪些方法、哪些接口