From ea9e721d222ff3216da6a51d3bd32d92326f6acd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=8C=E5=8F=89=E6=A0=91=E6=A0=91?= Date: Fri, 30 Jan 2026 03:38:05 +0800 Subject: [PATCH] =?UTF-8?q?fix(NewPostNotification):=20=E4=BF=AE=E5=A4=8DR?= =?UTF-8?q?SS=E6=96=87=E7=AB=A0=E6=A3=80=E6=B5=8B=E4=B8=AD=E7=9A=84?= =?UTF-8?q?=E9=87=8D=E5=A4=8D=E9=80=9A=E7=9F=A5=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修复因GUID处理不一致导致的重复通知。主要修改包括: - 将数据库版本升级至3,确保对象存储使用正确的键路径 - 新增GUID规范化函数,统一处理不同格式的标识符 - 优化文章比较逻辑,使用规范化后的GUID进行匹配 - 改进SCOPE_ID生成方式,基于BASE_URL而非路径名 --- .../widget/NewPostNotification.astro | 42 +++++++++++++------ 1 file changed, 29 insertions(+), 13 deletions(-) diff --git a/src/components/widget/NewPostNotification.astro b/src/components/widget/NewPostNotification.astro index 63ec1b3ff..3a7c46fc0 100644 --- a/src/components/widget/NewPostNotification.astro +++ b/src/components/widget/NewPostNotification.astro @@ -53,14 +53,15 @@ (async function() { const DB_NAME = 'fuwari-rss-store'; - const DB_VERSION = 2; + const DB_VERSION = 3; const STORE_NAME = 'posts'; const LOCAL_STORAGE_KEY = 'blog-posts-cache'; const NOTIFICATION_ID = 'new-post-notification'; const LIST_ID = 'new-post-list'; // Compute a context-aware ID for the current site/path - const SCOPE_ID = window.location.pathname.split('/')[1] || 'root'; + const BASE_PATH = (import.meta.env.BASE_URL ?? '/'); + const SCOPE_ID = BASE_PATH.replace(/^\/+|\/+$/g, '') || 'root'; // IndexedDB Helpers function openDB() { @@ -70,14 +71,30 @@ request.onsuccess = () => resolve(request.result); request.onupgradeneeded = (event) => { const db = event.target.result; - if (!db.objectStoreNames.contains(STORE_NAME)) { - // We use 'id' as the keyPath which will be a composite key - db.createObjectStore(STORE_NAME, { keyPath: 'id' }); + if (db.objectStoreNames.contains(STORE_NAME)) { + const existingStore = event.target.transaction.objectStore(STORE_NAME); + if (existingStore.keyPath !== 'id') { + db.deleteObjectStore(STORE_NAME); + db.createObjectStore(STORE_NAME, { keyPath: 'id' }); + } + return; } + db.createObjectStore(STORE_NAME, { keyPath: 'id' }); }; }); } + function normalizeGuid(guid, link) { + const value = (guid || link || '').trim(); + if (!value) return ''; + try { + const url = new URL(value, window.location.origin); + return `${url.pathname}${url.search}${url.hash}`; + } catch { + return value; + } + } + function generateId(guid) { // Create a unique ID combining the scope (pathname root) and the article guid return `${SCOPE_ID}:${guid}`; @@ -120,8 +137,9 @@ return items.map(item => { const title = item.querySelector('title')?.textContent || ''; - const link = item.querySelector('link')?.textContent || ''; - const guid = item.querySelector('guid')?.textContent || link; + const link = (item.querySelector('link')?.textContent || '').trim(); + const rawGuid = (item.querySelector('guid')?.textContent || '').trim(); + const guid = normalizeGuid(rawGuid || link, link); const pubDate = new Date(item.querySelector('pubDate')?.textContent || '').getTime(); const description = item.querySelector('description')?.textContent || ''; @@ -432,7 +450,7 @@ diff: mockDiff }, ]; - showNotification(mockPosts, Date.now(), true); + showNotification(mockPosts, Date.now(), true, Date.now()); return; } @@ -473,15 +491,13 @@ } else { // Compare const storedMap = new Map( - storedPosts - .filter(p => p.id && p.id.startsWith(`${SCOPE_ID}:`)) - .map(p => [p.guid, p]) + storedPosts.map(p => [p.id || generateId(p.guid || p.link || p.title), p]) ); const detectedChanges = []; currentPosts.forEach(post => { - const stored = storedMap.get(post.guid); + const stored = storedMap.get(generateId(post.guid)); if (!stored) { // New post detectedChanges.push({ ...post, isUpdated: false }); @@ -554,4 +570,4 @@ console.error('New post check failed:', e); } })(); - \ No newline at end of file +