Skip to content

权限与组织

权限与组织(IAM)覆盖后台管理员用户、角色、菜单权限、部门、岗位与用户组。系统以菜单权限码为核心做 RBAC 鉴权,以部门树和数据权限范围做数据访问约束,并与在线会话、账号锁定、审计日志、多租户隔离等后端能力联动。


能力总览

模块核心表权限码当前能力
用户管理usersuser_rolesuser_positionsuser_menususer_dept_scopessystem:user:listsystem:user:createsystem:user:updatesystem:user:deletesystem:user:importsystem:user:assign用户 CRUD、角色/岗位/部门分配、用户级菜单权限、用户级数据权限、批量删除、批量启停、批量重置密码、Excel 导入、Excel/CSV 导出、账号解锁、在线状态标记
角色管理rolesrole_menusrole_dept_scopesuser_rolessystem:role:listsystem:role:createsystem:role:updatesystem:role:deletesystem:role:assign角色 CRUD、菜单权限分配、关联用户分配、数据权限范围与指定部门范围
菜单管理menusrole_menususer_menussystem:menu:listsystem:menu:createsystem:menu:updatesystem:menu:delete目录 / 菜单 / 按钮三级模型、树形维护、权限码、可见性、排序、外链与查询参数
部门管理departmentsuserssystem:department:listsystem:department:createsystem:department:updatesystem:department:delete部门树、负责人、部门类别、联系方式、成员数量与成员预览、Excel/CSV 导出
岗位管理positionsuser_positionssystem:position:listsystem:position:createsystem:position:updatesystem:position:delete岗位 CRUD、批量删除、成员查看、成员全量设置、Excel/CSV 导出
用户组user_groupsuser_group_memberssystem:user-groups:listsystem:user-groups:createsystem:user-groups:updatesystem:user-groups:deletesystem:user-groups:assign用户组 CRUD、负责人、所属部门、成员数量与预览、成员全量设置、批量添加、批量移除、批量删除

管理后台用户与前台会员是两套独立账号体系。本文仅描述后台管理员 IAM;会员体系见功能模块


RBAC 权限模型

模型组成

层级表 / 字段说明
用户users.idusers.usernameusers.status后台管理员账号,状态枚举为 enabled / disabled
角色roles.coderoles.statusroles.data_scope角色编码参与 JWT roles 与超管判断;data_scope 控制数据权限
用户-角色user_roles.user_iduser_roles.role_id用户与角色多对多
菜单menus.typemenus.permissionmenus.visibletype 枚举为 directory / menu / button;按钮通常只承载权限码
角色-菜单role_menus.role_idrole_menus.menu_id角色继承的菜单与按钮权限
用户-菜单user_menus.user_iduser_menus.menu_id用户直接授权的菜单与按钮权限

权限校验

所有受保护接口通过 authMiddleware 注入管理员 JWT Payload,再由 guard({ permission }) 做权限判断:

ts
guard({ permission: 'system:user:update' })

校验规则:

  1. JWT roles 包含 super_admin 时直接放行。
  2. 非超管通过 getUserPermissions(userId) 查询用户有效权限。
  3. 有效权限由角色菜单 role_menus 与用户直接菜单 user_menus 合并而成。
  4. 仅采集 menus.permission 非空字符串作为权限码。
  5. 权限缓存按用户维度保存 5 分钟;角色菜单、用户角色、用户菜单变更时清理缓存。

guard({ permission }) 的权限码以路由文件实参为准。菜单种子中的按钮权限用于前端按钮展示控制,后端仍以路由守卫为最终准入点。

菜单权限与动态菜单

菜单实体字段包括 parentIdtitlenamepathcomponenticontypepermissionqueryisExternalsortstatusvisible

接口行为
GET /api/menus/user当前登录用户菜单树。超管返回全部菜单;普通用户根据角色菜单与用户直接菜单计算,并补齐父级菜单
GET /api/menus管理用菜单树,需登录
GET /api/menus/flat平铺菜单列表,需 system:menu:list

种子菜单中,IAM 页面位于「系统管理」下:

