uniapp实现App弹窗更新升级(完整版)

您所在的位置:网站首页 app推送功能怎么开启 uniapp实现App弹窗更新升级(完整版)

uniapp实现App弹窗更新升级(完整版)

2024-07-16 16:28:22| 来源: 网络整理| 查看: 265

对于没有做过App升级更新的伙伴来说,起步无非是困难重重的。 原理说来简单:对比版本号,版本号低的或相等的,不作为;版本号高的,弹窗、升级。 但是实际上双手放在键盘上,无从下手。 笔者最开始也是这个状态,靠的是一步步摸索、调试才有了让领导较为满意的结果,虽然前前后后修改了几个版本,但总算松了口气。 效果及代码展示如下: 在这里插入图片描述 在这里插入图片描述

// App.js import config from '@/utils/config.js'; import checkappupdate from '@/utils/checkappupdate.js'; //版本检测 let appType = plus.os.name.toLocaleLowerCase() let versions = plus.runtime.version.split('.').join('') axios({ url: '后端接口', params: { // '参数' } }).then(res => { let newversion = res.data.codeversion if(Number(newversion) > Number(versions)) { checkappupdate.check({ title:"检测到有新版本!", api: config.base_url + '后端接口' }) } }) // checkappupdate.js import config from '@/utils/config.js'; const $iconUrl = "/static/image/matser/mine/rowtos.png"; const $closeUrl = "/static/image/matser/mine/but_del.png"; const $gotoUrl = "/static/image/matser/mine/but_002.png"; const $mainColor = "#FF5B78"; function check(param = {}) { if (!param.api) return false; plus.runtime.getProperty(plus.runtime.appid, (widgetInfo) => { let platform = plus.os.name.toLocaleLowerCase() uni.request({ url: param['api'], data: { apptype: platform, version: widgetInfo.version }, header: { 'content-type': 'application/x-www-form-urlencoded' }, method: 'POST', dataType: 'json', success: (result) => { let data = result.data.data ? result.data.data : null if (data && result.data.code === 1 && data.downloadurl_sign) { if(/\.wgt/i.test(data.downloadurl_sign) || (platform == 'android' && /\.apk/i.test(data.downloadurl_sign))){ // 如果是热更新 wgt 或 android平台下apk let datas = { versionInfo: data.content, versionName: data.newversion, updateType: data.enforce == 0 ? "solicit" : "forcibly", //forcibly强制立即升级 solicit非强制升级 downloadurl_sign: data.downloadurl_sign } updatePopup(datas, '') return } if (platform == 'ios') { // 如果是ios,则跳转到appstore plus.runtime.openURL(result.data.data.downloadurl_sign) return; } } }, fail: (res) => { console.log('fail', res) } }) }); } function updatePopup(data, callback) { // 弹窗遮罩层 let maskLayer = new plus.nativeObj.View("maskLayer", { //先创建遮罩层 top: '0px', left: '0px', height: '100%', width: '100%', backgroundColor: 'rgba(0,0,0,0.5)' }); // 以下为计算菜单的nview绘制布局,为固定算法,使用者无关关心 const screenWidth = plus.screen.resolutionWidth; const screenHeight = plus.screen.resolutionHeight; //弹窗容器宽度 const popupViewWidth = screenWidth * 0.7; // 弹窗容器的Padding const viewContentPadding = 20; // 弹窗容器的宽度 const viewContentWidth = parseInt(popupViewWidth - (viewContentPadding * 2)); // 描述的列表 const descriptionList = drawtext(data.versionInfo, viewContentWidth); // 弹窗容器高度 let popupViewHeight = 80 + 20 + 20 + 90 + 10 + 60; let popupViewContentList = [{ src: $iconUrl, id: "logo", tag: "img", position: { top: "0px", left: "0px", width: popupViewWidth + 'px', height: (screenHeight / 5.5) + "px", } }, { tag: 'font', id: 'title', text: "发现新版本", textStyles: { size: '22px', color: "#5F94F9", // weight: "bold", whiteSpace: "normal" }, position: { top: '150px', left: viewContentPadding + "px", width: viewContentWidth - viewContentPadding * 2 + "px", height: "30px", } }]; popupViewContentList.push({ tag: 'rect', //绘制版本号 rectStyles:{ radius: "3px", color: "#5F94F9" }, position:{ top: '160px', left: (viewContentWidth / 2) + (viewContentWidth / 4) + 10 + "px", width: 50 + "px", height: "15px" } }) popupViewContentList.push({ tag: 'font', id: 'versionText', text: 'V' + data.versionName, textStyles: { size: '14px', color: "#FFF", lineSpacing: "0%", }, position: { top: '160px', left: (viewContentWidth / 2) + (viewContentWidth / 4) + 10 + "px", width: 50 + "px", height: "15px" } }) const textHeight = 18; let contentTop = 190; descriptionList.forEach((item,index) => { if(index > 0){ popupViewHeight += textHeight; contentTop += textHeight; } popupViewContentList.push({ tag: 'font', id: 'content' + index + 1, text: item.content, textStyles: { size: '15px', color: "#666", lineSpacing: "50%", align: "left" }, position: { top: contentTop + "px", left: viewContentPadding + "px", width: viewContentWidth + "px", height: textHeight + "px", } }); if(item.type == "break"){ contentTop += 10; popupViewHeight += 10; } }); if(data.updateType == "forcibly"){ popupViewContentList.push({ // 立即升级图片按钮 src: $gotoUrl, id: "gotos", tag: "img", position: { bottom: viewContentPadding + 'px', left: (viewContentPadding * 2) + "px", width: (viewContentWidth - viewContentPadding * 2) + "px", height: "40px" } }) } else { popupViewContentList.push({ // 立即升级图片按钮 src: $gotoUrl, id: "gotos", tag: "img", position: { bottom: viewContentPadding + 'px', left: (viewContentPadding * 2) + "px", width: (viewContentWidth - viewContentPadding * 2) + "px", height: "40px" } }) } // 弹窗内容 let popupView = new plus.nativeObj.View("popupView", { //创建底部图标菜单 tag: "rect", top: (screenHeight - popupViewHeight) / 2 + "px", left: '15%', height: popupViewHeight + "px", width: "70%" }); // 绘制白色背景 popupView.drawRect({ color: "#FFFFFF", radius: "8px" }, { top: "40px", height: popupViewHeight - 40 + "px", }); popupView.draw(popupViewContentList); // 绘制关闭按钮 const errViewWidth = screenWidth * 0.8; let errViewHeight = 80 + 20 + 20 + 90 + 10 + 60; let errTop = (screenHeight - errViewHeight) / 3.3 + "px" let errView = new plus.nativeObj.View('errView', {top: errTop, left: errViewWidth, height: '50px', width: '100%'}, [{ tag: 'img', id: 'img',src: $closeUrl, position: {top: '0px', left: '0px', width: '50px', height: '50px'}, }], ); popupView.addEventListener("click", function(e) { let maxTop = popupViewHeight - viewContentPadding; let maxLeft = popupViewWidth - viewContentPadding; let buttonWidth = (viewContentWidth - viewContentPadding) / 2; if (e.clientY > maxTop - 30 && e.clientY maskLayer.hide(); popupView.hide(); errView.hide(); newUpdateDownload(data) } } }); errView.addEventListener("click", function() { //处理点击关闭按钮点击 maskLayer.hide(); popupView.hide(); errView.hide(); }); // 显示弹窗 maskLayer.show(); popupView.show(); if(data.updateType == "solicit"){ // 点击遮罩层 errView.show(); maskLayer.addEventListener("click", function() { //处理遮罩层点击 maskLayer.hide(); popupView.hide(); errView.hide(); }); } else { errView.hide(); } } // 文字换行 function drawtext(text, maxWidth) { let textArr = text.split(""); let len = textArr.length; // 上个节点 let previousNode = 0; // 记录节点宽度 let nodeWidth = 0; // 文本换行数组 let rowText = []; // 如果是字母,侧保存长度 let letterWidth = 0; // 汉字宽度 let chineseWidth = 14; // otherFont宽度 let otherWidth = 7; for (let i = 0; i if(letterWidth > 0){ if(nodeWidth + chineseWidth + letterWidth * otherWidth > maxWidth){ rowText.push({ type: "text", content: text.substring(previousNode, i) }); previousNode = i; nodeWidth = chineseWidth; letterWidth = 0; } else { nodeWidth += chineseWidth + letterWidth * otherWidth; letterWidth = 0; } } else { if(nodeWidth + chineseWidth > maxWidth){ rowText.push({ type: "text", content: text.substring(previousNode, i) }); previousNode = i; nodeWidth = chineseWidth; }else{ nodeWidth += chineseWidth; } } } else { if(/\n/g.test(textArr[i])){ rowText.push({ type: "break", content: text.substring(previousNode, i) }); previousNode = i + 1; nodeWidth = 0; letterWidth = 0; }else if(textArr[i] == "\\" && textArr[i + 1] == "n"){ rowText.push({ type: "break", content: text.substring(previousNode, i) }); previousNode = i + 2; nodeWidth = 0; letterWidth = 0; }else if(/[a-zA-Z0-9]/g.test(textArr[i])){ letterWidth += 1; if(nodeWidth + letterWidth * otherWidth > maxWidth){ rowText.push({ type: "text", content: text.substring(previousNode, i + 1 - letterWidth) }); previousNode = i + 1 - letterWidth; nodeWidth = letterWidth * otherWidth; letterWidth = 0; } } else{ if(nodeWidth + otherWidth > maxWidth){ rowText.push({ type: "text", content: text.substring(previousNode, i) }); previousNode = i; nodeWidth = otherWidth; }else{ nodeWidth += otherWidth; } } } } if (previousNode type: "text", content: text.substring(previousNode, len) }); } return rowText; } function downloadPopupDrawing(data){ // 以下为计算菜单的nview绘制布局,为固定算法,使用者无关关心 const screenWidth = plus.screen.resolutionWidth; const screenHeight = plus.screen.resolutionHeight; //弹窗容器宽度 const popupViewWidth = screenWidth * 0.7; // 弹窗容器的Padding const viewContentPadding = 20; // 弹窗容器的宽度 const viewContentWidth = popupViewWidth - (viewContentPadding * 2); // 弹窗容器高度 let popupViewHeight = viewContentPadding * 3 + 60; let progressTip = data.progressTip || "准备下载..."; let contentText = data.contentText || "正在为您更新,请耐心等待"; let elementList = [ { tag: 'rect', //背景色 color: '#FFFFFF', rectStyles:{ radius: "8px" } }, { tag: 'font', id: 'title', text: "升级APP", textStyles: { size: '16px', color: "#333", weight: "bold", verticalAlign: "middle", whiteSpace: "normal" }, position: { top: viewContentPadding + 'px', height: "30px", } }, { tag: 'font', id: 'content', text: contentText, textStyles: { size: '14px', color: "#333", verticalAlign: "middle", whiteSpace: "normal" }, position: { top: viewContentPadding * 2 + 30 + 'px', height: "20px", } } ]; // 是否有进度条 if(data.progress){ popupViewHeight += viewContentPadding + 40; elementList = elementList.concat([ { tag: 'font', id: 'progressValue', text: progressTip, textStyles: { size: '14px', color: $mainColor, whiteSpace: "normal" }, position: { top: viewContentPadding * 4 + 20 + 'px', height: "30px" } }, { tag: 'rect', //绘制进度条背景 id: 'progressBg', rectStyles:{ radius: "4px", borderColor: $mainColor, borderWidth: "1px", }, position:{ top: viewContentPadding * 4 + 60 + 'px', left: viewContentPadding + "px", width: viewContentWidth + "px", height: "8px" } }, ]); } if (data.buttonNum == 2) { popupViewHeight += viewContentPadding + 30; elementList = elementList.concat([ { tag: 'rect', //绘制底边按钮 rectStyles:{ radius: "3px", borderColor: "#f1f1f1", borderWidth: "1px", }, position:{ bottom: viewContentPadding + 'px', left: viewContentPadding + "px", width: (viewContentWidth - viewContentPadding) / 2 + "px", height: "30px" } }, { tag: 'rect', //绘制底边按钮 rectStyles:{ radius: "3px", color: '#ff00ff' }, position:{ bottom: viewContentPadding + 'px', left: ((viewContentWidth - viewContentPadding) / 2 + viewContentPadding * 2) + "px", width: (viewContentWidth - viewContentPadding) / 2 + "px", height: "30px" } }, { tag: 'font', id: 'cancelText', text: "取消下载", textStyles: { size: '14px', color: "#666", lineSpacing: "0%", whiteSpace: "normal" }, position: { bottom: viewContentPadding + 'px', left: viewContentPadding + "px", width: (viewContentWidth - viewContentPadding) / 2 + "px", height: "30px", } }, { tag: 'font', id: 'confirmText', text: "后台下载", textStyles: { size: '14px', color: "#FFF", lineSpacing: "0%", whiteSpace: "normal" }, position: { bottom: viewContentPadding + 'px', left: ((viewContentWidth - viewContentPadding) / 2 + viewContentPadding * 2) + "px", width: (viewContentWidth - viewContentPadding) / 2 + "px", height: "30px", } } ]); } if (data.buttonNum == 1) { popupViewHeight += viewContentPadding + 40; elementList = elementList.concat([ { tag: 'rect', //绘制底边按钮 rectStyles:{ radius: "6px", color: '#ff00ff' }, position:{ bottom: viewContentPadding + 'px', left: viewContentPadding + "px", width: viewContentWidth + "px", height: "40px" } }, { tag: 'font', id: 'confirmText', text: "关闭", textStyles: { size: '14px', color: "#FFF", lineSpacing: "0%", }, position: { bottom: viewContentPadding + 'px', left: viewContentPadding + "px", width: viewContentWidth + "px", height: "40px" } } ]); } return { popupViewHeight:popupViewHeight, popupViewWidth:popupViewWidth, screenHeight:screenHeight, viewContentWidth:viewContentWidth, viewContentPadding:viewContentPadding, elementList: elementList }; } function downloadPopup(data) { // 弹窗遮罩层 let maskLayer = new plus.nativeObj.View("maskLayer", { //先创建遮罩层 top: '0px', left: '0px', height: '100%', width: '100%', backgroundColor: 'rgba(0,0,0,0.5)' }); let popupViewData = downloadPopupDrawing(data); // 弹窗内容 let popupView = new plus.nativeObj.View("popupView", { //创建底部图标菜单 tag: "rect", top: (popupViewData.screenHeight - popupViewData.popupViewHeight) / 2 + "px", left: '15%', height: popupViewData.popupViewHeight + "px", width: "70%", }); let progressValue = 0; let progressTip = 0; let contentText = 0; let buttonNum = 2; if(data.buttonNum >= 0){ buttonNum = data.buttonNum; } popupView.draw(popupViewData.elementList); let callbackData = { change: function(res) { let progressElement = []; if(res.progressValue){ progressValue = res.progressValue; // 绘制进度条 progressElement.push({ tag: 'rect', //绘制进度条背景 id: 'progressValueBg', rectStyles:{ radius: "4px", color: $mainColor }, position:{ top: popupViewData.viewContentPadding * 4 + 60 + 'px', left: popupViewData.viewContentPadding + "px", width: popupViewData.viewContentWidth * (res.progressValue / 100) + "px", height: "8px" } }); } if(res.progressTip){ progressTip = res.progressTip; progressElement.push({ tag: 'font', id: 'progressValue', text: res.progressTip, textStyles: { size: '14px', color: $mainColor, whiteSpace: "normal" }, position: { top: popupViewData.viewContentPadding * 4 + 20 + 'px', height: "30px" } }); } if(res.contentText){ contentText = res.contentText; progressElement.push({ tag: 'font', id: 'content', text: res.contentText, textStyles: { size: '16px', color: "#333", whiteSpace: "normal" }, position: { top: popupViewData.viewContentPadding * 2 + 30 + 'px', height: "30px", } }); } if(res.buttonNum >= 0 && buttonNum != res.buttonNum){ buttonNum = res.buttonNum; popupView.reset(); popupViewData = downloadPopupDrawing(Object.assign({ progressValue:progressValue, progressTip:progressTip, contentText:contentText, },res)); let newElement = []; popupViewData.elementList.map((item,index) => { let have = false; progressElement.forEach((childItem,childIndex) => { if(item.id == childItem.id){ have = true; } }); if(!have){ newElement.push(item); } }); progressElement = newElement.concat(progressElement); popupView.setStyle({ tag: "rect", top: (popupViewData.screenHeight - popupViewData.popupViewHeight) / 2 + "px", left: '15%', height: popupViewData.popupViewHeight + "px", width: "70%", }); popupView.draw(progressElement); }else{ popupView.draw(progressElement); } }, cancel: function() { maskLayer.hide(); popupView.hide(); } } popupView.addEventListener("click", function(e) { let maxTop = popupViewData.popupViewHeight - popupViewData.viewContentPadding; let maxLeft = popupViewData.popupViewWidth - popupViewData.viewContentPadding; if (e.clientY > maxTop - 40 && e.clientY // 单按钮 if (e.clientX > popupViewData.viewContentPadding && e.clientX // 双按钮 let buttonWidth = (popupViewData.viewContentWidth - popupViewData.viewContentPadding) / 2; if (e.clientX > popupViewData.viewContentPadding && e.clientX maskLayer.hide(); popupView.hide(); } } } }); // 显示弹窗 maskLayer.show(); popupView.show(); // 改变进度条 return callbackData; } // 新的下载 function newUpdateDownload(data) { if (data.shichang === 1 && /\.apk/i.test(data.downloadurl_sign)) { //去应用市场更新 plus.runtime.openURL(data.shichangurl); plus.runtime.quit(); } else { // 开始下载 // 创建下载任务 let dtask; let popupData = { progress: true, buttonNum: 0 //按钮的显示 0 ==> 无按钮,1 ==> 关闭按钮,2 ==> 取消下载和后台下载按钮 }; let lastProgressValue = 0; let popupObj = downloadPopup(popupData); dtask = plus.downloader.createDownload(data.downloadurl_sign, { filename: "_downloads/" }, function(download, status) { if (status == 200) { popupObj.change({ progressValue: 100, progressTip:"正在安装文件...", progress: true, buttonNum: 0 }); plus.runtime.install(download.filename, {}, function() { popupObj.change({ contentText: "应用资源下载完成!", buttonNum: 1, progress: false }); }, function(e) { popupObj.cancel(); plus.nativeUI.alert("安装文件失败[" + e.code + "]:" + e.message); }); } else { popupObj.change({ contentText: "文件下载失败...", buttonNum: 1, progress: false }); } }); dtask.start(); dtask.addEventListener("statechanged", function(task, status) { switch (task.state) { case 1: // 开始 popupObj.change({ progressValue:0, progressTip:"准备下载...", progress: true }); break; case 2: // 已连接到服务器 popupObj.change({ progressValue:0, progressTip:"开始下载...", progress: true }); break; case 3: const progress = parseInt(task.downloadedSize / task.totalSize * 100); if(progress - lastProgressValue >= 2){ lastProgressValue = progress; popupObj.change({ progressValue:progress, progressTip: "已下载" + progress + "%", progress: true }); } break; } }); popupObj.cancelDownload = function(){ dtask && dtask.abort(); uni.showToast({ title: "已取消下载", icon:"none" }); } // 重启APP popupObj.reboot = function(){ plus.runtime.restart(); } } } export default { check }

