fix: 修复知识库配置管理的权限检查和错误提示

1. 权限检查优化
   - 使用 hasPermission('dify:bind:update') 替代硬编码的角色判断
   - 支持细粒度的权限控制,市级管理员可以通过授权获得编辑权限
   - 保留降级方案,provincial_admin 角色自动拥有所有权限

2. 错误处理优化
   - 新增统一的 handleApiError 错误处理函数
   - 优先显示后端返回的具体错误信息(error.response.data.msg)
   - 支持多种错误格式的提取(axios、fetch、自定义格式)
   - 简化 handleCreate、handleUpdate、handleDelete 的错误处理代码

3. 调试支持
   - 添加权限检查的调试日志,便于排查问题
   - 输出当前路由、用户角色、权限列表等关键信息

修复问题:
- 市级管理员被授予 dify:bind:update 权限后,编辑按钮仍不显示
- 403 错误只显示通用提示,无法看到后端返回的具体错误原因

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-22 19:02:44 +08:00
parent cbdffc9b2e
commit 7e6424e9ac
+57 -26
View File
@@ -67,14 +67,63 @@ const ROLE_LABELS: Record<string, string> = {
export function useAreaDatasetConfig(): UseAreaDatasetConfigReturn {
// 权限控制
const { userRole: permissionUserRole } = usePermission();
const { hasPermission, userRole: permissionUserRole, permissions, permissionMap } = usePermission();
// 根据 userRole 判断权限
// provincial_admin 可以管理所有知识库配置
// 其他角色只能查看自己地区的配置
const canManageDataset = permissionUserRole === 'provincial_admin' || permissionUserRole.toLowerCase().includes('provin');
// 根据权限判断是否可以管理知识库配置
// 权限键:dify:bind:update(知识库绑定更新权限)
// 降级方案:如果 permissionMap 中没有配置权限,usePermission 会自动降级为角色判断
const canManageDataset = hasPermission('dify:bind:update');
const canViewDataset = true; // 所有登录用户都可以查看
// 🔍 调试日志(修复后可删除)
if (typeof window !== 'undefined') {
console.log('[DatasetConfig] 权限检查:', {
currentPath: window.location.pathname,
userRole: permissionUserRole,
hasDifyBindUpdate: hasPermission('dify:bind:update'),
currentPermissions: permissions,
canManageDataset,
});
}
// ==================== 错误处理工具函数 ====================
/**
* 统一处理 API 错误
* @param error 错误对象
* @param operation 操作名称(创建/更新/删除)
*/
const handleApiError = (error: any, operation: string) => {
console.error(`${operation}知识库绑定失败:`, error);
// 提取错误信息的优先级:
// 1. error.response.data.msg (axios 响应格式)
// 2. error.data.msg (其他格式)
// 3. error.msg (直接错误对象)
// 4. error.response.data.message (备用字段)
// 5. error.message (标准错误对象)
const errorMsg = error?.response?.data?.msg ||
error?.data?.msg ||
error?.msg ||
error?.response?.data?.message ||
error?.message;
// 检查是否为403权限不足错误
const is403 = error?.response?.status === 403 ||
error?.status === 403 ||
error?.code === 403;
if (is403) {
// 403 错误:显示具体的权限错误信息
message.error(errorMsg || `无权限操作:您没有${operation}知识库绑定的权限`);
} else {
// 其他错误:显示具体的错误信息或通用提示
message.error(errorMsg || `${operation}失败,请稍后重试`);
}
};
// ==================== 数据状态 ====================
// 数据状态
const [datasets, setDatasets] = useState<AreaDataset[]>([]);
const [allDatasets, setAllDatasets] = useState<AreaDataset[]>([]); // 保存所有数据用于提取地区
@@ -221,13 +270,7 @@ export function useAreaDatasetConfig(): UseAreaDatasetConfigReturn {
return false;
}
} catch (error: any) {
console.error('创建知识库绑定失败:', error);
// 检查是否为403权限不足错误
if (error?.response?.status === 403 || error?.status === 403 || error?.code === 403) {
message.error('无权限操作:您没有创建知识库绑定的权限');
} else {
message.error('创建失败,请稍后重试');
}
handleApiError(error, '创建');
return false;
} finally {
setSubmitLoading(false);
@@ -259,13 +302,7 @@ export function useAreaDatasetConfig(): UseAreaDatasetConfigReturn {
return false;
}
} catch (error: any) {
console.error('更新知识库绑定失败:', error);
// 检查是否为403权限不足错误
if (error?.response?.status === 403 || error?.status === 403 || error?.code === 403) {
message.error('无权限操作:您没有编辑知识库绑定的权限');
} else {
message.error('更新失败,请稍后重试');
}
handleApiError(error, '更新');
return false;
} finally {
setSubmitLoading(false);
@@ -296,13 +333,7 @@ export function useAreaDatasetConfig(): UseAreaDatasetConfigReturn {
return false;
}
} catch (error: any) {
console.error('删除知识库绑定失败:', error);
// 检查是否为403权限不足错误
if (error?.response?.status === 403 || error?.status === 403 || error?.code === 403) {
message.error('无权限操作:您没有删除知识库绑定的权限');
} else {
message.error('删除失败,请稍后重试');
}
handleApiError(error, '删除');
return false;
}
},