feat:替换 Dify 为自建 RAG去实现
1、修复了若干无权限时的失败提示语 2、新增了一个生成后续建议问题的功能 3、重构了知识问答部分的权限管理模块 4、修复了若干渲染不恰当的样式渲染
This commit is contained in:
@@ -136,36 +136,33 @@ export function useChatApps() {
|
||||
setLoadingDefault(true);
|
||||
setError(null);
|
||||
|
||||
let resolved = false; // 用局部变量跟踪,避免 React state 异步读取的问题
|
||||
|
||||
try {
|
||||
try {
|
||||
console.log('[useChatApps] ==================== 开始初始化对话应用 ====================');
|
||||
// 尝试加载可用应用列表
|
||||
console.log('[useChatApps] 步骤1: 调用loadChatApps()加载我的应用列表...');
|
||||
const apps = await loadChatApps();
|
||||
console.log('[useChatApps] 步骤1完成: 加载到', apps.length, '个应用');
|
||||
|
||||
if (apps.length > 0) {
|
||||
// 查找默认应用
|
||||
const defaultApp = apps.find((item) => item.is_default) || apps[0];
|
||||
// console.log('[useChatApps] 默认对话应用:', apps);
|
||||
setCurrentChatApp(defaultApp);
|
||||
console.log('[useChatApps] ==================== 初始化完成(路径1) ====================');
|
||||
resolved = true;
|
||||
} else {
|
||||
// 如果没有配置应用,尝试获取默认应用
|
||||
console.log('[useChatApps] 应用列表为空,调用loadDefaultChatApp()...');
|
||||
await loadDefaultChatApp();
|
||||
console.log('[useChatApps] ==================== 初始化完成(路径2) ====================');
|
||||
const app = await loadDefaultChatApp();
|
||||
if (app) resolved = true;
|
||||
}
|
||||
} catch (err) {
|
||||
// 加载应用列表失败,尝试获取默认应用
|
||||
console.warn('[useChatApps] 加载应用列表失败,尝试获取默认应用:', err);
|
||||
await loadDefaultChatApp();
|
||||
console.log('[useChatApps] ==================== 初始化完成(路径3) ====================');
|
||||
const app = await loadDefaultChatApp();
|
||||
if (app) resolved = true;
|
||||
}
|
||||
} catch (err: any) {
|
||||
console.error('[useChatApps] 初始化失败:', err);
|
||||
setError(err.message || '加载对话应用失败');
|
||||
console.warn('[useChatApps] 初始化异常:', err.message);
|
||||
} finally {
|
||||
if (!resolved) {
|
||||
// 权限不足等情况,构造占位应用让页面能渲染(输入框会被禁用)
|
||||
const fallbackApp = { app_id: '_fallback', app_name: '法务问答', description: '', is_default: true } as any;
|
||||
setChatApps([fallbackApp]);
|
||||
setCurrentChatApp(fallbackApp);
|
||||
setError(null);
|
||||
}
|
||||
setLoadingChatApps(false);
|
||||
setLoadingDefault(false);
|
||||
setInited(true);
|
||||
|
||||
@@ -94,11 +94,24 @@ export function useDocumentDetail(datasetId: string, document: Document | null)
|
||||
pollIndexingStatus(batch);
|
||||
}, [stopPolling, pollIndexingStatus]);
|
||||
|
||||
// 当文档变化时重置设置
|
||||
// 当文档变化时,从文档已有的 process_rule 回显设置,无则使用默认值
|
||||
useEffect(() => {
|
||||
if (document) {
|
||||
// 可以从文档中读取已有的设置,这里使用默认值
|
||||
setSettings(DEFAULT_DOCUMENT_DETAIL_SETTINGS);
|
||||
const rule = (document as any).process_rule;
|
||||
if (rule?.mode === 'custom' && rule?.rules) {
|
||||
const seg = rule.rules.segmentation || {};
|
||||
const preRules = rule.rules.pre_processing_rules || [];
|
||||
setSettings({
|
||||
separator: (seg.separator || '\\n\\n').replace(/\n/g, '\\n'),
|
||||
maxTokens: seg.max_tokens || DEFAULT_DOCUMENT_DETAIL_SETTINGS.maxTokens,
|
||||
chunkOverlap: DEFAULT_DOCUMENT_DETAIL_SETTINGS.chunkOverlap,
|
||||
removeExtraSpaces: preRules.find((r: any) => r.id === 'remove_extra_spaces')?.enabled ?? DEFAULT_DOCUMENT_DETAIL_SETTINGS.removeExtraSpaces,
|
||||
removeUrlsEmails: preRules.find((r: any) => r.id === 'remove_urls_emails')?.enabled ?? DEFAULT_DOCUMENT_DETAIL_SETTINGS.removeUrlsEmails,
|
||||
indexingTechnique: DEFAULT_DOCUMENT_DETAIL_SETTINGS.indexingTechnique,
|
||||
});
|
||||
} else {
|
||||
setSettings(DEFAULT_DOCUMENT_DETAIL_SETTINGS);
|
||||
}
|
||||
setPreviewSegments([]);
|
||||
setShowPreview(false);
|
||||
setIsProcessing(false);
|
||||
|
||||
@@ -105,8 +105,10 @@ export function useDatasetManager() {
|
||||
await loadDocuments(datasetId, 1);
|
||||
} catch (err: any) {
|
||||
console.error('[DatasetManager] 加载知识库详情失败:', err);
|
||||
setError(err.message || '加载知识库失败');
|
||||
message.error('加载知识库失败');
|
||||
const is403 = err.message?.includes('403') || err.response?.status === 403;
|
||||
const msg = is403 ? '您没有查看知识库的权限' : (err.message || '加载知识库失败');
|
||||
setError(msg);
|
||||
message.error(msg);
|
||||
} finally {
|
||||
setLoadingDataset(false);
|
||||
}
|
||||
@@ -151,13 +153,15 @@ export function useDatasetManager() {
|
||||
setDataset(fullDataset);
|
||||
await loadDocuments(firstDatasetId, 1);
|
||||
} else {
|
||||
setError('未找到知识库,请先在Dify中创建知识库');
|
||||
setError('未找到知识库,请先联系管理员创建知识库');
|
||||
}
|
||||
}
|
||||
} catch (err: any) {
|
||||
console.error('[DatasetManager] 加载知识库失败:', err);
|
||||
setError(err.message || '加载知识库失败');
|
||||
message.error('加载知识库失败');
|
||||
const is403 = err.message?.includes('403') || err.response?.status === 403;
|
||||
const msg = is403 ? '您没有查看知识库的权限' : (err.message || '加载知识库失败');
|
||||
setError(msg);
|
||||
message.error(msg);
|
||||
} finally {
|
||||
setLoadingDataset(false);
|
||||
setInited(true);
|
||||
|
||||
@@ -72,7 +72,7 @@ export function useAreaDatasetConfig(): UseAreaDatasetConfigReturn {
|
||||
// 根据权限判断是否可以管理知识库配置
|
||||
// 权限键:dify:bind:update(知识库绑定更新权限)
|
||||
// 降级方案:如果 permissionMap 中没有配置权限,usePermission 会自动降级为角色判断
|
||||
const canManageDataset = hasPermission('dify:bind:update');
|
||||
const canManageDataset = hasPermission('dify:config:manage');
|
||||
const canViewDataset = true; // 所有登录用户都可以查看
|
||||
|
||||
// 🔍 调试日志(修复后可删除)
|
||||
|
||||
@@ -426,11 +426,21 @@ export default function useChatMessage({
|
||||
resourceCount: messageEnd.metadata?.retriever_resources?.length || 0
|
||||
});
|
||||
|
||||
let needUpdate = false;
|
||||
|
||||
// 如果有检索资源,更新响应项
|
||||
if (messageEnd.metadata?.retriever_resources && messageEnd.metadata.retriever_resources.length > 0) {
|
||||
responseItem.retriever_resources = messageEnd.metadata.retriever_resources;
|
||||
needUpdate = true;
|
||||
}
|
||||
|
||||
// 更新聊天列表
|
||||
// 如果有建议问题,更新响应项
|
||||
if (messageEnd.metadata?.suggested_questions && messageEnd.metadata.suggested_questions.length > 0) {
|
||||
responseItem.suggestedQuestions = messageEnd.metadata.suggested_questions;
|
||||
needUpdate = true;
|
||||
}
|
||||
|
||||
if (needUpdate) {
|
||||
updateCurrentQA({
|
||||
responseItem: { ...responseItem },
|
||||
questionId,
|
||||
@@ -504,8 +514,12 @@ export default function useChatMessage({
|
||||
draft[messageIndex].feedback = feedback;
|
||||
}
|
||||
}));
|
||||
} catch (err) {
|
||||
} catch (err: any) {
|
||||
logError(`提交反馈时出错: ${err}`);
|
||||
const msg = err?.message || '提交反馈失败';
|
||||
const isPermission = msg.includes('403') || msg.includes('权限');
|
||||
const { message: antMessage } = await import('antd');
|
||||
antMessage.error(isPermission ? '您没有反馈权限' : msg);
|
||||
}
|
||||
}, [logError, getChatList, setChatList]);
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ interface RootLoaderData {
|
||||
permissions?: string[];
|
||||
permissionMap?: Record<string, string[]>; // ✅ 新增:权限映射表
|
||||
userRole: string;
|
||||
userArea?: string;
|
||||
userInfo?: {
|
||||
role_id?: number;
|
||||
role_key?: string;
|
||||
@@ -70,6 +71,7 @@ export function usePermission() {
|
||||
// 从root loader获取权限映射表
|
||||
const permissionMap = rootData?.permissionMap || {};
|
||||
const userRole = rootData?.userRole || 'common';
|
||||
const userArea = rootData?.userArea || '';
|
||||
|
||||
// 🔑 根据当前路由获取权限列表
|
||||
const currentPath = location.pathname;
|
||||
@@ -245,6 +247,7 @@ export function usePermission() {
|
||||
permissions: currentPermissions, // ✅ 返回当前路由的权限
|
||||
permissionMap, // ✅ 返回完整的权限映射表
|
||||
userRole,
|
||||
userArea,
|
||||
|
||||
// 基础检查方法
|
||||
hasPermission,
|
||||
|
||||
Reference in New Issue
Block a user