5+的样式好难调,如果有vue版的就更好了;以上内容适用于Android;ios的是跳转到store,还没测过,请自行调试。

文章参考来自插件市场,感谢两位作者 https://ext.dcloud.net.cn/plugin?id=2144 https://ext.dcloud.net.cn/plugin?id=1643



【本文地址】

公司简介

联系我们

今日新闻


点击排行

实验室常用的仪器、试剂和
说到实验室常用到的东西,主要就分为仪器、试剂和耗
不用再找了,全球10大实验
01、赛默飞世尔科技(热电)Thermo Fisher Scientif
三代水柜的量产巅峰T-72坦
作者:寞寒最近,西边闹腾挺大,本来小寞以为忙完这
通风柜跟实验室通风系统有
说到通风柜跟实验室通风,不少人都纠结二者到底是不
集消毒杀菌、烘干收纳为一
厨房是家里细菌较多的地方,潮湿的环境、没有完全密
实验室设备之全钢实验台如
全钢实验台是实验室家具中较为重要的家具之一,很多

推荐新闻


图片新闻

实验室药品柜的特性有哪些
实验室药品柜是实验室家具的重要组成部分之一,主要
小学科学实验中有哪些教学
计算机 计算器 一般 打孔器 打气筒 仪器车 显微镜
实验室各种仪器原理动图讲
1.紫外分光光谱UV分析原理:吸收紫外光能量,引起分
高中化学常见仪器及实验装
1、可加热仪器:2、计量仪器:(1)仪器A的名称:量
微生物操作主要设备和器具
今天盘点一下微生物操作主要设备和器具,别嫌我啰嗦
浅谈通风柜使用基本常识
 众所周知,通风柜功能中最主要的就是排气功能。在

专题文章

    CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