diff --git a/gateway/scripts/dashboard.py b/gateway/scripts/dashboard.py index 1f67e77..987bbfe 100644 --- a/gateway/scripts/dashboard.py +++ b/gateway/scripts/dashboard.py @@ -611,14 +611,21 @@ def _augment_wechat_status(entry): entry["qr_timestamp"] = None entry["session_age_hours"] = 0 - # 1. Fetch QR code (always available) + # 二维码【不再自动拉取】:避免 dashboard 每10秒轮询时自动刷新二维码(用户要求改手动获取)。 + # 只从"手动获取缓存"读取——用户点"获取登录二维码"后由 /api/wechat/status 写入; + # 且仅当缓存未过期(二维码约5分钟有效)才返回,过期视为无 → 前端显示"获取登录二维码"按钮。 try: - req = urllib.request.Request("http://localhost:3001/login?token=mowechat_fixed_token_001") - html = urllib.request.urlopen(req, timeout=5).read().decode("utf-8", errors="replace") - m = re.search(r'qrcode\.makeCode\("([^"]+)"\)', html) - if m: - entry["qr_url"] = m.group(1) - entry["qr_timestamp"] = now.isoformat() + cache_file = str(_GATEWAY_DIR / "temp" / "wechat_qr_cache.json") + if os.path.exists(cache_file): + with open(cache_file, encoding="utf-8") as f: + qc = json.load(f) + qurl = qc.get("qr_url") + qts = qc.get("ts", "") + if qurl and qts: + age_sec = (now - datetime.fromisoformat(qts)).total_seconds() + if age_sec < 300: # 二维码约5分钟有效 + entry["qr_url"] = qurl + entry["qr_timestamp"] = qts except Exception: pass @@ -1876,6 +1883,13 @@ def api_wechat_status(): if m: result["qr_url"] = m.group(1) result["qr_timestamp"] = now.isoformat() + # 手动获取到二维码 → 写入缓存,dashboard infra status 据此显示(避免自动拉取刷新) + try: + cache_file = str(_GATEWAY_DIR / "temp" / "wechat_qr_cache.json") + with open(cache_file, "w", encoding="utf-8") as _cf: + json.dump({"qr_url": m.group(1), "ts": now.isoformat()}, _cf, ensure_ascii=False) + except Exception: + pass except Exception as e: result["message"] = f"QR page fetch failed: {e}" diff --git a/gateway/scripts/templates/dashboard.html b/gateway/scripts/templates/dashboard.html index 65ce8d5..0728e49 100644 --- a/gateway/scripts/templates/dashboard.html +++ b/gateway/scripts/templates/dashboard.html @@ -332,16 +332,10 @@ async function fI(){ h+='\u4e8c\u7ef4\u7801\u7ea65\u5206\u949f\u6709\u6548'; h+=''; h+='
'; - h+='

\u83ab\u8377\u5fae\u4fe1\u9700\u8981\u626b\u7801\u767b\u5f55

'; - h+='

'+esc(s.message||'')+'\u3002\u7528\u5fae\u4fe1\u626b\u63cf\u5de6\u4fa7\u4e8c\u7ef4\u7801\u91cd\u65b0\u767b\u5f55\u3002

'; - h+='

\u94fe\u63a5: '+esc(s.qr_url||'')+'

'; - h+='
'; - setTimeout(function(){ - var el=document.getElementById('wechat-qr-age'); - if(el)el.innerHTML='\u4e8c\u7ef4\u7801\u5df2\u8fc7\u671f'; - var btn=document.getElementById('wechat-qr-refresh'); - if(btn)btn.textContent='\u5df2\u8fc7\u671f\uff0c\u70b9\u51fb\u5237\u65b0'; - },300000); + h+='

莫荷微信需要扫码登录

'; + h+='

'+esc(s.message||'')+'。用微信扫描左侧二维码重新登录。

'; + h+='

链接: '+esc(s.qr_url||'')+'

'; + h+=''; }else{ h+='
'; h+=''; @@ -682,6 +676,14 @@ function inMd(t){return t.replace(/\*\*([^*]+)\*\*/g,'$1').repl init();loadAll();setInterval(loadAll,10000);setInterval(fK,15000); /* --- WeChat QR: 获取二维码(触发容器 /api/bot/login) + 刷新 --- */ +function renderWechatQR(qrUrl){ + var box=document.getElementById('wechat-qr-get-status'); + if(box) box.innerHTML='' + +'
用微信扫描上方二维码登录(约5分钟有效,过期请点下方"刷新二维码")
' + +''; + var getBtn=document.getElementById('wechat-qr-get'); + if(getBtn) getBtn.style.display='none'; +} async function getWechatQR(){ var st=document.getElementById('wechat-qr-get-status'); var btn=document.getElementById('wechat-qr-get'); @@ -697,7 +699,7 @@ async function getWechatQR(){ await new Promise(res=>setTimeout(res,2000)); try{ var rs=await fetch('/api/wechat/status'),sd=await rs.json(); - if(sd.qr_url){location.reload();return;} + if(sd.qr_url){renderWechatQR(sd.qr_url);return;} }catch(e){} } if(st)st.innerHTML='\u4e8c\u7ef4\u7801\u672a\u751f\u6210\uff0c\u8bf7\u91cd\u8bd5'; @@ -712,10 +714,17 @@ async function getWechatQR(){ } } async function refreshWechatQR(){ + var st=document.getElementById('wechat-qr-get-status'); + if(st && !document.getElementById('wechat-qr-img')) st.innerHTML='正在刷新二维码...'; try{ await fetch('/api/wechat/trigger-login',{method:'POST'}); - // 刷新后等几秒重新拉状态 - setTimeout(function(){location.reload();},3000); + for(var i=0;i<10;i++){ + await new Promise(res=>setTimeout(res,2000)); + try{ + var rs=await fetch('/api/wechat/status'),sd=await rs.json(); + if(sd.qr_url){ renderWechatQR(sd.qr_url); return; } + }catch(e){} + } }catch(e){} } \ No newline at end of file