Merge dashboard KPIs into one compact card.

Put status badge and expand on one row; drop funds footnote, win/loss, and separate options float KPI.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-07-17 14:52:05 +08:00
parent 549d8a015c
commit 89148bb119
4 changed files with 83 additions and 58 deletions
+31 -46
View File
@@ -60,45 +60,31 @@
const floating = Number(totals.float_pnl_u);
const funding = totals.total_funding_usdt;
const trading = totals.total_trading_usdt;
const optionsFloat = Number(totals.options_float_pnl_u);
const optionsPos = totals.options_open_position_count;
elKpi.innerHTML = [
kpiCard("交易日", esc(totals.trading_day || "—"), ""),
kpiCard("平仓盈亏", pnlSigned(closed, 2), pnlClass(closed)),
kpiCard(
"平仓笔数",
`${totals.closed_count || 0}`,
"",
`${totals.win_count || 0} / 负 ${totals.loss_count || 0}`
),
kpiCard("浮盈亏", pnlSigned(floating, 2), pnlClass(floating)),
kpiCard(
"资金合计",
funding != null && trading != null
? `${fmt(Number(funding) + Number(trading), 2)}U`
: "—",
"",
`永续+期权 USDT 等价 · 资金 ${fmt(funding, 2)} + 交易 ${fmt(trading, 2)}`
),
kpiCard(
"实盘持仓",
`${totals.open_position_count || 0}`,
"",
Number.isFinite(optionsPos) && optionsPos > 0 ? `含期权 ${optionsPos}` : ""
),
Number.isFinite(optionsFloat) && Math.abs(optionsFloat) > 1e-9
? kpiCard("期权浮盈", pnlSigned(optionsFloat, 2), pnlClass(optionsFloat))
: "",
]
.filter(Boolean)
.join("");
const funds =
funding != null && trading != null ? Number(funding) + Number(trading) : NaN;
const totalPos = Number(totals.open_position_count) || 0;
const optPos = Number(totals.options_open_position_count) || 0;
const perpPos =
totals.perpetual_open_position_count != null
? Number(totals.perpetual_open_position_count) || 0
: Math.max(0, totalPos - optPos);
const items = [
kpiItem("交易日", esc(totals.trading_day || "—")),
kpiItem("资金合计", Number.isFinite(funds) ? `${fmt(funds, 2)}U` : "—"),
kpiItem("总持仓数量", `${totalPos}`),
kpiItem("期权持仓", `${optPos}`),
kpiItem("永续持仓", `${perpPos}`),
kpiItem("平仓数量", `${totals.closed_count || 0}`),
kpiItem("平仓盈亏", pnlSigned(closed, 2), pnlClass(closed)),
kpiItem("浮盈亏", pnlSigned(floating, 2), pnlClass(floating)),
];
elKpi.innerHTML = `<div class="dash-kpi-summary">${items.join("")}</div>`;
}
function kpiCard(label, value, valCls, sub) {
return `<div class="dash-kpi">
function kpiItem(label, value, valCls) {
return `<div class="dash-kpi-item">
<div class="dash-kpi-label">${esc(label)}</div>
<div class="dash-kpi-value ${valCls || ""}">${value}</div>
${sub ? `<div class="dash-kpi-sub">${esc(sub)}</div>` : ""}
</div>`;
}
@@ -245,17 +231,10 @@
const perpLines = accountPerpLines(ac);
const optionsPositions = Array.isArray(ac && ac.options_positions) ? ac.options_positions : [];
const issues = Array.isArray(ac && ac.issues) ? ac.issues : [];
const exId = ac && ac.id != null ? String(ac.id) : "";
const expandBtn = exId
? `<button type="button" class="dash-ac-expand-btn" data-dash-ex-id="${esc(exId)}" title="放大查看监控详情" aria-label="放大查看监控详情">` +
`<svg viewBox="0 0 24 24" width="14" height="14" aria-hidden="true"><path fill="currentColor" d="M15 3h6v6h-2V6.41l-7.29 7.3-1.42-1.42 7.3-7.29H15V3zM3 9h2v10h10v2H3V9z"/></svg>` +
`</button>`
: "";
const chips = renderMonitorCountChips((ac && ac.monitor_counts) || {});
const monitorRow =
chips.length || expandBtn
? `<div class="dash-ac-monitor-row">${chips.join("")}${expandBtn}</div>`
: "";
const monitorRow = chips.length
? `<div class="dash-ac-monitor-row">${chips.join("")}</div>`
: "";
const perpHtml = renderDashboardPerpTable(perpLines);
const optionsHtml = ac && ac.options_layout ? renderDashboardOptionsTable(optionsPositions) : "";
const issueHtml = issues
@@ -294,6 +273,12 @@
const badge = alert
? `<span class="dash-ac-badge alert">单日亏损 ≥${threshold}%</span>`
: `<span class="dash-ac-badge ok">${esc(ac.status || "—")}</span>`;
const exId = ac && ac.id != null ? String(ac.id) : "";
const expandBtn = exId
? `<button type="button" class="dash-ac-expand-btn" data-dash-ex-id="${esc(exId)}" title="放大查看监控详情" aria-label="放大查看监控详情">` +
`<svg viewBox="0 0 24 24" width="14" height="14" aria-hidden="true"><path fill="currentColor" d="M15 3h6v6h-2V6.41l-7.29 7.3-1.42-1.42 7.3-7.29H15V3zM3 9h2v10h10v2H3V9z"/></svg>` +
`</button>`
: "";
const lossBar =
alert && barW > 0
? `<div class="dash-loss-bar" title="占资金合计 ${fmt(lossPct, 2)}%"><i style="width:${barW}%"></i></div>`
@@ -302,7 +287,7 @@
return `<article class="dash-ac-card dash-ac-card-pos-only${cardCls}${alert ? " is-alert" : ""}${unmon ? " is-unmon" : ""}">
<div class="dash-ac-top">
<div class="dash-ac-name">${esc(ac.name || "—")}</div>
${badge}
<div class="dash-ac-top-actions">${badge}${expandBtn}</div>
</div>
${lossBar}
<div class="dash-ac-pos-body">${renderAccountPositions(ac)}</div>