Skip to content

应用更新与统计方案

状态:Phase 0 已实现(版本检测 / 下载安装 / 启动静默检查),统计与官网/后台为后续规划。 相关代码:src/services/update.service.tssrc/pages/update/index.vuesrc/constants/app.tssrc/types/update.tssrc/static/version.json

1. 背景与约束

爱生活是离线优先、隐私至上的应用(App Store 隐私标签声明"不收集任何数据"),目前:

  • 无官网、无后台管理系统、无应用商店上架渠道
  • H5 静态部署,Android 侧载 APK,iOS 待 TestFlight/App Store
  • 同步引擎已有可插拔 Provider(WebDAV / GitHub Gist),为后续扩展提供参考模式

因此升级与统计方案遵循两条原则:

  1. 零后端起步:版本清单就是一个静态 JSON,托管在任何静态服务器上,不需要自建后台
  2. 统计默认关闭、匿名化、可透明查看:不违背产品隐私承诺

2. 升级方案(已实现:Phase 0)

2.1 核心:静态版本清单 version.json

所有平台共用一份清单(结构见 src/types/update.ts):

json
{
  "versionName": "1.1.0",
  "versionCode": 101,
  "minVersionCode": 100,
  "releaseDate": "2026-08-20",
  "changelog": ["新增:xxx", "修复:yyy"],
  "rollout": 100,
  "platforms": {
    "android": { "url": "https://…/ai-life-os-1.1.0.apk", "sha256": "…", "size": 26843545 },
    "wgt":     { "url": "https://…/app.wgt", "sha256": "…", "size": 1048576 },
    "h5":      { "url": "" }
  }
}

字段说明:

字段说明
versionCodemanifest.json 的 versionCode 对应,比较以此为准
minVersionCode低于此版本的安装 → 强制更新(全局弹窗不可"稍后再说",必须升级)
rollout灰度比例 0-100;按设备稳定 ID 的 FNV-1a 哈希决定是否可见
platforms.androidAndroid 整包 APK(优先)
platforms.wgtwgt 资源包热更新(Android/iOS 通用,仅更 JS/页面)
platforms.h5H5 更新项:有 url 跳转新地址,否则原地刷新

2.2 分平台更新策略

平台更新方式说明
Android整包 APK 下载安装(platforms.android 优先)plus.downloader 带进度下载 → 大小校验(HTTPS + 下载字节数;设备端分块 SHA-256 在部分 webview 不可靠故省略,sha256 保留供发布端审计)→ plus.runtime.install({force:true})。Android 8+ 需在 HBuilderX 云打包配置 REQUEST_INSTALL_PACKAGES 权限
Android/iOSwgt 热更新(platforms.wgt紧急修复/小版本,安装后延迟 2.5s 自动重启(先关闭 SQLite 原生连接)。iOS 上 wgt 属灰色地带(Apple 禁止下载代码),仅限小修小补
H5重新部署 + 刷新/跳转Vite 构建产物带 hash,index.html 不缓存 + assets/ 长期缓存即可
iOS 正式版TestFlight / App Store无自建整包分发渠道(法律与可行性限制)
微信小程序微信发布体系不参与自更新

2.3 检查流程(src/services/update.service.ts)

解锁/手动触发 → getLocalVersion()(App 用 plus.runtime.getProperty 真实版本,其余用构建期注入常量)
→ fetchManifest()(地址优先级:VITE_UPDATE_MANIFEST_URL > App 内置默认公开仓库(HBuilderX 打包无需配置)> H5 同源 /static/version.json)
→ evaluateManifest():
    ① versionCode 比较(低于/等于本地 → 已是最新)
    ② rollout 灰度(hash(deviceId) % 100 >= rollout → 不提示)
    ③ 平台目标(android > wgt > h5;小程序不参与)
    ④ minVersionCode → 是否强制
→ 有更新:全局弹窗(`src/components/common/UpdatePrompt.vue`,挂在 Layout 上)
  展示 changelog + 下载进度,任何页面直接弹出,不跳转

触发入口

  • 解锁后自动检查src/App.vue 监听 appLocked 由 true→false(解锁完成),延迟 1.2s 后调用 useUpdateStore().check();同一会话「稍后再说」后不再自动弹出
  • 手动检查:设置页 → 检查更新(src/pages/update/index.vue),调用 store.check(true) 强制弹窗
  • 安装完成后:wgt 延迟 2.5s 自动重启(等待资源落盘,避免立即重启导致运行时损坏),重启前 closeNativeDatabase() 关闭 SQLite 原生连接(软重启不释放原生句柄,不关库会导致重启后数据读取失败)

2.4 版本注入

  • vite.config.ts 构建期读取版本,define 注入 __APP_VERSION__ / __APP_VERSION_CODE__
  • 版本来源优先级:src/manifest.json(HBuilderX 打包口径)> package.json(兜底)
  • src/constants/app.ts 消费注入值(测试环境回退 1.0.0/100)
  • 页面显示版本统一取运行时getLocalVersion() → plus.runtime):关于页、检查更新页一致,wgt 更新后保持正确