页面前端路由组件菜单权限码
用户管理/system/usersusers/UsersPagesystem:user:list
部门管理/system/departmentssystem/departments/DepartmentsPagesystem:department:list
岗位管理/system/positionssystem/positions/PositionsPagesystem:position:list
用户组/system/user-groupssystem/user-groups/UserGroupsPagesystem:user-groups:list
菜单管理/system/menussystem/menus/MenusPagesystem:menu:list
角色管理/system/rolessystem/roles/RolesPagesystem:role:list

内置角色:

角色codedataScope菜单范围
超级管理员super_adminallSEED_MENUS 全部菜单
普通用户userallmenuIds: [1, 202, 203, 310]

数据权限范围(dataScope)

数据权限枚举定义在数据库枚举 data_scope 与共享类型 DataScope 中:

前端文案过滤含义
all全部数据权限不追加数据权限过滤条件
custom指定部门数据权限按指定部门 ID 过滤;角色使用 role_dept_scopes,用户直接设置使用 user_dept_scopes
dept_only本部门数据权限仅匹配当前用户所在部门
dept本部门及以下数据权限匹配当前用户部门及全部子部门
self仅本人数据权限匹配数据归属人字段为当前用户 ID

角色级数据权限

角色表 roles.data_scope 默认值为 all。角色创建与更新支持:

  • dataScope: all / custom / dept_only / dept / self
  • deptScopeIds: 指定部门 ID 列表,仅 custom 需要配置

角色详情接口返回 menuIdsdeptScopeIds,用于角色编辑、菜单权限面板和数据权限面板。

用户级数据权限

用户表 users.user_data_scope 可为空。为空时表示不单独设置,前端文案为「跟随角色(不单独设置)」。

字段来源说明
userDataScopeusers.user_data_scope用户直接数据权限,null 表示未设置
deptScopeIdsuser_dept_scopes.dept_id用户直接指定部门
roleDataScope用户角色中的 roles.data_scope角色侧最宽松数据权限
roleDeptScopeIdsrole_dept_scopes.dept_id角色侧指定部门

GET /api/users/{id}/effective-permissions 返回最终预览:

  • directMenuIds:用户直接菜单 ID
  • roleMenuIds:角色继承菜单 ID
  • effectiveMenuIds:直接菜单与角色菜单并集
  • userDataScoperoleDataScopeeffectiveDataScope
  • userDeptScopeIdsroleDeptScopeIdseffectiveDeptScopeIds

过滤规则

getDataScopeCondition() 接收业务表的 deptColumnownerColumn

ts
await getDataScopeCondition({
  currentUserId,
  deptColumn: users.departmentId,
  ownerColumn: users.id,
});
  • super_admin 或命中 all:返回 undefined,调用方不追加 WHERE 条件。
  • dept:按当前用户部门及子部门过滤;用户无部门时降级为本人。
  • custom:合并角色指定部门与用户直接指定部门;未配置指定部门时降级为本人。
  • dept_only:仅当前用户部门;用户无部门时降级为本人。
  • self:按 ownerColumn = currentUserId 过滤。
  • 未传 deptColumn 时,部门类范围无法生效并降级到本人逻辑。

用户列表 GET /api/users 已接入数据权限过滤,使用 users.departmentId 作为部门列、users.id 作为本人列。


组织架构

部门树

部门表 departments 通过 parent_id 形成树结构,parent_id = 0 表示根节点。主要字段:

字段说明
namecode部门名称与编码;code 在租户维度唯一
category部门类别,支持 group / company / department
leader_id部门负责人,引用 users.id
phoneemail联系方式
sortstatus排序与状态
tenant_id多租户隔离字段

部门服务保证:

  • 上级部门必须存在。
  • 上级部门不能选择自身或自身子部门。
  • 删除部门前检查是否存在子部门或关联用户。
  • 部门树返回 userCount 与最多 5 个 userPreview

岗位

岗位表 positions 保存岗位基础信息,用户通过 user_positions 与岗位多对多关联。

字段说明
namecode岗位名称与编码;code 在租户维度唯一
sortstatus排序与状态
remark备注
tenant_id多租户隔离字段

岗位删除前会检查 user_positions 是否存在关联用户;存在关联用户时返回业务错误。岗位列表返回 userCount 与最多 5 个 userPreview,成员管理接口支持全量覆盖岗位成员。

用户组

用户组表 user_groups 用于将用户按业务协作关系分组,成员通过 user_group_members 维护。

