总览名称旁增加条件单标签,无仓时持仓列显示触发短文案。
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -719,6 +719,49 @@ button, .btn {
|
|||||||
color: #6ee7b7;
|
color: #6ee7b7;
|
||||||
background: rgba(52, 211, 153, 0.14);
|
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 {
|
.pos-brief {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding-left: 0;
|
padding-left: 0;
|
||||||
|
|||||||
+67
-3
@@ -46,12 +46,73 @@
|
|||||||
return parts.length ? parts.join(" · ") : "未设出场";
|
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 || [];
|
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 items = list.slice(0, 8).map(function (p) {
|
||||||
const id = p.inst_id || "";
|
const id = p.inst_id || "";
|
||||||
const sheets = escapeHtml(String(p.sheets != null ? p.sheets : "—"));
|
const sheets = escapeHtml(String(p.sheets != null ? p.sheets : "—"));
|
||||||
|
const fromCond = tagOpen && (!opened || opened === id);
|
||||||
return (
|
return (
|
||||||
"<li>" +
|
"<li>" +
|
||||||
escapeHtml(id) +
|
escapeHtml(id) +
|
||||||
@@ -59,6 +120,7 @@
|
|||||||
sheets +
|
sheets +
|
||||||
"张 · " +
|
"张 · " +
|
||||||
fmtPnlHtml(p.pnl_usdt) +
|
fmtPnlHtml(p.pnl_usdt) +
|
||||||
|
(fromCond ? '<span class="overview-cond-src">条件单</span>' : "") +
|
||||||
"</li>"
|
"</li>"
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@@ -237,6 +299,7 @@
|
|||||||
? snap.pnl.unrealized_usdt
|
? snap.pnl.unrealized_usdt
|
||||||
: snap.upl_total_usdc;
|
: snap.upl_total_usdc;
|
||||||
const brief = snap.positions_brief || snap.positions || [];
|
const brief = snap.positions_brief || snap.positions || [];
|
||||||
|
const cond = activeCondOrder(snap);
|
||||||
const online = !!row.online;
|
const online = !!row.online;
|
||||||
const status = online
|
const status = online
|
||||||
? '<span class="status-on">在线</span>'
|
? '<span class="status-on">在线</span>'
|
||||||
@@ -249,6 +312,7 @@
|
|||||||
"<td><strong>" +
|
"<td><strong>" +
|
||||||
escapeHtml(row.name || "") +
|
escapeHtml(row.name || "") +
|
||||||
"</strong>" +
|
"</strong>" +
|
||||||
|
condTagHtml(cond) +
|
||||||
err +
|
err +
|
||||||
"</td>" +
|
"</td>" +
|
||||||
"<td>" +
|
"<td>" +
|
||||||
@@ -279,7 +343,7 @@
|
|||||||
premiumRatioCell(snap) +
|
premiumRatioCell(snap) +
|
||||||
"</td>" +
|
"</td>" +
|
||||||
"<td>" +
|
"<td>" +
|
||||||
positionSummary(brief) +
|
positionSummary(brief, cond) +
|
||||||
"</td>" +
|
"</td>" +
|
||||||
"<td>" +
|
"<td>" +
|
||||||
exitSummary(brief) +
|
exitSummary(brief) +
|
||||||
|
|||||||
+1
-1
@@ -4,7 +4,7 @@
|
|||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<title>{% block title %}期权中控{% endblock %}</title>
|
<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>
|
</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 %}">
|
<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') %}
|
{% if session.get('logged_in') %}
|
||||||
|
|||||||
@@ -15,6 +15,6 @@
|
|||||||
<div id="overview-grid"></div>
|
<div id="overview-grid"></div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% block scripts %}
|
{% 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>
|
<script>HubOverview.boot();</script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
Reference in New Issue
Block a user