# 自动升级系统 — 实现规格 > 来源:需求探索会话 2026-05-28 > 状态:待开发 --- ## 1. 架构总览 ``` ┌──────────────┐ │ 远程版本 JSON │ ← 静态文件,放 CDN / OSS │ version.json │ └──────┬───────┘ │ HTTP GET ▼ ┌──────────────────┐ │ u-desktop.exe │ ← 主程序 │ · 启动时检查版本 │ │ · 弹窗提示升级 │ │ · 释放 updater │ └──────┬───────────┘ │ 启动进程 ▼ ┌──────────────────┐ │ updater.exe │ ← 通用升级器,参数化驱动 │ · 下载安装包 │ │ · SHA256 校验 │ │ · 备份旧版本 │ │ · 替换 + 启动 │ │ · 失败自动回滚 │ └──────────────────┘ ``` --- ## 2. 主程序改动 ### 2.1 版本号注入 `main.go` 增加版本变量,编译时注入: ```go var version = "dev" // -ldflags "-X main.version=0.6.0" ``` `build` 脚本 / publish 技能同步更新 ldflags。 ### 2.2 版本检查模块 新增 `updater.go`: ``` func checkUpdate() (*UpdateInfo, error) ``` - 启动时异步调用(不阻塞主流程) - 请求远程 `version.json` - 对比当前 version,返回更新信息或 nil 远程 version.json 格式: ```json { "version": "0.7.0", "force": false, "release_notes": "· 新增视频壁纸\n· 修复全屏检测偶发失效", "package": { "url": "https://c.1216.top/u-desktop/u-desktop-0.7.0.zip", "size": 8388608, "sha256": "abc123def456..." } } ``` version.json URL 存入 config 或硬编码默认值。 ### 2.3 升级弹窗 用 WebView2 新建一个无边框小窗口,HTML 渲染弹窗内容。 #### 弹窗策略 | force 字段 | 位置 | 按钮 | |-----------|------|------| | `false` | 右下角,托盘图标上方 | [稍后] [立即升级] | | `true` | 屏幕居中 | [立即升级](仅一个按钮) | #### 弹窗 HTML 结构 右下角气泡(非强制): ``` ┌─────────────────────────────┐ │ 发现新版本 v0.7.0 │ │ │ │ · 新增视频壁纸 │ │ · 修复全屏检测偶发失效 │ │ │ │ [稍后] [立即升级] │ └─────────────────────────────┘ ``` 居中弹窗(强制): ``` ┌─────────────────────────────────────┐ │ │ │ 发现新版本 v0.7.0 │ │ │ │ · 新增视频壁纸 │ │ · 修复全屏检测偶发失效 │ │ │ │ 大小: 8MB | 预计用时: ~10秒 │ │ │ │ [立即升级] │ └─────────────────────────────────────┘ ``` #### 弹窗窗口参数 | 参数 | 右下角 | 居中 | |------|--------|------| | 宽度 | 340px | 420px | | 高度 | auto(内容自适应) | auto | | 位置 | 屏幕右下角 - 边距 20px | 屏幕居中 | | 样式 | 无边框,圆角,毛玻璃 | 无边框,圆角,毛玻璃 | | 置顶 | TOPMOST | TOPMOST | ### 2.4 用户点击"立即升级" 1. 从自身嵌入资源释放 `updater.exe` 到临时目录(或主程序同级目录) 2. 构造命令行参数启动 updater.exe 3. 主程序退出 ```go exec.Command(tmpUpdaterPath, "--package-url", info.Package.URL, "--sha256", info.Package.SHA256, "--target", selfExePath, "--version", info.Version, "--force", strconv.FormatBool(info.Force), ).Start() // 主程序退出 ``` ### 2.5 托盘菜单 新增菜单项:"检查更新",手动触发版本检查。 --- ## 3. updater.exe ### 3.1 职责 通用升级器,不含业务逻辑,纯参数驱动。可复用于其他产品(u-tabs 等)。 ### 3.2 命令行参数 ```bash updater.exe \ --package-url <下载地址> \ --sha256 \ --target <目标exe路径> \ --version <目标版本号> \ --force \ --backup-dir <备份目录,默认 target 同级 backup/> ``` ### 3.3 流程 ``` 1. 显示进度窗口(WebView2 或控制台) 2. HTTP GET 下载 package-url → 临时文件 - 显示下载进度(已下载/总大小) - 支持断点续传(可选,初期不做) 3. 计算下载文件 SHA256,与参数比对 - 不匹配 → 报错退出 4. 备份当前 target → backup-dir/old-{timestamp}.exe 5. 如果是 zip 包:解压后替换 如果是 exe:直接覆盖 6. 启动新版本 target 7. updater 退出 异常处理: - 下载失败 → 重试 3 次,间隔 5s - 校验失败 → 报错,不替换 - 启动新版本后监听 5s,新进程退出则回滚 - 回滚:将 backup 中的旧 exe 还原 ``` ### 3.4 进度显示 初期:无 UI,日志写 `updater.log`(`-H windowsgui` 隐藏控制台)。 后续:可加 WebView2 进度窗口。 ### 3.5 日志 写入 `updater.log`(与 target 同目录),包含时间戳、步骤、错误信息。 --- ## 4. 构建 & 发布流程 ### 4.1 主程序构建 ```bash go build -ldflags "-H windowsgui -X main.version=0.7.0" -o u-desktop.exe ``` ### 4.2 updater 构建 独立 main 包,单独目录(如 `updater/`): ```bash cd updater && go build -ldflags "-H windowsgui" -o updater.exe ``` ### 4.3 发布 1. 构建 `u-desktop.exe` + `updater.exe` 2. UPX 压缩(可选) 3. 计算 SHA256 4. 上传到 `c.1216.top` 5. 更新远程 `version.json` 6. 更新 publish 技能(自动生成 version.json + 上传) --- ## 5. 配置 `config.go` 新增字段: ```go type Config struct { // ... 现有字段 UpdateURL string `json:"update_url"` // 版本检查 URL,默认 https://c.1216.top/u-desktop/version.json AutoCheckUpdate bool `json:"auto_check_update"` // 启动时自动检查,默认 true SkipVersion string `json:"skip_version"` // 用户跳过的版本号 } ``` --- ## 6. 目录结构 ``` u-desktop/ ├── main.go # 增加版本变量 ├── updater.go # 新增:版本检查 + 弹窗逻辑 ├── config.go # 增加 update 相关字段 ├── systray.go # 托盘菜单增加"检查更新" ├── web/ │ ├── update.html # 新增:升级弹窗 HTML │ └── ... ├── updater/ # 新增:升级器独立目录 │ └── main.go ├── docs/ │ ├── feature-roadmap.md │ └── auto-update-spec.md # 本文档 └── ... ``` --- ## 7. 实施顺序 | 步骤 | 内容 | 依赖 | |------|------|------| | 1 | `main.go` 加版本变量,构建脚本加 ldflags | 无 | | 2 | `updater.go` 版本检查函数 + config 字段 | 步骤 1 | | 3 | 远程 `version.json` 手动创建 + 上传 | 步骤 2 | | 4 | 升级弹窗 `update.html` + Go 端窗口创建 | 步骤 2 | | 5 | 主程序释放 + 启动 updater.exe | 步骤 4 | | 6 | `updater/` 目录,下载 + 校验 + 替换 + 回滚 | 步骤 5 | | 7 | 托盘菜单"检查更新" | 步骤 2 | | 8 | publish 技能集成 version.json 生成 | 步骤 3 |