diff --git a/crypto_monitor_binance/templates/index.html b/crypto_monitor_binance/templates/index.html index 14925b9..0a9be8d 100644 --- a/crypto_monitor_binance/templates/index.html +++ b/crypto_monitor_binance/templates/index.html @@ -3,8 +3,9 @@ - - + + + @@ -236,7 +237,6 @@ .stats-period-block .sub{font-size:.78rem;color:#8892b0;margin-bottom:10px;line-height:1.4} - diff --git a/crypto_monitor_gate/templates/index.html b/crypto_monitor_gate/templates/index.html index 9f2b5c6..ab864db 100644 --- a/crypto_monitor_gate/templates/index.html +++ b/crypto_monitor_gate/templates/index.html @@ -3,8 +3,9 @@ - - + + + @@ -236,7 +237,6 @@ .stats-period-block .sub{font-size:.78rem;color:#8892b0;margin-bottom:10px;line-height:1.4} - diff --git a/crypto_monitor_gate_bot/templates/index.html b/crypto_monitor_gate_bot/templates/index.html index 9f2b5c6..ab864db 100644 --- a/crypto_monitor_gate_bot/templates/index.html +++ b/crypto_monitor_gate_bot/templates/index.html @@ -3,8 +3,9 @@ - - + + + @@ -236,7 +237,6 @@ .stats-period-block .sub{font-size:.78rem;color:#8892b0;margin-bottom:10px;line-height:1.4} - diff --git a/crypto_monitor_okx/templates/index.html b/crypto_monitor_okx/templates/index.html index c63918a..a32063c 100644 --- a/crypto_monitor_okx/templates/index.html +++ b/crypto_monitor_okx/templates/index.html @@ -3,8 +3,9 @@ - - + + + @@ -236,7 +237,6 @@ .stats-period-block .sub{font-size:.78rem;color:#8892b0;margin-bottom:10px;line-height:1.4} - diff --git a/manual_trading_hub/static/app.css b/manual_trading_hub/static/app.css index f4c637e..efd6c72 100644 --- a/manual_trading_hub/static/app.css +++ b/manual_trading_hub/static/app.css @@ -1092,10 +1092,6 @@ body.market-chart-fs-open { background: var(--bg); } -.instance-frame-shell.is-instance-nav-loading .instance-frame { - visibility: hidden; -} - .exchange-fullscreen { position: fixed; inset: 0; diff --git a/manual_trading_hub/static/app.js b/manual_trading_hub/static/app.js index 1998a68..0923853 100644 --- a/manual_trading_hub/static/app.js +++ b/manual_trading_hub/static/app.js @@ -371,11 +371,6 @@ return j.url; } - function setInstanceFrameNavLoading(loading) { - const shell = document.getElementById("instance-frame-shell"); - if (shell) shell.classList.toggle("is-instance-nav-loading", !!loading); - } - async function openInstance(exchangeId, nextPath, opts) { const options = opts || {}; const newTab = !!options.newTab; @@ -428,10 +423,7 @@ ); instanceFrameUrl = url; const frame = document.getElementById("instance-frame"); - if (frame) { - setInstanceFrameNavLoading(true); - frame.src = url; - } + if (frame) frame.src = url; } catch (e) { showToast(String(e), true); } @@ -448,7 +440,6 @@ closeExchangeFullscreen(); instanceFrameUrl = url; if (titleEl) titleEl.textContent = title || "实例"; - setInstanceFrameNavLoading(true); frame.src = url; shell.classList.remove("hidden"); shell.setAttribute("aria-hidden", "false"); @@ -456,14 +447,16 @@ if (frame.dataset.themeSyncBound !== "1") { frame.dataset.themeSyncBound = "1"; frame.addEventListener("load", function syncInstanceFrameTheme() { - try { - if (globalThis.HubTheme && typeof HubTheme.get === "function" && frame.contentWindow) { - frame.contentWindow.postMessage( - { type: "hub-theme-sync", theme: HubTheme.get() }, - "*" - ); - } - } catch (_) {} + requestAnimationFrame(() => { + try { + if (globalThis.HubTheme && typeof HubTheme.get === "function" && frame.contentWindow) { + frame.contentWindow.postMessage( + { type: "hub-theme-sync", theme: HubTheme.get() }, + "*" + ); + } + } catch (_) {} + }); }); } } @@ -477,7 +470,6 @@ if (shell) { shell.classList.add("hidden"); shell.setAttribute("aria-hidden", "true"); - shell.classList.remove("is-instance-nav-loading"); } document.body.classList.remove("hub-instance-frame-open"); } @@ -3140,23 +3132,6 @@ const back = document.getElementById("instance-frame-back"); const refresh = document.getElementById("instance-frame-refresh"); const newTab = document.getElementById("instance-frame-newtab"); - const frame = document.getElementById("instance-frame"); - if (frame && frame.dataset.hubNavBound !== "1") { - frame.dataset.hubNavBound = "1"; - frame.addEventListener("load", () => setInstanceFrameNavLoading(false)); - } - if (!window.__hubInstanceFrameMsgBound) { - window.__hubInstanceFrameMsgBound = true; - window.addEventListener("message", (ev) => { - const d = ev.data; - if (!d || typeof d !== "object") return; - if (d.type === "instance-frame-navigating") { - setInstanceFrameNavLoading(true); - } else if (d.type === "instance-frame-ready" || d.type === "instance-theme-ready") { - setInstanceFrameNavLoading(false); - } - }); - } if (back) back.onclick = () => closeInstanceFrame(); if (refresh) refresh.onclick = () => refreshInstanceFrame(); if (newTab) { diff --git a/manual_trading_hub/static/index.html b/manual_trading_hub/static/index.html index bc349b6..38933ed 100644 --- a/manual_trading_hub/static/index.html +++ b/manual_trading_hub/static/index.html @@ -15,7 +15,7 @@ - + @@ -654,6 +654,6 @@ - + diff --git a/static/account_risk_badge.css b/static/account_risk_badge.css index 82da946..581ff88 100644 --- a/static/account_risk_badge.css +++ b/static/account_risk_badge.css @@ -68,6 +68,11 @@ html[data-theme="light"] { transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease; } +/* 中控 iframe 内切页:避免徽章过渡动画造成 header 闪动 */ +html[data-hub-linked="1"] .header-row .risk-status-badge { + transition: none; +} + .risk-status-badge::before { content: ""; width: 7px; diff --git a/static/instance_theme.js b/static/instance_theme.js index 2623f49..e470ee7 100644 --- a/static/instance_theme.js +++ b/static/instance_theme.js @@ -63,6 +63,7 @@ } let _linkedTheme = null; + let _appliedTheme = null; function get() { if (isHubLinked()) { @@ -191,13 +192,25 @@ const options = opts || {}; const linked = isHubLinked(); const t = normalize(theme); + const root = document.documentElement; + const unchanged = + !options.force && + _appliedTheme === t && + root.getAttribute("data-theme") === t; + if (unchanged) { + return t; + } + _appliedTheme = t; if (linked) { _linkedTheme = t; writeLinkedThemeStorage(t); - } else if (!options.skipStore) { + root.setAttribute("data-hub-linked", "1"); + } else { + root.removeAttribute("data-hub-linked"); + } + if (!linked && !options.skipStore) { setStandalone(t); } - const root = document.documentElement; root.setAttribute("data-theme", t); const meta = document.querySelector('meta[name="theme-color"]'); if (meta) meta.setAttribute("content", META[t]); @@ -283,20 +296,6 @@ apply(data.theme, { skipStore: true }); } - function notifyParentFrameNavStart() { - if (!isHubLinked()) return; - try { - window.parent.postMessage({ type: "instance-frame-navigating", theme: get() }, "*"); - } catch (_) {} - } - - function notifyParentFrameReady() { - if (!isHubLinked()) return; - try { - window.parent.postMessage({ type: "instance-frame-ready" }, "*"); - } catch (_) {} - } - /** 中控 iframe 内:拦截顶栏导航,fetch 后 document.write 原地换页,避免 iframe 卸载白屏 */ function initHubEmbedInFrameNav() { if (!isHubLinked()) return; @@ -310,7 +309,6 @@ async function navigateInFrame(href, opts) { const token = ++navToken; - notifyParentFrameNavStart(); try { const r = await fetch(href, { credentials: "same-origin" }); if (token !== navToken) return; @@ -320,9 +318,6 @@ } const html = await r.text(); if (token !== navToken) return; - document.open(); - document.write(html); - document.close(); let path = href; try { const u = new URL(href, location.href); @@ -330,6 +325,9 @@ } catch (_) {} if (opts && opts.replace) history.replaceState(null, "", path); else history.pushState(null, "", path); + document.open(); + document.write(html); + document.close(); } catch (_) { if (token === navToken) location.href = href; } @@ -368,7 +366,6 @@ apply(get(), { skipStore: true }); window.addEventListener("message", (ev) => initFromHubMessage(ev.data)); initHubEmbedInFrameNav(); - notifyParentFrameReady(); try { window.parent.postMessage({ type: "instance-theme-ready" }, "*"); } catch (_) {}