From f2d004a07d198d6d483f93228005506ae5c70ed2 Mon Sep 17 00:00:00 2001
From: 云 <2163098428@qq.com>
Date: 星期二, 09 六月 2026 16:43:04 +0800
Subject: [PATCH] feat(collaborativeApproval): 添加知识库RAG向量检索问答功能

---
 src/views/collaborativeApproval/knowledgeBase/index.vue |  133 ++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 127 insertions(+), 6 deletions(-)

diff --git a/src/views/collaborativeApproval/knowledgeBase/index.vue b/src/views/collaborativeApproval/knowledgeBase/index.vue
index 8d625cf..907e51f 100644
--- a/src/views/collaborativeApproval/knowledgeBase/index.vue
+++ b/src/views/collaborativeApproval/knowledgeBase/index.vue
@@ -259,6 +259,22 @@
           >
             淇濆瓨鏂囦欢鍏宠仈
           </el-button>
+          <el-button
+            v-if="uploadedBlobIds.length > 0"
+            type="text"
+            @click="clearUploadedFiles"
+            style="margin-left: 10px"
+          >
+            娓呯┖寰呬繚瀛樺垪琛�
+          </el-button>
+        </div>
+
+        <!-- 寰呬繚瀛樼殑鏂囦欢鍒楄〃 -->
+        <div v-if="uploadedBlobIds.length > 0" class="uploaded-list">
+          <div class="uploaded-tip">
+            <el-icon style="color: #409eff"><InfoFilled /></el-icon>
+            <span>宸蹭笂浼� {{ uploadedBlobIds.length }} 涓枃浠�,璇风偣鍑�"淇濆瓨鏂囦欢鍏宠仈"鎸夐挳瑙﹀彂鍚戦噺鍖栧鐞�</span>
+          </div>
         </div>
 
         <!-- 鏂囦欢鍒楄〃涓庡悜閲忓寲鐘舵�� -->
@@ -273,6 +289,12 @@
             </template>
           </el-table-column>
           <el-table-column prop="chunkCount" label="鍒囩墖鏁�" width="100" align="center" />
+          <el-table-column label="閿欒淇℃伅" width="200" show-overflow-tooltip>
+            <template #default="{ row }">
+              <span v-if="row.vectorError" style="color: #f56c6c">{{ row.vectorError }}</span>
+              <span v-else style="color: #909399">-</span>
+            </template>
+          </el-table-column>
           <el-table-column prop="createTime" label="涓婁紶鏃堕棿" width="180" />
           <el-table-column label="鎿嶄綔" width="150" align="center">
             <template #default="{ row }">
@@ -326,7 +348,7 @@
         <div class="chat-input">
           <el-input
             v-model="inputQuestion"
-            placeholder="璇疯緭鍏ラ棶棰橈紝鎸夊洖杞﹀彂閫�"
+            placeholder="璇疯緭鍏ラ棶棰�,鎸夊洖杞﹀彂閫�(Ctrl+Enter蹇嵎鍙戦��)"
             @keyup.enter="sendMessage"
             :disabled="chatLoading"
           >
@@ -334,6 +356,9 @@
               <el-button @click="sendMessage" :loading="chatLoading">鍙戦��</el-button>
             </template>
           </el-input>
+          <div class="chat-actions">
+            <el-button type="text" size="small" @click="clearMessages">娓呯┖瀵硅瘽</el-button>
+          </div>
         </div>
       </div>
     </FormDialog>
@@ -341,7 +366,7 @@
 </template>
 
 <script setup>
-import { Search } from "@element-plus/icons-vue";
+import { Search, InfoFilled } from "@element-plus/icons-vue";
 import { onMounted, ref, reactive, toRefs, getCurrentInstance, computed, watch, nextTick } from "vue";
 import { ElMessage, ElMessageBox } from "element-plus";
 import PIMTable from "@/components/PIMTable/PIMTable.vue";
@@ -412,6 +437,7 @@
   fileList: [],
   uploadedBlobIds: [],
   savingFiles: false,
+  vectorStatusTimer: null, // 鍚戦噺鍖栫姸鎬佽疆璇㈠畾鏃跺櫒
   chatDialogVisible: false,
   messages: [],
   inputQuestion: "",
@@ -436,6 +462,7 @@
   fileList,
   uploadedBlobIds,
   savingFiles,
+  vectorStatusTimer,
   chatDialogVisible,
   messages,
   inputQuestion,
@@ -872,9 +899,45 @@
   try {
     const res = await getVectorStatus(currentKnowledgeBase.value.id);
     fileList.value = res.data || [];
+
+    // 妫�鏌ユ槸鍚︽湁澶勭悊涓殑鏂囦欢,濡傛灉鏈夊垯鍚姩杞
+    const hasProcessing = res.data.some(item => item.vectorStatus === 1);
+    if (hasProcessing && !vectorStatusTimer.value) {
+      startVectorStatusPolling();
+    } else if (!hasProcessing && vectorStatusTimer.value) {
+      stopVectorStatusPolling();
+    }
   } catch (error) {
     console.error("鍔犺浇鏂囦欢鍒楄〃澶辫触:", error);
     ElMessage.error("鍔犺浇鏂囦欢鍒楄〃澶辫触");
+  }
+};
+
+// 寮�濮嬭疆璇㈠悜閲忓寲鐘舵��
+const startVectorStatusPolling = () => {
+  vectorStatusTimer.value = setInterval(async () => {
+    try {
+      const res = await getVectorStatus(currentKnowledgeBase.value.id);
+      fileList.value = res.data || [];
+
+      // 妫�鏌ユ槸鍚﹁繕鏈夊鐞嗕腑鐨勬枃浠�
+      const hasProcessing = res.data.some(item => item.vectorStatus === 1);
+      if (!hasProcessing) {
+        stopVectorStatusPolling();
+        ElMessage.success("鎵�鏈夋枃浠跺悜閲忓寲澶勭悊瀹屾垚");
+      }
+    } catch (error) {
+      console.error("杞鍚戦噺鍖栫姸鎬佸け璐�:", error);
+      stopVectorStatusPolling();
+    }
+  }, 3000); // 姣�3绉掕疆璇竴娆�
+};
+
+// 鍋滄杞鍚戦噺鍖栫姸鎬�
+const stopVectorStatusPolling = () => {
+  if (vectorStatusTimer.value) {
+    clearInterval(vectorStatusTimer.value);
+    vectorStatusTimer.value = null;
   }
 };
 
