- Add company module (3-tier org, CEO planning, parallel departments) - Add company orchestrator, knowledge extractor, presets, scheduler - Add company API endpoints, models, and frontend views - Add 今天吃啥 PWA app (69 dishes, real images, offline support) - Add team_projects output directory structure - Add unified manage.ps1 for service lifecycle - Add Windows startup guide v1.0 - Add TTS troubleshooting doc - Update frontend (AgentChat UX overhaul, new views) - Update backend (voice engine fix, multi-tenant, RBAC) - Remove deprecated startup scripts and old docs Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
89 lines
2.3 KiB
JavaScript
89 lines
2.3 KiB
JavaScript
/**
|
||
* Service Worker — 今天吃啥 PWA
|
||
* 策略:静态资源 Cache First,数据 Network First,图片 Cache First
|
||
*/
|
||
const CACHE_STATIC = 'weinan-dishes-v1';
|
||
const CACHE_IMAGES = 'weinan-images-v1';
|
||
|
||
const STATIC_FILES = [
|
||
'/',
|
||
'/index.html',
|
||
'/style.css',
|
||
'/app.js',
|
||
'/dishes.json',
|
||
'/manifest.json',
|
||
];
|
||
|
||
// Install: 预缓存核心静态资源
|
||
self.addEventListener('install', (event) => {
|
||
event.waitUntil(
|
||
caches.open(CACHE_STATIC).then((cache) => {
|
||
return cache.addAll(STATIC_FILES);
|
||
})
|
||
);
|
||
self.skipWaiting();
|
||
});
|
||
|
||
// Activate: 清理旧缓存
|
||
self.addEventListener('activate', (event) => {
|
||
event.waitUntil(
|
||
caches.keys().then((keys) => {
|
||
return Promise.all(
|
||
keys.filter((k) => k !== CACHE_STATIC && k !== CACHE_IMAGES)
|
||
.map((k) => caches.delete(k))
|
||
);
|
||
})
|
||
);
|
||
self.clients.claim();
|
||
});
|
||
|
||
// Fetch: 按资源类型分策略
|
||
self.addEventListener('fetch', (event) => {
|
||
const url = new URL(event.request.url);
|
||
|
||
// 图片: Cache First
|
||
if (url.pathname.match(/\.(jpg|png|svg|webp|ico)$/i)) {
|
||
event.respondWith(
|
||
caches.match(event.request).then((cached) => {
|
||
const fetchPromise = fetch(event.request).then((response) => {
|
||
if (response.ok) {
|
||
const clone = response.clone();
|
||
caches.open(CACHE_IMAGES).then((cache) => cache.put(event.request, clone));
|
||
}
|
||
return response;
|
||
});
|
||
return cached || fetchPromise;
|
||
})
|
||
);
|
||
return;
|
||
}
|
||
|
||
// dishes.json: Network First(保证数据新鲜)
|
||
if (url.pathname.endsWith('dishes.json')) {
|
||
event.respondWith(
|
||
fetch(event.request)
|
||
.then((response) => {
|
||
const clone = response.clone();
|
||
caches.open(CACHE_STATIC).then((cache) => cache.put(event.request, clone));
|
||
return response;
|
||
})
|
||
.catch(() => caches.match(event.request))
|
||
);
|
||
return;
|
||
}
|
||
|
||
// HTML/CSS/JS: Cache First(App Shell)
|
||
event.respondWith(
|
||
caches.match(event.request).then((cached) => {
|
||
const fetchPromise = fetch(event.request).then((response) => {
|
||
if (response.ok) {
|
||
const clone = response.clone();
|
||
caches.open(CACHE_STATIC).then((cache) => cache.put(event.request, clone));
|
||
}
|
||
return response;
|
||
});
|
||
return cached || fetchPromise;
|
||
})
|
||
);
|
||
});
|