更新记录

1.6.0(2026-06-02) 下载此版本

优化文档

1.5.9(2026-06-02) 下载此版本

新增pc后台管理模板代码,优化文档

1.5.8(2026-06-02) 下载此版本

新增pc后台管理模板代码

查看更多

平台兼容性

uni-app(3.7.8)

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

整包更新和热更新组件 支持vue3 支持打开纯血鸿蒙、安卓、苹果应用市场,支持wgt静默更新

  • ui图是采用uniapp官方更新组件的ui,如不满足需要,可自行替换
  • 一键式检查更新,同时支持整包升级与wgt资源包更新 支持打开纯血鸿蒙、安卓自带的应用市场和苹果appstore
  • 好看、实用、可自定义的客户端提示框
  • 支持强制更新,无法退出
  • 支持静默更新,下次启动后更新的内容自动生效
  • 支持覆盖原生tabar,原生导航栏

uniappx版本插件在下面这个地址

uniappx版本插件在这里

安装指引

  1. 在插件市场打开本插件页面,在右侧点击使用 HBuilderX 导入插件,选择要导入的项目点击确定(建议使用uni_modules版本 非uni_modules版本不在维护,有需要自行修改)

  2. pages.json中添加页面路径。注意:一定不要设置为pages.json中第一项

"pages": [
        // ……其他页面配置
        {
            "path": "uni_modules/rt-uni-update/components/rt-uni-update/rt-uni-update",
            "style": {
                "disableScroll": true,
                "app-plus": {
                    "backgroundColorTop": "transparent",
                    "background": "transparent",
                    "titleNView": false,
                    "scrollIndicator": false,
                    "popGesture": "none",
                    "animationType": "fade-in",
                    "animationDuration": 200

                }
            }
        }
]
  1. 查看显示效果 (注意:这里只是查看显示效果,具体代码需要按照下面的项目使用说明编写)

// App.vue的onShow中查看效果 如果无法跳转 请在`pages.json`中添加页面路径,参照第二步

uni.navigateTo({
    url: '/uni_modules/rt-uni-update/components/rt-uni-update/rt-uni-update'
});

PC管理后台都需要有一个app的版本管理系统(可参考下代码模板,根据自己需求和字段修改)

pc列表页代码 index.vue

