feat: options UI scroll layout, stats card, funding balance, and cross-account transfer

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-07-07 09:57:13 +08:00
parent 090b9c6215
commit e82fd15bb7
12 changed files with 245 additions and 66 deletions
+70 -1
View File
@@ -2356,8 +2356,16 @@ html[data-theme="light"] .settings-export-link {
}
.options-strike-table-wrap {
overflow-x: auto;
overflow-y: auto;
max-height: 352px;
margin-top: 8px;
}
.options-strike-table thead th {
position: sticky;
top: 0;
z-index: 1;
background: rgba(18, 24, 38, 0.98);
}
.options-strike-table {
width: 100%;
border-collapse: collapse;
@@ -2462,7 +2470,68 @@ html[data-theme="light"] .settings-export-link {
display: grid;
grid-template-columns: 1.15fr 0.85fr;
gap: 16px;
align-items: start;
align-items: stretch;
}
.options-order-card,
.options-pos-card-wrap {
display: flex;
flex-direction: column;
min-height: 0;
}
.options-pos-stack {
flex: 1;
display: flex;
flex-direction: column;
gap: 10px;
min-height: 0;
}
.options-pos-subcard {
display: flex;
flex-direction: column;
min-height: 0;
}
.options-pos-subcard h3 {
margin: 0 0 8px;
font-size: 0.95rem;
font-weight: 600;
}
.options-pos-live-pane {
flex: 1;
min-height: 100px;
max-height: 220px;
overflow-y: auto;
}
.options-pos-stats-card {
flex-shrink: 0;
}
.options-stats-grid {
display: flex;
flex-wrap: wrap;
gap: 16px 24px;
}
.options-stat-item {
display: flex;
flex-direction: column;
gap: 4px;
}
.options-stat-item .k {
font-size: 0.78rem;
opacity: 0.7;
}
.options-stat-item .v {
font-size: 1.1rem;
font-weight: 600;
}
.options-pos-history-card {
flex: 1;
min-height: 0;
display: flex;
flex-direction: column;
}
.options-history-table-wrap {
flex: 1;
overflow-y: auto;
min-height: 120px;
}
@media (max-width: 1100px) {
.options-dual-grid {
+26 -23
View File
@@ -9,7 +9,6 @@
optType: "C",
chain: null,
selectedInst: null,
posTab: "live",
};
function fmt(v, d) {
@@ -289,7 +288,7 @@
msgEl.textContent = d.ok ? "下单已提交,可在 OKX 委托中查看" : (d.msg || "失败");
msgEl.classList.toggle("opt-error", !d.ok);
if (d.ok) {
refreshPositions();
refreshAllPositions();
if (typeof refreshAccountSnapshot === "function") refreshAccountSnapshot();
} else {
alert(d.msg || "下单失败");
@@ -349,8 +348,7 @@
} else {
alert(r.msg || "平仓失败");
}
refreshPositions();
refreshHistory();
refreshAllPositions();
if (typeof refreshAccountSnapshot === "function") refreshAccountSnapshot();
} finally {
if (btn) btn.disabled = false;
@@ -380,6 +378,24 @@
});
}
async function refreshStats() {
const d = await apiJson("/api/options/stats");
const winEl = document.getElementById("opt-stats-winrate");
const plrEl = document.getElementById("opt-stats-plr");
const closedEl = document.getElementById("opt-stats-closed");
if (!d.ok) {
if (winEl) winEl.textContent = "—";
if (plrEl) plrEl.textContent = "—";
if (closedEl) closedEl.textContent = "—";
return;
}
if (winEl) winEl.textContent = d.total_closed ? d.win_rate + "%" : "0%";
if (plrEl) {
plrEl.textContent = d.profit_loss_ratio != null ? String(d.profit_loss_ratio) : "—";
}
if (closedEl) closedEl.textContent = String(d.total_closed || 0);
}
async function refreshHistory() {
const d = await apiJson("/api/options/history");
const tbody = document.getElementById("opt-history-tbody");
@@ -405,14 +421,10 @@
});
}
function switchPosTab(tab) {
state.posTab = tab;
document.querySelectorAll(".opt-pos-tab").forEach(function (b) {
b.classList.toggle("active", b.getAttribute("data-tab") === tab);
});
document.getElementById("opt-pos-live").hidden = tab !== "live";
document.getElementById("opt-pos-history").hidden = tab !== "history";
if (tab === "history") refreshHistory();
function refreshAllPositions() {
refreshPositions();
refreshStats();
refreshHistory();
}
document.querySelectorAll(".opt-uly-btn").forEach(function (btn) {
@@ -433,18 +445,9 @@
});
});
document.querySelectorAll(".opt-pos-tab").forEach(function (btn) {
btn.addEventListener("click", function () {
switchPosTab(btn.getAttribute("data-tab"));
});
});
document.getElementById("opt-exp-select").addEventListener("change", renderStrikes);
document.getElementById("opt-load-chain").addEventListener("click", loadChain);
document.getElementById("opt-refresh-positions").addEventListener("click", function () {
refreshPositions();
if (state.posTab === "history") refreshHistory();
});
document.getElementById("opt-refresh-positions").addEventListener("click", refreshAllPositions);
document.getElementById("opt-open-btn").addEventListener("click", openPosition);
document.querySelectorAll('input[name="opt-size-mode"]').forEach(function (r) {
@@ -464,5 +467,5 @@
updateSizeInputs();
loadChain();
refreshPositions();
refreshAllPositions();
})();
+3 -1
View File
@@ -64,10 +64,12 @@
body: JSON.stringify({
ccy: document.getElementById("opt-set-cross-ccy").value,
amount: amount,
account: document.getElementById("opt-set-cross-acct").value,
from_account: document.getElementById("opt-set-cross-from-acct").value,
to_account: document.getElementById("opt-set-cross-to-acct").value,
direction: document.getElementById("opt-set-cross-dir").value,
}),
});
setMsg("opt-set-cross-msg", d.ok ? "划转成功" : (d.msg || "失败"), !d.ok);
if (d.ok && typeof refreshAccountSnapshot === "function") refreshAccountSnapshot();
});
})();