苏州晴天婚车 發表於 2020-8-9 17:14:00

uni-app版本更新(二)

<p>APPUpdate.js</p>
<div class="cnblogs_Highlighter">
<pre class="brush:javascript;gutter:true;">// #ifdef APP-PLUS
import $http from '@/config/requestConfig';
const platform = uni.getSystemInfoSync().platform;
// 主颜色
const $mainColor = "FF5B78";
// 弹窗图标url
const $iconUrl = "/static/ic_ar.png";

// 获取当前应用的版本号
export const getCurrentNo = function(callback) {
        // 获取本地应用资源版本号
        plus.runtime.getProperty(plus.runtime.appid, function(inf) {
                callback &amp;&amp; callback({
                        versionCode: inf.version.replace(/\./g, ""),
                        version: inf.version
                });
        });
}
// 发起ajax请求获取服务端版本号
export const getServerNo = function(version,isPrompt = false, callback) {
        let httpData = {
                version:version
        };
        if (platform == "android") {
                httpData.type = 1101;
        } else {
                httpData.type = 1102;
        }
        /* 接口入参说明
       * version: 应用当前版本号(已自动获取)
       * type:平台(1101是安卓,1102是IOS)
       */
        $http.get("api/kemean/aid/v2/app_version", httpData,{
                isPrompt: isPrompt
        }).then(res =&gt; {
                /* res的数据说明
               * | 参数名称             | 一定返回         | 类型          | 描述
               * | -------------|--------- | --------- | ------------- |
               * | versionCode       | y          | int          | 版本号      |
               * | versionName       | y          | String        | 版本名称      |
               * | versionInfo       | y          | String        | 版本信息      |
               * | forceUpdate       | y          | boolean        | 是否强制更新|
               * | downloadUrl       | y          | String        | 版本下载链接(IOS安装包更新请放跳转store应用商店链接,安卓apk和wgt文件放文件下载链接)|
               */
                if (res &amp;&amp; res.downloadUrl) {
                        callback &amp;&amp; callback(res);
                } else if (isPrompt) {
                        uni.showToast({
                                title: "暂无新版本",
                                icon: "none"
                        });
                }
        });
}
// 从服务器下载应用资源包(wgt文件)
export const getDownload = function(data) {
        let popupData = {
                progress:true,
                buttonNum: 2
        };
        if(data.forceUpdate){
                popupData.buttonNum = 0;
        }
        let dtask;
        let lastProgressValue = 0;
        downloadPopup(popupData, function(res) {
                dtask = plus.downloader.createDownload(data.downloadUrl, {
                        filename: "_doc/update/"
                }, function(download, status) {
                        if (status == 200) {
                                res.change({
                                        progressValue: 100,
                                        progressTip:"正在安装文件...",
                                        progress: true,
                                        buttonNum: 0
                                });
                                plus.runtime.install(download.filename, {}, function() {
                                        res.change({
                                                contentText: "应用资源更新完成!",
                                                buttonNum: 1,
                                                progress: false
                                        });
                                }, function(e) {
                                        res.cancel();
                                        plus.nativeUI.alert("安装文件失败[" + e.code + "]:" + e.message);
                                });
                        } else {
                                res.change({
                                        contentText: "文件下载失败...",
                                        buttonNum: 1,
                                        progress: false
                                });
                        }
                });
                dtask.start();
                dtask.addEventListener("statechanged", function(task, status) {
                        switch (task.state) {
                                case 1: // 开始
                                        res.change({
                                                progressValue:0,
                                                progressTip:"准备下载...",
                                                progress: true
                                        });
                                        break;
                                case 2: // 已连接到服务器
                                        res.change({
                                                progressValue:0,
                                                progressTip:"开始下载...",
                                                progress: true
                                        });
                                        break;
                                case 3:
                                        const progress = parseInt(task.downloadedSize / task.totalSize * 100);
                                        if(progress - lastProgressValue &gt;= 2){
                                                lastProgressValue = progress;
                                                res.change({
                                                        progressValue:progress,
                                                        progressTip: "已下载" + progress + "%",
                                                        progress: true
                                                });
                                        }
                                       
                                        break;
                        }
                });
        },function(){
                // 取消下载
                dtask &amp;&amp; dtask.abort();
                uni.showToast({
                        title: "已取消下载",
                        icon:"none"
                });
        },
        function(){
                // 重启APP
                plus.runtime.restart();
        });
}
// 文字换行
function drawtext(text, maxWidth) {
        let textArr = text.split("");
        let len = textArr.length;
        // 上个节点
        let previousNode = 1;
        // 记录节点宽度
        let nodeWidth = 0;
        // 文本换行数组
        let rowText = [];
        for (let i = 0; i &lt; len; i++) {
                if (/[\u4e00-\u9fa5]/g.test(textArr)) {
                        nodeWidth += 24;
                } else {
                        nodeWidth += 12;
                }
                if (nodeWidth &gt;= maxWidth) {
                        rowText.push(text.substring(previousNode, i));
                        previousNode = i;
                        nodeWidth = 0;
                }
        }
        if (previousNode &lt; text.length) {
                rowText.push(text.substring(previousNode, text.length));
        }
        return rowText.length;
}
// 是否更新弹窗
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));
        // 文本高度
        let viewContentHeight = parseInt(drawtext(data.versionInfo, viewContentWidth) * 16) + 10;
        // 弹窗容器高度
        const popupViewHeight = viewContentHeight + 80 + 20 + 20 + 90;
        // 弹窗内容
        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.drawRect({
                radius: "3px",
                borderColor: "#f1f1f1",
                borderWidth: "1px",
        }, {
                bottom: viewContentPadding + 'px',
                left: viewContentPadding + "px",
                width: (viewContentWidth - viewContentPadding) / 2 + "px",
                height: "30px",
        });
        // 绘制底边按钮
        popupView.drawRect({
                radius: "3px",
                color: $mainColor,
        }, {
                bottom: viewContentPadding + 'px',
                left: ((viewContentWidth - viewContentPadding) / 2 + viewContentPadding * 2) + "px",
                width: (viewContentWidth - viewContentPadding) / 2 + "px",
                height: "30px",
        });
        popupView.draw([{
                        src: $iconUrl,
                        id: "logo",
                        tag: "img",
                        position: {
                                top: "0px",
                                left: (popupViewWidth - 124) / 2 + "px",
                                width: "124px",
                                height: "80px",
                        }
                },
                {
                        tag: 'font',
                        id: 'title',
                        text: "发现新版本" + data.versionName,
                        textStyles: {
                                size: '18px',
                                color: "#333",
                                weight: "bold",
                                whiteSpace: "normal"
                        },
                        position: {
                                top: '90px',
                                left: viewContentPadding + "px",
                                width: viewContentWidth + "px",
                                height: "30px",
                        }
                },
                {
                        tag: 'font',
                        id: 'content23',
                        text: data.versionInfo,
                        textStyles: {
                                size: '14px',
                                color: "#666",
                                lineSpacing: "50%",
                                whiteSpace: "normal"
                        },
                        position: {
                                top: '130px',
                                left: viewContentPadding + "px",
                                width: viewContentWidth + "px",
                                height: viewContentHeight + "px",
                        }
                },
                {
                        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",
                        }
                },
        ]);
        popupView.addEventListener("click", function(e) {
                let maxTop = popupViewHeight - viewContentPadding;
                let maxLeft = popupViewWidth - viewContentPadding;
                let buttonWidth = (viewContentWidth - viewContentPadding) / 2;
                if (e.clientY &gt; maxTop - 30 &amp;&amp; e.clientY &lt; maxTop) {
                        // 暂不升级
                        if (e.clientX &gt; viewContentPadding &amp;&amp; e.clientX &lt; maxLeft - buttonWidth - viewContentPadding) {
                                maskLayer.hide();
                                popupView.hide();
                        } else if (e.clientX &gt; maxLeft - buttonWidth &amp;&amp; e.clientX &lt; maxLeft) {
                                // 立即升级
                                maskLayer.hide();
                                popupView.hide();
                                callback &amp;&amp; callback();
                        }
                }
        });
        // 点击遮罩层
        maskLayer.addEventListener("click", function() { //处理遮罩层点击
                maskLayer.hide();
                popupView.hide();
        });
        // 显示弹窗
        maskLayer.show();
        popupView.show();
}
// 文件下载的弹窗绘图
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: "#f1f1f1",
                                        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: $mainColor
                                },
                                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: $mainColor
                                },
                                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, callback, cancelCallback,rebootCallback) {
        // 弹窗遮罩层
        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 &gt;= 0){
                buttonNum = data.buttonNum;
        }
        popupView.draw(popupViewData.elementList);
        popupView.addEventListener("click", function(e) {
                let maxTop = popupViewData.popupViewHeight - popupViewData.viewContentPadding;
                let maxLeft = popupViewData.popupViewWidth - popupViewData.viewContentPadding;
                if (e.clientY &gt; maxTop - 40 &amp;&amp; e.clientY &lt; maxTop) {
                        if(buttonNum == 1){
                                // 单按钮
                                if (e.clientX &gt; popupViewData.viewContentPadding &amp;&amp; e.clientX &lt; maxLeft) {
                                        maskLayer.hide();
                                        popupView.hide();
                                        rebootCallback &amp;&amp; rebootCallback();
                                }
                        }else if(buttonNum == 2){
                                // 双按钮
                                let buttonWidth = (popupViewData.viewContentWidth - popupViewData.viewContentPadding) / 2;
                                if (e.clientX &gt; popupViewData.viewContentPadding &amp;&amp; e.clientX &lt; maxLeft - buttonWidth - popupViewData.viewContentPadding) {
                                        maskLayer.hide();
                                        popupView.hide();
                                        cancelCallback &amp;&amp; cancelCallback();
                                } else if (e.clientX &gt; maxLeft - buttonWidth &amp;&amp; e.clientX &lt; maxLeft) {
                                        maskLayer.hide();
                                        popupView.hide();
                                }
                        }
                }
        });
        // 显示弹窗
        maskLayer.show();
        popupView.show();
        // 改变进度条
        callback({
                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 &gt;= 0 &amp;&amp; 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) =&gt; {
                                        let have = false;
                                        progressElement.forEach((childItem,childIndex) =&gt; {
                                                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();
                }
        });
}
export default function(isPrompt = false) {
        getCurrentNo(version =&gt; {
                getServerNo(version.versionCode,isPrompt, res =&gt; {
                        if (res.forceUpdate) {
                                if (/\.wgt$/i.test(res.downloadUrl)) {
                                        getDownload(res);
                                } else {
                                        if (platform == "android") {
                                                getDownload(res);
                                        } else {
                                                plus.runtime.openURL(res.downloadUrl);
                                        }
                                }
                        } else {
                                updatePopup(res, function() {
                                        if (/\.wgt$/i.test(res.downloadUrl)) {
                                                getDownload(res);
                                        } else {
                                                if (platform == "android") {
                                                        getDownload(res);
                                                } else {
                                                        plus.runtime.openURL(res.downloadUrl);
                                                }
                                        }
                                });
                        }
                });
        });
}
// #endif
</pre>
</div>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>说明文档:</p>
<div class="cnblogs_Highlighter">
<pre class="brush:javascript;gutter:true;">### 第一步配置APP更新接口
在`APPUpdate.js`里面`getServerNo`函数方法配置更新接口
```
let httpData = {
        version:version
};
if (platform == "android") {
        httpData.type = 1101;
} else {
        httpData.type = 1102;
}
/* 接口入参说明
* version: 应用当前版本号(已自动获取)
* type:平台(1101是安卓,1102是IOS)
*/
$http.get("api/kemean/aid/app_version", httpData).then(res =&gt; {
        /*接口出参说明 (res数据说明)
        * | 参数名称             | 一定返回         | 类型          | 描述
        * | -------------|--------- | --------- | ------------- |
        * | versionCode       | y          | int          | 版本号      |
        * | versionName       | y          | String        | 版本名称      |
        * | versionInfo       | y          | String        | 版本信息      |
        * | forceUpdate       | y          | boolean        | 是否强制更新|
        * | downloadUrl       | y          | String        | 版本下载链接 `IOS安装包更新请放跳转store应用商店链接,安卓apk和wgt文件放文件下载链接` |
        */
});
```

