diff --git a/lib/common/static/instance_theme.css b/lib/common/static/instance_theme.css index 1bd99fc..c12885b 100644 --- a/lib/common/static/instance_theme.css +++ b/lib/common/static/instance_theme.css @@ -3919,13 +3919,33 @@ html[data-theme="light"] .options-strike-table--t .opt-strike-row-atm td { background: rgba(255, 152, 0, 0.08); } .opt-order-inline-row td { - padding: 14px 16px !important; - background: rgba(74, 124, 255, 0.07); - border-top: 1px solid rgba(74, 124, 255, 0.25); - border-bottom: 1px solid rgba(74, 124, 255, 0.25); + padding: 0 !important; + border: none !important; + background: transparent !important; } -.opt-order-panel-inner { - border-radius: 8px; +.opt-order-backdrop { + position: fixed; + inset: 0; + z-index: 2100; + display: flex; + align-items: center; + justify-content: center; + padding: 16px; + background: rgba(0, 0, 0, 0.72); +} +.opt-order-backdrop[hidden] { + display: none !important; +} +.opt-order-dialog { + width: min(96vw, 720px); + max-height: 92vh; + overflow: auto; + background: var(--card-bg, #121726); + color: inherit; + border: 1px solid rgba(127, 127, 127, 0.35); + border-radius: 12px; + padding: 14px 16px 16px; + box-shadow: 0 12px 40px rgba(0, 0, 0, 0.45); } .opt-order-layout { display: block; @@ -4005,54 +4025,6 @@ html[data-theme="light"] .options-strike-table--t .opt-strike-row-atm td { font-size: 0.68rem; padding: 2px 8px; } -.opt-eth-order-backdrop { - position: fixed; - inset: 0; - z-index: 2100; - display: flex; - align-items: center; - justify-content: center; - padding: 16px; - background: rgba(0, 0, 0, 0.72); -} -.opt-eth-order-backdrop[hidden] { - display: none !important; -} -.opt-eth-order-dialog { - width: min(92vw, 420px); - background: var(--card-bg, #121726); - color: inherit; - border: 1px solid rgba(127, 127, 127, 0.35); - border-radius: 12px; - padding: 16px 18px 18px; - box-shadow: 0 12px 40px rgba(0, 0, 0, 0.45); -} -.opt-eth-order-dialog h3 { - margin: 0 0 8px; - font-size: 0.95rem; -} -.opt-eth-order-label { - display: block; - font-size: 0.76rem; - margin-bottom: 6px; - opacity: 0.85; -} -.opt-eth-order-dialog input[type="number"] { - width: 100%; - box-sizing: border-box; - font-size: 0.9rem; - padding: 8px 10px; - border-radius: 8px; -} -.opt-eth-order-actions { - display: flex; - flex-wrap: wrap; - gap: 8px; -} -.opt-eth-order-actions .btn-primary, -.opt-eth-order-actions .btn-secondary { - flex: 1 1 140px; -} html[data-theme="light"] .opt-pending-item { background: #fff; border-color: rgba(0, 0, 0, 0.08); @@ -4062,19 +4034,28 @@ html[data-theme="light"] .opt-pending-item { max-height: min(46vh, 360px); } } -.opt-order-panel-inner .opt-order-title { - margin: 0 0 8px; - font-size: 0.85rem; +.opt-order-dialog-head { + display: flex; + align-items: center; + gap: 8px; + margin-bottom: 10px; +} +.opt-order-dialog-head .opt-order-title { + margin: 0; + margin-right: auto; + font-size: 0.95rem; color: #9ec0ff; + font-weight: 650; } -.options-page-wrap .opt-order-panel-inner .opt-order-title { - font-size: 0.82rem; +.opt-order-dialog-actions { + display: flex; + flex-wrap: wrap; + gap: 8px; + margin-top: 10px; } -.opt-order-panel-host:not([hidden]) { - display: block; -} -.opt-order-panel-host[hidden] { - display: none !important; +.opt-order-dialog-actions .btn-primary, +.opt-order-dialog-actions .btn-secondary { + flex: 1 1 140px; } .options-order-grid { display: grid; diff --git a/lib/common/static/options_panel.js b/lib/common/static/options_panel.js index 00cd13b..d9cfbfe 100644 --- a/lib/common/static/options_panel.js +++ b/lib/common/static/options_panel.js @@ -91,16 +91,17 @@ } function parkOrderPanel() { - stopPendingOrdersPoll(); const panel = orderPanel(); const host = orderPanelHost(); - // 把整块 host(含面板)移回原位,再删行内 tr,避免 tbody 重绘销毁下单 DOM - if (host && orderPanelHome && host.parentElement !== orderPanelHome) { - orderPanelHome.appendChild(host); - } else if (panel && host && panel.parentElement !== host) { - host.appendChild(panel); + // 弹窗挂到 body;关闭后收回原位,绝不插入期权链表格 + if (panel && host && panel.parentElement !== host) host.appendChild(panel); + if (host) { + host.hidden = true; + host.setAttribute("aria-hidden", "true"); + if (orderPanelHome && host.parentElement !== orderPanelHome) { + orderPanelHome.appendChild(host); + } } - if (host) host.hidden = true; if (panel) panel.style.display = "none"; const inline = document.querySelector(".opt-order-inline-row"); if (inline) inline.remove(); @@ -121,32 +122,27 @@ document.querySelector('#opt-strike-tbody tr.opt-strike-row[data-inst="' + CSS.escape(instId) + '"]') || document.querySelector('#opt-strike-tbody tr.opt-strike-row[data-call-inst="' + CSS.escape(instId) + '"]') || document.querySelector('#opt-strike-tbody tr.opt-strike-row[data-put-inst="' + CSS.escape(instId) + '"]'); - if (!row) { - syncPickButtons(null); - return false; - } document.querySelectorAll(".opt-strike-row").forEach(function (r) { - r.classList.toggle("opt-row-selected", r === row); + r.classList.toggle("opt-row-selected", !!row && r === row); }); syncPickButtons(instId); const oldInline = document.querySelector(".opt-order-inline-row"); if (oldInline) oldInline.remove(); if (panel.parentElement !== host) host.appendChild(panel); - const tr = document.createElement("tr"); - tr.className = "opt-order-inline-row"; - const td = document.createElement("td"); - td.colSpan = strikeTableColspan(); - td.appendChild(host); - tr.appendChild(td); - row.after(tr); + // 挂到 body,避免被卡片 overflow 裁成「行内展开」 + if (host.parentElement !== document.body) document.body.appendChild(host); host.hidden = false; + host.setAttribute("aria-hidden", "false"); panel.style.display = ""; - tr.scrollIntoView({ behavior: "smooth", block: "nearest" }); - refreshPendingOrders(); - startPendingOrdersPoll(); return true; } + function closeOrderDialog() { + state.selectedInst = null; + state.orderQuote = null; + parkOrderPanel(); + } + function fmtPendingAge(sec) { if (sec == null || Number.isNaN(Number(sec))) return "—"; let s = Math.max(0, Math.round(Number(sec))); @@ -276,14 +272,15 @@ function updateSizeInputs() { const mode = currentSizeMode(); const sheetsEl = document.getElementById("opt-sheets-amount"); + const ethEl = document.getElementById("opt-eth-amount"); if (sheetsEl) sheetsEl.style.display = mode === "sheets" ? "" : "none"; + if (ethEl) ethEl.style.display = mode === "eth_amount" ? "" : "none"; } function hardenOrderAutofill() { const note = document.getElementById("opt-signal-note"); if (!note) return; function wipeNote() { - // 浏览器常把用户名(dekun)填进备注框 if (/^[a-z][a-z0-9._-]{1,31}$/i.test(String(note.value || "").trim())) { note.value = ""; } @@ -299,123 +296,6 @@ setTimeout(wipeNote, 800); } - function hideEthOrderDialog() { - const bd = document.getElementById("opt-eth-order-backdrop"); - if (bd) bd.hidden = true; - } - - function openEthOrderDialog() { - if (!state.selectedInst) { - alert("请先选择合约"); - const sheetsRadio = document.querySelector('input[name="opt-size-mode"][value="sheets"]'); - if (sheetsRadio) { - sheetsRadio.checked = true; - updateSizeInputs(); - } - return; - } - const bd = document.getElementById("opt-eth-order-backdrop"); - const instEl = document.getElementById("opt-eth-order-inst"); - const amountEl = document.getElementById("opt-eth-order-amount"); - const preview = document.getElementById("opt-eth-order-preview"); - const msg = document.getElementById("opt-eth-order-msg"); - if (instEl) instEl.textContent = state.selectedInst; - if (amountEl) { - amountEl.value = document.getElementById("opt-eth-amount").value || ""; - amountEl.focus(); - } - if (preview) preview.textContent = "输入币数量后显示张数与权利金估算"; - if (msg) { - msg.textContent = ""; - msg.classList.remove("opt-error"); - } - if (bd) bd.hidden = false; - refreshEthOrderPreview(); - } - - async function refreshEthOrderPreview() { - const preview = document.getElementById("opt-eth-order-preview"); - const amountEl = document.getElementById("opt-eth-order-amount"); - if (!preview || !amountEl || !state.selectedInst) return; - const eth = parseFloat(amountEl.value); - if (!Number.isFinite(eth) || eth <= 0) { - preview.textContent = "输入币数量后显示张数与权利金估算"; - return; - } - preview.textContent = "估算中…"; - try { - const url = - "/api/options/quote?inst_id=" + - encodeURIComponent(state.selectedInst) + - "&mode=eth_amountð_amount=" + - encodeURIComponent(String(eth)); - const d = await apiJson(url); - if (!d || !d.ok) { - preview.textContent = (d && d.msg) || "报价失败"; - return; - } - const sz = d.sizing || {}; - if (sz.ok === false) { - preview.textContent = sz.msg || "张数无效"; - return; - } - const sheets = sz.sheets != null ? sz.sheets : "—"; - const prem = sz.total_premium != null ? sz.total_premium : null; - const premTxt = prem != null ? fmt(prem, 2) + " USDC" : "—"; - preview.textContent = "约 " + sheets + " 张 · 预估权利金 " + premTxt; - } catch (e) { - preview.textContent = "报价失败"; - } - } - - async function submitEthOrderDialog() { - const amountEl = document.getElementById("opt-eth-order-amount"); - const msg = document.getElementById("opt-eth-order-msg"); - const submitBtn = document.getElementById("opt-eth-order-submit"); - const eth = amountEl ? parseFloat(amountEl.value) : NaN; - if (!Number.isFinite(eth) || eth <= 0) { - if (msg) { - msg.textContent = "请输入有效币数量"; - msg.classList.add("opt-error"); - } - return; - } - const hidden = document.getElementById("opt-eth-amount"); - if (hidden) hidden.value = String(eth); - const ethRadio = document.querySelector('input[name="opt-size-mode"][value="eth_amount"]'); - if (ethRadio) ethRadio.checked = true; - updateSizeInputs(); - if (submitBtn) submitBtn.disabled = true; - try { - if (state.selectedInst) { - await selectContract(state.selectedInst, null, true); - } - const ok = await openPosition(); - if (ok) { - hideEthOrderDialog(); - setOptionsPosTab("pending"); - } else if (msg) { - const orderMsg = document.getElementById("opt-order-msg"); - msg.textContent = (orderMsg && orderMsg.textContent) || "下单失败"; - msg.classList.add("opt-error"); - } - } finally { - if (submitBtn) submitBtn.disabled = false; - } - } - - function cancelEthOrderDialog() { - hideEthOrderDialog(); - const sheetsRadio = document.querySelector('input[name="opt-size-mode"][value="sheets"]'); - if (sheetsRadio) { - sheetsRadio.checked = true; - updateSizeInputs(); - } - const hidden = document.getElementById("opt-eth-amount"); - if (hidden) hidden.value = ""; - if (state.selectedInst) selectContract(state.selectedInst, null, true); - } - function quoteUrl(instId) { const mode = currentSizeMode(); let url = "/api/options/quote?inst_id=" + encodeURIComponent(instId) + "&mode=" + mode; @@ -1288,6 +1168,8 @@ startPendingOrdersPoll(); refreshAllPositions(); if (typeof refreshAccountSnapshot === "function") refreshAccountSnapshot(); + closeOrderDialog(); + setOptionsPosTab("pending"); return true; } alert(d.msg || "下单失败"); @@ -2191,44 +2073,31 @@ document.querySelectorAll('input[name="opt-size-mode"]').forEach(function (r) { r.addEventListener("change", function () { - const mode = currentSizeMode(); updateSizeInputs(); - if (mode === "eth_amount") { - openEthOrderDialog(); - return; - } if (state.selectedInst) selectContract(state.selectedInst, null, true); }); }); - const ethBackdrop = document.getElementById("opt-eth-order-backdrop"); - const ethCancel = document.getElementById("opt-eth-order-cancel"); - const ethSubmit = document.getElementById("opt-eth-order-submit"); - const ethAmount = document.getElementById("opt-eth-order-amount"); - if (ethCancel) ethCancel.addEventListener("click", cancelEthOrderDialog); - if (ethSubmit) ethSubmit.addEventListener("click", submitEthOrderDialog); - if (ethAmount) { - ethAmount.addEventListener("input", refreshEthOrderPreview); - ethAmount.addEventListener("change", refreshEthOrderPreview); - ethAmount.addEventListener("keydown", function (ev) { - if (ev.key === "Enter") { - ev.preventDefault(); - submitEthOrderDialog(); - } + function bindOrderDialogChrome() { + const host = orderPanelHost(); + const closeBtn = document.getElementById("opt-order-close-btn"); + const cancelBtn = document.getElementById("opt-order-cancel-btn"); + if (closeBtn) closeBtn.addEventListener("click", closeOrderDialog); + if (cancelBtn) cancelBtn.addEventListener("click", closeOrderDialog); + if (host) { + host.addEventListener("click", function (ev) { + if (ev.target === host) closeOrderDialog(); + }); + } + document.addEventListener("keydown", function (ev) { + if (ev.key !== "Escape") return; + const h = orderPanelHost(); + if (h && !h.hidden) closeOrderDialog(); }); } - if (ethBackdrop) { - ethBackdrop.addEventListener("click", function (ev) { - if (ev.target === ethBackdrop) cancelEthOrderDialog(); - }); - } - document.addEventListener("keydown", function (ev) { - if (ev.key !== "Escape") return; - const bd = document.getElementById("opt-eth-order-backdrop"); - if (bd && !bd.hidden) cancelEthOrderDialog(); - }); + bindOrderDialogChrome(); - ["opt-sheets-amount", "opt-target-idx"].forEach(function (id) { + ["opt-sheets-amount", "opt-eth-amount", "opt-target-idx"].forEach(function (id) { const el = document.getElementById(id); if (!el) return; el.addEventListener("change", function () { diff --git a/lib/instance/templates/embed_shell.html b/lib/instance/templates/embed_shell.html index 3884997..d02f1dd 100644 --- a/lib/instance/templates/embed_shell.html +++ b/lib/instance/templates/embed_shell.html @@ -7,7 +7,7 @@ - + {{ pwa_app_name }} diff --git a/lib/instance/templates/index.html b/lib/instance/templates/index.html index 26142c9..0f65049 100644 --- a/lib/instance/templates/index.html +++ b/lib/instance/templates/index.html @@ -17,7 +17,7 @@ {{ pwa_app_name }} - + -