/** * 逐篇精读模式组件 - ChatGPT风格全屏聊天 * 修复:参考文献格式、文档切换对话独立 */ import React, { useMemo } from 'react'; import { FileText, BookOpen, ExternalLink } from 'lucide-react'; import { ChatContainer } from '@/shared/components/Chat'; import type { KnowledgeBase, Document } from '../../api/knowledgeBaseApi'; import { getAccessToken } from '../../../../framework/auth/api'; interface DeepReadModeProps { kbId: string; kbInfo: KnowledgeBase; selectedDocuments: Document[]; } // 消息渲染参数类型 interface MessageRenderParams { id: string | number; message: { id: string | number; role: string; content: string; status?: string; [key: string]: unknown; }; status: string; } // 自定义消息渲染器 - 解析并格式化参考文献 const renderMessageContent = (params: MessageRenderParams) => { // 从params中提取消息内容 const textContent = params?.message?.content; // 空内容处理 if (!textContent || typeof textContent !== 'string' || textContent.trim() === '') { return
加载中...
; } // 处理参考文献格式 let formattedContent = textContent; // 1. 移除HTML标签,转换为可读格式 formattedContent = formattedContent.replace( /]*id="citation-detail-(\d+)"[^>]*>\[(\d+)\]<\/span>\s*\*?\*?([^*\n]+)\*?\*?/g, (_, _num, num2, title) => `\n📄 [${num2}] ${title.trim()}` ); // 2. 处理其他HTML span标签 formattedContent = formattedContent.replace(/]*>[^<]*<\/span>/g, ''); // 3. 处理Markdown加粗中的下划线(文件名) formattedContent = formattedContent.replace( /\*\*([^*]+\.pdf)\*\*/gi, '📄 **$1**' ); return (
{formattedContent.split('\n').map((line, idx) => { // 检测是否是参考文献行 if (line.startsWith('📄')) { return (
{line.replace('📄 ', '')}
); } // 检测是否是"参考文献"标题 if (line.includes('**参考文献**') || line.includes('📚 **参考文献**')) { return (
参考文献
); } // 普通文本 return line ?

{line}

: null; })}
); }; export const DeepReadMode: React.FC = ({ kbId, selectedDocuments }) => { // 使用useMemo确保文档切换时生成新的key const conversationKey = useMemo(() => { if (!selectedDocuments || selectedDocuments.length === 0) return ''; return `kb-deepread-${kbId}-${selectedDocuments[0].id}-${Date.now()}`; }, [kbId, selectedDocuments]); const selectedDocIds = useMemo(() => selectedDocuments.map(d => d.id), [selectedDocuments] ); if (!selectedDocuments || selectedDocuments.length === 0) { return (

选择文档开始精读

请在上方"逐篇精读"下拉框中选择一篇文档进行深度分析

); } const selectedDoc = selectedDocuments[0]; return (
{/* 当前文档提示 */}
当前精读: {selectedDoc.filename}
{/* Chat组件 - 使用key强制重新渲染 */}
{ // 🔑 关键:传递 fullTextDocumentIds 而不是 documentIds // fullTextDocumentIds 会触发全文加载模式,AI可以看到完整文献 // documentIds 只是过滤RAG检索结果,AI只能看到片段 const token = getAccessToken(); const response = await fetch('/api/v1/pkb/chat/stream', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Accept': 'text/event-stream', ...(token ? { 'Authorization': `Bearer ${token}` } : {}), }, body: JSON.stringify({ content: message, modelType: 'qwen-long', knowledgeBaseIds: [kbId], fullTextDocumentIds: selectedDocIds, // ✅ 改用全文模式 }), }); if (!response.ok) { throw new Error(`API请求失败: ${response.status}`); } const reader = response.body?.getReader(); const decoder = new TextDecoder(); let fullContent = ''; if (reader) { while (true) { const { done, value } = await reader.read(); if (done) break; const chunk = decoder.decode(value); const lines = chunk.split('\n'); for (const line of lines) { if (line.startsWith('data: ')) { const data = line.slice(6); if (data === '[DONE]') break; try { const json = JSON.parse(data); if (json.content) { fullContent += json.content; } } catch (e) { // 忽略解析错误 } } } } } return { content: fullContent, messageId: Date.now().toString(), }; }, }} customMessageRenderer={renderMessageContent} />
); };