From a64051177e3b05922862d63c13b4825f40e084ec Mon Sep 17 00:00:00 2001 From: afoim Date: Sun, 10 Aug 2025 17:00:48 +0800 Subject: [PATCH] =?UTF-8?q?refactor(umami):=20=E9=87=8D=E6=9E=84=20Umami?= =?UTF-8?q?=20=E6=95=B0=E6=8D=AE=E8=8E=B7=E5=8F=96=E9=80=BB=E8=BE=91?= =?UTF-8?q?=E5=B9=B6=E6=B7=BB=E5=8A=A0=E7=BC=93=E5=AD=98=E6=9C=BA=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 将重复的 Umami 数据获取逻辑提取为全局工具函数 添加本地缓存和并发请求处理 增加 401 错误时的自动重试机制 --- public/js/umami-share.js | 47 +++++++++++++++++++++++++++++ src/components/PostCard.astro | 14 ++++----- src/components/PostMeta.astro | 15 +++++---- src/components/widget/Profile.astro | 15 ++++----- src/layouts/Layout.astro | 1 + 5 files changed, 70 insertions(+), 22 deletions(-) create mode 100644 public/js/umami-share.js diff --git a/public/js/umami-share.js b/public/js/umami-share.js new file mode 100644 index 000000000..4e090c909 --- /dev/null +++ b/public/js/umami-share.js @@ -0,0 +1,47 @@ +(function (global) { + const cacheKey = 'umami-share-cache'; + const cacheTTL = 3600_000; // 1h + + async function fetchShareData(baseUrl, shareId) { + const cached = localStorage.getItem(cacheKey); + if (cached) { + try { + const parsed = JSON.parse(cached); + if (Date.now() - parsed.timestamp < cacheTTL) { + return parsed.value; + } + } catch { + localStorage.removeItem(cacheKey); + } + } + const res = await fetch(`${baseUrl}/api/share/${shareId}`); + if (!res.ok) { + throw new Error('获取 Umami 分享信息失败'); + } + const data = await res.json(); + localStorage.setItem(cacheKey, JSON.stringify({ timestamp: Date.now(), value: data })); + return data; + } + + /** + * 获取 Umami 分享数据(websiteId、token)。 + * 在缓存 TTL 内复用;并用全局 Promise 避免并发请求。 + * @param {string} baseUrl + * @param {string} shareId + * @returns {Promise<{websiteId: string, token: string}>} + */ + global.getUmamiShareData = function (baseUrl, shareId) { + if (!global.__umamiSharePromise) { + global.__umamiSharePromise = fetchShareData(baseUrl, shareId).catch((err) => { + delete global.__umamiSharePromise; + throw err; + }); + } + return global.__umamiSharePromise; + }; + + global.clearUmamiShareCache = function () { + localStorage.removeItem(cacheKey); + delete global.__umamiSharePromise; + }; +})(window); \ No newline at end of file diff --git a/src/components/PostCard.astro b/src/components/PostCard.astro index c1f26f66f..686d5964e 100644 --- a/src/components/PostCard.astro +++ b/src/components/PostCard.astro @@ -107,13 +107,8 @@ const { remarkPluginFrontmatter } = await entry.render(); } try { - // 第一步:获取网站ID和token - const shareResponse = await fetch(`${umamiConfig.baseUrl}/api/share/${umamiConfig.shareId}`); - if (!shareResponse.ok) { - throw new Error('获取分享信息失败'); - } - const shareData = await shareResponse.json(); - const { websiteId, token } = shareData; + // 调用全局工具获取 Umami 分享数据 + const { websiteId, token } = await getUmamiShareData(umamiConfig.baseUrl, umamiConfig.shareId); // 第二步:获取统计数据 const currentTimestamp = Date.now(); @@ -125,6 +120,11 @@ const { remarkPluginFrontmatter } = await entry.render(); } }); + if (statsResponse.status === 401) { + clearUmamiShareCache(); + return await fetchPostCardViews(slug); + } + if (!statsResponse.ok) { throw new Error('获取统计数据失败'); } diff --git a/src/components/PostMeta.astro b/src/components/PostMeta.astro index e83007601..2e8070e16 100644 --- a/src/components/PostMeta.astro +++ b/src/components/PostMeta.astro @@ -97,19 +97,14 @@ const className = Astro.props.class; {slug && ( {/* */}