字段说明
namecode用户组名称与编码;code 在租户维度唯一
description描述
owner_id负责人,引用 users.id
department_id所属部门,引用 departments.id
statusenabled / disabled
tenant_id多租户隔离字段

用户组支持成员查看、全量设置、批量添加、批量移除。删除用户组时,user_group_members 通过外键级联清理。


用户管理能力

用户字段

用户 DTO 与表字段覆盖以下核心信息:

字段说明
usernamenicknameemailphonegenderavatar基础资料
departmentIddepartmentName所属部门
positionIdspositions岗位分配
roles角色分配
statusenabled / disabled
passwordUpdatedAt密码更新时间
lastLoginAt最后登录时间
isLocked登录失败锁定状态
isOnline在线会话状态

用户列表支持 keywordphonedepartmentIdstatusstartTimeendTime 查询条件。其中 keyword 匹配 usernamenicknameemail,时间参数使用 YYYY-MM-DD HH:mm:ss 格式。

创建与更新

创建用户字段:

json
{
  "username": "zhangsan",
  "nickname": "张三",
  "email": "zhangsan@example.com",
  "password": "StrongPassword1",
  "phone": "13800138000",
  "gender": "male",
  "departmentId": 1,
  "positionIds": [1],
  "roleIds": [2],
  "status": "enabled"
}

服务层会校验:

  • 密码复杂度策略。
  • 部门、角色、岗位 ID 是否存在且在可访问租户范围内。
  • 同一租户下 usernameemail 不重复。
  • admin 用户不允许删除、禁用或参与批量重置密码。

批量与导入

能力接口说明
批量删除DELETE /api/users/batch请求体 ids
批量启停PUT /api/users/batch-status请求体 idsstatus
批量重置密码PUT /api/users/batch-password请求体 idspassword
下载导入模板GET /api/users/import-template返回 user_import_template.xlsx
导入用户POST /api/users/importmultipart/form-data 上传 file

导入模板列:

说明
用户名*昵称*邮箱*密码*必填
部门编码匹配 departments.code
岗位编码(逗号分隔)匹配 positions.code
角色编码(逗号分隔)匹配 roles.code
状态(enabled/disabled)留空默认 enabled

导入结果返回 totalsuccessfailederrors,其中 errors 包含 rowmessage

账号解锁与在线状态

  • POST /api/users/{id}/unlock 根据用户 ID 找到 username,清理登录锁定状态。
  • 用户列表通过在线会话数据计算 isOnline
  • 前端用户列表在用户在线且具备 system:session:forceLogout 时,可调用 DELETE /api/sessions/user/{id} 强制该用户所有会话下线。
  • 在线会话独立接口还支持 GET /api/sessionsDELETE /api/sessions/{tokenId}

接口一览

以下路径均已包含 /api 前缀;所有接口均要求 Bearer Token。权限列为「仅登录」表示该路由未配置具体权限码。

用户

方法路径说明权限
GET/api/users/all全量用户,下拉框使用system:user:list
GET/api/users用户分页列表system:user:list
POST/api/users创建用户system:user:create
DELETE/api/users/batch批量删除用户system:user:delete
PUT/api/users/batch-password批量重置用户密码system:user:update
PUT/api/users/batch-status批量修改用户状态system:user:update
GET/api/users/import-template下载导入模板system:user:import
POST/api/users/import导入用户system:user:import
PUT/api/users/{id}/password修改指定用户密码system:user:update
POST/api/users/{id}/unlock解锁账号system:user:update
GET/api/users/{id}用户详情system:user:list
PUT/api/users/{id}更新用户system:user:update
DELETE/api/users/{id}删除用户system:user:delete
PUT/api/users/{id}/roles分配用户角色system:user:assign
GET/api/users/{id}/menus获取用户菜单权限system:user:assign
PUT/api/users/{id}/menus分配用户直接菜单权限system:user:assign
GET/api/users/{id}/data-permission获取用户数据权限system:user:assign
PUT/api/users/{id}/data-permission设置用户数据权限system:user:assign
GET/api/users/{id}/effective-permissions获取最终有效权限system:user:assign

角色

