From 086a5fd1fa622be22239a1f2ef396732ea82e4d6 Mon Sep 17 00:00:00 2001 From: scout <1134087124@qq.com> Date: Sat, 14 Sep 2024 11:38:03 +0800 Subject: [PATCH] addhotLpload --- App.vue | 115 +++++-- main.js | 1 + manifest.json | 4 +- package.json | 1 + pages.json | 64 ++-- pages/index/index.vue | 84 ++--- uni_modules/rt-uni-update/changelog.md | 97 ++++++ .../rt-uni-update/rt-uni-update.vue | 303 ++++++++++++++++++ .../rt-uni-update/js_sdk/silence-update.js | 31 ++ uni_modules/rt-uni-update/package.json | 80 +++++ uni_modules/rt-uni-update/readme.md | 192 +++++++++++ .../rt-uni-update/static/app_update_close.png | Bin 0 -> 2378 bytes uni_modules/rt-uni-update/static/bg_top.png | Bin 0 -> 7744 bytes 13 files changed, 870 insertions(+), 102 deletions(-) create mode 100644 package.json create mode 100644 uni_modules/rt-uni-update/changelog.md create mode 100644 uni_modules/rt-uni-update/components/rt-uni-update/rt-uni-update.vue create mode 100644 uni_modules/rt-uni-update/js_sdk/silence-update.js create mode 100644 uni_modules/rt-uni-update/package.json create mode 100644 uni_modules/rt-uni-update/readme.md create mode 100644 uni_modules/rt-uni-update/static/app_update_close.png create mode 100644 uni_modules/rt-uni-update/static/bg_top.png diff --git a/App.vue b/App.vue index bea28b2..1b918e9 100644 --- a/App.vue +++ b/App.vue @@ -1,40 +1,89 @@ diff --git a/main.js b/main.js index f624f57..1f9c1d3 100644 --- a/main.js +++ b/main.js @@ -3,6 +3,7 @@ import App from './App' // #ifndef VUE3 import Vue from 'vue' import './uni.promisify.adaptor' + Vue.config.productionTip = false App.mpType = 'app' const app = new Vue({ diff --git a/manifest.json b/manifest.json index 2dd4b0c..d4509aa 100644 --- a/manifest.json +++ b/manifest.json @@ -2,8 +2,8 @@ "name" : "oa考勤系统", "appid" : "__UNI__4796942", "description" : "", - "versionName" : "2.1.1", - "versionCode" : 211, + "versionName" : "2.1.4", + "versionCode" : 214, "transformPx" : false, /* 5+App特有相关 */ "app-plus" : { diff --git a/package.json b/package.json new file mode 100644 index 0000000..0967ef4 --- /dev/null +++ b/package.json @@ -0,0 +1 @@ +{} diff --git a/pages.json b/pages.json index 50daf09..d19caf1 100644 --- a/pages.json +++ b/pages.json @@ -1,28 +1,42 @@ { - "pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages - { - "path": "pages/index/index", - "style": { - "navigationBarTitleText": "uni-app", - "navigationStyle": "custom" - } - }, - { - "path" : "pages/networko/index", - "style" : - { - "navigationBarTitleText": "uni-app", - "navigationStyle": "custom" - } - } + "pages": [ + //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages + { + "path": "pages/index/index", + "style": { + "navigationBarTitleText": "uni-app", + "navigationStyle": "custom" + } + }, + { + "path": "pages/networko/index", + "style": { + "navigationBarTitleText": "uni-app", + "navigationStyle": "custom" + } + }, - - ], - "globalStyle": { - "navigationBarTextStyle": "black", - "navigationBarTitleText": "uni-app", - "navigationBarBackgroundColor": "#F8F8F8", - "backgroundColor": "#F8F8F8" - }, - "uniIdRouter": {} + { + "path": "uni_modules/rt-uni-update/components/rt-uni-update/rt-uni-update", + "style": { + "app-plus": { + "animationDuration": 200, + "animationType": "fade-in", + "background": "transparent", + "backgroundColorTop": "transparent", + "popGesture": "none", + "scrollIndicator": false, + "titleNView": false + }, + "disableScroll": true + } + } + ], + "globalStyle": { + "navigationBarTextStyle": "black", + "navigationBarTitleText": "uni-app", + "navigationBarBackgroundColor": "#F8F8F8", + "backgroundColor": "#F8F8F8" + }, + "uniIdRouter": {} } diff --git a/pages/index/index.vue b/pages/index/index.vue index bcb1d7d..7f9936c 100644 --- a/pages/index/index.vue +++ b/pages/index/index.vue @@ -8,51 +8,51 @@ import {onExit } from "@dcloudio/uni-app"; import { Communication } from '../../utils/communication.js'; const commun=new Communication() - import { - registerRequestPermissionTipsListener, - unregisterRequestPermissionTipsListener, - setRequestPermissionTips - } from "@/uni_modules/uni-registerRequestPermissionTips" +// import { +// registerRequestPermissionTipsListener, +// unregisterRequestPermissionTipsListener, +// setRequestPermissionTips +// } from "@/uni_modules/uni-registerRequestPermissionTips" - const PermissionTips = { - "android.permission.CAMERA": "

