Files
kefu/deploy/review-assistant-20260917/production-js.diff
T
2026-09-21 10:34:06 +08:00

65 lines
19 KiB
Diff
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
--- C:\wechat_rpa\backups\review-assistant-20260917\assets\ui\console-app.js
+++ C:\wechat_rpa\assets\ui\console-app.js
@@ -507,6 +507,27 @@
</section>`;
}
+function reviewAssistantPanel(a){
+ const r = a.reviewAssistant || {};
+ const recipient = r.recipient || {};
+ const busy = Boolean(r.busy);
+ const canChoose = r.ready && !busy;
+ const canToggle = canChoose && (recipient.id || r.enabled);
+ return `<section class="panel panel-pad" style="margin:16px 0"><div class="panel-title"><h2>医疗助理审核提醒</h2><span class="badge ${r.enabled ? "green" : ""}">${r.enabled ? "当前账号已开启" : "当前账号未开启"}</span></div>
+ <p>客户会话进入待审核时,由当前托管企业微信账号向指定助理的私人微信发送客户咨询、待发送回复和审核原因。</p>
+ <div class="setting-line"><span>托管企微账号(最近核验)</span><strong>${esc(r.accountName || "尚未核验")}</strong>${r.accountId ? `<small>${esc(r.accountId)}</small>` : ""}</div>
+ <div class="setting-line"><span>助理私人微信</span><div style="flex:1;text-align:right"><strong>${esc(recipient.name || "尚未选择")}</strong>${recipient.label ? `<div class="tiny">${esc(recipient.label)}</div>` : ""}</div></div>
+ <div class="toolbar" style="margin:12px 0;flex-wrap:wrap"><button class="btn small" data-action="review-assistant-refresh" ${!r.supported || busy ? "disabled" : ""}>${icon("refresh")}${busy ? "正在核验…" : "读取当前账号"}</button>
+ <button class="btn small blue" data-action="review-assistant-choose" ${canChoose ? "" : "disabled"}>${recipient.id ? "更换助理联系人" : "选择助理联系人"}</button>
+ <span style="margin-left:auto">开启审核提醒</span><button class="switch ${r.enabled ? "on" : ""}" role="switch" aria-label="开启医疗助理审核提醒" aria-checked="${Boolean(r.enabled)}" data-action="review-assistant-toggle" ${canToggle ? "" : "disabled"}></button></div>
+ ${r.reason ? `<p class="tiny" style="color:var(--orange)">${esc(r.reason)}</p>` : ""}
+ ${r.message ? `<p class="tiny" role="status">${esc(r.message)}</p>` : ""}
+ ${r.notification && r.notification.message ? `<p class="tiny">最近提醒(读取账号时刷新):${esc(r.notification.message)}</p>` : ""}
+ <p class="tiny">设置按企微账号分别保存。选择或更换联系人后默认关闭,确认收件人后再开启;同名联系人按列表中的联系编号区分。</p>
+ <p class="tiny">人工用同一企业微信账号直接回复客户后结束本次审核;后续自动回复仍逐条风控。此识别以账号发出的消息为准,不区分手机或电脑。在助理私人微信回复提醒,不会解除客户审核。</p>
+ <details style="margin-top:12px"><summary style="cursor:pointer">提醒内容示例(只读,不会发送)</summary><pre style="white-space:pre-wrap;word-break:break-word;margin:12px 0 0;font:inherit;font-size:12px">${esc(r.preview || "请先读取当前账号")}</pre></details></section>`;
+}
+
automationView = function(){
if (STATE.demo) return _automationView();
const a = STATE.automation || {};
@@ -517,13 +538,13 @@
const ready = p.canSend === true && p.status === "native_ready" && p.databaseReady === true;
return `<div class="screen">${head("自动化设置","协议模式 · 保留原员工账号与现有客户会话",`<button class="btn primary" data-action="save-automation">${icon("save")}保存设置</button>`)}${transportPanel}
<div class="tabs"><button class="tab ${autoOn?"active":""}" data-action="send-mode" data-key="auto">自动发送</button><button class="tab ${autoOn?"":"active"}" data-action="send-mode" data-key="review">审核后发送</button></div>
- <section class="panel panel-pad"><div class="panel-title"><h2>${ready?"协议自动回复已就绪":"协议模式尚未就绪"}</h2><span class="badge ${ready?"green":"orange"}">${esc(ready?"原账号文本单聊":p.label || "正在准备检测")}</span></div>
+ ${reviewAssistantPanel(a)}<section class="panel panel-pad"><div class="panel-title"><h2>${ready?"协议自动回复已就绪":"协议模式尚未就绪"}</h2><span class="badge ${ready?"green":"orange"}">${esc(ready?"原账号文本单聊":p.label || "正在准备检测")}</span></div>
<p>启动后监听新到的文本消息,使用当前员工账号回复现有客户。审核模式下,回复保留在任务队列,点击“通过并发送”后发送。</p>
<div class="form-grid"><label class="flow-pill">监听间隔 <input class="num" id="auto-poll" type="number" min="0.2" max="300" step="0.1" value="${esc(a.poll ?? 2)}"> 秒</label><label class="flow-pill">连续消息等待 <input class="num" id="auto-batch" type="number" min="1" max="120" value="${esc(a.batch ?? 20)}"> 秒</label><label class="flow-pill">发送前等待 <input class="num" id="auto-delay" type="number" min="0" max="30" step="0.5" value="${esc(a.delay ?? 1)}"> 秒</label></div>
<p class="tiny">支持 ${esc(p.supportedClient || "5.0.10.6023 x86、5.0.11.6018 x86")}。自动识别安装盘符和目录;其他企业微信版本、x64 客户端仍需单独适配。当前自动处理文本消息。</p></section>
- <section class="panel panel-pad" style="margin-top:16px"><div class="panel-title"><h2>发送核对</h2><button class="btn small blue" data-action="security-rules">审核规则</button></div><p>客户补充消息时重新生成回复;人工已经回复时取消旧任务。发送结果不明确时暂停监听并保留记录,防止重复发送。</p><p class="tiny">协议模式按会话 ID 发送,不操作聊天窗口。切换账号或升级企业微信后,会重新校验可用性。</p></section></div>`;
- }
- return `<div class="screen">${head("自动化设置","配置企业微信监听、消息合并与自动发送规则",`<span class="btn"><i class="led"></i>${esc(a.wecom || "企业微信未识别")}</span><span class="btn"><i class="led"></i>规则已生效</span><button class="btn primary" data-action="save-automation">${icon("save")}保存设置</button>`)}${transportPanel}<div class="tabs"><button class="tab ${autoOn?"active":""}" data-action="send-mode" data-key="auto">${icon("send")} 自动发送</button><button class="tab ${autoOn?"":"active"}" data-action="send-mode" data-key="review">${icon("users")} 审核后发送</button></div><div class="automation-top"><section class="panel panel-pad"><div class="panel-title"><h2>监听与发送策略</h2></div><span class="badge green">${icon("activity")} ● 规则运行中</span><div class="auto-flow">${[["activity","扫描未读"],["log","提取消息"],["folder","合并消息"],["brain","请求 AI"],["send","回填发送"]].map(x=>`<div class="flow-step"><div class="flow-circle">${icon(x[0])}</div><strong>${x[1]}</strong></div>`).join("")}</div><div class="form-grid"><div class="flow-pill">${icon("clock")}扫描间隔 <input class="num" id="auto-poll" type="number" min="0.2" max="300" step="0.1" value="${esc(a.poll || "2")}"> 秒</div><div class="flow-pill">${icon("hourglass")} 连续消息等待 <input class="num" id="auto-batch" type="number" min="1" max="120" step="1" value="${esc(a.batch || "20")}"> 秒</div><div class="flow-pill">${icon("clock")}发送前等待 <input class="num" id="auto-delay" type="number" min="0" max="30" step="0.5" value="${esc(a.delay || "1")}"> 秒</div></div></section><section class="panel panel-pad"><div class="panel-title"><h2>企业微信窗口</h2></div><div class="wechat-graphic"><div class="fake-window"><div class="fake-check">✓</div></div><div class="stack"><div class="row"><span>${icon("clipboard")} 主窗口:</span><b style="color:var(--green)">● ${esc(a.wecom || "未识别")}</b></div><div class="row"><span>${icon("user")} 当前账号:</span><b>${esc(a.account || "—")}</b></div><div class="row"><span>${icon("globe")} DPI:</span><b>${esc(STATE.dpi || "—")}</b></div><div class="row"><span>${icon("monitor")} 最小化恢复:</span><b style="color:var(--green)">● 已开启</b></div></div></div><div class="task-actions"><button class="btn small blue" data-action="redetect">${icon("refresh")}重新检测</button></div></section></div><div class="automation-mid"><section class="panel panel-pad"><div class="panel-title"><h2>人机共存</h2></div><div class="setting-line"><span>启用人工操作保护</span><div class="switch ${a.mouseProtect?"on":""}" data-action="toggle-idle"></div></div><div style="text-align:center;margin-top:8px">鼠标静止 <input class="idle-num" id="auto-idle" type="number" min="0" max="3600" step="0.5" value="${esc(a.idle || "5")}"> 秒 后恢复</div><div class="setting-line" style="margin-top:10px"><span>草稿超时直发</span><div class="switch ${a.draftAutosend > 0 ? "on" : ""}" data-action="toggle-draft-autosend"></div></div><div style="text-align:center;margin-top:6px">输入框里有人工草稿 <input class="idle-num" id="auto-draft-autosend" type="number" min="1" max="1440" step="5" value="${esc(a.draftAutosend > 0 ? a.draftAutosend : 15)}" ${a.draftAutosend > 0 ? "" : "disabled"}> 分钟后直接发出</div><div class="tiny" style="text-align:center;margin-top:4px;color:var(--muted);font-size:11px">关闭时只跳过该会话、绝不动别人写的字;命中审核规则的仍会等人确认</div><div class="mouse-orb"><span style="color:#315fec">${icon("bot")}<br><small>AI 运行中</small></span><div class="mouse-pointer">${icon("cursor")}</div><span style="color:var(--orange)">${icon("pause")}<br><small>检测到人工操作<br>AI 暂停</small></span></div></section><section class="panel panel-pad"><div class="panel-title"><h2>消息处理</h2></div><div class="stack"><div class="setting-line"><span>✓ 同一客户连续消息自动合并</span></div><div class="setting-line"><span>✓ 保留最近 <input class="ai-num" id="auto-context" type="number" min="1" max="50" value="${esc(a.context || 8)}"> 轮上下文</span><span class="badge">${esc(a.context || 8)} 轮</span></div><div class="setting-line"><span>✓ 一次只处理 1 个会话</span><span class="badge">1 个</span></div></div></section><section class="panel panel-pad"><div class="panel-title"><h2>异常与兜底</h2></div><div class="stack"><div class="setting-line"><span style="color:var(--orange)">${icon("clock")}</span><span style="flex:1">AI 超时:${esc(a.timeout || 120)} 秒后重试</span><span class="badge">2 次</span></div><div class="setting-line"><span style="color:var(--orange)">${icon("alert")}</span><span style="flex:1">发送失败:自动重试</span><span class="badge green">已开启</span></div><div class="setting-line"><span style="color:#3c69f4">${icon("message")}</span><span style="flex:1">固定回复:${esc(a.reply || "在的,请稍等")}</span><button class="badge" data-action="edit-reply">编辑</button></div></div></section><section class="panel panel-pad"><div class="panel-title"><h2>高风险转人工</h2><span class="badge green">● 已开启</span></div><div class="risk-tags"><span class="risk-tag">${icon("shield")} 诊断</span><span class="risk-tag">${icon("package")} 用药调整</span><span class="risk-tag">${icon("coins")} 投诉退款</span></div><button class="btn small blue" style="margin:11px auto 0;display:flex" data-action="security-rules">${icon("settings")}规则管理</button></section></div><section class="panel panel-pad check-strip"><div class="panel-title"><h2>启动前检查</h2></div>${statusCells([["check","企业微信已登录", STATE.wecomConnected ? "检查完成" : "等待连接"],["cloud","AI 服务正常","检查完成"],["activity","窗口坐标已校准", STATE.wecomConnected ? "检查完成" : "待校准"],["shield","规则配置有效","检查完成"]])}</section></div>`;
+ <section class="panel panel-pad" style="margin-top:16px"><div class="panel-title"><h2>发送核对</h2><button class="btn small blue" data-action="security-rules">审核规则</button></div><p>客户补充消息时重新生成回复;人工已经回复时取消旧任务。发送结果不明确时保留该会话记录待核对,其他会话继续监听,防止重复发送。</p><p class="tiny">协议模式按会话 ID 发送,不操作聊天窗口。切换账号或升级企业微信后,会重新校验可用性。</p></section></div>`;
+ }
+ return `<div class="screen">${head("自动化设置","配置企业微信监听、消息合并与自动发送规则",`<span class="btn"><i class="led"></i>${esc(a.wecom || "企业微信未识别")}</span><span class="btn"><i class="led"></i>规则已生效</span><button class="btn primary" data-action="save-automation">${icon("save")}保存设置</button>`)}${transportPanel}<div class="tabs"><button class="tab ${autoOn?"active":""}" data-action="send-mode" data-key="auto">${icon("send")} 自动发送</button><button class="tab ${autoOn?"":"active"}" data-action="send-mode" data-key="review">${icon("users")} 审核后发送</button></div>${reviewAssistantPanel(a)}<div class="automation-top"><section class="panel panel-pad"><div class="panel-title"><h2>监听与发送策略</h2></div><span class="badge green">${icon("activity")} ● 规则运行中</span><div class="auto-flow">${[["activity","扫描未读"],["log","提取消息"],["folder","合并消息"],["brain","请求 AI"],["send","回填发送"]].map(x=>`<div class="flow-step"><div class="flow-circle">${icon(x[0])}</div><strong>${x[1]}</strong></div>`).join("")}</div><div class="form-grid"><div class="flow-pill">${icon("clock")}扫描间隔 <input class="num" id="auto-poll" type="number" min="0.2" max="300" step="0.1" value="${esc(a.poll || "2")}"> 秒</div><div class="flow-pill">${icon("hourglass")} 连续消息等待 <input class="num" id="auto-batch" type="number" min="1" max="120" step="1" value="${esc(a.batch || "20")}"> 秒</div><div class="flow-pill">${icon("clock")}发送前等待 <input class="num" id="auto-delay" type="number" min="0" max="30" step="0.5" value="${esc(a.delay || "1")}"> 秒</div></div></section><section class="panel panel-pad"><div class="panel-title"><h2>企业微信窗口</h2></div><div class="wechat-graphic"><div class="fake-window"><div class="fake-check">✓</div></div><div class="stack"><div class="row"><span>${icon("clipboard")} 主窗口:</span><b style="color:var(--green)">● ${esc(a.wecom || "未识别")}</b></div><div class="row"><span>${icon("user")} 当前账号:</span><b>${esc(a.account || "—")}</b></div><div class="row"><span>${icon("globe")} DPI:</span><b>${esc(STATE.dpi || "—")}</b></div><div class="row"><span>${icon("monitor")} 最小化恢复:</span><b style="color:var(--green)">● 已开启</b></div></div></div><div class="task-actions"><button class="btn small blue" data-action="redetect">${icon("refresh")}重新检测</button></div></section></div><div class="automation-mid"><section class="panel panel-pad"><div class="panel-title"><h2>人机共存</h2></div><div class="setting-line"><span>启用人工操作保护</span><div class="switch ${a.mouseProtect?"on":""}" data-action="toggle-idle"></div></div><div style="text-align:center;margin-top:8px">鼠标静止 <input class="idle-num" id="auto-idle" type="number" min="0" max="3600" step="0.5" value="${esc(a.idle || "5")}"> 秒 后恢复</div><div class="setting-line" style="margin-top:10px"><span>草稿超时直发</span><div class="switch ${a.draftAutosend > 0 ? "on" : ""}" data-action="toggle-draft-autosend"></div></div><div style="text-align:center;margin-top:6px">输入框里有人工草稿 <input class="idle-num" id="auto-draft-autosend" type="number" min="1" max="1440" step="5" value="${esc(a.draftAutosend > 0 ? a.draftAutosend : 15)}" ${a.draftAutosend > 0 ? "" : "disabled"}> 分钟后直接发出</div><div class="tiny" style="text-align:center;margin-top:4px;color:var(--muted);font-size:11px">关闭时只跳过该会话、绝不动别人写的字;命中审核规则的仍会等人确认</div><div class="mouse-orb"><span style="color:#315fec">${icon("bot")}<br><small>AI 运行中</small></span><div class="mouse-pointer">${icon("cursor")}</div><span style="color:var(--orange)">${icon("pause")}<br><small>检测到人工操作<br>AI 暂停</small></span></div></section><section class="panel panel-pad"><div class="panel-title"><h2>消息处理</h2></div><div class="stack"><div class="setting-line"><span>✓ 同一客户连续消息自动合并</span></div><div class="setting-line"><span>✓ 保留最近 <input class="ai-num" id="auto-context" type="number" min="1" max="50" value="${esc(a.context || 8)}"> 轮上下文</span><span class="badge">${esc(a.context || 8)} 轮</span></div><div class="setting-line"><span>✓ 一次只处理 1 个会话</span><span class="badge">1 个</span></div></div></section><section class="panel panel-pad"><div class="panel-title"><h2>异常与兜底</h2></div><div class="stack"><div class="setting-line"><span style="color:var(--orange)">${icon("clock")}</span><span style="flex:1">AI 超时:${esc(a.timeout || 120)} 秒后重试</span><span class="badge">2 次</span></div><div class="setting-line"><span style="color:var(--orange)">${icon("alert")}</span><span style="flex:1">发送失败:自动重试</span><span class="badge green">已开启</span></div><div class="setting-line"><span style="color:#3c69f4">${icon("message")}</span><span style="flex:1">固定回复:${esc(a.reply || "在的,请稍等")}</span><button class="badge" data-action="edit-reply">编辑</button></div></div></section><section class="panel panel-pad"><div class="panel-title"><h2>高风险转人工</h2><span class="badge green">● 已开启</span></div><div class="risk-tags"><span class="risk-tag">${icon("shield")} 诊断</span><span class="risk-tag">${icon("package")} 用药调整</span><span class="risk-tag">${icon("coins")} 投诉退款</span></div><button class="btn small blue" style="margin:11px auto 0;display:flex" data-action="security-rules">${icon("settings")}规则管理</button></section></div><section class="panel panel-pad check-strip"><div class="panel-title"><h2>启动前检查</h2></div>${statusCells([["check","企业微信已登录", STATE.wecomConnected ? "检查完成" : "等待连接"],["cloud","AI 服务正常","检查完成"],["activity","窗口坐标已校准", STATE.wecomConnected ? "检查完成" : "待校准"],["shield","规则配置有效","检查完成"]])}</section></div>`;
};
logsView = function(){
@@ -1325,6 +1346,15 @@
"edit-knowledge": () => callBridge("editKnowledge"),
"sync-knowledge": () => callBridge("syncKnowledge"),
"open-data": () => callBridge("openDataDir"),
+ "review-assistant-refresh": () => callBridge("refreshReviewAssistant"),
+ "review-assistant-choose": () => callBridge("chooseReviewAssistant"),
+ "review-assistant-toggle": () => {
+ const r = (STATE.automation || {}).reviewAssistant || {};
+ if (!r.ready || r.busy) return;
+ callBridgeWithFeedback("setReviewAssistantEnabled", [JSON.stringify({expected_account: r.accountId, enabled: !r.enabled})], {
+ pending: "正在核对当前账号与助理联系人…",
+ });
+ },
"save-automation": () => callBridgeWithFeedback(
"saveAutomationSettings", [collectAutomationPayload()], {
button: action, busyLabel: "保存中…",