Files
leaudit-platform-frontend/docs/role-permissions/FRONTEND_API_GUIDE.md
T
2026-05-06 09:42:29 +08:00

29 KiB
Raw Blame History

用户权限管理接口 - 前端对接文档

📋 文档信息

  • 版本: v3.0
  • 更新日期: 2025-11-26
  • API基础URL: http://YOUR_HOST:8000
  • 认证方式: JWT Bearer Token

⚠️ 重要提示 - 前端对接必读

1. Token过期处理

问题现象: API返回 code: 4001, msg: "token参数无效"

原因: JWT Token已过期(默认有效期1小时)

解决方案:

// 检查Token是否过期
const isTokenExpired = (token) => {
  try {
    const payload = JSON.parse(atob(token.split('.')[1]));
    return Date.now() >= payload.exp * 1000;
  } catch {
    return true;
  }
};

// 在发送请求前检查
if (isTokenExpired(token)) {
  await login(); // 重新登录获取新Token
}

2. 实际角色ID对应关系

⚠️ 数据库中的实际角色ID (请以实际数据为准):

角色名称 role_key 实际role_id 说明
省级管理员 provincial_admin 52 拥有完整RBAC管理权限
市级管理员 admin 1 负责本地区业务管理
普通员工 common 2 只能查看和管理自己的数据

调用示例:

// ✅ 正确:使用实际的role_id
const provincialAdminUsers = await getRoleUsers(52);
const adminUsers = await getRoleUsers(1);
const commonUsers = await getRoleUsers(2);

// ❌ 错误:使用Mock数据的ID
const wrongUsers = await getRoleUsers(3);  // 数据库中不存在

3. 响应格式说明

所有接口统一返回格式:

{
  "code": 200,
  "msg": "success",
  "data": { ... }
}

部分接口(如用户列表)直接返回数据对象:

{
  "users": [...],
  "total": 10
}

4. 权限要求

接口模块 权限要求 说明
RBAC管理接口 system:rbac:manage 仅provincial_admin角色
用户管理接口 JWT认证即可 所有登录用户
路由权限接口 JWT认证即可 所有登录用户

📚 接口总览

一、RBAC管理接口(18个)

基础路径: /api/v3/rbac

1.1 角色管理(5个接口)

方法 路径 说明
GET /roles 获取角色列表(支持分页、搜索)
GET /roles/{role_id} 获取角色详情
POST /roles 创建角色
PUT /roles/{role_id} 更新角色
DELETE /roles/{role_id} 删除角色(支持force参数)

1.2 权限管理(5个接口)

方法 路径 说明
GET /permissions 获取权限列表(支持树形/平铺)
GET /permissions/{permission_id} 获取权限详情
POST /permissions 创建权限
PUT /permissions/{permission_id} 更新权限
DELETE /permissions/{permission_id} 删除权限

1.3 角色权限关联(4个接口)

方法 路径 说明
GET /roles/{role_id}/permissions 获取角色的所有权限
POST /roles/{role_id}/permissions 批量分配权限给角色(支持替换/追加)
PUT /roles/{role_id}/permissions/{permission_id} 更新单个权限配置
DELETE /roles/{role_id}/permissions/{permission_id} 移除角色权限

1.4 用户角色管理(4个接口)

方法 路径 说明
GET /roles/{role_id}/users 获取拥有某角色的用户列表
GET /users/{user_id}/roles 获取用户的所有角色
POST /users/{user_id}/roles 为用户分配角色
DELETE /users/{user_id}/roles/{role_id} 移除用户角色

二、用户管理接口(3个)

基础路径: /admin/users

方法 路径 说明
GET /users 获取用户列表(支持分页、搜索)
GET /organizations 获取组织架构(树形结构)
GET /organizations/flat 获取组织列表(扁平结构)

三、路由权限接口(5个)

基础路径: /rbac

方法 路径 说明
GET /user/routes 获取当前用户可访问路由(树形)
GET /user/routes/flat 获取当前用户可访问路由(扁平)
GET /roles/{role_id}/routes 获取角色可访问路由
PUT /roles/{role_id}/routes 批量更新角色路由权限 新增
GET /check-route 检查路由访问权限

📖 详细接口说明

一、RBAC管理接口

1.1 获取角色列表

接口: GET /api/v3/rbac/roles

Query参数:

