豆包识别验证码加拖动验证码示例

380

主题

193

回帖

2397

积分

管理员

积分
2397
豆包识别验证码加拖动验证码示例

1.png

2.png

3.png

4.png

  1. // AIWROK 自动化流程:全屏截图 → 启动豆包 → 发送截图 → 等待AI回答 → 采集回答内容 → 保存到文件
  2. // 全程使用 agent.getXml() 获取界面源码
  3. // 包名:com.larus.nova(豆包)
  4. //
  5. // 使用说明:
  6. //   1. 在需要截图的页面运行脚本
  7. //   2. 脚本会自动截图并发送给豆包分析
  8. //   3. 采集结果保存到 /sdcard/豆包截图分析.json

  9. print.log("===== 豆包截图发送流程启动 =====");
  10. print.time();

  11. // ========== 配置区 ==========
  12. var 豆包包名 = "com.larus.nova";
  13. var 截图保存路径 = "/sdcard/screenshot.png";

  14. // 发送后等待AI回答的最大秒数(整体超时)
  15. var 等待回答超时秒 = 8;

  16. // 检测到新回答出现后,再等待多少秒让回答输出完整
  17. var 回答输出等待秒 = 10;

  18. // 验证码滑块拖动校准系数(根据实际效果调整,默认1.0)
  19. // 如果拖动距离偏大,调小此值(如0.95);如果偏小,调大此值(如1.05)
  20. var 滑块校准系数 = 1.0;

  21. // ========== 获取设备信息 ==========
  22. var 屏幕宽 = screen.getScreenWidth();
  23. var 屏幕高 = screen.getScreenHeight();
  24. var 验证码滑块距离 = null;
  25. print.log("屏幕尺寸:" + 屏幕宽 + " x " + 屏幕高);
  26. print.log("代理状态:" + (agent.isOpen() ? "已开启" : "未开启"));

  27. // ========== 工具函数 ==========

  28. function 获取UI() {
  29.     var xml = agent.getXml();
  30.     return "" + xml;
  31. }

  32. function 字符串长度(s) {
  33.     var str = "" + s;
  34.     return str.length;
  35. }

  36. function 解码HTML实体(s) {
  37.     var str = "" + s;
  38.     str = str.replace(/
/g, "\n");
  39.     str = str.replace(/
/g, "\r");
  40.     str = str.replace(/	/g, "\t");
  41.     str = str.replace(/'/g, "'");
  42.     str = str.replace(/"/g, '"');
  43.     str = str.replace(/"/g, '"');
  44.     str = str.replace(/'/g, "'");
  45.     str = str.replace(/&/g, "&");
  46.     str = str.replace(/&lt;/g, "<");
  47.     str = str.replace(/&gt;/g, ">");
  48.     return str;
  49. }

  50. function 采集AI回答列表(xml, 严格过滤) {
  51.     if (严格过滤 === undefined) 严格过滤 = true;
  52.     var xmlStr = "" + xml;
  53.     var 回答列表 = [];

  54.     var listIdx = xmlStr.indexOf('id/message_list"');
  55.     if (listIdx === -1) {
  56.         print.log("⚠ 未找到消息列表节点");
  57.         return 回答列表;
  58.     }

  59.     var 后面 = xmlStr.substring(listIdx);
  60.     var 位置 = 0;
  61.     while (true) {
  62.         var cvIdx = 后面.indexOf('id/content_view"', 位置);
  63.         if (cvIdx === -1) break;

  64.         var 段 = 后面.substring(cvIdx);
  65.         
  66.         var cvBounds = 段.match(/bounds="\[(\d+),(\d+)\]\[(\d+),(\d+)\]"/);
  67.         var isAI = false;
  68.         if (cvBounds) {
  69.             var cvX1 = parseInt(cvBounds[1]);
  70.             if (cvX1 < 屏幕宽 / 2) {
  71.                 isAI = true;
  72.             }
  73.         }

  74.         var 标签结束 = 段.indexOf(">");
  75.         if (标签结束 === -1) break;
  76.         var 子段 = 段.substring(标签结束 + 1);

  77.         var 文本匹配 = 子段.match(/<node[^>]*?text="([^"]+)"[^>]*?class="android\.widget\.TextView"[^>]*?\/?>/);
  78.         if (!文本匹配) {
  79.             文本匹配 = 子段.match(/<node[^>]*?class="android\.widget\.TextView"[^>]*?text="([^"]+)"[^>]*?\/?>/);
  80.         }

  81.         if (文本匹配 && 文本匹配[1]) {
  82.             var 原始文本 = 文本匹配[1];
  83.             var 解码文本 = 解码HTML实体(原始文本);
  84.             if (严格过滤) {
  85.                 if (isAI && 字符串长度(解码文本) > 0) {
  86.                     回答列表.push(解码文本);
  87.                 }
  88.             } else {
  89.                 if (字符串长度(解码文本) > 0) {
  90.                     回答列表.push(解码文本);
  91.                 }
  92.             }
  93.         }

  94.         位置 = cvIdx + 30;
  95.     }

  96.     return 回答列表;
  97. }

  98. function 获取当前最后AI回答(xml) {
  99.     var 回答列表 = 采集AI回答列表(xml);
  100.     if (回答列表.length === 0) return "";
  101.     return 回答列表[回答列表.length - 1];
  102. }

  103. // 全屏截图(使用shell命令)
  104. function 全屏截图(保存路径) {
  105.     try {
  106.         var result = agent.shell("screencap -p " + 保存路径);
  107.         print.log("✓ 截图命令执行:" + result);
  108.         
  109.         var lsResult = agent.shell("ls -la " + 保存路径);
  110.         print.log("✓ 截图文件检查:" + lsResult);
  111.         
  112.         return true;
  113.     } catch (e) {
  114.         print.log("⚠ 截图失败:" + e.message);
  115.         return false;
  116.     }
  117. }

  118. // 查找豆包的加号按钮(优先右下角 action_menu_entrance)
  119. function 查找加号按钮(xml) {
  120.     var xmlStr = "" + xml;
  121.    
  122.     var menuEntranceIdx = xmlStr.indexOf('id/action_menu_entrance"');
  123.     if (menuEntranceIdx !== -1) {
  124.         var 段 = xmlStr.substring(menuEntranceIdx);
  125.         var m = 段.match(/bounds="\[(\d+),(\d+)\]\[(\d+),(\d+)\]"/);
  126.         if (m) {
  127.             return {
  128.                 x: (parseInt(m[1]) + parseInt(m[3])) / 2,
  129.                 y: (parseInt(m[2]) + parseInt(m[4])) / 2
  130.             };
  131.         }
  132.     }

  133.     var entranceIdx = xmlStr.indexOf('id/action_entrance"');
  134.     if (entranceIdx !== -1) {
  135.         var 段2 = xmlStr.substring(entranceIdx);
  136.         var m2 = 段2.match(/bounds="\[(\d+),(\d+)\]\[(\d+),(\d+)\]"/);
  137.         if (m2) {
  138.             return {
  139.                 x: (parseInt(m2[1]) + parseInt(m2[3])) / 2,
  140.                 y: (parseInt(m2[2]) + parseInt(m2[4])) / 2
  141.             };
  142.         }
  143.     }

  144.     var plusIdx = xmlStr.indexOf('text="+"');
  145.     if (plusIdx !== -1) {
  146.         var 段3 = xmlStr.substring(plusIdx);
  147.         var m3 = 段3.match(/bounds="\[(\d+),(\d+)\]\[(\d+),(\d+)\]"/);
  148.         if (m3) {
  149.             return {
  150.                 x: (parseInt(m3[1]) + parseInt(m3[3])) / 2,
  151.                 y: (parseInt(m3[2]) + parseInt(m3[4])) / 2
  152.             };
  153.         }
  154.     }

  155.     var attachIdx = xmlStr.indexOf('content-desc="附件"');
  156.     if (attachIdx === -1) {
  157.         attachIdx = xmlStr.indexOf('content-desc="添加"');
  158.     }
  159.     if (attachIdx !== -1) {
  160.         var 段4 = xmlStr.substring(attachIdx);
  161.         var m4 = 段4.match(/bounds="\[(\d+),(\d+)\]\[(\d+),(\d+)\]"/);
  162.         if (m4) {
  163.             return {
  164.                 x: (parseInt(m4[1]) + parseInt(m4[3])) / 2,
  165.                 y: (parseInt(m4[2]) + parseInt(m4[4])) / 2
  166.             };
  167.         }
  168.     }

  169.     return null;
  170. }

  171. function 查找输入框中心(xml) {
  172.     var xmlStr = "" + xml;
  173.     var idx = xmlStr.indexOf('id/input_text"');
  174.     if (idx === -1) return null;

  175.     var 段 = xmlStr.substring(idx);
  176.     var m = 段.match(/bounds="\[(\d+),(\d+)\]\[(\d+),(\d+)\]"/);
  177.     if (!m) return null;

  178.     var x1 = parseInt(m[1]);
  179.     var y1 = parseInt(m[2]);
  180.     var x2 = parseInt(m[3]);
  181.     var y2 = parseInt(m[4]);
  182.     return {
  183.         x: (x1 + x2) / 2,
  184.         y: (y1 + y2) / 2
  185.     };
  186. }

  187. function 粘贴文本(文本) {
  188.     try {
  189.         Clipboard.copy("" + 文本);
  190.     } catch (e) {
  191.         print.log("⚠ Clipboard.copy 失败:" + e.message);
  192.     }
  193.     sleep.millisecond(毫秒 = 300);

  194.     try {
  195.         agent.shell("service call clipboard 3 i32 1 s16 '" + 文本 + "' i32 0");
  196.     } catch (e2) {
  197.         // 忽略错误
  198.     }
  199.     sleep.millisecond(毫秒 = 300);

  200.     agent.shell("input keyevent 279");
  201.     sleep.second(秒 = 1);
  202.     print.log("✓ 已粘贴文本:" + 文本);
  203. }

  204. function 是否已进入相机页面(xml) {
  205.     var xmlStr = "" + xml;
  206.     return xmlStr.indexOf('id/focus_container"') !== -1 && xmlStr.indexOf('id/suggest_action_bar"') === -1;
  207. }

  208. function 是否已进入图片预览页面(xml) {
  209.     var xmlStr = "" + xml;
  210.     return xmlStr.indexOf('id/focus_container"') !== -1 && xmlStr.indexOf('id/suggest_action_bar"') !== -1;
  211. }

  212. function 是否已进入图片选择列表页面(xml) {
  213.     var xmlStr = "" + xml;
  214.     return xmlStr.indexOf('id/media_viewpager"') !== -1 || xmlStr.indexOf('id/media_list"') !== -1;
  215. }

  216. function 查找相册选项(xml) {
  217.     var xmlStr = "" + xml;
  218.    
  219.     if (是否已进入图片预览页面(xml)) {
  220.         return { x: -1, y: -1, 已进入预览页: true };
  221.     }
  222.    
  223.     if (是否已进入图片选择列表页面(xml)) {
  224.         return { x: -1, y: -1, 已进入选择页: true };
  225.     }
  226.    
  227.     var albumIdx = xmlStr.indexOf('text="相册"');
  228.     if (albumIdx === -1) {
  229.         albumIdx = xmlStr.indexOf('text="图片"');
  230.     }
  231.     if (albumIdx === -1) {
  232.         albumIdx = xmlStr.indexOf('text="照片"');
  233.     }
  234.     if (albumIdx === -1) {
  235.         albumIdx = xmlStr.indexOf('text="所有照片"');
  236.     }
  237.     if (albumIdx === -1) {
  238.         albumIdx = xmlStr.indexOf('text="从相册选择"');
  239.     }
  240.     if (albumIdx === -1) {
  241.         albumIdx = xmlStr.indexOf('text="选择图片"');
  242.     }
  243.     if (albumIdx !== -1) {
  244.         var 段 = xmlStr.substring(albumIdx);
  245.         var m = 段.match(/bounds="\[(\d+),(\d+)\]\[(\d+),(\d+)\]"/);
  246.         if (m) {
  247.             return {
  248.                 x: (parseInt(m[1]) + parseInt(m[3])) / 2,
  249.                 y: (parseInt(m[2]) + parseInt(m[4])) / 2
  250.             };
  251.         }
  252.     }

  253.     var albumIconIdx = xmlStr.indexOf('content-desc="相册"');
  254.     if (albumIconIdx === -1) {
  255.         albumIconIdx = xmlStr.indexOf('content-desc="图片"');
  256.     }
  257.     if (albumIconIdx !== -1) {
  258.         var 段2 = xmlStr.substring(albumIconIdx);
  259.         var m2 = 段2.match(/bounds="\[(\d+),(\d+)\]\[(\d+),(\d+)\]"/);
  260.         if (m2) {
  261.             return {
  262.                 x: (parseInt(m2[1]) + parseInt(m2[3])) / 2,
  263.                 y: (parseInt(m2[2]) + parseInt(m2[4])) / 2
  264.             };
  265.         }
  266.     }

  267.     return null;
  268. }

  269. // 查找图片选择器中的第一张图片(刚截的图)
  270. function 查找第一张图片(xml) {
  271.     var xmlStr = "" + xml;
  272.    
  273.     var thumbnailIdx = xmlStr.indexOf('id/iv_thumbnail"');
  274.     if (thumbnailIdx !== -1) {
  275.         var 段 = xmlStr.substring(thumbnailIdx);
  276.         var m = 段.match(/bounds="\[(\d+),(\d+)\]\[(\d+),(\d+)\]"/);
  277.         if (m) {
  278.             return {
  279.                 x: (parseInt(m[1]) + parseInt(m[3])) / 2,
  280.                 y: (parseInt(m[2]) + parseInt(m[4])) / 2
  281.             };
  282.         }
  283.     }

  284.     var imageIdx = xmlStr.indexOf('class="android.widget.ImageView"');
  285.     if (imageIdx !== -1) {
  286.         var 段2 = xmlStr.substring(imageIdx);
  287.         var m2 = 段2.match(/bounds="\[(\d+),(\d+)\]\[(\d+),(\d+)\]"/);
  288.         if (m2) {
  289.             var x = (parseInt(m2[1]) + parseInt(m2[3])) / 2;
  290.             var y = (parseInt(m2[2]) + parseInt(m2[4])) / 2;
  291.             if (y > 400) {
  292.                 return { x: x, y: y };
  293.             }
  294.         }
  295.     }

  296.     return null;
  297. }

  298. // 查找发送按钮
  299. function 查找发送按钮中心(xml) {
  300.     var xmlStr = "" + xml;

  301.     var sendTextIdx = xmlStr.indexOf('text="发送"');
  302.     if (sendTextIdx !== -1) {
  303.         var 段 = xmlStr.substring(sendTextIdx);
  304.         var m = 段.match(/bounds="\[(\d+),(\d+)\]\[(\d+),(\d+)\]"/);
  305.         if (m) {
  306.             return {
  307.                 x: (parseInt(m[1]) + parseInt(m[3])) / 2,
  308.                 y: (parseInt(m[2]) + parseInt(m[4])) / 2
  309.             };
  310.         }
  311.     }

  312.     var sendIdIdx = xmlStr.indexOf('id/action_send"');
  313.     if (sendIdIdx !== -1) {
  314.         var 段2 = xmlStr.substring(sendIdIdx);
  315.         var m2 = 段2.match(/bounds="\[(\d+),(\d+)\]\[(\d+),(\d+)\]"/);
  316.         if (m2) {
  317.             return {
  318.                 x: (parseInt(m2[1]) + parseInt(m2[3])) / 2,
  319.                 y: (parseInt(m2[2]) + parseInt(m2[4])) / 2
  320.             };
  321.         }
  322.     }

  323.     var rightIconIdx = xmlStr.indexOf('id/right_icon"');
  324.     if (rightIconIdx !== -1) {
  325.         var 段3 = xmlStr.substring(rightIconIdx);
  326.         var m3 = 段3.match(/bounds="\[(\d+),(\d+)\]\[(\d+),(\d+)\]"/);
  327.         if (m3) {
  328.             var y = (parseInt(m3[2]) + parseInt(m3[4])) / 2;
  329.             if (y > 3000) {
  330.                 return {
  331.                     x: (parseInt(m3[1]) + parseInt(m3[3])) / 2,
  332.                     y: y
  333.                 };
  334.             }
  335.         }
  336.     }

  337.     return null;
  338. }

  339. function 查找并点击展开按钮(xml) {
  340.     var xmlStr = "" + xml;
  341.    
  342.     var expandIdx = xmlStr.indexOf('content-desc="展开"');
  343.     if (expandIdx === -1) {
  344.         expandIdx = xmlStr.indexOf('content-desc="更多"');
  345.     }
  346.     if (expandIdx === -1) {
  347.         expandIdx = xmlStr.indexOf('content-desc="收起"');
  348.     }
  349.    
  350.     if (expandIdx !== -1) {
  351.         var 段 = xmlStr.substring(expandIdx);
  352.         var m = 段.match(/bounds="\[(\d+),(\d+)\]\[(\d+),(\d+)\]"/);
  353.         if (m) {
  354.             var x = (parseInt(m[1]) + parseInt(m[3])) / 2;
  355.             var y = (parseInt(m[2]) + parseInt(m[4])) / 2;
  356.             agent.click(x, y);
  357.             print.log("✓ 已点击展开按钮(content-desc),坐标(" + Math.round(x) + "," + Math.round(y) + ")");
  358.             sleep.second(秒 = 1);
  359.             return true;
  360.         }
  361.     }

  362.     var textExpandIdx = xmlStr.indexOf('text="展开"');
  363.     if (textExpandIdx === -1) {
  364.         textExpandIdx = xmlStr.indexOf('text="更多"');
  365.     }
  366.     if (textExpandIdx !== -1) {
  367.         var 段2 = xmlStr.substring(textExpandIdx);
  368.         var m2 = 段2.match(/bounds="\[(\d+),(\d+)\]\[(\d+),(\d+)\]"/);
  369.         if (m2) {
  370.             var x2 = (parseInt(m2[1]) + parseInt(m2[3])) / 2;
  371.             var y2 = (parseInt(m2[2]) + parseInt(m2[4])) / 2;
  372.             agent.click(x2, y2);
  373.             print.log("✓ 已点击展开按钮(文本匹配),坐标(" + Math.round(x2) + "," + Math.round(y2) + ")");
  374.             sleep.second(秒 = 1);
  375.             return true;
  376.         }
  377.     }

  378.     return false;
  379. }

  380. function 等待AI回答完成(发送前的最后文本) {
  381.     var 已耗时 = 0;
  382.     var 检查间隔秒 = 1;
  383.     var 发送前回答数量 = 0;

  384.     var xml = 获取UI();
  385.     var 初始列表 = 采集AI回答列表(xml, false);
  386.     发送前回答数量 = 初始列表.length;
  387.     print.log("发送前AI回答数量:" + 发送前回答数量);

  388.     while (已耗时 < 等待回答超时秒) {
  389.         sleep.second(秒 = 检查间隔秒);
  390.         已耗时 += 检查间隔秒;

  391.         xml = 获取UI();

  392.         var 回答列表 = 采集AI回答列表(xml, false);
  393.         
  394.         if (回答列表.length > 发送前回答数量) {
  395.             print.log("✓ 检测到新回答(" + 已耗时 + "秒),数量从" + 发送前回答数量 + "增加到" + 回答列表.length);
  396.             sleep.second(秒 = 3);
  397.             
  398.             xml = 获取UI();
  399.             var 最终列表 = 采集AI回答列表(xml, false);
  400.             if (最终列表.length > 0) {
  401.                 var 最终文本 = 最终列表[最终列表.length - 1];
  402.                 print.log("✓ 采集成功,返回结果:" + 最终文本);
  403.                 return 最终文本;
  404.             }
  405.         }
  406.     }

  407.     print.log("⚠ 等待AI回答超时(" + 等待回答超时秒 + "秒),尝试返回当前内容");
  408.     xml = 获取UI();
  409.     var 兜底列表 = 采集AI回答列表(xml, false);
  410.     if (兜底列表.length > 0) {
  411.         var 兜底文本 = 兜底列表[兜底列表.length - 1];
  412.         print.log("✓ 超时兜底:返回当前采集到的回答:" + 兜底文本);
  413.         return 兜底文本;
  414.     }
  415.     return null;
  416. }

  417. function 格式化对话(对话列表) {
  418.     var 数据 = {
  419.         "采集时间": new Date().toString(),
  420.         "对话轮数": 对话列表.length,
  421.         "对话记录": []
  422.     };
  423.    
  424.     for (var i = 0; i < 对话列表.length; i++) {
  425.         数据.对话记录.push({
  426.             "序号": i + 1,
  427.             "角色": 对话列表[i].角色,
  428.             "内容": 对话列表[i].内容
  429.         });
  430.     }
  431.    
  432.     return JSON.stringify(数据, null, 2);
  433. }

  434. function 写入文件(文件路径, 内容) {
  435.     try {
  436.         var str = "" + 内容;
  437.         var fos = new java.io.FileOutputStream(文件路径);
  438.         fos.write(str.getBytes("UTF-8"));
  439.         fos.close();
  440.         print.log("✓ 已写入文件(JSON格式):" + 文件路径);
  441.         
  442.         var catResult = agent.shell("cat " + 文件路径 + " | head -2");
  443.         print.log("✓ cat验证结果:" + catResult);
  444.         
  445.         return true;
  446.     } catch (e) {
  447.         print.log("⚠ JSON写入异常:" + e.message);
  448.     }

  449.     print.log("✗ 写入文件失败:" + 文件路径);
  450.     return false;
  451. }

  452. function 主流程() {
  453.     // 步骤1:全屏截图
  454.     print.log("\n========== 步骤1:全屏截图 ==========");
  455.     var 截图成功 = 全屏截图(截图保存路径);
  456.     if (!截图成功) {
  457.         print.log("✗ 截图失败,退出流程");
  458.         print.log("===== 豆包截图发送流程结束 =====");
  459.         return;
  460.     }

  461.     // 步骤2:启动豆包APP
  462.     print.log("\n========== 步骤2:启动豆包APP ==========");
  463.     try {
  464.         app.openApp(豆包包名);
  465.         print.log("✓ 已启动豆包");
  466.     } catch (e) {
  467.         print.log("⚠ 启动失败:" + e.message);
  468.     }
  469.     sleep.second(秒 = 5);

  470.     // 步骤3:确认进入对话页面
  471.     print.log("\n========== 步骤3:确认进入对话页面 ==========");
  472.     var xml = 获取UI();
  473.     if (xml.indexOf("message_list") === -1) {
  474.         print.log("⚠ 当前页面可能不是豆包对话页,再次等待");
  475.         sleep.second(秒 = 3);
  476.         xml = 获取UI();
  477.     }

  478.     if (xml.indexOf("message_list") !== -1) {
  479.         print.log("✓ 已进入豆包对话页面");
  480.     } else {
  481.         print.log("⚠ 未检测到消息列表");
  482.     }

  483.     // 步骤4:记录发送前的最后一条AI回答(作为检测基线)
  484.     var 发送前最后文本 = 获取当前最后AI回答(xml);

  485.     // 步骤5:点击加号按钮打开附件菜单
  486.     print.log("\n========== 步骤5:打开附件菜单 ==========");
  487.     var 加号按钮 = 查找加号按钮(xml);
  488.     if (加号按钮) {
  489.         agent.click(加号按钮.x, 加号按钮.y);
  490.         print.log("✓ 已点击action_entrance按钮,坐标(" + Math.round(加号按钮.x) + "," + Math.round(加号按钮.y) + ")");
  491.     } else {
  492.         print.log("⚠ 未找到加号按钮,尝试点击输入框左侧区域");
  493.         var inputIdx = xml.indexOf('id/speak_area"');
  494.         if (inputIdx !== -1) {
  495.             var 段 = xml.substring(inputIdx);
  496.             var m = 段.match(/bounds="\[(\d+),(\d+)\]\[(\d+),(\d+)\]"/);
  497.             if (m) {
  498.                 var speakLeft = parseInt(m[1]);
  499.                 var speakY = (parseInt(m[2]) + parseInt(m[4])) / 2;
  500.                 agent.click(speakLeft - 50, speakY);
  501.                 print.log("✓ 已点击输入框左侧区域");
  502.             }
  503.         }
  504.     }
  505.     sleep.second(秒 = 2);

  506.     // 步骤6:等待页面跳转并处理图片选择
  507.     print.log("\n========== 步骤6:处理图片选择页面 ==========");
  508.     var 当前页面状态 = "未知";
  509.     var 尝试次数 = 0;
  510.     while (当前页面状态 === "未知" && 尝试次数 < 5) {
  511.         sleep.second(秒 = 2);
  512.         xml = 获取UI();
  513.         
  514.         if (是否已进入图片预览页面(xml)) {
  515.             当前页面状态 = "预览页";
  516.             print.log("✓ 已进入图片预览页面");
  517.         } else if (是否已进入图片选择列表页面(xml)) {
  518.             当前页面状态 = "选择列表";
  519.             print.log("✓ 已进入图片选择列表页面");
  520.         } else if (是否已进入相机页面(xml)) {
  521.             print.log("✓ 已进入相机页面,点击左下角图片缩略图进入相册");
  522.             agent.click(屏幕宽 * 0.15, 屏幕高 * 0.95);
  523.             print.log("✓ 已点击左下角图片缩略图");
  524.             continue;
  525.         } else {
  526.             var 相册选项 = 查找相册选项(xml);
  527.             if (相册选项 && !相册选项.已进入预览页 && !相册选项.已进入选择页) {
  528.                 print.log("✓ 找到相册选项,准备点击");
  529.                 agent.click(相册选项.x, 相册选项.y);
  530.                 print.log("✓ 已点击相册选项,坐标(" + Math.round(相册选项.x) + "," + Math.round(相册选项.y) + ")");
  531.                 continue;
  532.             }
  533.         }
  534.         尝试次数++;
  535.     }
  536.    
  537.     if (当前页面状态 === "选择列表") {
  538.         var 第一张图片 = 查找第一张图片(xml);
  539.         if (第一张图片) {
  540.             agent.click(第一张图片.x, 第一张图片.y);
  541.             print.log("✓ 已选择第一张图片,坐标(" + Math.round(第一张图片.x) + "," + Math.round(第一张图片.y) + ")");
  542.             sleep.second(秒 = 2);
  543.             
  544.             xml = 获取UI();
  545.             if (是否已进入图片预览页面(xml)) {
  546.                 当前页面状态 = "预览页";
  547.                 print.log("✓ 已进入图片预览页面");
  548.             }
  549.         }
  550.     }

  551.     // 步骤7:粘贴文字到输入框(选择图片后马上粘贴)
  552.     print.log("\n========== 步骤7:粘贴文字询问拖动距离坐标 ==========");
  553.     xml = 获取UI();
  554.     var 输入框 = 查找输入框中心(xml);
  555.     if (输入框) {
  556.         agent.click(输入框.x, 输入框.y);
  557.         sleep.second(秒 = 1);
  558.         粘贴文本("请告诉我验证码滑块需要拖动的距离坐标,只输出坐标数字,不要其他文字");
  559.     } else {
  560.         print.log("⚠ 未找到输入框");
  561.     }
  562.     sleep.second(秒 = 2);

  563.     // 步骤8:发送图片和文字
  564.     print.log("\n========== 步骤8:发送图片和文字 ==========");
  565.     if (当前页面状态 === "预览页") {
  566.         var confirmX = 屏幕宽 * 0.5;
  567.         var confirmY = 屏幕高 * 0.92;
  568.         agent.click(confirmX, confirmY);
  569.         print.log("✓ 已点击预览页底部中间白色对勾确认按钮,坐标(" + Math.round(confirmX) + "," + Math.round(confirmY) + ")");
  570.         sleep.second(秒 = 3);
  571.         xml = 获取UI();
  572.     }
  573.    
  574.     var sendBtn = 查找发送按钮中心(xml);
  575.     if (sendBtn) {
  576.         agent.click(sendBtn.x, sendBtn.y);
  577.         print.log("✓ 已点击对话页面发送按钮,坐标(" + Math.round(sendBtn.x) + "," + Math.round(sendBtn.y) + ")");
  578.     } else {
  579.         var actionSendIdx = xml.indexOf('id/action_send"');
  580.         if (actionSendIdx !== -1) {
  581.             var 段 = xml.substring(actionSendIdx);
  582.             var m = 段.match(/bounds="\[(\d+),(\d+)\]\[(\d+),(\d+)\]"/);
  583.             if (m) {
  584.                 var sendX = (parseInt(m[1]) + parseInt(m[3])) / 2;
  585.                 var sendY = (parseInt(m[2]) + parseInt(m[4])) / 2;
  586.                 agent.click(sendX, sendY);
  587.                 print.log("✓ 已点击action_send按钮,坐标(" + Math.round(sendX) + "," + Math.round(sendY) + ")");
  588.             }
  589.         }
  590.     }
  591.     sleep.second(秒 = 5);

  592.     // 步骤9:记录发送后的基线文本
  593.     print.log("\n========== 步骤9:记录基线文本 ==========");
  594.     xml = 获取UI();
  595.     发送前最后文本 = 获取当前最后AI回答(xml);
  596.     print.log("发送前最后文本长度:" + 字符串长度(发送前最后文本));

  597.     // 步骤10:等待AI回答
  598.     print.log("\n========== 步骤10:等待AI回答 ==========");

  599.     var 新回答文本 = 等待AI回答完成(发送前最后文本);

  600.     // 步骤11:解析坐标并保存为全局变量
  601.     print.log("\n========== 步骤11:解析坐标 ==========");
  602.    
  603.     if (新回答文本 && 字符串长度(新回答文本) > 0) {
  604.         print.log("✓ 采集到AI回答");
  605.         print.log("--- 采集内容开始 ---");
  606.         print.log(新回答文本);
  607.         print.log("--- 采集内容结束 ---");
  608.         
  609.         var 坐标匹配 = 新回答文本.match(/(\d+)\s*[,,]\s*(\d+)/);
  610.         if (坐标匹配) {
  611.             验证码滑块距离 = {
  612.                 x: parseInt(坐标匹配[1]),
  613.                 y: parseInt(坐标匹配[2])
  614.             };
  615.             print.log("✓ 提取到坐标:(" + 验证码滑块距离.x + ", " + 验证码滑块距离.y + ")");
  616.         } else {
  617.             var 单个数字匹配 = 新回答文本.match(/(\d+)/);
  618.             if (单个数字匹配) {
  619.                 验证码滑块距离 = {
  620.                     x: parseInt(单个数字匹配[1]),
  621.                     y: 0
  622.                 };
  623.                 print.log("✓ 提取到单个数字:" + 验证码滑块距离.x);
  624.             } else {
  625.                 验证码滑块距离 = null;
  626.                 print.log("⚠ 未提取到坐标");
  627.             }
  628.         }
  629.     } else {
  630.         验证码滑块距离 = null;
  631.         print.log("⚠ 未能采集到新回答");
  632.     }

  633.     // 步骤12:切换回B站并拖动验证码滑块
  634.     if (验证码滑块距离 && 验证码滑块距离.x > 0) {
  635.         print.log("\n========== 步骤12:切换回B站并拖动滑块 ==========");
  636.         
  637.         agent.shell("input keyevent 187");
  638.         print.log("✓ 已按后台键打开任务列表");
  639.         sleep.second(秒 = 2);

  640.         xml = 获取UI();
  641.         var biliIdx = xml.indexOf('哔哩哔哩');
  642.         if (biliIdx === -1) {
  643.             biliIdx = xml.indexOf('bilibili');
  644.         }
  645.         
  646.         if (biliIdx !== -1) {
  647.             var 段 = xml.substring(biliIdx);
  648.             var m = 段.match(/bounds="\[(\d+),(\d+)\]\[(\d+),(\d+)\]"/);
  649.             if (m) {
  650.                 var clickX = (parseInt(m[1]) + parseInt(m[3])) / 2;
  651.                 var clickY = (parseInt(m[2]) + parseInt(m[4])) / 2;
  652.                 agent.click(clickX, clickY);
  653.                 print.log("✓ 已点击B站任务卡片,坐标(" + Math.round(clickX) + "," + Math.round(clickY) + ")");
  654.             }
  655.         } else {
  656.             print.log("⚠ 未找到B站任务卡片,尝试直接打开");
  657.             try {
  658.                 app.openApp("tv.danmaku.bili");
  659.                 print.log("✓ 已打开B站");
  660.             } catch (e) {
  661.                 print.log("⚠ 打开B站失败:" + e.message);
  662.             }
  663.         }
  664.         sleep.second(秒 = 3);

  665.         var xml = 获取UI();
  666.         var 验证码区域左边界 = 屏幕宽 * 0.15;
  667.         
  668.         var 滑块轨道匹配 = xml.match(/<node[^>]*?text="拖动滑块完成拼图"[^>]*?bounds="\[(\d+),(\d+)\]\[(\d+),(\d+)\]"/);
  669.         if (滑块轨道匹配) {
  670.             验证码区域左边界 = parseInt(滑块轨道匹配[1]);
  671.         }

  672.         var 拖动距离 = 验证码滑块距离.x * 滑块校准系数;

  673.         var startX = 验证码区域左边界 + 50;
  674.         var startY = 屏幕高 * 0.42;
  675.         var endX = startX + 拖动距离;
  676.         var endY = startY;

  677.         print.log("✓ 验证码区域左边界: " + 验证码区域左边界 + ", 拖动距离: " + 拖动距离);
  678.         agent.swip(startX, startY, endX, endY, 2000);
  679.         print.log("✓ 已拖动滑块,起点(" + Math.round(startX) + "," + Math.round(startY) + "),终点(" + Math.round(endX) + "," + Math.round(endY) + ")");
  680.     }

  681.     print.log("\n===== 豆包截图发送流程结束 =====");
  682. }

  683. 主流程();
复制代码



举报 回复