Files
leaudit-platform-frontend/app/api/role-permissions/role-permissions.ts
T
LiangShiyong d5827a2146 fix: 1. 接入入口模块的管理接口,优化样式。
2. 将查看文档评查结果详情对接接口,采用接口的方式进行查询。
2025-11-26 23:37:14 +08:00

1125 lines
32 KiB
TypeScript

/**
* 角色权限管理 API
* 用于角色、路由权限、用户角色的管理
*/
// ==================== 常量定义 ====================
/**
* RBAC API 基础路径
* 注意:使用相对路径,会命中Remix API路由而不是后端服务器
*/
const RBAC_API_BASE = '/api/v3/rbac';
/**
* 统一响应处理函数
* 处理后端返回的统一格式响应
*/
function handleApiResponse<T>(response: ApiResponse<any>): 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;
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<RoleInfo[]> {
try {
// 导入 axios-client 的 get 函数
const { get } = await import('~/api/axios-client');
// 使用 axios-client 的 get 函数调用真实后端API
const response = await get<any>(`/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.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<RoleInfo | null> {
try {
const response = await get<any>(`${RBAC_API_BASE}/roles/${roleId}`);
const role = handleApiResponse<any>(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<RouteInfo[]> {
try {
const { get } = await import('~/api/axios-client');
// 调用后端API获取当前用户的路由(provincial_admin应该有所有路由权限)
const response = await get<any>('/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
});
return routes.map(mapRouteData);
} catch (error) {
console.error('❌ [getRoutes] 获取路由数据失败:', error);
// 失败时返回空数组,让前端显示错误提示
return [];
}
}
/**
* 获取指定角色的路由权限
* @param roleId 角色ID
*/
export async function getRoleRoutePermissions(roleId: number): Promise<RoleRoutePermission[]> {
try {
// 导入 axios-client 的 get 函数
const { get } = await import('~/api/axios-client');
// 使用 axios-client 的 get 函数调用真实后端API
const response = await get<any>(`/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()
}));
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<any>(`/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): 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,
status: route.status || 1,
parent_id: route.parent_id || null,
component: route.component,
// 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);
// 收集所有已选中的路由ID
const collectRouteIds = (routes: RouteInfo[]): number[] => {
let ids: number[] = [];
routes.forEach(route => {
ids.push(route.id);
if (route.children) {
ids = ids.concat(collectRouteIds(route.children));
}
});
return ids;
};
// 收集所有已选中的权限ID(从当前角色的权限中)
const collectPermissionIds = (routes: RouteInfo[]): number[] => {
let ids: number[] = [];
routes.forEach(route => {
if (route.permissions) {
ids = ids.concat(route.permissions.map(p => p.id));
}
if (route.children) {
ids = ids.concat(collectPermissionIds(route.children));
}
});
return ids;
};
const selectedRouteIds = collectRouteIds(mappedRoutes);
const selectedPermissionIds = collectPermissionIds(mappedRoutes);
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'
}));
const response = await post<any>(`/api/v3/rbac/roles/${roleId}/permissions`, {
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权限失败'
};
}
}
/**
* 更新角色的路由权限
* @param roleId 角色ID
* @param routeIds 路由ID数组
*/
export async function updateRoleRoutePermissions(
roleId: number,
routeIds: number[]
): Promise<{ success: boolean; message: string }> {
try {
// 导入 axios-client 的 put 函数
const { put } = await import('~/api/axios-client');
// 使用 axios-client 的 put 函数调用真实后端API
const response = await put<any>(`/rbac/roles/${roleId}/routes`, {
route_ids: routeIds,
permission: 'RW'
});
if (response.error) {
throw new Error(response.error);
}
// 后端响应格式: { code: 200, msg: "success", data: { role_id, assigned_count, removed_count, route_ids } }
let message = '角色权限更新成功';
if (response.data && response.data.msg) {
message = response.data.msg;
} else if (response.data && response.data.data) {
const { assigned_count, removed_count } = response.data.data;
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<UserInfo[]> {
try {
// 导入 axios-client 的 get 函数
const { get } = await import('~/api/axios-client');
// 构建查询参数对象
const queryParams: Record<string, any> = {};
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<any>(`/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 || '',
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<UserInfo[]> {
try {
// 导入 axios-client 的 get 函数
const { get } = await import('~/api/axios-client');
// 构建查询参数对象
const queryParams: Record<string, any> = {};
if (params?.page) queryParams.page = params.page;
if (params?.page_size) queryParams.page_size = params.page_size;
if (params?.username) queryParams.search = params.username;
// 使用 axios-client 的 get 函数,会自动添加 baseURL 和 Authorization
const response = await get<any>('/admin/users/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;
}
}
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 || '',
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<any>(`/api/v3/rbac/users/${userId}/roles`, {
role_ids: roleIds
});
if (response.error) {
throw new Error(response.error);
}
// 后端响应格式: { 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<any>(`/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<RoleInfo, 'id' | 'created_at' | 'updated_at'>
): 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<any>(`/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<Omit<RoleInfo, 'id' | 'created_at' | 'updated_at'>>
): 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<any>(`/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<any>(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<Permission[]> {
try {
const response = await get<any>(`${RBAC_API_BASE}/permissions`, {
format,
...params
});
const data = handleApiResponse<Permission[]>(response);
return data;
} catch (error) {
console.error('获取权限列表失败:', error);
return [];
}
}
/**
* 获取权限详情
* @param permissionId 权限ID
*/
export async function getPermissionDetail(permissionId: number): Promise<Permission | null> {
try {
const response = await get<any>(`${RBAC_API_BASE}/permissions/${permissionId}`);
const data = handleApiResponse<Permission>(response);
return data;
} catch (error) {
console.error('获取权限详情失败:', error);
return null;
}
}
/**
* 创建权限
* @param permissionData 权限数据
*/
export async function createPermission(
permissionData: Omit<Permission, 'id' | 'children'>
): 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<any>(`${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<Permission>(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<Omit<Permission, 'id' | 'children'>>
): Promise<{ success: boolean; message: string }> {
try {
const response = await put<any>(`${RBAC_API_BASE}/permissions/${permissionId}`, permissionData);
handleApiResponse<any>(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<any>(`${RBAC_API_BASE}/permissions/${permissionId}`);
handleApiResponse<any>(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<RolePermissionDetail[]> {
try {
const { get } = await import('~/api/axios-client');
const response = await get<any>(`/api/v3/rbac/roles/${roleId}/permissions`);
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 {
const response = await post<any>(`${RBAC_API_BASE}/roles/${roleId}/permissions`, {
permissions: permissions.map(p => ({
permission_id: p.permission_id,
grant_type: p.grant_type || 'GRANT',
data_scope: p.data_scope || 'ALL'
})),
replace
});
handleApiResponse<any>(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<RolePermissionConfig>
): Promise<{ success: boolean; message: string }> {
try {
const response = await put<any>(
`${RBAC_API_BASE}/roles/${roleId}/permissions/${permissionId}`,
config
);
handleApiResponse<any>(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 {
const response = await del<any>(`${RBAC_API_BASE}/roles/${roleId}/permissions/${permissionId}`);
handleApiResponse<any>(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<RoleInfo[]> {
try {
const { get } = await import('~/api/axios-client');
const response = await get<any>(`/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 [];
}
}