docs/prds/settings/about/about-update.md
本文档覆盖「设置 → 关于」页面的全部功能,包括应用信息展示、版本更新(检查/下载/安装)、外部链接导航、问题报告。 基于静态代码分析和动态 UI 验证综合整理,经 DA 质疑和 Tester 反馈修正定稿。
用户故事:作为用户,我希望在关于页面看到当前应用的名称、描述和版本号,以便了解我正在使用的版本。
正常流程(用户视角):
v{x.y.z}),版本号来自打包时的 package.jsonhttps://github.com/iOfficeAI/AionUi异常情况:
package.json,理论上不为空;若异常为空则显示 v验收标准:
v{x.y.z},与 package.json 一致用户故事:作为桌面端用户,我希望有一个明确的"检查更新"按钮,以便我主动查看是否有新版本可用。
前置条件:运行在 Electron 桌面端
正常流程(用户视角):
异常情况:
验收标准:
其他触发方式(应用菜单、启动时自动检查)见 F-ABOUT-12
用户故事:作为用户,我希望可以选择是否接收预发布(beta/dev)版本的更新通知,以便提前体验新功能或保持稳定版。
前置条件:运行在 Electron 桌面端
正常流程(用户视角):
技术说明:
localStorage('update.includePrerelease')useMemo 从 localStorage 读取该值。弹窗已打开状态下修改开关不会立即生效,需关闭后重新打开异常情况:
验收标准:
建议验证策略:双路径 fallback 逻辑通过单元测试验证;E2E 仅验证 checking → upToDate 流程
用户故事:作为用户,我希望系统能可靠地检查是否有新版本,即使某种检查方式失败也能通过备用方式完成。
正常流程(用户视角):
内部机制 — 双路径检查:
系统使用两种方式检查更新,串行执行(路径 A 先于路径 B),路径 B 始终执行:
| 路径 | 方式 | 用途 | 执行条件 |
|---|---|---|---|
| A. Auto-update | electron-updater(查询 GitHub Release yml) | 支持应用内自动下载安装 | 先执行,失败静默跳过 |
| B. Manual check | GitHub REST API GET /repos/{owner}/{repo}/releases | 获取版本信息、release notes、下载资产 | 始终执行 |
版本比较:使用 semver 语义化版本比较(semver.gt),当前版本来自 app.getVersion()。
异常情况:
验收标准:
app.getVersion() 返回非法 semver 时,显示"已是最新版本"而非错误建议验证策略:通过 React Testing Library 或 Storybook stories 覆盖 available 状态的 UI 渲染
用户故事:作为用户,当有新版本可用时,我希望看到版本号对比和更新日志,并可以一键下载/安装。
正常流程(用户视角):
当前版本 → 新版本(新版本号高亮)平台资产自动匹配:
系统根据当前平台和架构自动选择最佳安装包:
.exe, .msi, .dmg, .zip, .deb, .rpm(扩展名之外的 asset 如 .tar.gz 在评分前被过滤)异常情况:
验收标准:
建议验证策略:通过集成测试(mock autoUpdater 事件)覆盖 UI 状态切换;quitAndInstall 通过手动测试
用户故事:作为用户,我希望点击"下载并安装"后系统自动完成下载,并在准备就绪时提示我一键安装。
前置条件:electron-updater 确认有更新可用(auto-update 路径)
正常流程(用户视角):
平台差异:
quitAndInstall 后 1 秒强制 app.exit(0),因为 macOS 的 close-to-tray 行为会阻止 Squirrel 完成安装quitAndInstall 流程平台 Channel 映射(electron-updater 根据平台+架构选择对应 yml):
| 平台 + 架构 | Channel 文件 |
|---|---|
| macOS arm64 | latest-arm64-mac.yml |
| macOS x64 | latest-mac.yml |
| Windows arm64 | latest-win-arm64.yml |
| Windows x64 | latest.yml |
| Linux x64 | latest-linux.yml |
| Linux arm64 | latest-linux-arm64.yml |
异常情况:
验收标准:
建议验证策略:安全机制(URL 白名单、HTTPS、重定向限制)通过单元测试覆盖;下载流程通过集成测试
用户故事:作为用户,当自动安装更新不可用时,我希望系统能下载安装包到本地,我手动完成安装。
前置条件:auto-update 路径不可用,但有兼容的 GitHub Release 安装包
正常流程(用户视角):
安全机制:
github.com, objects.githubusercontent.com, github-releases.githubusercontent.com, release-assets.githubusercontent.com下载位置:系统"下载"目录(app.getPath('downloads'))
异常情况:
验收标准:
建议验证策略:通过 React Testing Library 渲染 error 状态验证 UI;错误码覆盖通过单元测试
用户故事:作为用户,当更新检查或下载失败时,我希望看到有意义的错误信息,并能重试或通过备选方式获取更新。
正常流程(用户视角):
错误类型汇总:
| 阶段 | 错误场景 | 用户可见信息 |
|---|---|---|
| 检查 | GitHub API 网络超时(30s) | 超时错误提示 |
| 检查 | GitHub API HTTP 错误 | API 错误 + 状态码 |
| 检查 | API 返回格式异常 | 格式错误提示 |
| 下载 | URL 不在允许列表 | 域名不允许 |
| 下载 | 非 HTTPS 协议 | 仅支持 HTTPS |
| 下载 | 重定向次数过多 | 重定向错误 |
| 下载 | 服务器返回错误 | 下载失败 + 状态码 |
| 下载 | 网络中断/取消 | 下载失败/已取消 |
| 安装 | quitAndInstall 失败 | Toast 提示(不影响弹窗) |
验收标准:
用户故事:作为用户,我希望更新弹窗在每个阶段都有清晰的视觉反馈,让我知道当前进展。
状态流转:
[打开弹窗]
│
▼
checking ──────────────┬──────────────┐
│ │ │
▼ ▼ ▼
upToDate available error ←─── [重试]
│ ▲
▼ │
downloading ────────┘
│ │
▼ ▼
downloaded success
│ │
▼ ▼
[安装退出] [打开文件]
各状态 UI 表现:
| 状态 | 图标 | 弹窗尺寸 | 主要内容 |
|---|---|---|---|
| checking | 旋转动画 | small | "正在检查更新..." |
| upToDate | 绿色对勾 | small | "已是最新版本" + 当前版本号 |
| available | 蓝色下载 | medium, 内容高度 420px | 版本对比 + release notes + 操作按钮 |
| downloading | 弹跳下载 | small | 进度条 + 速度 + 大小 |
| downloaded | 绿色对勾 | small | "准备安装" + 安装按钮(auto-update 路径) |
| success | 绿色对勾 | small | 下载路径 + 打开/显示按钮(manual 路径) |
| error | 红色叉号 | small | 错误信息 + 重试 + 前往 Release |
关键区分:
downloaded:auto-update 路径专用,用户点击"立即安装"后应用退出并安装success:manual 路径专用,用户点击"打开文件"或"在文件夹中显示"后手动安装已知局限:
验收标准:
用户故事:作为用户,我希望在关于页面快速访问帮助文档、更新日志、反馈渠道等外部资源。
正常流程(用户视角):
链接列表:
| 序号 | 标题 | 行为 | 目标 |
|---|---|---|---|
| 1 | 帮助文档 | 打开外部链接 | https://github.com/iOfficeAI/AionUi/wiki |
| 2 | 更新日志 | 打开外部链接 | https://github.com/iOfficeAI/AionUi/releases |
| 3 | 意见反馈 | 打开外部链接 | https://github.com/iOfficeAI/AionUi/issues |
| 4 | 问题报告 | 打开应用内弹窗 | FeedbackReportModal(见 F-ABOUT-11) |
| 5 | 联系我 | 打开外部链接 | https://x.com/WailiVery |
| 6 | 官网 | 打开外部链接 | https://www.aionui.com |
打开机制:
shell.openExternal,在系统默认浏览器中打开window.open(url, '_blank', 'noopener,noreferrer') 打开已知问题:
异常情况:
验收标准:
用户故事:作为用户,我希望可以直接在应用内提交问题报告,附带截图和描述,无需离开应用去 GitHub Issues。
正常流程(用户视角):
反馈模块列表(15 个):
| 模块名称 | Sentry Tag |
|---|---|
| Agent 检测与连接 | agent-detection |
| 助手与预设 | assistant-preset |
| 模型与认证 | model-auth |
| MCP 与工具 | mcp-tools |
| 技能与插件 | skills-plugin |
| 频道接入 | channel |
| 对话与会话 | conversation-session |
| 搜索与历史 | search-history |
| 工作区、文件与预览 | workspace-preview |
| WebUI 与远程连接 | webui-remote |
| 定时任务 | scheduled-task |
| 团队协作 | agent-team |
| 显示与桌宠 | display-desktop |
| 系统设置 | system-settings |
| 其他 | other |
异常情况:
electronAPI 不存在(WebUI 环境):跳过日志收集,仍可提交pasted-screenshot-{timestamp}-{index}.{ext}验收标准:
建议验证策略:通过集成测试(mock autoUpdater 事件)验证;E2E 无法覆盖
用户故事:作为用户,我希望除了关于页面按钮外,还能通过应用菜单触发检查更新;同时希望应用启动时自动检查是否有新版本。
触发方式汇总:
| 触发方式 | 机制 | 备注 |
|---|---|---|
| 关于页面按钮 | 渲染进程 CustomEvent | 见 F-ABOUT-02 |
| 应用菜单 | IPC ipcBridge.update.open.emit({ source: 'menu' }) | 主进程 → 渲染进程 |
| 启动时自动检查 | autoUpdater.checkForUpdatesAndNotify() | 非阻塞,不影响启动 |
启动时自动检查:
allowDowngrade = false,防止前次预发布设置残留异常情况:
available 事件可能在手动检查的 checking 状态中到达,导致显示不完整信息(已知局限)验收标准:
┌─────────────────────────────────────────────────────────┐
│ 渲染进程 (Renderer) │
│ │
│ AboutModalContent │
│ ├─ CustomEvent('aionui-open-update-modal') │
│ └─ localStorage('update.includePrerelease') │
│ │
│ UpdateModal │
│ ├─ ipcBridge.autoUpdate.check.invoke() → 检查(auto) │
│ ├─ ipcBridge.update.check.invoke() → 检查(manual)│
│ ├─ ipcBridge.autoUpdate.download.invoke()→ 下载(auto) │
│ ├─ ipcBridge.update.download.invoke() → 下载(manual)│
│ ├─ ipcBridge.autoUpdate.quitAndInstall.invoke() → 安装│
│ ├─ ipcBridge.autoUpdate.status.on() ← 状态事件 │
│ └─ ipcBridge.update.downloadProgress.on()← 下载进度 │
│ │
│ FeedbackReportModal │
│ ├─ electronAPI.collectFeedbackLogs() → 收集日志 │
│ └─ Sentry.captureEvent() → 提交反馈 │
└────────────────────┬────────────────────────────────────┘
│ IPC Bridge
┌────────────────────▼────────────────────────────────────┐
│ 主进程 (Main) │
│ │
│ updateBridge.ts │
│ ├─ update.check.provider → GitHub REST API │
│ ├─ update.download.provider → allowlisted download │
│ ├─ autoUpdate.check.provider → autoUpdaterService │
│ ├─ autoUpdate.download.provider → autoUpdaterService │
│ └─ autoUpdate.quitAndInstall.provider → quit+install │
│ │
│ autoUpdaterService.ts (Singleton) │
│ └─ electron-updater → broadcastStatus → IPC emit │
└────────────────────┬────────────────────────────────────┘
│
┌────────────────────▼────────────────────────────────────┐
│ 外部服务 │
│ ├─ GitHub REST API (releases 列表) │
│ ├─ GitHub Release Assets (安装包下载) │
│ ├─ electron-updater yml (latest*.yml) │
│ └─ Sentry (反馈事件) │
└─────────────────────────────────────────────────────────┘
| # | 功能点 | 局限描述 |
|---|---|---|
| 1 | F-ABOUT-03 | 弹窗已打开时修改预发布开关不会立即生效(useMemo 缓存) |
| 2 | F-ABOUT-04 | 当前版本非法 semver 时静默返回"已是最新",可能隐藏真实更新 |
| 3 | F-ABOUT-04 | 双路径串行执行,路径 A 超时会导致总耗时超过 60 秒 |
| 4 | F-ABOUT-06/07 | 下载中关闭弹窗无取消机制,重开后进度丢失 |
| 5 | F-ABOUT-07 | 服务器未返回 Content-Length 时进度条显示 0% |
| 6 | F-ABOUT-10 | "问题报告"与外部链接视觉无差异;链接打开失败无用户提示 |
| 7 | F-ABOUT-11 | 截图无文件大小限制,超大文件可能导致内存压力或 Sentry 拒绝 |
| 8 | F-ABOUT-12 | 启动自动检查与手动检查并发时事件可能互相干扰 |