yangg hai 2 días
pai
achega
2588aca8f8
Modificáronse 1 ficheiros con 243 adicións e 5 borrados
  1. 243 5
      src/views/report.vue

+ 243 - 5
src/views/report.vue

@@ -430,6 +430,41 @@
                 v-html="renderMarkdown(message.displayContent)"
               ></div>
               <div v-else>{{ message.content }}</div>
+              
+              <!-- 知识源显示区域 -->
+              <div v-if="message.role === 'assistant' && message.knowledgeSources && message.knowledgeSources.length > 0" class="knowledge-sources">
+                <div class="knowledge-sources-header">
+                  <DatabaseOutlined />
+                  <span>知识来源</span>
+                </div>
+                <div class="knowledge-sources-list">
+                  
+                  <div 
+                    v-for="(source, sourceIndex) in message.knowledgeSources" 
+                    :key="sourceIndex"
+                    class="knowledge-source-group"
+                  >
+                    
+                      <div class="knowledge-source-items">
+                        <div 
+                          class="knowledge-source-item"
+                          @click="handleKnowledgeSourceClick(source)"
+                        >
+                          <div class="knowledge-source-content">
+                            <div class="knowledge-source-title" @click.stop="previewDocument(source)">
+                              {{ source.file_name }}
+                            </div>
+                            <div class="knowledge-source-text" v-if="source.content">{{ source.content }}</div>
+                           <!--  <div class="knowledge-source-meta">
+                              <span class="knowledge-source-doc">文档ID: {{ source.doc_id }}</span>
+                              <span class="knowledge-source-score" v-if="source.rerank_score">相关度: {{ (source.rerank_score * 100).toFixed(1) }}%</span>
+                            </div> -->
+                          </div>
+                        </div>
+                    </div>
+                  </div>
+                </div>
+              </div>
             <div v-if="message.analysis_result" style="background-color: #f5f5f5; padding: 12px; border-radius: 8px; margin: 8px 0;">
                 <div v-for="value in message.analysis_result.insights" style="margin-bottom: 6px; border-bottom: 1px dashed #e5e5e5;">
                   {{ value.message }}
