fix(wechat-qr): stop auto-refresh of login QR — manual get/refresh only, with cache (no more 10s auto-fetch + 5min auto-change)

This commit is contained in:
hmo
2026-08-26 04:02:05 +08:00
parent 9b53ba6872
commit 0df627ca1b
2 changed files with 43 additions and 20 deletions
+21 -7
View File
@@ -611,14 +611,21 @@ def _augment_wechat_status(entry):
entry["qr_timestamp"] = None entry["qr_timestamp"] = None
entry["session_age_hours"] = 0 entry["session_age_hours"] = 0
# 1. Fetch QR code (always available) # 二维码【不再自动拉取】:避免 dashboard 每10秒轮询时自动刷新二维码(用户要求改手动获取)。
# 只从"手动获取缓存"读取——用户点"获取登录二维码"后由 /api/wechat/status 写入;
# 且仅当缓存未过期(二维码约5分钟有效)才返回,过期视为无 → 前端显示"获取登录二维码"按钮。
try: try:
req = urllib.request.Request("http://localhost:3001/login?token=mowechat_fixed_token_001") cache_file = str(_GATEWAY_DIR / "temp" / "wechat_qr_cache.json")
html = urllib.request.urlopen(req, timeout=5).read().decode("utf-8", errors="replace") if os.path.exists(cache_file):
m = re.search(r'qrcode\.makeCode\("([^"]+)"\)', html) with open(cache_file, encoding="utf-8") as f:
if m: qc = json.load(f)
entry["qr_url"] = m.group(1) qurl = qc.get("qr_url")
entry["qr_timestamp"] = now.isoformat() 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: except Exception:
pass pass
@@ -1876,6 +1883,13 @@ def api_wechat_status():
if m: if m:
result["qr_url"] = m.group(1) result["qr_url"] = m.group(1)
result["qr_timestamp"] = now.isoformat() 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: except Exception as e:
result["message"] = f"QR page fetch failed: {e}" result["message"] = f"QR page fetch failed: {e}"
+21 -12
View File
@@ -332,16 +332,10 @@ async function fI(){
h+='<span id=wechat-qr-age>\u4e8c\u7ef4\u7801\u7ea65\u5206\u949f\u6709\u6548</span></div>'; h+='<span id=wechat-qr-age>\u4e8c\u7ef4\u7801\u7ea65\u5206\u949f\u6709\u6548</span></div>';
h+='<button id=wechat-qr-refresh class="btn r" style="margin-top:4px;font-size:14px;padding:3px 10px" onclick="refreshWechatQR()">\u5237\u65b0\u4e8c\u7ef4\u7801</button></div>'; h+='<button id=wechat-qr-refresh class="btn r" style="margin-top:4px;font-size:14px;padding:3px 10px" onclick="refreshWechatQR()">\u5237\u65b0\u4e8c\u7ef4\u7801</button></div>';
h+='<div style=flex:1;min-width:160px;font-size:14px;color:var(--dim)>'; h+='<div style=flex:1;min-width:160px;font-size:14px;color:var(--dim)>';
h+='<p style="margin:0 0 4px;color:var(--yellow);font-weight:600">\u83ab\u8377\u5fae\u4fe1\u9700\u8981\u626b\u7801\u767b\u5f55</p>'; h+='<p style="margin:0 0 4px;color:var(--yellow);font-weight:600">莫荷微信需要扫码登录</p>';
h+='<p style=margin:0;line-height:1.5>'+esc(s.message||'')+'\u3002\u7528\u5fae\u4fe1\u626b\u63cf\u5de6\u4fa7\u4e8c\u7ef4\u7801\u91cd\u65b0\u767b\u5f55\u3002</p>'; h+='<p style=margin:0;line-height:1.5>'+esc(s.message||'')+'。用微信扫描左侧二维码重新登录。</p>';
h+='<p style=margin-top:4px>\u94fe\u63a5: <code style=word-break:break-all;font-size:13px>'+esc(s.qr_url||'')+'</code></p>'; h+='<p style=margin-top:4px>链接: <code style=word-break:break-all;font-size:13px>'+esc(s.qr_url||'')+'</code></p>';
h+='</div>'; h+='</div>';
setTimeout(function(){
var el=document.getElementById('wechat-qr-age');
if(el)el.innerHTML='<span style=color:var(--red)>\u4e8c\u7ef4\u7801\u5df2\u8fc7\u671f</span>';
var btn=document.getElementById('wechat-qr-refresh');
if(btn)btn.textContent='\u5df2\u8fc7\u671f\uff0c\u70b9\u51fb\u5237\u65b0';
},300000);
}else{ }else{
h+='<div style=text-align:center;flex-shrink:0>'; h+='<div style=text-align:center;flex-shrink:0>';
h+='<button id=wechat-qr-get class="btn s" style="font-size:14px;padding:8px 18px" onclick="getWechatQR()">\u83b7\u53d6\u767b\u5f55\u4e8c\u7ef4\u7801</button>'; h+='<button id=wechat-qr-get class="btn s" style="font-size:14px;padding:8px 18px" onclick="getWechatQR()">\u83b7\u53d6\u767b\u5f55\u4e8c\u7ef4\u7801</button>';
@@ -682,6 +676,14 @@ function inMd(t){return t.replace(/\*\*([^*]+)\*\*/g,'<strong>$1</strong>').repl
init();loadAll();setInterval(loadAll,10000);setInterval(fK,15000); init();loadAll();setInterval(loadAll,10000);setInterval(fK,15000);
/* --- WeChat QR: 获取二维码(触发容器 /api/bot/login + 刷新 --- */ /* --- WeChat QR: 获取二维码(触发容器 /api/bot/login + 刷新 --- */
function renderWechatQR(qrUrl){
var box=document.getElementById('wechat-qr-get-status');
if(box) box.innerHTML='<img id=wechat-qr-img src="https://api.qrserver.com/v1/create-qr-code/?size=200x200&data='+encodeURIComponent(qrUrl)+'" style="border:2px solid var(--green);border-radius:6px">'
+'<div style="margin-top:6px;font-size:13px;color:var(--dim)">用微信扫描上方二维码登录(约5分钟有效,过期请点下方"刷新二维码"</div>'
+'<button class="btn r" style="margin-top:6px;font-size:13px;padding:3px 10px" onclick="refreshWechatQR()">刷新二维码</button>';
var getBtn=document.getElementById('wechat-qr-get');
if(getBtn) getBtn.style.display='none';
}
async function getWechatQR(){ async function getWechatQR(){
var st=document.getElementById('wechat-qr-get-status'); var st=document.getElementById('wechat-qr-get-status');
var btn=document.getElementById('wechat-qr-get'); var btn=document.getElementById('wechat-qr-get');
@@ -697,7 +699,7 @@ async function getWechatQR(){
await new Promise(res=>setTimeout(res,2000)); await new Promise(res=>setTimeout(res,2000));
try{ try{
var rs=await fetch('/api/wechat/status'),sd=await rs.json(); 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){} }catch(e){}
} }
if(st)st.innerHTML='<span style=color:var(--red)>\u4e8c\u7ef4\u7801\u672a\u751f\u6210\uff0c\u8bf7\u91cd\u8bd5</span>'; if(st)st.innerHTML='<span style=color:var(--red)>\u4e8c\u7ef4\u7801\u672a\u751f\u6210\uff0c\u8bf7\u91cd\u8bd5</span>';
@@ -712,10 +714,17 @@ async function getWechatQR(){
} }
} }
async function refreshWechatQR(){ async function refreshWechatQR(){
var st=document.getElementById('wechat-qr-get-status');
if(st && !document.getElementById('wechat-qr-img')) st.innerHTML='<span style=color:var(--yellow)>正在刷新二维码...</span>';
try{ try{
await fetch('/api/wechat/trigger-login',{method:'POST'}); await fetch('/api/wechat/trigger-login',{method:'POST'});
// 刷新后等几秒重新拉状态 for(var i=0;i<10;i++){
setTimeout(function(){location.reload();},3000); 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){} }catch(e){}
} }
</script></body></html> </script></body></html>