Browse Source

聊天切换豆包

yichael 5 tháng trước cách đây
mục cha
commit
0a7feb7a69
39 tập tin đã thay đổi với 275 bổ sung400 xóa
  1. 30 17
      main-js/func/img-reg.js
  2. 146 71
      main-js/history.js
  3. 4 5
      src/pages/Chat/Input/Input.js
  4. 35 0
      src/pages/Processing/ActionParser.js
  5. 0 74
      static/processing/微信聊天自动发送工作流/history/chat_2026-01-14T13-18-10.json
  6. 0 54
      static/processing/微信聊天自动发送工作流/history/chat_2026-01-14T13-19-11.json
  7. 0 54
      static/processing/微信聊天自动发送工作流/history/chat_2026-01-14T13-20-39.json
  8. 0 54
      static/processing/微信聊天自动发送工作流/history/chat_2026-01-14T13-22-08.json
  9. 0 5
      static/processing/微信聊天自动发送工作流/history/chat_2026-01-14T17-18-22.json
  10. 0 5
      static/processing/微信聊天自动发送工作流/history/chat_2026-01-14T17-25-28.json
  11. 0 5
      static/processing/微信聊天自动发送工作流/history/chat_2026-01-14T17-31-49.json
  12. 0 5
      static/processing/微信聊天自动发送工作流/history/chat_2026-01-14T17-33-19.json
  13. 0 5
      static/processing/微信聊天自动发送工作流/history/chat_2026-01-14T17-34-48.json
  14. 5 0
      static/processing/微信聊天自动发送工作流/history/chat_2026-01-14T19-31-21.json
  15. 5 0
      static/processing/微信聊天自动发送工作流/history/chat_2026-01-14T19-52-19.json
  16. 5 0
      static/processing/微信聊天自动发送工作流/history/chat_2026-01-14T19-53-48.json
  17. 5 0
      static/processing/微信聊天自动发送工作流/history/chat_2026-01-14T19-59-33.json
  18. 5 0
      static/processing/微信聊天自动发送工作流/history/chat_2026-01-14T20-02-07.json
  19. 5 0
      static/processing/微信聊天自动发送工作流/history/chat_2026-01-14T20-12-55.json
  20. 5 0
      static/processing/微信聊天自动发送工作流/history/chat_2026-01-14T20-21-28.json
  21. 5 0
      static/processing/微信聊天自动发送工作流/history/chat_2026-01-14T20-23-06.json
  22. 5 0
      static/processing/微信聊天自动发送工作流/history/chat_2026-01-14T20-32-04.json
  23. 1 1
      static/processing/微信聊天自动发送工作流/history/summary.txt
  24. 14 45
      static/processing/微信聊天自动发送工作流/processing.json
  25. BIN
      static/processing/微信聊天自动发送工作流/tmp/2026-01-14_11-54-19/screenshot.png
  26. BIN
      static/processing/微信聊天自动发送工作流/tmp/2026-01-14_12-02-33/screenshot.png
  27. BIN
      static/processing/微信聊天自动发送工作流/tmp/2026-01-14_12-10-25/screenshot.png
  28. BIN
      static/processing/微信聊天自动发送工作流/tmp/2026-01-14_12-33-59/screenshot.png
  29. BIN
      static/processing/微信聊天自动发送工作流/tmp/2026-01-14_12-34-07/screenshot_ocr.png
  30. BIN
      static/processing/微信聊天自动发送工作流/tmp/2026-01-14_12-35-15/screenshot.png
  31. BIN
      static/processing/微信聊天自动发送工作流/tmp/2026-01-14_12-35-43/screenshot_ocr.png
  32. BIN
      static/processing/微信聊天自动发送工作流/tmp/2026-01-14_12-42-01/screenshot.png
  33. BIN
      static/processing/微信聊天自动发送工作流/tmp/2026-01-14_12-42-09/screenshot_ocr.png
  34. BIN
      static/processing/微信聊天自动发送工作流/tmp/2026-01-14_12-43-13/screenshot.png
  35. BIN
      static/processing/微信聊天自动发送工作流/tmp/2026-01-14_13-20-34/screenshot.png
  36. BIN
      static/processing/微信聊天自动发送工作流/tmp/2026-01-14_18-44-53/screenshot.png
  37. BIN
      static/processing/微信聊天自动发送工作流/tmp/2026-01-14_19-20-03/screenshot.png
  38. BIN
      static/processing/微信聊天自动发送工作流/tmp/2026-01-14_19-20-34/screenshot_ocr.png
  39. BIN
      temp_screenshot.png

+ 30 - 17
main-js/func/img-reg.js

@@ -63,7 +63,7 @@ def match_image(image1_path, image2_path, image1_size=None):
         image1_size: image1 的目标尺寸 (width, height),可选
         image1_size: image1 的目标尺寸 (width, height),可选
     
     
     Returns:
     Returns:
-        如果找到,返回 (x, y, width, height),否则返回 None
+        如果找到,返回 (x, y, width, height, similarity),否则返回 (None, similarity)
     """
     """
     img1_path = Path(image1_path)
     img1_path = Path(image1_path)
     img2_path = Path(image2_path)
     img2_path = Path(image2_path)
@@ -100,19 +100,19 @@ def match_image(image1_path, image2_path, image1_size=None):
     # 找到最佳匹配位置
     # 找到最佳匹配位置
     min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
     min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
     
     
-    # 设置阈值(0.8 表示 80% 相似度
-    threshold = 0.8
+    # 设置阈值(0.5 表示 50% 相似度,降低阈值以提高匹配成功率
+    threshold = 0.5
     
     
     if max_val >= threshold:
     if max_val >= threshold:
         # 找到匹配位置
         # 找到匹配位置
         top_left = max_loc
         top_left = max_loc
         x, y = top_left
         x, y = top_left
         
         
