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,
|
.options-chain-toolbar .btn-secondary.active,
|
||||||
.opt-uly-btn.active,
|
.opt-uly-btn.active,
|
||||||
.opt-type-btn.active {
|
.opt-type-btn.active,
|
||||||
|
.opt-pos-tab.active {
|
||||||
border-color: #5b8cff;
|
border-color: #5b8cff;
|
||||||
color: #cfe0ff;
|
color: #cfe0ff;
|
||||||
background: rgba(74, 124, 255, 0.28);
|
background: rgba(74, 124, 255, 0.28);
|
||||||
@@ -3191,13 +3192,49 @@ html[data-theme="light"] .options-estimate-row {
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
}
|
}
|
||||||
.options-pos-stack {
|
.options-pos-stack,
|
||||||
|
.options-pos-tab-body {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
min-height: 0;
|
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 {
|
.options-pos-subcard {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@@ -3213,22 +3250,14 @@ html[data-theme="light"] .options-estimate-row {
|
|||||||
font-size: 0.78rem;
|
font-size: 0.78rem;
|
||||||
color: #b8c0dc;
|
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 {
|
.options-pos-stats-card {
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
.options-stats-grid {
|
.options-stats-grid {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
gap: 8px 14px;
|
gap: 10px 16px;
|
||||||
|
padding: 4px 2px 8px;
|
||||||
}
|
}
|
||||||
.options-stat-item {
|
.options-stat-item {
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -3399,7 +3428,8 @@ html[data-theme="light"] .options-estimate-row {
|
|||||||
flex: 1;
|
flex: 1;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
min-height: 120px;
|
min-height: 180px;
|
||||||
|
max-height: 420px;
|
||||||
}
|
}
|
||||||
.opt-history-table {
|
.opt-history-table {
|
||||||
table-layout: fixed;
|
table-layout: fixed;
|
||||||
@@ -3485,19 +3515,6 @@ html[data-theme="light"] .options-estimate-row {
|
|||||||
.options-pos-head h2 {
|
.options-pos-head h2 {
|
||||||
margin: 0;
|
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 {
|
.opt-pos-card {
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
selectedInst: null,
|
selectedInst: null,
|
||||||
orderQuote: null,
|
orderQuote: null,
|
||||||
expandedPosInst: null,
|
expandedPosInst: null,
|
||||||
|
posTab: "live",
|
||||||
};
|
};
|
||||||
|
|
||||||
let lastGoodPositions = null;
|
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) {
|
function resolvePositionsList(d) {
|
||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
const list = (d && d.ok && d.positions) ? d.positions : [];
|
const list = (d && d.ok && d.positions) ? d.positions : [];
|
||||||
@@ -785,6 +813,7 @@
|
|||||||
document.getElementById("opt-load-chain").addEventListener("click", loadChain);
|
document.getElementById("opt-load-chain").addEventListener("click", loadChain);
|
||||||
document.getElementById("opt-refresh-positions").addEventListener("click", refreshAllPositions);
|
document.getElementById("opt-refresh-positions").addEventListener("click", refreshAllPositions);
|
||||||
document.getElementById("opt-open-btn").addEventListener("click", openPosition);
|
document.getElementById("opt-open-btn").addEventListener("click", openPosition);
|
||||||
|
bindOptionsPosTabs();
|
||||||
|
|
||||||
document.querySelectorAll('input[name="opt-size-mode"]').forEach(function (r) {
|
document.querySelectorAll('input[name="opt-size-mode"]').forEach(function (r) {
|
||||||
r.addEventListener("change", function () {
|
r.addEventListener("change", function () {
|
||||||
|
|||||||
@@ -78,16 +78,19 @@
|
|||||||
<h2>持仓</h2>
|
<h2>持仓</h2>
|
||||||
<button type="button" class="btn-secondary" id="opt-refresh-positions">刷新</button>
|
<button type="button" class="btn-secondary" id="opt-refresh-positions">刷新</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="options-pos-stack">
|
<div class="options-pos-tabs" role="tablist" aria-label="持仓面板">
|
||||||
<div class="card-nested options-pos-subcard">
|
<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>
|
||||||
<h3>当前持仓</h3>
|
<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 id="opt-pos-live" class="panel-scroll pos-list options-pos-live-pane">
|
||||||
<div class="pos-empty" id="opt-pos-empty">暂无持仓</div>
|
<div class="pos-empty" id="opt-pos-empty">暂无持仓</div>
|
||||||
<div id="opt-pos-cards"></div>
|
<div id="opt-pos-cards"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-nested options-pos-subcard options-pos-stats-card">
|
<div class="options-pos-pane" data-opt-pos-pane="stats" role="tabpanel" aria-labelledby="opt-pos-tab-stats" hidden>
|
||||||
<h3>数据统计</h3>
|
|
||||||
<div class="options-stats-grid">
|
<div class="options-stats-grid">
|
||||||
<div class="options-stat-item">
|
<div class="options-stat-item">
|
||||||
<span class="k">胜率</span>
|
<span class="k">胜率</span>
|
||||||
@@ -111,8 +114,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-nested options-pos-subcard options-pos-history-card">
|
<div class="options-pos-pane" data-opt-pos-pane="history" role="tabpanel" aria-labelledby="opt-pos-tab-history" hidden>
|
||||||
<h3>期权历史</h3>
|
|
||||||
<div class="options-history-table-wrap">
|
<div class="options-history-table-wrap">
|
||||||
<table class="options-strike-table opt-history-table" id="opt-history-table">
|
<table class="options-strike-table opt-history-table" id="opt-history-table">
|
||||||
<thead>
|
<thead>
|
||||||
@@ -137,4 +139,4 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<script src="/static/options_expiry_countdown.js?v=1"></script>
|
<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