/** * 角色权限管理 API * 用于角色、路由权限、用户角色的管理 */ // ==================== 常量定义 ==================== /** * RBAC API 基础路径 * 注意:使用相对路径,会命中Remix API路由而不是后端服务器 */ const RBAC_API_BASE = '/api/v3/rbac'; /** * 统一响应处理函数 * 处理后端返回的统一格式响应 */ function handleApiResponse(response: ApiResponse): T { if (response.error) { throw new Error(response.error); } if (response.data && 'code' in response.data) { if (response.data.code !== 200) { throw new Error(response.data.message || '请求失败'); } return response.data.data as T; } // 如果没有code字段,直接返回data return response.data as T; } // ==================== 类型定义 ==================== /** * API权限信息(关联到路由的权限) * v3.0新增:每个路由可以关联多个API操作权限 */ export interface ApiPermission { id: number; permission_key: string; // 权限标识,如 "evaluation_group:create:write" display_name: string; // 显示名称,如 "创建评查点分组" api_method: string; // HTTP方法:GET | POST | PUT | DELETE api_path: string; // API路径,如 "/api/v3/evaluation-point-groups" } /** * 路由信息 */ export interface RouteInfo { id: number; route_path: string; route_name: string; route_title: string; component?: string; parent_id?: number | null; icon?: string; sort_order: number; is_hidden: boolean; is_cache: boolean; status: number; permissions?: ApiPermission[]; // v3.0新增:关联的API权限列表 children?: RouteInfo[]; } /** * 角色信息 */ export interface RoleInfo { id: number; role_key: string; role_name: string; data_scope: string; description: string; parent_role_id?: number | null; priority: number; is_system_role: boolean; created_at: string; updated_at: string; } /** * 角色-路由权限关联 */ export interface RoleRoutePermission { id: number; role_id: number; route_id: number; permission: string; // 'R' | 'RW' | 'NONE' created_at: string; } /** * 用户信息 */ export interface UserInfo { id: number; username: string; nick_name: string; phone_number?: string; email?: string; area: string; // v3.3: 地区字段,用于权限隔离(省/市级别) ou_name: string; // 部门名称,用于组织显示(部门级别) status: number; is_leader: boolean; } /** * 用户-角色关联 */ export interface UserRoleRelation { id: number; user_id: number; role_id: number; created_at: string; } /** * RBAC权限信息 */ export interface Permission { id: number; permission_key: string; // 格式: module:resource:action module: string; // 模块名 resource: string; // 资源名 action: string; // 操作名 display_name: string; // 显示名称 description: string | null; permission_type: 'API' | 'MENU' | 'BUTTON'; is_system: boolean; parent_id: number | null; sort_order: number; children?: Permission[]; // 树形结构 } /** * 角色权限配置 */ export interface RolePermissionConfig { permission_id: number; grant_type?: 'GRANT' | 'DENY'; data_scope?: 'ALL' | 'DEPT' | 'SELF'; } /** * 角色权限详情 */ export interface RolePermissionDetail { id: number; permission_id: number; permission_key: string; display_name: string; grant_type: 'GRANT' | 'DENY'; data_scope: 'ALL' | 'DEPT' | 'SELF'; } /** * 获取所有角色列表 * @param params 查询参数 */ export async function getRoles(params?: { page?: number; page_size?: number; role_key?: string; role_name?: string; include_system?: boolean; }): Promise { try { // 导入 axios-client 的 get 函数 const { get } = await import('~/api/axios-client'); // 使用 axios-client 的 get 函数调用真实后端API const response = await get(`/api/v3/rbac/roles`, params || {}); if (response.error) { throw new Error(response.error); } // 后端响应格式: { code: 200, message: "success", data: { total, page, page_size, items: [...] } } let items: any[] = []; if (response.data && response.data.data && Array.isArray(response.data.data.items)) { items = response.data.data.items; } else if (response.data && Array.isArray(response.data.items)) { items = response.data.items; } // 数据格式转换(后端字段 -> 前端字段) const roles = items.map(role => ({ id: role.id, role_key: role.role_key, role_name: role.role_name, data_scope: role.data_scope, description: role.description || '', parent_role_id: role.parent_role_id || null, priority: role.priority || 0, is_system_role: (role.role_key == 'admin' || role.role_key == 'common') ? true : role.is_system || false, created_at: role.created_at, updated_at: role.updated_at })); return roles; } catch (error) { console.error('❌ [getRoles] 获取角色列表失败:', error); // 失败时返回空数组 return []; } } /** * 获取角色详情 * @param roleId 角色ID */ export async function getRoleDetail(roleId: number): Promise { try { const response = await get(`${RBAC_API_BASE}/roles/${roleId}`); const role = handleApiResponse(response); return { id: role.id, role_key: role.role_key, role_name: role.role_name, data_scope: role.data_scope, description: role.description || '', parent_role_id: role.parent_role_id || null, priority: role.priority || 0, is_system_role: role.is_system, created_at: role.created_at, updated_at: role.updated_at }; } catch (error) { console.error('获取角色详情失败:', error); return null; } } /** * 获取所有路由(树形结构) * 从后端API获取当前用户可访问的所有路由 */ export async function getRoutes(): Promise { try { const { get } = await import('~/api/axios-client'); // 调用后端API获取当前用户的路由(provincial_admin应该有所有路由权限) const response = await get('/rbac/user/routes'); if (response.error) { console.error('❌ [getRoutes] API调用失败:', response.error); throw new Error(response.error); } // 后端响应格式: { code: 200, msg: "success", data: { user_id, username, routes: [...], routes_flat: [...] } } let routes: any[] = []; if (response.data && response.data.data && Array.isArray(response.data.data.routes)) { routes = response.data.data.routes; } else if (response.data && Array.isArray(response.data.routes)) { // 兼容可能的响应格式 routes = response.data.routes; } // 将后端数据转换为前端RouteInfo格式 const mapRouteData = (route: any): RouteInfo => ({ id: route.id, route_path: route.route_path, route_name: route.route_name, route_title: route.route_title, icon: route.icon || '', sort_order: route.sort_order || 0, is_hidden: route.is_hidden || false, is_cache: route.is_cache !== false, // 默认true status: route.status || 1, parent_id: route.parent_id || null, component: route.component, children: route.children ? route.children.map(mapRouteData) : undefined }); console.log('获取当前用户的路由', routes.map(mapRouteData) ) return routes.map(mapRouteData); } catch (error) { console.error('❌ [getRoutes] 获取路由数据失败:', error); // 失败时返回空数组,让前端显示错误提示 return []; } } /** * 获取指定角色的路由权限 * @param roleId 角色ID */ export async function getRoleRoutePermissions(roleId: number): Promise { try { // 导入 axios-client 的 get 函数 const { get } = await import('~/api/axios-client'); // 使用 axios-client 的 get 函数调用真实后端API const response = await get(`/rbac/roles/${roleId}/routes`); if (response.error) { throw new Error(response.error); } // 后端响应格式: { code: 200, msg: "success", data: { role_id, routes: [...] } } let routes: any[] = []; if (response.data && response.data.data && Array.isArray(response.data.data.routes)) { routes = response.data.data.routes; } // 将路由数据转换为RoleRoutePermission格式 const permissions = routes.map((route, index) => ({ id: index + 1, role_id: roleId, route_id: route.id, permission: 'RW', // 默认读写权限 created_at: new Date().toISOString() })); console.log("路由权限数据", permissions) return permissions; } catch (error) { console.error('❌ [getRoleRoutePermissions] 获取角色路由权限失败:', error); // 失败时返回空数组,避免页面崩溃 return []; } } /** * 获取角色的路由权限(含API权限)- v3.0新增 * 返回树形结构的路由,每个路由包含关联的API权限 * @param roleId 角色ID */ export async function getRoleRoutesWithPermissions(roleId: number): Promise<{ routes: RouteInfo[]; selectedRouteIds: number[]; selectedPermissionIds: number[]; }> { try { const { get } = await import('~/api/axios-client'); const response = await get(`/rbac/roles/${roleId}/routes`); if (response.error) { throw new Error(response.error); } // 后端响应格式: { code: 200, msg: "success", data: { role_id, routes: [...] } } let routes: any[] = []; if (response.data && response.data.data && Array.isArray(response.data.data.routes)) { routes = response.data.data.routes; } else if (response.data && Array.isArray(response.data.routes)) { routes = response.data.routes; } // 递归转换路由数据格式 const mapRouteData = (route: any): any => ({ id: route.id, route_path: route.route_path, route_name: route.route_name, route_title: route.route_title, icon: route.icon || '', sort_order: route.sort_order || 0, is_hidden: route.is_hidden || false, is_cache: route.is_cache !== false, status: route.status || 1, parent_id: route.parent_id || null, component: route.component, // v3.2: 添加 enabled 字段 enabled: route.enabled !== undefined ? route.enabled : true, // v3.0: 转换permissions数组 permissions: Array.isArray(route.permissions) ? route.permissions.map((p: any) => ({ id: p.id, permission_key: p.permission_key, display_name: p.display_name, api_method: p.api_method, api_path: p.api_path })) : [], children: route.children ? route.children.map(mapRouteData) : undefined }); const mappedRoutes = routes.map(mapRouteData); // v3.2: 收集已启用的路由ID(enabled=true) const collectRouteIds = (routes: any[]): number[] => { let ids: number[] = []; routes.forEach(route => { // v3.2: 只收集 enabled=true 的路由 if (route.enabled) { ids.push(route.id); } if (route.children) { ids = ids.concat(collectRouteIds(route.children)); } }); return ids; }; // v3.5: 修复BUG - 删除了 collectPermissionIds 函数 // BUG说明:从路由元数据收集权限ID是错误的,因为路由的permissions数组包含的仅仅是权限定义, // 而不是实际授权状态。实际授权状态应该从 `/api/v3/rbac/role-permissions` 接口获取。 // // 之前的错误实现: // const collectPermissionIds = (routes: RouteInfo[]): number[] => { // let ids: number[] = []; // routes.forEach(route => { // if (route.permissions) { // ids = ids.concat(route.permissions.map(p => p.id)); // } // }); // return ids; // }; // // 修复方案:返回空数组,由调用方使用 getRolePermissions() 获取实际授权数据 const selectedRouteIds = collectRouteIds(mappedRoutes); const selectedPermissionIds: number[] = []; // v3.5: 修复BUG - 返回空数组 return { routes: mappedRoutes, selectedRouteIds, selectedPermissionIds }; } catch (error) { console.error('❌ [getRoleRoutesWithPermissions] 获取角色路由权限失败:', error); return { routes: [], selectedRouteIds: [], selectedPermissionIds: [] }; } } /** * 保存角色的API权限 - v3.0新增 * @param roleId 角色ID * @param permissionIds 权限ID数组 */ export async function saveRoleApiPermissions( roleId: number, permissionIds: number[] ): Promise<{ success: boolean; message: string }> { try { const { post } = await import('~/api/axios-client'); // 构建权限配置 const permissions = permissionIds.map(id => ({ permission_id: id, grant_type: 'GRANT', data_scope: 'ALL' })); // v3.4: 使用文档规范的API路径(查询参数方式) const response = await post('/api/v3/rbac/role-permissions', { role_id: roleId, permissions, replace: true // 替换模式:先删除现有权限,再插入新权限 }); if (response.error) { throw new Error(response.error); } let message = 'API权限保存成功'; if (response.data && response.data.message) { message = response.data.message; } else if (response.data && response.data.data) { const { assigned_count } = response.data.data; message = `成功分配 ${assigned_count} 个API权限`; } return { success: true, message }; } catch (error) { console.error('❌ [saveRoleApiPermissions] 保存API权限失败:', error); return { success: false, message: error instanceof Error ? error.message : '保存API权限失败' }; } } /** * 更新角色的路由权限 - v3.2更新 * @param roleId 角色ID * @param routeIds 路由ID数组 */ export async function updateRoleRoutePermissions( roleId: number, routeIds: number[] ): Promise<{ success: boolean; message: string; code?: number }> { try { // 导入 axios-client 的 put 函数 const { put } = await import('~/api/axios-client'); // 使用 axios-client 的 put 函数调用真实后端API const response = await put(`/rbac/roles/${roleId}/routes`, { route_ids: routeIds, permission: 'RW' }); if (response.error) { throw new Error(response.error); } // v3.3: 处理权限不足错误 if (response.data && response.data.code === 4003) { return { success: false, message: response.data.msg || '权限不足:仅省级管理员可以修改角色路由权限', code: 4003 }; } // v3.2: 新响应格式: { code: 200, msg: "success", data: { role_id, enabled_count, disabled_count, inserted_count, route_ids } } let message = '角色权限更新成功'; if (response.data && response.data.msg) { message = response.data.msg; } else if (response.data && response.data.data) { const { enabled_count, disabled_count, inserted_count } = response.data.data; if (enabled_count !== undefined && disabled_count !== undefined) { message = `成功启用 ${enabled_count} 个路由,禁用 ${disabled_count} 个路由`; if (inserted_count && inserted_count > 0) { message += `,新增 ${inserted_count} 个路由关联`; } } else { // 兼容旧版本响应格式 const { assigned_count, removed_count } = response.data.data; if (assigned_count !== undefined && removed_count !== undefined) { message = `成功分配 ${assigned_count} 个路由,移除了 ${removed_count} 个旧路由`; } } } return { success: true, message }; } catch (error) { console.error('❌ [updateRoleRoutePermissions] 更新角色权限失败:', error); return { success: false, message: error instanceof Error ? error.message : '更新角色权限失败' }; } } // ==================== 用户角色管理 API ==================== /** * 获取指定角色的用户列表 * @param roleId 角色ID * @param params 查询参数 */ export async function getRoleUsers( roleId: number, params?: { page?: number; page_size?: number; area?: string; username?: string; } ): Promise { try { // 导入 axios-client 的 get 函数 const { get } = await import('~/api/axios-client'); // 构建查询参数对象 const queryParams: Record = {}; if (params?.page) queryParams.page = params.page; if (params?.page_size) queryParams.page_size = params.page_size; if (params?.area) queryParams.area = params.area; if (params?.username) queryParams.username = params.username; // 使用 axios-client 的 get 函数调用真实后端API const response = await get(`/api/v3/rbac/roles/${roleId}/users`, queryParams); if (response.error) { throw new Error(response.error); } // 后端响应格式: { code: 200, message: "success", data: { total, page, page_size, items: [...] } } let items: any[] = []; if (response.data && response.data.data && Array.isArray(response.data.data.items)) { items = response.data.data.items; } else if (response.data && Array.isArray(response.data.items)) { items = response.data.items; } const users = items.map((user: any) => ({ id: user.user_id || user.id, username: user.username, nick_name: user.nick_name, phone_number: user.phone_number || '', email: user.email || '', area: user.area || '', // v3.3: 地区字段,用于权限隔离 ou_name: user.ou_name, status: user.status || 1, is_leader: user.is_leader || false })); return users; } catch (error) { console.error('❌ [getRoleUsers] 获取角色用户列表失败:', error); return []; } } /** * 获取所有用户列表 * @param params 查询参数 */ export async function getAllUsers(params?: { page?: number; page_size?: number; area?: string; username?: string; }): Promise { try { // 导入 axios-client 的 get 函数 const { get } = await import('~/api/axios-client'); // 构建查询参数对象 const queryParams: Record = {}; if (params?.page) queryParams.page = params.page; if (params?.page_size) queryParams.page_size = params.page_size; if (params?.username) queryParams.search = params.username; // v3.3: 使用标准 RBAC API,后端会自动根据用户角色进行地区过滤 // 省级管理员: 返回所有地区用户 // 市级管理员: 只返回同地区用户 const response = await get('/api/v2/users', queryParams); if (response.error) { throw new Error(response.error); } // axios-client 返回格式: { data: { users: [...], total: number }, status: 200 } // 后端实际返回: { users: [...], total: number } let users: any[] = []; if (response.data) { // 如果 response.data 是对象且包含 users 字段 if (response.data.users && Array.isArray(response.data.users)) { users = response.data.users; } // 如果 response.data 本身就是数组 else if (Array.isArray(response.data)) { users = response.data; } } console.log('获取的用户列表', users ) const userList = users.map(user => ({ id: user.user_id || user.id, // 优先使用 user_id,兼容不同的后端响应格式 username: user.username, nick_name: user.nick_name, phone_number: user.phone_number || '', email: user.email || '', area: user.area || '', // v3.3: 地区字段,用于权限隔离 ou_name: user.ou_name, status: user.status || 1, is_leader: user.is_leader || false })); return userList; } catch (error) { console.error('❌ [getAllUsers] 获取用户列表失败:', error); return []; } } /** * 为用户分配角色 * @param userId 用户ID * @param roleIds 角色ID数组 */ export async function assignUserRoles( userId: number, roleIds: number[] ): Promise<{ success: boolean; message: string }> { try { // 导入 axios-client 的 post 函数 const { post } = await import('~/api/axios-client'); // 使用 axios-client 的 post 函数调用真实后端API const response = await post(`/api/v3/rbac/users/${userId}/roles`, { role_ids: roleIds }); if (response.error) { throw new Error(response.error); } // v3.4: 检查后端返回的code(200表示成功) if (response.data && response.data.code && response.data.code !== 200) { // 后端返回错误,如权限不足(403)等 return { success: false, message: response.data.message || '分配失败' }; } // 后端响应格式: { code: 200, message: "角色分配成功", data: { user_id, roles: [...] } } let message = '用户角色分配成功'; if (response.data && response.data.message) { message = response.data.message; } return { success: true, message }; } catch (error) { console.error('❌ [assignUserRoles] 分配用户角色失败:', error); return { success: false, message: error instanceof Error ? error.message : '分配失败' }; } } /** * 移除用户角色 * @param userId 用户ID * @param roleId 角色ID */ export async function revokeUserRole( userId: number, roleId: number ): Promise<{ success: boolean; message: string }> { try { // 导入 axios-client 的 del 函数 const { del } = await import('~/api/axios-client'); // 使用 axios-client 的 del 函数调用真实后端API const response = await del(`/api/v3/rbac/users/${userId}/roles/${roleId}`); if (response.error) { throw new Error(response.error); } // 后端响应格式: { code: 200, message: "角色移除成功" } let message = '用户角色移除成功'; if (response.data && response.data.message) { message = response.data.message; } return { success: true, message }; } catch (error) { console.error('❌ [revokeUserRole] 移除用户角色失败:', error); return { success: false, message: error instanceof Error ? error.message : '移除失败' }; } } /** * 创建新角色 * @param roleData 角色数据 */ export async function createRole( roleData: Omit ): Promise<{ success: boolean; message: string; data?: RoleInfo }> { try { // 导入 axios-client 的 post 函数 const { post } = await import('~/api/axios-client'); // 使用 axios-client 的 post 函数调用真实后端API const response = await post(`/api/v3/rbac/roles`, { role_key: roleData.role_key, role_name: roleData.role_name, description: roleData.description || '', data_scope: roleData.data_scope || 'SELF', metadata: {} }); if (response.error) { throw new Error(response.error); } // 后端响应格式: { code: 200, message: "角色创建成功", data: { id, role_key, ... } } const data = response.data?.data || response.data; return { success: true, message: response.data?.message || '角色创建成功', data: { id: data.id, role_key: data.role_key, role_name: data.role_name, data_scope: data.data_scope, description: data.description || '', parent_role_id: data.parent_role_id || null, priority: data.priority || 0, is_system_role: data.is_system || false, created_at: data.created_at, updated_at: data.updated_at } }; } catch (error) { console.error('❌ [createRole] 创建角色失败:', error); return { success: false, message: error instanceof Error ? error.message : '创建角色失败' }; } } /** * 更新角色信息 * @param roleId 角色ID * @param roleData 角色数据 */ export async function updateRole( roleId: number, roleData: Partial> ): Promise<{ success: boolean; message: string }> { try { // 导入 axios-client 的 put 函数 const { put } = await import('~/api/axios-client'); const updatePayload: any = {}; if (roleData.role_name !== undefined) updatePayload.role_name = roleData.role_name; if (roleData.description !== undefined) updatePayload.description = roleData.description; if (roleData.data_scope !== undefined) updatePayload.data_scope = roleData.data_scope; if (roleData.priority !== undefined) updatePayload.priority = roleData.priority; if (roleData.parent_role_id !== undefined) updatePayload.parent_role_id = roleData.parent_role_id; const response = await put(`/api/v3/rbac/roles/${roleId}`, updatePayload); if (response.error) { throw new Error(response.error); } return { success: true, message: response.data?.message || '角色更新成功' }; } catch (error) { console.error('❌ [updateRole] 更新角色失败:', error); return { success: false, message: error instanceof Error ? error.message : '更新角色失败' }; } } /** * 删除角色 * @param roleId 角色ID * @param force 是否强制删除(会自动解除用户关联) */ export async function deleteRole( roleId: number, force = false ): Promise<{ success: boolean; message: string }> { try { // 导入 axios-client 的 del 函数 const { del } = await import('~/api/axios-client'); const url = `/api/v3/rbac/roles/${roleId}${force ? '?force=true' : ''}`; const response = await del(url); if (response.error) { throw new Error(response.error); } return { success: true, message: response.data?.message || '角色删除成功' }; } catch (error) { console.error('❌ [deleteRole] 删除角色失败:', error); return { success: false, message: error instanceof Error ? error.message : '删除角色失败' }; } } // ==================== 权限管理 API ==================== /** * 获取权限列表(树形或平铺) * @param format 格式:tree(树形)或 flat(平铺) * @param params 查询参数 */ export async function getPermissions( format: 'tree' | 'flat' = 'tree', params?: { module?: string; permission_type?: 'API' | 'MENU' | 'BUTTON'; include_system?: boolean; } ): Promise { try { const response = await get(`${RBAC_API_BASE}/permissions`, { format, ...params }); const data = handleApiResponse(response); return data; } catch (error) { console.error('获取权限列表失败:', error); return []; } } /** * 获取权限详情 * @param permissionId 权限ID */ export async function getPermissionDetail(permissionId: number): Promise { try { const response = await get(`${RBAC_API_BASE}/permissions/${permissionId}`); const data = handleApiResponse(response); return data; } catch (error) { console.error('获取权限详情失败:', error); return null; } } /** * 创建权限 * @param permissionData 权限数据 */ export async function createPermission( permissionData: Omit ): Promise<{ success: boolean; message: string; data?: Permission }> { try { // 从 permission_key 解析 module, resource, action const [module, resource, action] = permissionData.permission_key.split(':'); const response = await post(`${RBAC_API_BASE}/permissions`, { permission_key: permissionData.permission_key, display_name: permissionData.display_name, description: permissionData.description || '', module, resource, action, permission_type: permissionData.permission_type || 'API', parent_id: permissionData.parent_id || null, sort_order: permissionData.sort_order || 0, metadata: {} }); const data = handleApiResponse(response); return { success: true, message: '权限创建成功', data }; } catch (error) { console.error('创建权限失败:', error); return { success: false, message: error instanceof Error ? error.message : '创建权限失败' }; } } /** * 更新权限 * @param permissionId 权限ID * @param permissionData 权限数据 */ export async function updatePermission( permissionId: number, permissionData: Partial> ): Promise<{ success: boolean; message: string }> { try { const response = await put(`${RBAC_API_BASE}/permissions/${permissionId}`, permissionData); handleApiResponse(response); return { success: true, message: '权限更新成功' }; } catch (error) { console.error('更新权限失败:', error); return { success: false, message: error instanceof Error ? error.message : '更新权限失败' }; } } /** * 删除权限 * @param permissionId 权限ID */ export async function deletePermission( permissionId: number ): Promise<{ success: boolean; message: string }> { try { const response = await del(`${RBAC_API_BASE}/permissions/${permissionId}`); handleApiResponse(response); return { success: true, message: '权限删除成功' }; } catch (error) { console.error('删除权限失败:', error); return { success: false, message: error instanceof Error ? error.message : '删除权限失败' }; } } // ==================== 角色权限关联 API ==================== /** * 获取角色的所有权限(已分配的API权限) * @param roleId 角色ID */ export async function getRolePermissions(roleId: number): Promise { try { const { get } = await import('~/api/axios-client'); // v3.4: 使用文档规范的API路径(查询参数方式) const response = await get('/api/v3/rbac/role-permissions', { role_id: roleId }); if (response.error) { throw new Error(response.error); } // 解析响应数据 let permissions: any[] = []; if (response.data?.data?.permissions) { permissions = response.data.data.permissions; } else if (response.data?.permissions) { permissions = response.data.permissions; } else if (Array.isArray(response.data?.data)) { permissions = response.data.data; } else if (Array.isArray(response.data)) { permissions = response.data; } return permissions.map(perm => ({ id: perm.id, permission_id: perm.permission_id || perm.id, // 兼容:如果没有 permission_id,使用 id permission_key: perm.permission_key, display_name: perm.display_name, grant_type: perm.grant_type || 'GRANT', data_scope: perm.data_scope || 'ALL' })); } catch (error) { console.error('❌ [getRolePermissions] 获取角色权限失败:', error); return []; } } /** * 批量分配权限给角色 * @param roleId 角色ID * @param permissions 权限配置列表 * @param replace 是否替换全部(true=替换,false=追加) */ export async function assignPermissionsToRole( roleId: number, permissions: RolePermissionConfig[], replace = false ): Promise<{ success: boolean; message: string }> { try { // v3.4: 使用文档规范的API路径(查询参数方式) const response = await post(`${RBAC_API_BASE}/role-permissions`, { role_id: roleId, permissions: permissions.map(p => ({ permission_id: p.permission_id, grant_type: p.grant_type || 'GRANT', data_scope: p.data_scope || 'ALL' })), replace }); handleApiResponse(response); return { success: true, message: '权限分配成功' }; } catch (error) { console.error('分配权限失败:', error); return { success: false, message: error instanceof Error ? error.message : '分配权限失败' }; } } /** * 更新单个权限配置 * @param roleId 角色ID * @param permissionId 权限ID * @param config 权限配置 */ export async function updateRolePermission( roleId: number, permissionId: number, config: Partial ): Promise<{ success: boolean; message: string }> { try { // v3.4: 使用文档规范的API路径(查询参数方式) const response = await put( `${RBAC_API_BASE}/role-permissions?role_id=${roleId}&permission_id=${permissionId}`, config ); handleApiResponse(response); return { success: true, message: '权限配置更新成功' }; } catch (error) { console.error('更新权限配置失败:', error); return { success: false, message: error instanceof Error ? error.message : '更新权限配置失败' }; } } /** * 移除角色权限 * @param roleId 角色ID * @param permissionId 权限ID */ export async function revokeRolePermission( roleId: number, permissionId: number ): Promise<{ success: boolean; message: string }> { try { // v3.4: 使用文档规范的API路径(查询参数方式) const response = await del(`${RBAC_API_BASE}/role-permissions?role_id=${roleId}&permission_id=${permissionId}`); handleApiResponse(response); return { success: true, message: '权限移除成功' }; } catch (error) { console.error('移除权限失败:', error); return { success: false, message: error instanceof Error ? error.message : '移除权限失败' }; } } /** * 获取指定用户的所有角色 * @param userId 用户ID * @returns 用户的角色列表 */ export async function getUserRoles(userId: number): Promise { try { const { get } = await import('~/api/axios-client'); const response = await get(`/api/v3/rbac/users/${userId}/roles`); if (response.error) { console.error('❌ [getUserRoles] API调用失败:', response.error); throw new Error(response.error); } // 后端响应格式: { code: 200, msg: "success", data: { user_id, username, roles: [...] } } let roles: any[] = []; if (response.data && response.data.data && Array.isArray(response.data.data.roles)) { roles = response.data.data.roles; } else if (response.data && Array.isArray(response.data.roles)) { // 兼容可能的响应格式 roles = response.data.roles; } // 将后端数据转换为RoleInfo格式 return roles.map(role => ({ id: role.id || role.role_id, role_key: role.role_key, role_name: role.role_name, data_scope: role.data_scope, description: role.description || '', priority: role.priority || 0, is_system_role: role.is_system || false, created_at: role.created_at || '', updated_at: role.updated_at || '' })); } catch (error) { console.error('❌ [getUserRoles] 获取用户角色失败:', error); // 失败时返回空数组 return []; } }