From 01a1849174850fb5fdfbc45b5136dcf1c11acd4c Mon Sep 17 00:00:00 2001 From: Joshua Zhang Date: Mon, 29 Sep 2025 22:43:55 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0JS=E8=84=9A=E6=9C=AC=EF=BC=9A=E4=BB=8E?= =?UTF-8?q?=E6=9C=AC=E6=9C=BA=E5=B7=B2=E7=BC=93=E5=AD=98=E7=9A=84=E8=B4=A6?= =?UTF-8?q?=E5=8F=B7=E5=88=97=E8=A1=A8=E4=B8=AD=E9=80=89=E6=8B=A9=E5=B9=B6?= =?UTF-8?q?=E5=88=87=E6=8D=A2=E8=B4=A6=E5=8F=B7=E3=80=82=20(#2022)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 从本机已缓存的账号列表中选择并切换账号。 * 超时时长修改为1分钟 --------- Co-authored-by: 躁动的氨气 <131591012+zaodonganqi@users.noreply.github.com> --- repo/js/切换账号Dropdown/README.md | 12 + repo/js/切换账号Dropdown/assets/caret.png | Bin 0 -> 367 bytes repo/js/切换账号Dropdown/assets/logout.png | Bin 0 -> 646 bytes .../切换账号Dropdown/assets/paimon_cancel.png | Bin 0 -> 1721 bytes .../切换账号Dropdown/assets/paimon_menu.png | Bin 0 -> 2372 bytes repo/js/切换账号Dropdown/assets/quit.png | Bin 0 -> 1904 bytes repo/js/切换账号Dropdown/main.js | 282 ++++++++++++++++++ repo/js/切换账号Dropdown/manifest.json | 18 ++ repo/js/切换账号Dropdown/settings.json | 7 + 9 files changed, 319 insertions(+) create mode 100644 repo/js/切换账号Dropdown/README.md create mode 100644 repo/js/切换账号Dropdown/assets/caret.png create mode 100644 repo/js/切换账号Dropdown/assets/logout.png create mode 100644 repo/js/切换账号Dropdown/assets/paimon_cancel.png create mode 100644 repo/js/切换账号Dropdown/assets/paimon_menu.png create mode 100644 repo/js/切换账号Dropdown/assets/quit.png create mode 100644 repo/js/切换账号Dropdown/main.js create mode 100644 repo/js/切换账号Dropdown/manifest.json create mode 100644 repo/js/切换账号Dropdown/settings.json diff --git a/repo/js/切换账号Dropdown/README.md b/repo/js/切换账号Dropdown/README.md new file mode 100644 index 000000000..df00096a2 --- /dev/null +++ b/repo/js/切换账号Dropdown/README.md @@ -0,0 +1,12 @@ +# 选择并切换账号 + +## 使用前准备 + +确保你想要切换的账号是已登录状态,且账号选择列表中存在。 + +## 使用方式 + +1. 把此脚本添加到配置组 +2. 右键点击选择"修改JS脚本自定义配置" +3. 填入你想登录的账户名称,该名称必须和账号列表中显示的一致 + - 请确认你此次登录使用的是手机号还是邮箱 diff --git a/repo/js/切换账号Dropdown/assets/caret.png b/repo/js/切换账号Dropdown/assets/caret.png new file mode 100644 index 0000000000000000000000000000000000000000..3bb837eb0660c9c5c81af3074795cb85cde8d7f9 GIT binary patch literal 367 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&J!3HGrh2HJ~QjEnx?oJHr&dIz4a#+$GeH|GX zHuiJ>Nn{1`ISV`@iy0XB4uLSEsD@VqPy>sni(`m|e`=5?SAzl1m;d!aE;0Rawi;R- zU8e&Jx_uNBuQevzn&~s!tzX9G{Ncpw-)mn>?fek-`X|RiB!()pQr`YR-fq^1_9N$l{;EYmfx00L|Gp_ zFU{!msJrY#9LJMs#RuKKv2QuB^7p>t8y}m( LtDnm{r-UW|la!Id literal 0 HcmV?d00001 diff --git a/repo/js/切换账号Dropdown/assets/logout.png b/repo/js/切换账号Dropdown/assets/logout.png new file mode 100644 index 0000000000000000000000000000000000000000..99cc210ea98b7121196f8227047b54233b2356f8 GIT binary patch literal 646 zcmV;10(t$3P)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0vkz0K~z{r&6qo{ z0YMms&u<|*jYLDMbtyCoQ4k_7QHaD3Q27CRr9wy$5l1PfK0&D$3PE*t#dq>evKwZ0 zW6bRBP2OrI?>@UbGvCa7fk&h$Dt!O^!WZ4(rW95677*$M=<#?E-|u(m_xliuM8N0s z2|Ex7Ksud<{eDj}d1MGwEEbt?83%(w7z_r_k1`blG#ZVVKr0-J#hxE!Dh8-tuY=$3 zX98u7nLOeGipS&R%T1@#x1LNU#Fa{gf#MM}%WAb66LdTt>27a@FGuI_hzm$W2!w-K z%fK1OBin#b+wE5WmFxAIZZ?#yKq7JkXt&!zG#Z7~YDG6Oas;T+Xy{qJUXP3~GdTi8 zF9F?dm+qp=5g?^#9aY z^A3lDJP-z)&u3UJm&`!s9n_gjhGb}qr4$gaj55)MLV?WE=at(vpj<8os;cVyculSV zbvhjeM3W;x&1O^2(u%9AK%315!r?H?=X1J=kt0B#$W|avZDDQQ@$1vUX6cR;%^_Sz)20G#1O@aL9yNVWGeD!q+hx5N^J$y0A*6QsNg@ gUXZ7N{uCAd0e~SdWl-dWF8}}l07*qoM6N<$g2Oct3IG5A literal 0 HcmV?d00001 diff --git a/repo/js/切换账号Dropdown/assets/paimon_cancel.png b/repo/js/切换账号Dropdown/assets/paimon_cancel.png new file mode 100644 index 0000000000000000000000000000000000000000..2bffc12fb91c9a315b66d0f3b377f90ac45ca172 GIT binary patch literal 1721 zcmY*adpy%?7$2utF11(`a!bu*o7r~Smbo=+!zgVbp>4m7$u73B712$(^-;>DP^Yt` zW6_~-B*)RkrF=+E2ofByzg^)pZEKG-|zFso4zeztFeKF0R#du zX3(iYptS~npUjhp&>TR*<)c+1DOe4GxOu3g9Nu2O!j{XA5{fB^srp8Q ztq`Cff(c9)rgRHGT1ek7 zps!71?A_gDfPfrCrG2dcBZ_^rLLnt%FiNEot;C@vvM3CeL?U5aTrsY$D6j%0-zQdZ zR4B20-B$oAU(S;Wr3#@$Y^w$2a3%2yihX>%5FiUU0s-yI4lal z;ebs9EYVef<=TI3uMi6U?Jt&pl>rn4qdmc3(JorbTAv&!6Y@b8+LrEEw=d`a%ei5+ zME*m}{qGF;R?z!L8LdqJsLL0Fk}5&%oX->(f@7;^P`y|oTdVUY0#659wRm*S%=*^B zufVBdAAs&vD!8jkucwyw<+TI(?dA`5SD81*Vgz{&vlpIBi2Atg%{5dL+~sb1mVfa| z9E_E*Y8M(+n>UQ<>@$oO`T6+Ho-Vr7I6`Wiq4bXIb3*x_fWjQu>E1u7KA5!(???4E ze7n)a#I?%FGyM1!n0@#$TG61T6?0&M=4@`q0_^hMRJXn!94&fQ8i}bKUm>VQ!b!cA zX3NJMJc_2CU%cZJnvSf!Y1@NxBfft2NuDD6+(ayMdIBIHh=O39@Q%Umlu4tRrcJ7-ycY5NIV}*#J#`&PN(B@@~W1nj2s4GsICoY%|OD1J(Q}LG;e6qqAjIi zVRs`bEh+&^>4rOlVf zmKxDjy$!ymAt1BsN=pnfDl)%#Aw1!}Z@$DUhVbZiVE&xPExCJ6+v}1cXofux|4KN> zeg1y4{*%Xjx*LDb=_NSp>8(}#Ig2H~*kF-q?)G5pqN6LJ$9I@gmA~%Vlvj?!nf_xn z*N4n2u#2fYp4B>@F_#XDU`oW0#Lk|r@`>SEzznz<%R*r-hnRYui z7Jr(&x{$kJ{t!$)vzYIGu*4Huyz_ceaS&s)x!mq%;>Xp>#E4grgc}3r4NB9fyxq4H zr_T>3n=Ld&S>Kqh;yUN@;e}a{qj$E05Hp5;R9;+b+rhKH_Jm9$V0KG*9mwR#pW7d% z;fA&wFmj0USKrLV_jM;^(DBV%j%RK>p#1RX@D|;sKgx7K7{`&M10Q4al&LcLvhezW zw0oxh%+8e$h;MToIFjpKTn%#oiML2~$~;TCCRX38Nky3AG{a(c+I%+E;7CMEsmrfo!x2yNkWQC*(i8E92f^*vsLKFjJg3y70S^dpnwiaz!`!TBTr`D2aC zL1#aZ@ss+f#JotgDsj9u*hFw6IInrxw{VvE|bUG+kK=Mm6+)}MB+@Y~V}AhbF9 z*XQQRX5bV$iWX0HBv_8p@wH@3hV#Yln5v}Q=OwAjzF`&k5#RMChG?8*nrV}4M6k&3 z9_^@((?(y?hqi&b$y-YfbF5F)J*sK?PR+@TKXAM56N+I%JL0~uIiIy53t^H~Pcbqg zLmmnV3UTe*=0n93ro+&(GS|sz>C67Lg0ZCW8y365UJ;X`H^o=8F%cn9FTB}US3w~- zqK}f1(krc=EeV!WHUpn$dA5=F2OTR_y4lJ@`fAhN^>NwyYIK>#X*{+zE_!5ntTEwb zdEZH?V3N&V^*IPSRg{gWSfh8`W(MHusl5Vu4Y_OQ%3sGyn)f^`;W=EoeU$fh$tijk z9Zz$#va|O4aePJ9Z(-aR!TGkAB!3^hSmVdBdn?qH9T__{q4ALQp680KR(3A*)*SA% zx%)Kym(62$D3r`j8z4qtJ+T3I;@x9#0?}pHnhLO+W!9(omW%q#WiA?zp*U~t|H1GH KpjLSAIs6xkHuGr! literal 0 HcmV?d00001 diff --git a/repo/js/切换账号Dropdown/assets/paimon_menu.png b/repo/js/切换账号Dropdown/assets/paimon_menu.png new file mode 100644 index 0000000000000000000000000000000000000000..c424325b17a4956f7802352e7609bfcff2721afa GIT binary patch literal 2372 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 literal 0 HcmV?d00001 diff --git a/repo/js/切换账号Dropdown/main.js b/repo/js/切换账号Dropdown/main.js new file mode 100644 index 000000000..3df6681ea --- /dev/null +++ b/repo/js/切换账号Dropdown/main.js @@ -0,0 +1,282 @@ +(async function () { + // ====================================================== + // Library functions + + var u = {}; // utilities 工具函数集合 + u.logi = function(message, args) { log.info( "[切换账号]" + message, args) }; + u.logw = function(message, args) { log.warn( "[切换账号]" + message, args) }; + u.x = function (value) { return (value === undefined) ? genshin.width : genshin.width * (value / 1920); }; + u.y = function (value) { return (value === undefined) ? genshin.height : genshin.height * (value / 1080); }; + u.loadTemplate = function (filePath, x /* 0 if omit */, y /* 0 if omit */, w /* maxWidth if omit */, h /* maxHeight if omit */) { + const _x = u.x(x === undefined ? 0 : x); + const _y = u.y(y === undefined ? 0 : y); + const _w = u.x(w) - _x; + const _h = u.y(h) - _y; + return RecognitionObject.TemplateMatch(file.ReadImageMatSync(filePath), _x, _y, _w, _h); + }; + u.findText = function (resList, text) { + for (let i = 0; i < resList.count; i++) { + let res = resList[i]; + if (res.text == text) { + return res; + } + } + return null; + }; + u.matchUser = function (text, username) { + if (typeof text !== "string" || typeof username !== "string") return false; + if (text.length !== username.length) return false; + for (let i = 0; i < text.length; i++) { + const a = text[i]; + const b = username[i]; + if (a === '*' || b === '*') continue; + if (a !== b) return false; + } + return true; + }; + u.matchUserRelaxed = function (text, username) { + if (typeof text !== "string" || typeof username !== "string") return false; + // Check the head + for (let i = 0; i < text.length; i++) { + const a = text[i]; + const b = username[i]; + if (a === '*') break; // Stop checking when a '*' is found in text. + if (a !== b) return false; + } + // Check the tail + for (let i = 0; i < text.length; i++) { + const a = text[text.length - 1 - i]; + const b = username[username.length - 1 - i]; + if (a === '*') break; // Stop checking when a '*' is found in text. + if (a !== b) return false; + } + return true; + }; + u.waitAndFindImage = async function (asset, internal = 500, timeout = 60000) { + const start = Date.now(); + let lastLog = start; + let endTime = start + timeout; + while (Date.now() < endTime) { + let captureRegion = captureGameRegion(); + let res = captureRegion.Find(asset); + if (!res.isEmpty()) { + return res; + } + if (Date.now() - lastLog >= 10000) { + let elapsed = ((Date.now() - start) / 1000).toFixed(1); + u.logw("等待匹配图像已持续 {0} 秒,仍在尝试寻找图像:{1}", elapsed, asset.Name); + lastLog = Date.now(); + } + await sleep(internal); + } + return null; + } + u.waitAndFindText = async function (text, x, y, w, h, internal = 500) { + const start = Date.now(); + let lastLog = start; + while (true) { + let captureRegion = captureGameRegion(); + let resList = captureRegion.findMulti(RecognitionObject.ocr(x, y, w, h)); + if (typeof text === "string") { + let textFound = u.findText(resList, text); + if (textFound) { + return textFound; + } + } else if (text instanceof Array) { + var textFound = null; + for (let i = 0; i < text.length; i++) { + let textItem = text[i]; + textFound = u.findText(resList, textItem); + if (!textFound) { + break; + } + } + if (textFound) { + return textFound; + } + } + + if (Date.now() - lastLog >= 10000) { + let elapsed = ((Date.now() - start) / 1000).toFixed(1); + u.logw("等待匹配图像已持续 {0} 秒,仍在尝试寻找文字:{1}", elapsed, text.toString()); + lastLog = Date.now(); + } + await sleep(internal); + } + } + + // ====================================================== + // Setup + + const targetUser = settings.username; + + const assetLogoutIcon = u.loadTemplate("assets/logout.png", 1750, 900); + const assetPaimonMenuIcon = u.loadTemplate("assets/paimon_menu.png", 0, 0, 150, 150); + + // ====================================================== + // Check current state + + async function waitAndDetermineCurrentView() { + u.logi("开始判断当前画面状态"); + while (true) { + let captureRegion = captureGameRegion(); + let res = captureRegion.Find(assetLogoutIcon); + let logoutIconFound = !res.isEmpty(); + + if (logoutIconFound) { + let resList = captureRegion.findMulti(RecognitionObject.ocr(u.x(850), u.y(970), u.x(220), u.y(100))); + if (u.findText(resList, "点击进入")) { + u.logi("检测到目前处于登录界面"); + return false; + } + } + + // Not in the login screen, check if is in the game main menu. + let paimonIcon = captureRegion.Find(assetPaimonMenuIcon); + if (!paimonIcon.isEmpty()) { + u.logi("检测到目前处于游戏主界面"); + return true; + } + + // Not in the main game screen either, wait and try again. + u.logi("未检测到登出按钮或派蒙菜单图标,可能处于游戏中,等待状态变化"); + genshin.blessingOfTheWelkinMoon(); + moveMouseTo(960, 0); + await sleep(100); + middleButtonClick(); + genshin.returnMainUi(); + await sleep(4900); + } + } + + async function stateReturnToGenshinGate() { + const assetPaimonCancelIcon = u.loadTemplate("assets/paimon_cancel.png", 0, 0, 100, 100); + + while (true) { + let paimonIcon = await u.waitAndFindImage(assetPaimonMenuIcon, 500, 1000); + if (!paimonIcon) { + u.logi("检测到派蒙菜单图标不存在,可能已开启菜单,进入登出按钮识别流程"); + break; + } + moveMouseTo(960, 0); + await sleep(100); + middleButtonClick(); + keyPress("VK_ESCAPE"); + u.logi("已按下ESC键,打开派蒙菜单"); + await sleep(1000); + } + + // 识别派蒙菜单,点击登出按钮 + await u.waitAndFindImage(assetPaimonCancelIcon); + // u.logi("点击登出按钮"); + click(u.x(50), u.y(1024)); + + // 退出至登录界面 + let btnExitToLogin = await u.waitAndFindText("退出至登录界面", u.x(680), u.y(380), u.x(540), u.y(340)); + // u.logi("检测到\"退出至登录界面\"按钮,点击"); + // btnExitToLogin.DrawSelf("ExitToLoginBtn"); + btnExitToLogin.Click(); + } + + async function stateLogout() { + u.logi("开始登出"); + + let btnLogout = await u.waitAndFindImage(assetLogoutIcon); + // u.logi("识别到登出按钮,点击"); + btnLogout.DrawSelf("LogoutBtn"); + btnLogout.Click(); + + const assetQuitTextButton = u.loadTemplate("assets/quit.png", 680, 380, 1220, 720); + let btnQuit = await u.waitAndFindImage(assetQuitTextButton, 200); + // u.logi("识别到退出按钮,点击"); + // btnQuit.DrawSelf("QuitBtn"); + btnQuit.Click(); + }; + + async function stateChangeUser() { + u.logi("开始切换账号"); + await u.waitAndFindText(["进入游戏", "登录其他账号"], u.x(680), u.y(380), u.x(540), u.y(340), 200); + + const assetSelectUserDropDownIcon = u.loadTemplate("assets/caret.png", 680, 380, 1220, 720); + let captureRegion = captureGameRegion(); + let res = captureRegion.Find(assetSelectUserDropDownIcon); + if (res.isEmpty()) { + u.logi("未找到下拉菜单图标,点击硬编码的坐标(960, 500)展开菜单"); + click(u.x(960), u.y(500)); + } else { + // u.logi("识别到下拉菜单,点击"); + // res.DrawSelf("UserDropdown"); + res.Click(); + } + + u.logi("开始从下拉列表选择账号"); + var selectedUser = null; + { + const start = Date.now(); + let lastLog = start; + while (selectedUser == null) { + await sleep(200); + + let captureRegion = captureGameRegion(); + let resList = captureRegion.findMulti(RecognitionObject.ocr(u.x(680), u.y(540), u.x(540), u.y(500))); + for (let i = 0; i < resList.count; i++) { + let res = resList[i]; + let user = lastLog > start ? u.matchUserRelaxed(res.text, targetUser) : u.matchUser(res.text, targetUser); + if (user) { + selectedUser = res; + break; + } + } + + if (Date.now() - lastLog >= 10000) { + let elapsed = ((Date.now() - start) / 1000).toFixed(1); + u.logw("等待匹配图像已持续 {0} 秒,仍在尝试寻找账号文本:{1}", elapsed, targetUser); + lastLog = Date.now(); + for (let i = 0; i < resList.count; i++) { + let res = resList[i]; + u.logw("账户文本:{0}", res.text); + } + } + } + } + + u.logi("识别到目标账号:{0}", selectedUser.text); + selectedUser.DrawSelf("SelectUser"); + selectedUser.Click(); + + await sleep(500); + { + let captureRegion = captureGameRegion(); + let btnEnterGame = captureRegion.DeriveCrop(u.x(684), u.y(598), u.x(552), u.y(66)); + btnEnterGame.Click(); + // btnEnterGame.DrawSelf("EnterGameBtn"); + // u.logi("已点击\"进入游戏\"按钮,完成账号选择。"); + } + } + + async function stateEnterGame() { + // u.logi("开始进入游戏,等待游戏加载。"); + let textClickToStart = await u.waitAndFindText("点击进入", u.x(850), u.y(970), u.x(220), u.y(100)); + // u.logi("已识别到\"点击进入\"文本,点击鼠标进入游戏。"); + textClickToStart.DrawSelf("ClickToStart"); + textClickToStart.Click(); + } + + + // ====================================================== + // Main flow + + const isInGame = await waitAndDetermineCurrentView(); + if (isInGame) { + await stateReturnToGenshinGate(); + await sleep(1000); + } + await stateLogout(); + await sleep(500); + await stateChangeUser(); + await sleep(500); + await stateEnterGame(); + await sleep(20000); + await waitAndDetermineCurrentView(); + +})(); diff --git a/repo/js/切换账号Dropdown/manifest.json b/repo/js/切换账号Dropdown/manifest.json new file mode 100644 index 000000000..3ce7fbe00 --- /dev/null +++ b/repo/js/切换账号Dropdown/manifest.json @@ -0,0 +1,18 @@ +{ + "manifest_version": 1, + "name": "切换账号(从下拉列表中选择)", + "version": "1.0", + "bgi_version": "0.49.0", + "description": "退出当前登录用户并从列表中选定指定用户,纯鼠标操作。", + "tags": [ + "鼠标点击", + "切换账号" + ], + "authors": [ + { + "name": "密密麻麻" + } + ], + "settings_ui": "settings.json", + "main": "main.js" +} \ No newline at end of file diff --git a/repo/js/切换账号Dropdown/settings.json b/repo/js/切换账号Dropdown/settings.json new file mode 100644 index 000000000..b1a937d96 --- /dev/null +++ b/repo/js/切换账号Dropdown/settings.json @@ -0,0 +1,7 @@ +[ + { + "name": "username", + "type": "input-text", + "label": "请输入要切换的账号名称" + } +] \ No newline at end of file