fix(pjax): 样式表版本同步修复部署后旧会话裸奔 + 关于页 CSS 冗余清理
- pjax:success 时比对新取 HTML 的样式表指纹,不一致则整页 reload 一次 (sessionStorage 防循环)—— 根治「部署换了 CSS 指纹后,PJAX 旧会话 永远跑旧样式」的线上 bug(2026-10-07 关于页裸奔实锤) - cacheBust: true —— PJAX 请求加时间戳,绕开 HTML 长缓存 - main.css:删整段重复的响应式块/死选择器 .uk-scrollspy-inview .ab-bar/ 死代码 .about-card;.ab-stat 悬停归位进布局区
This commit is contained in:
1 parent
ac7ad23e8c
commit
72bbf9db3e
2 files changed
+57
-36
No files matched your search
@@ -4309,19 +4309,6 @@ input[type=submit] {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* About Page Card Style */
|
|
||||||
.about-card {
|
|
||||||
background-color: transparent;
|
|
||||||
border-radius: 0;
|
|
||||||
padding: 0;
|
|
||||||
box-shadow: none !important;
|
|
||||||
margin-bottom: 30px;
|
|
||||||
}
|
|
||||||
[data-theme="dark"] .about-card {
|
|
||||||
background-color: transparent;
|
|
||||||
box-shadow: none !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ══════════════════════════════════════════════════════════════════════════
|
/* ══════════════════════════════════════════════════════════════════════════
|
||||||
关于页 · B+C 方案(时间线 + 数据一览)
|
关于页 · B+C 方案(时间线 + 数据一览)
|
||||||
──────────────────────────────────────────────────────────────────────────
|
──────────────────────────────────────────────────────────────────────────
|
||||||
@@ -4482,6 +4469,10 @@ input[type=submit] {
|
|||||||
font-size: var(--ab-fs-micro); letter-spacing: 0.1em;
|
font-size: var(--ab-fs-micro); letter-spacing: 0.1em;
|
||||||
color: var(--sanji-color);
|
color: var(--sanji-color);
|
||||||
}
|
}
|
||||||
|
/* 数据卡悬停:极轻的边框加深,与主题其他卡片观感一致(不加阴影跳变) */
|
||||||
|
.ab-stat { transition: border-color 0.25s ease; }
|
||||||
|
.ab-stat:hover { border-color: rgba(0, 0, 0, 0.16); }
|
||||||
|
[data-theme="dark"] .ab-stat:hover { border-color: rgba(255, 255, 255, 0.16); }
|
||||||
|
|
||||||
.ab-bars { margin-top: 26px; }
|
.ab-bars { margin-top: 26px; }
|
||||||
.ab-bar {
|
.ab-bar {
|
||||||
@@ -4518,16 +4509,6 @@ input[type=submit] {
|
|||||||
}
|
}
|
||||||
[data-theme="dark"] .ab-footnote { color: #6b7280; }
|
[data-theme="dark"] .ab-footnote { color: #6b7280; }
|
||||||
|
|
||||||
/* ── 关于页响应式 ── */
|
|
||||||
@media (max-width: 700px) {
|
|
||||||
.ab-attr { gap: 12px; }
|
|
||||||
.ab-attr .k { width: 54px; }
|
|
||||||
.ab-stats { gap: 8px; }
|
|
||||||
.ab-stat { padding: 13px 4px; }
|
|
||||||
.ab-stat .n { font-size: 1.4rem; }
|
|
||||||
.ab-bar .n { width: 48px; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ══════════════════════════════════════════════════════════════════════════
|
/* ══════════════════════════════════════════════════════════════════════════
|
||||||
关于页 · 动效层(v7:纯 UIKit 官方写法,与其他页面完全同源,零自定义)
|
关于页 · 动效层(v7:纯 UIKit 官方写法,与其他页面完全同源,零自定义)
|
||||||
──────────────────────────────────────────────────────────────────────────
|
──────────────────────────────────────────────────────────────────────────
|
||||||
@@ -4537,20 +4518,21 @@ input[type=submit] {
|
|||||||
—— 官方默认时长就在打包 CSS 里:[class*=uk-animation-]{duration:.5s},
|
—— 官方默认时长就在打包 CSS 里:[class*=uk-animation-]{duration:.5s},
|
||||||
fade 0.8s。★ 这里不再覆盖时长/keyframes(v6 的自定义层已删,
|
fade 0.8s。★ 这里不再覆盖时长/keyframes(v6 的自定义层已删,
|
||||||
之前注释里说的「主题 0.2s 压制」实测并不存在)。
|
之前注释里说的「主题 0.2s 压制」实测并不存在)。
|
||||||
· 内容组 repeat: true:移出视口重藏、滚回重播 —— 滚动时页面是活的。
|
· 内容组不写 repeat:首次滚进播一次,滚回时保持就位不重播(用户定案)。
|
||||||
本文件只保留两件 UIKit 管不了的事:分类条宽度填充、减弱动效守卫。
|
本文件只保留两件 UIKit 管不了的事:分类条宽度填充、减弱动效守卫。
|
||||||
══════════════════════════════════════════════════════════════════════════ */
|
══════════════════════════════════════════════════════════════════════════ */
|
||||||
|
|
||||||
/* ── 1) 分类条:填充宽度从 0 长出 ──
|
/* ── 1) 分类条:填充宽度从 0 长出 ──
|
||||||
UIKit 只管「淡入+位移」,宽度是它不管的,用 transition 补。
|
UIKit 只管「淡入+位移」,宽度是它不管的,用 transition 补。
|
||||||
条体被 scrollspy 判定进视口后会带上 .uk-scrollspy-inview,以此放行到目标宽度;
|
条体被 scrollspy 判定进视口后会带上 .uk-scrollspy-inview,以此放行到目标宽度;
|
||||||
repeat 移出视口时类被摘掉 → 宽度回到 0,下次滚进重新长出。 */
|
不写 repeat → inview 类常驻,滚回时宽度保持、不重长。 */
|
||||||
.ab-bar .t i {
|
.ab-bar .t i {
|
||||||
width: 0;
|
width: 0;
|
||||||
transition: width 0.7s cubic-bezier(0.22, 0.61, 0.36, 1) 0.15s;
|
transition: width 0.7s cubic-bezier(0.22, 0.61, 0.36, 1) 0.15s;
|
||||||
}
|
}
|
||||||
.ab-bar.uk-scrollspy-inview .t i,
|
/* scrollspy 的 target 就是 .ab-bar 自身 → inview 类落在条体上,
|
||||||
.uk-scrollspy-inview .ab-bar .t i {
|
只此一个选择器即可(曾多写一条祖先版 .uk-scrollspy-inview .ab-bar,永不匹配) */
|
||||||
|
.ab-bar.uk-scrollspy-inview .t i {
|
||||||
width: var(--ab-bar-w, 0%);
|
width: var(--ab-bar-w, 0%);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4582,14 +4564,6 @@ input[type=submit] {
|
|||||||
.ab-bar .t i { width: var(--ab-bar-w, 0%); transition: none; }
|
.ab-bar .t i { width: var(--ab-bar-w, 0%); transition: none; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── 6) 数据卡悬停:极轻的边框加深,与主题其他卡片观感一致 ──
|
|
||||||
只为「可点」之外的静态卡增加一点呼吸感,不加阴影跳变。 */
|
|
||||||
.ab-stat {
|
|
||||||
transition: border-color 0.25s ease;
|
|
||||||
}
|
|
||||||
.ab-stat:hover { border-color: rgba(0, 0, 0, 0.16); }
|
|
||||||
[data-theme="dark"] .ab-stat:hover { border-color: rgba(255, 255, 255, 0.16); }
|
|
||||||
|
|
||||||
/* ── 关于页响应式 ── */
|
/* ── 关于页响应式 ── */
|
||||||
@media (max-width: 700px) {
|
@media (max-width: 700px) {
|
||||||
.ab-attr { gap: 12px; }
|
.ab-attr { gap: 12px; }
|
||||||
|
|||||||
@@ -8,7 +8,10 @@
|
|||||||
var pjax = new Pjax({
|
var pjax = new Pjax({
|
||||||
// 这里填写页面中改变的部分(和 CSS 选择器用法一样)
|
// 这里填写页面中改变的部分(和 CSS 选择器用法一样)
|
||||||
selectors: ["title", "#pjax-container"],
|
selectors: ["title", "#pjax-container"],
|
||||||
cacheBust: false,
|
// ★ cacheBust: PJAX 取新页面时在 URL 上加时间戳参数,绕开浏览器/CDN
|
||||||
|
// 对 HTML 的长期缓存。没有它,HTML 缓存期内 PJAX 会把「部署前的旧页面」
|
||||||
|
// 直接换进来(站点 HTML 的 Cache-Control 长达数天,踩过实锤)。
|
||||||
|
cacheBust: true,
|
||||||
elements: "a", // 拦截所有链接
|
elements: "a", // 拦截所有链接
|
||||||
switches: {
|
switches: {
|
||||||
"#pjax-container": Pjax.switches.default
|
"#pjax-container": Pjax.switches.default
|
||||||
@@ -21,6 +24,50 @@
|
|||||||
console.log("Pjax initialized:", pjax);
|
console.log("Pjax initialized:", pjax);
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
// ── 静态资源版本同步(修复「部署后 PJAX 页面样式裸奔」)──
|
||||||
|
// ─────────────────────────────────────────────────────────────
|
||||||
|
// 根因:Pjax 只换 title 和 #pjax-container,<head> 里的指纹 CSS
|
||||||
|
// (style.min.<hash>.css)一旦因部署换了指纹,**旧会话**里所有后续
|
||||||
|
// PJAX 页面都跑在旧样式上 —— 新 HTML 的类(.ab-* 等)在旧 CSS 里
|
||||||
|
// 不存在 → 内容裸奔成纯文本(2026-10-07 关于页上线实锤)。
|
||||||
|
//
|
||||||
|
// 解法:pjax:success 时事件对象上带有本次请求(pjax 库把 options 的
|
||||||
|
// 键直接拷到 event 上,options.request = XMLHttpRequest),从
|
||||||
|
// responseText 解析出新页面的样式表指纹,与当前 document 比对;
|
||||||
|
// 不一致 → 整页 reload 一次拿全新资源(sessionStorage 保证每次会话
|
||||||
|
// 至多一次,防异常情况下的循环刷新)。
|
||||||
|
document.addEventListener("pjax:success", function (e) {
|
||||||
|
var request = e.request;
|
||||||
|
if (!request || typeof request.responseText !== "string" || !request.responseText) return;
|
||||||
|
|
||||||
|
var fetchedLinks, currentLinks, i, changed = false;
|
||||||
|
try {
|
||||||
|
var doc = new DOMParser().parseFromString(request.responseText, "text/html");
|
||||||
|
fetchedLinks = doc.querySelectorAll('link[rel="stylesheet"]');
|
||||||
|
currentLinks = document.querySelectorAll('link[rel="stylesheet"]');
|
||||||
|
} catch (err) { return; }
|
||||||
|
|
||||||
|
if (fetchedLinks.length !== currentLinks.length) {
|
||||||
|
changed = true;
|
||||||
|
} else {
|
||||||
|
for (i = 0; i < fetchedLinks.length; i++) {
|
||||||
|
if (fetchedLinks[i].getAttribute("href") !== currentLinks[i].getAttribute("href")) {
|
||||||
|
changed = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!changed) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (sessionStorage.getItem("pjaxVerReload")) return; // 本会话已刷过
|
||||||
|
sessionStorage.setItem("pjaxVerReload", "1");
|
||||||
|
} catch (err) { /* 隐私模式等拿不到 sessionStorage:直接刷,概率极低 */ }
|
||||||
|
|
||||||
|
console.info("[pjax] 检测到样式表版本变化,整页刷新以加载新资源");
|
||||||
|
window.location.reload();
|
||||||
|
});
|
||||||
|
|
||||||
// UIKit 重新扫描(PJAX 必需)
|
// UIKit 重新扫描(PJAX 必需)
|
||||||
// ─────────────────────────────────────────────────────────────
|
// ─────────────────────────────────────────────────────────────
|
||||||
// UIKit 只在页面加载时做一次「全量 boot」:它遍历 document.body,把带
|
// UIKit 只在页面加载时做一次「全量 boot」:它遍历 document.body,把带
|
||||||
|
|||||||
Reference in new issue
Block a user