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 <cursoragent@cursor.com>
This commit is contained in:
+2
-1
@@ -44,7 +44,8 @@
|
|||||||
keyTimer = setInterval(pollKeyPrices, 1000);
|
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);
|
else document.addEventListener('DOMContentLoaded', startPolling);
|
||||||
if (window.qihuoOnPageLeave) window.qihuoOnPageLeave(stopPolling);
|
if (window.qihuoOnPageLeave) window.qihuoOnPageLeave(stopPolling);
|
||||||
})();
|
})();
|
||||||
|
|||||||
+2
-1
@@ -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);
|
else document.addEventListener('DOMContentLoaded', bootMarketPage);
|
||||||
if (window.qihuoOnPageLeave) window.qihuoOnPageLeave(cleanupMarketPage);
|
if (window.qihuoOnPageLeave) window.qihuoOnPageLeave(cleanupMarketPage);
|
||||||
window.addEventListener('pagehide', cleanupMarketPage);
|
window.addEventListener('pagehide', cleanupMarketPage);
|
||||||
|
|||||||
@@ -14,4 +14,14 @@
|
|||||||
global.qihuoEmitPageLoad = function () {
|
global.qihuoEmitPageLoad = function () {
|
||||||
global.dispatchEvent(new Event('qihuo:page-load'));
|
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();
|
||||||
|
};
|
||||||
})();
|
})();
|
||||||
|
|||||||
+2
-1
@@ -52,7 +52,8 @@
|
|||||||
timer = setInterval(pollPrices, 1000);
|
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);
|
else document.addEventListener('DOMContentLoaded', startPolling);
|
||||||
if (window.qihuoOnPageLeave) window.qihuoOnPageLeave(stopPolling);
|
if (window.qihuoOnPageLeave) window.qihuoOnPageLeave(stopPolling);
|
||||||
})();
|
})();
|
||||||
|
|||||||
+2
-1
@@ -169,7 +169,8 @@
|
|||||||
recalc();
|
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);
|
else document.addEventListener('DOMContentLoaded', bootReviewPage);
|
||||||
|
|
||||||
window.recalc = recalc;
|
window.recalc = recalc;
|
||||||
|
|||||||
+2
-1
@@ -158,6 +158,7 @@
|
|||||||
loadStats();
|
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);
|
else document.addEventListener('DOMContentLoaded', bootStatsPage);
|
||||||
})();
|
})();
|
||||||
|
|||||||
+2
-1
@@ -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();
|
else bootTradePage();
|
||||||
if (window.qihuoOnPageLeave) window.qihuoOnPageLeave(cleanupTradePage);
|
if (window.qihuoOnPageLeave) window.qihuoOnPageLeave(cleanupTradePage);
|
||||||
window.addEventListener('pagehide', cleanupTradePage);
|
window.addEventListener('pagehide', cleanupTradePage);
|
||||||
|
|||||||
+36
-18
@@ -71,9 +71,19 @@
|
|||||||
if (el.tagName === 'LINK' && isPermanentStylesheet(el)) return;
|
if (el.tagName === 'LINK' && isPermanentStylesheet(el)) return;
|
||||||
out.push(el);
|
out.push(el);
|
||||||
});
|
});
|
||||||
|
doc.querySelectorAll('.main style').forEach(function (el) {
|
||||||
|
out.push(el);
|
||||||
|
});
|
||||||
return out;
|
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) {
|
function collectPageScripts(doc) {
|
||||||
var out = [];
|
var out = [];
|
||||||
var pastCore = false;
|
var pastCore = false;
|
||||||
@@ -83,29 +93,34 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!pastCore) return;
|
if (!pastCore) return;
|
||||||
|
if (isCoreScript(el)) return;
|
||||||
out.push(el);
|
out.push(el);
|
||||||
});
|
});
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
function removePageAssets() {
|
function removePageAssets() {
|
||||||
document.querySelectorAll('head link[rel="stylesheet"]').forEach(function (el) {
|
document.querySelectorAll('[data-page-css]').forEach(function (el) { el.remove(); });
|
||||||
if (!isPermanentStylesheet(el)) el.remove();
|
|
||||||
});
|
|
||||||
document.querySelectorAll('head style').forEach(function (el) { el.remove(); });
|
|
||||||
document.querySelectorAll('body script[data-page-js]').forEach(function (el) { el.remove(); });
|
document.querySelectorAll('body script[data-page-js]').forEach(function (el) { el.remove(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
function applyPageCss(items) {
|
function applyPageCss(items) {
|
||||||
items.forEach(function (srcEl) {
|
return items.reduce(function (chain, srcEl) {
|
||||||
|
return chain.then(function () {
|
||||||
|
return new Promise(function (resolve) {
|
||||||
var el = srcEl.cloneNode(true);
|
var el = srcEl.cloneNode(true);
|
||||||
|
el.setAttribute('data-page-css', '');
|
||||||
if (el.tagName === 'LINK') {
|
if (el.tagName === 'LINK') {
|
||||||
el.setAttribute('data-page-css', '');
|
el.onload = function () { resolve(); };
|
||||||
} else {
|
el.onerror = function () { resolve(); };
|
||||||
el.setAttribute('data-page-css', '');
|
|
||||||
}
|
|
||||||
document.head.appendChild(el);
|
document.head.appendChild(el);
|
||||||
|
} else {
|
||||||
|
document.head.appendChild(el);
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
}, Promise.resolve());
|
||||||
}
|
}
|
||||||
|
|
||||||
function runPageScripts(items) {
|
function runPageScripts(items) {
|
||||||
@@ -132,7 +147,7 @@
|
|||||||
}, Promise.resolve());
|
}, Promise.resolve());
|
||||||
}
|
}
|
||||||
|
|
||||||
function syncNavActive(doc, url) {
|
function syncNavActive(doc) {
|
||||||
var nav = document.getElementById('site-nav');
|
var nav = document.getElementById('site-nav');
|
||||||
var fetchedNav = doc.getElementById('site-nav');
|
var fetchedNav = doc.getElementById('site-nav');
|
||||||
if (!nav || !fetchedNav) return;
|
if (!nav || !fetchedNav) return;
|
||||||
@@ -153,20 +168,23 @@
|
|||||||
|
|
||||||
function applyDocument(doc, url, fromPopstate) {
|
function applyDocument(doc, url, fromPopstate) {
|
||||||
var main = document.querySelector('.main');
|
var main = document.querySelector('.main');
|
||||||
var fetchedMain = doc.querySelector('.main');
|
if (!main || !doc.querySelector('.main')) {
|
||||||
if (!main || !fetchedMain) {
|
|
||||||
window.location.href = url;
|
window.location.href = url;
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
window.dispatchEvent(new Event('qihuo:page-leave'));
|
window.dispatchEvent(new Event('qihuo:page-leave'));
|
||||||
removePageAssets();
|
removePageAssets();
|
||||||
applyPageCss(collectPageCss(doc));
|
|
||||||
main.innerHTML = fetchedMain.innerHTML;
|
var cssItems = collectPageCss(doc);
|
||||||
|
var mainHtml = prepareMainHtml(doc);
|
||||||
|
|
||||||
|
return applyPageCss(cssItems).then(function () {
|
||||||
|
main.innerHTML = mainHtml;
|
||||||
document.title = doc.title || document.title;
|
document.title = doc.title || document.title;
|
||||||
syncNavActive(doc, url);
|
syncNavActive(doc, url);
|
||||||
|
return runPageScripts(collectPageScripts(doc));
|
||||||
return runPageScripts(collectPageScripts(doc)).then(function () {
|
}).then(function () {
|
||||||
currentUrl = normalizeUrl(url);
|
currentUrl = normalizeUrl(url);
|
||||||
if (!fromPopstate) {
|
if (!fromPopstate) {
|
||||||
history.pushState({ turbo: true }, '', currentUrl);
|
history.pushState({ turbo: true }, '', currentUrl);
|
||||||
@@ -190,8 +208,8 @@
|
|||||||
return fetchPage(target, ctrl.signal).then(function (doc) {
|
return fetchPage(target, ctrl.signal).then(function (doc) {
|
||||||
if (ctrl.signal.aborted) return;
|
if (ctrl.signal.aborted) return;
|
||||||
inflight = null;
|
inflight = null;
|
||||||
applyDocument(doc, target, !!opts.fromPopstate);
|
return applyDocument(doc, target, !!opts.fromPopstate);
|
||||||
}).catch(function (err) {
|
}).catch(function () {
|
||||||
if (ctrl.signal.aborted) return;
|
if (ctrl.signal.aborted) return;
|
||||||
inflight = null;
|
inflight = null;
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
|
|||||||
+1
-1
@@ -2,7 +2,7 @@
|
|||||||
* 专有软件 — 未经授权禁止复制、传播、转售。
|
* 专有软件 — 未经授权禁止复制、传播、转售。
|
||||||
* 详见 LICENSE.zh-CN.txt
|
* 详见 LICENSE.zh-CN.txt
|
||||||
*/
|
*/
|
||||||
var CACHE_VERSION = 'qihuo-v6';
|
var CACHE_VERSION = 'qihuo-v7';
|
||||||
var STATIC_CACHE = CACHE_VERSION + '-static';
|
var STATIC_CACHE = CACHE_VERSION + '-static';
|
||||||
var STATIC_ASSETS = [
|
var STATIC_ASSETS = [
|
||||||
'/static/css/base.css',
|
'/static/css/base.css',
|
||||||
|
|||||||
+29
-27
@@ -1,6 +1,35 @@
|
|||||||
{# Copyright (c) 2025-2026 马建军. All rights reserved. 专有软件,详见 LICENSE.zh-CN.txt #}
|
{# Copyright (c) 2025-2026 马建军. All rights reserved. 专有软件,详见 LICENSE.zh-CN.txt #}
|
||||||
{% extends "base.html" %}
|
{% extends "base.html" %}
|
||||||
{% block title %}统计分析 - 国内期货 · 交易复盘系统{% endblock %}
|
{% block title %}统计分析 - 国内期货 · 交易复盘系统{% endblock %}
|
||||||
|
{% block extra_css %}
|
||||||
|
<style>
|
||||||
|
.stats-summary-card{margin-bottom:1.25rem}
|
||||||
|
.stats-toolbar{display:flex;align-items:center;justify-content:flex-start;gap:1rem;margin-bottom:.75rem;flex-wrap:wrap}
|
||||||
|
.stat-grid-summary{
|
||||||
|
display:flex;flex-wrap:nowrap;align-items:stretch;gap:0;
|
||||||
|
margin-bottom:0;overflow-x:auto;-webkit-overflow-scrolling:touch;
|
||||||
|
}
|
||||||
|
.stat-grid-summary .stat-item{
|
||||||
|
flex:1 1 0;min-width:4.5rem;background:transparent;border:none;border-radius:0;
|
||||||
|
padding:.35rem .2rem;text-align:center;position:relative;overflow:visible;
|
||||||
|
border-right:1px solid var(--table-border);
|
||||||
|
}
|
||||||
|
.stat-grid-summary .stat-item:last-child{border-right:none}
|
||||||
|
.stat-grid-summary .stat-item::before{display:none}
|
||||||
|
.stat-grid-summary .stat-item:hover{transform:none;box-shadow:none}
|
||||||
|
.stat-grid-summary .stat-item .label{
|
||||||
|
font-size:.62rem;line-height:1.25;color:var(--text-muted);white-space:nowrap;
|
||||||
|
}
|
||||||
|
.stat-grid-summary .stat-item .value{
|
||||||
|
font-size:.78rem;font-weight:600;color:var(--text-title);margin-top:.12rem;
|
||||||
|
font-variant-numeric:tabular-nums;white-space:nowrap;
|
||||||
|
}
|
||||||
|
.stats-card-head{display:flex;align-items:flex-end;justify-content:space-between;gap:1rem;flex-wrap:wrap;margin-bottom:1rem}
|
||||||
|
.stats-card-head h2{margin-bottom:0}
|
||||||
|
.stats-view-field{width:auto;min-width:200px}
|
||||||
|
.stats-view-field select{width:100%;min-width:180px}
|
||||||
|
</style>
|
||||||
|
{% endblock %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
||||||
<div class="card stats-summary-card">
|
<div class="card stats-summary-card">
|
||||||
@@ -43,33 +72,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
|
||||||
.stats-summary-card{margin-bottom:1.25rem}
|
|
||||||
.stats-toolbar{display:flex;align-items:center;justify-content:flex-start;gap:1rem;margin-bottom:.75rem;flex-wrap:wrap}
|
|
||||||
.stat-grid-summary{
|
|
||||||
display:flex;flex-wrap:nowrap;align-items:stretch;gap:0;
|
|
||||||
margin-bottom:0;overflow-x:auto;-webkit-overflow-scrolling:touch;
|
|
||||||
}
|
|
||||||
.stat-grid-summary .stat-item{
|
|
||||||
flex:1 1 0;min-width:4.5rem;background:transparent;border:none;border-radius:0;
|
|
||||||
padding:.35rem .2rem;text-align:center;position:relative;overflow:visible;
|
|
||||||
border-right:1px solid var(--table-border);
|
|
||||||
}
|
|
||||||
.stat-grid-summary .stat-item:last-child{border-right:none}
|
|
||||||
.stat-grid-summary .stat-item::before{display:none}
|
|
||||||
.stat-grid-summary .stat-item:hover{transform:none;box-shadow:none}
|
|
||||||
.stat-grid-summary .stat-item .label{
|
|
||||||
font-size:.62rem;line-height:1.25;color:var(--text-muted);white-space:nowrap;
|
|
||||||
}
|
|
||||||
.stat-grid-summary .stat-item .value{
|
|
||||||
font-size:.78rem;font-weight:600;color:var(--text-title);margin-top:.12rem;
|
|
||||||
font-variant-numeric:tabular-nums;white-space:nowrap;
|
|
||||||
}
|
|
||||||
.stats-card-head{display:flex;align-items:flex-end;justify-content:space-between;gap:1rem;flex-wrap:wrap;margin-bottom:1rem}
|
|
||||||
.stats-card-head h2{margin-bottom:0}
|
|
||||||
.stats-view-field{width:auto;min-width:200px}
|
|
||||||
.stats-view-field select{width:100%;min-width:180px}
|
|
||||||
</style>
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block extra_js %}
|
{% block extra_js %}
|
||||||
|
|||||||
Reference in New Issue
Block a user