uni-app自动升级功能

发布于:2025-03-26 ⋅ 阅读:(24) ⋅ 点赞:(0)

效果图

一、VUE 

login.vue

<template>
	<view>
		<view class="uni-common-mt">
			<view class="uni-flex uni-column">
				<view class="flex-item  flex-item-V">
					<view class="logo">
						<image src="/static/image/uniui-logo.png" style="height:90px;display: none;"></image>
					</view>
					<view class="logoHead">欢迎使用WMS</view>
				</view>
				<view class="flex-item flex-item-V">

				</view>
				<view class="flex-item flex-item-V form">
					<form>
						<view class="uni-form-item uni-column">
							<uni-easyinput v-model="formData.loginName" maxlength="50" name="loginName"
								placeholder="请输入账号" prefixIcon="person" value="">
							</uni-easyinput>
						</view>

						<view class="uni-form-item uni-column">
							<uni-easyinput v-model="formData.password2" maxlength="50" name="password" type="password"
								placeholder="请输入密码" prefixIcon="locked" @confirm="formSubmit">
							</uni-easyinput>
						</view>

						<view class="uni-btn-v loginBtn">
							<button form-type="submit" type="primary" :loading="loginLoading" @click="formSubmit">登
								录</button>

						</view>
					</form>
				</view>
			</view>
		</view>
	</view>
	<view class="register-section">
		Copyright © 2025 **科技 版本号:{{ThisVersion}}
	</view>
</template>

