Show hub fullscreen options positions as cards matching instance data.
Enrich hub options snapshot with close preview and render read-only option position cards in exchange fullscreen view. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -773,6 +773,7 @@ _TRADE_STATS_CALENDAR_JS = _REPO_STATIC / "trade_stats_calendar.js"
|
||||
_ACCOUNT_RISK_BADGE_CSS = _REPO_STATIC / "account_risk_badge.css"
|
||||
_ACCOUNT_RISK_BADGE_JS = _REPO_STATIC / "account_risk_badge.js"
|
||||
_OPTIONS_EXPIRY_COUNTDOWN_JS = _REPO_STATIC / "options_expiry_countdown.js"
|
||||
_OPTIONS_POSITION_CARDS_JS = _REPO_STATIC / "options_position_cards.js"
|
||||
|
||||
|
||||
@app.get("/assets/account_risk_badge.css")
|
||||
@@ -807,6 +808,16 @@ def hub_options_expiry_countdown_js():
|
||||
)
|
||||
|
||||
|
||||
@app.get("/assets/options_position_cards.js")
|
||||
def hub_options_position_cards_js():
|
||||
if not _OPTIONS_POSITION_CARDS_JS.is_file():
|
||||
raise HTTPException(status_code=404, detail="options_position_cards.js not found")
|
||||
return FileResponse(
|
||||
str(_OPTIONS_POSITION_CARDS_JS),
|
||||
media_type="application/javascript; charset=utf-8",
|
||||
)
|
||||
|
||||
|
||||
@app.get("/assets/ai_review_render.js")
|
||||
def hub_ai_review_render_js():
|
||||
"""与三所实例共用仓库根 static/ai_review_render.js(须在 /assets mount 之前注册)."""
|
||||
|
||||
@@ -1970,6 +1970,35 @@ body.market-chart-fs-open {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.exchange-fullscreen .hub-opt-pos-list {
|
||||
margin-bottom: 14px;
|
||||
}
|
||||
|
||||
.hub-opt-pos-card .pos-grid {
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
.hub-opt-pos-card .opt-pos-cell--depth {
|
||||
grid-column: span 2;
|
||||
}
|
||||
|
||||
.hub-opt-pos-card .opt-bid-plain {
|
||||
color: #dbe6ff;
|
||||
font-variant-numeric: tabular-nums;
|
||||
line-height: 1.35;
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
.hub-opt-pos-card .opt-close-value {
|
||||
font-weight: 700;
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
|
||||
.hub-opt-pos-card .pos-card-symbol strong {
|
||||
font-size: 0.72rem;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.hub-pos-card .pos-cell {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
@@ -3569,7 +3569,23 @@
|
||||
return html;
|
||||
}
|
||||
|
||||
function renderOptionsSectionBody(row) {
|
||||
function renderOptionsPositionsCards(pos) {
|
||||
if (!pos.length) return '<div class="empty-hint">暂无期权持仓</div>';
|
||||
if (!globalThis.OptionsPositionCards || !OptionsPositionCards.renderCard) {
|
||||
return renderOptionsPositionsTable(pos);
|
||||
}
|
||||
const cls = hubPosListCountClass(pos.length);
|
||||
let html = `<div class="hub-pos-list hub-opt-pos-list ${cls}" data-pos-count="${pos.length}">`;
|
||||
pos.forEach((p) => {
|
||||
html += OptionsPositionCards.renderCard(p, { readOnly: true, hub: true });
|
||||
});
|
||||
html += "</div>";
|
||||
return html;
|
||||
}
|
||||
|
||||
function renderOptionsSectionBody(row, opts) {
|
||||
const options = opts || {};
|
||||
const layout = options.layout || "table";
|
||||
const opt = row.options || {};
|
||||
let html = "";
|
||||
if (opt.enabled === false) {
|
||||
@@ -3585,7 +3601,7 @@
|
||||
const bal = optionsBalanceFields(opt);
|
||||
html += renderStatRow(bal.funding, bal.trading, bal.upl);
|
||||
html += `<div class="section-title hub-options-title">期权持仓 · ${pos.length} 仓</div>`;
|
||||
html += renderOptionsPositionsTable(pos);
|
||||
html += layout === "cards" ? renderOptionsPositionsCards(pos) : renderOptionsPositionsTable(pos);
|
||||
if (row.flask_url_browser || row.flask_url) {
|
||||
html += `<div class="hub-options-actions"><a class="btn-link btn-open-instance" href="#" data-ex-id="${esc(row.id)}" data-next="/options">打开期权页</a></div>`;
|
||||
}
|
||||
@@ -3602,11 +3618,11 @@
|
||||
return html;
|
||||
}
|
||||
|
||||
function renderOptionsMonitorSection(row) {
|
||||
function renderOptionsMonitorSection(row, opts) {
|
||||
if (!rowHasOptionsLayout(row)) return "";
|
||||
let html = '<div class="hub-monitor-block hub-monitor-options">';
|
||||
html += '<div class="hub-monitor-block-label">期权账户</div>';
|
||||
html += renderOptionsSectionBody(row);
|
||||
html += renderOptionsSectionBody(row, opts);
|
||||
html += "</div>";
|
||||
return html;
|
||||
}
|
||||
@@ -3723,7 +3739,7 @@
|
||||
if (rowHasOptionsLayout(row)) {
|
||||
html += "</div>";
|
||||
}
|
||||
html += renderOptionsMonitorSection(row);
|
||||
html += renderOptionsMonitorSection(row, { layout: "cards" });
|
||||
html += '<div class="hub-fs-sections-grid">';
|
||||
if ((row.capabilities || []).includes("key")) {
|
||||
if (!flaskOk) {
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600&family=Orbitron:wght@500;600;700&display=swap" rel="stylesheet" media="print" onload="this.media='all'" />
|
||||
<noscript><link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600&family=Orbitron:wght@500;600;700&display=swap" rel="stylesheet" /></noscript>
|
||||
<link rel="stylesheet" href="/assets/app.css?v=20260710-logs-cal" />
|
||||
<link rel="stylesheet" href="/assets/app.css?v=20260711-hub-opt-cards" />
|
||||
<link rel="stylesheet" href="/assets/trade_stats_calendar.css?v=4" />
|
||||
<link rel="stylesheet" href="/assets/account_risk_badge.css?v=4" />
|
||||
<script src="/assets/account_risk_badge.js?v=4"></script>
|
||||
@@ -1237,7 +1237,8 @@
|
||||
<script src="/assets/ai_review_render.js?v=3"></script>
|
||||
<script src="/assets/time_close_ui.js?v=3"></script>
|
||||
<script src="/assets/options_expiry_countdown.js?v=1"></script>
|
||||
<script src="/assets/options_position_cards.js?v=1"></script>
|
||||
<script src="/assets/backup.js?v=1"></script>
|
||||
<script src="/assets/app.js?v=20260708-hub-ai-save"></script>
|
||||
<script src="/assets/app.js?v=20260711-hub-opt-cards"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user