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 %}