条件单列表改为中控后台并行缓存并以 SSE 推浏览器,下发仍走中控到实例。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-10-07 14:50:52 +08:00
parent 1c68493aa0
commit 5ffcee3f56
6 changed files with 444 additions and 55 deletions
+96 -10
View File
@@ -117,7 +117,7 @@
});
const dd = await rr.json();
alert(dd.msg || (dd.ok ? "已取消" : "失败"));
refresh();
requestCondRefresh();
});
});
box.querySelectorAll("[data-exit]").forEach(function (btn) {
@@ -148,7 +148,7 @@
});
const dd = await rr.json();
alert(dd.msg || (dd.ok ? "已更新" : "失败"));
refresh();
requestCondRefresh();
});
});
}
@@ -414,13 +414,25 @@
fillOrderBox(document.getElementById("cond-list-done"), lastDone, "暂无已结束的条件单", "done");
}
async function loadOrders() {
let condVersion = 0;
let condLoading = false;
let condEventSource = null;
let condReconnectTimer = null;
function setCondStatus(msg) {
const el = document.getElementById("cond-status");
if (el) el.textContent = msg || "";
}
async function loadOrders(opts) {
opts = opts || {};
const activeBox = document.getElementById("cond-list-active");
const doneBox = document.getElementById("cond-list-done");
if (!activeBox && !doneBox) return;
const r = await fetch("/api/cond_orders");
const r = await fetch("/api/cond_orders", { credentials: "same-origin" });
const d = await r.json();
const list = d.orders || [];
condVersion = Number(d.cond_version) || condVersion;
lastActive = [];
lastDone = [];
list.forEach(function (o) {
@@ -428,6 +440,19 @@
else lastDone.push(o);
});
paintCachedOrders();
if (!opts.silent) {
const live = condEventSource && condEventSource.readyState === 1;
const sec = Number(d.poll_interval_sec) || 10;
setCondStatus(
(live ? "SSE 已连接 · " : "") +
"进行中 " +
lastActive.length +
" · 已结束 " +
lastDone.length +
(d.updated_at ? " · " + d.updated_at : "") +
(d.refreshing ? " · 后台拉取中" : " · 后台每 " + sec + "s 并行拉")
);
}
}
async function createOrder() {
@@ -467,16 +492,72 @@
const tog = document.getElementById("cond-add-toggle");
if (tog) tog.checked = false;
}
refresh();
requestCondRefresh();
}
async function refresh() {
await Promise.all([loadCandidates(), loadOrders()]);
async function refresh(opts) {
opts = opts || {};
if (condLoading) return;
condLoading = true;
if (!opts.silent) setCondStatus("读取缓存…");
try {
await Promise.all([loadCandidates(), loadOrders({ silent: !!opts.silent })]);
} finally {
condLoading = false;
}
}
async function requestCondRefresh() {
try {
await fetch("/api/cond_orders/refresh", {
method: "POST",
credentials: "same-origin",
});
} catch (_) {}
refresh({ silent: true });
}
function closeCondStream() {
if (condEventSource) {
condEventSource.close();
condEventSource = null;
}
if (condReconnectTimer) {
clearTimeout(condReconnectTimer);
condReconnectTimer = null;
}
}
function connectCondStream() {
if (typeof EventSource === "undefined") return;
closeCondStream();
condEventSource = new EventSource("/api/cond_orders/stream");
condEventSource.addEventListener("cond", function (ev) {
try {
const st = JSON.parse(ev.data || "{}");
const ver = Number(st.cond_version) || 0;
if (ver && ver !== condVersion) {
refresh({ silent: true });
} else if (st.refreshing) {
setCondStatus("后台并行拉取条件单…");
}
} catch (_) {}
});
condEventSource.onerror = function () {
closeCondStream();
setCondStatus("SSE 断开,8s 后重连…");
condReconnectTimer = setTimeout(function () {
connectCondStream();
refresh({ silent: true });
}, 8000);
};
}
function boot() {
const btn = document.getElementById("btn-cond-refresh");
if (btn) btn.addEventListener("click", refresh);
if (btn) btn.addEventListener("click", function () {
requestCondRefresh();
});
const create = document.getElementById("btn-cond-create");
if (create) create.addEventListener("click", createOrder);
const typeEl = document.getElementById("cf-opt-type");
@@ -484,9 +565,14 @@
if (typeEl) typeEl.addEventListener("change", syncTriggerHint);
if (pxEl) pxEl.addEventListener("input", syncTriggerHint);
syncTriggerHint();
// 读缓存秒开 + SSE;不再前端定时现场拉实例
refresh();
setInterval(refresh, 10000);
connectCondStream();
}
global.HubCondOrders = { boot: boot, refresh: refresh };
global.HubCondOrders = {
boot: boot,
refresh: refresh,
requestRefresh: requestCondRefresh,
};
})(window);