fix(hub): use single position table header on desktop monitor cards
Render all exchange positions in one table row group instead of repeating column headers per symbol. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1272,6 +1272,14 @@ body.market-chart-fs-open {
|
|||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.pos-table-wrap {
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.data-table-positions tbody tr:not(:last-child) td {
|
||||||
|
border-bottom: 1px dashed var(--border-soft);
|
||||||
|
}
|
||||||
|
|
||||||
.pos-action-group {
|
.pos-action-group {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
|
|||||||
@@ -1537,16 +1537,25 @@
|
|||||||
.join("");
|
.join("");
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderPositionBlock(exchangeId, exchangeKey, x, monitorOrder, trendPlan, tickMap, opts) {
|
function renderPositionTableRow(
|
||||||
|
exchangeId,
|
||||||
|
exchangeKey,
|
||||||
|
x,
|
||||||
|
monitorOrder,
|
||||||
|
trendPlan,
|
||||||
|
tickMap,
|
||||||
|
opts
|
||||||
|
) {
|
||||||
const options = opts || {};
|
const options = opts || {};
|
||||||
const compact = !!options.compact;
|
const compact = !!options.compact;
|
||||||
const symAttr = esc(x.symbol || "").replace(/"/g, """);
|
const symAttr = esc(x.symbol || "").replace(/"/g, """);
|
||||||
const exKeyAttr = esc(exchangeKey || exchangeId || "").replace(/"/g, """);
|
|
||||||
const sideAttr = esc((x.side || "").toLowerCase()).replace(/"/g, """);
|
const sideAttr = esc((x.side || "").toLowerCase()).replace(/"/g, """);
|
||||||
const side = sideAttr || "long";
|
const side = sideAttr || "long";
|
||||||
const contractsAttr = esc(String(x.contracts != null ? x.contracts : "")).replace(/"/g, """);
|
const contractsAttr = esc(String(x.contracts != null ? x.contracts : "")).replace(
|
||||||
|
/"/g,
|
||||||
|
"""
|
||||||
|
);
|
||||||
const cond = condOrdersFromPosition(x);
|
const cond = condOrdersFromPosition(x);
|
||||||
const reg = Array.isArray(x.regular_orders) ? x.regular_orders : [];
|
|
||||||
const tpsl = resolvePositionTpsl(x, monitorOrder, trendPlan);
|
const tpsl = resolvePositionTpsl(x, monitorOrder, trendPlan);
|
||||||
const beSecured = isBreakevenSecured(side, tpsl.entry, monitorOrder, cond, x);
|
const beSecured = isBreakevenSecured(side, tpsl.entry, monitorOrder, cond, x);
|
||||||
const slAttr = esc(String(tpsl.sl)).replace(/"/g, """);
|
const slAttr = esc(String(tpsl.sl)).replace(/"/g, """);
|
||||||
@@ -1559,13 +1568,7 @@
|
|||||||
<button type="button" class="btn-place-tpsl btn-sm ghost" data-ex-id="${esc(exchangeId)}" data-symbol="${symAttr}" data-side="${sideAttr}" data-contracts="${contractsAttr}" data-sl="${slAttr}" data-tp="${tpAttr}">委托</button>
|
<button type="button" class="btn-place-tpsl btn-sm ghost" data-ex-id="${esc(exchangeId)}" data-symbol="${symAttr}" data-side="${sideAttr}" data-contracts="${contractsAttr}" data-sl="${slAttr}" data-tp="${tpAttr}">委托</button>
|
||||||
<button type="button" class="btn-close-pos btn-sm danger" data-ex-id="${esc(exchangeId)}" data-symbol="${symAttr}" data-side="${sideAttr}">平仓</button>
|
<button type="button" class="btn-close-pos btn-sm danger" data-ex-id="${esc(exchangeId)}" data-symbol="${symAttr}" data-side="${sideAttr}">平仓</button>
|
||||||
</div>`;
|
</div>`;
|
||||||
const ordersBlock = compact
|
return `<tr>
|
||||||
? ""
|
|
||||||
: renderOrdersCollapse(exchangeId, x.symbol, cond, reg, tickMap);
|
|
||||||
return `<div class="pos-block">
|
|
||||||
<div class="table-scroll">
|
|
||||||
<table class="data-table"><thead><tr><th>合约</th><th>方向</th><th>开仓价</th><th>标记价</th><th>张数</th><th>浮盈</th><th>操作</th></tr></thead><tbody>
|
|
||||||
<tr>
|
|
||||||
<td class="td-symbol"><button type="button" class="btn-open-market sym-link" ${mktAttrs} title="打开行情区(含入场/止盈止损)">${esc(x.symbol)}</button>${symBeBadge}</td>
|
<td class="td-symbol"><button type="button" class="btn-open-market sym-link" ${mktAttrs} title="打开行情区(含入场/止盈止损)">${esc(x.symbol)}</button>${symBeBadge}</td>
|
||||||
<td class="${sideDirCls(x.side)}">${renderDirectionHtml(x.side)}</td>
|
<td class="${sideDirCls(x.side)}">${renderDirectionHtml(x.side)}</td>
|
||||||
<td class="td-entry">${fmtEntryPrice(x, tickMap)}</td>
|
<td class="td-entry">${fmtEntryPrice(x, tickMap)}</td>
|
||||||
@@ -1573,13 +1576,57 @@
|
|||||||
<td>${fmt(x.contracts, 4)}</td>
|
<td>${fmt(x.contracts, 4)}</td>
|
||||||
<td class="${pnlCls(x.unrealized_pnl)}">${fmt(x.unrealized_pnl, 2)}</td>
|
<td class="${pnlCls(x.unrealized_pnl)}">${fmt(x.unrealized_pnl, 2)}</td>
|
||||||
<td class="td-actions">${actionCell}</td>
|
<td class="td-actions">${actionCell}</td>
|
||||||
</tr>
|
</tr>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderPositionBlock(exchangeId, exchangeKey, x, monitorOrder, trendPlan, tickMap, opts) {
|
||||||
|
const options = opts || {};
|
||||||
|
const compact = !!options.compact;
|
||||||
|
const reg = Array.isArray(x.regular_orders) ? x.regular_orders : [];
|
||||||
|
const cond = condOrdersFromPosition(x);
|
||||||
|
const ordersBlock = compact
|
||||||
|
? ""
|
||||||
|
: renderOrdersCollapse(exchangeId, x.symbol, cond, reg, tickMap);
|
||||||
|
const rowHtml = renderPositionTableRow(
|
||||||
|
exchangeId,
|
||||||
|
exchangeKey,
|
||||||
|
x,
|
||||||
|
monitorOrder,
|
||||||
|
trendPlan,
|
||||||
|
tickMap,
|
||||||
|
opts
|
||||||
|
);
|
||||||
|
return `<div class="pos-block">
|
||||||
|
<div class="table-scroll">
|
||||||
|
<table class="data-table"><thead><tr><th>合约</th><th>方向</th><th>开仓价</th><th>标记价</th><th>张数</th><th>浮盈</th><th>操作</th></tr></thead><tbody>
|
||||||
|
${rowHtml}
|
||||||
</tbody></table>
|
</tbody></table>
|
||||||
</div>
|
</div>
|
||||||
${ordersBlock}
|
${ordersBlock}
|
||||||
</div>`;
|
</div>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function renderGridPositionsTable(exchangeId, exchangeKey, positions, orders, trends, tickMap) {
|
||||||
|
const rows = positions
|
||||||
|
.map((p) =>
|
||||||
|
renderPositionTableRow(
|
||||||
|
exchangeId,
|
||||||
|
exchangeKey,
|
||||||
|
p,
|
||||||
|
findMonitorOrder(orders, p.symbol, p.side),
|
||||||
|
findTrendPlan(trends, p.symbol, p.side),
|
||||||
|
tickMap,
|
||||||
|
{ compact: true }
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.join("");
|
||||||
|
return `<div class="pos-table-wrap table-scroll">
|
||||||
|
<table class="data-table data-table-positions"><thead><tr><th>合约</th><th>方向</th><th>开仓价</th><th>标记价</th><th>张数</th><th>浮盈</th><th>操作</th></tr></thead><tbody>
|
||||||
|
${rows}
|
||||||
|
</tbody></table>
|
||||||
|
</div>`;
|
||||||
|
}
|
||||||
|
|
||||||
function renderGridBody(row, ag, pos, hm, flaskOk, keys, orders, trends, rolls, kmap) {
|
function renderGridBody(row, ag, pos, hm, flaskOk, keys, orders, trends, rolls, kmap) {
|
||||||
const tickMap = buildPriceTickMap(row);
|
const tickMap = buildPriceTickMap(row);
|
||||||
let inner = `<div class="stat-row">
|
let inner = `<div class="stat-row">
|
||||||
@@ -1588,19 +1635,14 @@
|
|||||||
</div>`;
|
</div>`;
|
||||||
inner += `<div class="section-title">交易所持仓 · ${pos.length} 仓</div>`;
|
inner += `<div class="section-title">交易所持仓 · ${pos.length} 仓</div>`;
|
||||||
if (pos.length) {
|
if (pos.length) {
|
||||||
inner += pos
|
inner += renderGridPositionsTable(
|
||||||
.map((p) =>
|
row.id,
|
||||||
renderPositionBlock(
|
row.key || row.id,
|
||||||
row.id,
|
pos,
|
||||||
row.key || row.id,
|
orders,
|
||||||
p,
|
trends,
|
||||||
findMonitorOrder(orders, p.symbol, p.side),
|
tickMap
|
||||||
findTrendPlan(trends, p.symbol, p.side),
|
);
|
||||||
tickMap,
|
|
||||||
{ compact: true }
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.join("");
|
|
||||||
} else {
|
} else {
|
||||||
inner += '<div class="empty-hint">无持仓</div>';
|
inner += '<div class="empty-hint">无持仓</div>';
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -246,6 +246,6 @@
|
|||||||
<div id="toast"></div>
|
<div id="toast"></div>
|
||||||
<script src="https://unpkg.com/lightweight-charts@4.2.0/dist/lightweight-charts.standalone.production.js"></script>
|
<script src="https://unpkg.com/lightweight-charts@4.2.0/dist/lightweight-charts.standalone.production.js"></script>
|
||||||
<script src="/assets/chart.js?v=20260603-hub-binance-tick"></script>
|
<script src="/assets/chart.js?v=20260603-hub-binance-tick"></script>
|
||||||
<script src="/assets/app.js?v=20260604-hub-grid-compact2"></script>
|
<script src="/assets/app.js?v=20260604-hub-pos-table"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
Reference in New Issue
Block a user