{
  page: 1,              // 页码
  page_size: 20,        // 每页数量
  role_key: "",         // 角色标识过滤(可选)
  role_name: "",        // 角色名称模糊搜索(可选)
  include_system: true  // 是否包含系统角色(可选)
}

响应示例:

{
  "code": 200,
  "message": "success",
  "data": {
    "total": 3,
    "page": 1,
    "page_size": 20,
    "items": [
      {
        "id": 52,
        "role_key": "provincial_admin",
        "role_name": "省级管理员",
        "description": "省级权限,可管理所有地区",
        "data_scope": "ALL",
        "is_system": true,
        "user_count": 1,
        "permission_count": 15
      },
      {
        "id": 1,
        "role_key": "admin",
        "role_name": "市级管理员",
        "data_scope": "DEPT",
        "is_system": true,
        "user_count": 6
      }
    ]
  }
}

1.2 创建角色

接口: POST /api/v3/rbac/roles

请求体参数:

字段 类型 必填 验证规则 示例
role_key string 必须以小写字母开头,只能包含小写字母、数字、下划线 department_leader
role_name string 任意字符,建议不超过50字 部门负责人
description string 角色描述 负责部门日常管理
data_scope string 可选值:ALL/DEPT/SELF,默认SELF DEPT
metadata object 自定义元数据 {}

role_key 验证规则:

  • 必须以小写字母开头:a-z
  • 只能包含:小写字母、数字、下划线
  • 正确示例:admin_role, department_leader, role123
  • 错误示例:1231(数字开头), Test_Role(大写), admin-role(连字符)

请求示例:

{
  "role_key": "department_leader",
  "role_name": "部门负责人",
  "description": "负责部门日常管理",
  "data_scope": "DEPT"
}

响应示例:

{
  "code": 200,
  "message": "角色创建成功",
  "data": {
    "id": 53,
    "role_key": "department_leader",
    "role_name": "部门负责人",
    "data_scope": "DEPT",
    "is_system": false
  }
}

错误响应示例:

{
  "code": 4002,
  "msg": "参数验证错误",
  "data": [
    {
      "type": "value_error",
      "loc": ["body", "role_key"],
      "msg": "Value error, role_key只能包含小写字母、数字、下划线,且必须以字母开头",
      "input": "1231"
    }
  ]
}

1.3 获取角色的所有用户

接口: GET /api/v3/rbac/roles/{role_id}/users

Query参数:

{
  page: 1,
  page_size: 20,
  area: "梅州",      // 按地区过滤(可选)
  username: "admin"  // 用户名模糊搜索(可选)
}

响应示例:

{
  "code": 200,
  "message": "success",
  "data": {
    "total": 6,
    "page": 1,
    "page_size": 20,
    "items": [
      {
        "user_id": 8,
        "username": "梅州烟草",
        "nick_name": "梅州烟草",
        "area": "梅州管理员账号",
        "ou_name": "梅州管理员账号",
        "phone_number": null,
        "email": null,
        "assigned_at": "2025-11-18T01:40:25.030949+00:00"
      }
    ]
  }
}

1.4 批量分配权限给角色

接口: POST /api/v3/rbac/roles/{role_id}/permissions

请求体:

{
  "permissions": [
    {
      "permission_id": 10,
      "grant_type": "GRANT",
      "data_scope": "ALL"
    },
    {
      "permission_id": 11,
      "grant_type": "GRANT",
      "data_scope": "DEPT"
    }
  ],
  "replace": true
}

参数说明:

  • replace: true=替换全部权限,false=追加权限
  • grant_type: GRANT(授予)或 DENY(拒绝)
  • data_scope: ALL(全部数据)/ DEPT(本部门)/ SELF(仅自己)

响应示例:

{
  "code": 200,
  "message": "权限分配成功",
  "data": {
    "role_id": 2,
    "assigned_count": 2
  }
}

1.5 为用户分配角色

接口: POST /api/v3/rbac/users/{user_id}/roles

请求体:

{
  "role_ids": [1, 2]
}

响应示例:

{
  "code": 200,
  "message": "角色分配成功",
  "data": {
    "user_id": 20,
    "username": "test_user",
    "assigned_roles": [
      {"role_id": 1, "role_name": "市级管理员"},
      {"role_id": 2, "role_name": "普通员工"}
    ]
  }
}

注意事项:

  • ⚠️ 不能给自己分配角色(防止提权)
  • ⚠️ provincial_admin角色只能由省级管理员分配
  • ⚠️ admin角色只能给本地区用户分配角色