方法路径说明权限
GET/api/roles/all全量角色,下拉框使用system:role:list
GET/api/roles角色分页列表system:role:list
GET/api/roles/{id}角色详情,含 menuIdsdeptScopeIdssystem:role:list
POST/api/roles创建角色system:role:create
PUT/api/roles/{id}更新角色system:role:update
DELETE/api/roles/{id}删除角色system:role:delete
PUT/api/roles/{id}/menus分配角色菜单system:role:assign
GET/api/roles/{id}/users获取角色关联用户system:role:list
PUT/api/roles/{id}/users分配角色用户system:role:assign

菜单

方法路径说明权限
GET/api/menus/user当前用户可见菜单树仅登录
GET/api/menus管理用全量菜单树仅登录
GET/api/menus/flat平铺菜单列表system:menu:list
GET/api/menus/{id}菜单详情system:menu:list
POST/api/menus创建菜单system:menu:create
PUT/api/menus/{id}更新菜单system:menu:update
DELETE/api/menus/{id}删除菜单及子菜单system:menu:delete

部门

方法路径说明权限
GET/api/departments部门树system:department:list
GET/api/departments/flat部门扁平列表system:department:list
GET/api/departments/{id}部门详情system:department:list
POST/api/departments创建部门system:department:create
PUT/api/departments/{id}更新部门system:department:update
DELETE/api/departments/{id}删除部门system:department:delete

岗位

方法路径说明权限
GET/api/positions/all全量岗位,下拉框使用system:position:list
GET/api/positions岗位分页列表system:position:list
GET/api/positions/{id}岗位详情system:position:list
POST/api/positions创建岗位system:position:create
PUT/api/positions/{id}更新岗位system:position:update
DELETE/api/positions/batch批量删除岗位system:position:delete
DELETE/api/positions/{id}删除岗位system:position:delete
GET/api/positions/{id}/members获取岗位成员system:position:list
PUT/api/positions/{id}/members设置岗位成员system:position:update

用户组

方法路径说明权限
GET/api/user-groups/all全量用户组,下拉框使用system:user-groups:list
GET/api/user-groups用户组分页列表system:user-groups:list
GET/api/user-groups/{id}用户组详情system:user-groups:list
POST/api/user-groups创建用户组system:user-groups:create
PUT/api/user-groups/{id}更新用户组system:user-groups:update
DELETE/api/user-groups/batch批量删除用户组system:user-groups:delete
DELETE/api/user-groups/{id}删除用户组system:user-groups:delete
GET/api/user-groups/{id}/members获取用户组成员system:user-groups:list
PUT/api/user-groups/{id}/members设置用户组成员system:user-groups:assign
POST/api/user-groups/{id}/members添加用户组成员system:user-groups:assign
DELETE/api/user-groups/{id}/members移除用户组成员system:user-groups:assign

在线会话联动

方法路径说明权限
GET/api/sessions在线会话列表system:session:list
DELETE/api/sessions/{tokenId}强制指定会话下线system:session:forceLogout
DELETE/api/sessions/user/{id}强制指定用户所有会话下线system:session:forceLogout

前端页面

页面路由主要交互
用户管理/system/users部门主从布局、用户列表、创建/编辑、头像、角色/岗位/部门分配、批量删除、批量启停、批量重置密码、导入导出、解锁、强制下线入口
用户菜单权限弹窗用户管理弹窗读取 /api/menus/api/users/{id}/effective-permissions,展示角色继承、用户直接授权与最终菜单权限
用户数据权限弹窗用户管理弹窗读取和保存 /api/users/{id}/data-permission,支持用户级 dataScope 与指定部门
角色管理/system/roles角色列表、创建/编辑、状态切换、菜单权限分配、数据权限设置、关联用户分配、导出
菜单管理/system/menus菜单树维护、目录/菜单/按钮类型、状态切换、可见性、权限码
部门管理/system/departments部门树、负责人、部门成员预览、创建/编辑/删除、状态切换、导出
岗位管理/system/positions岗位列表、成员管理、批量删除、状态切换、导出
用户组管理/system/user-groups用户组列表、负责人/部门、成员管理、批量删除、状态切换

前端按钮展示通过 usePermission() 读取当前用户权限码控制,例如 system:user:create 控制用户创建按钮,system:role:assign 控制角色菜单权限与关联用户操作。后端路由守卫仍是最终权限校验来源。


相关文档

Built with VitePress for local documentation preview.