2.5 发版流程(发布者操作)

📖 完整操作手册见 docs/release-guide.md(含回滚方案、验收清单、踩坑记录)。

推荐架构:源码私有 + 发布公开双仓库

  • 源码仓库 lutlelk/ai-life-os 保持私有,不对外
  • 另建一个公开仓库(如 lutlelk/ai-life-os-release)只放发布产物:
    • Release 附件(APK / wgt)→ 公开仓库附件可匿名下载(私有仓库会 403)
    • 仓库根目录的 version.json → App 端通过 raw 链接读取(无需鉴权)
  • App 端无需配置环境变量:内置默认指向该公开仓库(HBuilderX 云打包不带 .env,代码内兜底;CLI 构建可用 VITE_UPDATE_MANIFEST_URL 覆盖为自建服务器)
  • H5 端沿用同源 /static/version.json(跟随 H5 部署)

方式一:脚本一键发布(推荐)scripts/release-gitee.mjs

bash
# 构建产物后,一条命令完成:建 Release + 传附件 + 回写本地清单 + 推送远端清单
GITEE_TOKEN=你的令牌 node scripts/release-gitee.mjs \
  --release-repo lutlelk/ai-life-os-release \
  --files dist/build/app/android-release.apk dist/build/app/app.wgt \
  --changelog "新增:xxx" \
  --update-manifest src/static/version.json \
  --push-manifest
  • --release-repo:公开发布仓库(缺省=源码仓库);源码仓库仅用于读版本号,不写入任何内容
  • --push-manifest:把 version.json 通过 contents API 提交到发布仓库根目录,脚本最后会打印建议的 VITE_UPDATE_MANIFEST_URL
  • 仓库地址自动从 package.json 解析,tag 默认 v{version};发布仓库为私有时会红字警告
  • Gitee 私人令牌:头像 → 设置 → 安全设置 → 私人令牌(勾选 releases 权限),只在生成时显示一次
  • 完整用法见脚本头部注释

