fix(hub): stop instance iframe nav flash after account status badge
Load account_risk_badge.css before body paint, skip redundant hub theme re-apply, remove iframe hide overlay, and disable badge transitions in hub embed. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -3,8 +3,9 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
|
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
|
||||||
<script src="/static/instance_theme.js?v=7"></script>
|
<script src="/static/instance_theme.js?v=8"></script>
|
||||||
<link rel="stylesheet" href="/static/instance_theme_early.css?v=2">
|
<link rel="stylesheet" href="/static/instance_theme_early.css?v=3">
|
||||||
|
<link rel="stylesheet" href="/static/account_risk_badge.css?v=2">
|
||||||
|
|
||||||
<meta name="theme-color" content="#0b0d14">
|
<meta name="theme-color" content="#0b0d14">
|
||||||
<meta name="apple-mobile-web-app-title" content="监控">
|
<meta name="apple-mobile-web-app-title" content="监控">
|
||||||
@@ -236,7 +237,6 @@
|
|||||||
.stats-period-block .sub{font-size:.78rem;color:#8892b0;margin-bottom:10px;line-height:1.4}
|
.stats-period-block .sub{font-size:.78rem;color:#8892b0;margin-bottom:10px;line-height:1.4}
|
||||||
</style>
|
</style>
|
||||||
<link rel="stylesheet" href="/static/instance_theme.css?v=14">
|
<link rel="stylesheet" href="/static/instance_theme.css?v=14">
|
||||||
<link rel="stylesheet" href="/static/account_risk_badge.css?v=1">
|
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
<body data-page="{{ page }}">
|
<body data-page="{{ page }}">
|
||||||
|
|||||||
@@ -3,8 +3,9 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
|
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
|
||||||
<script src="/static/instance_theme.js?v=7"></script>
|
<script src="/static/instance_theme.js?v=8"></script>
|
||||||
<link rel="stylesheet" href="/static/instance_theme_early.css?v=2">
|
<link rel="stylesheet" href="/static/instance_theme_early.css?v=3">
|
||||||
|
<link rel="stylesheet" href="/static/account_risk_badge.css?v=2">
|
||||||
|
|
||||||
<meta name="theme-color" content="#0b0d14">
|
<meta name="theme-color" content="#0b0d14">
|
||||||
<meta name="apple-mobile-web-app-title" content="监控">
|
<meta name="apple-mobile-web-app-title" content="监控">
|
||||||
@@ -236,7 +237,6 @@
|
|||||||
.stats-period-block .sub{font-size:.78rem;color:#8892b0;margin-bottom:10px;line-height:1.4}
|
.stats-period-block .sub{font-size:.78rem;color:#8892b0;margin-bottom:10px;line-height:1.4}
|
||||||
</style>
|
</style>
|
||||||
<link rel="stylesheet" href="/static/instance_theme.css?v=14">
|
<link rel="stylesheet" href="/static/instance_theme.css?v=14">
|
||||||
<link rel="stylesheet" href="/static/account_risk_badge.css?v=1">
|
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
<body data-page="{{ page }}">
|
<body data-page="{{ page }}">
|
||||||
|
|||||||
@@ -3,8 +3,9 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
|
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
|
||||||
<script src="/static/instance_theme.js?v=7"></script>
|
<script src="/static/instance_theme.js?v=8"></script>
|
||||||
<link rel="stylesheet" href="/static/instance_theme_early.css?v=2">
|
<link rel="stylesheet" href="/static/instance_theme_early.css?v=3">
|
||||||
|
<link rel="stylesheet" href="/static/account_risk_badge.css?v=2">
|
||||||
|
|
||||||
<meta name="theme-color" content="#0b0d14">
|
<meta name="theme-color" content="#0b0d14">
|
||||||
<meta name="apple-mobile-web-app-title" content="监控">
|
<meta name="apple-mobile-web-app-title" content="监控">
|
||||||
@@ -236,7 +237,6 @@
|
|||||||
.stats-period-block .sub{font-size:.78rem;color:#8892b0;margin-bottom:10px;line-height:1.4}
|
.stats-period-block .sub{font-size:.78rem;color:#8892b0;margin-bottom:10px;line-height:1.4}
|
||||||
</style>
|
</style>
|
||||||
<link rel="stylesheet" href="/static/instance_theme.css?v=14">
|
<link rel="stylesheet" href="/static/instance_theme.css?v=14">
|
||||||
<link rel="stylesheet" href="/static/account_risk_badge.css?v=1">
|
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
<body data-page="{{ page }}">
|
<body data-page="{{ page }}">
|
||||||
|
|||||||
@@ -3,8 +3,9 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
|
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
|
||||||
<script src="/static/instance_theme.js?v=7"></script>
|
<script src="/static/instance_theme.js?v=8"></script>
|
||||||
<link rel="stylesheet" href="/static/instance_theme_early.css?v=2">
|
<link rel="stylesheet" href="/static/instance_theme_early.css?v=3">
|
||||||
|
<link rel="stylesheet" href="/static/account_risk_badge.css?v=2">
|
||||||
|
|
||||||
<meta name="theme-color" content="#0b0d14">
|
<meta name="theme-color" content="#0b0d14">
|
||||||
<meta name="apple-mobile-web-app-title" content="监控">
|
<meta name="apple-mobile-web-app-title" content="监控">
|
||||||
@@ -236,7 +237,6 @@
|
|||||||
.stats-period-block .sub{font-size:.78rem;color:#8892b0;margin-bottom:10px;line-height:1.4}
|
.stats-period-block .sub{font-size:.78rem;color:#8892b0;margin-bottom:10px;line-height:1.4}
|
||||||
</style>
|
</style>
|
||||||
<link rel="stylesheet" href="/static/instance_theme.css?v=14">
|
<link rel="stylesheet" href="/static/instance_theme.css?v=14">
|
||||||
<link rel="stylesheet" href="/static/account_risk_badge.css?v=1">
|
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
<body data-page="{{ page }}">
|
<body data-page="{{ page }}">
|
||||||
|
|||||||
@@ -1092,10 +1092,6 @@ body.market-chart-fs-open {
|
|||||||
background: var(--bg);
|
background: var(--bg);
|
||||||
}
|
}
|
||||||
|
|
||||||
.instance-frame-shell.is-instance-nav-loading .instance-frame {
|
|
||||||
visibility: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.exchange-fullscreen {
|
.exchange-fullscreen {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
inset: 0;
|
inset: 0;
|
||||||
|
|||||||
@@ -371,11 +371,6 @@
|
|||||||
return j.url;
|
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) {
|
async function openInstance(exchangeId, nextPath, opts) {
|
||||||
const options = opts || {};
|
const options = opts || {};
|
||||||
const newTab = !!options.newTab;
|
const newTab = !!options.newTab;
|
||||||
@@ -428,10 +423,7 @@
|
|||||||
);
|
);
|
||||||
instanceFrameUrl = url;
|
instanceFrameUrl = url;
|
||||||
const frame = document.getElementById("instance-frame");
|
const frame = document.getElementById("instance-frame");
|
||||||
if (frame) {
|
if (frame) frame.src = url;
|
||||||
setInstanceFrameNavLoading(true);
|
|
||||||
frame.src = url;
|
|
||||||
}
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
showToast(String(e), true);
|
showToast(String(e), true);
|
||||||
}
|
}
|
||||||
@@ -448,7 +440,6 @@
|
|||||||
closeExchangeFullscreen();
|
closeExchangeFullscreen();
|
||||||
instanceFrameUrl = url;
|
instanceFrameUrl = url;
|
||||||
if (titleEl) titleEl.textContent = title || "实例";
|
if (titleEl) titleEl.textContent = title || "实例";
|
||||||
setInstanceFrameNavLoading(true);
|
|
||||||
frame.src = url;
|
frame.src = url;
|
||||||
shell.classList.remove("hidden");
|
shell.classList.remove("hidden");
|
||||||
shell.setAttribute("aria-hidden", "false");
|
shell.setAttribute("aria-hidden", "false");
|
||||||
@@ -456,6 +447,7 @@
|
|||||||
if (frame.dataset.themeSyncBound !== "1") {
|
if (frame.dataset.themeSyncBound !== "1") {
|
||||||
frame.dataset.themeSyncBound = "1";
|
frame.dataset.themeSyncBound = "1";
|
||||||
frame.addEventListener("load", function syncInstanceFrameTheme() {
|
frame.addEventListener("load", function syncInstanceFrameTheme() {
|
||||||
|
requestAnimationFrame(() => {
|
||||||
try {
|
try {
|
||||||
if (globalThis.HubTheme && typeof HubTheme.get === "function" && frame.contentWindow) {
|
if (globalThis.HubTheme && typeof HubTheme.get === "function" && frame.contentWindow) {
|
||||||
frame.contentWindow.postMessage(
|
frame.contentWindow.postMessage(
|
||||||
@@ -465,6 +457,7 @@
|
|||||||
}
|
}
|
||||||
} catch (_) {}
|
} catch (_) {}
|
||||||
});
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -477,7 +470,6 @@
|
|||||||
if (shell) {
|
if (shell) {
|
||||||
shell.classList.add("hidden");
|
shell.classList.add("hidden");
|
||||||
shell.setAttribute("aria-hidden", "true");
|
shell.setAttribute("aria-hidden", "true");
|
||||||
shell.classList.remove("is-instance-nav-loading");
|
|
||||||
}
|
}
|
||||||
document.body.classList.remove("hub-instance-frame-open");
|
document.body.classList.remove("hub-instance-frame-open");
|
||||||
}
|
}
|
||||||
@@ -3140,23 +3132,6 @@
|
|||||||
const back = document.getElementById("instance-frame-back");
|
const back = document.getElementById("instance-frame-back");
|
||||||
const refresh = document.getElementById("instance-frame-refresh");
|
const refresh = document.getElementById("instance-frame-refresh");
|
||||||
const newTab = document.getElementById("instance-frame-newtab");
|
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 (back) back.onclick = () => closeInstanceFrame();
|
||||||
if (refresh) refresh.onclick = () => refreshInstanceFrame();
|
if (refresh) refresh.onclick = () => refreshInstanceFrame();
|
||||||
if (newTab) {
|
if (newTab) {
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||||
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600&family=Orbitron:wght@500;600;700&display=swap" rel="stylesheet" media="print" onload="this.media='all'" />
|
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600&family=Orbitron:wght@500;600;700&display=swap" rel="stylesheet" media="print" onload="this.media='all'" />
|
||||||
<noscript><link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600&family=Orbitron:wght@500;600;700&display=swap" rel="stylesheet" /></noscript>
|
<noscript><link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600&family=Orbitron:wght@500;600;700&display=swap" rel="stylesheet" /></noscript>
|
||||||
<link rel="stylesheet" href="/assets/app.css?v=20260614-instance-frame-nav" />
|
<link rel="stylesheet" href="/assets/app.css?v=20260614-instance-nav-v2" />
|
||||||
<link rel="stylesheet" href="/assets/account_risk_badge.css?v=1" />
|
<link rel="stylesheet" href="/assets/account_risk_badge.css?v=1" />
|
||||||
<link rel="stylesheet" href="/assets/dashboard.css?v=20260612-dash-monitor-count" />
|
<link rel="stylesheet" href="/assets/dashboard.css?v=20260612-dash-monitor-count" />
|
||||||
</head>
|
</head>
|
||||||
@@ -654,6 +654,6 @@
|
|||||||
<script src="/assets/dashboard.js?v=20260612-dash-monitor-count"></script>
|
<script src="/assets/dashboard.js?v=20260612-dash-monitor-count"></script>
|
||||||
<script src="/assets/ai_review_render.js?v=3"></script>
|
<script src="/assets/ai_review_render.js?v=3"></script>
|
||||||
<script src="/assets/time_close_ui.js?v=2"></script>
|
<script src="/assets/time_close_ui.js?v=2"></script>
|
||||||
<script src="/assets/app.js?v=20260614-instance-frame-nav"></script>
|
<script src="/assets/app.js?v=20260614-instance-nav-v2"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -68,6 +68,11 @@ html[data-theme="light"] {
|
|||||||
transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease;
|
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 {
|
.risk-status-badge::before {
|
||||||
content: "";
|
content: "";
|
||||||
width: 7px;
|
width: 7px;
|
||||||
|
|||||||
+18
-21
@@ -63,6 +63,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
let _linkedTheme = null;
|
let _linkedTheme = null;
|
||||||
|
let _appliedTheme = null;
|
||||||
|
|
||||||
function get() {
|
function get() {
|
||||||
if (isHubLinked()) {
|
if (isHubLinked()) {
|
||||||
@@ -191,13 +192,25 @@
|
|||||||
const options = opts || {};
|
const options = opts || {};
|
||||||
const linked = isHubLinked();
|
const linked = isHubLinked();
|
||||||
const t = normalize(theme);
|
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) {
|
if (linked) {
|
||||||
_linkedTheme = t;
|
_linkedTheme = t;
|
||||||
writeLinkedThemeStorage(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);
|
setStandalone(t);
|
||||||
}
|
}
|
||||||
const root = document.documentElement;
|
|
||||||
root.setAttribute("data-theme", t);
|
root.setAttribute("data-theme", t);
|
||||||
const meta = document.querySelector('meta[name="theme-color"]');
|
const meta = document.querySelector('meta[name="theme-color"]');
|
||||||
if (meta) meta.setAttribute("content", META[t]);
|
if (meta) meta.setAttribute("content", META[t]);
|
||||||
@@ -283,20 +296,6 @@
|
|||||||
apply(data.theme, { skipStore: true });
|
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 卸载白屏 */
|
/** 中控 iframe 内:拦截顶栏导航,fetch 后 document.write 原地换页,避免 iframe 卸载白屏 */
|
||||||
function initHubEmbedInFrameNav() {
|
function initHubEmbedInFrameNav() {
|
||||||
if (!isHubLinked()) return;
|
if (!isHubLinked()) return;
|
||||||
@@ -310,7 +309,6 @@
|
|||||||
|
|
||||||
async function navigateInFrame(href, opts) {
|
async function navigateInFrame(href, opts) {
|
||||||
const token = ++navToken;
|
const token = ++navToken;
|
||||||
notifyParentFrameNavStart();
|
|
||||||
try {
|
try {
|
||||||
const r = await fetch(href, { credentials: "same-origin" });
|
const r = await fetch(href, { credentials: "same-origin" });
|
||||||
if (token !== navToken) return;
|
if (token !== navToken) return;
|
||||||
@@ -320,9 +318,6 @@
|
|||||||
}
|
}
|
||||||
const html = await r.text();
|
const html = await r.text();
|
||||||
if (token !== navToken) return;
|
if (token !== navToken) return;
|
||||||
document.open();
|
|
||||||
document.write(html);
|
|
||||||
document.close();
|
|
||||||
let path = href;
|
let path = href;
|
||||||
try {
|
try {
|
||||||
const u = new URL(href, location.href);
|
const u = new URL(href, location.href);
|
||||||
@@ -330,6 +325,9 @@
|
|||||||
} catch (_) {}
|
} catch (_) {}
|
||||||
if (opts && opts.replace) history.replaceState(null, "", path);
|
if (opts && opts.replace) history.replaceState(null, "", path);
|
||||||
else history.pushState(null, "", path);
|
else history.pushState(null, "", path);
|
||||||
|
document.open();
|
||||||
|
document.write(html);
|
||||||
|
document.close();
|
||||||
} catch (_) {
|
} catch (_) {
|
||||||
if (token === navToken) location.href = href;
|
if (token === navToken) location.href = href;
|
||||||
}
|
}
|
||||||
@@ -368,7 +366,6 @@
|
|||||||
apply(get(), { skipStore: true });
|
apply(get(), { skipStore: true });
|
||||||
window.addEventListener("message", (ev) => initFromHubMessage(ev.data));
|
window.addEventListener("message", (ev) => initFromHubMessage(ev.data));
|
||||||
initHubEmbedInFrameNav();
|
initHubEmbedInFrameNav();
|
||||||
notifyParentFrameReady();
|
|
||||||
try {
|
try {
|
||||||
window.parent.postMessage({ type: "instance-theme-ready" }, "*");
|
window.parent.postMessage({ type: "instance-theme-ready" }, "*");
|
||||||
} catch (_) {}
|
} catch (_) {}
|
||||||
|
|||||||
Reference in New Issue
Block a user