Files
EmailBill/Web/public/service-worker.js
孙诚 319f8f7d7b
Some checks failed
Docker Build & Deploy / Build Docker Image (push) Failing after 1m10s
Docker Build & Deploy / Deploy to Production (push) Has been skipped
Docker Build & Deploy / Cleanup Dangling Images (push) Successful in 1s
Docker Build & Deploy / WeChat Notification (push) Successful in 1s
大量的代码格式化
2026-01-16 11:15:44 +08:00

194 lines
5.0 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
const VERSION = '1.0.0' // Build Time: 2026-01-07 15:59:36
const CACHE_NAME = `emailbill-${VERSION}`
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) => {
// 只针对成功的GET请求进行缓存
if (request.method === 'GET' && response.status === 200) {
const responseClone = response.clone()
caches.open(CACHE_NAME).then((cache) => {
cache.put(request, responseClone)
})
}
return response
})
.catch(() => {
// 网络失败时尝试从缓存获取
return caches.match(request)
})
)
return
}
// 页面请求使用网络优先策略,确保能获取到最新的 index.html
if (request.mode === 'navigate') {
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('/index.html') || 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)
}
}