-        # 返回坐标和尺寸 (x, y, width, height)
-        return (x, y, template_width, template_height)
+        # 返回坐标和尺寸 (x, y, width, height, similarity)
+        return (x, y, template_width, template_height, max_val)
     else:
     else:
-        # 未找到匹配
-        return None
+        # 未找到匹配,返回 (None, None, None, None, similarity) 以便获取匹配度
+        return (None, None, None, None, max_val)
 
 
 # 主逻辑
 # 主逻辑
 if __name__ == '__main__':
 if __name__ == '__main__':
@@ -128,19 +128,32 @@ if __name__ == '__main__':
     try:
     try:
         result = match_image(image1_path, image2_path, image1_size)
         result = match_image(image1_path, image2_path, image1_size)
         
         
-        if result:
-            x, y, w, h = result
-            output = {
-                'success': True,
-                'x': int(x),
-                'y': int(y),
-                'width': int(w),
-                'height': int(h)
-            }
+        if result and len(result) >= 5:
+            x, y, w, h, max_similarity = result[0], result[1], result[2], result[3], result[4]
+            
+            if x is not None and y is not None:
+                # 匹配成功
+                output = {
+                    'success': True,
+                    'x': int(x),
+                    'y': int(y),
+                    'width': int(w),
+                    'height': int(h),
+                    'similarity': float(max_similarity)
+                }
+            else:
+                # 匹配失败,但返回了匹配度信息
+                similarity_percent = round(max_similarity * 100, 2)
+                output = {
+                    'success': False,
+                    'error': f'未找到匹配的图像(相似度: {similarity_percent}%,阈值: 50%)',
+                    'similarity': float(max_similarity)
+                }
         else:
         else:
+            # 意外情况
             output = {
             output = {
                 'success': False,
                 'success': False,
-                'error': '未找到匹配的图像'
+                'error': '图像匹配失败:无法获取匹配结果'
             }
             }
         
         
         print(json.dumps(output, ensure_ascii=False))
         print(json.dumps(output, ensure_ascii=False))

+ 146 - 71
main-js/history.js

@@ -187,6 +187,7 @@ export async function ocrLastMessage(ipPort, method, avatarPath, area, folderPat
 
 
     // 3. 保存截图到临时文件(如果提供了工作流文件夹,保存到 tmp/时间戳 目录)
     // 3. 保存截图到临时文件(如果提供了工作流文件夹,保存到 tmp/时间戳 目录)
     let screenshotPath;
     let screenshotPath;
+    let tmpDir = null; // 用于跟踪需要删除的临时目录
     if (folderPath) {
     if (folderPath) {
       const { mkdir } = await import('fs/promises');
       const { mkdir } = await import('fs/promises');
       // 确保 folderPath 是绝对路径
       // 确保 folderPath 是绝对路径
@@ -206,7 +207,7 @@ export async function ocrLastMessage(ipPort, method, avatarPath, area, folderPat
       }
       }
       
       
       const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19).replace('T', '_');
       const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19).replace('T', '_');
