From 7a8ca3ab7d377b919e757c4694e94f5a5fb46cb2 Mon Sep 17 00:00:00 2001 From: yan Date: Fri, 13 Feb 2026 02:34:11 +0800 Subject: [PATCH] =?UTF-8?q?feat(auto-plan):=20=E6=B7=BB=E5=8A=A0=E7=A7=98?= =?UTF-8?q?=E5=A2=83=E9=80=80=E5=87=BA=E7=95=8C=E9=9D=A2=E5=A4=84=E7=90=86?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 outDomainUI 函数用于处理秘境退出界面 - 添加 isInOutDomainUI 函数检测是否在秘境退出界面 - 实现 findTextAndClick 通用文本查找点击功能 - 在 main.js 中关闭自动分解和原粹树脂榨干功能 - 修复代码格式化问题和拼写错误 - 添加退出秘境相关的图片资源映射配置 --- repo/js/AutoPlanDomain/assets/out_domain.jpg | Bin 0 -> 2489 bytes repo/js/AutoPlanDomain/main.js | 12 +- repo/js/AutoPlanDomain/utils/tool.js | 116 ++++++++++++++++++- 3 files changed, 122 insertions(+), 6 deletions(-) create mode 100644 repo/js/AutoPlanDomain/assets/out_domain.jpg diff --git a/repo/js/AutoPlanDomain/assets/out_domain.jpg b/repo/js/AutoPlanDomain/assets/out_domain.jpg new file mode 100644 index 0000000000000000000000000000000000000000..d082b9269a8efa2b778b6eaf5d8fe84dcea0c9de GIT binary patch literal 2489 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 ma1Wd+1xG9Mw2-v}#o~sGj&gzuKW3^7a { + // let name = '主界面' + let main_ui = getJsonPath('out_domain'); + // 定义识别对象 + let paimonMenuRo = RecognitionObject.TemplateMatch( + file.ReadImageMatSync(`${main_ui.path}${main_ui.name}${main_ui.type}`), + 0, + 0, + genshinJson.width / 3.0, + genshinJson.width / 5.0 + ); + let captureRegion = captureGameRegion(); + let res = captureRegion.find(paimonMenuRo); + captureRegion.Dispose() + return !res.isEmpty(); +}; + +async function outDomainUI() { + let ms = 300 + let index = 1 + await sleep(ms); + while (!isInOutDomainUI()) { + await sleep(ms); + await keyPress("ESCAPE"); + await sleep(ms); + if (index > 3) { + log.error(`多次尝试匹配退出秘境界面失败 假定已经退出处理`); + } + index += 1 + } + + if (isInOutDomainUI()) { + try { + //点击确认按钮 + await findTextAndClick('确认') + }catch (e) { + log.error(`多次尝试点击确认失败 假定已经退出处理`); + } + + } + +} + +/** + * 通用找文本并点击(OCR) + * @param {string|string[]} text 目标文本(单个文本或文本列表,列表时需全部匹配) + * @param {number} [x=0] OCR 区域左上角 X + * @param {number} [y=0] OCR 区域左上角 Y + * @param {number} [w=1920] OCR 区域宽度 + * @param {number} [h=1080] OCR 区域高度 + * @param {number} [attempts=5] OCR 尝试次数 + * @param {number} [interval=50] 每次 OCR 之间的等待间隔(毫秒) + * @param {number} [preClickDelay=50] 点击前等待时间(毫秒) + * @param {number} [postClickDelay=50] 点击后等待时间(毫秒) + * + * @returns + * - RecognitionResult | null + */ +async function findTextAndClick( + text, + x = 0, + y = 0, + w = 1920, + h = 1080, + attempts = 5, + interval = 50, + preClickDelay = 50, + postClickDelay = 50 +) { + const keyword = text.toLowerCase(); + + for (let i = 0; i < attempts; i++) { + const gameRegion = captureGameRegion(); + try { + const ro = RecognitionObject.Ocr(x, y, w, h); + const results = gameRegion.findMulti(ro); + + for (let j = 0; j < results.count; j++) { + const res = results[j]; + if ( + res.isExist() && + res.text && + res.text.toLowerCase().includes(keyword) + ) { + await sleep(preClickDelay); + res.click(); + await sleep(postClickDelay); + return res; + } + } + } finally { + gameRegion.dispose(); + } + + await sleep(interval); + } + + return null; +} + /** * 抛出错误函数 * 该函数用于显示错误通知并抛出错误对象 * @param {string} msg - 错误信息,将用于通知和错误对象 */ -function throwError(msg,isNotification=false) { +function throwError(msg, isNotification = false) { // 使用notification组件显示错误通知 // notification.error(`${msg}`); if (isNotification) { @@ -139,5 +248,8 @@ export { getJsonPath, isInMainUI, toMainUi, + isInOutDomainUI, + outDomainUI, + findTextAndClick, throwError, } \ No newline at end of file