<script setup>
	import {
		nextTick,
		onMounted,
		ref
	} from 'vue';
	import {
		userApi
	} from "@/api/user";
	import graceChecker from "@/common/graceChecker.js";
	import CryptoJS from 'crypto-js';
	import G from '@/utils/global.js'
	const ThisVersion = G.ApkVersion;
	const loginLoading = ref(false);
	const myForm = ref();
	const formData = ref({
		loginName: "",
		password: "",
		password2: "",
		tenantId: "1867144130501541888",
		lang: "zh_cn",
		industry: null
	}); 
	//提交登录
	const formSubmit = (e) => {
		//定义表单规则
		var rule = [{
				name: "loginName",
				checkType: "string",
				checkRule: "1,20",
				errorMsg: "请输入1-20位的账号"
			},
			{
				name: "password2",
				checkType: "string",
				checkRule: "3,20",
				errorMsg: "请输入3-20密码"
			}
		];
		//进行表单检查 
		var checkRes = graceChecker.check(formData.value, rule);
		if (checkRes) {
			//登录信息 
			formData.value.password = CryptoJS.SHA256(formData.value.password2).toString(CryptoJS.enc.Hex);
			let thisObj = {
				"thisObj": formData.value
			};
			loginLoading.value = true;
			uni.setStorageSync('token', "login");

			//1.登录得到code
			userApi.LoginByOauth(thisObj).then(loginRes => {
				console.log('loginRes========', JSON.stringify(loginRes));
				if (loginRes.mfail != '0' || loginRes.data == null) {
					loginLoading.value = false;
					uni.showToast({
						icon: 'none',
						duration: G.ShowPopTime,
						title: `登录异常,code获取异常:${loginRes.msg}`
					});
					return;
				} else {
					//2.通过code获取Token
					let postData = {
						code: loginRes.data.code
					};
					//获取token
					userApi.GetTokenFromCode(postData).then(tokenRes => {
						console.log('Token========', JSON.stringify(tokenRes));
						if (tokenRes.mfail != '0' || tokenRes.data == null) {
							loginLoading.value = false;
							uni.showToast({
								icon: 'none',
								duration: G.ShowPopTime,
								title: `登录异常,token获取异常:${res.msg}`
							});
							return;
						}
						//登录成功后,将token写入全局变量
						uni.setStorageSync('token', tokenRes.data.token);
						//跳转到首页
						nextTick(() => {
							uni.reLaunch({
								animationType: 'zoom-out',
								animationDuration: 200,
								url: "/pages/index/index"
							});

						});
					}).catch(error => {
						uni.setStorageSync('token', null);
						loginLoading.value = false;
						uni.showToast({
							icon: 'none',
							duration: G.ShowPopTime,
							title: `访问失败,请联系管理员!:${res.msg}`
						});

					});

				}

			}).catch(error => {
				uni.setStorageSync('token', null);
				loginLoading.value = false;
				uni.showToast({
					icon: 'none',
					duration: G.ShowPopTime,
					title: `访问失败,请联系管理员!:${res.msg}`
				});
			});

		} else {
			loginLoading.value = false;
			uni.showToast({
				title: graceChecker.error,
				icon: "error",
				duration: G.ShowPopTime
			});
		}

	}
	//自动更新升级新版本
	const autoUpdate = () => { 
		var myVerson =ThisVersion; //Android当前版本
		var obj = {
			AppType: G.AppType, //1.Android(默认)  2.ISO 
			AppVersion: myVerson
		}		
		userApi.getVersion(obj).then(res => {
			console.log("查询服务器版本信息---------------- " + JSON.stringify(res));
			if (res == undefined) {
				console.log('连接服务器失败!');
			} else {
				if (res.IsUpdate == true) {
					console.log('需要更新版本!');  
					uni.showModal({
						title: "版本更新",
						content: '检测到程序有新版本,是否立即进行新版本下载?',
						confirmText: '立即更新',
						cancelText: '稍后进行',
						success: function(res) {
							if (res.confirm) {
								//设置 最新版本apk的下载 
								let downloadApkUrl = G.DownLoadUrl;
								//GLOBAL.DOMAIN_URL + "/apk/mzz2.apk";
								let dtask = plus.downloader.createDownload(downloadApkUrl, {},
									function(d, status) {
										// 下载完成 
										if (status == 200) {
											plus.runtime.install(plus.io
												.convertLocalFileSystemURL(d
													.filename), {}, {},
												function(error) {
													uni.showToast({
														title: '安装失败',
														duration: 1500
													});
												})
										} else {
											uni.showToast({
												title: '更新失败',
												duration: 1500
											});
										}
									});
								dtask.start();
								var prg = 0;
								var showLoading = plus.nativeUI.showWaiting("正在下载");
								 //创建一个showWaiting对象 
								dtask.addEventListener('statechanged', function(task, status) {
									// 给下载任务设置一个监听 并根据状态  做操作
									switch (task.state) {
										case 1:
											showLoading.setTitle("正在下载");
											break;
										case 2:
											//showLoading.setTitle("已连接到服务器");
											break;
										case 3:
											prg = parseInt(
												(parseFloat(task.downloadedSize) /
													parseFloat(task.totalSize)) *
												100
											);
											showLoading.setTitle("正在下载" + prg + "%  ");										
											break;
										case 4:
											plus.nativeUI.closeWaiting();
											//下载完成
											break;
									}
								});
							} else if (res.cancel) {
								console.log('稍后更新');
							}
						}
					});
				} else {
					console.log('不需要更新版本!');
				}
			}
		}).catch(error => {
			console.log('访问失败,请联系管理员!!');
		});
	}
	onMounted(() => {
		uni.setStorageSync('token', null);
		autoUpdate();
	});
</script>

<style scoped lang="scss">
	view {
		box-sizing: border-box;
	}

	.uni-common-mt {
		margin: 0;
	}

	.flex-item:nth-child(1) {
		display: flex;
		flex-flow: column;
		justify-content: center;
		align-content: center;
	}

	.flex-item:nth-child(2) {
		height: 120rpx;
		background: url("/static/login-style.png") round space;

	}

	.logo {
		min-height: 100rpx;
		padding-left: 10px;
		margin-top: 100rpx;
	}

	.logoHead {
		font-family: 'Microsoft YaHei', sans-serif;
		text-align: center;
		color: darkblue;
		font-size: 58rpx;
		font-weight: bold;
		text-shadow: 1px 1px rgba(0, 0, 0, .3);
		padding-bottom: 40rpx;
	}

	.loginBtn {
		padding-top: 40rpx;
	}

	.form {
		padding: 0px 40px;
	}

	.register-section {
		position: absolute;
		left: 0;
		bottom: 20px;
		width: 100%;
		font-size: $uni-font-size-sm;
		color: $uni-text-color;
		text-align: center;
	}
</style>