正在读取通讯录权限

通讯录权限不会获取任何信息,请注意", - "android.permission.READ_PHONE_STATE": "

正在读取网络状态权限

通讯录权限不会获取任何信息,请注意通讯录权限不会获取任何信息,请注意通讯录权限不会获取任何信息,请注意" - } -onExit(()=>{ - unregisterRequestPermissionTipsListener() -}) +// const PermissionTips = { +// "android.permission.CAMERA": "

正在读取通讯录权限

通讯录权限不会获取任何信息,请注意", +// "android.permission.READ_PHONE_STATE": "

正在读取网络状态权限

通讯录权限不会获取任何信息,请注意通讯录权限不会获取任何信息,请注意通讯录权限不会获取任何信息,请注意" +// } +// onExit(()=>{ +// unregisterRequestPermissionTipsListener() +// }) - const brand = uni.getSystemInfoSync().deviceBrand - setRequestPermissionTips(PermissionTips) - registerRequestPermissionTipsListener({ - onRequest: (e) => { - console.log('onRequest',e) - }, - onConfirm: (e) => { - commun.sendToH5('permission-application',{action:'open-permission',data:e}); - }, - onComplete: (e) => { - commun.sendToH5('permission-application',{action:'close-permission',data:e}); +// const brand = uni.getSystemInfoSync().deviceBrand +// setRequestPermissionTips(PermissionTips) +// registerRequestPermissionTipsListener({ +// onRequest: (e) => { +// console.log('onRequest',e) +// }, +// onConfirm: (e) => { +// commun.sendToH5('permission-application',{action:'open-permission',data:e}); +// }, +// onComplete: (e) => { +// commun.sendToH5('permission-application',{action:'close-permission',data:e}); - // 华为手机在权限禁止之后,再次申请权限不会出现权限申请框。此时应该引导用户去系统设置开启此权限,不应该频繁申请。 - if (brand.toLowerCase() === "huawei") { - const tips = {} - let hasDeniedPermission = false - for (let k in PermissionTips) { - if (e[k] !== "denied") { - tips[k] = PermissionTips[k] - } else { - hasDeniedPermission = true - } - } - setRequestPermissionTips(tips) // 更新弹框提醒,防止华为手机不出现权限申请框时权限提醒框闪烁的情况 - if (hasDeniedPermission) - uni.showModal({ - content: "权限已经被拒绝,请前往设置中开启" - }) - } - } - }) +// // 华为手机在权限禁止之后,再次申请权限不会出现权限申请框。此时应该引导用户去系统设置开启此权限,不应该频繁申请。 +// if (brand.toLowerCase() === "huawei") { +// const tips = {} +// let hasDeniedPermission = false +// for (let k in PermissionTips) { +// if (e[k] !== "denied") { +// tips[k] = PermissionTips[k] +// } else { +// hasDeniedPermission = true +// } +// } +// setRequestPermissionTips(tips) // 更新弹框提醒,防止华为手机不出现权限申请框时权限提醒框闪烁的情况 +// if (hasDeniedPermission) +// uni.showModal({ +// content: "权限已经被拒绝,请前往设置中开启" +// }) +// } +// } +// }) function initializeWebView() { const currentWebview = getCurrentPages().pop().$getAppWebview() commun.setWebView(currentWebview.children()[0]) diff --git a/uni_modules/rt-uni-update/changelog.md b/uni_modules/rt-uni-update/changelog.md new file mode 100644 index 0000000..df869ce --- /dev/null +++ b/uni_modules/rt-uni-update/changelog.md @@ -0,0 +1,97 @@ +## 1.5.2(2023-09-08) +优化文档 +## 1.5.1(2023-05-26) +优化文档 +## 1.5.0(2023-05-23) +优化文档 +## 1.4.9(2023-05-23) +文档新增后台版本管理示例图 +## 1.4.8(2023-05-23) +优化当前版本显示 +## 1.4.7(2023-05-23) +新增当前运行版本名称和新版本名称显示 +## 1.4.6(2023-05-22) +新增显示安装包大小 +## 1.4.5(2023-04-27) +优化页面不透明 +## 1.4.4(2023-04-25) +新增pages_init.json自动注册页面 +## 1.4.3(2023-04-25) +修改app下载链接 +## 1.4.2(2023-04-25) +优化 +## 1.4.1(2023-04-15) +优化bug +## 1.4.0(2023-04-14) +删除无用代码 +## 1.3.9(2023-04-14) +优化 +## 1.3.8(2023-04-03) +优化文档 +## 1.3.7(2023-03-23) +优化文档 +## 1.3.6(2023-03-23) +优化文档 +## 1.3.5(2023-03-08) +新增常见问题 +## 1.3.4(2023-03-07) +解决应用切换到后台再次打开更新弹窗叠加多个的问题 +## 1.3.3(2023-03-02) +优化提示文档 +## 1.3.2(2023-02-02) +优化部分wgt包无法安装的提示 +## 1.3.1(2023-01-12) +修改示例下载文件地址 +## 1.3.0(2022-11-17) +兼容低版本安卓手机,用户拒绝安装后,去掉自动重启,优化体验 +## 1.2.9(2022-11-14) +优化插件 +## 1.2.8(2022-11-14) +优化整包更新用户体验 +## 1.2.7(2022-11-14) +修复apk整包更新时,点击拒绝安装,更新进度还在的bug +## 1.2.6(2022-10-17) +优化问题汇总 +## 1.2.5(2022-10-17) +常见问题优化 +## 1.2.4(2022-09-21) +文档新增常见问题汇总,方便更快的解决问题 +## 1.2.3(2022-09-21) +文档新增常见问题汇总,方便更快的解决问题 +## 1.2.2(2022-09-21) +文档新增常见问题汇总,方便更快的解决问题 +## 1.2.1(2022-09-21) +文档新增常见问题汇总,方便更快的解决问题 +## 1.2.0(2022-08-03) +优化插件,wgt升级重启,整包升级不重启 +## 1.1.9(2022-08-01) +新增弹出一个合并页面路由的pages.json修改界面。插件使用者点击确认按钮即可完成插件页面向项目pages.json的注册。HBuilderX 3.5.0+支持 +## 1.1.8(2022-07-25) +1、静默更新后提示用户重启应用,以解决样式错乱的问题 +2、跳转应用市场下载后,解决更新提示弹窗一直叠加的问题 +## 1.1.7(2022-07-22) +优化示例代码 +## 1.1.6(2022-07-22) +优化文档 +## 1.1.5(2022-07-19) +优化文档 +## 1.1.4(2022-07-19) +优化文档 +## 1.1.3(2022-07-19) +优化文档 +## 1.1.2(2022-07-18) +优化wgt更新文档 +## 1.1.1(2022-07-17) +新增wgt包静默更新 +## 1.1.0(2022-05-17) +优化readme文档 +## 1.0.9(2022-05-14) +优化 +## 1.0.8(2022-05-05) +修复图片不显示的bug +## 1.0.7(2022-01-19) +1.0.7 优化readme文档 +## 1.0.6(2022-01-19) +正式支持uni_modules +## 1.0.5(2022-01-19) +测试支持uni_models diff --git a/uni_modules/rt-uni-update/components/rt-uni-update/rt-uni-update.vue b/uni_modules/rt-uni-update/components/rt-uni-update/rt-uni-update.vue new file mode 100644 index 0000000..e88c8a5 --- /dev/null +++ b/uni_modules/rt-uni-update/components/rt-uni-update/rt-uni-update.vue @@ -0,0 +1,303 @@ + + + + + diff --git a/uni_modules/rt-uni-update/js_sdk/silence-update.js b/uni_modules/rt-uni-update/js_sdk/silence-update.js new file mode 100644 index 0000000..90c1ff9 --- /dev/null +++ b/uni_modules/rt-uni-update/js_sdk/silence-update.js @@ -0,0 +1,31 @@ +export default function silenceUpdate(url) { + uni.downloadFile({ + url, + success: res => { + if (res.statusCode === 200) { + plus.runtime.install( + res.tempFilePath, { + force: true //true表示强制安装,不进行版本号的校验;false则需要版本号校验, + }, + function() { + uni.showModal({ + title: '更新提示', + content: '新版本已经准备好,请重启应用', + showCancel: false, + success: function(res) { + if (res.confirm) { + // console.log('用户点击确定'); + plus.runtime.restart() + } + } + }); + // console.log('install success...'); + }, + function(e) { + console.error('install fail...'); + } + ); + } + } + }); +} diff --git a/uni_modules/rt-uni-update/package.json b/uni_modules/rt-uni-update/package.json new file mode 100644 index 0000000..9f19ced --- /dev/null +++ b/uni_modules/rt-uni-update/package.json @@ -0,0 +1,80 @@ +{ + "id": "rt-uni-update", + "displayName": "app升级整包更新和热更新支持vue3 支持打开安卓、苹果市场,wgt静默更新", + "version": "1.5.2", + "description": "app升级、整包更新和热更新组件 支持vue3 支持打开安卓、苹果应用市场,支持wgt静默更新,无感知,支持覆盖原生tabar,原生导航栏", + "keywords": [ + "整包更新", + "热更新", + "vue3", + "静默更新", + "app更新升级" +], + "repository": "", +"engines": { + }, +"dcloudext": { + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "", + "type": "component-vue" + }, + "uni_modules": { + "dependencies": [], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "Vue": { + "vue2": "y", + "vue3": "y" + }, + "App": { + "app-vue": "y", + "app-nvue": "y" + }, + "H5-mobile": { + "Safari": "u", + "Android Browser": "u", + "微信浏览器(Android)": "u", + "QQ浏览器(Android)": "u" + }, + "H5-pc": { + "Chrome": "u", + "IE": "u", + "Edge": "u", + "Firefox": "u", + "Safari": "u" + }, + "小程序": { + "微信": "u", + "阿里": "u", + "百度": "u", + "字节跳动": "u", + "QQ": "u" + }, + "快应用": { + "华为": "u", + "联盟": "u" + } + } + } + } +} \ No newline at end of file diff --git a/uni_modules/rt-uni-update/readme.md b/uni_modules/rt-uni-update/readme.md new file mode 100644 index 0000000..fc8649d --- /dev/null +++ b/uni_modules/rt-uni-update/readme.md @@ -0,0 +1,192 @@ +## 整包更新和热更新组件 支持vue3 支持打开安卓、苹果应用市场,支持wgt静默更新 + + - ui图是采用uniapp官方更新组件的ui,如不满足需要,可自行替换 + - 一键式检查更新,同时支持整包升级与wgt资源包更新 支持打开安卓自带的应用市场和苹果appstore + - 好看、实用、可自定义的客户端提示框 + - 支持强制更新,无法退出 + - 支持静默更新,下次启动后更新的内容自动生效 + - 支持覆盖原生tabar,原生导航栏 + +## 安装指引 + +1. 在插件市场打开本插件页面,在右侧点击`使用 HBuilderX 导入插件`,选择要导入的项目点击确定(建议使用uni_modules版本 非uni_modules版本不在维护,有需要自行修改) + +2. 在`pages.json`中添加页面路径。注意:一定不要设置为pages.json中第一项(在1.1.9版本新增弹出一个合并页面路由的pages.json修改界面。点击确认按钮即可完成插件页面向项目pages.json的注册。HBuilderX 3.5.0+支持,无需手动添加) + +``` +"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 + + } + } + } +] +``` + +3. 查看显示效果 (注意:这里只是查看显示效果,具体代码需要按照下面的项目使用说明编写) + +``` + +// App.vue的onShow中查看效果 如果无法跳转 请在`pages.json`中添加页面路径,参照第二步 + +uni.navigateTo({ + url: '/uni_modules/rt-uni-update/components/rt-uni-update/rt-uni-update' +}); + +``` + + +## 前言,一般来说,后台都需要有一个app的版本管理系统(可参考下图) + +![app的版本管理系统](https://img-cdn-aliyun.dcloud.net.cn/stream/plugin_screens/d7898110-7905-11ec-a3c8-0f6ace22f6cc_3.png?image_process=quality,q_70/format,webp&v=1684809490) +![app的版本管理系统](https://img-cdn-aliyun.dcloud.net.cn/stream/plugin_screens/d7898110-7905-11ec-a3c8-0f6ace22f6cc_4.png?image_process=quality,q_70/format,webp&v=1684809494) + + +## 项目使用说明 最重要!!! + +- 注意!!!后端返回数据要求 字段如下 (如果后端字段不一样,请在跳转更新页时手动赋值,示例见下面代码) + +``` +data:{ + // 版本更新内容 支持
自动换行 + describe: '1. 修复已知问题
+ 2. 优化用户体验', + edition_url: '', //apk、wgt包下载地址或者应用市场地址 安卓应用市场 market://details?id=xxxx 苹果store itms-apps://itunes.apple.com/cn/app/xxxxxx + 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代表是 +} + +// 如果后端返回的字段和上面不一致,请在前端手动赋值(示例) + + data.edition_url = res.data.editionUrl + data.edition_force = res.data.editionForce + data.package_type = res.data.packageType + data.xxx = res.data.xxx + + +``` + + +## 后端注意!!! + +edition_number传这个参数是为了解决部分用户app长期不使用,第一次打开服务器查到的版本是最新的是wgt包,但是之前app有过整包更新,如果直接更新最新wgt的话,会出现以前的整包添加的原生模块或者安卓权限无法使用,所以后端查询版本必须返回大于当前edition_number版本的最新的整包apk地址或者是应用市场地址,如果没有大于edition_number的整包,就返回最新的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 + 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 { + //跳转更新页面 (注意!!!如果pages.json第一页的代码里有一打开就跳转其他页面的操作,下面这行代码最好写在setTimeout里面设置延时3到5秒再执行) + uni.navigateTo({ + url: '/uni_modules/rt-uni-update/components/rt-uni-update/rt-uni-update?obj=' + + JSON.stringify(res.data.data) + }); + } + } else { + + // 如果是手动检查新版本 需开启以下注释 + /* uni.showModal({ + title: '提示', + content: '已是最新版本', + showCancel: false + }) */ + } + } + + + }) + + }); + + //#endif + + + +``` + +# 常见问题汇总!!! + +# 热更新制作wgt包的方法:1、修改manifest.json版本名称和版本号,必须大于当前版本。2、点击菜单的发行——原生App-制作应用wgt包 + +# app上传地址:个人建议开通unicloud的阿里云按量付费,方便、便宜,apk或者wgt包直接上传到云存储就行。 + +## 1、调试请打包自定义基座测试,否则uni.getSystemInfoSync().platform获取到的可能不是android或者ios,会导致无法跳转更新页 + +## 2、进度条不显示,但可以正常安装,原因:99%的情况是因为下载链接为内网链接,内网链接无法监听下载进度,请更换为外网链接 + +## 3、进度条显示,下载apk完成后,安卓不会自动弹出安装页面,原因:可能是离线打包未添加安卓安装权限,请添加以下权限或者使用云打包 + +``` + + +``` +``` + +``` + +## 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](https://ask.dcloud.net.cn/question/164141) + +## 12、跳转更新页后无法获取参数,可能是使用了uni-simple-router等第三方路由插件,解决办法:通过eventChannel.$emit等方式传参,在插件里接收赋值 + + +有鼓励,更有动力,如果您认为这个插件帮到了您的开发工作,麻烦给个五星好评鼓励一下,有能力的也可以小小赞赏一下,感谢支持。 + + + + +## 如有问题,请加qq 965969604 \ No newline at end of file diff --git a/uni_modules/rt-uni-update/static/app_update_close.png b/uni_modules/rt-uni-update/static/app_update_close.png new file mode 100644 index 0000000000000000000000000000000000000000..7fe1deca02877608aa32b6a97c161b234cef44b9 GIT binary patch literal 2378 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 Kj0=pML;nXZ+_@nD literal 0 HcmV?d00001