// 微信绑定 modal(ClawBot 扫码,DESIGN §8.7):扫码绑定 + 自检发送 + 解绑。 // 左侧 rail「微信」按钮触发。后端:POST /v1/wechat/bind/qrcode、GET /v1/wechat/bind/status、 // GET /v1/wechat/bind、DELETE /v1/wechat/bind、POST /v1/wechat/test。 import { $ } from "./dom.js"; import { api } from "./api.js"; let _polling = false; const sleep = (ms) => new Promise((r) => setTimeout(r, ms)); function setState(cls, msg) { const el = $("wx-state"); el.className = "wx-status " + cls; el.textContent = msg; } async function refresh() { try { const b = await api("GET", "/v1/wechat/bind"); if (b.bound) { const push = b.can_push ? "可主动推送" : "需在微信里发条消息以开启主动推送"; setState("ok", "已绑定" + (b.user_im_id ? "" : "(待首次开口)") + " · " + push); $("wx-test").disabled = false; $("wx-unbind").disabled = false; } else { setState("wait", "尚未绑定。点「绑定」生成二维码,用手机微信扫。"); $("wx-test").disabled = true; $("wx-unbind").disabled = true; } } catch (e) { setState("err", "查询失败: " + e.message + "(确认已上 migration 0012 + 开 ZCBOT_WECHAT_BOT_ENABLED)"); $("wx-test").disabled = true; $("wx-unbind").disabled = true; } } function openWechatModal() { $("wechat-modal").classList.add("show"); $("wx-qrbox").hidden = true; refresh(); refreshWecom(); } // ───── 企业微信(仅推送)───── function setWc(cls, msg) { const el = $("wc-state"); el.className = "wx-status " + cls; el.textContent = msg; } async function refreshWecom() { try { const b = await api("GET", "/v1/wecom/bind"); if (!b.configured) { setWc("wait", "未配置:管理员需建自建应用 + 配 WECOM_CORPID/AGENTID/SECRET。"); $("wc-bind").disabled = true; $("wc-test").disabled = true; $("wc-unbind").disabled = true; return; } $("wc-bind").disabled = false; if (b.bound) { setWc("ok", "已绑定 · 成员 " + (b.wecom_userid || "")); $("wc-test").disabled = false; $("wc-unbind").disabled = false; } else { setWc("wait", "未绑定。点「绑定企业微信」扫码授权。"); $("wc-test").disabled = true; $("wc-unbind").disabled = true; } } catch (e) { setWc("err", "查询失败: " + e.message); } } async function wecomBind() { $("wc-bind").disabled = true; try { const r = await api("GET", "/v1/wecom/oauth/url"); window.open(r.authorize_url, "_blank"); setWc("wait", "已打开授权页…扫码 / 确认后会自动刷新(也可手动重开本面板)。"); for (let i = 0; i < 30; i++) { // 轮询绑定结果 ~60s await sleep(2000); try { const b = await api("GET", "/v1/wecom/bind"); if (b.bound) { await refreshWecom(); return; } } catch (e) { /* 继续轮询 */ } } await refreshWecom(); } catch (e) { setWc("err", "绑定出错: " + e.message); } finally { $("wc-bind").disabled = false; } } export function closeWechatModal() { _polling = false; $("wechat-modal").classList.remove("show"); } async function bindFlow() { if (_polling) return; _polling = true; $("wx-bind").disabled = true; try { while (_polling) { // 二维码过期自动换新 const q = await api("POST", "/v1/wechat/bind/qrcode"); $("wx-qrimg").src = q.qr_png; $("wx-qrbox").hidden = false; setState("wait", "等待扫码…(二维码约 1 分钟过期,会自动换新)"); let expired = false; while (_polling && !expired) { let s; try { s = await api("GET", "/v1/wechat/bind/status?qrcode_id=" + encodeURIComponent(q.qrcode_id)); } catch (e) { await sleep(2000); continue; } if (s.status === "confirmed") { _polling = false; $("wx-qrbox").hidden = true; setState("ok", "绑定成功!去微信「微信 ClawBot」发句话试试。"); await refresh(); return; } if (s.status === "expired") { expired = true; break; } await sleep(1000); } } } catch (e) { setState("err", "绑定出错: " + e.message); } finally { _polling = false; $("wx-bind").disabled = false; } } // ───── 顶层绑定 ───── $("hd-wechat").onclick = openWechatModal; $("wx-close").onclick = closeWechatModal; $("wechat-modal").addEventListener("click", (e) => { if (e.target.id === "wechat-modal") closeWechatModal(); // 点遮罩关闭 }); $("wx-bind").onclick = bindFlow; $("wx-unbind").onclick = async () => { _polling = false; if (!confirm("确定解绑微信?")) return; try { await api("DELETE", "/v1/wechat/bind"); $("wx-qrbox").hidden = true; await refresh(); } catch (e) { setState("err", "解绑失败: " + e.message); } }; $("wx-test").onclick = async () => { $("wx-test").disabled = true; try { const r = await api("POST", "/v1/wechat/test"); if (r.ok) setState("ok", "测试消息已发送,去微信查收。"); else setState("err", "推送未送达(" + r.reason + ")。多半是超 24h 没在微信互动:发条消息再试。"); } catch (e) { setState("err", "测试失败: " + e.message); } finally { $("wx-test").disabled = false; } }; $("wc-bind").onclick = wecomBind; $("wc-unbind").onclick = async () => { if (!confirm("确定解绑企业微信?")) return; try { await api("DELETE", "/v1/wecom/bind"); await refreshWecom(); } catch (e) { setWc("err", "解绑失败: " + e.message); } }; $("wc-test").onclick = async () => { $("wc-test").disabled = true; try { const r = await api("POST", "/v1/wecom/test"); if (r.ok) setWc("ok", "测试消息已发送,去企业微信查收。"); else setWc("err", "推送未送达(" + r.reason + ")。"); } catch (e) { setWc("err", "测试失败: " + e.message); } finally { $("wc-test").disabled = false; } };