Răsfoiți Sursa

修改内容

yangg 3 săptămâni în urmă
părinte
comite
4b3368316b

Fișier diff suprimat deoarece este prea mare
+ 0 - 0
dist/assets/forget-password-D20F_k0g.js


Fișier diff suprimat deoarece este prea mare
+ 0 - 1
dist/assets/index-tDyIIwdu.js


Fișier diff suprimat deoarece este prea mare
+ 0 - 0
dist/assets/login-BfSyuGcv.js


Fișier diff suprimat deoarece este prea mare
+ 0 - 0
dist/assets/register-mRTP14Y_.js


Fișier diff suprimat deoarece este prea mare
+ 0 - 0
dist/assets/report-BjthnxX-.js


Fișier diff suprimat deoarece este prea mare
+ 0 - 0
dist/assets/report-COswXvmW.js


Fișier diff suprimat deoarece este prea mare
+ 0 - 0
dist/assets/report-Cp3z2zt5.css


Fișier diff suprimat deoarece este prea mare
+ 0 - 0
dist/assets/report-DUpEEVEj.css


+ 1 - 1
dist/index.html

@@ -5,7 +5,7 @@
     <link rel="icon" type="image/svg+xml" href="/vite.svg" />
     <meta name="viewport" content="width=device-width, initial-scale=1.0" />
     <title></title>
-    <script type="module" crossorigin src="/assets/index-Bhi9BLS1.js"></script>
+    <script type="module" crossorigin src="/assets/index-tDyIIwdu.js"></script>
     <link rel="modulepreload" crossorigin href="/assets/vendor-CDgCf3zB.js">
     <link rel="stylesheet" crossorigin href="/assets/index-CVrWfcbZ.css">
   </head>

+ 91 - 22
src/views/report.vue

@@ -485,13 +485,20 @@
             v-model="inputContent"
             @keyup.enter="sendMessage"
             placeholder="Type a message..."
-          /><!--  @input="handleInputChange" -->
+          /><!--  @input="handleInputChange"  :disabled="(!inputContent && attachedFiles.length === 0)"-->
           <button
             class="send-btn"
             @click="sendMessage"
-            :disabled="!inputContent && attachedFiles.length === 0"
+           
           >
-            <img src="../assets/svg/up.svg" alt="send" />
+            <template v-if="isTyping">
+              <span class="loading-btn">
+                <span class="loading-square"></span>
+              </span>
+            </template>
+            <template v-else>
+              <img src="../assets/svg/up.svg" alt="send" />
+            </template>
           </button>
         </div>
       </div>