global.js

export default {
	CAPTCHA_TYPE: {
		COMMON: 'common'
	},
	ShowPopTime: 5000, //弹框持续时间
	AppType: 1, //1.Android(默认)  2.ISO
	ApkVersion: 'v5.3.25.2', //Android当前版本
	IsoVersion: 'v5.2.20.1', //Iso当前版本
	DownLoadUrl: 'http://192.168.6.1/APPDownLoad/TJWMSApp.apk', //正式下载App地址
	REQUEST_URL: 'http://192.168.6.3', //正式api地址 http://192.168.6.3,代理地址/base-api	
	// REQUEST_URL: 'http://localhost:80', //本地api地址/
	FileHandler: 'http://192.168.6.1/APPDownLoad/' //正式保存图片地址UAWebService/api/Test/SaveFile
};

API user.ts

import { request } from '@/utils/request.js';
//1.登录得到code
const LoginByOauth = (data) => {
	return request.post('/levault/usrsvr/Usr/LoginByOauth', data);
};
//2.通过code获取Token
const GetTokenFromCode = (data) => {
	return request.post('/levault/usrsvr/Usr/GetTokenFromCode', data);
};
// 获取版本号
 const getVersion=(data)=> {
	return request.post('http://192.168.6.1/api/GetVersion', data);  
};
export const userApi = {
	LoginByOauth,
	GetTokenFromCode,
	getVersion
};

request.js