二、用户管理接口

2.1 获取用户列表

接口: GET /admin/users/users

Query参数:

{
  page: 1,
  page_size: 20,
  ou_id: "000",        // 组织ID过滤(可选)
  is_leader: true,     // 是否领导过滤(可选)
  search: "admin"      // 搜索关键词(可选)
}

响应示例:

{
  "users": [
    {
      "id": 5,
      "username": "admin",
      "nick_name": "admin",
      "ou_id": "000",
      "ou_name": "test",
      "is_leader": true,
      "status": 0
    }
  ],
  "total": 10
}

⚠️ 已知问题: 当前版本 total 字段返回0,请以 users 数组长度为准。


2.2 获取组织架构(树形)

接口: GET /admin/users/organizations

Query参数:

{
  include_users: true  // 是否包含用户信息
}

响应示例:

{
  "organizations": [
    {
      "ou_id": "000",
      "ou_name": "总部",
      "parent_ou_id": null,
      "level": 0,
      "children": [
        {
          "ou_id": "0000000A1ML",
          "ou_name": "梅州市局",
          "parent_ou_id": "000",
          "level": 1,
          "users": [
            {
              "id": 8,
              "username": "梅州烟草",
              "nick_name": "梅州烟草",
              "ou_id": "0000000A1ML",
              "ou_name": "梅州市局"
            }
          ]
        }
      ],
      "users": []
    }
  ],
  "total_organizations": 5,
  "total_users": 10
}

三、路由权限接口

3.1 获取当前用户可访问路由

接口: GET /rbac/user/routes

响应示例:

{
  "code": 200,
  "msg": "success",
  "data": {
    "user_id": 5,
    "username": "admin",
    "routes": [
      {
        "id": 1,
        "route_path": "/",
        "route_name": "Home",
        "route_title": "首页",
        "component": "Layout",
        "parent_id": null,
        "icon": "home",
        "sort_order": 0,
        "is_hidden": false,
        "is_cache": true,
        "meta": {},
        "children": [
          {
            "id": 11,
            "route_path": "/dashboard",
            "route_name": "Dashboard",
            "route_title": "工作台",
            "parent_id": 1
          }
        ]
      }
    ],
    "routes_flat": [
      {"id": 1, "route_path": "/", "route_name": "Home"},
      {"id": 11, "route_path": "/dashboard", "route_name": "Dashboard"}
    ]
  }
}

说明:

  • routes: 树形结构(用于构建菜单)
  • routes_flat: 扁平结构(用于路由守卫权限检查)

3.2 获取角色可访问路由(含API权限)v3.0更新

接口: GET /rbac/roles/{role_id}/routes

v3.0 重大变更:

  • 返回格式从扁平列表改为树形结构
  • 每个路由节点新增 permissions 字段,包含该页面关联的所有API操作权限
  • 用于权限管理界面展示「页面 → API权限」的层级关系

响应示例:

{
  "code": 200,
  "msg": "success",
  "data": {
    "role_id": 1,
    "routes": [
      {
        "id": 31,
        "route_path": "/home",
        "route_name": "Home",
        "route_title": "系统概览",
        "parent_id": null,
        "icon": "ri-dashboard-line",
        "sort_order": 1,
        "is_hidden": false,
        "component": "views/Home.vue",
        "permissions": []
      },
      {
        "id": 41,
        "route_path": "/rules",
        "route_name": "Rules",
        "route_title": "规则管理",
        "parent_id": null,
        "icon": "ri-book-3-line",
        "sort_order": 3,
        "is_hidden": false,
        "component": "views/rules/Index.vue",
        "permissions": [
          {
            "id": 28,
            "permission_key": "evaluation_group:list:read",
            "display_name": "查看评查点分组列表",
            "api_method": "GET",
            "api_path": "/api/v3/evaluation-point-groups"
          },
          {
            "id": 30,
            "permission_key": "evaluation_group:create:write",
            "display_name": "创建评查点分组",
            "api_method": "POST",
            "api_path": "/api/v3/evaluation-point-groups"
          },
          {
            "id": 35,
            "permission_key": "evaluation_point:list:read",
            "display_name": "查看评查点规则列表",
            "api_method": "GET",
            "api_path": "/api/v3/evaluation-points"
          }
        ],
        "children": [
          {
            "id": 43,
            "route_path": "/rule-groups",
            "route_name": "RuleGroups",
            "route_title": "评查点分组",
            "parent_id": 41,
            "permissions": []
          }
        ]
      }
    ]
  }
}

