From 6d55a5494605924d6a7e1dd30078cb5de4f5500f Mon Sep 17 00:00:00 2001 From: dekun Date: Fri, 26 Jun 2026 20:55:36 +0800 Subject: [PATCH] Fix turbo nav layout flash and stats page not loading. Wait for page CSS before swapping content, hoist inline styles to head, and boot page scripts immediately when DOM markers exist. Co-authored-by: Cursor --- static/js/keys.js | 3 +- static/js/market.js | 3 +- static/js/page.js | 10 +++++++ static/js/plans.js | 3 +- static/js/review.js | 3 +- static/js/stats.js | 3 +- static/js/trade.js | 3 +- static/js/turbonav.js | 64 +++++++++++++++++++++++++++---------------- static/sw.js | 2 +- templates/stats.html | 56 +++++++++++++++++++------------------ 10 files changed, 93 insertions(+), 57 deletions(-) diff --git a/static/js/keys.js b/static/js/keys.js index 0db6a41..78ce392 100644 --- a/static/js/keys.js +++ b/static/js/keys.js @@ -44,7 +44,8 @@ keyTimer = setInterval(pollKeyPrices, 1000); } - if (window.qihuoOnPageLoad) window.qihuoOnPageLoad(startPolling); + if (window.qihuoPageBoot) window.qihuoPageBoot(startPolling, '#key-monitor-list'); + else if (window.qihuoOnPageLoad) window.qihuoOnPageLoad(startPolling); else document.addEventListener('DOMContentLoaded', startPolling); if (window.qihuoOnPageLeave) window.qihuoOnPageLeave(stopPolling); })(); diff --git a/static/js/market.js b/static/js/market.js index f8c4870..e8c95e4 100644 --- a/static/js/market.js +++ b/static/js/market.js @@ -742,7 +742,8 @@ }); } - if (window.qihuoOnPageLoad) window.qihuoOnPageLoad(bootMarketPage); + if (window.qihuoPageBoot) window.qihuoPageBoot(bootMarketPage, '#market-chart-wrap'); + else if (window.qihuoOnPageLoad) window.qihuoOnPageLoad(bootMarketPage); else document.addEventListener('DOMContentLoaded', bootMarketPage); if (window.qihuoOnPageLeave) window.qihuoOnPageLeave(cleanupMarketPage); window.addEventListener('pagehide', cleanupMarketPage); diff --git a/static/js/page.js b/static/js/page.js index 187e27d..0e78c06 100644 --- a/static/js/page.js +++ b/static/js/page.js @@ -14,4 +14,14 @@ global.qihuoEmitPageLoad = function () { global.dispatchEvent(new Event('qihuo:page-load')); }; + + /** Register page boot + run now if the page marker is already in DOM (turbo nav). */ + global.qihuoPageBoot = function (fn, selector) { + function run() { + if (selector && !global.document.querySelector(selector)) return; + fn(); + } + global.addEventListener('qihuo:page-load', run); + run(); + }; })(); diff --git a/static/js/plans.js b/static/js/plans.js index 7767e29..013ec7a 100644 --- a/static/js/plans.js +++ b/static/js/plans.js @@ -52,7 +52,8 @@ timer = setInterval(pollPrices, 1000); } - if (window.qihuoOnPageLoad) window.qihuoOnPageLoad(startPolling); + if (window.qihuoPageBoot) window.qihuoPageBoot(startPolling, '#plan-monitor-list'); + else if (window.qihuoOnPageLoad) window.qihuoOnPageLoad(startPolling); else document.addEventListener('DOMContentLoaded', startPolling); if (window.qihuoOnPageLeave) window.qihuoOnPageLeave(stopPolling); })(); diff --git a/static/js/review.js b/static/js/review.js index 495d308..9167cf3 100644 --- a/static/js/review.js +++ b/static/js/review.js @@ -169,7 +169,8 @@ recalc(); } - if (window.qihuoOnPageLoad) window.qihuoOnPageLoad(bootReviewPage); + if (window.qihuoPageBoot) window.qihuoPageBoot(bootReviewPage, '#review-form'); + else if (window.qihuoOnPageLoad) window.qihuoOnPageLoad(bootReviewPage); else document.addEventListener('DOMContentLoaded', bootReviewPage); window.recalc = recalc; diff --git a/static/js/stats.js b/static/js/stats.js index 0c89767..1eff91b 100644 --- a/static/js/stats.js +++ b/static/js/stats.js @@ -158,6 +158,7 @@ loadStats(); } - if (window.qihuoOnPageLoad) window.qihuoOnPageLoad(bootStatsPage); + if (window.qihuoPageBoot) window.qihuoPageBoot(bootStatsPage, '#stats-summary'); + else if (window.qihuoOnPageLoad) window.qihuoOnPageLoad(bootStatsPage); else document.addEventListener('DOMContentLoaded', bootStatsPage); })(); diff --git a/static/js/trade.js b/static/js/trade.js index 26cb005..fafbd9d 100644 --- a/static/js/trade.js +++ b/static/js/trade.js @@ -1648,7 +1648,8 @@ } }); - if (window.qihuoOnPageLoad) window.qihuoOnPageLoad(bootTradePage); + if (window.qihuoPageBoot) window.qihuoPageBoot(bootTradePage, '#position-live-list, #order-live-list'); + else if (window.qihuoOnPageLoad) window.qihuoOnPageLoad(bootTradePage); else bootTradePage(); if (window.qihuoOnPageLeave) window.qihuoOnPageLeave(cleanupTradePage); window.addEventListener('pagehide', cleanupTradePage); diff --git a/static/js/turbonav.js b/static/js/turbonav.js index d0e49ea..1b17818 100644 --- a/static/js/turbonav.js +++ b/static/js/turbonav.js @@ -71,9 +71,19 @@ if (el.tagName === 'LINK' && isPermanentStylesheet(el)) return; out.push(el); }); + doc.querySelectorAll('.main style').forEach(function (el) { + out.push(el); + }); return out; } + function prepareMainHtml(doc) { + var fetchedMain = doc.querySelector('.main'); + if (!fetchedMain) return ''; + fetchedMain.querySelectorAll('style').forEach(function (el) { el.remove(); }); + return fetchedMain.innerHTML; + } + function collectPageScripts(doc) { var out = []; var pastCore = false; @@ -83,29 +93,34 @@ return; } if (!pastCore) return; + if (isCoreScript(el)) return; out.push(el); }); return out; } function removePageAssets() { - document.querySelectorAll('head link[rel="stylesheet"]').forEach(function (el) { - if (!isPermanentStylesheet(el)) el.remove(); - }); - document.querySelectorAll('head style').forEach(function (el) { el.remove(); }); + document.querySelectorAll('[data-page-css]').forEach(function (el) { el.remove(); }); document.querySelectorAll('body script[data-page-js]').forEach(function (el) { el.remove(); }); } function applyPageCss(items) { - items.forEach(function (srcEl) { - var el = srcEl.cloneNode(true); - if (el.tagName === 'LINK') { - el.setAttribute('data-page-css', ''); - } else { - el.setAttribute('data-page-css', ''); - } - document.head.appendChild(el); - }); + return items.reduce(function (chain, srcEl) { + return chain.then(function () { + return new Promise(function (resolve) { + var el = srcEl.cloneNode(true); + el.setAttribute('data-page-css', ''); + if (el.tagName === 'LINK') { + el.onload = function () { resolve(); }; + el.onerror = function () { resolve(); }; + document.head.appendChild(el); + } else { + document.head.appendChild(el); + resolve(); + } + }); + }); + }, Promise.resolve()); } function runPageScripts(items) { @@ -132,7 +147,7 @@ }, Promise.resolve()); } - function syncNavActive(doc, url) { + function syncNavActive(doc) { var nav = document.getElementById('site-nav'); var fetchedNav = doc.getElementById('site-nav'); if (!nav || !fetchedNav) return; @@ -153,20 +168,23 @@ function applyDocument(doc, url, fromPopstate) { var main = document.querySelector('.main'); - var fetchedMain = doc.querySelector('.main'); - if (!main || !fetchedMain) { + if (!main || !doc.querySelector('.main')) { window.location.href = url; return Promise.resolve(); } window.dispatchEvent(new Event('qihuo:page-leave')); removePageAssets(); - applyPageCss(collectPageCss(doc)); - main.innerHTML = fetchedMain.innerHTML; - document.title = doc.title || document.title; - syncNavActive(doc, url); - return runPageScripts(collectPageScripts(doc)).then(function () { + var cssItems = collectPageCss(doc); + var mainHtml = prepareMainHtml(doc); + + return applyPageCss(cssItems).then(function () { + main.innerHTML = mainHtml; + document.title = doc.title || document.title; + syncNavActive(doc, url); + return runPageScripts(collectPageScripts(doc)); + }).then(function () { currentUrl = normalizeUrl(url); if (!fromPopstate) { history.pushState({ turbo: true }, '', currentUrl); @@ -190,8 +208,8 @@ return fetchPage(target, ctrl.signal).then(function (doc) { if (ctrl.signal.aborted) return; inflight = null; - applyDocument(doc, target, !!opts.fromPopstate); - }).catch(function (err) { + return applyDocument(doc, target, !!opts.fromPopstate); + }).catch(function () { if (ctrl.signal.aborted) return; inflight = null; setLoading(false); diff --git a/static/sw.js b/static/sw.js index 4bdf277..318e04f 100644 --- a/static/sw.js +++ b/static/sw.js @@ -2,7 +2,7 @@ * 专有软件 — 未经授权禁止复制、传播、转售。 * 详见 LICENSE.zh-CN.txt */ -var CACHE_VERSION = 'qihuo-v6'; +var CACHE_VERSION = 'qihuo-v7'; var STATIC_CACHE = CACHE_VERSION + '-static'; var STATIC_ASSETS = [ '/static/css/base.css', diff --git a/templates/stats.html b/templates/stats.html index b919429..0b6181c 100644 --- a/templates/stats.html +++ b/templates/stats.html @@ -1,6 +1,35 @@ {# Copyright (c) 2025-2026 马建军. All rights reserved. 专有软件,详见 LICENSE.zh-CN.txt #} {% extends "base.html" %} {% block title %}统计分析 - 国内期货 · 交易复盘系统{% endblock %} +{% block extra_css %} + +{% endblock %} {% block content %}
@@ -43,33 +72,6 @@
- {% endblock %} {% block extra_js %}