修改前端
This commit is contained in:
@@ -710,14 +710,35 @@ body.hub-fullscreen-open {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.hub-pos-card .pos-side-long {
|
||||
background: rgba(37, 58, 110, 0.9);
|
||||
color: #6eb5ff;
|
||||
.hub-pos-card .pos-side-long,
|
||||
.hub-pos-card .pos-side-badge.side-long {
|
||||
background: rgba(0, 255, 157, 0.12);
|
||||
color: var(--green);
|
||||
border: 1px solid rgba(0, 255, 157, 0.35);
|
||||
}
|
||||
|
||||
.hub-pos-card .pos-side-short {
|
||||
background: rgba(74, 34, 48, 0.9);
|
||||
color: #ff8a8a;
|
||||
.hub-pos-card .pos-side-short,
|
||||
.hub-pos-card .pos-side-badge.side-short {
|
||||
background: rgba(255, 77, 109, 0.12);
|
||||
color: var(--red);
|
||||
border: 1px solid rgba(255, 77, 109, 0.35);
|
||||
}
|
||||
|
||||
.side-long {
|
||||
color: var(--green);
|
||||
font-weight: 600;
|
||||
text-shadow: 0 0 10px rgba(0, 255, 157, 0.25);
|
||||
}
|
||||
|
||||
.side-short {
|
||||
color: var(--red);
|
||||
font-weight: 600;
|
||||
text-shadow: 0 0 10px rgba(255, 77, 109, 0.25);
|
||||
}
|
||||
|
||||
.data-table td.side-long,
|
||||
.data-table td.side-short {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.hub-pos-card .pos-head-actions {
|
||||
@@ -890,6 +911,31 @@ body.hub-fullscreen-open {
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.hub-mini-card.hub-key-pending,
|
||||
.list-line.hub-key-pending {
|
||||
border-color: rgba(0, 212, 255, 0.55);
|
||||
background: rgba(0, 212, 255, 0.08);
|
||||
box-shadow: 0 0 16px rgba(0, 212, 255, 0.12);
|
||||
}
|
||||
|
||||
.hub-key-pending-tag {
|
||||
display: inline-block;
|
||||
margin-left: 6px;
|
||||
padding: 1px 7px;
|
||||
font-size: 10px;
|
||||
font-weight: 600;
|
||||
color: var(--accent);
|
||||
background: rgba(0, 212, 255, 0.15);
|
||||
border: 1px solid rgba(0, 212, 255, 0.45);
|
||||
border-radius: 4px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.hub-key-pending .hub-key-status-line,
|
||||
.list-line.hub-key-pending {
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
.hub-mini-title {
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
|
||||
@@ -77,6 +77,45 @@
|
||||
return n > 0 ? "pnl-pos" : "pnl-neg";
|
||||
}
|
||||
|
||||
function normSide(side) {
|
||||
const s = (side || "").toLowerCase();
|
||||
if (s === "buy") return "long";
|
||||
if (s === "sell") return "short";
|
||||
return s;
|
||||
}
|
||||
|
||||
function sideDirCls(side) {
|
||||
const s = normSide(side);
|
||||
if (s === "long") return "side-long";
|
||||
if (s === "short") return "side-short";
|
||||
return "";
|
||||
}
|
||||
|
||||
function sideDirLabel(side) {
|
||||
const s = normSide(side);
|
||||
if (s === "long") return "做多";
|
||||
if (s === "short") return "做空";
|
||||
return side || "—";
|
||||
}
|
||||
|
||||
function renderDirectionHtml(side) {
|
||||
const cls = sideDirCls(side);
|
||||
const label = sideDirLabel(side);
|
||||
if (!cls) return esc(String(label));
|
||||
return `<span class="${cls}">${esc(label)}</span>`;
|
||||
}
|
||||
|
||||
function keyHasPendingOrder(keyRow, keyPrice) {
|
||||
const kp = keyPrice || {};
|
||||
const oid = keyRow.fib_limit_order_id;
|
||||
if (oid != null && String(oid).trim() !== "") return true;
|
||||
const gm = String(kp.gate_metrics || "");
|
||||
if (gm.includes("限价单") || gm.includes("挂单")) return true;
|
||||
const gs = String(kp.gate_summary || "");
|
||||
if (/挂|限价|等待成交/.test(gs)) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/** 全屏持仓区:按仓位数量附加布局 class(1~6 固定列数,7+ 自动填充) */
|
||||
function hubPosListCountClass(n) {
|
||||
const c = Math.max(0, parseInt(n, 10) || 0);
|
||||
@@ -499,8 +538,8 @@
|
||||
function renderLivePositionCard(exchangeId, pos, monitorOrder) {
|
||||
const symbol = pos.symbol || "";
|
||||
const side = (pos.side || "long").toLowerCase();
|
||||
const sideCn = side === "long" ? "做多" : "做空";
|
||||
const sideCls = side === "long" ? "pos-side-long" : "pos-side-short";
|
||||
const sideCn = sideDirLabel(side);
|
||||
const sideCls = sideDirCls(side) || "side-long";
|
||||
const mo = monitorOrder || {};
|
||||
const cond = condOrdersFromPosition(pos);
|
||||
const reg = Array.isArray(pos.regular_orders) ? pos.regular_orders : [];
|
||||
@@ -584,10 +623,16 @@
|
||||
.map((k) => {
|
||||
const kp = kmap[k.id] || kmap[String(k.id)] || {};
|
||||
const mt = k.monitor_type || k.type || "";
|
||||
return `<div class="hub-mini-card">
|
||||
<div class="hub-mini-title">${esc(k.symbol)} · ${esc(mt)}</div>
|
||||
const pending = keyHasPendingOrder(k, kp);
|
||||
const cardCls = pending ? "hub-mini-card hub-key-pending" : "hub-mini-card";
|
||||
const dir = k.direction ? ` · ${renderDirectionHtml(k.direction)}` : "";
|
||||
const pendingTag = pending
|
||||
? `<span class="hub-key-pending-tag">挂单中</span>`
|
||||
: "";
|
||||
return `<div class="${cardCls}">
|
||||
<div class="hub-mini-title">${esc(k.symbol)} · ${esc(mt)}${dir} ${pendingTag}</div>
|
||||
<div class="hub-mini-line">上沿 ${esc(k.upper)} / 下沿 ${esc(k.lower)}</div>
|
||||
<div class="hub-mini-line">${esc(kp.gate_summary || kp.price_display || kp.price || "—")}</div>
|
||||
<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>
|
||||
</div>`;
|
||||
})
|
||||
.join("");
|
||||
@@ -598,7 +643,7 @@
|
||||
return orders
|
||||
.map(
|
||||
(o) => `<div class="hub-mini-card">
|
||||
<div class="hub-mini-title">#${esc(o.id)} · ${esc(o.symbol || o.exchange_symbol)} · ${esc(o.direction)}</div>
|
||||
<div class="hub-mini-title">#${esc(o.id)} · ${esc(o.symbol || o.exchange_symbol)} · ${renderDirectionHtml(o.direction)}</div>
|
||||
<div class="hub-mini-line">触发 ${fmt(o.trigger_price, 4)} · SL ${fmt(o.stop_loss, 4)} · TP ${fmt(o.take_profit, 4)} · ${esc(o.trade_style || o.monitor_type || "下单监控")}</div>
|
||||
</div>`
|
||||
)
|
||||
@@ -610,7 +655,7 @@
|
||||
return trends
|
||||
.map(
|
||||
(t) => `<div class="hub-mini-card">
|
||||
<div class="hub-mini-title">#${esc(t.id)} · ${esc(t.symbol)} · ${esc(t.direction)}</div>
|
||||
<div class="hub-mini-title">#${esc(t.id)} · ${esc(t.symbol)} · ${renderDirectionHtml(t.direction)}</div>
|
||||
<div class="hub-mini-line">SL ${fmt(t.stop_loss, 4)} · TP ${fmt(t.take_profit, 4)} · 状态 ${esc(t.status || "active")}</div>
|
||||
</div>`
|
||||
)
|
||||
@@ -643,7 +688,7 @@
|
||||
<table class="data-table"><thead><tr><th>合约</th><th>方向</th><th>张数</th><th>浮盈</th><th>操作</th></tr></thead><tbody>
|
||||
<tr>
|
||||
<td>${esc(x.symbol)}</td>
|
||||
<td>${esc(x.side)}</td>
|
||||
<td class="${sideDirCls(x.side)}">${renderDirectionHtml(x.side)}</td>
|
||||
<td>${fmt(x.contracts, 4)}</td>
|
||||
<td class="${pnlCls(x.unrealized_pnl)}">${fmt(x.unrealized_pnl, 4)}</td>
|
||||
<td class="td-actions">
|
||||
@@ -673,7 +718,7 @@
|
||||
if (orders.length) {
|
||||
inner += `<div class="section-title">下单监控 · ${orders.length}</div>`;
|
||||
orders.forEach((o) => {
|
||||
inner += `<div class="list-line">${esc(o.symbol || o.exchange_symbol)} · ${esc(o.direction)} · 触发 ${fmt(o.trigger_price, 4)}</div>`;
|
||||
inner += `<div class="list-line">${esc(o.symbol || o.exchange_symbol)} · ${renderDirectionHtml(o.direction)} · 触发 ${fmt(o.trigger_price, 4)}</div>`;
|
||||
});
|
||||
}
|
||||
if ((row.capabilities || []).includes("key")) {
|
||||
@@ -687,19 +732,24 @@
|
||||
keys.forEach((k) => {
|
||||
const kp = kmap[k.id] || kmap[String(k.id)] || {};
|
||||
const mt = k.monitor_type || k.type || "";
|
||||
let line = `${esc(k.symbol)} · ${esc(mt)} · ${k.upper} / ${k.lower}`;
|
||||
const pending = keyHasPendingOrder(k, kp);
|
||||
const lineCls = pending ? "list-line hub-key-pending" : "list-line";
|
||||
let line = `${esc(k.symbol)} · ${esc(mt)}`;
|
||||
if (k.direction) line += ` · ${renderDirectionHtml(k.direction)}`;
|
||||
if (pending) line += ` · <span class="hub-key-pending-tag">挂单</span>`;
|
||||
line += ` · ${esc(k.upper)} / ${esc(k.lower)}`;
|
||||
if (kp.price_display != null || kp.price != null) {
|
||||
line += ` · ${esc(kp.price_display != null ? kp.price_display : kp.price)}`;
|
||||
}
|
||||
line += ` · ${esc(kp.gate_summary || "-")}`;
|
||||
inner += `<div class="list-line">${line}</div>`;
|
||||
inner += `<div class="${lineCls}">${line}</div>`;
|
||||
});
|
||||
}
|
||||
}
|
||||
if ((row.capabilities || []).includes("trend") && trends.length) {
|
||||
inner += `<div class="section-title">趋势回调 · ${trends.length}</div>`;
|
||||
trends.forEach((t) => {
|
||||
inner += `<div class="list-line">#${t.id} ${esc(t.symbol)} ${t.direction} · SL ${t.stop_loss} · TP ${t.take_profit}</div>`;
|
||||
inner += `<div class="list-line">#${t.id} ${esc(t.symbol)} ${renderDirectionHtml(t.direction)} · SL ${t.stop_loss} · TP ${t.take_profit}</div>`;
|
||||
});
|
||||
}
|
||||
if (rolls.length) {
|
||||
|
||||
@@ -8,7 +8,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=20260525-perf" />
|
||||
<link rel="stylesheet" href="/assets/app.css?v=20260525-ui-dir" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="app-bg" aria-hidden="true"></div>
|
||||
@@ -109,6 +109,6 @@
|
||||
</div>
|
||||
|
||||
<div id="toast"></div>
|
||||
<script src="/assets/app.js?v=20260525-hub-sso"></script>
|
||||
<script src="/assets/app.js?v=20260525-ui-dir"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -8,7 +8,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=20260525-perf" />
|
||||
<link rel="stylesheet" href="/assets/app.css?v=20260525-ui-dir" />
|
||||
</head>
|
||||
<body class="login-page">
|
||||
<div class="login-bg" aria-hidden="true"></div>
|
||||
|
||||
Reference in New Issue
Block a user