18 KiB
18 KiB
角色/用户/菜单管理详细设计文档
1. 目标
基于当前项目已有的分层框架(model / dao / service / controller / views)新增以下能力:
- 角色管理
- 角色表
- 权限表
- 用户角色关联表
- 角色权限关联能力
- 用户管理
- 用户表
- 用户与角色分配
- 菜单管理
- 菜单表
- 角色分配菜单
本次仅输出详细设计,不直接改业务代码。
2. 当前项目框架观察
2.1 现有分层风格
当前项目采用如下结构:
app/api/model/*.pyapp/api/dao/*.pyapp/api/service/*.pyapp/api/controller/*.pyapp/api/views.py
2.2 当前职责边界
model
- 定义 SQLAlchemy 表模型
- 每个领域通常独立一个 model 文件
dao
- 负责数据库增删改查
- 已有通用风格:
createupdate_by_idget_by_idlist_by_filtersdelete_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. 总体设计原则
- 严格按当前框架分层
- controller 不直接查数据库
- 跨表聚合通过 service + dao 实现
- 保持与现有字段风格一致:
- 主键
id - 软删字段
is_delete - 时间字段
created_time/updated_time
- 主键
- 优先支持后台管理能力,不先引入复杂 RBAC 继承体系
- 菜单、权限、角色、用户四个域解耦,但通过关联表关联
4. 业务对象与关系
4.1 核心对象
- 用户
user - 角色
role - 权限
permission - 菜单
menu
4.2 关联对象
- 用户角色关联
user_role - 角色权限关联
role_permission - 角色菜单关联
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) | 手机号 | |
| 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
包含:
UserUserRole
6.2 app/api/model/rbacModel.py
包含:
RolePermissionRolePermissionMenuRoleMenu
也可以拆成
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_listuser_detailuser_createuser_updateuser_deleteuser_role_assignuser_role_list
返回增强建议
user_list 每项增加:
role_idsrole_names
9.2 app/api/controller/rbacController.py
角色相关
role_listrole_detailrole_createrole_updaterole_deleterole_permission_assignrole_permission_listrole_menu_assignrole_menu_list
权限相关
permission_listpermission_detailpermission_createpermission_updatepermission_delete
菜单相关
menu_treemenu_detailmenu_createmenu_updatemenu_delete
10. 接口清单设计
以下接口路径保持当前项目风格。
10.1 角色管理接口
角色列表
GET /role/list- 参数:
keyword,status,pageNo,pageSize - 返回:角色分页列表
角色详情
GET /role/detail- 参数:
roleId
创建角色
POST /role/create- 参数:
codenamedescriptionstatusisSystem
更新角色
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- 参数:
roleIdpermissionIds: []
建议语义:覆盖式保存
10.5 角色菜单分配接口
查询角色菜单
GET /role/menu/list- 参数:
roleId - 返回:
menuIds+ 菜单树
分配角色菜单
POST /role/menu/assign- 参数:
roleIdmenuIds: []
建议语义:覆盖式保存
10.6 用户管理接口
用户列表
GET /user/list- 参数:
keyword,status,pageNo,pageSize
用户详情
GET /user/detail- 参数:
userId
创建用户
POST /user/create- 参数:
usernamerealNamepasswordmobileemailstatus
更新用户
POST /user/update- 参数:
userId- 可选更新字段
删除用户
POST /user/delete- 参数:
userId
10.7 用户角色分配接口
查询用户角色
GET /user/role/list- 参数:
userId - 返回:
roleIds+ 角色列表
分配用户角色
POST /user/role/assign- 参数:
userIdroleIds: []
建议语义:覆盖式保存
11. 返回结构建议
11.1 角色列表项
{
"id": 1,
"code": "admin",
"name": "管理员",
"description": "系统管理员",
"status": 1,
"is_system": 1,
"created_time": "2025-01-01 10:00:00"
}
11.2 用户列表项
{
"id": 1,
"username": "zhangsan",
"real_name": "张三",
"mobile": "13800000000",
"email": "a@test.com",
"status": 1,
"role_ids": [1, 2],
"role_names": ["管理员", "测试经理"]
}
11.3 菜单树项
{
"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.pyapp/api/model/rbacModel.py
12.2 新增 dao
app/api/dao/userDao.pyapp/api/dao/rbacDao.py
12.3 新增 service
app/api/service/userService.pyapp/api/service/rbacService.py
12.4 新增 controller
app/api/controller/userController.pyapp/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 数据层
- 建表 SQL
- model
- dao
- service
第二阶段:角色/权限/菜单接口
- role CRUD
- permission CRUD
- menu CRUD
- role-permission assign
- role-menu assign
第三阶段:用户接口
- user CRUD
- user-role assign
- user list/detail 聚合角色信息
第四阶段:初始化与联调
- 初始化菜单
- 初始化权限
- 初始化管理员角色
- 初始化管理员用户
15. 关键设计决策
15.1 分配类接口采用覆盖式保存
原因:
- 前端实现简单
- 后端一致性更好
- 避免增删混合接口过多
15.2 菜单与权限分离
原因:
- 菜单是导航资源
- 权限是操作资源
- 一些按钮权限不一定出现在菜单树中
15.3 用户表单独建设,不复用现有 project_member
原因:
project_member是项目成员关系,不是系统账户主表- 用户管理需要登录凭据、状态、手机号、邮箱等字段
15.4 先不引入复杂组织架构
原因:
- 当前需求聚焦 RBAC + 用户 + 菜单
- 可后续扩展部门/租户/产品维度数据权限
16. 后续可扩展项
- 登录认证
- JWT / Session
- 密码重置
- 数据权限
- 按产品/项目/部门的数据访问范围
- 操作审计日志
- 菜单与接口权限自动同步
- 超级管理员保护机制
17. 需要你确认的点
请你确认以下设计取舍:
- 用户表是否需要登录密码字段(默认:需要)
- 权限是否按
module:action编码(默认:是) - 菜单是否需要按钮类型
type=3(默认:需要) - 分配接口是否采用覆盖式保存(默认:是)
- 是否需要初始化内置角色:
- 超级管理员
- 测试经理
- 测试工程师
- 用户是否允许多角色(默认:允许)
- 菜单是否只做系统后台菜单,不含项目业务模块动态菜单(默认:只做后台菜单)
18. 下一步建议
如果你确认这份设计,我下一步可以继续给你输出两部分:
- 完整建表 SQL
- 按当前项目风格拆好的代码落地清单
- 每个文件该写哪些类、哪些方法、哪些接口