更新记录

1.1.3(2026-03-25)

  • 提供插件内 config.js,集中配置应用 ID 与更新服务地址
  • 文档补充页面集成步骤与启动页两种 WGT 方案说明

平台兼容性

uni-app(4.11)

Vue2 Vue3 Chrome Safari app-vue app-nvue Android iOS 鸿蒙
- - - - - -
微信小程序 支付宝小程序 抖音小程序 百度小程序 快手小程序 京东小程序 鸿蒙元服务 QQ小程序 飞书小程序 小红书小程序 快应用-华为 快应用-联盟
- - - - - - - - - - - -

其他

多语言 暗黑模式 宽屏模式
× ×

isir-version-update

App 热更新组件,支持 APK 全包更新(弹窗提示 + 下载安装)和 WGT 热更新(后台静默下载下次安装,或在启动页内检查→下载→安装→重启),含 ThinkPHP8 完整后端 + 企业级管理后台。

功能特性

  • APK 全包更新:弹窗提示用户,显示更新日志、下载进度、自动安装
  • WGT 热更新:① 后台静默下载,下次启动安装(wgt-installer mixin);② 启动页一条龙检查/下载/安装(launch-wgt-flow.js
  • 强制更新模式:隐藏关闭按钮,用户必须更新
  • 下载失败自动重试(最多 3 次)
  • WGT 版本码本地管理,无需依赖 appWgtVersion
  • 含 ThinkPHP8 后端(API + 管理后台 + 建表 SQL)
  • 零第三方依赖,不依赖 uview-plus 等 UI 库

快速开始

第 1 步:导入插件

在 HBuilderX 插件市场导入,或手动将 uni_modules/isir-version-update 目录复制到你的项目 src/uni_modules/ 下。

第 2 步:部署后端

  1. server/database_init.sql 导入你的 MySQL 数据库
  2. server/thinkphp8/AppUpdate.php 复制到 ThinkPHP8 项目的 app/controller/ 目录
  3. server/thinkphp8/CrossDomain.php 复制到 app/middleware/ 目录
  4. server/thinkphp8/route.php 中的路由配置合并到你的 route/app.php
  5. config/middleware.php 中注册跨域中间件:
    return [
    'alias' => [
        'cross' => \app\middleware\CrossDomain::class,
    ],
    ];
  6. server/admin/appUpdate.html 复制到 public/admin/ 目录,访问 http://你的域名/admin/appUpdate.html 即可打开管理后台

第 3 步:修改插件内 config.js(必做)

插件根目录 uni_modules/isir-version-update/config.js 导出三项常量,安装插件后请先改为你自己的值(与后台应用 app_id、更新服务域名一致):

导出项 含义
APP_UPDATE_APP_ID 应用唯一标识
APP_UPDATE_SERVER_URL 更新服务站点根地址(如 https://api.example.com,不要带 /appUpdate/check
APP_UPDATE_WGT_INIT_CODE 首次安装时的本地 WGT 数字版本码,默认 10001

业务页面里统一写法:

import {
  APP_UPDATE_APP_ID,
  APP_UPDATE_SERVER_URL,
  APP_UPDATE_WGT_INIT_CODE,
} from '@/uni_modules/isir-version-update/config.js'

从插件市场升级本插件时:HBuilderX 可能覆盖 uni_modules 内文件,升级前请备份 config.js,升级后检查并恢复你的 appId / serverUrl

若你不希望使用 config.js,也可在模板里继续写死 appIdserverUrl(与下面「页面集成」一致即可)。

第 4 步:pages.json 建议

  • 启动页(若使用 launch-wgt-flowwgt-installer)放在 pages 数组第一项,保证冷启动先进入启动页。
  • 主界面(Tab 首页、不带 Tab 的首屏)需能 常驻或尽早 挂载 <isir-version-update />,否则 APK 全包更新 不会在恰当的时机检查(WGT 若走启动页一条龙,可与组件的 skipSilentWgtCheck 配合,见下表)。

第 5 步:页面集成说明(在哪些页面写什么)

以下为 uni-app App(Android / iOS) 推荐集成表;H5 / 小程序不会执行原生更新逻辑。

5.1 总览

页面角色 pages.json 中典型路径 必做? 要放什么
启动页 pages/splash/indexpages/Launchpage/index 二选一方案下必做其一 方式 Bmountedawait runLaunchWgtFlow({ appId, serverUrl, wgtInitCode } ← 来自 config.js,下同),并用 onStatus / onProgress 绑定你的加载 UI;方式 Amixins: [wgtInstaller],实现 onWgtSkip / onWgtFail
主包首页 pages/index/index(含 Tab 时多为第一个 tab 容器页) 建议必做 <isir-version-update />:传入与 config.js 一致的 appIdserverUrlwgtInitCode。若启动页已用 方式 B,请加 :skipSilentWgtCheck="true",避免 WGT 查两次
其它业务子页 任意 选做 一般不要重复挂载组件,除非你需要独立 Tab 无首页容器

5.2 主包首页(APK 弹窗 + 可选 WGT 静默)

组件支持 easycom;若未配置 easycom,需 import 注册(见插件内组件路径)。

仅使用方式 A(启动页 mixin)时:首页 不要skipSilentWgtCheck,以便组件在后台 静默下载 WGT,下次启动由启动页 安装

<template>
  <view>
    <isir-version-update
      :app-id="APP_UPDATE_APP_ID"
      :server-url="APP_UPDATE_SERVER_URL"
      :wgt-init-code="APP_UPDATE_WGT_INIT_CODE"
    />
    <!-- 下方为你的首页内容 -->
  </view>
</template>
<script>
import {
  APP_UPDATE_APP_ID,
  APP_UPDATE_SERVER_URL,
  APP_UPDATE_WGT_INIT_CODE,
} from '@/uni_modules/isir-version-update/config.js'
export default {
  data() {
    return {
      APP_UPDATE_APP_ID,
      APP_UPDATE_SERVER_URL,
      APP_UPDATE_WGT_INIT_CODE,
    }
  },
}
</script>

使用方式 B(启动页 runLaunchWgtFlow)时:首页组件加上 skipSilentWgtCheck,只负责 APK 与弹窗 UI:

<isir-version-update
  :app-id="APP_UPDATE_APP_ID"
  :server-url="APP_UPDATE_SERVER_URL"
  :wgt-init-code="APP_UPDATE_WGT_INIT_CODE"
  :skip-silent-wgt-check="true"
/>

5.3 启动页:方式 B(runLaunchWgtFlow)最小示例

mounted(Vue2)或 onMounted(Vue3) 中调用;不要result.waitingRestart === true 时再 uni.reLaunch(即将重启)。

import { runLaunchWgtFlow } from '@/uni_modules/isir-version-update/js_sdk/launch-wgt-flow.js'
import {
  APP_UPDATE_APP_ID,
  APP_UPDATE_SERVER_URL,
  APP_UPDATE_WGT_INIT_CODE,
} from '@/uni_modules/isir-version-update/config.js'

// 在 methods 中:
async startSplashFlow() {
  const result = await runLaunchWgtFlow({
    appId: APP_UPDATE_APP_ID,
    serverUrl: APP_UPDATE_SERVER_URL,
    wgtInitCode: APP_UPDATE_WGT_INIT_CODE,
    onStatus: (t) => { this.wgtStatusText = t },
    : (n) => { this.wgtProgress = n },
  })
  if (result.waitingRestart) return
  // 无更新或失败:再执行你的 uni.reLaunch 到登录页/首页
}

附录:方式 A(mixin)完整模板

第 5.1 表一致:选用方式 A 时,在启动页混入 wgtInstaller,并在 首页 挂载组件且 不要 使用 skipSilentWgtCheck

<template>
  <view class="splash" v-if="wgtInstalling">
    <text>{{ wgtStatusText }}</text>
    <view class="progress-bar">
      <view class="progress-fill" :style="{ width: wgtProgress + '%' }"></view>
    </view>
  </view>
</template>

<script>
import wgtInstaller from '@/uni_modules/isir-version-update/js_sdk/wgt-installer.js'

export default {
  mixins: [wgtInstaller],
  methods: {
    onWgtSkip() {
      uni.reLaunch({ url: '/pages/index/index' })
    },
    onWgtFail(err) {
      console.error('WGT安装失败', err)
    }
  }
}
</script>

mixin 提供数据: wgtInstallingwgtProgresswgtStatusText
行为: 有待安装包则安装并重启;无则立即 onWgtSkip();失败则 onWgtFail(可选)后仍 onWgtSkip()

附录:runLaunchWgtFlow(方式 B)流程与返回值

调用示例见 第 5.3 节(参数请使用 config.js 中常量)。

非 APP: Promise 得到 { skipped: true }

APP: 若有历史 pending_wgt_* 先安装;否则请求 WGT 检查 → 有更新则下载并 plus.runtime.install → 成功后更新本地版本码并 plus.runtime.restart();无更新或失败则 { skipped: true }

返回字段 含义
waitingRestart 已安排重启,禁止再执行 uni.reLaunch
skipped 未走重启(无更新、失败、或非 APP),继续你的路由逻辑

Props 属性

属性 类型 必填 默认值 说明
appId String - 应用唯一标识,区分不同 APP 项目
serverUrl String - 后端服务器地址,如 https://update.example.com
autoCheck Boolean true 组件挂载后是否自动检查更新
skipSilentWgtCheck Boolean false true在组件内请求 WGT 检查/静默下载,仍会检查 APK;与启动页 launch-wgt-flow 联用时可避免重复
wgtInitCode Number 10001 WGT 初始版本码,第一次安装 APP 时的默认值

Events 事件

事件名 参数 说明
has-update { version, updateInfo, updateType } 有更新可用
no-update { currentVersion } 当前已是最新版本
check-error { error } 检查更新失败
download-progress { type, progress, totalBytesWritten, totalBytesExpectedToWrite } 下载进度
download-error { error, retryCount } 下载失败
install-success { type } 安装成功
install-error { error, type } 安装失败
wgt-ready { version, filePath } WGT 静默下载完成,下次启动生效

插件内文件一览

路径 说明
config.js 全局配置APP_UPDATE_*),导入插件后修改
js_sdk/wgt-installer.js 启动页 mixin:仅安装待安装 WGT
js_sdk/launch-wgt-flow.js runLaunchWgtFlow:启动页 WGT 检查、下载、安装、重启
components/isir-version-update/isir-version-update.vue 页面组件(APK 弹窗 + WGT 静默逻辑)

Methods 方法

方法名 说明
manualCheck() 手动触发检查更新(通过 ref 调用)
<isir-version-update ref="updater" appId="xxx" serverUrl="xxx" :autoCheck="false" />
<button @click="$refs.updater.manualCheck()">检查更新</button>

WGT 版本码机制

由于 uni-app 没有原生的 WGT 版本号 API,本插件采用本地存储数字版本码的方案:

  1. APP 首次安装时,本地存储默认版本码(默认 10001,可通过 wgtInitCode 自定义)
  2. 后台发布 WGT 时,填写比当前版本码更大的数字(如 10002
  3. 组件检查更新时,将本地版本码发送给后端比较
  4. WGT 安装成功后,自动更新本地版本码

后端 API 接口

方法 路径 说明
GET /appUpdate/check 检查更新(前端组件调用)
POST /appUpdate/upload 上传安装包(管理后台调用)
GET /appUpdate/list 版本列表
POST /appUpdate/del 删除版本
POST /appUpdate/edit 编辑版本信息
GET /appUpdate/detail 版本详情
POST /appUpdate/toggleStatus 切换启用/禁用
GET /appUpdate/appList 应用列表
GET /appUpdate/clientReport 客户端上报版本

管理后台

server/admin/appUpdate.html 部署到后端 public/admin/ 目录,访问即可使用企业级管理界面:

  • 数据统计卡片(应用数、版本数、APK/WGT 数量)
  • 客户端上报版本查看(便于确定下次发版填多大的版本号)
  • 版本发布(上传 APK/WGT + 填写版本号和更新日志)
  • 版本编辑(修改强制更新、更新日志等)
  • 版本启用/禁用/删除

静态资源

组件使用了一张弹窗背景图 static/versionUpdate.png,请将你的更新弹窗背景图放入插件的 static/ 目录中。

如果没有自定义背景图,可以在网上搜索 "app更新弹窗背景" 找一张合适的。建议尺寸:宽 600rpx,高 700rpx 左右。

注意事项

  • 本插件仅支持 APP 端(Android/iOS),H5 和小程序环境会自动跳过更新检查
  • APK 版本号使用语义化格式(如 1.0.0),WGT 版本码使用纯数字递增(如 10001
  • 上传的安装包文件存储在后端 public/uploads/app_update/{app_id}/ 目录下
  • 后端需要 PHP 8.0+ 和 ThinkPHP 8.x

发布到 DCloud 插件市场(避免常见报错)

重要: 插件 package.jsonid、磁盘目录名、components 下子目录名、主 vue 文件名须 完全一致(建议 全小写 + 连字符,如本插件为 isir-version-update),以便通过 easycom 校验并支持普通授权定价。在插件市场创建插件时,插件 ID 请填 isir-version-update(或 你的作者id-version-update,但与包内 id、解压目录名须一致)。

1. components/isir-version-update 不存在 / 插件包格式不正确

多为 zip 根目录多包了一层。正确做法是:解压后 第一层 就应能看到本插件的 package.jsoncomponents/ 目录(即与 uni_modules 插件目录结构 一致)。

  • 错误:zip 里是 uni_modules/isir-version-update/...src/uni_modules/...,或再多一层空文件夹
  • 正确:在资源管理器中进入 uni_modules/isir-version-update选中该文件夹内全部内容(或选中该文件夹本身用「压缩到 xxx.zip」,保证解压第一层即 package.json + components),压缩为 标准 zip,文件名建议英文(如 isir-version-update.zip

更稳妥:在 HBuilderX 中对本插件目录下的 package.json 右键 → 发布到插件市场,由工具打包,避免手工 zip 结构错误。

2. 「仅 easycom 规范的前端组件插件可设置价格」

插件市场当前对 付费 + 自动加密 的前端组件,优先支持符合 easycom 的 uni_modules 组件传统 uni-app(Vue2)+ 付费加密 可能与 uni-app x + 云端编译加密 规则不完全一致。若持续无法设价:

  • 可先 免费发布 验证 zip 与文档;或
  • 向 DCloud 插件市场工单 / 官方文档确认 「component-vue + uni-app Vue2」 是否允许与普通授权同价上架;或
  • 长期方案:将主组件按官方要求迁移至 uni-app x + easycom(见 付费前端插件说明

本插件已采用 components/isir-version-update/isir-version-update.vue,安装后可直接 不写 import、在页面使用 <isir-version-update />(与 easycom 一致);示例工程里若仍 import 组件,仅为便于说明,不影响 easycom 能力。

3. 付费插件与 uni_modules.encrypt

package.json 内已配置 uni_modules.encrypt,列出可参与加密的 JS 文件路径(相对于插件根目录)。config.js 未列入加密,便于购买「普通授权」的用户修改自己的 appId / serverUrl;若市场审核要求调整列表,以审核意见为准。

隐私、权限声明

1. 本插件需要申请的系统权限列表:

无(插件通过 uni 官方 API 实现;实际网络等权限以应用 manifest 与宿主 App 配置为准。)

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

插件会向用户在 config.js 或组件_props 中配置的 serverUrl 发起版本检查等请求,典型包含 app_id、当前 APK 版本号或 WGT 版本码;数据用途为判断是否有更新、下载地址:无其它内置采集。后端由用户自行部署,隐私以用户隐私政策为准。

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率: