fix(options): soft-poll chain quotes so list asks stay fresh

SSE only refreshed positions; chain asks were one-shot until manual reload, which could mislead open decisions.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-08-11 11:21:30 +08:00
parent c514a75026
commit 24bb8532c4
2 changed files with 47 additions and 4 deletions
+46 -3
View File
@@ -37,9 +37,14 @@
let selectSeq = 0;
let refreshAllTimer = null;
let pendingRefreshTimer = null;
let chainSoftTimer = null;
let lastChainSoftAt = 0;
let chainQuotedAt = 0;
let pendingTtlSeconds = 600;
const POSITIONS_STALE_MS = 45000;
const PENDING_POLL_MS = 8000;
/** 链卖一/买一静默刷新节流:无推送,靠拉;过密会撞 OKX 50011 */
const CHAIN_SOFT_POLL_MS = 15000;
const orderPanelHome = (function () {
const host = document.getElementById("opt-order-panel-host");
return host ? host.parentElement : null;
@@ -632,6 +637,15 @@
if (el) el.textContent = fmt(buf, 2);
}
function fmtChainQuotedAt() {
if (!chainQuotedAt) return "";
const d = new Date(chainQuotedAt);
const pad = function (n) {
return n < 10 ? "0" + n : String(n);
};
return pad(d.getHours()) + ":" + pad(d.getMinutes()) + ":" + pad(d.getSeconds());
}
function renderIndexLine() {
const idx = state.chain && state.chain.index_px;
const dte = state.chain && state.chain.chain_max_dte_days;
@@ -645,12 +659,36 @@
const line = document.getElementById("opt-index-line");
if (line) {
const liqHint = askLiqFilterOn() ? "仅显示卖一深度≥1张" : "显示全部卖一(含估算~)";
const ageHint = chainQuotedAt ? " · 链报价 " + fmtChainQuotedAt() + "(约每15s静默刷新)" : "";
line.textContent =
"指数 " + state.underlying + " ≈ " + fmt(idx, 2) +
" · 默认最近一期 · " + liqHint + " · 实值含平值 · 虚值=价外";
" · 默认最近一期 · " + liqHint + " · 实值含平值 · 虚值=价外" + ageHint;
}
}
function softRefreshChainThrottled(force) {
if (document.hidden) return;
if (!document.getElementById("options-root")) return;
const now = Date.now();
if (!force && now - lastChainSoftAt < CHAIN_SOFT_POLL_MS) return;
lastChainSoftAt = now;
void loadChain({ soft: true });
}
function startChainSoftPoll() {
if (chainSoftTimer) return;
chainSoftTimer = setInterval(function () {
if (!document.getElementById("options-root")) {
if (chainSoftTimer) {
clearInterval(chainSoftTimer);
chainSoftTimer = null;
}
return;
}
softRefreshChainThrottled(false);
}, CHAIN_SOFT_POLL_MS);
}
function pickNearestExpiry(exps) {
if (!exps || !exps.length) return "";
const now = Date.now();
@@ -1269,6 +1307,8 @@
panelCache.chain = d;
panelCache.underlying = uly;
panelCache.optType = state.optType;
chainQuotedAt = Date.now();
lastChainSoftAt = chainQuotedAt;
syncAskLiqFilterFromChain(d);
if (!soft) {
state.selectedInst = null;
@@ -2206,6 +2246,7 @@
updateUnderlyingLabel();
refreshPendingOrders();
startPendingOrdersPoll();
startChainSoftPoll();
const hasCache =
chainHasExpiries(panelCache.chain) &&
panelCache.underlying === state.underlying &&
@@ -2215,8 +2256,8 @@
renderExpiries();
renderStrikes();
refreshAllPositions();
// 后台静默刷新,避免缓存过期后到期日变空
loadChain({ soft: true });
// 后台静默刷新,避免缓存过期后到期日变空 / 卖一过期
softRefreshChainThrottled(true);
return;
}
requestAnimationFrame(function () {
@@ -2340,6 +2381,8 @@
window.OptionsPanelLive = {
refreshSoft: function () {
refreshAllPositions();
// embed SSE 只通知「该拉了」,不推送链报价;这里节流拉新鲜卖一/买一
softRefreshChainThrottled(false);
},
refreshChain: loadChain,
};
+1 -1
View File
@@ -322,4 +322,4 @@
</div>
</div>
<script src="/static/options_expiry_countdown.js?v=1"></script>
<script src="/static/options_panel.js?v=56"></script>
<script src="/static/options_panel.js?v=57"></script>