@@ -807,6 +814,7 @@ const conversations = ref([
 // 添加打字效果相关的状态
 const typingSpeed = 50; // 打字速度(毫秒/字符)
 const isTyping = ref(false);
+const typingTimeout = ref(null); // 添加打字超时引用
 
 // 添加音频播放相关的响应式变量
 const audioPlayer = ref(null);
@@ -1194,6 +1202,9 @@ const scrollToBottom = () => {
 
 // 添加 session_id 的响应式引用
 const session_id = ref("");
+// 添加取消控制器
+const abortController = ref(null);
+
 // 修改发送消息方法
 const sendMessage = async () => {
   // 检查登录状态
@@ -1202,13 +1213,26 @@ const sendMessage = async () => {
     router.push('/login');
     return;
   }
-
+  if(isTyping.value){
+    isTyping.value = false;
+    // 如果存在正在进行的请求,取消它
+    if (abortController.value) {
+      abortController.value.abort();
+      abortController.value = null;
+    }
+    // 清除打字效果的定时器
+    if (typingTimeout.value) {
+      clearTimeout(typingTimeout.value);
+      typingTimeout.value = null;
+    }
+    return;
+  }
   if (
     (!inputContent.value.trim() && attachedFiles.value.length === 0) ||
     isTyping.value
   )
     return;
-
+    isTyping.value = true;
   // 保存当前输入内容
   const currentMessage = inputContent.value.trim();
 
@@ -1279,6 +1303,9 @@ const sendMessage = async () => {
  /*  scrollToBottom(); */
 
   try {
+    // 创建新的 AbortController
+    abortController.value = new AbortController();
+    
     // 根据开关状态选择不同的 API 端点
     const apiEndpoint = enableWebSearch.value
       ? `${import.meta.env.VITE_BASE_AI_API}/api/chat/web-search-llm/`
@@ -1300,7 +1327,8 @@ const sendMessage = async () => {
     {
       headers: {
         'Authorization': `JWT ${localStorage.getItem('token')}`
-      }
+      },
+      signal: abortController.value.signal
     }
   );
 
@@ -1339,18 +1367,32 @@ const sendMessage = async () => {
     await typeMessage(aiMessage);
     
   } catch (error) {
-    console.error("发送消息失败:", error);
-    messages.value = messages.value.filter(
-      (msg) => msg.id !== tempAiMessage.id
-    );
-    messages.value.push({
-      id: Date.now() + 2,
-      role: "assistant",
-      content: "Sorry, there was an error processing your request.",
-      displayContent: "Sorry, there was an error processing your request.",
-    });
+    if (error.name === 'CanceledError') {
+      console.log('请求已被取消');
+      messages.value = messages.value.filter(
+        (msg) => msg.id !== tempAiMessage.id
+      );
+      messages.value.push({
+        id: Date.now() + 2,
+        role: "assistant",
+        content: "生成已取消",
+        displayContent: "生成已取消",
+      });
+    } else {
+      console.error("发送消息失败:", error);
+      messages.value = messages.value.filter(
+        (msg) => msg.id !== tempAiMessage.id
+      );
+      messages.value.push({
+        id: Date.now() + 2,
+        role: "assistant",
+        content: "Sorry, there was an error processing your request.",
+        displayContent: "Sorry, there was an error processing your request.",
+      });
+    }
   } finally {
     isTyping.value = false;
+    abortController.value = null;
     await nextTick();
     /* scrollToBottom(); */
   }
@@ -1398,14 +1440,15 @@ const typeMessage = async (message) => {
     message.displayContent = ""; // 确保开始时是空的
 
     const typeChar = () => {
-      if (i < message.content.length) {
+      if (i < message.content.length && isTyping.value) {
         message.displayContent = message.content.substring(0, i + 1);
         i++;
-        nextTick(() => {
-         /*  scrollToBottom(); */
-          setTimeout(typeChar, delay);
-        });
+        typingTimeout.value = setTimeout(typeChar, delay);
       } else {
+        if (!isTyping.value) {
+          // 如果打字被取消,直接显示完整内容
+          message.displayContent = message.content;
+        }
         resolve();
       }
     };
@@ -2190,7 +2233,6 @@ const updateCollapsedState = () => {
   const handleDocClick = (doc) => {
     currentDoc.value = doc;
   };
-
  </script>
 
 <style scoped>
@@ -2569,6 +2611,7 @@ const updateCollapsedState = () => {
   cursor: pointer;
   color: rgba(0, 0, 0, 0.45);
   border-radius: 4px;
+  padding: 0;
 }
 
 .attachment-btn:hover,
@@ -2835,6 +2878,32 @@ const updateCollapsedState = () => {
   transition: border 0.3s, background 0.3s; /* 替换 var(--ant-motion-duration-slow) */
   border: 1px solid #f0f0f0; /* 替换合的 border 属性 */
 }
+
+.loading-btn {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    width: 32px;
+    height: 32px;
+    background: #4d7cff;
+    border-radius: 50%;
+    position: relative;
+  }
+
+  .loading-square {
+    width: 14px;
+    height: 14px;
+    background: #fff;
+    border-radius: 3px;
+    display: block;
+    animation: loading-square-blink 1s infinite;
+  }
+
+  @keyframes loading-square-blink {
+    0%, 100% { opacity: 1; }
+    50% { opacity: 0.5; }
+  }
+
 :root {
   --ant-color-bg-container: #ffffff;
   --ant-border-radius-lg: 8px;

Unele fișiere nu au fost afișate deoarece prea multe fișiere au fost modificate în acest diff