# RBAC 权限管理前端对接文档 ## 概述 本文档详细说明 RBAC(基于角色的访问控制)模块的所有 API 接口和业务逻辑,包括: - 角色管理(5个接口) - 权限管理(5个接口) - 角色权限关联(4个接口) - 用户角色管理(4个接口) - 路由管理(3个接口) **总计:21个 API 接口** --- ## 目录 1. [核心概念](#核心概念) 2. [角色管理 API](#角色管理-api) 3. [权限管理 API](#权限管理-api) 4. [角色权限关联 API](#角色权限关联-api) 5. [用户角色管理 API](#用户角色管理-api) 6. [路由管理 API](#路由管理-api) 7. [业务逻辑详解](#业务逻辑详解) 8. [前端实现指南](#前端实现指南) --- ## 核心概念 ### 角色层级 | 角色 | role_key | 说明 | 数据范围 | |------|----------|------|----------| | 省级管理员 | `provincial_admin` | 最高权限,管理所有地区 | ALL | | 市级管理员 | `admin` | 管理本地区用户 | DEPT | | 普通员工 | `common` | 普通操作权限 | SELF | ### 数据范围 (data_scope) | 值 | 说明 | |----|------| | `ALL` | 全部数据(所有地区) | | `DEPT` | 部门数据(本地区) | | `SELF` | 个人数据(仅自己) | ### 权限类型 (permission_type) | 值 | 说明 | |----|------| | `API` | API 接口权限 | | `MENU` | 菜单访问权限 | | `BUTTON` | 按钮操作权限 | ### 授权类型 (grant_type) | 值 | 说明 | |----|------| | `GRANT` | 授予权限 | | `DENY` | 拒绝权限 | ### 权限类型(独立/通用) | 类型 | route_id | related_routes | 说明 | |------|----------|----------------|------| | **独立权限** | 有值(如58) | NULL | 只属于单个页面 | | **通用权限** | NULL | 有值(如[58,37]) | 被多个页面共享 | ### 关键数据表 | 表名 | 说明 | |------|------| | `roles` | 角色定义表 | | `permissions` | 权限定义表 | | `role_permissions` | 角色-权限关联表 | | `user_role` | 用户-角色关联表 | | `sys_routes` | 前端路由配置表 | | `sso_users` | 用户信息表 | | `rbac_audit_logs` | RBAC审计日志表 | --- ## 角色管理 API ### 1. 获取角色列表 **请求** ```http GET /api/v3/rbac/roles?page=1&page_size=20&role_name=&include_system=true ``` **权限要求**: 仅需登录(所有用户可访问,返回数据根据角色过滤) **Query 参数** | 参数 | 类型 | 必填 | 默认值 | 说明 | |------|------|------|--------|------| | page | int | 否 | 1 | 页码 | | page_size | int | 否 | 20 | 每页数量(1-100) | | role_key | string | 否 | - | 角色标识精确过滤 | | role_name | string | 否 | - | 角色名称模糊搜索 | | include_system | bool | 否 | true | 是否包含系统角色 | **响应** ```json { "total": 10, "page": 1, "page_size": 20, "items": [ { "id": 1, "role_key": "provincial_admin", "role_name": "省级管理员", "description": "系统最高权限管理员", "data_scope": "ALL", "is_system": true, "user_count": 5, "permission_count": 120, "created_at": "2025-01-01T00:00:00", "updated_at": "2025-01-01T00:00:00", "metadata": null }, { "id": 2, "role_key": "admin", "role_name": "市级管理员", "description": "地市级管理员", "data_scope": "DEPT", "is_system": true, "user_count": 20, "permission_count": 80, "created_at": "2025-01-01T00:00:00", "updated_at": "2025-01-01T00:00:00", "metadata": null } ] } ``` **业务逻辑** - 所有登录用户都可以查看角色列表 - 角色是全局统一的,不区分地区 - 返回数据包含用户数量和权限数量统计 --- ### 2. 获取角色详情 **请求** ```http GET /api/v3/rbac/roles/{role_id} ``` **权限要求**: `system:rbac:manage` **Path 参数** | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | role_id | int | 是 | 角色ID | **响应** ```json { "id": 2, "role_key": "admin", "role_name": "市级管理员", "description": "地市级管理员", "data_scope": "DEPT", "is_system": true, "permissions": [ { "id": 1, "permission_id": 10, "permission_key": "document:list:read", "display_name": "查看文档列表", "grant_type": "GRANT", "data_scope": "DEPT" }, { "id": 2, "permission_id": 11, "permission_key": "document:detail:read", "display_name": "查看文档详情", "grant_type": "GRANT", "data_scope": "DEPT" } ], "metadata": null, "created_at": "2025-01-01T00:00:00", "updated_at": "2025-01-01T00:00:00" } ``` --- ### 3. 创建角色 **请求** ```http POST /api/v3/rbac/roles Content-Type: application/json { "role_key": "reviewer", "role_name": "评查员", "description": "负责文档评查工作", "data_scope": "DEPT", "metadata": { "department": "评查部" } } ``` **权限要求**: `system:rbac:manage` **Request Body** | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | role_key | string | 是 | 角色标识(唯一,只能包含小写字母、数字、下划线) | | role_name | string | 是 | 角色名称 | | description | string | 否 | 角色描述 | | data_scope | string | 否 | 数据范围(ALL/DEPT/SELF,默认SELF) | | metadata | object | 否 | 扩展元数据 | **响应** ```json { "id": 10, "role_key": "reviewer", "role_name": "评查员", "description": "负责文档评查工作", "data_scope": "DEPT", "is_system": false, "permissions": [], "metadata": {"department": "评查部"}, "created_at": "2025-12-11T10:00:00", "updated_at": "2025-12-11T10:00:00" } ``` **业务逻辑** - `role_key` 只能包含小写字母、数字、下划线,且必须以字母开头 - `role_key` 必须唯一 - 新创建的角色 `is_system` 默认为 `false` - 操作会记录到审计日志 --- ### 4. 更新角色 **请求** ```http PUT /api/v3/rbac/roles/{role_id} Content-Type: application/json { "role_name": "高级评查员", "description": "负责高级文档评查工作", "data_scope": "ALL" } ``` **权限要求**: `system:rbac:manage` **Request Body**(所有字段可选) | 参数 | 类型 | 说明 | |------|------|------| | role_name | string | 角色名称 | | description | string | 角色描述 | | data_scope | string | 数据范围 | | metadata | object | 扩展元数据 | **响应** ```json { "id": 10, "role_key": "reviewer", "role_name": "高级评查员", "description": "负责高级文档评查工作", "data_scope": "ALL", "is_system": false, "permissions": [], "metadata": {"department": "评查部"}, "created_at": "2025-12-11T10:00:00", "updated_at": "2025-12-11T11:00:00" } ``` **业务逻辑** - `role_key` 不可修改 - 系统角色(`is_system=true`)有额外限制 - `provincial_admin` 角色禁止修改 `data_scope` - 操作会记录到审计日志 --- ### 5. 删除角色 **请求** ```http DELETE /api/v3/rbac/roles/{role_id}?force=false ``` **权限要求**: `system:rbac:manage` **Query 参数** | 参数 | 类型 | 必填 | 默认值 | 说明 | |------|------|------|--------|------| | force | bool | 否 | false | 强制删除(自动解除用户关联) | **响应** ```json { "code": 200, "message": "角色删除成功: 评查员", "data": { "role_id": 10, "deleted_users": 5 } } ``` **业务逻辑** - 系统角色(`is_system=true`)禁止删除 - `provincial_admin` 角色绝对禁止删除 - 删除时自动解除用户关联、角色权限关联 - 操作会记录到审计日志 --- ## 权限管理 API ### 1. 获取权限列表 **请求** ```http GET /api/v3/rbac/permissions?format=tree&module=&permission_type=&include_system=true ``` **权限要求**: `system:rbac:manage` **Query 参数** | 参数 | 类型 | 必填 | 默认值 | 说明 | |------|------|------|--------|------| | format | string | 否 | tree | 返回格式(tree/flat) | | module | string | 否 | - | 按模块过滤 | | permission_type | string | 否 | - | 权限类型过滤(API/MENU/BUTTON) | | include_system | bool | 否 | true | 是否包含系统权限 | **响应(树形格式)** ```json [ { "id": 1, "permission_key": "document:*:*", "display_name": "文档管理", "description": "文档管理模块全部权限", "module": "document", "resource": "*", "action": "*", "permission_type": "API", "is_system": true, "parent_id": null, "sort_order": 0, "children": [ { "id": 2, "permission_key": "document:list:read", "display_name": "查看文档列表", "module": "document", "resource": "list", "action": "read", "permission_type": "API", "is_system": false, "parent_id": 1, "sort_order": 0, "children": [] } ] } ] ``` **业务逻辑** - 树形格式:按 `parent_id` 构建层级结构 - 平铺格式:直接返回列表 --- ### 2. 获取权限详情 **请求** ```http GET /api/v3/rbac/permissions/{permission_id} ``` **权限要求**: `system:rbac:manage` **响应** ```json { "id": 10, "permission_key": "document:list:read", "display_name": "查看文档列表", "description": "允许查看文档列表", "module": "document", "resource": "list", "action": "read", "permission_type": "API", "is_system": false, "parent_id": 1, "sort_order": 0, "metadata": null, "created_at": "2025-01-01T00:00:00", "updated_at": "2025-01-01T00:00:00" } ``` --- ### 3. 创建权限 **请求** ```http POST /api/v3/rbac/permissions Content-Type: application/json { "permission_key": "evaluation:result:export", "display_name": "导出评查结果", "description": "允许导出评查结果为Excel", "module": "evaluation", "resource": "result", "action": "export", "permission_type": "API", "parent_id": null, "sort_order": 10 } ``` **权限要求**: `system:rbac:manage` **Request Body** | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | permission_key | string | 是 | 权限键(格式:module:resource:action) | | display_name | string | 是 | 显示名称 | | description | string | 否 | 权限描述 | | module | string | 否 | 模块名(可从permission_key自动解析) | | resource | string | 否 | 资源名(可从permission_key自动解析) | | action | string | 否 | 操作名(可从permission_key自动解析) | | permission_type | string | 否 | 权限类型(API/MENU/BUTTON,默认API) | | parent_id | int | 否 | 父权限ID | | sort_order | int | 否 | 排序顺序(默认0) | | metadata | object | 否 | 扩展元数据 | **响应** ```json { "id": 100, "permission_key": "evaluation:result:export", "display_name": "导出评查结果", "description": "允许导出评查结果为Excel", "module": "evaluation", "resource": "result", "action": "export", "permission_type": "API", "is_system": false, "parent_id": null, "sort_order": 10, "metadata": null, "created_at": "2025-12-11T10:00:00", "updated_at": "2025-12-11T10:00:00" } ``` **业务逻辑** - `permission_key` 格式必须是 `module:resource:action` - `permission_key` 必须唯一 - 如果包含通配符 `*`,自动标记为系统权限 - 如果指定 `parent_id`,必须指向存在的权限 - 操作会记录到审计日志 --- ### 4. 更新权限 **请求** ```http PUT /api/v3/rbac/permissions/{permission_id} Content-Type: application/json { "display_name": "导出评查结果(新)", "description": "允许导出评查结果为Excel或PDF", "sort_order": 5 } ``` **权限要求**: `system:rbac:manage` **Request Body**(所有字段可选) | 参数 | 类型 | 说明 | |------|------|------| | display_name | string | 显示名称 | | description | string | 权限描述 | | sort_order | int | 排序顺序 | | metadata | object | 扩展元数据 | **业务逻辑** - `permission_key` 不可修改 - 系统权限有额外限制 - 操作会记录到审计日志 --- ### 5. 删除权限 **请求** ```http DELETE /api/v3/rbac/permissions/{permission_id}?force=false ``` **权限要求**: `system:rbac:manage` **Query 参数** | 参数 | 类型 | 默认值 | 说明 | |------|------|--------|------| | force | bool | false | 强制删除(自动解除角色关联) | **响应** ```json { "code": 200, "message": "权限删除成功: 导出评查结果", "data": { "permission_id": 100, "deleted_role_relations": 3 } } ``` **业务逻辑** - 系统权限禁止删除 - 有子权限的权限禁止删除(必须先删除子权限) - `force=false` 时,有角色关联则拒绝删除 - `force=true` 时,自动解除角色关联后删除 - 操作会记录到审计日志 --- ## 角色权限关联 API ### 1. 获取角色的所有权限 **请求** ```http GET /api/v3/rbac/role-permissions?role_id=2 ``` **权限要求**: `system:rbac:manage` **Query 参数** | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | role_id | int | 是 | 角色ID | **响应** ```json { "code": 200, "message": "success", "data": { "role_id": 2, "role_name": "市级管理员", "role_key": "admin", "permissions": [ { "id": 1, "permission_id": 10, "permission_key": "document:list:read", "display_name": "查看文档列表", "module": "document", "resource": "list", "action": "read", "permission_type": "API", "grant_type": "GRANT", "data_scope": "DEPT" }, { "id": 2, "permission_id": 11, "permission_key": "document:detail:read", "display_name": "查看文档详情", "module": "document", "resource": "detail", "action": "read", "permission_type": "API", "grant_type": "GRANT", "data_scope": "DEPT" } ] } } ``` --- ### 2. 批量分配角色权限 **请求** ```http POST /api/v3/rbac/role-permissions Content-Type: application/json { "role_id": 2, "permissions": [ {"permission_id": 10, "grant_type": "GRANT", "data_scope": "DEPT"}, {"permission_id": 11, "grant_type": "GRANT", "data_scope": "DEPT"}, {"permission_id": 12, "grant_type": "DENY", "data_scope": null} ], "replace": true } ``` **权限要求**: `system:rbac:manage` **Request Body** | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | role_id | int | 是 | 角色ID | | permissions | array | 是 | 权限列表 | | permissions[].permission_id | int | 是 | 权限ID | | permissions[].grant_type | string | 是 | 授权类型(GRANT/DENY) | | permissions[].data_scope | string | 否 | 数据范围(ALL/DEPT/SELF) | | replace | bool | 否 | 替换模式(默认false) | **模式说明** - `replace=true`: 替换全部权限(未在列表中的权限设为DENY) - `replace=false`: 追加模式(保留现有权限,追加新权限) **响应** ```json { "code": 200, "message": "成功替换权限", "data": { "role_id": 2, "role_name": "市级管理员", "assigned_count": 3, "replace": true } } ``` **业务逻辑** - 验证所有 `permission_id` 必须存在 - `provincial_admin` 角色的核心权限不可移除(即使在replace模式下) - 核心权限:`system:rbac:manage`、`system:*:*` - 操作会记录到审计日志 --- ### 3. 更新单个角色权限 **请求** ```http PUT /api/v3/rbac/role-permissions?role_id=2&permission_id=10 Content-Type: application/json { "grant_type": "DENY", "data_scope": "SELF" } ``` **权限要求**: `system:rbac:manage` **Query 参数** | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | role_id | int | 是 | 角色ID | | permission_id | int | 是 | 权限ID | **Request Body**(至少提供一个) | 参数 | 类型 | 说明 | |------|------|------| | grant_type | string | 授权类型(GRANT/DENY) | | data_scope | string | 数据范围(ALL/DEPT/SELF) | **响应** ```json { "code": 200, "message": "权限更新成功", "data": { "id": 1, "role_id": 2, "permission_id": 10, "grant_type": "DENY", "data_scope": "SELF" } } ``` --- ### 4. 移除角色权限 **请求** ```http DELETE /api/v3/rbac/role-permissions?role_id=2&permission_id=10 ``` **权限要求**: `system:rbac:manage` **Query 参数** | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | role_id | int | 是 | 角色ID | | permission_id | int | 是 | 权限ID | **响应** ```json { "code": 200, "message": "成功移除角色权限: 市级管理员 - 查看文档列表", "data": { "role_id": 2, "permission_id": 10 } } ``` **业务逻辑** - `provincial_admin` 角色的核心权限不可移除 - 核心权限列表:`system:rbac:manage`、`system:*:*` - 操作会记录到审计日志 --- ## 用户角色管理 API ### 1. 获取角色的所有用户 **请求** ```http GET /api/v3/rbac/roles/{role_id}/users?page=1&page_size=20&area=&username= ``` **权限要求**: 仅需登录(数据根据用户角色过滤) **Path 参数** | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | role_id | int | 是 | 角色ID | **Query 参数** | 参数 | 类型 | 必填 | 默认值 | 说明 | |------|------|------|--------|------| | page | int | 否 | 1 | 页码 | | page_size | int | 否 | 20 | 每页数量(1-100) | | area | string | 否 | - | 按地区过滤 | | username | string | 否 | - | 用户名模糊搜索 | **响应** ```json { "total": 20, "page": 1, "page_size": 20, "items": [ { "user_id": 100, "username": "zhangsan", "nick_name": "张三", "area": "梅州", "ou_name": "梅州市检察院", "phone_number": "13800138000", "email": "zhangsan@example.com", "assigned_at": "2025-01-01T00:00:00" } ] } ``` **业务逻辑** - `provincial_admin`: 可查看所有地区用户 - `admin`: 只能查看同地区(area字段)的用户 --- ### 2. 获取用户的所有角色 **请求** ```http GET /api/v3/rbac/users/{user_id}/roles ``` **权限要求**: `system:rbac:manage` **Path 参数** | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | user_id | int | 是 | 用户ID | **响应** ```json { "user_id": 100, "username": "zhangsan", "nick_name": "张三", "roles": [ { "role_id": 2, "role_key": "admin", "role_name": "市级管理员", "data_scope": "DEPT", "assigned_at": "2025-01-01T00:00:00" } ] } ``` --- ### 3. 为用户分配角色 **请求** ```http POST /api/v3/rbac/users/{user_id}/roles Content-Type: application/json { "role_ids": [2] } ``` **权限要求**: `system:rbac:manage` **Path 参数** | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | user_id | int | 是 | 用户ID | **Request Body** | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | role_ids | array | 是 | 角色ID列表 | **响应** ```json { "code": 200, "message": "角色分配成功", "data": { "user_id": 100, "username": "zhangsan", "assigned_roles": [ {"role_id": 2, "role_name": "市级管理员"} ] } } ``` **业务逻辑** - 一个用户只能拥有一个角色 - 如果用户已有角色,需要先移除再分配新角色 - 禁止给自己分配角色(防止自己提权) - `admin` 只能给本地区用户分配角色 - `admin` 不能分配 `provincial_admin` 或 `admin` 角色(只有省级管理员可以) - 操作会记录到审计日志 --- ### 4. 移除用户角色 **请求** ```http DELETE /api/v3/rbac/users/{user_id}/roles/{role_id} ``` **权限要求**: `system:rbac:manage` **Path 参数** | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | user_id | int | 是 | 用户ID | | role_id | int | 是 | 角色ID | **响应** ```json { "code": 200, "message": "成功移除用户角色: zhangsan - 市级管理员", "data": { "user_id": 100, "role_id": 2 } } ``` **业务逻辑** - 禁止移除自己的角色(防止自锁) - `admin` 只能移除本地区用户的角色 - `admin` 不能移除用户的 `provincial_admin` 或 `admin` 角色 - 操作会记录到审计日志 --- ## 路由管理 API ### 1. 获取所有路由列表 **请求** ```http GET /api/v3/routes?format=tree&include_hidden=false ``` **权限要求**: 仅需登录 **Query 参数** | 参数 | 类型 | 必填 | 默认值 | 说明 | |------|------|------|--------|------| | format | string | 否 | tree | 返回格式(tree/flat) | | include_hidden | bool | 否 | false | 是否包含隐藏路由 | **响应(树形格式)** ```json [ { "id": 2, "route_path": "/documents", "route_name": "Documents", "route_title": "文件管理", "component": "views/documents/index", "parent_id": null, "icon": "ri-file-list-line", "sort_order": 1, "is_hidden": false, "is_cache": true, "meta": null, "status": 0, "created_at": "2025-01-01T00:00:00", "updated_at": "2025-01-01T00:00:00", "children": [ { "id": 58, "route_path": "/reviews", "route_name": "Reviews", "route_title": "文档评查结果详情", "parent_id": 2, "children": null } ] } ] ``` --- ### 2. 获取路由详情 **请求** ```http GET /api/v3/routes/{route_id} ``` **权限要求**: 仅需登录 **响应** ```json { "id": 58, "route_path": "/reviews", "route_name": "Reviews", "route_title": "文档评查结果详情", "component": "views/reviews/index", "parent_id": 2, "icon": "ri-file-list-line", "sort_order": 3, "is_hidden": false, "is_cache": true, "meta": null, "status": 0, "created_at": "2025-01-01T00:00:00", "updated_at": "2025-01-01T00:00:00" } ``` --- ### 3. 获取路由的所有权限(含通用权限)⭐核心接口 **请求** ```http GET /api/v3/routes/{route_id}/permissions ``` **权限要求**: 仅需登录 **响应** ```json { "route_id": 58, "route_path": "/reviews", "route_title": "文档评查结果详情", "permissions": [ { "id": 82, "permission_key": "evaluation_point:result:view", "display_name": "查看评查结果", "description": "查看评查结果详情", "module": "evaluation_point", "resource": "result", "action": "view", "permission_type": "API", "route_id": 58, "related_routes": null, "api_path": "/api/postgrest/proxy/evaluation_results", "api_method": "GET", "is_system": false, "sort_order": 0, "is_shared": false }, { "id": 88, "permission_key": "evaluation:audit_status:view", "display_name": "查看审计状态", "description": "查看审计状态(通用权限)", "module": "evaluation", "resource": "audit_status", "action": "view", "permission_type": "API", "route_id": null, "related_routes": [58, 37], "api_path": "/api/postgrest/proxy/audit_status", "api_method": "GET", "is_system": false, "sort_order": 0, "is_shared": true } ] } ``` **响应字段说明** | 字段 | 说明 | |------|------| | `route_id` | 当前查询的路由ID | | `route_path` | 路由路径 | | `route_title` | 路由标题 | | `permissions` | 权限列表 | | `permissions[].is_shared` | **关键字段**:`true`=通用权限,`false`=独立权限 | | `permissions[].related_routes` | 通用权限关联的所有路由ID | **业务逻辑** 查询SQL逻辑: ```sql SELECT * FROM permissions WHERE route_id = {route_id} -- 独立权限 OR {route_id} = ANY(related_routes) -- 通用权限 ORDER BY CASE WHEN related_routes IS NOT NULL THEN 1 ELSE 0 END, sort_order, id ``` --- ## 业务逻辑详解 ### 1. 权限检查逻辑 后端权限检查**只看 `permission_key`**,与 `route_id` 无关: ```sql SELECT p.permission_key FROM role_permissions rp JOIN permissions p ON rp.permission_id = p.id WHERE rp.role_id = {user_role_id} AND rp.grant_type = 'GRANT' ``` ### 2. 通用权限保存逻辑 - 通用权限在数据库中只有**一条记录** - 保存时只需提交**一次 permission_id** - 两个页面自动都会有该权限 ```javascript // 正确:通用权限只提交一次 { "permissions": [ {"permission_id": 88, "grant_type": "GRANT"} // 通用权限 ] } // 错误:不需要为每个页面分别提交 { "permissions": [ {"permission_id": 88, "grant_type": "GRANT", "route_id": 58}, // ❌ 不需要 {"permission_id": 88, "grant_type": "GRANT", "route_id": 37} // ❌ 不需要 ] } ``` ### 3. 角色层级权限控制 | 操作 | provincial_admin | admin | common | |------|------------------|-------|--------| | 查看角色列表 | ✅ 全部 | ✅ 全部 | ✅ 全部 | | 查看角色详情 | ✅ | ✅ | ❌ | | 创建/修改/删除角色 | ✅ | ❌ | ❌ | | 分配 provincial_admin 角色 | ✅ | ❌ | ❌ | | 分配 admin 角色 | ✅ | ❌ | ❌ | | 分配 common 角色 | ✅ | ✅(本地区) | ❌ | | 查看用户列表 | ✅ 全部 | ✅ 本地区 | ❌ | ### 4. 核心权限保护 `provincial_admin` 角色的以下核心权限不可移除: | 权限 | 说明 | |------|------| | `system:rbac:manage` | RBAC管理权限 | | `system:*:*` | 系统全部权限 | ### 5. 安全检查规则 | 规则 | 说明 | |------|------| | 禁止自操作 | 不能给自己分配/移除角色 | | 地区隔离 | admin 只能操作本地区用户 | | 权限升级限制 | 只有省级管理员可以分配管理员角色 | | 系统保护 | 系统角色/权限禁止删除 | | 关联检查 | 有子权限的权限禁止删除 | ### 6. 审计日志 所有写操作都会记录到 `rbac_audit_logs` 表: | 操作类型 | 说明 | |----------|------| | CREATE_ROLE | 创建角色 | | UPDATE_ROLE | 更新角色 | | DELETE_ROLE | 删除角色 | | CREATE_PERMISSION | 创建权限 | | UPDATE_PERMISSION | 更新权限 | | DELETE_PERMISSION | 删除权限 | | BATCH_ASSIGN_PERMISSION | 批量分配权限 | | UPDATE_ROLE_PERMISSION | 更新角色权限 | | REVOKE_ROLE_PERMISSION | 移除角色权限 | | ASSIGN_USER_ROLE | 分配用户角色 | | REVOKE_USER_ROLE | 移除用户角色 | --- ## 前端实现指南 ### 1. 判断通用权限 ```javascript // 使用后端返回的 is_shared 字段 function isSharedPermission(permission) { return permission.is_shared === true; } ``` ### 2. 加载权限配置页面 ```javascript async function loadPermissionConfigPage(roleId) { // 1. 获取所有路由树 const routesRes = await fetch('/api/v3/routes?format=tree'); const routes = await routesRes.json(); // 2. 获取角色已有的权限 const rolePermRes = await fetch(`/api/v3/rbac/role-permissions?role_id=${roleId}`); const rolePermissions = await rolePermRes.json(); const checkedIds = new Set( rolePermissions.data.permissions .filter(p => p.grant_type === 'GRANT') .map(p => p.permission_id) ); // 3. 为每个路由加载权限 for (const route of flattenRoutes(routes)) { const permRes = await fetch(`/api/v3/routes/${route.id}/permissions`); const permData = await permRes.json(); route.permissions = permData.permissions.map(p => ({ ...p, checked: checkedIds.has(p.id) })); } return routes; } // 扁平化路由树 function flattenRoutes(routes, result = []) { for (const route of routes) { result.push(route); if (route.children) { flattenRoutes(route.children, result); } } return result; } ``` ### 3. 处理通用权限勾选同步 ```javascript // 权限勾选变化处理 function onPermissionCheck(permission, checked, allRoutes) { // 更新当前权限的勾选状态 permission.checked = checked; // 如果是通用权限,同步更新其他关联路由的显示 if (permission.is_shared && permission.related_routes) { permission.related_routes.forEach(routeId => { const route = findRouteById(allRoutes, routeId); if (route && route.permissions) { const samePerm = route.permissions.find(p => p.id === permission.id); if (samePerm) { samePerm.checked = checked; } } }); } } ``` ### 4. 保存权限配置 ```javascript async function saveRolePermissions(roleId, allRoutes) { // 收集所有勾选的权限(去重,通用权限只收集一次) const checkedPermissionIds = new Set(); flattenRoutes(allRoutes).forEach(route => { if (route.permissions) { route.permissions .filter(p => p.checked) .forEach(p => checkedPermissionIds.add(p.id)); } }); // 构建请求数据 const requestData = { role_id: roleId, permissions: Array.from(checkedPermissionIds).map(id => ({ permission_id: id, grant_type: 'GRANT', data_scope: 'DEPT' // 根据业务需求设置 })), replace: true }; // 提交 const response = await fetch('/api/v3/rbac/role-permissions', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(requestData) }); return response.json(); } ``` ### 5. UI 展示建议 ```jsx function PermissionItem({ permission, onChange }) { return (