diff --git a/public/auth.json b/public/auth.json index acf0250..5bcc1cc 100644 --- a/public/auth.json +++ b/public/auth.json @@ -26,7 +26,6 @@ "src/main.tsx": "https://kevisual.cn/root/ai/kevisual/frontend/vite-react-template/src/main.tsx", "public/auth.json": "https://kevisual.cn/root/ai/kevisual/frontend/vite-react-template/public/auth.json", "src/agents/index.ts": "https://kevisual.cn/root/ai/kevisual/frontend/vite-react-template/src/agents/index.ts", - "src/modules/basename.ts": "https://kevisual.cn/root/ai/kevisual/frontend/vite-react-template/src/modules/basename.ts", "src/modules/query.ts": "https://kevisual.cn/root/ai/kevisual/frontend/vite-react-template/src/modules/query.ts", "src/routes/demo.tsx": "https://kevisual.cn/root/ai/kevisual/frontend/vite-react-template/src/routes/demo.tsx", "src/routes/index.tsx": "https://kevisual.cn/root/ai/kevisual/frontend/vite-react-template/src/routes/index.tsx", diff --git a/src/components/a/PWAUpdate.tsx b/src/components/a/PWAUpdate.tsx new file mode 100644 index 0000000..d03f1b3 --- /dev/null +++ b/src/components/a/PWAUpdate.tsx @@ -0,0 +1,60 @@ +import { useState } from 'react'; +import { useRegisterSW } from 'virtual:pwa-register/react'; +import { Button } from '@/components/ui/button'; +import { + Card, + CardContent, + CardDescription, + CardFooter, + CardHeader, + CardTitle, +} from '@/components/ui/card'; + +function PWAUpdate() { + const { + needRefresh: [needRefresh, setNeedRefresh], + updateServiceWorker, + } = useRegisterSW({ + onNeedRefresh() { + setNeedRefresh(true); + }, + }); + + const [isLoading, setIsLoading] = useState(false); + + const handleUpdate = async () => { + setIsLoading(true); + await updateServiceWorker(true); + setIsLoading(false); + }; + + const handleDismiss = () => { + setNeedRefresh(false); + }; + + if (!needRefresh) { + return null; + } + + return ( +
+ + + 发现新版本 + 有新版本可用,点击立即更新 + + + + + + + +
+ ); +} + +export default PWAUpdate; diff --git a/src/components/ui/skeleton.tsx b/src/components/ui/skeleton.tsx new file mode 100644 index 0000000..0118624 --- /dev/null +++ b/src/components/ui/skeleton.tsx @@ -0,0 +1,13 @@ +import { cn } from "@/lib/utils" + +function Skeleton({ className, ...props }: React.ComponentProps<"div">) { + return ( +
+ ) +} + +export { Skeleton } diff --git a/src/main.tsx b/src/main.tsx index f876785..30e2907 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -4,6 +4,7 @@ import { routeTree } from './routeTree.gen' import './index.css' import { getDynamicBasename } from './modules/basename' import './agents/index.ts'; +import PWAUpdate from './components/a/PWAUpdate.tsx'; // Set up a Router instance const router = createRouter({ routeTree, @@ -23,5 +24,10 @@ const rootElement = document.getElementById('root')! if (!rootElement.innerHTML) { const root = ReactDOM.createRoot(rootElement) - root.render() + root.render( + <> + + + + ) } \ No newline at end of file diff --git a/vite.config.ts b/vite.config.ts index 1f5a380..648b7ce 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -33,6 +33,38 @@ export default defineConfig({ VitePWA({ injectRegister: 'auto', registerType: 'autoUpdate', + // Workbox 缓存策略配置 + workbox: { + // API 请求使用网络优先策略,确保获取最新数据 + runtimeCaching: [ + { + urlPattern: /^https?.*\/api\/.*/, + handler: 'NetworkFirst', + options: { + cacheName: 'api-cache', + expiration: { + maxEntries: 50, + maxAgeSeconds: 60 * 60 * 24, // 24小时 + }, + cacheableResponse: { + statuses: [0, 200], + }, + }, + }, + // 静态资源使用缓存优先,但设置较短过期时间 + { + urlPattern: /^https?.*\.(js|css|woff2?|png|jpg|jpeg|svg|gif|ico)/, + handler: 'StaleWhileRevalidate', + options: { + cacheName: 'static-resources', + expiration: { + maxEntries: 100, + maxAgeSeconds: 60 * 60 * 24 * 7, // 7天 + }, + }, + }, + ], + }, }), ], resolve: {