-      const tmpDir = join(absoluteFolderPath, 'tmp', timestamp);
+      tmpDir = join(absoluteFolderPath, 'tmp', timestamp);
       await mkdir(tmpDir, { recursive: true });
       await mkdir(tmpDir, { recursive: true });
       screenshotPath = join(tmpDir, 'screenshot_ocr.png');
       screenshotPath = join(tmpDir, 'screenshot_ocr.png');
     } else {
     } else {
@@ -216,45 +217,57 @@ export async function ocrLastMessage(ipPort, method, avatarPath, area, folderPat
     const screenshotBuffer = Buffer.from(screenshotResult.data, 'base64');
     const screenshotBuffer = Buffer.from(screenshotResult.data, 'base64');
     await writeFile(screenshotPath, screenshotBuffer);
     await writeFile(screenshotPath, screenshotBuffer);
 
 
-    // 4. 调用 JS 实现进行OCR识别
-    const normalizedScreenshotPath = screenshotPath.replace(/\\/g, '/');
-    let result;
-    
-    if (method === 'full-screen') {
-      // 全屏OCR识别
-      result = await ocrFullScreenFromFunc(normalizedScreenshotPath, width, height);
-    } else if (method === 'by-avatar' && avatarPath) {
-      // 通过头像定位最后一条消息
-      let friendAvatarArg = null;
-      let myAvatarArg = null;
+    try {
+      // 4. 调用 JS 实现进行OCR识别
+      const normalizedScreenshotPath = screenshotPath.replace(/\\/g, '/');
+      let result;
       
       
-      if (isAbsolute(avatarPath)) {
-        friendAvatarArg = avatarPath;
-        myAvatarArg = avatarPath;
+      if (method === 'full-screen') {
+        // 全屏OCR识别
+        result = await ocrFullScreenFromFunc(normalizedScreenshotPath, width, height);
+      } else if (method === 'by-avatar' && avatarPath) {
+        // 通过头像定位最后一条消息
+        let friendAvatarArg = null;
+        let myAvatarArg = null;
+        
+        if (isAbsolute(avatarPath)) {
+          friendAvatarArg = avatarPath;
+          myAvatarArg = avatarPath;
+        } else {
+          const folderName = avatarPath.split(/[/\\]/)[0];
+          const avatarName = avatarPath.split(/[/\\]/).slice(1).join('/');
+          friendAvatarArg = join(__dirname, '..', 'static', 'processing', folderName, avatarName);
+          myAvatarArg = friendAvatarArg;
+        }
+        
+        const normalizedFriendAvatar = friendAvatarArg.replace(/\\/g, '/');
+        const normalizedMyAvatar = myAvatarArg.replace(/\\/g, '/');
+        result = await getLastMessageFromFunc(normalizedScreenshotPath, normalizedFriendAvatar, normalizedMyAvatar, width, height);
       } else {
       } else {
-        const folderName = avatarPath.split(/[/\\]/)[0];
-        const avatarName = avatarPath.split(/[/\\]/).slice(1).join('/');
-        friendAvatarArg = join(__dirname, '..', 'static', 'processing', folderName, avatarName);
-        myAvatarArg = friendAvatarArg;
+        // 默认使用全屏OCR
+        result = await ocrFullScreenFromFunc(normalizedScreenshotPath, width, height);
       }
       }
       
       
-      const normalizedFriendAvatar = friendAvatarArg.replace(/\\/g, '/');
-      const normalizedMyAvatar = myAvatarArg.replace(/\\/g, '/');
-      result = await getLastMessageFromFunc(normalizedScreenshotPath, normalizedFriendAvatar, normalizedMyAvatar, width, height);
-    } else {
-      // 默认使用全屏OCR
-      result = await ocrFullScreenFromFunc(normalizedScreenshotPath, width, height);
-    }
-    
-    if (result.success) {
-      // 返回兼容旧API的格式
-      return {
-        success: true,
-        text: result.text || '',
-        position: result.position || null
-      };
-    } else {
-      return { success: false, error: result.error || 'OCR识别失败' };
+      if (result.success) {
+        // 返回兼容旧API的格式
+        return {
+          success: true,
+          text: result.text || '',
+          position: result.position || null
+        };
+      } else {
+        return { success: false, error: result.error || 'OCR识别失败' };
+      }
+    } finally {
+      // 5. 使用完后删除临时目录
+      if (tmpDir) {
+        try {
+          await rm(tmpDir, { recursive: true, force: true });
+          console.log(`已删除临时目录: ${tmpDir}`);
+        } catch (rmError) {
+          console.warn(`删除临时目录失败: ${tmpDir}`, rmError);
+        }
+      }
     }
     }
   } catch (error) {
   } catch (error) {
     console.error('OCR识别失败:', error);
     console.error('OCR识别失败:', error);
@@ -287,6 +300,7 @@ export async function extractChatHistory(ipPort, friendAvatarPath, myAvatarPath,
 
 
     // 3. 保存截图到临时文件(如果提供了工作流文件夹,保存到 tmp/时间戳 目录)
     // 3. 保存截图到临时文件(如果提供了工作流文件夹,保存到 tmp/时间戳 目录)
     let screenshotPath;
     let screenshotPath;
+    let tmpDir = null; // 用于跟踪需要删除的临时目录
     if (workflowFolderPath) {
     if (workflowFolderPath) {
       const { mkdir } = await import('fs/promises');
       const { mkdir } = await import('fs/promises');
       // 确保 workflowFolderPath 是绝对路径
       // 确保 workflowFolderPath 是绝对路径
@@ -306,7 +320,7 @@ export async function extractChatHistory(ipPort, friendAvatarPath, myAvatarPath,
       }
       }
       
       
       const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19).replace('T', '_');
       const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19).replace('T', '_');
-      const tmpDir = join(absoluteWorkflowPath, 'tmp', timestamp);
+      tmpDir = join(absoluteWorkflowPath, 'tmp', timestamp);
       await mkdir(tmpDir, { recursive: true });
       await mkdir(tmpDir, { recursive: true });
       screenshotPath = join(tmpDir, 'screenshot.png');
       screenshotPath = join(tmpDir, 'screenshot.png');
     } else {
     } else {
@@ -326,46 +340,58 @@ export async function extractChatHistory(ipPort, friendAvatarPath, myAvatarPath,
       return { success: false, error: `截图文件写入失败: ${err.message}` };
       return { success: false, error: `截图文件写入失败: ${err.message}` };
     }
     }
 
 
-    // 4. 调用 JS 函数提取聊天记录
-    // 转换头像路径为绝对路径
-    let friendAvatarArg = null;
-    if (friendAvatarPath) {
-      if (isAbsolute(friendAvatarPath)) {
-        friendAvatarArg = friendAvatarPath;
-      } else {
-        friendAvatarArg = join(__dirname, '..', 'static', 'processing', friendAvatarPath);
+    try {
+      // 4. 调用 JS 函数提取聊天记录
+      // 转换头像路径为绝对路径
+      let friendAvatarArg = null;
+      if (friendAvatarPath) {
+        if (isAbsolute(friendAvatarPath)) {
+          friendAvatarArg = friendAvatarPath;
+        } else {
+          friendAvatarArg = join(__dirname, '..', 'static', 'processing', friendAvatarPath);
+        }
       }
       }
-    }
-    
-    let myAvatarArg = null;
-    if (myAvatarPath) {
-      if (isAbsolute(myAvatarPath)) {
-        myAvatarArg = myAvatarPath;
-      } else {
-        myAvatarArg = join(__dirname, '..', 'static', 'processing', myAvatarPath);
+      
+      let myAvatarArg = null;
+      if (myAvatarPath) {
+        if (isAbsolute(myAvatarPath)) {
+          myAvatarArg = myAvatarPath;
+        } else {
+          myAvatarArg = join(__dirname, '..', 'static', 'processing', myAvatarPath);
+        }
       }
       }
-    }
-    
-    // 如果提供了工作流文件夹路径,转换为绝对路径
-    let workflowFolderArg = null;
-    if (workflowFolderPath) {
-      if (isAbsolute(workflowFolderPath)) {
-        workflowFolderArg = workflowFolderPath;
-      } else {
-        if (workflowFolderPath.startsWith('static/processing/')) {
-          const folderName = workflowFolderPath.replace('static/processing/', '');
-          workflowFolderArg = join(__dirname, '..', 'static', 'processing', folderName);
-        } else if (workflowFolderPath.startsWith('static\\processing\\')) {
-          const folderName = workflowFolderPath.replace('static\\processing\\', '');
-          workflowFolderArg = join(__dirname, '..', 'static', 'processing', folderName);
+      
+      // 如果提供了工作流文件夹路径,转换为绝对路径
+      let workflowFolderArg = null;
+      if (workflowFolderPath) {
+        if (isAbsolute(workflowFolderPath)) {
+          workflowFolderArg = workflowFolderPath;
         } else {
         } else {
-          workflowFolderArg = join(__dirname, '..', 'static', 'processing', workflowFolderPath);
+          if (workflowFolderPath.startsWith('static/processing/')) {
+            const folderName = workflowFolderPath.replace('static/processing/', '');
+            workflowFolderArg = join(__dirname, '..', 'static', 'processing', folderName);
+          } else if (workflowFolderPath.startsWith('static\\processing\\')) {
+            const folderName = workflowFolderPath.replace('static\\processing\\', '');
+            workflowFolderArg = join(__dirname, '..', 'static', 'processing', folderName);
+          } else {
+            workflowFolderArg = join(__dirname, '..', 'static', 'processing', workflowFolderPath);
+          }
+        }
+      }
+      
+      const result = await extractChatHistoryFromFunc(screenshotPath, friendAvatarArg, myAvatarArg, width, height, workflowFolderArg);
+      return result;
+    } finally {
+      // 5. 使用完后删除临时目录
+      if (tmpDir) {
+        try {
+          await rm(tmpDir, { recursive: true, force: true });
+          console.log(`已删除临时目录: ${tmpDir}`);
+        } catch (rmError) {
+          console.warn(`删除临时目录失败: ${tmpDir}`, rmError);
         }
         }
       }
       }
     }
     }
-    
-    const result = await extractChatHistoryFromFunc(screenshotPath, friendAvatarArg, myAvatarArg, width, height, workflowFolderArg);
-    return result;
   } catch (error) {
   } catch (error) {
     console.error('提取聊天记录失败:', error);
     console.error('提取聊天记录失败:', error);
     if (error.message && error.message.includes('timeout')) {
     if (error.message && error.message.includes('timeout')) {
@@ -604,6 +630,55 @@ export function registerIpcHandlers() {
       await writeFile(filePath, JSON.stringify(historyData, null, 2), 'utf-8');
       await writeFile(filePath, JSON.stringify(historyData, null, 2), 'utf-8');
 
 
       console.log(`聊天记录已保存到: ${filePath}`);
       console.log(`聊天记录已保存到: ${filePath}`);
+
+      // 限制 history 文件夹中最多保存 10 个文件,超过则删除最早的文件
+      try {
+        const files = await readdir(historyDir, { withFileTypes: true });
+        // 过滤出 JSON 文件(chat_*.json)
+        const jsonFiles = files
+          .filter(file => file.isFile() && file.name.startsWith('chat_') && file.name.endsWith('.json'))
+          .map(file => ({
+            name: file.name,
+            path: join(historyDir, file.name)
+          }));
+
+        // 如果文件数量超过 10 个,删除最早的文件
+        if (jsonFiles.length > 10) {
+          // 获取所有文件的统计信息(创建时间或修改时间)
+          const filesWithStats = await Promise.all(
+            jsonFiles.map(async (file) => {
+              const stats = await stat(file.path);
+              return {
+                ...file,
+                birthtime: stats.birthtime || stats.mtime, // 使用创建时间,如果没有则使用修改时间
+                mtime: stats.mtime
+              };
+            })
+          );
+
+          // 按时间排序(最早的在前)
+          filesWithStats.sort((a, b) => {
+            const timeA = a.birthtime.getTime();
+            const timeB = b.birthtime.getTime();
+            return timeA - timeB;
+          });
+
+          // 删除最早的文件,直到只剩下 10 个
+          const filesToDelete = filesWithStats.slice(0, filesWithStats.length - 10);
+          for (const file of filesToDelete) {
+            try {
+              await rm(file.path, { force: true });
+              console.log(`已删除最早的聊天记录文件: ${file.name}`);
+            } catch (deleteError) {
+              console.warn(`删除文件失败: ${file.name}`, deleteError);
+            }
+          }
+        }
+      } catch (cleanupError) {
+        // 清理失败不影响保存操作
+        console.warn('清理旧聊天记录文件时出错:', cleanupError);
+      }
+
       return { success: true, filePath };
       return { success: true, filePath };
     } catch (error) {
     } catch (error) {
       console.error('保存聊天记录失败:', error);
       console.error('保存聊天记录失败:', error);

+ 4 - 5
src/pages/Chat/Input/Input.js

@@ -415,7 +415,7 @@ export function InputLogic(onSendMessage, onLoadingChange) {
       const controller = new AbortController();
       const controller = new AbortController();
       const timeoutId = setTimeout(() => controller.abort(), 1000); // 1秒超时
       const timeoutId = setTimeout(() => controller.abort(), 1000); // 1秒超时
 
 
-      const response = await fetch('http://localhost:8848/api/img2text', {
+      const response = await fetch('https://ai-anim.com/api/img2text', {
         method: 'POST',
         method: 'POST',
         headers: {
         headers: {
           'Content-Type': 'application/json',
           'Content-Type': 'application/json',
@@ -575,13 +575,12 @@ ${images.map((img, index) => `图片${index + 1}: 原始文件名 ${img.original
     const fullPrompt = `${SYSTEM_PROMPT}${imageInfoPrompt}\n\n用户需求:${userPrompt}`;
     const fullPrompt = `${SYSTEM_PROMPT}${imageInfoPrompt}\n\n用户需求:${userPrompt}`;
       
       
       const requestBody = {
       const requestBody = {
-        prompt: fullPrompt,
-        modelName: 'gpt-5-nano-ca'
+        input: fullPrompt
       };
       };
 
 
-      console.log('Sending request to GPT API:', requestBody);
+      console.log('Sending request to Doubao API:', requestBody);
 
 
-      const response = await fetch('https://ai-anim.com/api/text2textByModel', {
+      const response = await fetch('https://ai-anim.com/api/doubaoText2text', {
         method: 'POST',
         method: 'POST',
         headers: {
         headers: {
           'Content-Type': 'application/json',
           'Content-Type': 'application/json',

+ 35 - 0
src/pages/Processing/ActionParser.js

@@ -742,8 +742,14 @@ export async function executeAction(action, device, folderPath, resolution) {
 
 
       case 'input': {
       case 'input': {
         // 输入文本
         // 输入文本
+        const inputStartTime = Date.now();
+        console.log(`[input] 开始输入操作: ${new Date(inputStartTime).toLocaleTimeString('zh-CN', { hour12: false, hour: '2-digit', minute: '2-digit', second: '2-digit', fractionalSecondDigits: 3 })}`);
+        
         // 先解析value(可能在运行时变量才被赋值,需要重新解析)
         // 先解析value(可能在运行时变量才被赋值,需要重新解析)
+        let parseStartTime = Date.now();
         let inputValue = resolveValue(action.value);
         let inputValue = resolveValue(action.value);
+        let parseEndTime = Date.now();
+        console.log(`[input] 解析变量耗时: ${parseEndTime - parseStartTime}ms`);
         
         
         // 如果value为空或undefined,且target存在,使用target(用于向后兼容,target可能也是定位文字)
         // 如果value为空或undefined,且target存在,使用target(用于向后兼容,target可能也是定位文字)
         if (!inputValue && action.target) {
         if (!inputValue && action.target) {
@@ -772,6 +778,9 @@ export async function executeAction(action, device, folderPath, resolution) {
 
 
         // 如果设置了clear,先清空输入框(通过发送退格键)
         // 如果设置了clear,先清空输入框(通过发送退格键)
         if (action.clear) {
         if (action.clear) {
+          const clearStartTime = Date.now();
+          console.log(`[input] 开始清空输入框: ${new Date(clearStartTime).toLocaleTimeString('zh-CN', { hour12: false, hour: '2-digit', minute: '2-digit', second: '2-digit', fractionalSecondDigits: 3 })}`);
+          
           // 发送退格键清空输入框(假设最多200个字符)
           // 发送退格键清空输入框(假设最多200个字符)
           // 使用Android的KEYCODE_DEL,值为67
           // 使用Android的KEYCODE_DEL,值为67
           for (let i = 0; i < 200; i++) {
           for (let i = 0; i < 200; i++) {
@@ -784,14 +793,29 @@ export async function executeAction(action, device, folderPath, resolution) {
           }
           }
           // 等待清空完成
           // 等待清空完成
           await new Promise(resolve => setTimeout(resolve, 200));
           await new Promise(resolve => setTimeout(resolve, 200));
+          
+          const clearEndTime = Date.now();
+          console.log(`[input] 清空输入框完成,耗时: ${clearEndTime - clearStartTime}ms`);
         }
         }
 
 
+        const sendTextStartTime = Date.now();
+        console.log(`[input] 开始发送文本: ${new Date(sendTextStartTime).toLocaleTimeString('zh-CN', { hour12: false, hour: '2-digit', minute: '2-digit', second: '2-digit', fractionalSecondDigits: 3 })}`);
+        console.log(`[input] 待输入文本内容: ${inputValue}`);
+        
         const textResult = await window.electronAPI.sendText(device, inputValue);
         const textResult = await window.electronAPI.sendText(device, inputValue);
         
         
+        const sendTextEndTime = Date.now();
+        console.log(`[input] 发送文本完成,耗时: ${sendTextEndTime - sendTextStartTime}ms`);
+        console.log(`[input] sendText 返回结果:`, textResult);
+        
         if (!textResult.success) {
         if (!textResult.success) {
+          console.error(`[input] 输入失败: ${textResult.error}`);
           return { success: false, error: `输入失败: ${textResult.error}` };
           return { success: false, error: `输入失败: ${textResult.error}` };
         }
         }
 
 
+        const inputEndTime = Date.now();
+        console.log(`[input] 输入操作总耗时: ${inputEndTime - inputStartTime}ms`);
+
         // 确保正确显示UTF-8编码的中文
         // 确保正确显示UTF-8编码的中文
         try {
         try {
           const displayValue = Buffer.isBuffer(inputValue) 
           const displayValue = Buffer.isBuffer(inputValue) 
@@ -1339,9 +1363,20 @@ export async function executeActionSequence(
         console.log(`${stepPrefix}执行步骤 ${i + 1}/${actions.length}: ${action.type}`);
         console.log(`${stepPrefix}执行步骤 ${i + 1}/${actions.length}: ${action.type}`);
       }
       }
 
 
+      // 记录步骤开始时间
+      const stepStartTime = Date.now();
+      const stepStartTimeStr = new Date(stepStartTime).toLocaleTimeString('zh-CN', { hour12: false, hour: '2-digit', minute: '2-digit', second: '2-digit', fractionalSecondDigits: 3 });
+      console.log(`${stepPrefix}[${stepStartTimeStr}] 步骤 ${i + 1} 开始执行: ${action.type}`);
+
       // 执行操作
       // 执行操作
       const result = await executeAction(action, device, folderPath, resolution);
       const result = await executeAction(action, device, folderPath, resolution);
 
 
+      // 记录步骤结束时间
+      const stepEndTime = Date.now();
+      const stepEndTimeStr = new Date(stepEndTime).toLocaleTimeString('zh-CN', { hour12: false, hour: '2-digit', minute: '2-digit', second: '2-digit', fractionalSecondDigits: 3 });
+      const stepDuration = stepEndTime - stepStartTime;
+      console.log(`${stepPrefix}[${stepEndTimeStr}] 步骤 ${i + 1} 执行完成: ${action.type}, 耗时: ${stepDuration}ms (${(stepDuration / 1000).toFixed(2)}秒)`);
+
       if (!result.success) {
       if (!result.success) {
         console.error(`${stepPrefix}步骤 ${i + 1} 执行失败:`, result.error);
         console.error(`${stepPrefix}步骤 ${i + 1} 执行失败:`, result.error);
         return { success: false, error: result.error, completedSteps: i };
         return { success: false, error: result.error, completedSteps: i };

+ 0 - 74
static/processing/微信聊天自动发送工作流/history/chat_2026-01-14T13-18-10.json

@@ -1,74 +0,0 @@
-{
-  "timestamp": "2026-01-14T13:18:10.103Z",
-  "messageCount": 17,
-  "messages": [
-    {
-      "sender": "friend",
-      "text": "Mikey"
-    },
-    {
-      "sender": "me",
-      "text": "收到啦,有空再聊哦"
-    },
-    {
-      "sender": "friend",
-      "text": "请把对方的原话发过来,或描述核"
-    },
-    {
-      "sender": "friend",
-      "text": "心意思,我再给你一条不超过20"
-    },
-    {
-      "sender": "friend",
-      "text": "字的回复。先给你几个快速选项,"
-    },
-    {
-      "sender": "friend",
-      "text": "直接可用:"
-    },
-    {
-      "sender": "friend",
-      "text": "- 收到啦,啥时候聊?"
-    },
-    {
-      "sender": "friend",
-      "text": "-没事,最近怎么样?"
-    },
-    {
-      "sender": "friend",
-      "text": "-可以的,咱们约时间!"
-    },
-    {
-      "sender": "friend",
-      "text": "-有空再聊哈。"
-    },
-    {
-      "sender": "friend",
-      "text": "你好"
-    },
-    {
-      "sender": "me",
-      "text": "你好"
-    },
-    {
-      "sender": "friend",
-      "text": "你经常玩 soul吗?"
-    },
-    {
-      "sender": "me",
-      "text": "还好,我都不怎么上了"
-    },
-    {
-      "sender": "me",
-      "text": "你呢"
-    },
-    {
-      "sender": "friend",
-      "text": "我也不怎么上,上周才注册的"
-    },
-    {
-      "sender": "me",
-      "text": "三"
-    }
-  ]
-}

+ 0 - 54
static/processing/微信聊天自动发送工作流/history/chat_2026-01-14T13-19-11.json

@@ -1,54 +0,0 @@
-{
-  "timestamp": "2026-01-14T13:19:11.606Z",
-  "messageCount": 12,
-  "messages": [
-    {
-      "sender": "me",
-      "text": "241 5522"
-    },
-    {
-      "sender": "me",
-      "text": "Mikey ●··"
-    },
-    {
-      "sender": "friend",
-      "text": "你好"
-    },
-    {
-      "sender": "me",
-      "text": "你好"
-    },
-    {
-      "sender": "friend",
-      "text": "你经常玩soul吗?"
-    },
-    {
-      "sender": "me",
-      "text": "还好,我都不怎么上了"
-    },
-    {
-      "sender": "me",
-      "text": "你呢"
-    },
-    {
-      "sender": "friend",
-      "text": "我也不怎么上,上周才注册的"
-    },
-    {
-      "sender": "friend",
-      "text": ")("
-    },
-    {
-      "sender": "me",
-      "text": "区"
-    },
-    {
-      "sender": "me",
-      "text": "中 符 英"
-    },
-    {
-      "sender": "me",
-      "text": "三"
-    }
-  ]
-}

+ 0 - 54
static/processing/微信聊天自动发送工作流/history/chat_2026-01-14T13-20-39.json

@@ -1,54 +0,0 @@
-{
-  "timestamp": "2026-01-14T13:20:39.782Z",
-  "messageCount": 12,
-  "messages": [
-    {
-      "sender": "me",
-      "text": "K18 52"
-    },
-    {
-      "sender": "friend",
-      "text": "く ··· Mikey"
-    },
-    {
-      "sender": "me",
-      "text": "你好"
-    },
-    {
-      "sender": "friend",
-      "text": "你经常玩 soul吗?"
-    },
-    {
-      "sender": "me",
-      "text": "还好,我都不怎么上了"
-    },
-    {
-      "sender": "me",
-      "text": "你呢"
-    },
-    {
-      "sender": "friend",
-      "text": "我也不怎么上,上周才注册的"
-    },
-    {
-      "sender": "friend",
-      "text": "哈哈,你也是新手?周末一起去看"
-    },
-    {
-      "sender": "friend",
-      "text": "看新鲜事?"
-    },
-    {
-      "sender": "me",
-      "text": "区"
-    },
-    {
-      "sender": "me",
-      "text": "中 符 英"
-    },
-    {
-      "sender": "me",
-      "text": "三"
-    }
-  ]
-}

+ 0 - 54
static/processing/微信聊天自动发送工作流/history/chat_2026-01-14T13-22-08.json

@@ -1,54 +0,0 @@
-{
-  "timestamp": "2026-01-14T13:22:08.933Z",
-  "messageCount": 12,
-  "messages": [
-    {
-      "sender": "friend",
-      "text": "Mikey"
-    },
-    {
-      "sender": "me",
-      "text": "你呢"
-    },
-    {
-      "sender": "friend",
-      "text": "我也不怎么上,上周才注册的"
-    },
-    {
-      "sender": "friend",
-      "text": "哈哈,你也是新手?周末一起去看"
-    },
-    {
-      "sender": "friend",
-      "text": "看新鲜事?"
-    },
-    {
-      "sender": "friend",
-      "text": "周末?去看啥?"
-    },
-    {
-      "sender": "friend",
-      "text": "周末一起去看新鲜事?我负责带好"
-    },
-    {
-      "sender": "friend",
-      "text": "奇心。"
-    },
-    {
-      "sender": "me",
-      "text": "(+"
-    },
-    {
-      "sender": "me",
-      "text": "区"
-    },
-    {
-      "sender": "me",
-      "text": "中 符 英"
-    },
-    {
-      "sender": "me",
-      "text": "三"
-    }
-  ]
-}

+ 0 - 5
static/processing/微信聊天自动发送工作流/history/chat_2026-01-14T17-18-22.json

@@ -1,5 +0,0 @@
-{
-  "timestamp": "2026-01-14T17:18:22.185Z",
-  "messageCount": 0,
-  "messages": []
-}

+ 0 - 5
static/processing/微信聊天自动发送工作流/history/chat_2026-01-14T17-25-28.json

@@ -1,5 +0,0 @@
-{
-  "timestamp": "2026-01-14T17:25:28.147Z",
-  "messageCount": 0,
-  "messages": []
-}

+ 0 - 5
static/processing/微信聊天自动发送工作流/history/chat_2026-01-14T17-31-49.json

@@ -1,5 +0,0 @@
-{
-  "timestamp": "2026-01-14T17:31:49.092Z",
-  "messageCount": 0,
-  "messages": []
-}

+ 0 - 5
static/processing/微信聊天自动发送工作流/history/chat_2026-01-14T17-33-19.json

@@ -1,5 +0,0 @@
-{
-  "timestamp": "2026-01-14T17:33:19.155Z",
-  "messageCount": 0,
-  "messages": []
-}

+ 0 - 5
static/processing/微信聊天自动发送工作流/history/chat_2026-01-14T17-34-48.json

@@ -1,5 +0,0 @@
-{
-  "timestamp": "2026-01-14T17:34:48.824Z",
-  "messageCount": 0,
-  "messages": []
-}

+ 5 - 0
static/processing/微信聊天自动发送工作流/history/chat_2026-01-14T19-31-21.json

@@ -0,0 +1,5 @@
+{
+  "timestamp": "2026-01-14T19:31:21.167Z",
+  "messageCount": 0,
+  "messages": []
+}

+ 5 - 0
static/processing/微信聊天自动发送工作流/history/chat_2026-01-14T19-52-19.json

@@ -0,0 +1,5 @@
+{
+  "timestamp": "2026-01-14T19:52:19.692Z",
+  "messageCount": 0,
+  "messages": []
+}

+ 5 - 0
static/processing/微信聊天自动发送工作流/history/chat_2026-01-14T19-53-48.json

@@ -0,0 +1,5 @@
+{
+  "timestamp": "2026-01-14T19:53:48.692Z",
+  "messageCount": 0,
+  "messages": []
+}

+ 5 - 0
static/processing/微信聊天自动发送工作流/history/chat_2026-01-14T19-59-33.json

@@ -0,0 +1,5 @@
+{
+  "timestamp": "2026-01-14T19:59:33.371Z",
+  "messageCount": 0,
+  "messages": []
+}

+ 5 - 0
static/processing/微信聊天自动发送工作流/history/chat_2026-01-14T20-02-07.json

@@ -0,0 +1,5 @@
+{
+  "timestamp": "2026-01-14T20:02:07.382Z",
+  "messageCount": 0,
+  "messages": []
+}

+ 5 - 0
static/processing/微信聊天自动发送工作流/history/chat_2026-01-14T20-12-55.json

@@ -0,0 +1,5 @@
+{
+  "timestamp": "2026-01-14T20:12:55.593Z",
+  "messageCount": 0,
+  "messages": []
+}

+ 5 - 0
static/processing/微信聊天自动发送工作流/history/chat_2026-01-14T20-21-28.json

@@ -0,0 +1,5 @@
+{
+  "timestamp": "2026-01-14T20:21:28.411Z",
+  "messageCount": 0,
+  "messages": []
+}

+ 5 - 0
static/processing/微信聊天自动发送工作流/history/chat_2026-01-14T20-23-06.json

@@ -0,0 +1,5 @@
+{
+  "timestamp": "2026-01-14T20:23:06.849Z",
+  "messageCount": 0,
+  "messages": []
+}

+ 5 - 0
static/processing/微信聊天自动发送工作流/history/chat_2026-01-14T20-32-04.json

@@ -0,0 +1,5 @@
+{
+  "timestamp": "2026-01-14T20:32:04.322Z",
+  "messageCount": 0,
+  "messages": []
+}

+ 1 - 1
static/processing/微信聊天自动发送工作流/history/summary.txt

@@ -1 +1 @@
-两人最近才注册Soul,周末约定一起浏览新鲜事,由对方带路,氛围轻松,夹杂好奇与玩笑
+以日常问候与近况更新为主,互问午饭、在家与否、是否在想对方;氛围轻松随意,带有调侃与亲密感

+ 14 - 45
static/processing/微信聊天自动发送工作流/processing.json

@@ -5,37 +5,14 @@
 	"variables": {
 	"variables": {
 		"lastMessage": "",
 		"lastMessage": "",
 		"currentMessage": "",
 		"currentMessage": "",
-		"chatHistory": "",
-		"historySummary": "",
-		"reply": ""
-	},
-	"chatHistoryConfig": {
-		"friendAvatar": "好友头像.png",
-		"myAvatar": "我的头像.png"
+		"reply": "",
+		"sendPos": ""
 	},
 	},
 	"actions": [
 	"actions": [
 		{
 		{
 			"type": "while",
 			"type": "while",
 			"condition": "true",
 			"condition": "true",
 			"body": [
 			"body": [
-				{
-					"type": "extract-chat-history",
-					"friendAvatar": "好友头像.png",
-					"myAvatar": "我的头像.png",
-					"variable": "chatHistory",
-					"delay": "2s"
-				},
-				{
-					"type": "save-chat-history",
-					"variable": "chatHistory",
-					"delay": "0.5s"
-				},
-				{
-					"type": "generate-history-summary",
-					"variable": "chatHistory",
-					"summaryVariable": "historySummary",
-					"delay": "3s"
-				},
 				{
 				{
 					"type": "ocr",
 					"type": "ocr",
 					"method": "full-screen",
 					"method": "full-screen",
@@ -48,36 +25,28 @@
 					"then": [
 					"then": [
 						{
 						{
 							"type": "ai-generate",
 							"type": "ai-generate",
-							"prompt": "你是一个刚认识女方不久的男生,正在和女方通过微信聊天。你的目标是:通过自然、有趣的对话让女方对你产生好感,建立良好的第一印象。\n\n历史聊天总结(帮助你了解之前的对话内容和氛围):\n{historySummary}\n\n当前聊天记录:\n{chatHistory}\n\n女方最新发来的消息:\"{currentMessage}\"\n\n请根据以上信息,代入我的角色,生成一条自然、有趣的回复。要求:\n1. 完全代入刚认识女方不久的男生角色,用轻松、有趣、略带暧昧的口吻回复;\n2. 回复要自然流畅,像真实聊天一样,不要过于刻意或油腻;\n3. 可以适当展现幽默感、关心或好奇心,让对话更有趣;\n4. 如果识别的内容不清楚或包含无关文字,请根据核心意思理解并回复;\n5. 回复长度控制在20字以内;\n6. 回复要符合聊天记录的语境和风格,参考历史总结了解之前的对话氛围;\n7. 目标是让女方对你产生好感,但不要过于直接或冒进。\n\n请严格按照以下JSON格式返回,不要包含任何其他文字:\n{\n  \"reply\": \"你的回复内容\"\n}",
+							"prompt": "你是一个刚认识女方不久的男生,正在和女方通过微信聊天。你的目标是:通过自然、有趣的对话让女方对你产生好感,建立良好的第一印象。\n\n女方最新发来的消息:\"{currentMessage}\"\n\n请根据以上信息,代入我的角色,生成一条自然、有趣的回复。要求:\n1. 完全代入刚认识女方不久的男生角色,用轻松、有趣、略带暧昧的口吻回复;\n2. 回复要自然流畅,像真实聊天一样,不要过于刻意或油腻;\n3. 可以适当展现幽默感、关心或好奇心,让对话更有趣;\n4. 如果识别的内容不清楚或包含无关文字,请根据核心意思理解并回复;\n5. 回复长度控制在20字以内;\n6. 目标是让女方对你产生好感,但不要过于直接或冒进。\n\n请严格按照以下JSON格式返回,不要包含任何其他文字:\n{\n  \"reply\": \"你的回复内容\"\n}",
 							"variable": "reply",
 							"variable": "reply",
 							"delay": "5s"
 							"delay": "5s"
 						},
 						},
-						{
-							"type": "locate",
-							"method": "image",
-							"target": "微信聊天界面的输入框定位图.png",
-							"variable": "inputPos",
-							"delay": "0.5s"
-						},
-						{
-							"type": "click",
-							"method": "position",
-							"target": "{inputPos}",
-							"delay": "0.3s"
-						},
 						{
 						{
 							"type": "input",
 							"type": "input",
 							"target": "输入框",
 							"target": "输入框",
 							"value": "{reply}",
 							"value": "{reply}",
-							"clear": true,
 							"delay": "0.5s"
 							"delay": "0.5s"
 						},
 						},
 						{
 						{
-							"type": "locate",
-							"method": "image",
-							"target": "微信聊天界面的发送按钮定位图.png",
-							"variable": "sendPos",
-							"delay": "0.5s"
+							"type": "if",
+							"condition": "{sendPos} == \"\" || {sendPos} == undefined",
+							"then": [
+								{
+									"type": "locate",
+									"method": "image",
+									"target": "微信聊天界面的发送按钮定位图.png",
+									"variable": "sendPos",
+									"delay": "0.5s"
+								}
+							]
 						},
 						},
 						{
 						{
 							"type": "click",
 							"type": "click",

BIN
static/processing/微信聊天自动发送工作流/tmp/2026-01-14_11-54-19/screenshot.png


BIN
static/processing/微信聊天自动发送工作流/tmp/2026-01-14_12-02-33/screenshot.png


BIN
static/processing/微信聊天自动发送工作流/tmp/2026-01-14_12-10-25/screenshot.png


BIN
static/processing/微信聊天自动发送工作流/tmp/2026-01-14_12-33-59/screenshot.png


BIN
static/processing/微信聊天自动发送工作流/tmp/2026-01-14_12-34-07/screenshot_ocr.png


BIN
static/processing/微信聊天自动发送工作流/tmp/2026-01-14_12-35-15/screenshot.png


BIN
static/processing/微信聊天自动发送工作流/tmp/2026-01-14_12-35-43/screenshot_ocr.png


BIN
static/processing/微信聊天自动发送工作流/tmp/2026-01-14_12-42-01/screenshot.png


BIN
static/processing/微信聊天自动发送工作流/tmp/2026-01-14_12-42-09/screenshot_ocr.png


BIN
static/processing/微信聊天自动发送工作流/tmp/2026-01-14_12-43-13/screenshot.png


BIN
static/processing/微信聊天自动发送工作流/tmp/2026-01-14_13-20-34/screenshot.png


BIN
static/processing/微信聊天自动发送工作流/tmp/2026-01-14_18-44-53/screenshot.png


BIN
static/processing/微信聊天自动发送工作流/tmp/2026-01-14_19-20-03/screenshot.png


BIN
static/processing/微信聊天自动发送工作流/tmp/2026-01-14_19-20-34/screenshot_ocr.png


BIN
temp_screenshot.png