import config from '@/utils/config';
// 统一 POST 请求方法示例
const post = async (url, data, options = {}) => {
	if (!String(url).startsWith('http://')) {
		url = config.url + url;
	}
	console.log("uni.getStorageSync('token')==========", uni.getStorageSync('token'));
	//判断是否登录
	if (uni.getStorageSync('token') == null || uni.getStorageSync('token') == '') {
		// uni.reLaunch({
		// 	animationType: 'zoom-out',
		// 	animationDuration: 200,
		// 	url: "/pages/login/index"
		// });
	}
	const defaultOptions = {
		method: 'POST',
		header: {
			'Content-Type': 'application/json'
			// ,'token': `${uni.getStorageSync('token')}`
		}
	};
	const finalOptions = { ...defaultOptions, ...options };
	// 如果服务器需要 token,可以在这里添加 Authorization 头部
	if (!finalOptions.header['token'] && uni.getStorageSync('token')) {
		finalOptions.header['token'] = `${uni.getStorageSync('token')}`;
	}

	// if (!finalOptions.header['Authorization'] && uni.getStorageSync('token')) {
	//   finalOptions.header['Authorization'] = `Bearer ${uni.getStorageSync('token')}`;
	// }
	console.log('POST 请求参数=====', JSON.stringify(data));
	console.log('POST 请求header=====', finalOptions);
	console.log('POST url=====', url);
	uni.showLoading({
		title: '加载中...'
	});
	return new Promise((resolve, reject) => {
		uni.request({
			...finalOptions,
			url: url,
			data: data,
			success: (res) => {
				console.log('请示结果=============', res);
				if (res.statusCode === 200) {
					resolve(res.data);
				} else {
					reject(new Error(`POST请求失败,状态码:${res.statusCode}`));
					uni.showToast({
						icon: 'none',
						title: `POST请求失败,状态码:${res.statusCode}`
					});
				}
			},
			fail: (err) => {
				reject(err);
				// 网络错误或其他请求失败的情况
				uni.showToast({
					icon: 'none',
					title: 'POST系统异常,请稍后再试'
				});
			},
			complete: () => {
				uni.hideLoading();
			}
		});
	});
};
// 统一 GET 请求方法示例
const get = async (url, data, options = {}) => {
	url = config.url + url;
	console.log("uni.getStorageSync('token')==========", uni.getStorageSync('token'));
	const defaultOptions = {
		method: 'GET',
		header: {
			'Content-Type': 'application/json'
			// ,'token': `${uni.getStorageSync('token')}`
		}
	};
	//判断是否登录
	if (uni.getStorageSync('token') == null || uni.getStorageSync('token') == '') {
		// uni.reLaunch({
		// 	animationType: 'zoom-out',
		// 	animationDuration: 200,
		// 	url: "/pages/login/index"
		// });
	}
	const finalOptions = { ...defaultOptions, ...options };
	// 如果服务器需要 token,可以在这里添加 Authorization 头部
	if (!finalOptions.header['token'] && uni.getStorageSync('token')) {
		finalOptions.header['token'] = `${uni.getStorageSync('token')}`;
	}

	// if (!finalOptions.header['Authorization'] && uni.getStorageSync('token')) {
	//   finalOptions.header['Authorization'] = `Bearer ${uni.getStorageSync('token')}`;
	// }

	console.log('GET 请求header=====', finalOptions);
	console.log('GET url=====', url);
	console.log('GET 请求参数=====', data);
	uni.showLoading({
		title: '加载中...'
	});
	return new Promise((resolve, reject) => {
		uni.request({
			...finalOptions,
			url: url,
			data: data,
			success: (res) => {
				console.log('GET请示结果=============', res);
				if (res.statusCode === 200) {
					resolve(res.data);
				} else {
					reject(new Error(`GET请求失败,状态码:${res.statusCode}`));
					uni.showToast({
						icon: 'none',
						title: `GET请求失败,状态码:${res.statusCode}`
					});
				}
			},
			fail: (err) => {
				reject(err);
				// 网络错误或其他请求失败的情况
				uni.showToast({
					icon: 'none',
					title: 'GET系统异常,请稍后再试'
				});
			},
			complete: () => {
				uni.hideLoading();
			}
		});
	});
};
const postAsync = async (url, data, options = {}) => {
	try {
		// 合并基础URL
		const fullUrl = config.url + url;

		// 构建请求头(动态添加token)
		const headers = {
			'Content-Type': 'application/json',
			...(uni.getStorageSync('token') && { token: uni.getStorageSync('token') })
		};

		// 合并自定义配置
		const finalOptions = {
			method: 'POST',
			header: { ...headers, ...options.header },
			...options
		};

		// 调试日志(开发环境保留)
		if (process.env.NODE_ENV === 'development') {
			console.log('[POST Request]', {
				url: fullUrl,
				data,
				headers: finalOptions.header
			});
		}

		// 发送请求
		const response = await new Promise((resolve, reject) => {
			uni.request({
				url: fullUrl,
				data,
				...finalOptions,
				success: (res) => resolve(res),
				fail: (err) => reject(err)
			});
		});

		// 处理响应状态码
		if (response.statusCode !== 200) {
			const errorMessage = `请求失败 (${response.statusCode})`;
			uni.showToast({ icon: 'none', title: errorMessage });
			throw new Error(errorMessage);
		}

		return response.data;
	} catch (error) {
		// 统一错误处理
		const errorMessage = error.errMsg || '系统异常,请稍后再试';
		uni.showToast({ icon: 'none', title: errorMessage });
		throw error; // 继续抛出错误供调用方捕获
	}
};
export const request = {
	post,
	postAsync,
	get
};

二、C# MVC接口代码

检测系统版本号,是否需要升级

using MAPP.WebApi.Models;
 
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using System.Web.Configuration;

