fix: 修复角色权限管理模块的API认证和数据加载问题

主要修复:
1. 修复所有RBAC API函数使用axios-client(自动添加JWT token)
   - getRoles, createRole, updateRole, deleteRole 从rbacFetch切换到axios-client
   - 解决401未授权导致的数据加载失败问题

2. 修复用户ID字段不匹配问题
   - getAllUsers函数使用user_id字段(兼容user.user_id || user.id)
   - 确保角色分配时使用正确的用户ID

3. 修复路由ID不匹配问题
   - getRoutes函数改用真实后端API(GET /rbac/user/routes)
   - 解决前端Mock路由ID与数据库不一致导致的400错误

4. 增强axios-client成功响应识别
   - 支持code=200作为成功状态(原本只支持code=0)
   - 兼容不同后端API的响应格式

5. 实现用户单角色限制功能
   - 添加getUserRoles API函数
   - 分配角色前检查用户现有角色
   - 在用户列表中显示当前角色标签

6. 改进创建角色的表单验证
   - role_key必须以字母开头(正则:^[a-z][a-z0-9_]*$)
   - 添加实时验证提示
   - 更新提示文案说明规则

7. 添加删除操作的安全确认机制
   - 删除角色/移除用户角色前显示确认模态框
   - 3秒倒计时后才能确认删除
   - 成功删除后自动刷新数据

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-11-24 18:03:57 +08:00
parent 1b546e6818
commit 689ef6bc3d
5 changed files with 2802 additions and 174 deletions
+27 -1
View File
@@ -81,6 +81,7 @@ axiosInstance.interceptors.request.use(
(config) => {
// 检查是否在白名单中
if (isInAuthWhitelist(config.url)) {
console.log('🔓 [Request Interceptor] URL在白名单中,跳过Authorization:', config.url);
return config;
}
@@ -89,12 +90,24 @@ axiosInstance.interceptors.request.use(
const token = localStorage.getItem('access_token');
if (token) {
config.headers.Authorization = `Bearer ${token}`;
console.log('🔑 [Request Interceptor] 添加Authorization头:', {
url: config.url,
method: config.method,
hasToken: !!token,
tokenPreview: token.substring(0, 20) + '...'
});
} else {
console.warn('⚠️ [Request Interceptor] 没有找到access_token:', {
url: config.url,
localStorage: Object.keys(localStorage)
});
}
}
return config;
},
(error) => {
console.error('❌ [Request Interceptor] 请求拦截器错误:', error);
return Promise.reject(error);
}
);
@@ -114,9 +127,21 @@ export class AuthenticationError extends Error {
*/
axiosInstance.interceptors.response.use(
(response) => {
console.log('✅ [Response Interceptor] 请求成功:', {
url: response.config.url,
status: response.status,
statusText: response.statusText
});
return response;
},
(error) => {
console.error('❌ [Response Interceptor] 请求失败:', {
url: error.config?.url,
status: error.response?.status,
statusText: error.response?.statusText,
data: error.response?.data
});
if (isAxiosError(error) && error.response?.status === 401) {
// 检查是否在错误容忍白名单中
const requestUrl = error.config?.url;
@@ -442,7 +467,8 @@ export async function apiRequest<T>(
// 检查API返回的状态码
const data = response.data;
if (data && typeof data === 'object' && 'code' in data && data.code !== 0) {
// 修复:支持code=0PostgREST)和code=200RBAC API)两种成功响应
if (data && typeof data === 'object' && 'code' in data && data.code !== 0 && data.code !== 200) {
const errorMessage = data.message || data.msg || '未知错误';
console.error(`API请求失败: ${errorMessage} - ${url}`);
File diff suppressed because it is too large Load Diff