Highlight selected Call/Put legs on the OO hedge T-quote board.

Selected buttons show 腿A/腿B and accent styling so the active strikes are obvious.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-08-06 09:13:00 +08:00
parent f19500bcd9
commit baf928d064
5 changed files with 82 additions and 7 deletions
+65 -4
View File
@@ -882,6 +882,50 @@
}); });
} }
function selectedOoLegMap() {
const map = {};
if (state.legA && state.legA.inst_id) map[String(state.legA.inst_id)] = "A";
if (state.legB && state.legB.inst_id) map[String(state.legB.inst_id)] = "B";
return map;
}
function syncOoPickHighlight() {
const tbody = $("hp-oo-tbody");
if (!tbody) return;
const map = selectedOoLegMap();
tbody.querySelectorAll(".hp-oo-pick").forEach(function (btn) {
const inst = String(btn.getAttribute("data-inst") || "");
const leg = map[inst];
const on = !!leg;
btn.classList.toggle("is-selected", on);
btn.classList.toggle("active", on);
btn.setAttribute("aria-pressed", on ? "true" : "false");
const side = String(btn.getAttribute("data-side") || "").toUpperCase();
const base = side === "P" ? "Put" : "Call";
btn.textContent = on ? "腿" + leg + " · " + base : base;
btn.title = on ? "已选用为腿" + leg + "(再点其他合约可改选)" : "选用此 " + base;
});
tbody.querySelectorAll("tr").forEach(function (tr) {
const callBtn = tr.querySelector('.hp-oo-pick[data-side="C"]');
const putBtn = tr.querySelector('.hp-oo-pick[data-side="P"]');
const callOn = !!(callBtn && map[String(callBtn.getAttribute("data-inst") || "")]);
const putOn = !!(putBtn && map[String(putBtn.getAttribute("data-inst") || "")]);
tr.classList.toggle("hp-oo-row-selected", callOn || putOn);
tr.querySelectorAll("td.opt-t-call").forEach(function (td) {
td.classList.toggle("hp-oo-side-selected", callOn);
});
if (callBtn && callBtn.parentElement) {
callBtn.parentElement.classList.toggle("hp-oo-side-selected", callOn);
}
tr.querySelectorAll("td.opt-t-put").forEach(function (td) {
td.classList.toggle("hp-oo-side-selected", putOn);
});
if (putBtn && putBtn.parentElement) {
putBtn.parentElement.classList.toggle("hp-oo-side-selected", putOn);
}
});
}
function renderTStrikes() { function renderTStrikes() {
const tbody = $("hp-oo-tbody"); const tbody = $("hp-oo-tbody");
if (!tbody) return; if (!tbody) return;
@@ -892,6 +936,7 @@
return; return;
} }
const rows = buildStraddleRows(exp.contracts); const rows = buildStraddleRows(exp.contracts);
const selected = selectedOoLegMap();
rows.forEach(function (row) { rows.forEach(function (row) {
const tr = document.createElement("tr"); const tr = document.createElement("tr");
const call = row.call; const call = row.call;
@@ -901,6 +946,8 @@
if (!callOk && !putOk) return; if (!callOk && !putOk) return;
const callAsk = callOk ? fmtPxSz(call.ask, call.ask_sz, call.ask_estimated, call.tick_sz) : "—"; const callAsk = callOk ? fmtPxSz(call.ask, call.ask_sz, call.ask_estimated, call.tick_sz) : "—";
const putAsk = putOk ? fmtPxSz(put.ask, put.ask_sz, put.ask_estimated, put.tick_sz) : "—"; const putAsk = putOk ? fmtPxSz(put.ask, put.ask_sz, put.ask_estimated, put.tick_sz) : "—";
const callLeg = callOk ? selected[String(call.inst_id)] : "";
const putLeg = putOk ? selected[String(put.inst_id)] : "";
tr.innerHTML = tr.innerHTML =
'<td class="opt-t-call opt-px-sz">' + '<td class="opt-t-call opt-px-sz">' +
callAsk + callAsk +
@@ -908,9 +955,15 @@
(callOk ? moneynessBadge(call) : "—") + (callOk ? moneynessBadge(call) : "—") +
"</td><td>" + "</td><td>" +
(callOk (callOk
? '<button type="button" class="btn-secondary hp-oo-pick" data-side="C" data-inst="' + ? '<button type="button" class="btn-secondary hp-oo-pick' +
(callLeg ? " is-selected active" : "") +
'" data-side="C" data-inst="' +
call.inst_id + call.inst_id +
'">Call</button>' '" aria-pressed="' +
(callLeg ? "true" : "false") +
'">' +
(callLeg ? "腿" + callLeg + " · Call" : "Call") +
"</button>"
: "—") + : "—") +
'</td><td class="opt-t-strike"><strong>' + '</td><td class="opt-t-strike"><strong>' +
row.strike + row.strike +
@@ -920,9 +973,15 @@
putAsk + putAsk +
"</td><td>" + "</td><td>" +
(putOk (putOk
? '<button type="button" class="btn-secondary hp-oo-pick" data-side="P" data-inst="' + ? '<button type="button" class="btn-secondary hp-oo-pick' +
(putLeg ? " is-selected active" : "") +
'" data-side="P" data-inst="' +
put.inst_id + put.inst_id +
'">Put</button>' '" aria-pressed="' +
(putLeg ? "true" : "false") +
'">' +
(putLeg ? "腿" + putLeg + " · Put" : "Put") +
"</button>"
: "—") + : "—") +
"</td>"; "</td>";
tbody.appendChild(tr); tbody.appendChild(tr);
@@ -947,6 +1006,7 @@
renderOoLegs(); renderOoLegs();
}); });
}); });
syncOoPickHighlight();
} }
function renderOoLegs() { function renderOoLegs() {
@@ -980,6 +1040,7 @@
fill("腿A", state.legA, "hp-oo-leg-a-info", "hp-oo-sheets-a"); fill("腿A", state.legA, "hp-oo-leg-a-info", "hp-oo-sheets-a");
fill("腿B", state.legB, "hp-oo-leg-b-info", "hp-oo-sheets-b"); fill("腿B", state.legB, "hp-oo-leg-b-info", "hp-oo-sheets-b");
autoFillOoSheets(); autoFillOoSheets();
syncOoPickHighlight();
} }
function ooSheets(id) { function ooSheets(id) {
+14
View File
@@ -3729,6 +3729,20 @@ html[data-theme="light"] .opt-be-dist-down {
.hedge-plan-page-wrap .opt-row-selected td { .hedge-plan-page-wrap .opt-row-selected td {
background: rgba(90, 140, 255, 0.18); background: rgba(90, 140, 255, 0.18);
} }
.hedge-plan-page-wrap .hp-oo-pick.is-selected,
.hedge-plan-page-wrap .hp-oo-pick.active {
border-color: var(--accent, #00d4ff);
color: var(--text, #fff);
background: rgba(0, 212, 255, 0.22);
box-shadow: inset 0 0 0 1px rgba(0, 212, 255, 0.45), 0 0 0 2px rgba(0, 212, 255, 0.2);
font-weight: 700;
}
.hedge-plan-page-wrap .hp-oo-side-selected {
background: rgba(0, 212, 255, 0.12);
}
.hedge-plan-page-wrap tr.hp-oo-row-selected td.opt-t-strike {
color: var(--accent, #00d4ff);
}
.hedge-plan-page-wrap .hp-tab-panel.hidden, .hedge-plan-page-wrap .hp-tab-panel.hidden,
.hedge-plan-page-wrap .hp-tab-panel[hidden] { .hedge-plan-page-wrap .hp-tab-panel[hidden] {
display: none !important; display: none !important;
@@ -327,4 +327,4 @@
</div> </div>
</div> </div>
</div> </div>
<script src="/static/hedge_plan.js?v=33"></script> <script src="/static/hedge_plan.js?v=34"></script>
+1 -1
View File
@@ -8,7 +8,7 @@
<link rel="stylesheet" href="/static/instance_theme_early.css?v=4"> <link rel="stylesheet" href="/static/instance_theme_early.css?v=4">
<link rel="stylesheet" href="/static/account_risk_badge.css?v=4"> <link rel="stylesheet" href="/static/account_risk_badge.css?v=4">
<link rel="stylesheet" href="/static/instance_page.css?v=13"> <link rel="stylesheet" href="/static/instance_page.css?v=13">
<link rel="stylesheet" href="/static/instance_theme.css?v=111"> <link rel="stylesheet" href="/static/instance_theme.css?v=112">
<script src="/static/account_risk_badge.js?v=4"></script> <script src="/static/account_risk_badge.js?v=4"></script>
<script src="/static/open_submit_gate.js?v=1"></script> <script src="/static/open_submit_gate.js?v=1"></script>
<meta name="theme-color" content="#0b0d14"> <meta name="theme-color" content="#0b0d14">
+1 -1
View File
@@ -19,7 +19,7 @@
<link rel="manifest" href="/static/icons/manifest.webmanifest"> <link rel="manifest" href="/static/icons/manifest.webmanifest">
<title>{{ pwa_app_name }}</title> <title>{{ pwa_app_name }}</title>
<link rel="stylesheet" href="/static/instance_page.css?v=13"> <link rel="stylesheet" href="/static/instance_page.css?v=13">
<link rel="stylesheet" href="/static/instance_theme.css?v=111"> <link rel="stylesheet" href="/static/instance_theme.css?v=112">
</head> </head>
<body <body