From 427b17d7a02f37217c3b4e1bf8ccb37917685303 Mon Sep 17 00:00:00 2001 From: zqlit Date: Wed, 20 May 2026 14:33:05 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=B8=80=E4=B8=8B=E5=8D=9A?= =?UTF-8?q?=E5=AE=A2=E7=9A=84=E6=80=A7=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .claude/settings.json | 13 +- .claude/worktrees/agent-a29465a348705c475 | 1 + .claude/worktrees/agent-a41f7b6fbd8eb1368 | 1 + .claude/worktrees/agent-a88ac4fa046a2faca | 1 + .claude/worktrees/agent-a97b858be06004781 | 1 + GitHubblog.tmp-circles.html | 969 ++++++++++++++++++ GitHubblog.tmp-links.html | 536 ++++++++++ content/about.md | 4 +- themes/Ying/assets/css/main.css | 69 +- themes/Ying/assets/js/modules/cache.js | 202 ++++ .../Ying/assets/js/modules/floating-tools.js | 9 +- themes/Ying/assets/js/modules/lazyload.js | 90 +- themes/Ying/assets/js/modules/mypjax.js | 12 + .../_default/_markup/render-image.html | 9 +- themes/Ying/layouts/_default/list.html | 2 +- themes/Ying/layouts/_default/single.html | 1 - themes/Ying/layouts/index.html | 2 +- themes/Ying/layouts/page/about.html | 2 +- themes/Ying/layouts/page/archives.html | 2 +- themes/Ying/layouts/page/circles.html | 148 ++- themes/Ying/layouts/page/links.html | 98 +- themes/Ying/layouts/partials/footer.html | 9 +- themes/Ying/layouts/partials/head.html | 10 +- themes/Ying/layouts/partials/header.html | 2 +- 24 files changed, 2045 insertions(+), 148 deletions(-) create mode 160000 .claude/worktrees/agent-a29465a348705c475 create mode 160000 .claude/worktrees/agent-a41f7b6fbd8eb1368 create mode 160000 .claude/worktrees/agent-a88ac4fa046a2faca create mode 160000 .claude/worktrees/agent-a97b858be06004781 create mode 100644 GitHubblog.tmp-circles.html create mode 100644 GitHubblog.tmp-links.html create mode 100644 themes/Ying/assets/js/modules/cache.js diff --git a/.claude/settings.json b/.claude/settings.json index 0816336f..26effad4 100644 --- a/.claude/settings.json +++ b/.claude/settings.json @@ -12,7 +12,18 @@ "Read(//e/GitHub/Another-Blog/content/posts/2026/202605091914/**)", "Read(//e/GitHub/Another-Blog/content/posts/2026/202605091921/**)", "Read(//e/GitHub/Another-Blog/content/posts/2026/202604300006/**)", - "Bash(cmd //c \"taskkill /F /PID 40384\")" + "Bash(cmd //c \"taskkill /F /PID 40384\")", + "PowerShell(try { $r = Invoke-WebRequest -UseBasicParsing http://127.0.0.1:1316/circles.html; 'OK' } catch { $_.Exception.Message })", + "Bash(\"/c/Program Files/Google/Chrome/Application/chrome.exe\" --headless=new --disable-gpu --virtual-time-budget=12000 --dump-dom \"http://127.0.0.1:1316/links.html\")", + "Bash(\"/c/Program Files/Google/Chrome/Application/chrome.exe\" --headless=new --disable-gpu --virtual-time-budget=12000 --dump-dom \"http://127.0.0.1:1316/circles.html\")", + "Bash(curl -s http://127.0.0.1:1316/links.html -o E:\\\\GitHub\\\\blog\\\\.tmp-links.html)", + "Bash(curl -s http://127.0.0.1:1316/circles.html -o E:\\\\GitHub\\\\blog\\\\.tmp-circles.html)", + "Bash(curl -s -o \".tmp-links.html\" http://127.0.0.1:1316/links.html)", + "Bash(curl -s -o \".tmp-circles.html\" http://127.0.0.1:1316/circles.html)", + "Bash(curl -s http://127.0.0.1:1316/ -o \".tmp-index.html\")", + "Bash(curl -s \"http://127.0.0.1:1316/js/bundle.min.ca22314448750e3cd87573167443c4f61447dd8c77fdb2a8ecf962e6e770a7b7.js\" -o \".tmp-bundle.js\")", + "Bash([ ! -x \"$CHROME\" ])", + "Bash(powershell -c \"\\(Get-Command chrome.exe\\).Source\")" ], "additionalDirectories": [ "E:\\GitHub\\Another-Blog" diff --git a/.claude/worktrees/agent-a29465a348705c475 b/.claude/worktrees/agent-a29465a348705c475 new file mode 160000 index 00000000..39b69bf8 --- /dev/null +++ b/.claude/worktrees/agent-a29465a348705c475 @@ -0,0 +1 @@ +Subproject commit 39b69bf85087d14ffec41cd4349606db410822c6 diff --git a/.claude/worktrees/agent-a41f7b6fbd8eb1368 b/.claude/worktrees/agent-a41f7b6fbd8eb1368 new file mode 160000 index 00000000..39b69bf8 --- /dev/null +++ b/.claude/worktrees/agent-a41f7b6fbd8eb1368 @@ -0,0 +1 @@ +Subproject commit 39b69bf85087d14ffec41cd4349606db410822c6 diff --git a/.claude/worktrees/agent-a88ac4fa046a2faca b/.claude/worktrees/agent-a88ac4fa046a2faca new file mode 160000 index 00000000..39b69bf8 --- /dev/null +++ b/.claude/worktrees/agent-a88ac4fa046a2faca @@ -0,0 +1 @@ +Subproject commit 39b69bf85087d14ffec41cd4349606db410822c6 diff --git a/.claude/worktrees/agent-a97b858be06004781 b/.claude/worktrees/agent-a97b858be06004781 new file mode 160000 index 00000000..39b69bf8 --- /dev/null +++ b/.claude/worktrees/agent-a97b858be06004781 @@ -0,0 +1 @@ +Subproject commit 39b69bf85087d14ffec41cd4349606db410822c6 diff --git a/GitHubblog.tmp-circles.html b/GitHubblog.tmp-circles.html new file mode 100644 index 00000000..710ba009 --- /dev/null +++ b/GitHubblog.tmp-circles.html @@ -0,0 +1,969 @@ + + + + + + + 友圈 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+
+ 优世界 +
+ 点击头像切换昼夜 +
+
+
+
+ + + + + + + + + +
+
不以物喜,不以己悲
+
+
+ +
+ + + +
+ +
+
+ +
+
+
+

正在探索朋友们的新动态...

+
+
+
+ + + +
+
+
+
+ + +
+ +
+ + + +
+
+
+ + + + + + + + + + + + +
+ + +
+
+
+

搜索文章

+ × +
+
+
+ + +
+
+ +

输入关键词并回车进行搜索

+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/GitHubblog.tmp-links.html b/GitHubblog.tmp-links.html new file mode 100644 index 00000000..4f513022 --- /dev/null +++ b/GitHubblog.tmp-links.html @@ -0,0 +1,536 @@ + + + + + + + 友链 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+
+ 优世界 +
+ 点击头像切换昼夜 +
+
+
+
+ + + + + + + + + +
+
不以物喜,不以己悲
+
+
+ +
+ + + +
+ +
+ +
+ +
+ + +
+ +
+ + + +
+
+
+ + + + + + + + + + + + +
+ + +
+
+
+

搜索文章

+ × +
+
+
+ + +
+
+ +

输入关键词并回车进行搜索

+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/content/about.md b/content/about.md index ec4d26e7..1bb68d8d 100644 --- a/content/about.md +++ b/content/about.md @@ -14,10 +14,10 @@ draft: false

关于博主

Hello, World!

-

湖北 · 襄阳 -> 武汉

+

湖北 · 襄阳 -> 深圳

00后,性格随和,风趣幽默

未来计划定居江苏南京

-

工作:运维工程师

+

工作:待业

diff --git a/themes/Ying/assets/css/main.css b/themes/Ying/assets/css/main.css index ae44ff08..ee344510 100644 --- a/themes/Ying/assets/css/main.css +++ b/themes/Ying/assets/css/main.css @@ -513,8 +513,8 @@ ul { z-index: 10; position: relative; text-align: center; - backdrop-filter: blur(10px); - -webkit-backdrop-filter: blur(10px); + backdrop-filter: blur(6px); + -webkit-backdrop-filter: blur(6px); /* Smoother transition */ transition: background-color 0.5s cubic-bezier(0.4, 0, 0.2, 1), color 0.5s cubic-bezier(0.4, 0, 0.2, 1); @@ -528,15 +528,26 @@ ul { contain-intrinsic-size: 1000px; } */ -/* Mobile Optimization: Remove expensive effects */ -@media (max-width: 767px) { - .main, - [data-theme="dark"] .main, - .artalk-related, - .floating-tools { - backdrop-filter: none !important; - -webkit-backdrop-filter: none !important; - box-shadow: none !important; +@media (min-width: 768px) { + .main { + background: rgba(255, 255, 255, 0.88); + -webkit-backdrop-filter: blur(6px); + backdrop-filter: blur(6px); + } + + [data-theme="dark"] #pjax-loading-skeleton { + -webkit-backdrop-filter: blur(10px); + backdrop-filter: blur(10px); + } + + .floating-tools a { + -webkit-backdrop-filter: blur(4px) saturate(140%); + backdrop-filter: blur(4px) saturate(140%); + } + + .atk-loading { + -webkit-backdrop-filter: none; + backdrop-filter: none; } } @@ -1825,7 +1836,8 @@ darkb-text:active { [data-theme="dark"] #pjax-loading-skeleton { background: rgba(15, 23, 42, 0.94) !important; box-shadow: var(--card-shadow-dark) !important; - backdrop-filter: blur(18px); + -webkit-backdrop-filter: blur(10px); + backdrop-filter: blur(10px); } [data-theme="dark"] .skeleton-line { @@ -2969,6 +2981,17 @@ input[type=submit] { .lazyload { width: 100%; + max-width: 100%; + height: auto; +} + +.post-content img, +.entry-content img { + display: block; + max-width: 100%; + height: auto; + content-visibility: auto; + contain-intrinsic-size: 700px auto; } /* 设置进度条的背景色 */ @@ -3504,8 +3527,8 @@ input[type=submit] { /* Optimized transition: specific properties instead of all */ transition: background-color 0.3s ease, color 0.3s ease, transform 0.3s ease, border-color 0.3s ease; /* Restored backdrop-filter */ - backdrop-filter: blur(10px) saturate(180%); - -webkit-backdrop-filter: blur(10px) saturate(180%); + backdrop-filter: blur(4px) saturate(140%); + -webkit-backdrop-filter: blur(4px) saturate(140%); border: 1px solid rgba(255, 255, 255, 0.4); /* GPU Acceleration for individual items */ transform: translate3d(0, 0, 0); @@ -4060,8 +4083,8 @@ img[atk-emoticon] { background: rgba(255, 255, 255, 0.8) !important; box-shadow: none !important; /* 去除阴影,更简洁 */ border-radius: 8px !important; - backdrop-filter: blur(4px); /* 轻微模糊 */ - -webkit-backdrop-filter: blur(4px); + backdrop-filter: none; + -webkit-backdrop-filter: none; /* display: flex !important; <-- 移除这个强制显示 */ align-items: center; justify-content: center; @@ -4747,17 +4770,17 @@ html[data-theme="light"] .atk-loading-spinner svg circle { /* Lazy Load Animation */ .lazyload { - opacity: 0; - transform: translateY(30px); /* 稍微增加位移距离,增强上浮感 */ - filter: blur(5px); /* 减少模糊,避免过于影响性能 */ - transition: opacity 0.8s ease-out, transform 0.8s cubic-bezier(0.215, 0.61, 0.355, 1), filter 0.8s ease-out; /* 使用 ease-out 和自定义贝塞尔曲线,模拟自然惯性 */ - will-change: opacity, transform; /* 移除 filter 的 will-change 以节省内存 */ + opacity: 1; + transform: none; + filter: none; + transition: none; + will-change: auto; } .lazyload.lazy-loaded { opacity: 1; - transform: translateY(0); - filter: blur(0); + transform: none; + filter: none; } [data-theme="dark"] .ai-comment-card .atk-content p { diff --git a/themes/Ying/assets/js/modules/cache.js b/themes/Ying/assets/js/modules/cache.js new file mode 100644 index 00000000..596293ae --- /dev/null +++ b/themes/Ying/assets/js/modules/cache.js @@ -0,0 +1,202 @@ +window.BrowserCache = (function () { + var PREFIX = 'ying-cache:'; + var DEBUG_KEY = PREFIX + 'debug'; + var DEBUG = detectDebug(); + + function detectDebug() { + try { + if (typeof window === 'undefined' || !window.location) return false; + var loc = window.location; + var host = loc.hostname || ''; + var protocol = loc.protocol || ''; + var search = loc.search || ''; + + // Explicit URL override wins over everything. + if (/(^|[?&])debug-cache=1(&|$)/.test(search)) return true; + if (/(^|[?&])debug-cache=0(&|$)/.test(search)) return false; + + // Persisted toggle (set via setDebug) wins over auto-detection. + try { + var stored = localStorage.getItem(DEBUG_KEY); + if (stored === '1') return true; + if (stored === '0') return false; + } catch (e) {} + + // Auto-enable on local dev origins. + if (protocol === 'file:') return true; + if (host === 'localhost' || host === '127.0.0.1' || host === '0.0.0.0') return true; + } catch (e) {} + return false; + } + + function setDebug(enabled) { + DEBUG = !!enabled; + try { + localStorage.setItem(DEBUG_KEY, DEBUG ? '1' : '0'); + } catch (e) {} + return DEBUG; + } + + function isDebug() { + return DEBUG; + } + + function isStorageAvailable() { + try { + var key = PREFIX + '__test__'; + localStorage.setItem(key, '1'); + localStorage.removeItem(key); + return true; + } catch (e) { + return false; + } + } + + function buildKey(key) { + return PREFIX + key; + } + + function log(tagOrEvent, payload) { + if (!DEBUG || typeof console === 'undefined' || !console.info) return; + var label = tagOrEvent && tagOrEvent.charAt(0) === '[' ? tagOrEvent : '[BrowserCache][' + tagOrEvent + ']'; + console.info(label, payload || {}); + } + + function formatDuration(ms) { + if (!ms || ms <= 0) return '0s'; + var totalSeconds = Math.floor(ms / 1000); + var hours = Math.floor(totalSeconds / 3600); + var minutes = Math.floor((totalSeconds % 3600) / 60); + var seconds = totalSeconds % 60; + if (hours > 0) return hours + 'h ' + minutes + 'm'; + if (minutes > 0) return minutes + 'm ' + seconds + 's'; + return seconds + 's'; + } + + function remove(key) { + if (!isStorageAvailable()) return; + try { + localStorage.removeItem(buildKey(key)); + log('remove', { key: buildKey(key) }); + } catch (e) {} + } + + function read(key, options) { + options = options || {}; + if (!isStorageAvailable()) { + log('storage-unavailable', { key: buildKey(key) }); + return null; + } + + var fullKey = buildKey(key); + + try { + var raw = localStorage.getItem(fullKey); + if (!raw) { + log('miss', { key: fullKey }); + return null; + } + + var payload = JSON.parse(raw); + if (!payload || typeof payload !== 'object') { + remove(key); + log('invalid-payload', { key: fullKey }); + return null; + } + + if (payload.version !== options.version) { + remove(key); + log('version-mismatch', { key: fullKey, expected: options.version, actual: payload.version }); + return null; + } + + if (typeof payload.cachedAt !== 'number' || !('data' in payload)) { + remove(key); + log('invalid-shape', { key: fullKey }); + return null; + } + + if (typeof options.validate === 'function' && !options.validate(payload.data)) { + remove(key); + log('validate-failed', { key: fullKey }); + return null; + } + + var now = Date.now(); + var age = now - payload.cachedAt; + var softTtl = options.softTtl || 0; + var hardTtl = options.hardTtl || softTtl; + + if (hardTtl > 0 && age > hardTtl) { + remove(key); + log('expired', { key: fullKey, age: formatDuration(age), hardTtl: formatDuration(hardTtl) }); + return null; + } + + var result = { + key: fullKey, + data: payload.data, + cachedAt: payload.cachedAt, + age: age, + ageText: formatDuration(age), + softTtl: softTtl, + softTtlText: formatDuration(softTtl), + hardTtl: hardTtl, + hardTtlText: formatDuration(hardTtl), + isFresh: softTtl <= 0 || age <= softTtl, + isStale: softTtl > 0 && age > softTtl + }; + + log(result.isFresh ? 'hit-fresh' : 'hit-stale', { + key: fullKey, + age: result.ageText, + softTtl: result.softTtlText, + hardTtl: result.hardTtlText + }); + + return result; + } catch (e) { + remove(key); + log('parse-failed', { key: fullKey, message: e && e.message ? e.message : e }); + return null; + } + } + + function write(key, options, data) { + options = options || {}; + if (!isStorageAvailable()) { + log('storage-unavailable', { key: buildKey(key) }); + return; + } + + var fullKey = buildKey(key); + + try { + localStorage.setItem(fullKey, JSON.stringify({ + version: options.version, + cachedAt: Date.now(), + data: data + })); + log('write', { + key: fullKey, + softTtl: formatDuration(options.softTtl || 0), + hardTtl: formatDuration(options.hardTtl || options.softTtl || 0) + }); + } catch (e) { + if (DEBUG && typeof console !== 'undefined' && console.warn) { + console.warn('BrowserCache write failed:', e); + } + } + } + + return { + read: read, + write: write, + remove: remove, + buildKey: buildKey, + formatDuration: formatDuration, + log: log, + setDebug: setDebug, + isDebug: isDebug + }; +})(); diff --git a/themes/Ying/assets/js/modules/floating-tools.js b/themes/Ying/assets/js/modules/floating-tools.js index e7c0d5b7..cb559c9a 100644 --- a/themes/Ying/assets/js/modules/floating-tools.js +++ b/themes/Ying/assets/js/modules/floating-tools.js @@ -198,16 +198,21 @@ window.initFloatingTools = function() { } if (container) { - window.lightboxObserver = new MutationObserver(function(mutations) { + var syncLightboxState = function() { var lightbox = document.querySelector('.view-image'); if (lightbox) { container.classList.add('hidden'); } else { container.classList.remove('hidden'); } + }; + + window.lightboxObserver = new MutationObserver(function() { + syncLightboxState(); }); - window.lightboxObserver.observe(document.body, { childList: true }); + window.lightboxObserver.observe(document.body, { childList: true, subtree: true }); + syncLightboxState(); } } catch (e) { diff --git a/themes/Ying/assets/js/modules/lazyload.js b/themes/Ying/assets/js/modules/lazyload.js index d8b48ef1..95799887 100644 --- a/themes/Ying/assets/js/modules/lazyload.js +++ b/themes/Ying/assets/js/modules/lazyload.js @@ -1,77 +1,59 @@ (function() { - // Default configuration var defaults = { - offsetBottom: 100, // Distance from bottom to start loading - showTime: 1100, // Transition duration (ms) - queueInterval: 200 // Time between showing successive images in queue + offsetBottom: 100, + showTime: 1100, + queueInterval: 200 }; var observer; - var imageQueue = []; // Queue for images waiting to be shown - var isProcessingQueue = false; function init(setting) { - // Merge settings defaults = Object.assign({}, defaults, setting || {}); - // Reset queue - imageQueue = []; - isProcessingQueue = false; - - // Disconnect previous observer if exists (for PJAX) if (observer) { observer.disconnect(); observer = null; } - // Check for IntersectionObserver support if (!window.IntersectionObserver) { loadAllImages(); return; } - // Initialize IntersectionObserver observer = new IntersectionObserver(function(entries, self) { entries.forEach(function(entry) { - if (entry.isIntersecting) { - var img = entry.target; - - // Load immediately without queue - loadImage(img); - - // Stop observing this image once it's triggered - self.unobserve(img); - } + if (!entry.isIntersecting) return; + + var img = entry.target; + loadImage(img); + self.unobserve(img); }); }, { - rootMargin: "0px 0px " + defaults.offsetBottom + "px 0px", - threshold: 0.01 + rootMargin: "0px 0px " + defaults.offsetBottom + "px 0px", + threshold: 0.01 }); observeImages(); } - // Removed addToQueue and processQueue functions as we want instant loading + function getPendingImages() { + return document.querySelectorAll('img.lazyload[data-lazy-src], .post-content img[data-lazy-src]:not(.lazy-loaded)'); + } function observeImages() { - var images = document.querySelectorAll('img.lazyload, .post-content img:not(.lazy-loaded)'); - + var images = getPendingImages(); + images.forEach(function(img) { - if (img.classList.contains('lazy-loaded')) return; - - // Update transition duration based on settings - if (defaults.showTime) { - // We'll set this via inline style or rely on CSS class if it matches default - // But for full control, let's set it - img.style.transitionDuration = (defaults.showTime / 1000) + 's'; - } - - if (img.getAttribute('data-lazy-src')) { - observer.observe(img); - } + observer.observe(img); }); } + function markLoaded(img, callback) { + img.classList.add('lazy-loaded'); + img.removeAttribute('data-lazy-src'); + if (callback) callback(); + } + function loadImage(img, callback) { var src = img.getAttribute('data-lazy-src'); if (!src) { @@ -79,37 +61,28 @@ return; } + img.decoding = 'async'; + var temp = new Image(); - - var onComplete = function() { - // Swap source + temp.decoding = 'async'; + + temp.onload = function() { img.src = src; - - requestAnimationFrame(() => { - requestAnimationFrame(() => { - img.classList.add('lazy-loaded'); - img.removeAttribute('data-lazy-src'); - // Execute callback immediately after starting animation logic - if (callback) callback(); - }); + requestAnimationFrame(function() { + markLoaded(img, callback); }); }; - temp.onload = onComplete; temp.onerror = function() { - // Fallback img.src = src; - requestAnimationFrame(() => { - img.classList.add('lazy-loaded'); - if (callback) callback(); - }); + markLoaded(img, callback); }; temp.src = src; } function loadAllImages() { - var images = document.querySelectorAll('img.lazyload'); + var images = getPendingImages(); images.forEach(function(img) { loadImage(img); }); @@ -117,5 +90,4 @@ window.lazyLoadInit = init; window.lazyLoadRefresh = observeImages; - })(); diff --git a/themes/Ying/assets/js/modules/mypjax.js b/themes/Ying/assets/js/modules/mypjax.js index f41a174a..2d5d5530 100644 --- a/themes/Ying/assets/js/modules/mypjax.js +++ b/themes/Ying/assets/js/modules/mypjax.js @@ -50,6 +50,16 @@ function pjax_reload() { } } +function refreshHeatmap() { + if (typeof renderHeatmap === 'function') { + try { + renderHeatmap(); + } catch (e) { + console.error('renderHeatmap error:', e); + } + } +} + // pjax发送时期 document.addEventListener("pjax:send", function () { // pjax动画减少圆圈动画 @@ -141,4 +151,6 @@ document.addEventListener("pjax:complete", function () { window.initSearch(); } catch(e) { console.error('initSearch error:', e); } } + + refreshHeatmap(); }); diff --git a/themes/Ying/layouts/_default/_markup/render-image.html b/themes/Ying/layouts/_default/_markup/render-image.html index 50dd7bd1..abd39b8e 100644 --- a/themes/Ying/layouts/_default/_markup/render-image.html +++ b/themes/Ying/layouts/_default/_markup/render-image.html @@ -1,10 +1,17 @@ {{ $src := .Destination }} +{{ $alt := .Text }} +{{ $width := "" }} +{{ $height := "" }} +{{ $srcset := "" }} + {{- if not (strings.HasPrefix $src "http") -}} {{- $img := .Page.Resources.GetMatch $src -}} {{- if $img -}} {{- $src = $img.RelPermalink -}} + {{- $width = printf "%d" $img.Width -}} + {{- $height = printf "%d" $img.Height -}} {{- else -}} {{- $src = $src | relURL -}} {{- end -}} {{- end -}} -{{ .Text }} \ No newline at end of file +{{ $alt }} \ No newline at end of file diff --git a/themes/Ying/layouts/_default/list.html b/themes/Ying/layouts/_default/list.html index 5d7d9023..193e1e0f 100644 --- a/themes/Ying/layouts/_default/list.html +++ b/themes/Ying/layouts/_default/list.html @@ -6,7 +6,7 @@ {{ range $paginator.Pages }}
{{ .Date.Format "January 2, 2006" }}
- {{ .Title }} + {{ .Title }}
{{ end }}
diff --git a/themes/Ying/layouts/_default/single.html b/themes/Ying/layouts/_default/single.html index 2f524707..870533fc 100644 --- a/themes/Ying/layouts/_default/single.html +++ b/themes/Ying/layouts/_default/single.html @@ -90,6 +90,5 @@ {{ end }} - {{ end }} \ No newline at end of file diff --git a/themes/Ying/layouts/index.html b/themes/Ying/layouts/index.html index 943adf73..8c0760ae 100644 --- a/themes/Ying/layouts/index.html +++ b/themes/Ying/layouts/index.html @@ -41,7 +41,7 @@ {{ range $paginator.Pages }}
{{ .Date.Format "January 2, 2006" }}
- {{ .Title }} + {{ .Title }} {{ $publishDate := .Date }} diff --git a/themes/Ying/layouts/page/about.html b/themes/Ying/layouts/page/about.html index a3d0fd92..4a06c8b0 100644 --- a/themes/Ying/layouts/page/about.html +++ b/themes/Ying/layouts/page/about.html @@ -1,5 +1,5 @@ {{ define "main" }} -
+
{{ .Content }} diff --git a/themes/Ying/layouts/page/archives.html b/themes/Ying/layouts/page/archives.html index daf5b780..48a70bd4 100644 --- a/themes/Ying/layouts/page/archives.html +++ b/themes/Ying/layouts/page/archives.html @@ -38,7 +38,7 @@
  • {{ .Date.Format "01/02" }} - {{ .Title }} + {{ .Title }}
  • {{ end }} diff --git a/themes/Ying/layouts/page/circles.html b/themes/Ying/layouts/page/circles.html index 5388d5e9..7ddeab1a 100644 --- a/themes/Ying/layouts/page/circles.html +++ b/themes/Ying/layouts/page/circles.html @@ -337,6 +337,15 @@ allPosts: [], currentIndex: 0, BATCH_SIZE: 10, + CACHE_KEY: 'friend-circle-v1', + CACHE_OPTIONS: { + version: 2, + softTtl: 5 * 60 * 1000, + hardTtl: 60 * 60 * 1000, + validate: function(data) { + return !!data && Array.isArray(data.posts); + } + }, timeAgo: function (dateStr) { const date = new Date(dateStr); @@ -403,6 +412,74 @@ }); }, + renderEmpty: function () { + const container = document.getElementById("friend-circle-container"); + if (!container) return; + container.innerHTML = '
    暂无动态
    '; + }, + + renderError: function () { + const container = document.getElementById("friend-circle-container"); + if (!container) return; + container.innerHTML = '
    加载失败,请稍后刷新重试
    '; + }, + + applyData: function (data) { + const container = document.getElementById("friend-circle-container"); + if (!container) return; + + if (!data.posts || data.posts.length === 0) { + this.renderEmpty(); + return; + } + + window.FriendCircle.allPosts = data.posts; + window.fcUpdateTime = new Date(data.updated).toLocaleString(); + window.FriendCircle.currentIndex = 0; + container.innerHTML = ""; + window.FriendCircle.loadMore(); + }, + + fetchData: function () { + if (window.BrowserCache && typeof window.BrowserCache.log === 'function') { + window.BrowserCache.log('[FriendCircleCache][fetch]', { + key: window.BrowserCache ? window.BrowserCache.buildKey(window.FriendCircle.CACHE_KEY) : window.FriendCircle.CACHE_KEY, + softTtl: window.BrowserCache ? window.BrowserCache.formatDuration(window.FriendCircle.CACHE_OPTIONS.softTtl) : window.FriendCircle.CACHE_OPTIONS.softTtl, + hardTtl: window.BrowserCache ? window.BrowserCache.formatDuration(window.FriendCircle.CACHE_OPTIONS.hardTtl) : window.FriendCircle.CACHE_OPTIONS.hardTtl + }); + } + return fetch("https://rssapi.usj.cc/api/articles?limit=50") + .then(function(res) { + if (!res.ok) throw new Error("Network response was not ok"); + return res.json(); + }) + .then(function(apiData) { + const posts = (apiData.articles || []).map(function(a) { + return { + title: a.title || '', + link: a.link || '', + date: a.pubDate || '', + author: a.feedName || a.author || '', + avatar: a.favicon || '', + blogUrl: a.siteUrl || '', + image: null, + description: '' + }; + }); + + const data = { + posts: posts, + updated: apiData.timestamp || new Date().toISOString() + }; + + if (window.BrowserCache) { + window.BrowserCache.write(window.FriendCircle.CACHE_KEY, window.FriendCircle.CACHE_OPTIONS, data); + } + + return data; + }); + }, + initTooltip: function() { if (this.tooltipInitialized) return; this.tooltipInitialized = true; @@ -476,42 +553,35 @@ if (this.isFetching) return; this.isFetching = true; - // 从 RSS API 拉取按时间排序的文章 - fetch("https://rssapi.usj.cc/api/articles?limit=50&t=" + new Date().getTime()) - .then(function(res) { - if (!res.ok) throw new Error("Network response was not ok"); - return res.json(); - }) - .then(function(apiData) { - // 将 API 格式转换为友圈格式 - const posts = (apiData.articles || []).map(function(a) { - return { - title: a.title || '', - link: a.link || '', - date: a.pubDate || '', - author: a.feedName || a.author || '', - avatar: a.favicon || '', - blogUrl: a.siteUrl || '', - image: null, - description: '' - }; + const cached = window.BrowserCache && window.BrowserCache.read(this.CACHE_KEY, this.CACHE_OPTIONS); + if (cached) { + if (window.BrowserCache && typeof window.BrowserCache.log === 'function') { + window.BrowserCache.log('[FriendCircleCache][render]', { + key: cached.key, + age: cached.ageText, + isFresh: cached.isFresh, + softTtl: cached.softTtlText, + hardTtl: cached.hardTtlText }); - const data = { posts: posts, updated: apiData.timestamp || new Date().toISOString() }; + } + this.applyData(cached.data); + if (cached.isFresh) { + this.isFetching = false; + return; + } + } - if (!data.posts || data.posts.length === 0) { - container.innerHTML = '
    暂无动态
    '; - return; - } - - window.FriendCircle.allPosts = data.posts; - window.fcUpdateTime = new Date(data.updated).toLocaleString(); - window.FriendCircle.currentIndex = 0; - container.innerHTML = ""; - window.FriendCircle.loadMore(); + this.fetchData() + .then(function(data) { + window.FriendCircle.applyData(data); }) .catch(function(err) { - console.error("Friend Circle Error:", err); - container.innerHTML = '
    加载失败,请稍后刷新重试
    '; + if (window.BrowserCache && window.BrowserCache.isDebug && window.BrowserCache.isDebug()) { + console.error("Friend Circle Error:", err); + } + if (!cached) { + window.FriendCircle.renderError(); + } }) .finally(function() { window.FriendCircle.isFetching = false; @@ -519,12 +589,18 @@ } }; - if (document.readyState === "loading") { - document.addEventListener("DOMContentLoaded", function() { + function initFriendCirclePage() { + if (window.FriendCircle && typeof window.FriendCircle.init === 'function') { window.FriendCircle.init(); - }); + } + } + + document.addEventListener('pjax:complete', initFriendCirclePage); + + if (document.readyState === "loading") { + document.addEventListener("DOMContentLoaded", initFriendCirclePage); } else { - window.FriendCircle.init(); + initFriendCirclePage(); }
    diff --git a/themes/Ying/layouts/page/links.html b/themes/Ying/layouts/page/links.html index b531490e..b03d5938 100644 --- a/themes/Ying/layouts/page/links.html +++ b/themes/Ying/layouts/page/links.html @@ -78,18 +78,96 @@ var list = document.getElementById('links-list'); if (!list) return; - fetch('https://rssapi.usj.cc/api/links?t=' + new Date().getTime()) - .then(function(res) { return res.json(); }) - .then(function(data) { - var links = data.links || []; - if (links.length === 0) return; - var html = ''; - links.forEach(function(l) { - html += '
  • ' + l.name + '' + (l.description || '') + '
  • '; + var CACHE_KEY = 'friend-links-v1'; + var CACHE_OPTIONS = { + version: 2, + softTtl: 6 * 60 * 60 * 1000, + hardTtl: 24 * 60 * 60 * 1000, + validate: function(data) { + return !!data && Array.isArray(data.links); + } + }; + + function escapeHtml(value) { + return String(value || '') + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"') + .replace(/'/g, '''); + } + + function renderState(message, className) { + list.innerHTML = '
  • ' + escapeHtml(message) + '
  • '; + } + + function renderLinks(links) { + if (!Array.isArray(links) || links.length === 0) { + renderState('暂无友链数据', 'links-empty'); + return; + } + + var html = ''; + links.forEach(function(l) { + html += '
  • ' + escapeHtml(l.name) + '' + escapeHtml(l.description || '') + '
  • '; + }); + list.innerHTML = html; + } + + function logCache(event, payload) { + if (window.BrowserCache && typeof window.BrowserCache.log === 'function') { + window.BrowserCache.log('[LinksCache][' + event + ']', payload); + } + } + + function fetchLinks() { + logCache('fetch', { + key: window.BrowserCache ? window.BrowserCache.buildKey(CACHE_KEY) : CACHE_KEY, + softTtl: window.BrowserCache ? window.BrowserCache.formatDuration(CACHE_OPTIONS.softTtl) : CACHE_OPTIONS.softTtl, + hardTtl: window.BrowserCache ? window.BrowserCache.formatDuration(CACHE_OPTIONS.hardTtl) : CACHE_OPTIONS.hardTtl + }); + return fetch('https://rssapi.usj.cc/api/links') + .then(function(res) { + if (!res.ok) throw new Error('Failed to fetch links'); + return res.json(); + }) + .then(function(data) { + var links = Array.isArray(data.links) ? data.links : []; + var payload = { links: links }; + window.BrowserCache.write(CACHE_KEY, CACHE_OPTIONS, payload); + return payload; }); - list.innerHTML = html; + } + + var cached = window.BrowserCache && window.BrowserCache.read(CACHE_KEY, CACHE_OPTIONS); + if (cached) { + logCache('render', { + key: cached.key, + age: cached.ageText, + isFresh: cached.isFresh, + softTtl: cached.softTtlText, + hardTtl: cached.hardTtlText + }); + renderLinks(cached.data.links); + if (cached.isFresh) { + return; + } + } else { + renderState('友链加载中...', 'links-loading'); + } + + fetchLinks() + .then(function(payload) { + renderLinks(payload.links); }) - .catch(function() {}); + .catch(function(err) { + if (window.BrowserCache && window.BrowserCache.isDebug && window.BrowserCache.isDebug()) { + console.error('Links Error:', err); + } + if (!cached) { + renderState('友链加载失败,请稍后刷新重试', 'links-error'); + } + }); })();
    diff --git a/themes/Ying/layouts/partials/footer.html b/themes/Ying/layouts/partials/footer.html index 6a1db395..a082a469 100644 --- a/themes/Ying/layouts/partials/footer.html +++ b/themes/Ying/layouts/partials/footer.html @@ -52,19 +52,20 @@ {{ $uikit := resources.Get "js/libs/uikit.min.js" }} {{ $easylazyload := resources.Get "js/modules/lazyload.js" }} {{ $viewimage := resources.Get "js/libs/view-image.min.js" }} -{{ $artalk := resources.Get "js/libs/Artalk.js" }} {{ $barrage := resources.Get "js/modules/barrage.js" }} {{ $main := resources.Get "js/main.js" }} {{ $mypjax := resources.Get "js/modules/mypjax.js" }} {{ $nprogress := resources.Get "js/libs/nprogress.js" }} {{ $message := resources.Get "js/libs/message.min.js" }} -{{ $echarts := resources.Get "js/libs/echarts.min.js" }} {{ $tiaozhuan := resources.Get "js/modules/tiaozhuan.js" }} {{ $reward := resources.Get "js/modules/reward.js" }} +{{ $echarts := resources.Get "js/libs/echarts.min.js" }} +{{ $artalk := resources.Get "js/libs/Artalk.js" }} {{/* Modules */}} {{ $utils := resources.Get "js/modules/utils.js" }} {{ $loader := resources.Get "js/modules/loader.js" }} +{{ $cache := resources.Get "js/modules/cache.js" }} {{ $search := resources.Get "js/modules/search.js" }} {{ $floatingTools := resources.Get "js/modules/floating-tools.js" }} {{ $paragraphComments := resources.Get "js/modules/paragraph-comments.js" }} @@ -72,9 +73,9 @@ {{ $artalkModule := resources.Get "js/modules/artalk.js" }} {{ $pjaxLib := resources.Get "js/libs/pjax.js" }} -{{ $scripts := slice $iconfont $lightgallery $uikit $easylazyload $viewimage $artalk $barrage $utils $loader $search $floatingTools $paragraphComments $infiniteScroll $artalkModule $nprogress $pjaxLib $main $mypjax $message $echarts $tiaozhuan $reward | resources.Concat "js/bundle.js" | resources.Minify | resources.Fingerprint }} +{{ $scripts := slice $iconfont $lightgallery $uikit $easylazyload $viewimage $barrage $utils $loader $cache $search $floatingTools $paragraphComments $infiniteScroll $artalkModule $nprogress $pjaxLib $main $mypjax $message $tiaozhuan $reward $echarts $artalk | resources.Concat "js/bundle.js" | resources.Minify | resources.Fingerprint }} - + +