@@ -957,6 +1020,12 @@
   }
 };
 
+// 娓呯┖寰呬繚瀛樼殑鏂囦欢鍒楄〃
+const clearUploadedFiles = () => {
+  uploadedBlobIds.value = [];
+  ElMessage.success("宸叉竻绌哄緟淇濆瓨鏂囦欢鍒楄〃");
+};
+
 // 鍒犻櫎鏂囦欢
 const deleteFile = async (row) => {
   try {
@@ -1009,7 +1078,8 @@
   currentKnowledgeBase.value = null;
   fileList.value = [];
   uploadedBlobIds.value = [];
-  getList(); // 鍒锋柊涓诲垪琛紝鏇存柊鏂囦欢鏁伴噺
+  stopVectorStatusPolling(); // 鍋滄杞
+  getList(); // 鍒锋柊涓诲垪琛�,鏇存柊鏂囦欢鏁伴噺
 };
 
 // ============ 鐭ヨ瘑搴撻棶绛旂浉鍏� ============
@@ -1027,6 +1097,11 @@
 const sendMessage = async () => {
   if (!inputQuestion.value.trim()) {
     ElMessage.warning("璇疯緭鍏ラ棶棰�");
+    return;
+  }
+
+  if (!currentKnowledgeBase.value?.id) {
+    ElMessage.error("鐭ヨ瘑搴撲俊鎭紓甯�");
     return;
   }
 
@@ -1061,7 +1136,8 @@
     });
 
     if (!response.ok) {
-      throw new Error('璇锋眰澶辫触');
+      const errorText = await response.text();
+      throw new Error(errorText || '璇锋眰澶辫触');
     }
 
     // 澶勭悊SSE娴佸紡鍝嶅簲
@@ -1083,16 +1159,40 @@
       await nextTick();
       scrollToBottom();
     }
+
+    // 濡傛灉AI杩斿洖绌哄唴瀹�,鏄剧ず鎻愮ず
+    if (!aiContent.trim()) {
+      messages.value[messages.value.length - 1].content = '鎶辨瓑,鐭ヨ瘑搴撲腑鏈壘鍒扮浉鍏冲唴瀹�,璇峰皾璇曞叾浠栭棶棰樸��';
+    }
   } catch (error) {
     console.error("闂瓟璇锋眰澶辫触:", error);
-    ElMessage.error("闂瓟璇锋眰澶辫触锛岃绋嶅悗閲嶈瘯");
+    ElMessage.error("闂瓟璇锋眰澶辫触,璇风◢鍚庨噸璇�");
     messages.value.push({
       role: 'assistant',
-      content: '鎶辨瓑锛屽彂鐢熶簡閿欒锛岃绋嶅悗閲嶈瘯'
+      content: '鎶辨瓑,鍙戠敓浜嗛敊璇�,璇风◢鍚庨噸璇�'
     });
   } finally {
     chatLoading.value = false;
   }
+};
+
+// 娓呯┖瀵硅瘽
+const clearMessages = () => {
+  ElMessageBox.confirm(
+    "纭畾瑕佹竻绌烘墍鏈夊璇濊褰曞悧?",
+    "娓呯┖纭",
+    {
+      confirmButtonText: "纭畾",
+      cancelButtonText: "鍙栨秷",
+      type: "warning"
+    }
+  ).then(() => {
+    messages.value = [];
+    memoryId.value = crypto.randomUUID(); // 閲嶆柊鐢熸垚浼氳瘽ID
+    ElMessage.success("瀵硅瘽宸叉竻绌�");
+  }).catch(() => {
+    // 鐢ㄦ埛鍙栨秷
+  });
 };
 
 // 婊氬姩鍒板簳閮�
@@ -1195,6 +1295,22 @@
   align-items: center;
 }
 
+.uploaded-list {
+  margin-top: 16px;
+  padding: 12px;
+  background: #f0f9ff;
+  border-radius: 6px;
+  border: 1px solid #b3d8ff;
+}
+
+.uploaded-tip {
+  display: flex;
+  align-items: center;
+  gap: 8px;
+  color: #409eff;
+  font-size: 14px;
+}
+
 /* 鐭ヨ瘑搴撻棶绛旀牱寮� */
 .knowledge-chat {
   display: flex;
@@ -1272,4 +1388,9 @@
   margin-top: auto;
 }
 
+.chat-actions {
+  margin-top: 8px;
+  text-align: right;
+}
+
 </style>

--
Gitblit v1.9.3