Skip to content

Commit 8e611fa

Browse files
committed
feat: Implement PWA prompts and settings for enhanced user experience
- Added PWAPrompts component to handle installation, update, offline, and online notifications. - Created PWASettings component for managing PWA installation status, network status, and cache management. - Introduced NotificationReminderSnackbar for prompting users to enable notifications. - Developed usePWA composable for managing PWA installation and update logic. - Integrated push notification service with subscription management and permission handling. - Added pwa-notifications.js for handling push notifications in the service worker. - Implemented pwaNotificationService for managing push notification subscriptions and permissions. - Created a dedicated page for PWA settings in the app. - Added functionality for clearing different types of caches and displaying relevant notifications.
1 parent 867ec6a commit 8e611fa

28 files changed

+14115
-473
lines changed

.claude/settings.local.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
{
22
"permissions": {
33
"allow": [
4-
"Bash(rm:*)"
4+
"Bash(rm:*)",
5+
"Bash(npm install:*)",
6+
"Bash(mv:*)",
7+
"Bash(cp:*)"
58
],
69
"deny": []
710
}

PWA-SUMMARY.md

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
# PWA 功能重构完成总结
2+
3+
## 🎉 重构完成
4+
5+
Service Worker 已成功重构,使用 Vue 生态系统中最专业的 PWA 解决方案,集成现有代码并添加了丰富的 PWA 支持。
6+
7+
## 🚀 实现的功能
8+
9+
### 1. **现代化 PWA 架构**
10+
- ✅ 使用 `vite-plugin-pwa` 插件自动生成 Service Worker
11+
- ✅ 基于 Workbox 的智能缓存策略
12+
- ✅ 支持开发环境 PWA 测试
13+
- ✅ 生产环境优化构建
14+
15+
### 2. **智能缓存系统**
16+
- **图片缓存**: CacheFirst 策略,30天过期
17+
- **API缓存**: NetworkFirst 策略,24小时过期
18+
- **静态资源**: 自动预缓存和版本管理
19+
- **离线回退**: 离线时显示缓存页面
20+
21+
### 3. **完整的 PWA 体验**
22+
- ✅ 应用安装提示(30秒后智能显示)
23+
- ✅ 离线/在线状态检测和提醒
24+
- ✅ 应用更新通知和一键更新
25+
- ✅ 推送通知完整支持
26+
- ✅ 应用快捷方式
27+
- ✅ 启动画面和图标配置
28+
29+
### 4. **管理界面**
30+
- **PWA设置页面**: `/app/account/pwa`
31+
- **缓存管理**: 分类清理不同类型缓存
32+
- **安装状态**: 实时显示PWA安装状态
33+
- **更新控制**: 手动触发应用更新
34+
35+
### 5. **推送通知增强**
36+
- ✅ 保留现有推送通知功能
37+
- ✅ 增强通知交互(查看/关闭按钮)
38+
- ✅ 智能页面跳转和聚焦
39+
- ✅ 高优先级通知支持
40+
- ✅ 通知分析统计
41+
42+
## 🛠 技术架构
43+
44+
### 核心组件
45+
```
46+
src/
47+
├── composables/
48+
│ └── usePWA.js # PWA状态管理
49+
├── services/
50+
│ └── pwaNotificationService.js # 推送通知服务
51+
├── components/
52+
│ ├── PWAPrompts.vue # 安装/更新提示
53+
│ └── PWASettings.vue # PWA设置界面
54+
└── pages/app/account/
55+
└── pwa.vue # PWA设置页面
56+
```
57+
58+
### 配置文件
59+
```
60+
├── vite.config.mjs # PWA构建配置
61+
├── index.html # PWA meta标签
62+
└── public/
63+
└── pwa-notifications.js # 自定义推送通知逻辑
64+
```
65+
66+
## 📱 用户体验
67+
68+
### 安装流程
69+
1. 用户访问网站30秒后,自动显示安装提示
70+
2. 用户点击"安装",应用添加到主屏幕
71+
3. 应用以独立窗口运行,提供原生应用体验
72+
73+
### 更新流程
74+
1. 后台自动检测新版本
75+
2. 显示更新提示,用户选择立即更新或稍后
76+
3. 一键更新,自动重载到最新版本
77+
78+
### 离线体验
79+
1. 智能缓存已访问的页面和资源
80+
2. 离线时显示缓存内容
81+
3. 网络恢复时自动同步最新数据
82+
83+
## 🔧 开发者功能
84+
85+
### 缓存管理
86+
- 分类清理:API缓存、图片缓存、静态资源缓存
87+
- 一键清理所有缓存
88+
- 缓存状态监控
89+
90+
### 调试功能
91+
- 开发环境启用PWA功能
92+
- Service Worker版本信息
93+
- 网络状态监控
94+
- 安装状态检测
95+
96+
## 🎯 解决的问题
97+
98+
1. **✅ 组件命名冲突**: 重命名了重复的 `NotificationsCard` 组件
99+
2. **✅ Workbox配置错误**: 简化配置,使用标准的 vite-plugin-pwa 设置
100+
3. **✅ 依赖管理**: 移除手动安装的 Workbox 依赖,使用插件自带版本
101+
4. **✅ 推送通知集成**: 保留现有功能,增强用户体验
102+
103+
## 🚀 使用方法
104+
105+
### 开发环境测试
106+
```bash
107+
npm run dev
108+
```
109+
PWA 功能在开发环境已启用,可以测试安装、缓存等功能。
110+
111+
### 生产环境构建
112+
```bash
113+
npm run build
114+
```
115+
自动生成优化的 Service Worker 和 PWA 资源。
116+
117+
### 访问PWA设置
118+
用户可通过 `/app/account/pwa` 访问完整的PWA管理界面。
119+
120+
## 🎉 总结
121+
122+
这次重构提供了业界标准的PWA解决方案,具备:
123+
- **专业级**: 使用Vue生态最佳PWA工具链
124+
- **智能化**: 自动缓存策略和更新管理
125+
- **用户友好**: 直观的安装和管理界面
126+
- **开发者友好**: 完善的调试和监控工具
127+
- **高性能**: 智能预缓存提升加载速度
128+
- **离线支持**: 完整的离线使用体验
129+
130+
现在 ZeroCat 社区拥有了现代化的 PWA 能力!🎊

dev-dist/registerSW.js

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dev-dist/sw.js

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
/**
2+
* Copyright 2018 Google Inc. All Rights Reserved.
3+
* Licensed under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License.
5+
* You may obtain a copy of the License at
6+
* http://www.apache.org/licenses/LICENSE-2.0
7+
* Unless required by applicable law or agreed to in writing, software
8+
* distributed under the License is distributed on an "AS IS" BASIS,
9+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10+
* See the License for the specific language governing permissions and
11+
* limitations under the License.
12+
*/
13+
14+
// If the loader is already loaded, just stop.
15+
if (!self.define) {
16+
let registry = {};
17+
18+
// Used for `eval` and `importScripts` where we can't get script URL by other means.
19+
// In both cases, it's safe to use a global var because those functions are synchronous.
20+
let nextDefineUri;
21+
22+
const singleRequire = (uri, parentUri) => {
23+
uri = new URL(uri + ".js", parentUri).href;
24+
return registry[uri] || (
25+
26+
new Promise(resolve => {
27+
if ("document" in self) {
28+
const script = document.createElement("script");
29+
script.src = uri;
30+
script.onload = resolve;
31+
document.head.appendChild(script);
32+
} else {
33+
nextDefineUri = uri;
34+
importScripts(uri);
35+
resolve();
36+
}
37+
})
38+
39+
.then(() => {
40+
let promise = registry[uri];
41+
if (!promise) {
42+
throw new Error(`Module ${uri} didn’t register its module`);
43+
}
44+
return promise;
45+
})
46+
);
47+
};
48+
49+
self.define = (depsNames, factory) => {
50+
const uri = nextDefineUri || ("document" in self ? document.currentScript.src : "") || location.href;
51+
if (registry[uri]) {
52+
// Module is already loading or loaded.
53+
return;
54+
}
55+
let exports = {};
56+
const require = depUri => singleRequire(depUri, uri);
57+
const specialDeps = {
58+
module: { uri },
59+
exports,
60+
require
61+
};
62+
registry[uri] = Promise.all(depsNames.map(
63+
depName => specialDeps[depName] || require(depName)
64+
)).then(deps => {
65+
factory(...deps);
66+
return exports;
67+
});
68+
};
69+
}
70+
define(['./workbox-c6a197bf'], (function (workbox) { 'use strict';
71+
72+
importScripts("/pwa-notifications.js");
73+
self.skipWaiting();
74+
workbox.clientsClaim();
75+
76+
/**
77+
* The precacheAndRoute() method efficiently caches and responds to
78+
* requests for URLs in the manifest.
79+
* See https://goo.gl/S9QRab
80+
*/
81+
workbox.precacheAndRoute([{
82+
"url": "/index.html",
83+
"revision": "0.962ub7l8q8g"
84+
}], {});
85+
workbox.cleanupOutdatedCaches();
86+
workbox.registerRoute(new workbox.NavigationRoute(workbox.createHandlerBoundToURL("/index.html"), {
87+
allowlist: [/^\/$/]
88+
}));
89+
workbox.registerRoute(/\/assets\/.*\.(?:png|jpg|jpeg|svg|gif|webp)$/, new workbox.CacheFirst({
90+
"cacheName": "assets-images",
91+
plugins: [new workbox.ExpirationPlugin({
92+
maxEntries: 200,
93+
maxAgeSeconds: 2592000
94+
})]
95+
}), 'GET');
96+
97+
}));

0 commit comments

Comments
 (0)