Bladeren bron

合并代码

chd 6 maanden geleden
bovenliggende
commit
3b7168d62f
4 gewijzigde bestanden met toevoegingen van 77 en 58 verwijderingen
  1. 3 2
      css/chat.css
  2. 12 29
      js/ai-service.js
  3. 60 25
      js/chat-ui.js
  4. 2 2
      js/content.js

+ 3 - 2
css/chat.css

@@ -505,6 +505,7 @@
 }
 
 /* 复制按钮样式 */
+.fill-button,
 .copy-button {
   display: flex;
   align-items: center;
@@ -519,12 +520,12 @@
   cursor: pointer;
   transition: all 0.2s ease;
 }
-
+.fill-button:hover,
 .copy-button:hover {
   background: rgba(0, 0, 0, 0.05);
   color: #1a73e8;
 }
-
+.fill-button svg, 
 .copy-button svg {
   width: 14px;
   height: 14px;

+ 12 - 29
js/ai-service.js

@@ -7,7 +7,7 @@ class AIService {
     this.apiEndpoint = CONFIG.AI_API.ENDPOINT;
     this.messageContainer = document.getElementById("chat-messages");
     this.model = CONFIG.AI_API.MODEL;
-    
+
     this.context = [];
     this.currentExcelData = null; // 保存当前Excel数据
     this.response = ''
@@ -64,31 +64,13 @@ class AIService {
       const response = await this.openai.chat.completions.create({
         model: "qwen-plus",  //模型列表:https://help.aliyun.com/zh/model-studio/getting-started/models
         messages: this.formatMessages(message),
-        stream:true
+        stream: true
       });
-      try {
-        const iterator = response.iterator();
-        for await (const chunk of iterator) {
-          if (chunk) {
-            console.log(chunk);
-            
-            const decodedChunk = chunk.choices[0].delta.content;
-            if (decodedChunk) {
-              text += decodedChunk;
-              paragraph.innerHTML = text
-            }
-         
-          }
-        }
-        
-      } catch (error) {
-        if (signal.aborted) {
-          console.log("Stream reading aborted");
-        } else {
-          console.error("Error reading stream:", error);
-        }
-      } 
-      console.log((+new Date() - a) / 1000)
+      
+      return response;
+
+
+      // console.log((+new Date() - a) / 1000)
       // console.log(completion.choices[0].message.content);
 
       // const response = await fetch(this.apiEndpoint, {
@@ -117,11 +99,12 @@ class AIService {
 
       // return aiResponse;
     } catch (error) {
-      if (error.name === "AbortError") {
-        throw new Error("REQUEST_ABORTED");
-      }
+      // if (error.name === "AbortError") {
+      //   throw new Error("REQUEST_ABORTED");
+      // }
       console.error("API call failed:", error);
-      throw error;
+      // throw error;
+      return '[FILE]'
     } finally {
       this.controller = null;
     }

+ 60 - 25
js/chat-ui.js

@@ -195,7 +195,7 @@ class ChatUI {
         // 发送分析请求到父页面
         window.parent.postMessage({ type: "ANALYZE_PAGE" }, "*");
         console.log(2222285);
-        
+
       });
       console.log(this.iframeInfo);
       this.fileInput.click();
@@ -265,10 +265,7 @@ class ChatUI {
 基于这个Excel文件的内容,请回答以下问题:
 ${this.iframeInfo}`;
       }
-
       const response = await this.aiService.sendMessage(prompt);
-console.log(response);
-
       if (this.loadingDiv) {
         this.loadingDiv.remove();
         this.loadingDiv = null;
@@ -309,13 +306,7 @@ console.log(response);
    * @param {boolean} typing 是否使用打字效果
    * @param {boolean} isInterrupted 是否是中断消息
    */
-  addMessage(
-    content,
-    type,
-    typing = type === "assistant",
-    isInterrupted = false
-  ) {
-    if (!content) return
+  async addMessage(content, type, typing = type === "assistant", isInterrupted = false) {
     const messageDiv = document.createElement("div");
     messageDiv.className = `message ${type}`;
 
@@ -336,8 +327,13 @@ console.log(response);
     if (type === "assistant" && !isInterrupted) {
       const copyButton = this.createCopyButton(content);
       actionsDiv.appendChild(copyButton);
-      actionsDiv.appendChild(this.createFillButton());
+      console.log(content);
+
+      console.log(Object.prototype.toString.call(content));
 
+      if (Object.prototype.toString.call(content) === "[object Object]") {
+        actionsDiv.appendChild(this.createFillButton(paragraph));
+      }
     }
 
     // 添加时间戳
@@ -350,7 +346,34 @@ console.log(response);
     messageDiv.appendChild(messageContent);
     this.messageContainer.appendChild(messageDiv);
 
-    paragraph.innerHTML = this.formatMessage(content);
+    if (typing) {
+      messageContent.classList.add("typing");
+      if (typeof content !== 'string') {
+        const signal = content.controller.signal;
+        try {
+          const iterator = content.iterator();
+          for await (const chunk of iterator) {
+            if (chunk) {
+              const decodedChunk = chunk.choices[0].delta.content;
+              if (decodedChunk) {
+                paragraph.innerHTML += decodedChunk;
+              }
+            }
+          }
+        } catch (error) {
+          if (signal.aborted) {
+            console.log("Stream reading aborted");
+          } else {
+            console.error("Error reading stream:", error);
+          }
+        }
+      } else {
+        await this.typeMessage(paragraph, content);
+      }
+      messageContent.classList.remove("typing");
+    } else {
+      paragraph.innerHTML = this.formatMessage(content);
+    }
 
     const { scrollTop, scrollHeight, clientHeight } = this.messageContainer;
     const wasAtBottom = scrollHeight - scrollTop - clientHeight < 100;
@@ -369,7 +392,7 @@ console.log(response);
    * @param {string} text 要显示的文字
    */
   async typeMessage(element, text) {
-   return  element.innerHTML = text;
+    return element.innerHTML = text;
     let index = 0;
     const rawText = text;
     const tempDiv = document.createElement("div");
@@ -546,12 +569,24 @@ console.log(response);
         .replace(/^>\s+(.+)$/gm, "<blockquote>$1</blockquote>")
     );
   }
-  createFillButton() {
+
+  createFillButton(paragraph) {
     const button = document.createElement("button");
-    button.id = 'fill-button'
     button.className = "fill-button";
-    button.innerHTML = `填充`;
-  
+    button.innerHTML = `
+      <svg viewBox="0 0 24 24" fill="currentColor">
+        <path d="M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04c.39-.39.39-1.02 0-1.41l-2.34-2.34c-.39-.39-1.02-.39-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z"/>
+      </svg>
+      <span>填充</span>
+    `;
+    button.addEventListener("click", () => {
+      window.parent.postMessage({
+        type: "HANDLE_FILL_INPUT", data: {
+          formData: JSON.parse(paragraph.innerHTML.split('json')[1].split('```')[0])  //根据不同返回修改res
+        }
+      }, "*");
+    });
+
     return button;
   }
   /**
@@ -739,7 +774,7 @@ console.log(response);
         this.loadingDiv = null;
       }
 
-      await this.addMessage(response, "assistant", true);
+      await this.addMessage(response, "assistant", false);
 
       // 将总结内容添加到上下文
       this.aiService.updateContext(prompt, "user");
@@ -778,7 +813,7 @@ console.log(response);
         if (this.excelTypes[extension]) {
           try {
             this.setInputState(true);
-            this.loadingDiv = ''
+            this.loadingDiv = this.createLoadingMessage();
 
             // 读取Excel文件
             const data = await this.readExcelFile(file);
@@ -797,12 +832,12 @@ console.log(response);
             // 调用AI服务理解数据
             const response = await this.aiService.sendMessage(prompt);
             console.log(response);
-            
+
             if (this.loadingDiv) {
               this.loadingDiv.remove();
               this.loadingDiv = null;
             }
-           0 &&  window.parent.postMessage({
+            0 && window.parent.postMessage({
               type: "HANDLE_FILL_INPUT", data: {
                 excelData: this.excelData,
                 formData: JSON.parse(response.split('json')[1].split('```')[0])  //根据不同返回修改res
@@ -840,7 +875,7 @@ console.log(response);
     const headers = data[0];
     const rows = data.slice(1);
     const sampleRows = rows.slice(0, 2);
-    console.log(); 
+    console.log();
     data[0].forEach((header, i) => {
       if (!this.excelData[header]) this.excelData[header] = []
       this.excelData[header].push(data[1][i])
@@ -850,7 +885,7 @@ console.log(response);
         excelData: this.excelData,
       }
     }, "*");
-   
+
     return `我将向你展示一个通过SheetJS库读取的Excel文件内容和一个form表单。请帮我理解这些数据:
 
 文件名:${fileName}
@@ -917,7 +952,7 @@ ${this.iframeInfo}
 //             .join(", ")}`;
 //         })                                                                                                  
 //         .join("\n")}
-  
+
 // 等待DOM加载完成后再初始化
 document.addEventListener("DOMContentLoaded", () => {
   try {

+ 2 - 2
js/content.js

@@ -95,7 +95,7 @@ class SidebarManager {
       // 创建并触发 change 事件
       const changeEvent = new Event('change', { bubbles: true });
       element.dispatchEvent(changeEvent);
- 
+
       // 可选:如果表单使用了 React/Vue 等框架,可能还需要触发以下事件
       element.dispatchEvent(new Event('blur'));
       element.dispatchEvent(new KeyboardEvent('keyup', { key: 'Enter' }));
@@ -164,7 +164,7 @@ class SidebarManager {
               }
             }
           }
-          
+
           if (item.type === 'date') {
             formatDate
             const input = formChildren.find(child => child.id === item.findByValue)