fix(hedge): equal-height right shell card with strategy status
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -421,6 +421,62 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isPoOptionPrimaryPlan(p) {
|
||||||
|
if (!p || p.plan_type !== "perp_options") return false;
|
||||||
|
return p.option_primary == 1 || p.option_primary === true || Number(p.option_primary) === 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setPoStrategyStatus(kind, planId) {
|
||||||
|
const el = $("hp-po-strategy-status");
|
||||||
|
if (!el) return;
|
||||||
|
el.classList.remove("is-watching", "is-holding", "is-idle");
|
||||||
|
if (!isOptionPrimary()) {
|
||||||
|
el.textContent = "";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const idPart = planId ? " #" + planId : "";
|
||||||
|
if (kind === "watching") {
|
||||||
|
el.textContent = "盯盘中" + idPart;
|
||||||
|
el.classList.add("is-watching");
|
||||||
|
} else if (kind === "holding") {
|
||||||
|
el.textContent = "持仓中" + idPart;
|
||||||
|
el.classList.add("is-holding");
|
||||||
|
} else {
|
||||||
|
el.textContent = "未启动";
|
||||||
|
el.classList.add("is-idle");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function refreshPoStrategyStatus() {
|
||||||
|
const el = $("hp-po-strategy-status");
|
||||||
|
if (!el) return;
|
||||||
|
if (!isOptionPrimary()) {
|
||||||
|
setPoStrategyStatus("", null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const d = await apiJson("/api/hedge-plan/active");
|
||||||
|
const uly = (state.underlying || "ETH").toUpperCase();
|
||||||
|
const rows = (d.plans || []).filter(function (p) {
|
||||||
|
return isPoOptionPrimaryPlan(p) && String(p.underlying || "").toUpperCase() === uly;
|
||||||
|
});
|
||||||
|
if (!rows.length) {
|
||||||
|
setPoStrategyStatus("idle", null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
rows.sort(function (a, b) {
|
||||||
|
return Number(b.id || 0) - Number(a.id || 0);
|
||||||
|
});
|
||||||
|
const p = rows[0];
|
||||||
|
const st = String(p.status || "");
|
||||||
|
if (st === "watching") setPoStrategyStatus("watching", p.id);
|
||||||
|
else if (st === "active" || st === "opening" || st === "partial") setPoStrategyStatus("holding", p.id);
|
||||||
|
else setPoStrategyStatus("idle", null);
|
||||||
|
} catch (e) {
|
||||||
|
/* ignore status refresh errors */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function syncOoRecommendUI() {
|
function syncOoRecommendUI() {
|
||||||
const cur = state.ooRecommend || "";
|
const cur = state.ooRecommend || "";
|
||||||
document.querySelectorAll(".hp-oo-recommend-btn").forEach(function (b) {
|
document.querySelectorAll(".hp-oo-recommend-btn").forEach(function (b) {
|
||||||
@@ -1747,6 +1803,7 @@
|
|||||||
syncTabUI();
|
syncTabUI();
|
||||||
if (state.tab === "perp_options" || state.tab === "options_options") {
|
if (state.tab === "perp_options" || state.tab === "options_options") {
|
||||||
void loadGates();
|
void loadGates();
|
||||||
|
if (state.tab === "perp_options") void refreshPoStrategyStatus();
|
||||||
} else if (state.tab === "active") {
|
} else if (state.tab === "active") {
|
||||||
void loadActivePlans();
|
void loadActivePlans();
|
||||||
} else if (state.tab === "history") {
|
} else if (state.tab === "history") {
|
||||||
@@ -2167,6 +2224,7 @@
|
|||||||
void loadActivePlans();
|
void loadActivePlans();
|
||||||
void loadHistory();
|
void loadHistory();
|
||||||
void loadGates();
|
void loadGates();
|
||||||
|
void refreshPoStrategyStatus();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
alert(e.message || String(e));
|
alert(e.message || String(e));
|
||||||
}
|
}
|
||||||
@@ -2531,10 +2589,9 @@
|
|||||||
body: JSON.stringify(body),
|
body: JSON.stringify(body),
|
||||||
});
|
});
|
||||||
setGateLine(d.gates);
|
setGateLine(d.gates);
|
||||||
|
setPoStrategyStatus("watching", d.plan_id || null);
|
||||||
alert((d.msg || "已启动盯盘") + (d.plan_id ? "\n计划 #" + d.plan_id : ""));
|
alert((d.msg || "已启动盯盘") + (d.plan_id ? "\n计划 #" + d.plan_id : ""));
|
||||||
state.tab = "active";
|
void refreshPoStrategyStatus();
|
||||||
syncTabUI();
|
|
||||||
void loadActivePlans();
|
|
||||||
void loadGates();
|
void loadGates();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
alert(e.message || String(e));
|
alert(e.message || String(e));
|
||||||
@@ -2688,6 +2745,7 @@
|
|||||||
const tbody = $("hp-strike-tbody");
|
const tbody = $("hp-strike-tbody");
|
||||||
if (tbody) tbody.innerHTML = '<tr><td colspan="6" class="err">' + (e.message || e) + "</td></tr>";
|
if (tbody) tbody.innerHTML = '<tr><td colspan="6" class="err">' + (e.message || e) + "</td></tr>";
|
||||||
}
|
}
|
||||||
|
if (state.tab === "perp_options") void refreshPoStrategyStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
syncTabUI();
|
syncTabUI();
|
||||||
@@ -2702,5 +2760,10 @@
|
|||||||
updateOoBudgetLine(null);
|
updateOoBudgetLine(null);
|
||||||
bind();
|
bind();
|
||||||
syncOptionPrimaryUI();
|
syncOptionPrimaryUI();
|
||||||
void refreshAll();
|
void refreshAll().then(function () {
|
||||||
|
void refreshPoStrategyStatus();
|
||||||
|
});
|
||||||
|
setInterval(function () {
|
||||||
|
if (state.tab === "perp_options" && isOptionPrimary()) void refreshPoStrategyStatus();
|
||||||
|
}, 15000);
|
||||||
})();
|
})();
|
||||||
|
|||||||
@@ -3542,12 +3542,57 @@ html[data-theme="light"] .opt-be-dist-down {
|
|||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.hedge-plan-page-wrap .hp-po-right-card {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
min-width: 0;
|
||||||
|
min-height: 0;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
.hedge-plan-page-wrap .hp-po-right-stack {
|
.hedge-plan-page-wrap .hp-po-right-stack {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 12px;
|
gap: 10px;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
|
flex: 1 1 auto;
|
||||||
|
}
|
||||||
|
.hedge-plan-page-wrap .hp-po-inner-card {
|
||||||
|
margin: 0;
|
||||||
|
padding: 10px 12px;
|
||||||
|
border-radius: 8px;
|
||||||
|
background: rgba(255, 255, 255, 0.03);
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.08);
|
||||||
|
min-width: 0;
|
||||||
|
min-height: 0;
|
||||||
|
}
|
||||||
|
.hedge-plan-page-wrap .hp-po-inner-card > h2 {
|
||||||
|
margin: 0 0 8px;
|
||||||
|
font-size: 0.95rem;
|
||||||
|
}
|
||||||
|
.hedge-plan-page-wrap .hp-po-action-row {
|
||||||
|
margin-top: auto;
|
||||||
|
padding-top: 10px;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
.hedge-plan-page-wrap .hp-po-strategy-status {
|
||||||
|
font-size: 0.86rem;
|
||||||
|
font-weight: 700;
|
||||||
|
letter-spacing: 0.02em;
|
||||||
|
min-height: 1.2em;
|
||||||
|
}
|
||||||
|
.hedge-plan-page-wrap .hp-po-strategy-status.is-watching {
|
||||||
|
color: #fbbf24;
|
||||||
|
}
|
||||||
|
.hedge-plan-page-wrap .hp-po-strategy-status.is-holding {
|
||||||
|
color: #3dd68c;
|
||||||
|
}
|
||||||
|
.hedge-plan-page-wrap .hp-po-strategy-status.is-idle {
|
||||||
|
color: #6b7388;
|
||||||
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
.hedge-plan-page-wrap .hp-po-quote-head {
|
.hedge-plan-page-wrap .hp-po-quote-head {
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -3841,19 +3886,30 @@ html[data-theme="light"] .opt-be-dist-down {
|
|||||||
align-items: stretch;
|
align-items: stretch;
|
||||||
margin-bottom: 28px;
|
margin-bottom: 28px;
|
||||||
}
|
}
|
||||||
.hedge-plan-page-wrap .options-dual-grid > .card,
|
.hedge-plan-page-wrap .options-dual-grid > .card {
|
||||||
.hedge-plan-page-wrap .hp-po-right-stack > .card {
|
|
||||||
height: 100%;
|
height: 100%;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
.hedge-plan-page-wrap #hp-po-layout {
|
||||||
|
align-items: stretch;
|
||||||
|
}
|
||||||
|
.hedge-plan-page-wrap #hp-po-layout > .card {
|
||||||
|
align-self: stretch;
|
||||||
|
}
|
||||||
.hedge-plan-page-wrap .hp-po-right-stack > .hp-po-perp-quote-card {
|
.hedge-plan-page-wrap .hp-po-right-stack > .hp-po-perp-quote-card {
|
||||||
height: auto;
|
height: auto;
|
||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
}
|
}
|
||||||
.hedge-plan-page-wrap .hp-po-right-stack > .hp-opt-card {
|
.hedge-plan-page-wrap .hp-po-right-stack > .hp-opt-card {
|
||||||
flex: 1 1 auto;
|
flex: 1 1 auto;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
min-height: 0;
|
||||||
|
}
|
||||||
|
.hedge-plan-page-wrap .hp-po-right-stack > .hp-opt-card .hp-strike-table-wrap--6 {
|
||||||
|
flex: 1 1 auto;
|
||||||
}
|
}
|
||||||
.hedge-plan-page-wrap .hp-action-row {
|
.hedge-plan-page-wrap .hp-action-row {
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
|
|||||||
@@ -149,8 +149,9 @@
|
|||||||
<div id="hp-sizing-line" class="muted hp-po-sizing"></div>
|
<div id="hp-sizing-line" class="muted hp-po-sizing"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="card hp-po-right-card">
|
||||||
<div class="hp-po-right-stack">
|
<div class="hp-po-right-stack">
|
||||||
<div class="card hp-po-perp-quote-card">
|
<div class="hp-po-inner-card hp-po-perp-quote-card">
|
||||||
<h2>永续行情 <span class="muted hp-acct-tag">合约账户</span></h2>
|
<h2>永续行情 <span class="muted hp-acct-tag">合约账户</span></h2>
|
||||||
<div class="hp-po-quote-head">
|
<div class="hp-po-quote-head">
|
||||||
<span id="hp-po-mark" class="hp-po-mark" aria-live="polite">标记 —</span>
|
<span id="hp-po-mark" class="hp-po-mark" aria-live="polite">标记 —</span>
|
||||||
@@ -158,7 +159,7 @@
|
|||||||
<p id="hp-perp-quote" class="muted hp-po-meta">加载中…</p>
|
<p id="hp-perp-quote" class="muted hp-po-meta">加载中…</p>
|
||||||
<p id="hp-po-perp-quote-right" class="muted hp-po-meta" hidden></p>
|
<p id="hp-po-perp-quote-right" class="muted hp-po-meta" hidden></p>
|
||||||
</div>
|
</div>
|
||||||
<div class="card hp-opt-card">
|
<div class="hp-po-inner-card hp-opt-card">
|
||||||
<h2>期权 · <span id="hp-opt-type-label">Call</span> <span class="muted hp-acct-tag" id="hp-opt-acct-tag">期权账户</span></h2>
|
<h2>期权 · <span id="hp-opt-type-label">Call</span> <span class="muted hp-acct-tag" id="hp-opt-acct-tag">期权账户</span></h2>
|
||||||
<div class="form-row hp-opt-toolbar hp-po-opt-toolbar">
|
<div class="form-row hp-opt-toolbar hp-po-opt-toolbar">
|
||||||
<select id="hp-exp-select"><option value="">选择到期日</option></select>
|
<select id="hp-exp-select"><option value="">选择到期日</option></select>
|
||||||
@@ -193,10 +194,12 @@
|
|||||||
<span class="muted" id="hp-premium-line"></span>
|
<span class="muted" id="hp-premium-line"></span>
|
||||||
</div>
|
</div>
|
||||||
<div id="hp-opt-bal-line" class="muted hp-po-meta hp-opt-bal-line"></div>
|
<div id="hp-opt-bal-line" class="muted hp-po-meta hp-opt-bal-line"></div>
|
||||||
<div class="form-row hp-action-row">
|
|
||||||
<button type="button" class="primary" id="hp-preview-btn" title="以期权为主=盯盘启动">策略启动</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-row hp-action-row hp-po-action-row">
|
||||||
|
<span id="hp-po-strategy-status" class="hp-po-strategy-status" aria-live="polite"></span>
|
||||||
|
<button type="button" class="primary" id="hp-preview-btn" title="以期权为主=盯盘启动">策略启动</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -403,4 +406,4 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<script src="/static/hedge_plan.js?v=43"></script>
|
<script src="/static/hedge_plan.js?v=44"></script>
|
||||||
|
|||||||
Reference in New Issue
Block a user