字段说明:

字段 类型 说明
id int 路由ID
route_path string 前端路由路径
route_name string 路由名称(用于Vue router name
route_title string 页面标题(用于菜单显示)
parent_id int/null 父路由IDnull表示顶级路由
icon string 菜单图标
sort_order int 排序顺序
is_hidden bool 是否隐藏(不显示在侧边栏)
component string Vue组件路径
permissions array 关联的API权限列表
children array 子路由列表(可选)

permissions 子字段说明:

字段 类型 说明
id int 权限ID
permission_key string 权限标识(用于权限检查)
display_name string 权限显示名称
api_method string HTTP方法(GET/POST/PUT/DELETE等)
api_path string API路径

3.3 批量更新角色路由权限

接口: PUT /rbac/roles/{role_id}/routes

功能说明:

  • 批量更新指定角色的路由权限
  • 采用替换模式:先删除现有所有关联,再插入新关联
  • 自动清除相关缓存(角色缓存 + 用户缓存)

请求体:

{
  "route_ids": [1, 11, 12, 3, 31, 32, 2, 21],
  "permission": "RW"
}

参数说明:

  • route_ids: 路由ID列表(必填)
  • permission: 权限类型,可选值:
    • R: 只读权限
    • W: 只写权限
    • RW: 读写权限(默认)

响应示例:

{
  "code": 200,
  "msg": "success",
  "data": {
    "role_id": 2,
    "assigned_count": 8,
    "removed_count": 5,
    "route_ids": [1, 11, 12, 3, 31, 32, 2, 21]
  }
}

前端调用示例:

const updateRoleRoutes = async (roleId, routeIds) => {
  const response = await fetch(`/rbac/roles/${roleId}/routes`, {
    method: 'PUT',
    headers: {
      'Authorization': `Bearer ${token}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      route_ids: routeIds,
      permission: 'RW'
    })
  });

  const result = await response.json();

  if (result.code === 200) {
    console.log(`成功分配 ${result.data.assigned_count} 个路由`);
    console.log(`移除了 ${result.data.removed_count} 个旧路由`);
  }

  return result;
};

// 使用示例
await updateRoleRoutes(2, [1, 11, 12, 3, 31, 32, 2, 21]);

注意事项:

  • ⚠️ 所有 route_ids 必须存在且未删除
  • ⚠️ 使用事务确保数据一致性
  • ⚠️ 会自动清除所有受影响用户的路由缓存

3.4 检查路由访问权限

接口: GET /rbac/check-route

Query参数:

{
  route_path: "/system/users"
}

响应示例:

{
  "code": 200,
  "msg": "success",
  "data": {
    "route_path": "/system/users",
    "has_access": true
  }
}

🚨 错误码说明

HTTP状态码

状态码 说明 处理建议
200 成功 -
400 请求参数错误 检查请求体格式和必填字段
401 未认证 Token过期或无效,需要重新登录
403 无权限 显示权限不足提示
404 资源不存在 检查ID是否正确
409 冲突 如role_key重复
500 服务器错误 联系后端排查

常见错误处理

// 统一错误处理
const handleError = (error) => {
  if (error.response?.status === 401) {
    // Token过期,跳转登录
    localStorage.removeItem('token');
    window.location.href = '/login';
  } else if (error.response?.status === 403) {
    alert('权限不足');
  } else if (error.response?.data?.detail) {
    alert(error.response.data.detail);
  } else {
    alert('操作失败,请稍后重试');
  }
};

💡 常见问题FAQ

Q1: 为什么所有接口返回 code: 4001?

A: Token已过期,请重新登录获取新Token

Q2: role_id应该用哪个?文档里写的1,2,3还是52,1,2

A: 使用实际数据库中的ID

  • provincial_admin = 52
  • admin = 1
  • common = 2

Q3: 需要用Mock数据吗?

A: 不需要,所有接口已完整实现,直接调用真实API

Q4: 如何判断当前用户是否有RBAC管理权限?

// 方式1:检查JWT中的user_role
const payload = JSON.parse(atob(token.split('.')[1]));
const isProvincialAdmin = payload.user_role === 'provincial_admin';

// 方式2:调用权限检查接口(推荐)
const routes = await fetch('/rbac/user/routes');
const hasRBACAccess = routes.data.routes.some(r => r.route_path === '/rbac');

Q5: 如何实现角色权限页面的路由分配功能?

A: 使用新的批量更新接口 PUT /rbac/roles/{role_id}/routes:

  1. 通过 GET /rbac/roles/{role_id}/routes 获取当前角色已有路由
  2. 用户选择要分配的路由ID列表
  3. 调用 PUT /rbac/roles/{role_id}/routes 提交更新
  4. 接口会自动替换所有路由权限并清除缓存

Q6: total字段为什么返回0

A: /admin/users/users 接口的 total 字段当前版本存在bug,请以 users 数组长度为准。该问题已记录,将在后续版本修复。

Q7: 批量更新路由权限后,用户需要重新登录吗?

A: 不需要。接口会自动清除相关用户的路由缓存,用户刷新页面即可看到新权限。


📦 前端开发清单

  • 移除所有RBAC相关的Mock数据
  • 使用实际的role_id52, 1, 2
  • 实现Token过期自动刷新机制
  • 处理401/403错误(跳转登录/权限提示)
  • 使用 PUT /rbac/roles/{role_id}/routes 实现路由权限分配
  • 处理 total 字段为0的情况(用数组长度代替)
  • v3.0新增: 适配新的路由权限接口(含permissions字段)

🎯 v3.0 前端修改思路说明

一、架构变更说明

变更前(v2.0:

sys_routes 表:同时存储页面路由和API接口路由
└── 侧边栏展示所有路由(包括API接口)❌ 不符合预期

变更后(v3.0:

sys_routes 表:仅存储页面路由(侧边栏菜单)
permissions 表:存储API操作权限(通过 route_id 关联到页面)

页面路由
├── 规则管理 (/rules)
│   ├── [权限] 查看评查点分组列表 (GET /api/v3/evaluation-point-groups)
│   ├── [权限] 创建评查点分组 (POST /api/v3/evaluation-point-groups)
│   ├── [权限] 查看评查点规则列表 (GET /api/v3/evaluation-points)
│   └── ...
└── 系统设置 (/settings)
    └── [子页面] 角色权限管理 (/role-permissions)

二、权限管理界面修改思路

2.1 数据结构适配

// 新的路由类型定义
interface RouteWithPermissions {
  id: number;
  route_path: string;
  route_name: string;
  route_title: string;
  parent_id: number | null;
  icon: string;
  sort_order: number;
  is_hidden: boolean;
  component: string;
  permissions: Permission[];  // 新增:关联的API权限
  children?: RouteWithPermissions[];
}

interface Permission {
  id: number;
  permission_key: string;
  display_name: string;
  api_method: string;
  api_path: string;
}

2.2 权限分配界面布局建议

┌─────────────────────────────────────────────────────────────┐
│ 角色权限管理 - 市级管理员                                      │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  ☑ 系统概览 (/home)                                         │
│                                                             │
│  ☑ 规则管理 (/rules)                                       │
│     ├─ ☑ 查看评查点分组列表 [GET]                            │
│     ├─ ☑ 创建评查点分组 [POST]                               │
│     ├─ ☑ 更新评查点分组 [PUT]                                │
│     ├─ ☐ 删除评查点分组 [DELETE]  ← 未勾选                   │
│     ├─ ☑ 查看评查点规则列表 [GET]                            │
│     └─ ...                                                  │
│                                                             │
│  ☐ 系统设置 (/settings)                                      │
│     └─ ☑ 角色权限管理 (/role-permissions)                    │
│                                                             │
└─────────────────────────────────────────────────────────────┘

2.3 前端组件实现示例

<template>
  <div class="role-permission-manager">
    <h3>角色权限管理 - {{ role.role_name }}</h3>

    <!-- 路由权限树 -->
    <el-tree
      :data="routeTree"
      show-checkbox
      node-key="id"
      :default-checked-keys="checkedRouteIds"
      :props="treeProps"
      @check="handleRouteCheck"
    >
      <template #default="{ node, data }">
        <span class="route-node">
          <i :class="data.icon"></i>
          {{ data.route_title }}

          <!-- 展示该路由关联的API权限 -->
          <div v-if="data.permissions?.length" class="permission-list">
            <el-checkbox-group v-model="checkedPermissions[data.id]">
              <el-checkbox
                v-for="perm in data.permissions"
                :key="perm.id"
                :label="perm.id"
              >
                <el-tag :type="getMethodTagType(perm.api_method)" size="small">
                  {{ perm.api_method }}
                </el-tag>
                {{ perm.display_name }}
              </el-checkbox>
            </el-checkbox-group>
          </div>
        </span>
      </template>
    </el-tree>

    <el-button type="primary" @click="savePermissions">保存权限</el-button>
  </div>
</template>

<script setup>
import { ref, onMounted } from 'vue'

const routeTree = ref([])
const checkedRouteIds = ref([])
const checkedPermissions = ref({}) // { routeId: [permissionId, ...] }

// 获取角色路由权限
const fetchRoleRoutes = async (roleId) => {
  const res = await fetch(`/rbac/roles/${roleId}/routes`, {
    headers: { 'Authorization': `Bearer ${token}` }
  })
  const { data } = await res.json()
  routeTree.value = data.routes

  // 初始化已选中的路由和权限
  initCheckedState(data.routes)
}

// 根据HTTP方法返回标签类型
const getMethodTagType = (method) => {
  const types = {
    'GET': 'success',
    'POST': 'primary',
    'PUT': 'warning',
    'DELETE': 'danger',
    'PATCH': 'info'
  }
  return types[method] || 'info'
}

// 保存权限
const savePermissions = async () => {
  // 1. 保存路由权限
  await fetch(`/rbac/roles/${roleId}/routes`, {
    method: 'PUT',
    headers: {
      'Authorization': `Bearer ${token}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      route_ids: checkedRouteIds.value,
      permission: 'RW'
    })
  })

  // 2. 保存功能权限(如需细粒度控制)
  // await saveRolePermissions(roleId, flattenPermissions())

  ElMessage.success('权限保存成功')
}
</script>