### 第二步 使用方法
```
// App.vue页面

// #ifdef APP-PLUS
import APPUpdate from "@/utils/APPUpdate";
// #endif

onLaunch: function(e) {
        // #ifdef APP-PLUS
        APPUpdate();
        // #endif
}
```

### 第三步 添加APP安装应用的权限
在`manifest.json`文件里面`APP模块权限配置`的`Android打包权限配置`勾选以下权限
```
&lt;uses-permission android:name=\"android.permission.INSTALL_PACKAGES\"/&gt;
&lt;uses-permission android:name=\"android.permission.REQUEST_INSTALL_PACKAGES\"/&gt;
```

### 修改弹窗的主题色或弹窗图标
在`APPUpdate.js`里面上面`$mainColor`常量中定义主题颜色,`$iconUrl`常量中定义图标地址

### 检查APP是否有新版本(一般在设置页面使用)
```
// #ifdef APP-PLUS
import APPUpdate, { getCurrentNo } from "@/utils/APPUpdate";
// #endif
export default {
        data() {
                return {
                        version: "" // 版本号
                };
        },
        //第一次加载
        onLoad(e) {
                // #ifdef APP-PLUS
                getCurrentNo(res =&gt; {
                        // 进页面获取当前APP版本号(用于页面显示)
                        this.version = res.version;
                });
                // #endif
        },
        //方法
        methods: {
                // 检查APP是否有新版本
                onAPPUpdate() {
                        // true 没有新版本的时候有提示,默认:false
                        APPUpdate(true);
                }
        }
}
```
</pre>
</div>
<p>  </p>
<p>&nbsp;</p><br><br>
来源:https://www.cnblogs.com/yeziyou/p/13463560.html
頁: [1]
查看完整版本: uni-app版本更新(二)