feat: 重构更新流程 — 无更新不抛异常、用户决定下载、更新详情展示(md文件中的)

【核心重构】
  - getLatestVersion() 不再 throw Error,无更新时返回 { version: APP_VERSION }
  - checkForUpdates() 先自行预检 → 无更新直发 IPC,有更新才交 electron-updater
  - 移除 NO_UPDATE_MESSAGE 常量及所有字符串匹配拦截代码
  - HeiXiuProvider 增加 500ms TTL 缓存,避免预检+electron-updater 重复请求 API

  【用户体验】
  - 检查到新版本后不再自动下载,展示更新内容供用户决定
  - 新增"下载更新"按钮(与"安装更新"分离为两步操作)
  - 设置页新增"查看详情"弹窗,Markdown 格式化渲染更新日志
  - available / downloading / downloaded 三个状态 UI 独立展示

  【Bug 修复】
  - 测试服务器版本排序:字符串序 → 语义版本序(_version_key),0.0.10 正确 > 0.0.9
  - 版本比较:!= → <(_version_key),防止高版本误判为有更新
  - get_best_release fallback 同样改为语义版本排序
  - Windows cmd set 命令尾部空格 → Invalid URL(.trim() 修复)
  - electron-updater 'error' 事件中拦截 NO_UPDATE_MESSAGE → UPDATE_NOT_AVAILABLE

  【文档更新】
  - CHANGELOG.md、PROJECT.md、UpdateA.md 同步更新架构图和流程说明
This commit is contained in:
2026-06-04 18:31:52 +08:00
parent b55c2fdd2e
commit 6204c14b88
37 changed files with 1908 additions and 648 deletions

View File

@@ -205,6 +205,71 @@
- 类型检查npm run typechecktsc --noEmit
# 自动更新系统
## 架构
```
客户端 (Electron 主进程)
checkForUpdates()
├─ ① HeiXiuProvider.getLatestVersion() → 调用自有版本检查 API
│ └─ hasUpdate=false → 直接 IPC 通知 UI不经过 electron-updater
└─ ② hasUpdate=true → electron-updater.checkForUpdates()
├─ HeiXiuProvider.getLatestVersion() → TTL 缓存命中,不重复请求
├─ emit 'update-available'(含 releaseNotes→ UI 展示版本信息
└─ 用户点击"下载更新" → downloadUpdate()
├─ 差分下载(对比 .blockmap仅下载变更区块
├─ SHA512 校验
└─ 下载完成 → 用户点击"安装更新" → NSIS/DMG/AppImage 执行
```
| 模块 | 位置 | 职责 |
|------|------|------|
| `HeiXiuProvider` | `electron/main/updater.ts` | 自定义 Provider调用自有 API无更新返回 APP_VERSION |
| `checkForUpdates` | `electron/main/updater.ts` | 预检版本 → 无更新直发 IPC / 有更新交 electron-updater |
| `downloadUpdate` | `electron/main/updater.ts` | 用户确认后触发下载(从 checkForUpdates 分离) |
| `netRequest` | `electron/main/net-request.ts` | Electron net.request 的 axios 风格封装 |
| `useUpdater` | `src/hooks/use-updater.ts` | 渲染进程更新状态 Hook单例 IPC 监听) |
| `UpdateSetting` | `src/pages/settings/UpdateSetting.tsx` | 设置页更新区块(含"查看详情"弹窗) |
| `server.py` | `test-server/server.py` | 本地测试服务器,扫描 release/ 目录,语义版本排序 |
## 环境变量加载机制(主进程)
加载顺序后者覆盖前者OS 环境变量始终优先):
```
① OS 环境变量set KEY=VALUE && .\app.exe ← 最高优先级
② .env.local不进 git个人覆盖用
③ .env.{mode}dev→.env.developmentbuild→.env.production
④ updater.ts 硬编码默认值https://www.heixiu.com
```
| 文件 | 何时生效 | 进 git | 用途 |
|------|---------|:------:|------|
| `.env.development` | `npm run dev` | ✅ | 本地开发API → 测试服务器) |
| `.env.production` | `npm run build:xxx` | ❌ | 构建时参考API → 生产服务器) |
| `.env.local` | 始终(后加载) | ❌ | 个人特殊配置(打包后连本地测试) |
> `.env.production` 和 `.env.local` 不打包进 ASAR。打包后无这些文件时自动使用代码默认值。
## 测试工作流
```powershell
# 1. 构建两个版本
npm run build:win # → release/0.0.3/
# 改 package.json version = "0.0.4"
npm run build:win # → release/0.0.4/
# 2. 启动测试服务器
cd test-server && python server.py --release-dir ../release --port 8000
# 3. 启动旧版本客户端
set UPDATE_API_URL=http://127.0.0.1:8000 && .\release\0.0.3\win-unpacked\船长·HeiXiu.exe
# → 5 秒后自动检测到 0.0.4 → 差分下载 → 提示安装
```
相关文档:[UpdateA.md](UpdateA.md)、[test-server/README.md](test-server/README.md)
# 与其他 AI 协作的补充说明
- 所有生成的代码片段必须放在完整的文件上下文中,并注明所属文件路径。