@@ -1497,8 +1532,18 @@ const fetchDocumentSummary = async () => {
 // 获取聊天历史
 const fetchChatHistory = async () => {
   try {
-    const response = await  axios.get(
-      `${import.meta.env.VITE_BASE_AI_API}/api/chat/history`,
+    // 从个人信息中获取 user_id 和 merchant_id
+    const userInfo = JSON.parse(localStorage.getItem('userInfo'));
+    const userId = userInfo.user_id || userInfo.id || 1; // 备用默认值
+    const merchantId = userInfo.merchant?.merchant_id || 1;
+    
+    // 使用 FormData 传参
+    const formData = new FormData();
+    formData.append('user_id', userId);
+    formData.append('merchant_id', merchantId);
+    
+    const response = await axios.post(
+      `${import.meta.env.VITE_BASE_AI_API}/api/chat/history?merchant_id=${merchantId}&user_id=${userId}&full_content=1`,
       {
         headers: {
           'Authorization': `JWT ${localStorage.getItem('token')}`
@@ -1556,6 +1601,31 @@ const getConversationType = (type) => {
   return typeMap[type] || '对话';
 };
 
+// 处理知识源点击事件
+const handleKnowledgeSourceClick = (item) => {
+  // 可以在这里实现跳转到具体文档或显示更多详情
+  console.log('点击知识源:', item);
+  
+  // 示例:可以打开一个新窗口显示文档详情
+  if (item.doc_id) {
+    // 这里可以根据实际需求实现跳转逻辑
+    // 比如打开文档详情页面或显示文档内容
+    ElMessage.info(`查看文档 ${item.doc_id} 的详细信息`);
+  }
+};
+
+// 处理文档预览点击事件
+const previewDocument = (source) => {
+  console.log('预览文档:', source);
+  
+  if (source.minio_url) {
+    // 在新窗口中打开文档预览
+    window.open(source.minio_url, '_blank');
+  } else {
+    ElMessage.warning('该文档暂无预览链接');
+  }
+};
+
 // 处理步骤点击事件
 const handleStepClick = (step) => {
   // 显示进度条弹窗
@@ -2268,7 +2338,7 @@ const summaryHtml=ref('')
       const response = await axios.post(apiEndpoint, {
       message: currentMessage,
       chat_config_id: "2",
-      user_id: "13365429324",
+      user_id: JSON.parse(localStorage.getItem('userInfo')).user_id||"13365429324",
       session_id: session_id.value,
       source: "pc",
       image_urls: imageUrls,
@@ -2325,6 +2395,7 @@ const summaryHtml=ref('')
       content: messageContent,
       displayContent: "",
       audioData: audioInfo || null,
+      knowledgeSources: responseData.knowledge_sources || null, // 添加知识源数据
     });
     messages.value.push(aiMessage);
 
@@ -2654,8 +2725,53 @@ const addNewConversation = () => {
 const switchConversation = (conversationId) => {
   currentConversationId.value = conversationId;
   const conversation = conversations.value.find((c) => c.id === conversationId);
-  messages.value = conversation ? conversation.messages : [];
-  session_id.value = ""; // 重置 session_id
+  
+  if (conversation) {
+    // 如果会话有缓存的消息,直接使用
+    if (conversation.messages && conversation.messages.length > 0) {
+      messages.value = conversation.messages;
+    } 
+    // 如果会话有 sessionData,从中提取消息
+    else if (conversation.sessionData) {
+      const sessionData = conversation.sessionData;
+      const extractedMessages = [];
+      
+      // 添加用户消息
+      if (sessionData.user_message) {
+        extractedMessages.push({
+          id: `user_${sessionData.user_message.created_at}`,
+          role: 'user',
+          content: sessionData.user_message.content,
+          timestamp: sessionData.user_message.created_at,
+          type: 'text'
+        });
+      }
+      
+      // 添加助手消息
+      if (sessionData.last_message && sessionData.last_message.role === 'assistant') {
+        extractedMessages.push({
+          id: `assistant_${sessionData.last_message.created_at}`,
+          role: 'assistant',
+          content: sessionData.last_message.content,
+          displayContent: sessionData.last_message.content, // 添加 displayContent 用于显示
+          timestamp: sessionData.last_message.created_at,
+          type: 'text'
+        });
+      }
+      
+      messages.value = extractedMessages;
+      // 将提取的消息保存到会话中,避免重复提取
+      conversation.messages = extractedMessages;
+    } else {
+      messages.value = [];
+    }
+    
+    // 设置 session_id
+    session_id.value = conversationId;
+  } else {
+    messages.value = [];
+    session_id.value = "";
+  }
 };
 
 const handleFileDrop = async (event) => {
@@ -4432,6 +4548,7 @@ const updateCollapsedState = () => {
   text-overflow: ellipsis;
   display: -webkit-box;
   -webkit-line-clamp: 2;
+  line-clamp: 2;
   -webkit-box-orient: vertical;
   white-space:nowrap;
 	overflow:hidden;
@@ -5453,6 +5570,127 @@ const updateCollapsedState = () => {
 .message-text ::v-deep table tr:nth-child(even) {
   background-color: #f2f2f2;
 }
+
+/* 知识源样式 */
+.knowledge-sources {
+  margin-top: 12px;
+  padding: 12px;
+  background: #f8f9fa;
+  border-radius: 8px;
+ 
+}
+
+.knowledge-sources-header {
+  display: flex;
+  align-items: center;
+  gap: 8px;
+  margin-bottom: 12px;
+  font-size: 14px;
+  font-weight: 500;
+  color: #1890ff;
+}
+
+.knowledge-sources-header .anticon {
+  font-size: 16px;
+}
+
+
+.knowledge-source-group:last-child {
+  margin-bottom: 0;
+}
+
+.knowledge-source-type {
+  font-size: 12px;
+  color: #666;
+  margin-bottom: 8px;
+  padding: 4px 8px;
+  background: #e6f7ff;
+  border-radius: 4px;
+  display: inline-block;
+}
+
+.knowledge-source-items {
+  display: flex;
+  flex-direction: column;
+  gap: 8px;
+}
+
+/* .knowledge-source-item {
+  background: #fff;
+  border: 1px solid #e8e8e8;
+  border-radius: 6px;
+  padding: 12px;
+  cursor: pointer;
+  transition: all 0.3s ease;
+  position: relative;
+}
+
+.knowledge-source-item:hover {
+  border-color: #1890ff;
+  box-shadow: 0 2px 8px rgba(24, 144, 255, 0.15);
+  transform: translateY(-1px);
+} */
+
+.knowledge-source-content {
+  position: relative;
+}
+
+.knowledge-source-title {
+  font-size: 14px;
+  font-weight: 500;
+  color: #1890ff;
+  margin-bottom: 6px;
+  line-height: 1.4;
+  cursor: pointer;
+  text-decoration: underline;
+  transition: color 0.3s ease;
+  white-space: nowrap;
+  overflow: hidden;
+  text-overflow: ellipsis;
+}
+
+.knowledge-source-title:hover {
+  color: #40a9ff;
+  text-decoration: underline;
+}
+
+.knowledge-source-text {
+  font-size: 12px;
+  color: #666;
+  line-height: 1.5;
+  margin-bottom: 8px;
+  display: -webkit-box;
+  -webkit-line-clamp: 3;
+  line-clamp: 3;
+  -webkit-box-orient: vertical;
+  overflow: hidden;
+  text-overflow: ellipsis;
+}
+
+.knowledge-source-meta {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  font-size: 11px;
+  color: #999;
+}
+
+.knowledge-source-doc {
+  background: #f0f0f0;
+  padding: 2px 6px;
+  border-radius: 3px;
+}
+
+.knowledge-source-score {
+  color: #52c41a;
+  font-weight: 500;
+}
+
+/* 知识源点击效果 */
+.knowledge-source-item:active {
+  transform: translateY(0);
+  box-shadow: 0 1px 4px rgba(24, 144, 255, 0.2);
+}
 .video-preview {
   position: relative;
   width: 300px;