Files
leaudit-platform-frontend/auth_doc/通用权限前端对接文档.md
LiangShiyong d4000cd292 fix: 1. 继续对齐交叉评查的接口,完善创建交叉评查的逻辑 和 相关组件的渲染布局。
2. 文档的基本信息修改改用接口。      3. 重新完善角色权限管理的页面逻辑。     4.将评查点列表中的返回逻辑改用浏览器的记忆返回。
2025-12-12 12:00:36 +08:00

35 KiB
Raw Permalink Blame History

RBAC 权限管理前端对接文档

概述

本文档详细说明 RBAC(基于角色的访问控制)模块的所有 API 接口和业务逻辑,包括:

  • 角色管理(5个接口)
  • 权限管理(5个接口)
  • 角色权限关联(4个接口)
  • 用户角色管理(4个接口)
  • 路由管理(3个接口)

总计:21个 API 接口


目录

  1. 核心概念
  2. 角色管理 API
  3. 权限管理 API
  4. 角色权限关联 API
  5. 用户角色管理 API
  6. 路由管理 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. 获取角色列表

请求

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 是否包含系统角色

响应

{
    "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. 获取角色详情

请求

GET /api/v3/rbac/roles/{role_id}

权限要求: system:rbac:manage

Path 参数

参数 类型 必填 说明
role_id int 角色ID

响应

{
    "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. 创建角色

请求

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 扩展元数据

响应

{
    "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. 更新角色

请求

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 扩展元数据

响应

{
    "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. 删除角色

请求

DELETE /api/v3/rbac/roles/{role_id}?force=false

权限要求: system:rbac:manage

Query 参数

参数 类型 必填 默认值 说明
force bool false 强制删除(自动解除用户关联)

响应

{
    "code": 200,
    "message": "角色删除成功: 评查员",
    "data": {
        "role_id": 10,
        "deleted_users": 5
    }
}

业务逻辑

  • 系统角色(is_system=true)禁止删除
  • provincial_admin 角色绝对禁止删除
  • 删除时自动解除用户关联、角色权限关联
  • 操作会记录到审计日志

权限管理 API

1. 获取权限列表

请求

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 是否包含系统权限

响应(树形格式)

[
    {
        "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. 获取权限详情

请求

GET /api/v3/rbac/permissions/{permission_id}

权限要求: system:rbac:manage

响应

{
    "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. 创建权限

请求

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 扩展元数据

响应

{
    "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. 更新权限

请求

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. 删除权限

请求

DELETE /api/v3/rbac/permissions/{permission_id}?force=false

权限要求: system:rbac:manage

Query 参数

参数 类型 默认值 说明
force bool false 强制删除(自动解除角色关联)

响应

{
    "code": 200,
    "message": "权限删除成功: 导出评查结果",
    "data": {
        "permission_id": 100,
        "deleted_role_relations": 3
    }
}

业务逻辑

  • 系统权限禁止删除
  • 有子权限的权限禁止删除(必须先删除子权限)
  • force=false 时,有角色关联则拒绝删除
  • force=true 时,自动解除角色关联后删除
  • 操作会记录到审计日志

角色权限关联 API

1. 获取角色的所有权限

请求

GET /api/v3/rbac/role-permissions?role_id=2

权限要求: system:rbac:manage

Query 参数

参数 类型 必填 说明
role_id int 角色ID

响应

{
    "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. 批量分配角色权限

请求

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: 追加模式(保留现有权限,追加新权限)

响应

{
    "code": 200,
    "message": "成功替换权限",
    "data": {
        "role_id": 2,
        "role_name": "市级管理员",
        "assigned_count": 3,
        "replace": true
    }
}

业务逻辑

  • 验证所有 permission_id 必须存在
  • provincial_admin 角色的核心权限不可移除(即使在replace模式下)
  • 核心权限:system:rbac:managesystem:*:*
  • 操作会记录到审计日志

3. 更新单个角色权限

请求

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

响应

{
    "code": 200,
    "message": "权限更新成功",
    "data": {
        "id": 1,
        "role_id": 2,
        "permission_id": 10,
        "grant_type": "DENY",
        "data_scope": "SELF"
    }
}

4. 移除角色权限

请求

DELETE /api/v3/rbac/role-permissions?role_id=2&permission_id=10

权限要求: system:rbac:manage

Query 参数

参数 类型 必填 说明
role_id int 角色ID
permission_id int 权限ID

响应

{
    "code": 200,
    "message": "成功移除角色权限: 市级管理员 - 查看文档列表",
    "data": {
        "role_id": 2,
        "permission_id": 10
    }
}

业务逻辑

  • provincial_admin 角色的核心权限不可移除
  • 核心权限列表:system:rbac:managesystem:*:*
  • 操作会记录到审计日志

用户角色管理 API

1. 获取角色的所有用户

请求

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 - 用户名模糊搜索

响应

{
    "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. 获取用户的所有角色

请求

GET /api/v3/rbac/users/{user_id}/roles

权限要求: system:rbac:manage

Path 参数

参数 类型 必填 说明
user_id int 用户ID

响应

{
    "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. 为用户分配角色

请求

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列表

响应

{
    "code": 200,
    "message": "角色分配成功",
    "data": {
        "user_id": 100,
        "username": "zhangsan",
        "assigned_roles": [
            {"role_id": 2, "role_name": "市级管理员"}
        ]
    }
}

业务逻辑

  • 一个用户只能拥有一个角色
  • 如果用户已有角色,需要先移除再分配新角色
  • 禁止给自己分配角色(防止自己提权)
  • admin 只能给本地区用户分配角色
  • admin 不能分配 provincial_adminadmin 角色(只有省级管理员可以)
  • 操作会记录到审计日志

4. 移除用户角色

请求

DELETE /api/v3/rbac/users/{user_id}/roles/{role_id}

权限要求: system:rbac:manage

Path 参数

参数 类型 必填 说明
user_id int 用户ID
role_id int 角色ID

响应

{
    "code": 200,
    "message": "成功移除用户角色: zhangsan - 市级管理员",
    "data": {
        "user_id": 100,
        "role_id": 2
    }
}

业务逻辑

  • 禁止移除自己的角色(防止自锁)
  • admin 只能移除本地区用户的角色
  • admin 不能移除用户的 provincial_adminadmin 角色
  • 操作会记录到审计日志

路由管理 API

1. 获取所有路由列表

请求

GET /api/v3/routes?format=tree&include_hidden=false

权限要求: 仅需登录

Query 参数

参数 类型 必填 默认值 说明
format string tree 返回格式(tree/flat
include_hidden bool false 是否包含隐藏路由

响应(树形格式)

[
    {
        "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. 获取路由详情

请求

GET /api/v3/routes/{route_id}

权限要求: 仅需登录

响应

{
    "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. 获取路由的所有权限(含通用权限)核心接口

请求

GET /api/v3/routes/{route_id}/permissions

权限要求: 仅需登录

响应

{
    "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逻辑:

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 无关:

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
  • 两个页面自动都会有该权限
// 正确:通用权限只提交一次
{
    "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. 判断通用权限

// 使用后端返回的 is_shared 字段
function isSharedPermission(permission) {
    return permission.is_shared === true;
}

2. 加载权限配置页面

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. 处理通用权限勾选同步

// 权限勾选变化处理
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. 保存权限配置

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 展示建议

function PermissionItem({ permission, onChange }) {
    return (
        <div className={`permission-item ${permission.is_shared ? 'shared' : ''}`}>
            <Checkbox
                checked={permission.checked}
                onChange={(e) => onChange(permission, e.target.checked)}
            />
            <span className="permission-name">
                {permission.is_shared && <Tag color="blue">通用</Tag>}
                {permission.display_name}
            </span>
            <span className="permission-api">
                {permission.api_method} {permission.api_path}
            </span>
            {permission.is_shared && (
                <Tooltip title={`此权限同时适用于路由: ${permission.related_routes.join(', ')}`}>
                    <InfoCircleOutlined />
                </Tooltip>
            )}
        </div>
    );
}

6. 样式参考

.permission-item {
    display: flex;
    align-items: center;
    padding: 8px 12px;
    border-bottom: 1px solid #f0f0f0;
}

.permission-item.shared {
    background-color: #f0f7ff;
    border-left: 3px solid #1890ff;
}

.permission-name {
    flex: 1;
    margin-left: 8px;
}

.permission-api {
    color: #999;
    font-size: 12px;
    font-family: monospace;
}

API 接口汇总

角色管理(5个)

接口 方法 权限要求 说明
/api/v3/rbac/roles GET 登录 获取角色列表
/api/v3/rbac/roles/{role_id} GET system:rbac:manage 获取角色详情
/api/v3/rbac/roles POST system:rbac:manage 创建角色
/api/v3/rbac/roles/{role_id} PUT system:rbac:manage 更新角色
/api/v3/rbac/roles/{role_id} DELETE system:rbac:manage 删除角色

权限管理(5个)

接口 方法 权限要求 说明
/api/v3/rbac/permissions GET system:rbac:manage 获取权限列表
/api/v3/rbac/permissions/{permission_id} GET system:rbac:manage 获取权限详情
/api/v3/rbac/permissions POST system:rbac:manage 创建权限
/api/v3/rbac/permissions/{permission_id} PUT system:rbac:manage 更新权限
/api/v3/rbac/permissions/{permission_id} DELETE system:rbac:manage 删除权限

角色权限关联(4个)

接口 方法 权限要求 说明
/api/v3/rbac/role-permissions GET system:rbac:manage 获取角色的所有权限
/api/v3/rbac/role-permissions POST system:rbac:manage 批量分配角色权限
/api/v3/rbac/role-permissions PUT system:rbac:manage 更新单个角色权限
/api/v3/rbac/role-permissions DELETE system:rbac:manage 移除角色权限

用户角色管理(4个)

接口 方法 权限要求 说明
/api/v3/rbac/roles/{role_id}/users GET 登录 获取角色的所有用户
/api/v3/rbac/users/{user_id}/roles GET system:rbac:manage 获取用户的所有角色
/api/v3/rbac/users/{user_id}/roles POST system:rbac:manage 为用户分配角色
/api/v3/rbac/users/{user_id}/roles/{role_id} DELETE system:rbac:manage 移除用户角色

路由管理(3个)

接口 方法 权限要求 说明
/api/v3/routes GET 登录 获取所有路由列表
/api/v3/routes/{route_id} GET 登录 获取路由详情
/api/v3/routes/{route_id}/permissions GET 登录 获取路由的所有权限(含通用权限)

当前通用权限数据

id permission_key display_name related_routes
88 evaluation:audit_status:view 查看审计状态 [58, 37]
89 evaluation:audit_status:update 更新审计状态 [58, 37]
136 evaluation:result:update 更新评查结果 [58, 37]
137 evaluation:audit_status:create 创建审核状态 [58, 37]
138 evaluation:document:confirm 确认文档审核完成 [58, 37]

关联的路由

route_id route_title route_path
58 文档评查结果详情 /reviews
37 评查结果 /cross-checking/result

更新记录

日期 版本 说明
2025-12-11 3.0 完整 RBAC 文档,包含 21 个 API 接口和详细业务逻辑
2025-12-11 2.0 使用 FastAPI 专用接口,删除 PostgREST 方式