From fc4898a9eeaacf05cf535f6dfe928bea8401fcaa Mon Sep 17 00:00:00 2001 From: jason Date: Tue, 3 Mar 2026 23:50:26 +0800 Subject: [PATCH] feat: implement custom node.js sync server and secure extension client with login/register UI --- background.js | 72 +++++++++ popup.css | 66 +++++--- popup.html | 111 ++++++++++---- popup.js | 307 ++++++++++++++++++++++++++++++++------ server/Dockerfile | 17 +++ server/docker-compose.yml | 12 ++ server/package.json | 14 ++ server/server.js | 129 ++++++++++++++++ 8 files changed, 629 insertions(+), 99 deletions(-) create mode 100644 server/Dockerfile create mode 100644 server/docker-compose.yml create mode 100644 server/package.json create mode 100644 server/server.js diff --git a/background.js b/background.js index 10ad2bc..61f5ad7 100644 --- a/background.js +++ b/background.js @@ -139,6 +139,78 @@ function autoFillLogin(username, password) { passwordEl.focus(); setNativeValue(passwordEl, password); triggerEvents(passwordEl); + + // --- New: Auto-click Login Button --- + setTimeout(() => { + // 常规登录按钮选择器 + const loginButtonSelectors = [ + 'button[type="submit"]', + 'input[type="submit"]', + 'button.login-btn', + 'button.submit-btn', + '#login-btn', + '.login-button', + 'button.ant-btn-primary' // 适配 Ant Design + ]; + + let loginBtn = null; + for (const selector of loginButtonSelectors) { + const btn = document.querySelector(selector); + if (btn && btn.offsetWidth > 0 && btn.offsetHeight > 0) { + loginBtn = btn; + break; + } + } + + // 如果没有按选择器找到,尝试按文本内容查找 + if (!loginBtn) { + const allBtns = document.querySelectorAll('button, div[role="button"], span'); + for (const btn of allBtns) { + const text = btn.innerText || btn.textContent; + if (btn.offsetWidth > 0 && btn.offsetHeight > 0 && + (text.includes('登录') || text.includes('Log In') || text.includes('Login')) && + btn.tagName !== 'BODY') { + loginBtn = btn; + break; + } + } + } + + if (loginBtn) { + console.log("[QuickPurge] Login button found, clicking..."); + loginBtn.click(); + + // --- New: Secondary Confirmation Auto-click --- + // 登录后开启定时检测,识别“账号已登录”确认弹窗 + let confirmTries = 0; + const confirmInterval = setInterval(() => { + confirmTries++; + const allBtns = document.querySelectorAll('button, div[role="button"], span'); + let confirmBtn = null; + + for (const btn of allBtns) { + const text = (btn.innerText || btn.textContent).trim(); + // 匹配“确认”、“继续登录”等文字,且由于是弹窗按钮,通常会有特定的类名 + if (btn.offsetWidth > 0 && btn.offsetHeight > 0 && + (text === '确认' || text === '确定' || text === '继续登录' || text === 'Confirm') && + btn.tagName !== 'BODY') { + confirmBtn = btn; + break; + } + } + + if (confirmBtn) { + console.log("[QuickPurge] Secondary confirmation button found, clicking..."); + confirmBtn.click(); + clearInterval(confirmInterval); + } + + if (confirmTries > 20) { // 最多检测 5 秒 (250mx * 20) + clearInterval(confirmInterval); + } + }, 250); + } + }, 300); // 填充完后等待 300ms 点击,确保框架已处理输入 }, 50); return true; diff --git a/popup.css b/popup.css index 2022e47..51a8b0d 100644 --- a/popup.css +++ b/popup.css @@ -238,8 +238,25 @@ button { flex-grow: 1; overflow: hidden; margin-right: 8px; - pointer-events: none; - /* easier dragging */ + cursor: pointer; + padding: 6px 8px; + border-radius: 6px; + transition: all 0.2s ease; + /* Ensure child clicks are captured */ + pointer-events: auto; +} + +.rule-info:hover { + background: rgba(59, 130, 246, 0.08); +} + +.rule-info:active { + background: rgba(59, 130, 246, 0.15); + transform: scale(0.995); +} + +.rule-info:active { + background: rgba(59, 130, 246, 0.1); } .rule-domain { @@ -254,15 +271,38 @@ button { .rule-env { display: inline-block; - background: rgba(59, 130, 246, 0.1); - color: var(--accent-color); padding: 2px 6px; border-radius: 4px; font-size: 10px; + font-weight: 500; margin-left: 6px; vertical-align: middle; } +.env-dd-pp { + background: #E0E7FF; + color: #4338CA; + border: 1px solid #C7D2FE; +} + +.env-dd-ats { + background: #DCFCE7; + color: #15803D; + border: 1px solid #BBF7D0; +} + +.env-std-pp { + background: #FEF3C7; + color: #B45309; + border: 1px solid #FDE68A; +} + +.env-std-ats { + background: #FCE7F3; + color: #BE185D; + border: 1px solid #FBCFE8; +} + .rule-acc { font-size: 11px; color: var(--text-secondary); @@ -276,24 +316,14 @@ button { gap: 4px; } -.btn-execute { - color: var(--success-color); - background: rgba(16, 185, 129, 0.1); -} - -.btn-execute:hover { - background: rgba(16, 185, 129, 0.2); - color: #059669; -} - .btn-delete { color: var(--danger-color); - background: rgba(239, 68, 68, 0.1); + background: rgba(239, 68, 68, 0.05); } .btn-delete:hover { - background: rgba(239, 68, 68, 0.2); - color: #b91c1c; + background: rgba(239, 68, 68, 0.15); + color: var(--danger-hover); } .loading { @@ -323,4 +353,4 @@ button { .empty-state svg { color: #cbd5e1; -} +} \ No newline at end of file diff --git a/popup.html b/popup.html index b1d9a60..a0e3b97 100644 --- a/popup.html +++ b/popup.html @@ -3,50 +3,97 @@ - QuickPurge + 清速登 -
-

QuickPurge & AutoLogin

- -
+
+
+

清速登

+
+ 切换账号 + +
+
-