效果图
一、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; }
}
}