feat: show time-close countdown after symbol in monitor area
Move timed-close badge next to contract name on hub board and instance position cards; refresh countdown on board render. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1495,6 +1495,9 @@
|
||||
}
|
||||
syncMonitorGridColumns(box, displayRows.length);
|
||||
bindMonitorInteractions(box);
|
||||
if (window.TimeCloseUI && TimeCloseUI.tickLocalCountdowns) {
|
||||
TimeCloseUI.tickLocalCountdowns();
|
||||
}
|
||||
|
||||
if (expandedExchangeId && fs && fsInner) {
|
||||
const row = rows.find((r) => String(r.id) === String(expandedExchangeId));
|
||||
@@ -1505,6 +1508,9 @@
|
||||
fs.setAttribute("aria-hidden", "false");
|
||||
document.body.classList.add("hub-fullscreen-open");
|
||||
bindMonitorInteractions(fsInner);
|
||||
if (window.TimeCloseUI && TimeCloseUI.tickLocalCountdowns) {
|
||||
TimeCloseUI.tickLocalCountdowns();
|
||||
}
|
||||
fsInner.querySelectorAll(".btn-expand-back").forEach((btn) => {
|
||||
btn.onclick = (ev) => {
|
||||
ev.stopPropagation();
|
||||
@@ -2073,6 +2079,17 @@
|
||||
return html;
|
||||
}
|
||||
|
||||
function timeCloseSymbolBadgeHtml(item) {
|
||||
if (!item || !item.time_close_enabled) return "";
|
||||
const tcLabel = item.time_close_label || `时间平仓 ${item.time_close_hours || ""}h`;
|
||||
const tcCd = item.time_close_countdown || "--:--:--";
|
||||
const tcAt = item.time_close_at_ms != null ? String(item.time_close_at_ms) : "";
|
||||
return (
|
||||
`<span class="pos-symbol-time-close pos-time-close-meta pos-meta-on" data-close-at-ms="${esc(tcAt)}">` +
|
||||
`${esc(tcLabel)} · <span class="pos-time-close-cd">${esc(tcCd)}</span></span>`
|
||||
);
|
||||
}
|
||||
|
||||
function renderTrendDcaTable(t, tickMap) {
|
||||
const levels = resolveTrendDcaLevels(t);
|
||||
if (!levels.length) return "";
|
||||
@@ -2304,26 +2321,18 @@
|
||||
meta.push(
|
||||
`<span class="${beOn ? "pos-meta-on" : "pos-meta-off"}">移动保本:${beOn ? "开" : "关"}</span>`
|
||||
);
|
||||
if (mo.time_close_enabled) {
|
||||
const tcLabel = mo.time_close_label || `时间平仓 ${mo.time_close_hours || ""}h`;
|
||||
const tcCd = mo.time_close_countdown || "--:--:--";
|
||||
const tcAt = mo.time_close_at_ms != null ? String(mo.time_close_at_ms) : "";
|
||||
meta.push(
|
||||
`<span class="pos-meta-item pos-meta-on pos-time-close-meta" data-close-at-ms="${esc(tcAt)}">` +
|
||||
`${esc(tcLabel)} · 倒计时 <span class="pos-time-close-cd">${esc(tcCd)}</span></span>`
|
||||
);
|
||||
}
|
||||
} else {
|
||||
meta.push("来源: 交易所持仓");
|
||||
meta.push("风格: —");
|
||||
meta.push(`<span class="pos-meta-off">移动保本:关</span>`);
|
||||
}
|
||||
const symBeBadge = beSecured ? ` ${breakevenBadgeHtml()}` : "";
|
||||
const tcSymBadge = !isTrend && mo.time_close_enabled ? timeCloseSymbolBadgeHtml(mo) : "";
|
||||
const mktAttrs = marketOpenBtnAttrs(exchangeId, exchangeKey, symbol, pos, monitorOrder, trendPlan);
|
||||
return `<div class="pos-card hub-pos-card">
|
||||
<div class="pos-card-head">
|
||||
<div class="pos-card-symbol">
|
||||
<button type="button" class="btn-open-market sym-link pos-symbol-link" ${mktAttrs} title="打开行情区(含入场/止盈止损)"><strong>${esc(symbol)}</strong></button>${symBeBadge}
|
||||
<button type="button" class="btn-open-market sym-link pos-symbol-link" ${mktAttrs} title="打开行情区(含入场/止盈止损)"><strong>${esc(symbol)}</strong></button>${tcSymBadge}${symBeBadge}
|
||||
<span class="pos-side-badge ${sideCls}">${sideCn}</span>
|
||||
</div>
|
||||
<div class="pos-head-actions">
|
||||
@@ -2382,8 +2391,14 @@
|
||||
const amtLine = amtTxt
|
||||
? `<div class="hub-mini-line">挂单数量 ${esc(amtTxt)}</div>`
|
||||
: "";
|
||||
const keyTc =
|
||||
k.time_close_enabled && k.time_close_at_ms
|
||||
? timeCloseSymbolBadgeHtml(k)
|
||||
: k.time_close_enabled && k.time_close_hours
|
||||
? `<span class="pos-symbol-time-close pos-meta-on">时间平仓 ${esc(k.time_close_hours)}h</span>`
|
||||
: "";
|
||||
return `<div class="${cardCls}">
|
||||
<div class="hub-mini-title">${esc(k.symbol)} · ${esc(mt)}${dir} ${pendingTag}</div>
|
||||
<div class="hub-mini-title">${esc(k.symbol)} ${keyTc} · ${esc(mt)}${dir} ${pendingTag}</div>
|
||||
<div class="hub-mini-line">上沿 ${esc(k.upper)} / 下沿 ${esc(k.lower)}</div>
|
||||
${amtLine}
|
||||
<div class="hub-mini-line hub-key-status-line">${esc(kp.gate_summary || kp.price_display || kp.price || "—")}${kp.gate_metrics ? ` · ${esc(kp.gate_metrics)}` : ""}</div>
|
||||
@@ -2398,8 +2413,9 @@
|
||||
return orders
|
||||
.map((o) => {
|
||||
const sym = o.exchange_symbol || o.symbol || "";
|
||||
const tcBadge = o.time_close_enabled ? timeCloseSymbolBadgeHtml(o) : "";
|
||||
return `<div class="hub-mini-card">
|
||||
<div class="hub-mini-title">#${esc(o.id)} · ${esc(o.symbol || o.exchange_symbol)} · ${renderDirectionHtml(o.direction)}</div>
|
||||
<div class="hub-mini-title">#${esc(o.id)} · ${esc(o.symbol || o.exchange_symbol)} ${tcBadge} · ${renderDirectionHtml(o.direction)}</div>
|
||||
<div class="hub-mini-line">触发 ${fmtSymbolPrice(o.trigger_price, sym, tickMap)} · SL ${fmtSymbolPrice(o.stop_loss, sym, tickMap)} · TP ${fmtSymbolPrice(o.take_profit, sym, tickMap)} · ${esc(o.trade_style || o.monitor_type || "下单监控")}</div>
|
||||
</div>`;
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user