From 8c7c22369e45735613daebd848813e6e6211bf4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=85=AC=E6=98=8E?= <83812544+Ed1s0nZ@users.noreply.github.com> Date: Wed, 17 Jun 2026 12:30:20 +0800 Subject: [PATCH] Add files via upload --- web/static/css/style.css | 57 +++++++++++++++++++++++++ web/static/i18n/en-US.json | 1 + web/static/i18n/zh-CN.json | 1 + web/static/js/wechat-robot.js | 79 ++++++++++++++++++++++++++++++----- web/templates/index.html | 7 ++++ 5 files changed, 135 insertions(+), 10 deletions(-) diff --git a/web/static/css/style.css b/web/static/css/style.css index 055b59fa..cc9ef7fe 100644 --- a/web/static/css/style.css +++ b/web/static/css/style.css @@ -22734,6 +22734,58 @@ button.chat-files-dropdown-item:hover:not(:disabled) { display: none; } +.robot-wechat-bound-flash { + display: flex; + align-items: center; + gap: 8px; + margin: 12px 0 0; + padding: 10px 14px; + border-radius: 8px; + background: rgba(40, 167, 69, 0.1); + border: 1px solid rgba(40, 167, 69, 0.35); + color: var(--success-color); + font-size: 0.875rem; + font-weight: 500; + line-height: 1.45; + opacity: 0; + transform: translateY(-4px); + transition: opacity 0.25s ease, transform 0.25s ease; +} + +.robot-wechat-bound-flash[hidden] { + display: none !important; +} + +.robot-wechat-bound-flash.is-visible { + opacity: 1; + transform: translateY(0); +} + +.robot-wechat-bound-flash-icon { + flex-shrink: 0; + display: flex; + align-items: center; + justify-content: center; +} + +.robot-wechat-bound-summary { + margin: 10px 0 0; + font-size: 0.8125rem; + color: var(--text-secondary); + line-height: 1.45; +} + +.robot-wechat-bound-summary code { + font-family: ui-monospace, SFMono-Regular, Menlo, monospace; + font-size: 0.75rem; + padding: 2px 6px; + border-radius: 4px; + background: var(--bg-tertiary); + border: 1px solid var(--border-color); + color: var(--text-primary); + word-break: break-all; +} + .robot-wechat-panel { margin-top: 16px; padding: 20px; @@ -22751,6 +22803,11 @@ button.chat-files-dropdown-item:hover:not(:disabled) { gap: 10px; } +/* display:flex 会覆盖 [hidden] 默认 display:none,须显式隐藏 */ +.robot-wechat-bound-panel[hidden] { + display: none !important; +} + .robot-wechat-bound-icon { width: 56px; height: 56px; diff --git a/web/static/i18n/en-US.json b/web/static/i18n/en-US.json index 891ea4d4..d9774a19 100644 --- a/web/static/i18n/en-US.json +++ b/web/static/i18n/en-US.json @@ -1083,6 +1083,7 @@ "botAgent": "Bot Agent", "ilinkBotId": "iLink Bot ID (filled after bind)", "boundSuccess": "Binding successful. WeChat bot is enabled.", + "alreadyBound": "This WeChat account is already bound.", "openLink": "QR not showing? Open link in WeChat on your phone" }, "wecom": { diff --git a/web/static/i18n/zh-CN.json b/web/static/i18n/zh-CN.json index 2f08f2b8..dc914bb5 100644 --- a/web/static/i18n/zh-CN.json +++ b/web/static/i18n/zh-CN.json @@ -1071,6 +1071,7 @@ "botAgent": "Bot Agent", "ilinkBotId": "iLink Bot ID(绑定后自动填充)", "boundSuccess": "绑定成功,微信机器人已启用。", + "alreadyBound": "该微信已绑定过,无需重复绑定。", "openLink": "无法显示二维码?点击用手机微信打开链接" }, "wecom": { diff --git a/web/static/js/wechat-robot.js b/web/static/js/wechat-robot.js index 2446f317..d1ee42e1 100644 --- a/web/static/js/wechat-robot.js +++ b/web/static/js/wechat-robot.js @@ -2,6 +2,7 @@ let wechatBindSessionKey = null; let wechatBindPollTimer = null; +let wechatBindFlashTimer = null; function wechatT(key, fallback) { return typeof t === 'function' ? t(key) : fallback; @@ -88,13 +89,50 @@ function stopWechatBindPoll() { } } -/** 已绑定:仅展示成功状态,不显示二维码/配对码 */ +function clearWechatBindSuccessNotice() { + if (wechatBindFlashTimer) { + clearTimeout(wechatBindFlashTimer); + wechatBindFlashTimer = null; + } + const flash = document.getElementById('robot-wechat-bound-flash'); + if (flash) { + flash.classList.remove('is-visible'); + flash.hidden = true; + } +} + +/** 绑定成功后的内联提示(约 4.5 秒后自动淡出) */ +function showWechatBindSuccessNotice(message) { + const text = message || wechatT('settings.robots.wechat.boundSuccess', '绑定成功,微信机器人已启用。'); + const flash = document.getElementById('robot-wechat-bound-flash'); + const flashText = document.getElementById('robot-wechat-bound-flash-text'); + + if (flash) { + if (flashText) flashText.textContent = text; + flash.hidden = false; + requestAnimationFrame(() => flash.classList.add('is-visible')); + if (wechatBindFlashTimer) clearTimeout(wechatBindFlashTimer); + wechatBindFlashTimer = setTimeout(() => { + flash.classList.remove('is-visible'); + wechatBindFlashTimer = setTimeout(() => { + flash.hidden = true; + wechatBindFlashTimer = null; + }, 300); + }, 4500); + } + + if (typeof window.showChatToast === 'function') { + window.showChatToast(text, 'success'); + } +} + +/** 已绑定:收起二维码区,仅展示紧凑摘要 */ function showWechatBoundUI(wechat) { const wc = wechat || {}; const wrap = document.getElementById('robot-wechat-qr-wrap'); const boundPanel = document.getElementById('robot-wechat-bound-panel'); const scanPanel = document.getElementById('robot-wechat-scan-panel'); - const boundId = document.getElementById('robot-wechat-bound-id'); + const summary = document.getElementById('robot-wechat-bound-summary'); const btn = document.getElementById('robot-wechat-bind-btn'); stopWechatBindPoll(); @@ -102,8 +140,8 @@ function showWechatBoundUI(wechat) { setWechatBadge('bound'); setWechatCardBound(true); - if (wrap) wrap.hidden = false; - if (boundPanel) boundPanel.hidden = false; + if (wrap) wrap.hidden = true; + if (boundPanel) boundPanel.hidden = true; if (scanPanel) scanPanel.hidden = true; const verifyWrap = document.getElementById('robot-wechat-verify-wrap'); @@ -117,14 +155,15 @@ function showWechatBoundUI(wechat) { } if (ph) ph.hidden = false; - if (boundId) { - const id = wc.ilink_bot_id || document.getElementById('robot-wechat-ilink-bot-id')?.value?.trim() || ''; + const id = wc.ilink_bot_id || document.getElementById('robot-wechat-ilink-bot-id')?.value?.trim() || ''; + if (summary) { if (id) { - boundId.textContent = wechatT('settings.robots.wechat.boundBotId', '已绑定 Bot ID:') + id; - boundId.hidden = false; + const prefix = wechatT('settings.robots.wechat.boundBotId', '已绑定 Bot ID:'); + summary.innerHTML = `${prefix}${escapeHtml(id)}`; + summary.hidden = false; } else { - boundId.textContent = ''; - boundId.hidden = true; + summary.textContent = ''; + summary.hidden = true; } } @@ -133,21 +172,32 @@ function showWechatBoundUI(wechat) { } } +function escapeHtml(text) { + return String(text) + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"'); +} + /** 扫码绑定进行中 */ function showWechatScanUI() { const wrap = document.getElementById('robot-wechat-qr-wrap'); const boundPanel = document.getElementById('robot-wechat-bound-panel'); const scanPanel = document.getElementById('robot-wechat-scan-panel'); + const summary = document.getElementById('robot-wechat-bound-summary'); const btn = document.getElementById('robot-wechat-bind-btn'); setWechatBadge('scanning'); setWechatCardBound(false); + clearWechatBindSuccessNotice(); ensureWechatSteps(); updateWechatSteps('generate'); if (wrap) wrap.hidden = false; if (boundPanel) boundPanel.hidden = true; if (scanPanel) scanPanel.hidden = false; + if (summary) summary.hidden = true; const verifyWrap = document.getElementById('robot-wechat-verify-wrap'); if (verifyWrap) verifyWrap.hidden = true; @@ -163,7 +213,10 @@ function showWechatScanUI() { /** 未绑定且未在扫码:隐藏面板 */ function hideWechatQrWrap() { const wrap = document.getElementById('robot-wechat-qr-wrap'); + const summary = document.getElementById('robot-wechat-bound-summary'); if (wrap) wrap.hidden = true; + if (summary) summary.hidden = true; + clearWechatBindSuccessNotice(); setWechatBadge('idle'); setWechatCardBound(false); } @@ -278,6 +331,9 @@ async function pollWechatBindStatus() { const idEl = document.getElementById('robot-wechat-ilink-bot-id'); if (idEl) idEl.value = data.ilink_bot_id; } + showWechatBindSuccessNotice( + data.message || wechatT('settings.robots.wechat.boundSuccess', '绑定成功,微信机器人已启用。') + ); if (typeof loadConfig === 'function') { await loadConfig(false); } else { @@ -299,6 +355,9 @@ async function pollWechatBindStatus() { break; case 'binded_redirect': stopWechatBindPoll(); + showWechatBindSuccessNotice( + data.message || wechatT('settings.robots.wechat.alreadyBound', '该微信已绑定过,无需重复绑定。') + ); showWechatBoundUI({ bound: true }); return; case 'expired': diff --git a/web/templates/index.html b/web/templates/index.html index 56467593..d5a6b334 100644 --- a/web/templates/index.html +++ b/web/templates/index.html @@ -2817,6 +2817,13 @@

用微信扫码确认后会自动保存并启用。

+ +