用 vite-plugin-pwa 生成 manifest 与 Service Worker,不自己写缓存逻辑。 - 装到桌面:manifest 名字/主题色/三个图标(any + maskable + apple-touch-icon), 图标和页头、安卓桌面是同一枚;首页底部给安装引导,能装就弹「安装」, iOS 给「分享 → 添加到主屏幕」,关掉记在 localStorage - 发版提示:registerType=prompt,收到新版本只在底部提示,点「刷新」才换。 故意不自动刷新——Vditor、图表是懒加载分片,后台换 chunk 会让面板 404 - 缓存边界:只预缓存页面骨架(约 0.8MB),/api/ 一律 NetworkOnly, 离线宁可报错也不端旧数据;/vditor/ 走 CacheFirst,不拖慢首次安装 - 顺手修:UpdatePrompt 居中改用 flex 包一层,animate-slide-up 的 keyframes 自带 transform,会和 -translate-x-1/2 抢属性,手机窄屏会把卡片推出屏幕 验证:web/e2e/pwa.mjs 19 项全绿(manifest/SW 激活/预缓存/安装引导/iOS 文案/ 发版提示/断网仍能打开);tsc 通过、vite build 通过。 已知限制:Service Worker 只在 https 或 localhost 注册,生产入口还是 http, 所以内网 IP 上装不了——需要域名 + 证书反代或隧道,已写进 DEPLOY.md 第 6 节。
This commit is contained in:
+31
-3
@@ -152,7 +152,35 @@ curl -sI http://192.168.8.188:8200/api/v1/app/release/download/dadaotask-0.2.0.a
|
||||
手机端:装上新包 → 下次启动自动查一次;也可以在首页底部点「检查更新」。
|
||||
装完再启动,`version_code` 已是最新,接口返回 `has_update=false`,不会再弹。
|
||||
|
||||
## 6. 运维
|
||||
## 6. Web 装到桌面(PWA)
|
||||
|
||||
前端已经打成 PWA:`/manifest.webmanifest` 与 `/sw.js` 由后端静态层直接返回(`_SPAStaticFiles` 挂在 `/`,
|
||||
不需要额外配置),`node_modules/.bin` 之外没有额外依赖。发布流程不变。
|
||||
|
||||
**装的条件是安全上下文**——浏览器只允许 `https` 或 `localhost` 注册 Service Worker,也就是说:
|
||||
|
||||
| 入口 | 能不能装 |
|
||||
|---|---|
|
||||
| `https://<域名>/` | 能,手机和电脑都会出现安装入口 |
|
||||
| `http://127.0.0.1:8200/`(本机打开) | 能,仅限这台机器 |
|
||||
| `http://192.168.8.188:8200/` | **不能**,非安全上下文:不弹安装、SW 也不注册 |
|
||||
|
||||
内网 IP 目前就是这种情况,所以真要在手机上装到桌面,得给入口套一层 HTTPS:
|
||||
在能装 nginx 的机器上(或 fnsvr-01 的 1Panel OpenResty)加一个 `443 → 127.0.0.1:8200` 的反代就好,
|
||||
应用本身不用改;示例见 `deploy/prod/nginx.dadaotask.conf.example`。也可以用 Cloudflare Tunnel 之类的
|
||||
隧道拿一个 https 域名,同样不用碰应用代码。
|
||||
|
||||
装好之后的两个行为:
|
||||
|
||||
- **图标**:来自 `web/public/icons/`(any + maskable 两套,iOS 吃 `apple-touch-icon.png`),
|
||||
与 Web 页头、安卓桌面图标是同一枚。
|
||||
- **发版提示**:SW 采用 `registerType: "prompt"`,检测到新版本只在页面底部提示「有新版了」,
|
||||
用户点「刷新」才切换。**故意不自动刷新**:Vditor、图表是懒加载分片,后台把 chunk 换掉之后,
|
||||
用户下一次点开面板就是 404(编辑器白屏)。
|
||||
- **离线**:只预缓存页面骨架(构建产物 + 图标,约 0.8MB),`/api/` 一律 NetworkOnly——
|
||||
宁可报错,也不拿旧数据糊弄人。
|
||||
|
||||
## 7. 运维
|
||||
|
||||
```bash
|
||||
systemctl --user status dadaotask-api # 状态
|
||||
@@ -164,11 +192,11 @@ journalctl --user -u dadaotask-api -f # 日志(gunicorn 输出到 stdout
|
||||
- 回滚:`cd ~/app/dadaotask && git reset --hard <旧 commit> && bash deploy/prod/deploy.sh`;**数据库迁移不回滚**,回滚代码前确认旧代码兼容新表结构
|
||||
- 端口:`8200`(systemd 单元与 `deploy.sh` 的 `PORT` 默认值,两处要一致)
|
||||
|
||||
## 7. 已知限制(当前阶段)
|
||||
## 8. 已知限制(当前阶段)
|
||||
|
||||
| 限制 | 影响 | 解除方式 |
|
||||
|---|---|---|
|
||||
| 没有 HTTPS / 域名 | 只能内网 IP 访问,令牌明文传输 | 域名 + nginx + 证书(需 root) |
|
||||
| 没有 HTTPS / 域名 | 只能内网 IP 访问,令牌明文传输;**PWA 装不上**(非安全上下文) | 域名 + nginx + 证书(需 root) |
|
||||
| 内测固定验证码 | 谁都能用任意手机号登录 | 接短信通道,关 `INTERNAL_TEST_LOGIN` |
|
||||
| 无 pgvector | 语义检索走 `real[]` 全表扫描,数据量大了会慢 | 上独立 pgvector 实例(`deploy/docker-compose.vector.yml`) |
|
||||
| 上传目录在本机磁盘 | 机器坏了附件就没了 | 备份 `backend/var/uploads`,或将来到对象存储 |
|
||||
|
||||
@@ -501,3 +501,43 @@
|
||||
### 7.6 没做的
|
||||
- 安卓端登录页仍只有验证码,账号页也没有——下一步对齐(密码登录 + 改昵称 + 退出)
|
||||
- 手机号换绑、头像上传未做(头像现在只有首字母)
|
||||
|
||||
## 8. Web 装到桌面(PWA,2026-10-31)
|
||||
|
||||
### 8.1 要解决的问题
|
||||
"web版本帮我封装成PWA,这样方便安装到手机桌面和电脑桌面。"(用户原话)
|
||||
|
||||
现在每次用都要敲地址、开浏览器、找标签页;手机上还给不了"点了图标就进来"的感觉。
|
||||
|
||||
### 8.2 决定(写进注释了,别以后翻案)
|
||||
- 用 `vite-plugin-pwa`(本就在 devDependencies 里,2.0.0)生成 SW 与 manifest,不自己写
|
||||
- `registerType: "prompt"` + `injectRegister: null`:**有新版只提示,点「刷新」才换**。
|
||||
理由:Vditor、图表是懒加载分片,`autoUpdate` 会在用户开着页面时把 chunk 换掉,
|
||||
下一次点开面板就是 404(编辑器白屏)
|
||||
- 预缓存只放构建产物与图标(约 0.8MB);`/api/` 一律 NetworkOnly——离线宁可报错,也不端旧数据
|
||||
- 图标复用 Web Logo 的 32 单位坐标生成,和页头、安卓桌面图标同一枚
|
||||
|
||||
### 8.3 实现
|
||||
| 位置 | 内容 |
|
||||
|---|---|
|
||||
| `web/vite.config.ts` | manifest(standalone、主题色 `#2f6054`、三个图标)+ workbox(`navigateFallback` 回退 `index.html`,`/vditor/` 走 CacheFirst,`/api/` NetworkOnly) |
|
||||
| `web/index.html` | favicon 改成同款 Logo(内联 SVG)、`theme-color`、`apple-touch-icon`、`viewport-fit=cover` |
|
||||
| `web/src/lib/pwa.ts` | 生产环境注册 SW、`dadao:pwa-update-ready` 事件、`applyServiceWorkerUpdate()`、`isStandalone()` |
|
||||
| `web/src/components/UpdatePrompt.tsx` | 底部卡片「有新版了」+ 稍后 / 刷新(**居中用 flex 包一层**:`animate-slide-up` 的 keyframes 自带 transform,会和 `-translate-x-1/2` 抢属性,手机窄屏上卡片会被推出屏幕右侧) |
|
||||
| `web/src/components/InstallHint.tsx` | 首页底部安装引导:能装就给「安装」按钮(拦 `beforeinstallprompt`),iOS 给"分享 → 添加到主屏幕",关掉记在 localStorage |
|
||||
| `web/public/icons/` | `icon-192` / `icon-512`(any)、`maskable-512`、`apple-touch-icon`(180,iOS 不吃透明) |
|
||||
|
||||
### 8.4 验证
|
||||
- `web/e2e/pwa.mjs`(**19 项全绿**):manifest 名字/standalone/三个图标 → 图标都能下载 200 →
|
||||
SW 已 `activated` 且作用域是整站 → 页面骨架已进预缓存 → 主题色 → 桌面尺寸控制台零报错 →
|
||||
窄屏有安装引导 → iOS 文案是「分享 → 添加到主屏幕」→ 关掉后刷新不再出现 →
|
||||
有新版会提示 → 点「稍后」收起 → **断网后页面骨架仍能打开**
|
||||
- 跑法:后端用 `WEB_DIST_DIR=<repo>/web/dist` 起一个同构站点(生产同形),
|
||||
然后 `node web/e2e/pwa.mjs`;`BASE` 可换环境
|
||||
- 截图:`web/e2e/artifacts/pwa-install-hint.png`、`pwa-update-prompt.png`、`pwa-offline.png`
|
||||
|
||||
### 8.5 还没解开的
|
||||
- **生产入口还是 http**:Service Worker 只在 https / localhost 注册,所以内网 IP 上装不了、
|
||||
也看不到安装提示(桌面用 `127.0.0.1` 打开可以)。要么加域名 + 证书反代(`443 → 127.0.0.1:8200`),
|
||||
要么用 Cloudflare Tunnel 之类拿个 https 域名;应用代码不用改。已写进 `DEPLOY.md` 第 6 节
|
||||
- 安卓端还在走自己的 OTA(原生包),和 PWA 是两条路;要不要让安卓也改成加载 Web,等产品定
|
||||
|
||||
Reference in New Issue
Block a user