diff --git a/lib/common/static/hedge_plan.js b/lib/common/static/hedge_plan.js
index 785ade2..60100f4 100644
--- a/lib/common/static/hedge_plan.js
+++ b/lib/common/static/hedge_plan.js
@@ -35,6 +35,9 @@
fundingUsdc: null,
tradeBudgetUsdc: null,
budgetBuffer: 0.95,
+ previewOk: false,
+ canStart: false,
+ previewPlanType: null,
};
function $(id) {
@@ -169,13 +172,24 @@
];
if (gates.reasons && gates.reasons.length) parts.push(gates.reasons.join("; "));
el.textContent = parts.join(" · ");
- const start = $("hp-start-btn");
- const startOo = $("hp-start-btn-oo");
- if ((gates.plan_type || state.mode) === "options_options") {
- if (startOo) startOo.disabled = !gates.can_start;
- } else {
- if (start) start.disabled = !gates.can_start;
- }
+ state.canStart = !!gates.can_start;
+ syncPreviewStartBtn();
+ }
+
+ function syncPreviewStartBtn() {
+ const start = $("hp-preview-start");
+ if (!start) return;
+ start.disabled = !(state.previewOk && state.canStart);
+ }
+
+ function openPreviewModal() {
+ const modal = $("hp-preview-modal");
+ if (modal) modal.hidden = false;
+ }
+
+ function closePreviewModal() {
+ const modal = $("hp-preview-modal");
+ if (modal) modal.hidden = true;
}
function setOptionsBalance(chain) {
@@ -851,8 +865,18 @@
async function runPreview() {
const isOo = state.mode === "options_options";
- const tbody = $(isOo ? "hp-result-tbody-oo" : "hp-result-tbody");
- const summary = $(isOo ? "hp-summary-oo" : "hp-summary");
+ const tbody = $("hp-result-tbody");
+ const summary = $("hp-preview-summary");
+ const midTh = $("hp-preview-mid-th");
+ const title = $("hp-preview-title");
+ state.previewOk = false;
+ state.previewPlanType = isOo ? "options_options" : "perp_options";
+ syncPreviewStartBtn();
+ if (midTh) midTh.textContent = isOo ? "腿盈亏" : "永续/腿盈亏";
+ if (title) title.textContent = isOo ? "情景测算 · 期期" : "情景测算 · 永期";
+ if (summary) summary.textContent = "";
+ if (tbody) tbody.innerHTML = '
| 计算中… |
';
+ openPreviewModal();
try {
let body;
if (isOo) {
@@ -949,7 +973,11 @@
"";
tbody.appendChild(tr);
});
+ state.previewOk = true;
+ syncPreviewStartBtn();
} catch (e) {
+ state.previewOk = false;
+ syncPreviewStartBtn();
if (tbody) tbody.innerHTML = '| ' + (e.message || e) + " |
";
if (summary) summary.textContent = "";
}
@@ -1075,14 +1103,19 @@
state.mode = "options_options";
void runPreview();
});
- if ($("hp-start-btn"))
- $("hp-start-btn").addEventListener("click", function () {
- void startPlan("perp_options");
+ if ($("hp-preview-cancel")) $("hp-preview-cancel").addEventListener("click", closePreviewModal);
+ if ($("hp-preview-cancel-x")) $("hp-preview-cancel-x").addEventListener("click", closePreviewModal);
+ if ($("hp-preview-start"))
+ $("hp-preview-start").addEventListener("click", function () {
+ const planType = state.previewPlanType || state.mode;
+ void startPlan(planType, true);
});
- if ($("hp-start-btn-oo"))
- $("hp-start-btn-oo").addEventListener("click", function () {
- void startPlan("options_options");
+ const previewModal = $("hp-preview-modal");
+ if (previewModal) {
+ previewModal.addEventListener("click", function (ev) {
+ if (ev.target === previewModal) closePreviewModal();
});
+ }
if ($("hp-detail-close")) $("hp-detail-close").addEventListener("click", closeModal);
const modal = $("hp-detail-modal");
if (modal) {
@@ -1442,8 +1475,9 @@
}
}
- async function startPlan(planType) {
+ async function startPlan(planType, fromPreviewModal) {
const isOo = planType === "options_options";
+ const startBtn = $("hp-preview-start");
try {
let body;
if (isOo) {
@@ -1487,17 +1521,22 @@
margin: state.market && state.market.full_margin_sizing && state.market.full_margin_sizing.margin_capital,
};
}
- if (!window.confirm("确认启动对冲计划并真实下单?\n(将按期权账户/合约账户分别下单)")) return;
+ if (!fromPreviewModal) {
+ if (!window.confirm("确认启动对冲计划并真实下单?\n(将按期权账户/合约账户分别下单)")) return;
+ }
+ if (startBtn) startBtn.disabled = true;
const d = await apiJson("/api/hedge-plan/start", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(body),
});
setGateLine(d.gates);
+ closePreviewModal();
alert("计划已启动 #" + (d.plan_id || "") + (d.dry_run ? " (dry_run)" : ""));
void loadGates();
} catch (e) {
alert(e.message || String(e));
+ syncPreviewStartBtn();
}
}
diff --git a/lib/common/static/instance_theme.css b/lib/common/static/instance_theme.css
index b62e248..8d4fd2c 100644
--- a/lib/common/static/instance_theme.css
+++ b/lib/common/static/instance_theme.css
@@ -3536,15 +3536,24 @@ html[data-theme="light"] .opt-be-dist-down {
display: flex;
flex-direction: column;
}
-.hedge-plan-page-wrap .hp-preview-card {
- margin-top: 0;
- clear: both;
-}
.hedge-plan-page-wrap .hp-action-row {
margin-top: 10px;
gap: 8px;
justify-content: flex-end;
}
+.hedge-plan-page-wrap .hp-preview-modal {
+ width: min(96vw, 920px);
+}
+.hedge-plan-page-wrap .hp-preview-summary {
+ margin: 0 0 10px;
+ font-size: 0.84rem;
+ line-height: 1.45;
+}
+.hedge-plan-page-wrap .hp-preview-actions {
+ margin-top: 14px;
+ justify-content: flex-end;
+ gap: 10px;
+}
.hedge-plan-page-wrap .hp-pick.active,
.hedge-plan-page-wrap .opt-row-selected td {
background: rgba(90, 140, 255, 0.18);
diff --git a/lib/hedge_plan/templates/hedge_plan_panel.html b/lib/hedge_plan/templates/hedge_plan_panel.html
index e165f0c..2251c23 100644
--- a/lib/hedge_plan/templates/hedge_plan_panel.html
+++ b/lib/hedge_plan/templates/hedge_plan_panel.html
@@ -97,31 +97,9 @@
-
-
-
情景测算
-
-
-
-
-
- | 情景 |
- 现货价 |
- 永续/腿盈亏 |
- 期权盈亏 |
- 合计≈U |
- 说明 |
-
-
-
- | 填写参数后点计算 |
-
-
-
-
@@ -215,31 +193,9 @@
-
-
-
情景测算
-
-
-
-
-
- | 情景 |
- 现货价 |
- 腿盈亏 |
- 期权 |
- 合计≈U |
- 说明 |
-
-
-
- | 选用两腿并填上破/下破目标后点计算 |
-
-
-
-
@@ -297,5 +253,36 @@
加载中…
+
+
+
+
+
情景测算
+
+
+
+
+
+
+
+ | 情景 |
+ 现货价 |
+ 永续/腿盈亏 |
+ 期权盈亏 |
+ 合计≈U |
+ 说明 |
+
+
+
+ | 计算中… |
+
+
+
+
+
+
+
+
+
-
+