const CACHE_NAME = 'emailbill-v1'; const urlsToCache = [ '/', '/index.html', '/favicon.ico', '/manifest.json' ]; // 安装 Service Worker self.addEventListener('install', (event) => { console.log('[Service Worker] 安装中...'); event.waitUntil( caches.open(CACHE_NAME) .then((cache) => { console.log('[Service Worker] 缓存文件'); return cache.addAll(urlsToCache); }) ); }); // 监听跳过等待消息 self.addEventListener('message', (event) => { if (event.data && event.data.type === 'SKIP_WAITING') { self.skipWaiting(); } }); // 激活 Service Worker self.addEventListener('activate', (event) => { console.log('[Service Worker] 激活中...'); event.waitUntil( caches.keys().then((cacheNames) => { return Promise.all( cacheNames.map((cacheName) => { if (cacheName !== CACHE_NAME) { console.log('[Service Worker] 删除旧缓存:', cacheName); return caches.delete(cacheName); } }) ); }).then(() => self.clients.claim()) ); }); // 拦截请求 self.addEventListener('fetch', (event) => { const { request } = event; const url = new URL(request.url); // 跳过跨域请求 if (url.origin !== location.origin) { return; } // API请求使用网络优先策略 if (url.pathname.startsWith('/api/')) { event.respondWith( fetch(request) .then((response) => { // 克隆响应以便缓存 const responseClone = response.clone(); caches.open(CACHE_NAME).then((cache) => { cache.put(request, responseClone); }); return response; }) .catch(() => { // 网络失败时尝试从缓存获取 return caches.match(request); }) ); return; } // 静态资源使用缓存优先策略 event.respondWith( caches.match(request) .then((response) => { if (response) { return response; } return fetch(request).then((response) => { // 检查是否是有效响应 if (!response || response.status !== 200 || response.type !== 'basic') { return response; } const responseClone = response.clone(); caches.open(CACHE_NAME).then((cache) => { cache.put(request, responseClone); }); return response; }); }) .catch(() => { // 返回离线页面或默认内容 if (request.destination === 'document') { return caches.match('/index.html'); } }) ); }); // 后台同步 self.addEventListener('sync', (event) => { console.log('[Service Worker] 后台同步:', event.tag); if (event.tag === 'sync-data') { event.waitUntil(syncData()); } }); // 推送通知 self.addEventListener('push', (event) => { console.log('[Service Worker] 收到推送消息'); let data = { title: '账单管理', body: '您有新的消息', url: '/', icon: '/icons/icon-192x192.png' }; if (event.data) { try { const json = event.data.json(); data = { ...data, ...json }; } catch { data.body = event.data.text(); } } const options = { body: data.body, icon: data.icon, badge: '/icons/icon-72x72.png', vibrate: [200, 100, 200], tag: 'emailbill-notification', requireInteraction: false, data: { url: data.url } }; event.waitUntil( self.registration.showNotification(data.title, options) ); }); // 通知点击 self.addEventListener('notificationclick', (event) => { console.log('[Service Worker] 通知被点击'); event.notification.close(); const urlToOpen = event.notification.data?.url || '/'; event.waitUntil( clients.matchAll({ type: 'window', includeUncontrolled: true }).then((windowClients) => { // 如果已经打开了该 URL,则聚焦 for (let i = 0; i < windowClients.length; i++) { const client = windowClients[i]; if (client.url === urlToOpen && 'focus' in client) { return client.focus(); } } // 否则打开新窗口 if (clients.openWindow) { return clients.openWindow(urlToOpen); } }) ); }); // 数据同步函数 async function syncData() { try { // 这里添加需要同步的逻辑 console.log('[Service Worker] 执行数据同步'); } catch (error) { console.error('[Service Worker] 同步失败:', error); } }