方式二:网页手动上传

  1. 仓库页 → 右侧「发行版」→「新建发行版」
  2. 填标签(v1.1.0)、标题、更新说明(Markdown,即 changelog)
  3. 「添加附件」上传 APK / wgt → 发布
  4. 进入发行版页,复制附件下载链接(Gitee 格式为 https://gitee.com/{owner}/{repo}/attach_files/{id}/download/{文件名}每次上传链接都会变
  5. 把链接填进 version.jsonplatforms.android.url / platforms.wgt.url(sha256 可用 shasum -a 256 文件 生成)

手动发版清单(两种方式通用)

① 改 manifest.json(versionCode+1、versionName)与 package.json(version)
② 构建:
   - H5:npm run build:h5 → 部署 dist/build/h5(version.json 跟随 H5 同源部署)
   - Android:npm run build:app-android → 签名 APK
   - wgt:HBuilderX「发行 → 制作应用资源升级包」
③ 上传 APK / wgt 到 Gitee Releases(脚本或网页)
④ 更新 version.json(versionCode、changelog、下载地址、sha256、size、rollout)
⑤ git tag vx.y.z && push

CORS / 可见性注意事项

  • Gitee 附件与 raw 文件不带 CORS 头 —— App 原生下载/请求不受影响,但 H5 浏览器不能直接 fetch gitee.com 的文件 → version.json 的 H5 读取走同源 /static/version.json(跟随 H5 部署)
  • 私有仓库的 Release 附件无法匿名下载(403) → 发布仓库必须设为公开(源码仓库可保持私有)
  • 建议 version.json 的 HTTP 缓存 TTL 设短(如 60s)或 no-cache,保证检查即时生效。

2.6 环境变量

bash
# .env.production(仅自建服务器/其它托管时需要;App 有内置默认,可省略)
# VITE_UPDATE_MANIFEST_URL=https://your-host/version.json

地址优先级:VITE_UPDATE_MANIFEST_URL > App 内置默认(https://gitee.com/lutlelk/ai-life-os-release/raw/master/version.json,HBuilderX 云打包不带 .env 也能用)> H5 同源 /static/version.jsonsrc/static/version.json 已随构建拷贝到产物 static/ 目录)。

3. 统计方案(规划:Phase 1+)

核心约束:不违背"不收集数据"的隐私承诺 → 统计必须 匿名 / 默认关闭 / 可透明查看 / 可一键删除。

方案 A:本地统计(推荐必做,零网络)

src/services/event.service.ts 已把各模块写操作统一记录到本地 lifeEvents 表 —— 本地统计的底座现成:

  • 本地聚合:模块使用频率、打卡率、番茄钟完成数 → 喂给现有 AI 洞察/回顾
  • 设置页「使用数据」透明页:展示、导出、一键清空

方案 B:免费第三方渠道(近零代码)

渠道说明
uni统计(DCloud)uni-app 官方,HBuilderX 一键开通;页面访问 + uni.report() 事件 + 崩溃,免费
友盟+ / Bugly国内 App 标配,有 uni-app 集成;含留存与崩溃分析
商店后台上架应用宝/华为/小米/Google Play 后,各市场自带 DAU/MAU/安装/卸载统计

方案 C:自建匿名遥测(完全自主可控)

  • 事件仅上报 { deviceIdHash(HMAC+盐), platform, version, event, ts },不含用户内容
  • 默认关闭,设置页展示待上报队列,一键删除
  • 接收端复用现有同步思路(WebDAV/Gist/静态站 + 离线脚本解析)
  • H5 官网可上 Umami / Plausible / Cloudflare Web Analytics(隐私友好、免费、可自托管)

合规要点

  • 苹果隐私标签一旦接统计,需从"不收集"改为声明 Analytics 收集并更新隐私政策 → 默认关闭 + 明示是关键
  • 国内按《个人信息保护法》:匿名聚合数据风险低;接第三方 SDK 需在隐私政策声明

4. 官网 & 后台(规划:Phase 2)

  • 官网:现有 VitePress 文档站(docs/)扩展 Download 页(APK 下载 + H5 入口 + changelog + 隐私政策),部署 Cloudflare Pages / Gitee Pages
  • 后台:前期不需要管理系统 —— Git Releases + version.json 即"发布后台";需要发布管理时再加 Cloudflare Worker + KV 或云函数的极简 /api/releases/latest

5. 路线图

Phase内容状态
0版本清单检测、Android 整包/wgt 下载安装、启动静默检查、H5 兜底清单✅ 已实现
1uni统计 开通 + 商店渠道;「使用数据」本地透明页待做
2VitePress 官网 + Download 页 + CI 发版流水线待做
3匿名遥测上报 + 轻量发布后台待做