Add tabbed layout for options positions card.
Split current positions, stats, and history into tabs to save vertical space and improve readability. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -3033,7 +3033,8 @@ html[data-theme="light"] .opt-be-dist-down {
|
||||
}
|
||||
.options-chain-toolbar .btn-secondary.active,
|
||||
.opt-uly-btn.active,
|
||||
.opt-type-btn.active {
|
||||
.opt-type-btn.active,
|
||||
.opt-pos-tab.active {
|
||||
border-color: #5b8cff;
|
||||
color: #cfe0ff;
|
||||
background: rgba(74, 124, 255, 0.28);
|
||||
@@ -3191,13 +3192,49 @@ html[data-theme="light"] .options-estimate-row {
|
||||
flex-direction: column;
|
||||
min-height: 0;
|
||||
}
|
||||
.options-pos-stack {
|
||||
.options-pos-stack,
|
||||
.options-pos-tab-body {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
min-height: 0;
|
||||
}
|
||||
.options-pos-tabs {
|
||||
display: flex;
|
||||
gap: 6px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.opt-pos-tab {
|
||||
flex: 1;
|
||||
font-size: 0.78rem;
|
||||
padding: 6px 8px;
|
||||
min-height: 32px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.opt-pos-tab.active {
|
||||
border-color: #5b8cff;
|
||||
color: #cfe0ff;
|
||||
background: rgba(74, 124, 255, 0.28);
|
||||
}
|
||||
.options-pos-pane {
|
||||
display: none;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
min-height: 0;
|
||||
}
|
||||
.options-pos-pane.is-active {
|
||||
display: flex;
|
||||
}
|
||||
.options-pos-live-pane {
|
||||
flex: 1;
|
||||
min-height: 180px;
|
||||
max-height: 420px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.options-pos-live-pane.options-pos-live-pane--accordion {
|
||||
max-height: 480px;
|
||||
}
|
||||
.options-pos-subcard {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -3213,22 +3250,14 @@ html[data-theme="light"] .options-estimate-row {
|
||||
font-size: 0.78rem;
|
||||
color: #b8c0dc;
|
||||
}
|
||||
.options-pos-live-pane {
|
||||
flex: 1;
|
||||
min-height: 100px;
|
||||
max-height: 220px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.options-pos-live-pane.options-pos-live-pane--accordion {
|
||||
max-height: 360px;
|
||||
}
|
||||
.options-pos-stats-card {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.options-stats-grid {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px 14px;
|
||||
gap: 10px 16px;
|
||||
padding: 4px 2px 8px;
|
||||
}
|
||||
.options-stat-item {
|
||||
display: flex;
|
||||
@@ -3399,7 +3428,8 @@ html[data-theme="light"] .options-estimate-row {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
overflow-x: auto;
|
||||
min-height: 120px;
|
||||
min-height: 180px;
|
||||
max-height: 420px;
|
||||
}
|
||||
.opt-history-table {
|
||||
table-layout: fixed;
|
||||
@@ -3485,19 +3515,6 @@ html[data-theme="light"] .options-estimate-row {
|
||||
.options-pos-head h2 {
|
||||
margin: 0;
|
||||
}
|
||||
.options-pos-tabs {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.opt-pos-tab.active {
|
||||
border-color: #5b8cff;
|
||||
color: #cfe0ff;
|
||||
background: rgba(74, 124, 255, 0.28);
|
||||
}
|
||||
.options-pos-pane {
|
||||
min-height: 200px;
|
||||
}
|
||||
.opt-pos-card {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
selectedInst: null,
|
||||
orderQuote: null,
|
||||
expandedPosInst: null,
|
||||
posTab: "live",
|
||||
};
|
||||
|
||||
let lastGoodPositions = null;
|
||||
@@ -576,6 +577,33 @@
|
||||
}
|
||||
}
|
||||
|
||||
function setOptionsPosTab(tabId) {
|
||||
const tab = tabId || "live";
|
||||
state.posTab = tab;
|
||||
document.querySelectorAll(".opt-pos-tab").forEach(function (btn) {
|
||||
const on = btn.getAttribute("data-opt-pos-tab") === tab;
|
||||
btn.classList.toggle("active", on);
|
||||
btn.setAttribute("aria-selected", on ? "true" : "false");
|
||||
});
|
||||
document.querySelectorAll("[data-opt-pos-pane]").forEach(function (pane) {
|
||||
const on = pane.getAttribute("data-opt-pos-pane") === tab;
|
||||
pane.classList.toggle("is-active", on);
|
||||
pane.hidden = !on;
|
||||
});
|
||||
if (tab === "live" && window.OptionsExpiryCountdown && OptionsExpiryCountdown.ensureTimer) {
|
||||
OptionsExpiryCountdown.ensureTimer();
|
||||
}
|
||||
}
|
||||
|
||||
function bindOptionsPosTabs() {
|
||||
document.querySelectorAll(".opt-pos-tab").forEach(function (btn) {
|
||||
btn.addEventListener("click", function () {
|
||||
setOptionsPosTab(btn.getAttribute("data-opt-pos-tab"));
|
||||
});
|
||||
});
|
||||
setOptionsPosTab(state.posTab);
|
||||
}
|
||||
|
||||
function resolvePositionsList(d) {
|
||||
const now = Date.now();
|
||||
const list = (d && d.ok && d.positions) ? d.positions : [];
|
||||
@@ -785,6 +813,7 @@
|
||||
document.getElementById("opt-load-chain").addEventListener("click", loadChain);
|
||||
document.getElementById("opt-refresh-positions").addEventListener("click", refreshAllPositions);
|
||||
document.getElementById("opt-open-btn").addEventListener("click", openPosition);
|
||||
bindOptionsPosTabs();
|
||||
|
||||
document.querySelectorAll('input[name="opt-size-mode"]').forEach(function (r) {
|
||||
r.addEventListener("change", function () {
|
||||
|
||||
@@ -78,16 +78,19 @@
|
||||
<h2>持仓</h2>
|
||||
<button type="button" class="btn-secondary" id="opt-refresh-positions">刷新</button>
|
||||
</div>
|
||||
<div class="options-pos-stack">
|
||||
<div class="card-nested options-pos-subcard">
|
||||
<h3>当前持仓</h3>
|
||||
<div class="options-pos-tabs" role="tablist" aria-label="持仓面板">
|
||||
<button type="button" class="btn-secondary opt-pos-tab active" data-opt-pos-tab="live" role="tab" aria-selected="true" id="opt-pos-tab-live">当前持仓</button>
|
||||
<button type="button" class="btn-secondary opt-pos-tab" data-opt-pos-tab="stats" role="tab" aria-selected="false" id="opt-pos-tab-stats">数据统计</button>
|
||||
<button type="button" class="btn-secondary opt-pos-tab" data-opt-pos-tab="history" role="tab" aria-selected="false" id="opt-pos-tab-history">期权历史</button>
|
||||
</div>
|
||||
<div class="options-pos-tab-body">
|
||||
<div class="options-pos-pane is-active" data-opt-pos-pane="live" role="tabpanel" aria-labelledby="opt-pos-tab-live">
|
||||
<div id="opt-pos-live" class="panel-scroll pos-list options-pos-live-pane">
|
||||
<div class="pos-empty" id="opt-pos-empty">暂无持仓</div>
|
||||
<div id="opt-pos-cards"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-nested options-pos-subcard options-pos-stats-card">
|
||||
<h3>数据统计</h3>
|
||||
<div class="options-pos-pane" data-opt-pos-pane="stats" role="tabpanel" aria-labelledby="opt-pos-tab-stats" hidden>
|
||||
<div class="options-stats-grid">
|
||||
<div class="options-stat-item">
|
||||
<span class="k">胜率</span>
|
||||
@@ -111,8 +114,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-nested options-pos-subcard options-pos-history-card">
|
||||
<h3>期权历史</h3>
|
||||
<div class="options-pos-pane" data-opt-pos-pane="history" role="tabpanel" aria-labelledby="opt-pos-tab-history" hidden>
|
||||
<div class="options-history-table-wrap">
|
||||
<table class="options-strike-table opt-history-table" id="opt-history-table">
|
||||
<thead>
|
||||
@@ -137,4 +139,4 @@
|
||||
</div>
|
||||
</div>
|
||||
<script src="/static/options_expiry_countdown.js?v=1"></script>
|
||||
<script src="/static/options_panel.js?v=17"></script>
|
||||
<script src="/static/options_panel.js?v=18"></script>
|
||||
|
||||
Reference in New Issue
Block a user