<template>
  <div class="layout-padding">
    <div class="layout-padding-auto layout-padding-view">
      <!-- 搜索区域 -->
      <el-row>
        <el-form :model="queryForm" ref="queryRef" :inline="true" @keyup.enter="getDataList">
          <el-form-item label="应用名称" prop="appName">
            <el-input clearable placeholder="请输入应用名称" v-model="queryForm.appName" />
          </el-form-item>
          <el-form-item>
            <el-button icon="search" type="primary" @click="getDataList">查询</el-button>
            <el-button icon="Refresh" @click="resetQuery">重置</el-button>
          </el-form-item>
        </el-form>
      </el-row>

      <!-- 操作按钮区 -->
      <el-row>
        <div class="mb8" style="width: 100%">
          <el-button icon="folder-add" type="primary" class="ml10" @click="handleAdd">发布新版</el-button>
        </div>
      </el-row>

      <!-- 版本列表表格 -->
      <el-table
        :data="dataList"
        v-loading="loading"
        border
        @selection-change="selectionChangHandle"
      >
        <el-table-column prop="appName" label="应用名称" show-overflow-tooltip width="120" />
        <el-table-column prop="appId" label="AppID" show-overflow-tooltip width="150" />
        <el-table-column prop="editionNumber" label="版本号" width="100" />
        <el-table-column prop="editionName" label="版本名称" width="120" />
        <el-table-column prop="platform" label="系统类型" width="100">
          <template #default="scope">
            <el-tag :type="scope.row.platform === 'android' ? 'success' : scope.row.platform === 'ios' ? 'warning' : 'danger'">
              {{ scope.row.platform === 'android' ? 'Android' : scope.row.platform === 'ios' ? 'iOS' : '鸿蒙' }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column prop="packageType" label="安装包类型" width="100">
          <template #default="scope">
            <el-tag :type="scope.row.packageType === 0 ? 'success' : 'warning'">
              {{ scope.row.packageType === 0 ? '整包更新' : 'wgt热更新' }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column prop="editionIssue" label="是否发行" width="90">
          <template #default="scope">
            <el-tag :type="scope.row.editionIssue === 1 ? 'success' : 'info'">
              {{ scope.row.editionIssue === 1 ? '是' : '否' }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column prop="editionSilence" label="静默更新" width="90">
          <template #default="scope">
            {{ scope.row.editionSilence === 1 ? '是' : '否' }}
          </template>
        </el-table-column>
        <el-table-column prop="editionForce" label="强制更新" width="100">
          <template #default="scope">
            {{ scope.row.editionForce === 1 ? '是' : '否' }}
          </template>
        </el-table-column>
        <el-table-column prop="editionDesc" label="更新内容" min-width="200" show-overflow-tooltip>
          <template #default="scope">
            <div v-html="scope.row.editionDesc"></div>
          </template>
        </el-table-column>

        <el-table-column label="操作" fixed="right" width="180">
          <template #default="scope">
            <el-button icon="edit-pen" text type="primary"  @click="handleEdit(scope.row)">编辑</el-button>
          </template>
        </el-table-column>
      </el-table>

      <!-- 分页组件 -->
      <el-pagination
                    v-model:current-page="pagination.current"
                    v-model:page-size="pagination.size"
                    :page-sizes="[10, 20, 30, 50,100]"
                    :size="pagination.size"
                    layout="total, sizes, prev, pager, next, jumper"
                    :total="pagination.total"
                    @size-change="handleSizeChange"
                    @current-change="handleCurrentChange"
                />
    </div>

    <!-- 版本编辑/新增弹窗 -->
    <VersionDialog ref="versionDialogRef" @refresh="getDataList" />
  </div>
</template>

<script setup lang="ts" name="appVersionManager">
import { reactive, ref, onMounted } from 'vue'
import { ElMessage } from 'element-plus'
import { useMessage, useMessageBox } from '/@/hooks/message'
import { fetchList, delObjs } from '/@/api/app/version'
import VersionDialog from './form.vue'

// 搜索表单
const queryForm = reactive({
  appName: '',
})

// 列表数据
const dataList = ref<any[]>([])
const loading = ref(false)
const pagination = reactive({
  current: 1,
  size: 20,
  total: 0
})

// 多选
const selectObjs = ref<string[]>([])
const multiple = ref(true)

// 搜索相关
const queryRef = ref()

// 弹窗引用
const versionDialogRef = ref()

// 获取列表数据
const getDataList = async () => {
  loading.value = true
  try {
    const params = {
      ...queryForm,
      current: pagination.current,
      size: pagination.size
    }
    const res = await fetchList(params)
    dataList.value = res.data.list || []
    pagination.total = res.data.total || 0
  } catch (error: any) {
    useMessage().error(error.message || '获取列表失败')
  } finally {
    loading.value = false
  }
}

// 重置搜索
const resetQuery = () => {
  queryRef.value?.resetFields()
  // 重置搜索条件
  queryForm.appName = ''
  queryForm.platform = ''
  queryForm.editionIssue = undefined
  pagination.current = 1
  getDataList()
}

// 分页改变
const handleSizeChange = (size: number) => {
  pagination.size = size
  pagination.current = 1
  getDataList()
}
const handleCurrentChange = (current: number) => {
  pagination.current = current
  getDataList()
}

// 多选事件
const selectionChangHandle = (objs: { id: string }[]) => {
  selectObjs.value = objs.map(({ id }) => id)
  multiple.value = !objs.length
}

// 新增
const handleAdd = () => {
  versionDialogRef.value?.openDialog()
}

// 编辑
const handleEdit = (row: any) => {
  versionDialogRef.value?.openDialog(row.id)
}

// 单个删除
const handleDelete = async (id: string) => {
  try {
    await useMessageBox().confirm('此操作将永久删除该版本')
  } catch {
    return
  }
  try {
    await delObjs(id)
    ElMessage.success('删除成功')
    getDataList()
  } catch (err: any) {
    useMessage().error(err.msg)
  }
}

onMounted(() => {
  getDataList()
})
</script>

<style scoped lang="scss">
.layout-padding {
  padding: 20px;
}

.layout-padding-auto {
  background: #fff;
  border-radius: 8px;
  padding: 20px;
}

.mb8 {
  margin-bottom: 8px;
}

.ml10 {
  margin-left: 10px;
}

.mr20 {
  margin-right: 20px;
}

:deep(.el-table) {
  font-size: 14px;
}

:deep(.el-table th.el-table__cell) {
  background-color: #f5f7fa;
}
</style>

pc更新弹窗组件代码 form.vue

<template>
  <el-dialog
    :title="form.id ? '编辑版本' : '发布新版'"
    v-model="visible"
    :close-on-click-modal="false"
    draggable
    width="70%"
  >
    <el-form
      ref="dataFormRef"
      :model="form"
      :rules="dataRules"
      label-width="130px"
      v-loading="loading"
    >
      <!-- 基础信息 -->
      <div class="bt">基础信息</div>
      <el-row :gutter="24">
        <el-col :span="12" class="mb20">
          <el-form-item label="AppID" prop="appId">
            <el-input v-model="form.appId" placeholder="例如:__UNI__xxxxx" />
          </el-form-item>
        </el-col>
        <el-col :span="12" class="mb20">
          <el-form-item label="应用名称" prop="appName">
            <el-input v-model="form.appName" placeholder="请输入应用名称" />
          </el-form-item>
        </el-col>
        <el-col :span="12" class="mb20">
          <el-form-item label="版本号(数字)" prop="editionNumber">
            <el-input-number v-model="form.editionNumber" :min="1" style="width: 100%" />
          </el-form-item>
        </el-col>
        <el-col :span="12" class="mb20">
          <el-form-item label="版本名称" prop="editionName">
            <el-input v-model="form.editionName" placeholder="例如:1.0.0" />
          </el-form-item>
        </el-col>
        <el-col :span="12" class="mb20">
          <el-form-item label="系统类型" prop="platform">
            <el-radio-group v-model="form.platform">
              <el-radio label="android">Android</el-radio>
              <el-radio label="ios">iOS</el-radio>
              <el-radio label="harmonyos">鸿蒙</el-radio>
            </el-radio-group>
          </el-form-item>
        </el-col>
        <el-col :span="12" class="mb20">
          <el-form-item label="安装包类型" prop="packageType">
            <el-radio-group v-model="form.packageType">
              <el-radio :label="0">整包更新(APK/应用市场)</el-radio>
              <el-radio :label="1">WGT热更新</el-radio>
            </el-radio-group>
          </el-form-item>
        </el-col>
        <el-col :span="12" class="mb20">
          <el-form-item label="是否发行" prop="editionIssue">
            <el-switch v-model="form.editionIssue" :active-value="1" :inactive-value="0" />
            <span class="form-tip">(上架市场审核时请设为“否”)</span>
          </el-form-item>
        </el-col>
        <el-col :span="12" class="mb20">
          <el-form-item label="静默更新" prop="editionSilence">
            <el-switch v-model="form.editionSilence" :active-value="1" :inactive-value="0" />
            <span class="form-tip">(静默下载,下次启动生效)</span>
          </el-form-item>
        </el-col>
        <el-col :span="12" class="mb20">
          <el-form-item label="强制更新" prop="editionForce">
            <el-switch v-model="form.editionForce" :active-value="1" :inactive-value="0" />
            <span class="form-tip">(强制弹窗,不更新无法使用)</span>
          </el-form-item>
        </el-col>
      </el-row>

      <!-- 下载地址 -->
      <div class="bt">下载地址</div>
      <el-row :gutter="24">
        <el-col :span="24" class="mb20">
          <el-form-item label="下载地址" prop="editionUrl">
            <div>
              <el-input
                v-model="form.editionUrl"
                placeholder="http:// 或 market:// 或 itms-apps:// 等"
                style="flex: 1;margin-bottom: 10px;"
              />
                <el-upload
                action="#"
                class="avatar-uploader"
                :limit="1"
                drag
                ref="upload"
                :on-change="beforeAvatarUpload"
                :file-list="File.fileList"
                :auto-upload="false"
                accept=".apk,.wgt"
            >
                <i class="el-icon-upload"></i>
                <div class="el-upload__text">
                    上传安装包(.apk/.wgt),上传成功后会自动填充下载地址
                </div>

            </el-upload>
            </div>
          </el-form-item>
        </el-col>
      </el-row>

      <!-- 更新内容 -->
      <div class="bt">更新内容</div>
      <el-row :gutter="24">
        <el-col :span="24" class="mb20">
          <el-form-item label="更新内容" prop="editionDesc">
            <!-- 富文本组件 -->
            <editor v-model:get-html="form.editionDesc" />
          </el-form-item>
        </el-col>
      </el-row>
    </el-form>

    <template #footer>
      <span class="dialog-footer">
        <el-button @click="visible = false">取消</el-button>
        <el-button type="primary" @click="onSubmit" :loading="loading">确认</el-button>
      </span>
    </template>
  </el-dialog>
</template>

<script setup>
import { ref, reactive, nextTick } from 'vue'
import { ElMessage } from 'element-plus'
import { addObj, putObj, getObj,uploadApi } from '/@/api/app/version'
import { useMessage } from '/@/hooks/message';
const emit = defineEmits(['refresh'])

const visible = ref(false)
const loading = ref(false)
const uploadLoading = ref(false)
const dataFormRef = ref(null)

const form = reactive({
  id: undefined,
  appId: '',
  appName: '',
  editionNumber: 100,
  editionName: '1.0.0',
  platform: 'android',
  packageType: 1,
  editionIssue: 1,
  editionSilence: 1,
  editionForce: 0,
  editionUrl: '',
  editionDesc: ''
})

const dataRules = {
  appId: [{ required: true, message: '请输入 AppID', trigger: 'blur' }],
  appName: [{ required: true, message: '请输入应用名称', trigger: 'blur' }],
  editionNumber: [{ required: true, message: '请输入版本号', trigger: 'blur' }],
  editionName: [{ required: true, message: '请输入版本名称', trigger: 'blur' }],
  platform: [{ required: true, message: '请选择系统类型', trigger: 'change' }],
  packageType: [{ required: true, message: '请选择安装包类型', trigger: 'change' }],
  editionUrl: [{ required: true, message: '请输入下载地址', trigger: 'blur' }],
  editionDesc: [{ required: true, message: '请输入更新内容', trigger: 'blur' }]
}
const File = reactive({
    fileList: [],
});

const beforeAvatarUpload = (file) => {
    file = file.raw;
        uploadLoading.value = true
        let fromData = new FormData();

        fromData.append('file', file);
        uploadApi(fromData).then((res) => {
            uploadLoading.value = false
            if (res.status == 200) {
                useMessage().success('上传成功');
                form.editionUrl = 'http://你的ip' +  res.data.objectName;
            } else {
                useMessage().error(res.message);
            }
        }).catch(()=>{
            uploadLoading.value = false
            useMessage().error('上传失败');
        });

};

const openDialog = (id) => {
  visible.value = true
  Object.assign(form, {
    id: undefined,
    appId: '',
    appName: '',
    editionNumber: 100,
    editionName: '1.0.0',
    platform: 'android',
    packageType: 1,
    editionIssue: 1,
    editionSilence: 0,
    editionForce: 1,
    editionUrl: '',
    editionDesc: ''
  })
  nextTick(() => {
    dataFormRef.value?.clearValidate()
    File.fileList = []
  })
  if (id) {
    getVersionDetail(id)
  }
}

const getVersionDetail = async (id) => {
  loading.value = true
  try {
    const res = await getObj(id)
    if (res.code === 0 || res.status === 200) {
      const detail = res.data
      Object.assign(form, {
        id: detail.id,
        appId: detail.appId,
        appName: detail.appName,
        editionNumber: detail.editionNumber,
        editionName: detail.editionName,
        platform: detail.platform,
        packageType: detail.packageType,
        editionIssue: detail.editionIssue,
        editionSilence: detail.editionSilence,
        editionForce: detail.editionForce,
        editionUrl: detail.editionUrl,
        editionDesc: detail.editionDesc?.replace(/<br>/g, '\n') || ''
      })
    } else {
      ElMessage.error(res.message || '获取版本详情失败')
    }
  } catch (error) {
    ElMessage.error('获取版本详情失败')
    console.error(error)
  } finally {
    loading.value = false
  }
}

const onSubmit = async () => {
  try {
    await dataFormRef.value?.validate()
  } catch {
    return
  }
  loading.value = true
  try {
    const submitData = {
      ...form,
      editionDesc: form.editionDesc?.replace(/\n/g, '<br>') || ''
    }
    let res
    if (form.id) {
      res = await putObj(submitData)
    } else {
      res = await addObj(submitData)
    }
    if (res.code === 0 || res.status === 200) {
      ElMessage.success(form.id ? '编辑成功' : '发布成功')
      visible.value = false
      emit('refresh')
    } else {
      ElMessage.error(res.message || '操作失败')
    }
  } catch (error) {
    ElMessage.error('操作失败')
    console.error(error)
  } finally {
    loading.value = false
  }
}

defineExpose({ openDialog })
</script>

<style lang="scss" scoped>
.tip {
  padding: 8px 16px;
  background-color: #ecf8ff;
  border-radius: 4px;
  border-left: 5px solid #50bfff;
  margin: 20px 0;
  font-size: 13px;
  color: #31708f;
}
.bt {
  margin-left: 30px;
  margin-bottom: 20px;
  font-size: 18px;
  font-weight: bold;
  border-left: 4px solid #409eff;
  padding-left: 12px;
}
.mb20 {
  margin-bottom: 20px;
}
.form-tip {
  font-size: 12px;
  color: #909399;
  margin-left: 10px;
}
.dialog-footer {
  text-align: right;
}
</style>

项目使用说明 最重要!!!

  • 注意!!!后端返回数据要求 字段如下 (如果后端字段不一样,请在跳转更新页时手动赋值,示例见下面代码)
data:{
    // 版本更新内容 支持<br>自动换行
    describe: '1. 修复已知问题<br>
                2. 优化用户体验', 
    edition_url: '', //apk、wgt包下载地址或者应用市场地址  安卓应用市场: market://details?id=xxxx 苹果store: itms-apps://itunes.apple.com/cn/app/xxxxxx 鸿蒙: store//appgallery.huawei.com/app/detail?id=包名 或者 https://appgallery.huawei.com/app/detail?id=包名
    edition_force: 0, //是否强制更新 0代表否 1代表是
    package_type: 1, //0是整包升级(apk或者appstore或者安卓应用市场) 1是wgt升级
    edition_issue:1, //是否发行  0否 1是 为了控制上架应用市场审核时不能弹出热更新框
    edition_number:100, //版本号 最重要的manifest里的版本号 (检查更新主要以服务器返回的edition_number版本号是否大于当前app的版本号来实现是否更新)
    edition_name:'1.0.0',// 版本名称 manifest里的版本名称
    edition_silence:0, // 是否静默更新 0代表否 1代表是
}

// 如果后端返回的字段和上面不一致,请在前端手动赋值(示例)

let data = res.data.data;
data.edition_url = res.data.data.editionUrl;
data.describe = res.data.data.editionDesc;
data.edition_force = res.data.data.editionForce; 
data.package_type = res.data.data.packageType; 
data.edition_issue = res.data.data.editionIssue; 
data.edition_number = res.data.data.editionNumber; 
data.edition_name = res.data.data.editionName; 
data.edition_silence = res.data.data.editionSilence; 
//跳转更新页面 (注意!!!如果pages.json第一页的代码里有一打开就跳转其他页面的操作,下面这行代码最好写在setTimeout里面设置延时3到5秒再执行)
uni.navigateTo({
    url: '/uni_modules/rt-uni-update/components/rt-uni-update/rt-uni-update?obj=' + JSON.stringify(data)
});

后端注意!!!

后端根据前端的edition_number这个字段,先查询大于edition_number的整包地址,如果没有,那就返回大于当前edition_number的最新一条记录就行

edition_number传这个参数是为了解决部分用户app长期不使用,第一次打开服务器查到的版本是最新的是wgt包,但是之前app有过整包更新,如果直接更新最新wgt的话,会出现以前的整包添加的原生模块或者安卓权限无法使用,

  • 前端示例代码 或者根据实际业务修改 如果需要自动检测新版本,建议写在App.vue的onShow中
import silenceUpdate from '@/uni_modules/rt-uni-update/js_sdk/silence-update.js' //引入静默更新

//#ifdef APP-PLUS 

// 获取本地应用资源版本号
        plus.runtime.getProperty(plus.runtime.appid, (inf) => {
            //获取服务器的版本号
            uni.request({
                url: 'http://127.0.0.1:8088/edition_manage/get_edition', //示例接口
                data: {
                    edition_type: plus.runtime.appid,
                    version_type: uni.getSystemInfoSync().platform, //android或者ios或者harmonyos
                    edition_number: inf.versionCode // 打包时manifest设置的版本号 
                },
                success: (res) => {
                    //res.data.xxx根据后台返回的数据决定(我这里后端返回的是data),所以是res.data.data 
                    //判断后台返回版本号是否大于当前应用版本号 && 是否发行 (上架应用市场时一定不能弹出更新提示)
                    if (Number(res.data.data.edition_number) > Number(inf.versionCode) && res
                        .data.data.edition_issue == 1) {

                        //如果是wgt升级,并且是静默更新 (注意!!! 如果是手动检查新版本,就不用判断静默更新,请直接跳转更新页,不然点击检查新版本后会没反应)
                        if (res.data.data.package_type == 1 && res.data.data.edition_silence == 1) {

                            //调用静默更新方法 传入下载地址
                            silenceUpdate(res.data.data.edition_url)

                        } else {
                            // 如果后端返回的字段和上面不一致,请在前端手动赋值(示例)
                            let data = res.data.data;
                            data.edition_url = res.data.data.editionUrl;
                            data.describe = res.data.data.editionDesc;
                            data.edition_force = res.data.data.editionForce; 
                            data.package_type = res.data.data.packageType; 
                            data.edition_issue = res.data.data.editionIssue; 
                            data.edition_number = res.data.data.editionNumber; 
                            data.edition_name = res.data.data.editionName; 
                            data.edition_silence = res.data.data.editionSilence; 
                            //跳转更新页面 (注意!!!如果pages.json第一页的代码里有一打开就跳转其他页面的操作,下面这行代码最好写在setTimeout里面设置延时3到5秒再执行)
                            uni.navigateTo({
                                url: '/uni_modules/rt-uni-update/components/rt-uni-update/rt-uni-update?obj=' + JSON.stringify(data)
                            });

                        }
                    } else {

                        // 如果是手动检查新版本 需开启以下注释
                        /* uni.showModal({
                            title: '提示',
                            content: '已是最新版本',
                            showCancel: false
                        }) */
                    }
                }

            })

        });

        //#endif    

应用商店常见地址

鸿蒙5.0以下及安卓手机自带应用市场:market://details?id=包名
苹果AppStore:itms-apps://itunes.apple.com/cn/app/id<应用ID>
鸿蒙5.0及以上:store//appgallery.huawei.com/app/detail?id=包名 或者 https://appgallery.huawei.com/app/detail?id=包名

常见问题汇总!!!

热更新制作wgt包的方法:1、修改manifest.json版本名称和版本号,必须大于当前版本。2、点击菜单的发行——原生App-制作应用wgt包

app上传地址:个人建议开通unicloud的阿里云按量付费,方便、便宜,apk或者wgt包直接上传到云存储就行。

1、调试请打包自定义基座测试,否则uni.getSystemInfoSync().platform获取到的可能不是android或者ios,会导致无法跳转更新页

2、进度条不显示,先把下载路径在浏览器打开,测试一下是否能正常下载,排查原因:99%的情况是因为下载链接为内网链接,内网链接无法监听下载进度,请更换为外网链接,或者是检查后端是否设置content-length,如果用的是支付宝云的话,支付宝云下载文件时是流式返回,没有进度

3、进度条显示,下载apk完成后,安卓不会自动弹出安装页面,原因:可能是离线打包未添加安卓安装权限,请添加以下权限,除了加权限,还要去sdk里把install-apk-release.aar放自己基座的lib文件夹里。或者使用云打包

<uses-permission android:name="android.permission.INSTALL_PACKAGES" />
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />

4、在app.vue中无法跳转到更新页,原因:第一、在pages.json中忘记注册页面,第二、如果已经注册过页面,一般在app.vue或者首页中会有默认跳转,所以影响到了跳转更新页,解决办法:修改跳转逻辑或者在跳转更新页时加setTimeout,延时几秒在跳转

5、app内下载apk时会跳转外部下载,原因:安卓apk下载链接必须为.apk结尾,如果不是.apk结尾,就会跳转外部下载(比如应用市场链接)。

6、热更新时wgt包可以下载,但是无法安装,控制台提示wgt/wgtu文件格式错误。解决方法:下载地址必须为http://xxxxxx.wgt的格式,就是链接必须以.wgt结尾。2、如果地址是http://xxxxxx.wgt格式,请在浏览器打开这个下载地址,如果无法自动下载,一般可能都是后端下载权限的问题导致的

7、整包更新/热更新成功后,还是一直弹更新弹窗,原因是,打wgt包时未修改manifest.json的版本号,请修改版本号后上传服务器后重试。

8、苹果支持appstore链接和wgt更新,不支持整包ipa更新。

9、wgt更新,进度条100%,苹果无法安装,原因:1、wgt包名不要设置为中文,2、增加原生模块必须上传appstore,不能热更新

10、不能热更新的有:1、如果原项目没有nvue页面,新增nvue后也必须整包更新,2、增加推送、第三方登录、地图、视频播放、支付等模块,或者其他安卓权限。3、修改启动图或者app图标

11、更新弹窗后面的页面一半儿白屏,官方的bug

12、跳转更新页后无法获取参数,可能是使用了uni-simple-router等第三方路由插件,解决办法:通过eventChannel.$emit等方式传参,在插件里接收赋值

13、鸿蒙测试wgt更新,需要使用 发行 -> APP-Harmony 本地打包 -> 生成安装包 -> unpackage/dist/build/app-harmony 中的项目使用 华为开发者工具devEco 打开项目,连接真机测试 wgt 更新。并且要先卸载手机上的标准基座,通过为开发者工具devEco重新运行安装

插件不完美,但是可以适配大多数更新需求,如果您认为这个插件帮到了您的开发工作,麻烦给个五星好评鼓励一下,有能力的也可以小小赞赏一下,感谢支持。

隐私、权限声明

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

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

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

许可协议

MIT协议