总览名称旁增加条件单标签,无仓时持仓列显示触发短文案。
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -719,6 +719,49 @@ button, .btn {
|
||||
color: #6ee7b7;
|
||||
background: rgba(52, 211, 153, 0.14);
|
||||
}
|
||||
.overview-table td strong {
|
||||
display: inline-block;
|
||||
margin-right: 8px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.overview-cond-tag {
|
||||
display: inline-block;
|
||||
margin-top: 4px;
|
||||
padding: 2px 8px;
|
||||
border-radius: 999px;
|
||||
font-size: 0.72rem;
|
||||
font-weight: 700;
|
||||
white-space: nowrap;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.overview-cond-tag.is-armed {
|
||||
color: #7dd3fc;
|
||||
background: rgba(56, 189, 248, 0.16);
|
||||
}
|
||||
.overview-cond-tag.is-trig {
|
||||
color: #fbbf24;
|
||||
background: rgba(251, 191, 36, 0.16);
|
||||
}
|
||||
.overview-cond-tag.is-open {
|
||||
color: #6ee7b7;
|
||||
background: rgba(52, 211, 153, 0.16);
|
||||
}
|
||||
.overview-cond-wait-line {
|
||||
color: #9ec0ff;
|
||||
font-size: 0.8rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
.overview-cond-src {
|
||||
display: inline-block;
|
||||
margin-left: 6px;
|
||||
padding: 0 6px;
|
||||
border-radius: 999px;
|
||||
font-size: 0.68rem;
|
||||
font-weight: 700;
|
||||
color: #7dd3fc;
|
||||
background: rgba(56, 189, 248, 0.14);
|
||||
vertical-align: middle;
|
||||
}
|
||||
.pos-brief {
|
||||
margin: 0;
|
||||
padding-left: 0;
|
||||
|
||||
+67
-3
@@ -46,12 +46,73 @@
|
||||
return parts.length ? parts.join(" · ") : "未设出场";
|
||||
}
|
||||
|
||||
function positionSummary(brief) {
|
||||
function activeCondOrder(snap) {
|
||||
const list = snap && snap.cond_orders_active;
|
||||
if (Array.isArray(list) && list.length && list[0]) return list[0];
|
||||
if (snap && snap.cond_order) return snap.cond_order;
|
||||
if (snap && snap.cond_order_locked) return { status: "armed" };
|
||||
return null;
|
||||
}
|
||||
|
||||
function condStatusLabel(st) {
|
||||
const map = { armed: "待命", triggering: "触发中", open: "持仓中" };
|
||||
return map[st] || "占用";
|
||||
}
|
||||
|
||||
function condStatusClass(st) {
|
||||
if (st === "open") return "is-open";
|
||||
if (st === "triggering") return "is-trig";
|
||||
return "is-armed";
|
||||
}
|
||||
|
||||
function condTagHtml(cond) {
|
||||
if (!cond) return "";
|
||||
const st = String(cond.status || "armed");
|
||||
return (
|
||||
'<span class="overview-cond-tag ' +
|
||||
condStatusClass(st) +
|
||||
'">条件单 · ' +
|
||||
escapeHtml(condStatusLabel(st)) +
|
||||
"</span>"
|
||||
);
|
||||
}
|
||||
|
||||
function condWaitLine(cond) {
|
||||
if (!cond) return "条件单占用";
|
||||
const put = String(cond.opt_type || "").toUpperCase() !== "C";
|
||||
const uly = String(cond.underlying || "").trim();
|
||||
const side =
|
||||
String(cond.trigger_side || "").toLowerCase() === "lte"
|
||||
? "下穿 ≤"
|
||||
: put
|
||||
? "上穿 ≥"
|
||||
: "下穿 ≤";
|
||||
const px = cond.trigger_px != null && cond.trigger_px !== "" ? String(cond.trigger_px) : "";
|
||||
const bits = [];
|
||||
if (uly) bits.push(uly + " " + (put ? "Put" : "Call"));
|
||||
if (px) bits.push(side + " " + px);
|
||||
return bits.length ? bits.join(" · ") : "条件单占用";
|
||||
}
|
||||
|
||||
function positionSummary(brief, cond) {
|
||||
const list = brief || [];
|
||||
if (!list.length) return '<span class="muted">暂无持仓</span>';
|
||||
if (!list.length) {
|
||||
if (cond) {
|
||||
return (
|
||||
'<div class="overview-cond-wait">' +
|
||||
'<div class="overview-cond-wait-line">' +
|
||||
escapeHtml(condWaitLine(cond)) +
|
||||
"</div></div>"
|
||||
);
|
||||
}
|
||||
return '<span class="muted">暂无持仓</span>';
|
||||
}
|
||||
const opened = cond && String(cond.opened_inst_id || "").trim();
|
||||
const tagOpen = !!(cond && String(cond.status || "") === "open");
|
||||
const items = list.slice(0, 8).map(function (p) {
|
||||
const id = p.inst_id || "";
|
||||
const sheets = escapeHtml(String(p.sheets != null ? p.sheets : "—"));
|
||||
const fromCond = tagOpen && (!opened || opened === id);
|
||||
return (
|
||||
"<li>" +
|
||||
escapeHtml(id) +
|
||||
@@ -59,6 +120,7 @@
|
||||
sheets +
|
||||
"张 · " +
|
||||
fmtPnlHtml(p.pnl_usdt) +
|
||||
(fromCond ? '<span class="overview-cond-src">条件单</span>' : "") +
|
||||
"</li>"
|
||||
);
|
||||
});
|
||||
@@ -237,6 +299,7 @@
|
||||
? snap.pnl.unrealized_usdt
|
||||
: snap.upl_total_usdc;
|
||||
const brief = snap.positions_brief || snap.positions || [];
|
||||
const cond = activeCondOrder(snap);
|
||||
const online = !!row.online;
|
||||
const status = online
|
||||
? '<span class="status-on">在线</span>'
|
||||
@@ -249,6 +312,7 @@
|
||||
"<td><strong>" +
|
||||
escapeHtml(row.name || "") +
|
||||
"</strong>" +
|
||||
condTagHtml(cond) +
|
||||
err +
|
||||
"</td>" +
|
||||
"<td>" +
|
||||
@@ -279,7 +343,7 @@
|
||||
premiumRatioCell(snap) +
|
||||
"</td>" +
|
||||
"<td>" +
|
||||
positionSummary(brief) +
|
||||
positionSummary(brief, cond) +
|
||||
"</td>" +
|
||||
"<td>" +
|
||||
exitSummary(brief) +
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>{% block title %}期权中控{% endblock %}</title>
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='hub.css') }}?v=20">
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='hub.css') }}?v=21">
|
||||
</head>
|
||||
<body class="{% if request.path.startswith('/login') %}page-login{% elif request.path.startswith('/desk') %}page-desk{% elif request.path.startswith('/stats') %}page-stats{% elif request.path.startswith('/instances') %}page-instances{% elif request.path == '/' %}page-dashboard{% endif %}">
|
||||
{% if session.get('logged_in') %}
|
||||
|
||||
@@ -15,6 +15,6 @@
|
||||
<div id="overview-grid"></div>
|
||||
{% endblock %}
|
||||
{% block scripts %}
|
||||
<script src="{{ url_for('static', filename='hub.js') }}?v=19"></script>
|
||||
<script src="{{ url_for('static', filename='hub.js') }}?v=20"></script>
|
||||
<script>HubOverview.boot();</script>
|
||||
{% endblock %}
|
||||
|
||||
Reference in New Issue
Block a user