namespace MAPP.WebApi.Controllers
{
    public class SystemController : ApiController
    {
        /// <summary>
        /// 校验系统版本号,返回是否需要更新
        /// </summary>
        /// <param name="jo"></param>
        /// <returns></returns> 
        [HttpPost, Route("api/GetVersion")]
        public HttpResponseMessage GetVersion(JObject jo)
        {
            var result = new AppSystemModel();
            result.IsSuccess = true;
            result.IsUpdate = false;
            int appType = 1;//默认安卓系统
            try
            {
                //判断是否启用自动更新
                if (WebConfigurationManager.AppSettings["OpenAppUpdateOnline"].ToString() != "1")
                {
                    result.IsUpdate = false;
                    result.NewVersion = "";
                    //result.returnMsg = "不需要更新!";
                    return Request.CreateResponse(HttpStatusCode.OK, result);
                }

                string appVersion = "";
                if (jo["AppVersion"] == null)
                {
                    result.IsSuccess = false;
                    result.IsUpdate = false;
                    result.Msg = "无法获取当前版本号!";
                    return Request.CreateResponse(HttpStatusCode.OK, result);
                }

                if (jo["AppType"] != null)
                {
                    if (jo["AppType"].ToString() == "2")
                    {
                        appType = 2;
                    }
                }

                if (appType == 1)
                {
                    appVersion = WebConfigurationManager.AppSettings["APKVersion"].ToString();
                }
                else
                {
                    appVersion = WebConfigurationManager.AppSettings["IOSVersion"].ToString();
                }
                //服务器端版本
                Version v1_server = new Version(appVersion.ToLower().Replace("v", ""));
                //手机端版本
                Version v2_pda = new Version(jo["AppVersion"].ToString().ToLower().Replace("v", ""));
                if (v1_server > v2_pda)
                {
                    result.IsUpdate = true;
                    result.Msg = "请更新系统!";
                    return Request.CreateResponse(HttpStatusCode.OK, result);
                }
                else
                {
                    result.IsUpdate = false;
                    result.Msg = "";
                    return Request.CreateResponse(HttpStatusCode.OK, result);
                }
            }
            catch (Exception ex)
            {
                result.IsSuccess = false;
                result.IsUpdate = false;
                result.Msg = "获取版本号失败:" + ex.Message;
                return Request.CreateResponse(HttpStatusCode.OK, result);
            }
        }

    }
}

web.config

<?xml version="1.0" encoding="utf-8"?>
<!--
  有关如何配置 ASP.NET 应用程序的详细信息,请访问
  https://go.microsoft.com/fwlink/?LinkId=301879
  -->
<configuration>
  <appSettings>
    <!--==========Android版本相关配置============-->
    <!--APP更新下载路径-->
    <add key="AppDownLoadUrl" value="http://192.168.6.1/UpLoad/APPDownLoad/"/>
    <!-- APP是否启用自动升级:1启用,2关闭 -->
    <add key="OpenAppUpdateOnline" value="1"/>
    <!-- ==========Android版本号============ -->
    <add key="APKVersion" value="v1.5.20.1"/>
    <!--==========IOS版本号============-->
    <add key="IOSVersion" value="v1.3.31.1"/>
    
    <add key="webpages:Version" value="3.0.0.0"/>
    <add key="webpages:Enabled" value="false"/>
    <add key="ClientValidationEnabled" value="true"/>
    <add key="UnobtrusiveJavaScriptEnabled" value="true"/>
  </appSettings>
  <system.web>
    <compilation debug="true" targetFramework="4.6.1"/>
    <httpRuntime targetFramework="4.6.1"/>
  </system.web>
  <system.webServer>
    <handlers>
      <remove name="ExtensionlessUrlHandler-Integrated-4.0"/>
      <remove name="OPTIONSVerbHandler"/>
      <remove name="TRACEVerbHandler"/>
      <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler"
        preCondition="integratedMode,runtimeVersionv4.0"/>
    </handlers>
    <staticContent>
      <mimeMap fileExtension=".apk" mimeType="application/vnd.android.package-archive" />
    </staticContent>
  </system.webServer> 
</configuration>

AppSystemModel.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace MAPP.WebApi.Models
{
    public class AppSystemModel
    {
        /// <summary>
        /// 是否成功
        /// </summary>
        public bool IsSuccess { get; set; }

        /// <summary>
        /// 返回App版本是否需要更新
        /// </summary>
        public bool IsUpdate { get; set; }

        /// <summary>
        /// 最新版本号
        /// </summary>
        public string NewVersion { get; set; }

        /// <summary>
        /// 返回消息
        /// </summary>
        public string Msg { get; set; }
    }

    public class Payloaddata
    {
        public string token { get; set; }
        public string nickname { get; set; }
        public string profile { get; set; }
        public bool hasLogin { get; set; }
        public bool isGoogle { get; set; }
        public object result { get; set; }
    }

    public class LoginModel
    {
        public string UserId { get; set; }
        public string RoleCode { get; set; }
        public object DeptId { get; set; }
        public string UserName { get; set; }
    }

    public class UserInfo
    {
        public string UserCode { get; set; }
        public string UserName { get; set; }
        public object AppModelPageList { get; set; }
        public object AppModelList { get; set; }
    }
}