diff --git a/uni_modules/uni-upgrade-center-app/pages/upgrade-popup.vue b/uni_modules/uni-upgrade-center-app/pages/upgrade-popup.vue index 2a98a2155c70d89ab4b0287d74dc02da606bdb9b..b82cdc1965d68cfd22be0e08e748c6279d321b99 100644 --- a/uni_modules/uni-upgrade-center-app/pages/upgrade-popup.vue +++ b/uni_modules/uni-upgrade-center-app/pages/upgrade-popup.vue @@ -3,7 +3,7 @@ {{title}} - + @@ -53,7 +53,7 @@ - + @@ -314,11 +314,11 @@ }, downLoadComplete() { this.downloading = false; - + this.downLoadPercent = 0 this.downloadedSize = 0 this.packageFileSize = 0 - + downloadTask = null; // 强制更新,直接安装 @@ -555,4 +555,4 @@ flex-direction: column; align-items: center; } - \ No newline at end of file + diff --git a/uni_modules/uni-upgrade-center-app/readme.md b/uni_modules/uni-upgrade-center-app/readme.md index 3e830b5acf2e6744239e1fba529e50265533683f..53ff781d975f94f4e7b5ae8bd6dd4fcff8339817 100644 --- a/uni_modules/uni-upgrade-center-app/readme.md +++ b/uni_modules/uni-upgrade-center-app/readme.md @@ -1,126 +1 @@ -## 升级中心 - app插件与 `uni-admin` 版本关系 - -### `uni-admin >= 1.9.3`:云函数 `checkVersion` 废弃,使用 uni-admin 自带的 `uni-upgrade-center` 云函数。 - -# uni-upgrade-center - App - -### 概述 - -> 统一管理App及App在`Android`、`iOS`平台上`App安装包`和`wgt资源包`的发布升级 - -> uni升级中心分为业务插件和后台管理插件。本插件为业务插件,包括uni升级中心客户端检查更新的前后端逻辑。后台管理系统另见 [uni-upgrade-center - Admin](https://ext.dcloud.net.cn/plugin?id=4470) - -### uni升级中心 - 客户端检查更新插件 - - 一键式检查更新,同时支持整包升级与wgt资源包更新 - - 好看、实用、可自定义的客户端提示框 - -## 安装指引 - -1. 依赖数据库`opendb-app-versions`,如果没有此库,请在云服务空间中创建。 - -2. 使用`HBuilderX 3.1.0+`,因为要使用到`uni_modules` - -3. 在插件市场打开本插件页面,在右侧点击`使用 HBuilderX 导入插件`,选择要导入的项目点击确定 - -4. 绑定一个服务空间。自 `0.6.0` 起,依赖 `uni-admin 1.9.3+` 的 `uni-upgrade-center 云函数`,请和 uni-admin 项目关联同一个服务空间 - -5. 找到`/uni_modules/uni-upgrade-center-app/uniCloud/cloudfunctions/check-version`,右键上传部署。自 `0.6.0` 起,依赖 `uni-admin 1.9.3+` 的 `uni-upgrade-center 云函数`,插件不再单独提供云函数,这样可以省下一个云函数名额。 - -6. 在`pages.json`中添加页面路径。**注:请不要设置为pages.json中第一项** -```json -"pages": [ - // ……其他页面配置 - { - "path": "uni_modules/uni-upgrade-center-app/pages/upgrade-popup", - "style": { - "disableScroll": true, - "app-plus": { - "backgroundColorTop": "transparent", - "background": "transparent", - "titleNView": false, - "scrollIndicator": false, - "popGesture": "none", - "animationType": "fade-in", - "animationDuration": 200 - - } - } - } -] -``` - -7. 将`@/uni_modules/uni-upgrade-center-app/utils/check-update`import到需要用到的地方,调用一下即可 - 1. 默认使用当前绑定的服务空间,如果要请求其他服务空间,可以使用其他服务空间的 `callFunction`。[详情](https://uniapp.dcloud.io/uniCloud/cf-functions.html#call-by-function-cross-space) - -8. 升级弹框可自行编写,也可以使用`uni.showModal`,或使用现有的升级弹框样式,如果不满足UI需求请自行替换资源文件。在`utils/check-update.js`中都有实例。 - -9. wgt更新时,打包前请务必将manifest.json中的版本修改为更高版本。 - -### 更新下载安装`check-update.js` - -*该函数在utils目录下* - -1. 如果是静默更新,则不会打开更新弹框,会在后台下载后安装,下次启动应用生效 - -2. 如果是 iOS,则会直接打开AppStore的链接 - -3. 其他情况,会将`check-version`返回的结果保存在localStorage中,并跳转进入`upgrade-popup.vue`打开更新弹框 - -### 检查更新函数`check-version` - -*该函数在uniCloud/cloudfunctions目录下* - -1. 使用检查更新需要传递三个参数 `appid`、`appVersion`、`wgtVersion` - -2. `appid` 使用 plus.runtime.appid 获取,*注:真机运行时为固定值HBuilder,在调试的时候请使用本地调试云函数* - -3. `appVersion` 使用 plus.runtime.version 获取 - -4. `wgtVersion` 使用 plus.runtime.getProperty(plus.runtime.appid,(wgtInfo) => { wgtInfo.version }) 获取 - -5. `check-version`云函数内部会自动获取 App 平台 - - -**Tips** - -1. `check-version`云函数内部有版本对比函数(compare)。 - - 使用多段式版本格式(如:"3.0.0.0.0.1.0.1", "3.0.0.0.0.1")。如果不满足对比规则,请自行修改。 - - 如果修改,请将*pages/upgrade-popup.vue*中*compare*函数一并修改 - -## 项目代码说明 - -### 更新弹框 -- `upgrade-popup.vue` - 更新应用: - - 如果云函数`check-version`返回的参数表明需要更新,则将参数保存在localStorage中,带着键值跳转该页面 - - 进入时会先从localStorage中尝试取出之前存的安装包路径(此包不会是强制安装类型的包) - - 如果有已经保存的包,则和传进来的 `version` 进行比较,如果相等则安装。大于和小于都不进行安装,因为admin端可能会调整包的版本。不符合更新会将此包删除 - - 如果本地没有包或者包不符合安装条件,则进行下载安装包 - - 点击下载会有进度条、已下载大小和下载包的大小 - - 下载完成会提示安装: - - 如果是 wgt 包,安装时则会提示 正在安装…… 和 安装完成。安装完成会提示是否重启 - - 如果是 原生安装包,则直接跳出去覆盖安装 - - 下载过程中,如果退出会提示是否取消下载。如果是强制更新,则只会提示正在下载请稍后,此时不可退出 - - 如果是下载完成了没有安装就退出,则会将下载完成的包保存在本地。将包的本地路径和包version保存在localStorage中 - -### 工具类 utils -- `call-check-version` - - 请求云函数`check-version`拿取版本检测结果 -- `check-update` - - 调用`call-check-version`并根据结果判断是否显示更新弹框 - -### 云函数 -- `check-version` - 检查应用更新: - - 根据传参,先检测传参是否完整,appid appVersion wgtVersion 必传 - - 先从数据库取出所有该平台(会从上下文读取平台信息)的所有线上发行更新 - - 再从所有线上发行更新中取出版本最大的一版。如果可以,尽量先检测wgt的线上发行版更新 - - 使用上一步取出的版本包的版本号 和传参 appVersion、wgtVersion 来检测是否有更新。必须同时大于这两项,因为上一次可能是wgt热更新,否则返回暂无更新 - - 如果库中 wgt包 版本大于传参 appVersion,但是不满足 min_uni_version < appVersion,则不会使用wgt更新,会接着判断库中 app包version 是否大于 appVersion - - 返回结果: - - |code|message| - |:-:|:-:| - |0|当前版本已经是最新的,不需要更新| - |101|wgt更新| - |102|整包更新| - |-101|暂无更新或检查appid是否填写正确| - |-102|请检查传参是否填写正确| \ No newline at end of file +文档已移至 [uni-upgrade-center](https://uniapp.dcloud.net.cn/uniCloud/upgrade-center.html) \ No newline at end of file diff --git a/uni_modules/uni-upgrade-center-app/utils/call-check-version.ts b/uni_modules/uni-upgrade-center-app/utils/call-check-version.ts index 0ca97842246b40ad38ce3c695948a9d2670032fa..c14ce3d0065a8a2aa5f3b0558e8101d002cc6d55 100644 --- a/uni_modules/uni-upgrade-center-app/utils/call-check-version.ts +++ b/uni_modules/uni-upgrade-center-app/utils/call-check-version.ts @@ -29,25 +29,25 @@ export type UniUpgradeCenterResult = { min_uni_version : string | null // 升级 wgt 的最低 uni-app 版本 } -export default function (): Promise { +export default function () : Promise { // #ifdef APP return new Promise((resolve, reject) => { const systemInfo = uni.getSystemInfoSync() const appId = systemInfo.appId const appVersion = systemInfo.appVersion // #ifndef UNI-APP-X - if (plus.runtime.appid && plus.runtime.version) { - plus.runtime.getProperty(plus.runtime.appid, function (widgetInfo) { + if (typeof appId === 'string' && typeof appVersion === 'string' && appId.length > 0 && appVersion.length > 0) { + plus.runtime.getProperty(appId, function (widgetInfo) { if (widgetInfo.version) { let data = { action: 'checkVersion', - appid: plus.runtime.appid, - appVersion: plus.runtime.version, + appid: appId, + appVersion: appVersion, wgtVersion: widgetInfo.version } uniCloud.callFunction({ name: 'uni-upgrade-center', - data: data, + data, success: (e) => { resolve(e.result as UniUpgradeCenterResult) }, @@ -69,7 +69,7 @@ export default function (): Promise { action: 'checkVersion', appid: appId, appVersion: appVersion, - is_uniapp_x: true, + is_uniapp_x: true, wgtVersion: '0.0.0.0.0.1' } try { @@ -77,20 +77,20 @@ export default function (): Promise { name: 'uni-upgrade-center', data: data }).then(res => { - const code = res.result['code'] - if (['Int', 'Long', 'number'].includes(typeof code) && (code as number) < 0) { + const code = res.result['code'] + if (['Int', 'Long', 'number'].includes(typeof code) && (code as number) < 0) { reject({ code: res.result['code'], message: res.result['message'] }) - } else { - const result = JSON.parse(JSON.stringify(res.result)) as UniUpgradeCenterResult + } else { + const result = JSON.parse(JSON.stringify(res.result)) as UniUpgradeCenterResult resolve(result) } }).catch((err : any | null) => { const error = err as UniCloudError - if (error.errMsg == '未匹配到云函数[uni-upgrade-center]') - error.errMsg = '【uni-upgrade-center-app】未配置uni-upgrade-center,无法升级。参考: https://uniapp.dcloud.net.cn/uniCloud/upgrade-center.html' + if (error.errMsg == '未匹配到云函数[uni-upgrade-center]') + error.errMsg = '【uni-upgrade-center-app】未配置uni-upgrade-center,无法升级。参考: https://uniapp.dcloud.net.cn/uniCloud/upgrade-center.html' reject(error.errMsg) }) } catch (e) { @@ -103,10 +103,10 @@ export default function (): Promise { }) // #endif // #ifndef APP-PLUS - /* return new Promise((resolve, reject) => { + return new Promise((resolve, reject) => { reject({ message: '请在App中使用' }) - }) */ + }) // #endif } diff --git a/uni_modules/uni-upgrade-center-app/utils/check-update.ts b/uni_modules/uni-upgrade-center-app/utils/check-update.ts index 7adf0586bb105768a78e6f6dab1072137bc2baee..865abc84c08f24fefd2b148a92bf729b57104d56 100644 --- a/uni_modules/uni-upgrade-center-app/utils/check-update.ts +++ b/uni_modules/uni-upgrade-center-app/utils/check-update.ts @@ -1,26 +1,26 @@ import callCheckVersion, { UniUpgradeCenterResult } from "./call-check-version" // #ifdef UNI-APP-X import { ComponentPublicInstance } from 'vue' +import { openSchema } from './utils.uts' // #endif // 推荐再App.vue中使用 const PACKAGE_INFO_KEY = '__package_info__' + +// uni-app 项目无法从 vue 中导出 ComponentPublicInstance 类型,故使用条件编译 // #ifdef UNI-APP-X export default function (component : ComponentPublicInstance | null = null) : Promise { - // #endif - // #ifndef UNI-APP-X - export default function () : Promise { - // #endif - // #ifdef APP-PLUS - return new Promise((resolve, reject) => { - callCheckVersion().then(async (uniUpgradeCenterResult) => { - // NOTE uni-app x 3.96 解构有问题 - const code = uniUpgradeCenterResult.code - const message = uniUpgradeCenterResult.message - const url = uniUpgradeCenterResult.url // 安装包下载地址 - // const is_silently = uniUpgradeCenterResult.is_silently // 是否静默更新 - // const platform = uniUpgradeCenterResult.platform // 安装包平台 - // const type = uniUpgradeCenterResult.type // 安装包类型 +// #endif +// #ifndef UNI-APP-X +export default function () : Promise { +// #endif + // #ifdef APP-PLUS + return new Promise((resolve, reject) => { + callCheckVersion().then(async (uniUpgradeCenterResult) => { + // NOTE uni-app x 3.96 解构有问题 + const code = uniUpgradeCenterResult.code + const message = uniUpgradeCenterResult.message + const url = uniUpgradeCenterResult.url // 安装包下载地址 // 此处逻辑仅为示例,可自行编写 if (code > 0) { @@ -65,81 +65,29 @@ export default function (component : ComponentPublicInstance | null = null) : Pr // #endif } - // #ifdef UNI-APP-X - /** - * 使用 uni.showModal 升级 - */ - function updateUseModal(packageInfo : UniUpgradeCenterResult) : void { - const { - title, // 标题 - contents, // 升级内容 - is_mandatory, // 是否强制更新 - url, // 安装包下载地址 - } = packageInfo; - - let confirmText = '立即下载更新' - - return uni.showModal({ - title, - content: contents, - showCancel: !is_mandatory, - confirmText, - success: res => { - if (res.cancel) return; - - uni.showToast({ - title: '后台下载中……', - duration: 1000 - }); - - // wgt 和 安卓下载更新 - uni.downloadFile({ - url, - success: res => { - if (res.statusCode !== 200) { - console.error('下载安装包失败'); - return; - } - // 下载好直接安装,下次启动生效 - uni.installApk({ - filePath: res.tempFilePath, - success: () => { - uni.showModal({ - title: '安装成功请手动重启' - }); - }, - fail: err => { - uni.showModal({ - title: '更新失败', - content: err.message, - showCancel: false - }); - } - }); - } - }); - } - }); - } - // #endif - - // #ifndef UNI-APP-X - /** - * 使用 uni.showModal 升级 - */ - function updateUseModal(packageInfo : UniUpgradeCenterResult) : void { - const { - title, // 标题 - contents, // 升级内容 - is_mandatory, // 是否强制更新 - url, // 安装包下载地址 - platform, // 安装包平台 - type // 安装包类型 - } = packageInfo; - - let isWGT = type === 'wgt' - let isiOS = !isWGT ? platform.includes('iOS') : false; - let confirmText = isiOS ? '立即跳转更新' : '立即下载更新' +/** + * 使用 uni.showModal 升级 + */ +function updateUseModal(packageInfo : UniUpgradeCenterResult) : void { + // #ifdef APP + const { + title, // 标题 + contents, // 升级内容 + is_mandatory, // 是否强制更新 + url, // 安装包下载地址 + type, + platform + } = packageInfo; + + let isWGT = type === 'wgt' + let isiOS = !isWGT ? platform.includes('iOS') : false; + + // #ifndef UNI-APP-X + let confirmText = isiOS ? '立即跳转更新' : '立即下载更新' + // #endif + // #ifdef UNI-APP-X + let confirmText = '立即下载更新' + // #endif return uni.showModal({ title, @@ -149,54 +97,80 @@ export default function (component : ComponentPublicInstance | null = null) : Pr success: res => { if (res.cancel) return; - // 安装包下载 - if (isiOS) { - plus.runtime.openURL(url); - return; - } + if (isiOS) { + // iOS 平台跳转 AppStore + // #ifndef UNI-APP-X + plus.runtime.openURL(url); + // #endif + // #ifdef UNI-APP-X + openSchema(url) + // #endif + return; + } uni.showToast({ title: '后台下载中……', duration: 1000 }); - // wgt 和 安卓下载更新 - uni.downloadFile({ - url, - success: res => { - if (res.statusCode !== 200) { - console.error('下载安装包失败'); - return; - } - // 下载好直接安装,下次启动生效 - plus.runtime.install(res.tempFilePath, { - force: false - }, () => { - if (is_mandatory) { - //更新完重启app - plus.runtime.restart(); - return; - } - uni.showModal({ - title: '安装成功是否重启?', - success: res => { - if (res.confirm) { - //更新完重启app - plus.runtime.restart(); - } - } - }); - }, err => { - uni.showModal({ - title: '更新失败', - content: err - .message, - showCancel: false - }); - }); - } - }); - } - }); - } -// #endif + // wgt 和 安卓下载更新 + uni.downloadFile({ + url, + success: res => { + if (res.statusCode !== 200) { + console.error('下载安装包失败'); + return; + } + // 下载好直接安装,下次启动生效 + // uni-app x 项目没有 plus5+ 故使用条件编译 + // #ifndef UNI-APP-X + plus.runtime.install(res.tempFilePath, { + force: false + }, () => { + if (is_mandatory) { + //更新完重启app + plus.runtime.restart(); + return; + } + uni.showModal({ + title: '安装成功是否重启?', + success: res => { + if (res.confirm) { + //更新完重启app + plus.runtime.restart(); + } + } + }); + }, err => { + uni.showModal({ + title: '更新失败', + content: err + .message, + showCancel: false + }); + }); + // #endif + + // #ifdef UNI-APP-X + uni.installApk({ + filePath: res.tempFilePath, + success: () => { + uni.showModal({ + title: '安装成功请手动重启' + }); + }, + fail: err => { + uni.showModal({ + title: '更新失败', + content: err.message, + showCancel: false + }); + } + }); + // #endif + } + }); + } + }); + // #endif +}