三、权限检查逻辑修改

3.1 按钮级权限控制

// 权限指令 v-permission
app.directive('permission', {
  mounted(el, binding) {
    const { value } = binding  // permission_key
    const userPermissions = store.state.user.permissions

    if (!userPermissions.includes(value)) {
      el.parentNode?.removeChild(el)
    }
  }
})

// 使用示例
<el-button
  v-permission="'evaluation_group:create:write'"
  @click="handleCreate"
>
  新建分组
</el-button>

3.2 API请求权限校验

// 请求拦截器中添加权限检查
axios.interceptors.request.use((config) => {
  const { method, url } = config
  const requiredPermission = findPermissionByApi(method, url)

  if (requiredPermission && !hasPermission(requiredPermission)) {
    ElMessage.error('无权执行此操作')
    return Promise.reject(new Error('Permission denied'))
  }

  return config
})

四、数据流程图

┌──────────────┐     GET /rbac/roles/{id}/routes     ┌──────────────┐
│   前端页面    │ ─────────────────────────────────→ │   后端API    │
│  权限管理     │                                     │              │
└──────────────┘                                     └──────────────┘
       │                                                    │
       │                                                    ▼
       │                                            ┌──────────────┐
       │                                            │  数据库查询   │
       │                                            │ sys_routes   │
       │                                            │ permissions  │
       │                                            │ role_route   │
       │                                            └──────────────┘
       │                                                    │
       │         返回树形结构(含permissions                │
       │ ←──────────────────────────────────────────────────┘
       │
       ▼
┌──────────────────────────────────────────────────────────────────┐
│  渲染权限树                                                       │
│  ├── 页面路由节点(可展开)                                        │
│  │   └── API权限列表(checkbox                                  │
│  └── 用户勾选/取消勾选                                            │
└──────────────────────────────────────────────────────────────────┘
       │
       │ PUT /rbac/roles/{id}/routes  (保存路由权限)
       │ POST /api/v3/rbac/roles/{id}/permissions  (保存功能权限)
       ▼
┌──────────────┐
│   权限生效    │
│  用户刷新后   │
│  看到新权限   │
└──────────────┘

五、迁移检查清单

序号 检查项 状态
1 更新 GET /rbac/roles/{role_id}/routes 接口调用,适配新的树形返回格式
2 权限管理界面支持展示「页面路由 → API权限」层级结构
3 添加 permissions 字段的 TypeScript 类型定义
4 实现按钮级权限控制(使用 permission_key
5 测试权限保存和刷新后生效

📞 技术支持

如有问题,请联系后端开发团队。

文档版本: v3.0 最后更新: 2025-11-26 维护者: Backend Team