Procházet zdrojové kódy

feat(mode_workflow): 自建确认弹框 uiConfirm 替换浏览器原生 confirm(搜全部达标/解构全部已采纳)

刘文武 před 5 dny
rodič
revize
dd846b95f7
1 změnil soubory, kde provedl 36 přidání a 3 odebrání
  1. 36 3
      examples/mode_workflow/index.html

+ 36 - 3
examples/mode_workflow/index.html

@@ -2080,6 +2080,10 @@
       .qr-thr-lab { color:#666; font-size:12px; }
       .qr-thr-lab { color:#666; font-size:12px; }
       .qr-thr { width:46px; padding:3px 5px; border:1px solid #ddd; border-radius:6px; font-size:12px; }
       .qr-thr { width:46px; padding:3px 5px; border:1px solid #ddd; border-radius:6px; font-size:12px; }
       #qr-score:disabled { opacity:.6; cursor:wait; }
       #qr-score:disabled { opacity:.6; cursor:wait; }
+      .ui-confirm-bg { position:fixed; inset:0; background:rgba(0,0,0,.38); z-index:200; display:flex; align-items:center; justify-content:center; }
+      .ui-confirm { background:#fff; border-radius:14px; box-shadow:0 14px 50px rgba(0,0,0,.28); width:400px; max-width:92vw; padding:22px 24px; }
+      .ui-confirm-msg { font-size:14px; color:#1a1a1a; line-height:1.6; white-space:pre-line; margin-bottom:18px; }
+      .ui-confirm-acts { display:flex; justify-content:flex-end; gap:10px; }
       .qr-dims { padding:8px 20px 10px; max-height:32vh; overflow:auto; border-bottom:1px solid #f0f0f0; }
       .qr-dims { padding:8px 20px 10px; max-height:32vh; overflow:auto; border-bottom:1px solid #f0f0f0; }
       .qr-row { display:flex; align-items:flex-start; gap:10px; padding:4px 0; }
       .qr-row { display:flex; align-items:flex-start; gap:10px; padding:4px 0; }
       .qr-row + .qr-row { border-top:1px solid #f6f6f6; }
       .qr-row + .qr-row { border-top:1px solid #f6f6f6; }
@@ -2933,11 +2937,11 @@
         ea.textContent = `解构全部已采纳(${adoptedN})`;
         ea.textContent = `解构全部已采纳(${adoptedN})`;
       }
       }
       $("#btn-batch").onclick = () => state.selected.size && startExtract([...state.selected]);
       $("#btn-batch").onclick = () => state.selected.size && startExtract([...state.selected]);
-      $("#btn-extract-adopted").onclick = () => {
+      $("#btn-extract-adopted").onclick = async () => {
         const cids = (state.posts || []).filter((p) => p.adopted).map((p) => p.case_id);
         const cids = (state.posts || []).filter((p) => p.adopted).map((p) => p.case_id);
         if (!cids.length) return toast("当前 query 下没有已采纳的帖子", "warn");
         if (!cids.length) return toast("当前 query 下没有已采纳的帖子", "warn");
         const dir = state.mode === "process" ? "工序" : "工具";
         const dir = state.mode === "process" ? "工序" : "工具";
-        if (!confirm(`对该 query 下全部 ${cids.length} 个已采纳帖做${dir}解构?\n已解构过的会自动跳过/复用,不重复花钱。`)) return;
+        if (!(await uiConfirm(`对该 query 下全部 ${cids.length} 个已采纳帖做${dir}解构?\n已解构过的会自动跳过/复用,不重复花钱。`))) return;
         startExtract(cids);   // 复用:认领锁 + 解构去重 + showTask 轮询
         startExtract(cids);   // 复用:认领锁 + 解构去重 + showTask 轮询
       };
       };
 
 
@@ -3668,6 +3672,35 @@
       /* ════ 任务面板(✕ 只隐藏;「操作日志」按钮可随时唤回)════ */
       /* ════ 任务面板(✕ 只隐藏;「操作日志」按钮可随时唤回)════ */
       let pollTimer = null,
       let pollTimer = null,
         hasTask = false;
         hasTask = false;
+      // 自建确认弹框(替代浏览器原生 confirm):返回 Promise<bool>。Enter=确定 / Esc=取消 / 点遮罩=取消
+      function uiConfirm(message, opt = {}) {
+        const { okText = "确定", cancelText = "取消" } = opt;
+        return new Promise((resolve) => {
+          const bg = document.createElement("div");
+          bg.className = "ui-confirm-bg";
+          bg.innerHTML =
+            '<div class="ui-confirm"><div class="ui-confirm-msg"></div>'
+            + '<div class="ui-confirm-acts">'
+            + '<button class="btn" data-act="cancel"></button>'
+            + '<button class="btn seal" data-act="ok"></button></div></div>';
+          bg.querySelector(".ui-confirm-msg").textContent = message;
+          bg.querySelector('[data-act="cancel"]').textContent = cancelText;
+          bg.querySelector('[data-act="ok"]').textContent = okText;
+          document.body.appendChild(bg);
+          const done = (v) => { bg.remove(); document.removeEventListener("keydown", onKey, true); resolve(v); };
+          bg.addEventListener("click", (e) => {
+            if (e.target === bg) return done(false);
+            const a = e.target.closest("[data-act]");
+            if (a) done(a.dataset.act === "ok");
+          });
+          const onKey = (e) => {
+            if (e.key === "Escape") { e.preventDefault(); done(false); }
+            else if (e.key === "Enter") { e.preventDefault(); done(true); }
+          };
+          document.addEventListener("keydown", onKey, true);
+          bg.querySelector('[data-act="ok"]').focus();
+        });
+      }
       function showTask(title, taskId, onDone, onSettled) {
       function showTask(title, taskId, onDone, onSettled) {
         hasTask = true;
         hasTask = true;
         $("#task-panel").hidden = false;
         $("#task-panel").hidden = false;
@@ -3987,7 +4020,7 @@
       $("#qr-search-all").onclick = async () => {
       $("#qr-search-all").onclick = async () => {
         const keeps = Object.entries(qrState.scores || {}).filter(([, v]) => qrKeep(v));
         const keeps = Object.entries(qrState.scores || {}).filter(([, v]) => qrKeep(v));
         if (!keeps.length) return;
         if (!keeps.length) return;
-        if (!confirm(`将对 ${keeps.length} 个达标 query 各起一次搜索(小红书+公众号 各20),确认?`)) return;
+        if (!(await uiConfirm(`将对 ${keeps.length} 个达标 query 各起一次搜索(小红书+公众号 各20),确认?`))) return;
         qrClosePop();
         qrClosePop();
         const items = [];
         const items = [];
         for (const [, v] of keeps) {
         for (const [, v] of keeps) {