实现方案
我将为你创建一个完整的版本检查和强制更新功能,包括:
-
版本检查工具类 - 获取当前App版本号和系统信息
-
版本更新服务 - 请求后端接口检查版本
-
强制更新组件 - 显示更新提示并跳转浏览器
-
使用示例 - 在App.vue中集成

1. 版本检查工具类 (utils/version.js)
/**
* 版本检查和更新工具类
*/
class VersionUtils {
/**
* 获取当前App版本号
* @returns {string} 版本号
*/
static getCurrentVersion() {
// #ifdef APP-PLUS
const appInfo = plus.runtime.getProperty('version');
return appInfo;
// #endif
// #ifdef H5
// H5环境返回默认版本号
return '1.0.0';
// #endif
// #ifdef MP
// 小程序环境返回默认版本号
return '1.0.0';
// #endif
}
/**
* 获取当前系统信息
* @returns {object} 系统信息 {platform: 'ios'|'android', version: string}
*/
static getSystemInfo() {
// #ifdef APP-PLUS
const systemInfo = uni.getSystemInfoSync();
const platform = systemInfo.platform.toLowerCase();
return {
platform: platform === 'ios' ? 'ios' : 'android',
version: systemInfo.system
};
// #endif
// #ifdef H5
const userAgent = navigator.userAgent.toLowerCase();
let platform = 'unknown';
if (userAgent.includes('iphone') || userAgent.includes('ipad') || userAgent.includes('ipod')) {
platform = 'ios';
} else if (userAgent.includes('android')) {
platform = 'android';
}
return {
platform,
version: navigator.userAgent
};
// #endif
// #ifdef MP
return {
platform: 'mp',
version: '1.0.0'
};
// #endif
}
/**
* 比较版本号
* @param {string} version1 版本号1
* @param {string} version2 版本号2
* @returns {number} 1: version1 > version2, -1: version1 < version2, 0: 相等
*/
static compareVersion(version1, version2) {
const v1 = version1.split('.').map(Number);
const v2 = version2.split('.').map(Number);
const maxLength = Math.max(v1.length, v2.length);
for (let i = 0; i < maxLength; i++) {
const num1 = v1[i] || 0;
const num2 = v2[i] || 0;
if (num1 > num2) return 1;
if (num1 < num2) return -1;
}
return 0;
}
/**
* 检查是否需要强制更新
* @param {string} currentVersion 当前版本
* @param {string} serverVersion 服务器版本
* @returns {boolean} 是否需要更新
*/
static needForceUpdate(currentVersion, serverVersion) {
return this.compareVersion(currentVersion, serverVersion) < 0;
}
}
export default VersionUtils;
2. 版本更新服务 (services/versionService.js)
import VersionUtils from '@/utils/version.js';
/**
* 版本更新服务
*/
class VersionService {
constructor() {
this.baseUrl = 'https://your-api-domain.com'; // 替换为你的后端API地址
}
/**
* 检查版本更新
* @returns {Promise<object>} 版本检查结果
*/
async checkVersion() {
try {
const currentVersion = VersionUtils.getCurrentVersion();
const systemInfo = VersionUtils.getSystemInfo();
const response = await uni.request({
url: `${this.baseUrl}/api/version/check`,
method: 'POST',
data: {
currentVersion,
platform: systemInfo.platform,
systemVersion: systemInfo.version
},
header: {
'Content-Type': 'application/json'
}
});
if (response.statusCode === 200 && response.data) {
const { code, data, message } = response.data;
if (code === 200) {
return {
success: true,
data: {
currentVersion,
serverVersion: data.serverVersion,
downloadUrl: data.downloadUrl,
forceUpdate: data.forceUpdate || false,
updateMessage: data.updateMessage || '发现新版本,请更新到最新版本',
needUpdate: VersionUtils.needForceUpdate(currentVersion, data.serverVersion)
}
};
} else {
return {
success: false,
message: message || '版本检查失败'
};
}
} else {
return {
success: false,
message: '网络请求失败'
};
}
} catch (error) {
console.error('版本检查错误:', error);
return {
success: false,
message: '版本检查异常'
};
}
}
/**
* 跳转到外部浏览器下载
* @param {string} downloadUrl 下载地址
*/
openExternalBrowser(downloadUrl) {
const systemInfo = VersionUtils.getSystemInfo();
// #ifdef APP-PLUS
if (systemInfo.platform === 'ios') {
// iOS使用Safari浏览器
plus.runtime.openURL(downloadUrl);
} else if (systemInfo.platform === 'android') {
// Android使用系统默认浏览器
plus.runtime.openURL(downloadUrl);
}
// #endif
// #ifdef H5
// H5环境直接跳转
window.open(downloadUrl, '_blank');
// #endif
// #ifdef MP
// 小程序环境提示用户手动打开
uni.showModal({
title: '提示',
content: '请复制链接到浏览器打开:' + downloadUrl,
showCancel: false
});
// #endif
}
}
export default new VersionService();
3. 强制更新组件 (components/ForceUpdate.vue)
<template>
<view v-if="showUpdateModal" class="force-update-modal">
<view class="modal-mask"></view>
<view class="modal-content">
<view class="update-icon">
<text class="iconfont icon-update"></text>
</view>
<view class="update-title">发现新版本</view>
<view class="update-message">{{ updateMessage }}</view>
<view class="version-info">
<text>当前版本:{{ currentVersion }}</text>
<text>最新版本:{{ serverVersion }}</text>
</view>
<view class="update-actions">
<button
v-if="!forceUpdate"
class="btn-cancel"
@click="handleCancel"
>
稍后更新
</button>
<button
class="btn-update"
@click="handleUpdate"
>
立即更新
</button>
</view>
</view>
</view>
</template>
<script>
import versionService from '@/services/versionService.js';
export default {
name: 'ForceUpdate',
data() {
return {
showUpdateModal: false,
currentVersion: '',
serverVersion: '',
downloadUrl: '',
forceUpdate: false,
updateMessage: ''
};
},
methods: {
/**
* 显示更新弹窗
* @param {object} versionInfo 版本信息
*/
showUpdate(versionInfo) {
this.currentVersion = versionInfo.currentVersion;
this.serverVersion = versionInfo.serverVersion;
this.downloadUrl = versionInfo.downloadUrl;
this.forceUpdate = versionInfo.forceUpdate;
this.updateMessage = versionInfo.updateMessage;
this.showUpdateModal = true;
},
/**
* 处理更新
*/
handleUpdate() {
if (this.downloadUrl) {
versionService.openExternalBrowser(this.downloadUrl);
}
// 如果是强制更新,不关闭弹窗
if (!this.forceUpdate) {
this.hideUpdate();
}
},
/**
* 处理取消
*/
handleCancel() {
this.hideUpdate();
},
/**
* 隐藏更新弹窗
*/
hideUpdate() {
this.showUpdateModal = false;
}
}
};
</script>
<style scoped>
.force-update-modal {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 9999;
}
.modal-mask {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.6);
}
.modal-content {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 280px;
background-color: #fff;
border-radius: 12px;
padding: 24px;
text-align: center;
}
.update-icon {
margin-bottom: 16px;
}
.update-icon .iconfont {
font-size: 48px;
color: #007aff;
}
.update-title {
font-size: 18px;
font-weight: bold;
color: #333;
margin-bottom: 12px;
}
.update-message {
font-size: 14px;
color: #666;
line-height: 1.5;
margin-bottom: 16px;
}
.version-info {
background-color: #f5f5f5;
border-radius: 8px;
padding: 12px;
margin-bottom: 20px;
}
.version-info text {
display: block;
font-size: 12px;
color: #999;
line-height: 1.8;
}
.update-actions {
display: flex;
gap: 12px;
}
.btn-cancel,
.btn-update {
flex: 1;
height: 40px;
border-radius: 20px;
font-size: 14px;
border: none;
}
.btn-cancel {
background-color: #f5f5f5;
color: #666;
}
.btn-update {
background-color: #007aff;
color: #fff;
}
</style>
4. 在App.vue中集成 (App.vue)
<script>
import versionService from '@/services/versionService.js';
import ForceUpdate from '@/components/ForceUpdate.vue';
export default {
components: {
ForceUpdate
},
data() {
return {
versionChecked: false
};
},
onLaunch() {
// App启动时检查版本
this.checkAppVersion();
},
methods: {
/**
* 检查App版本
*/
async checkAppVersion() {
try {
const result = await versionService.checkVersion();
if (result.success && result.data.needUpdate) {
// 显示更新弹窗
this.$refs.forceUpdate.showUpdate(result.data);
}
this.versionChecked = true;
} catch (error) {
console.error('版本检查失败:', error);
this.versionChecked = true;
}
}
}
};
</script>
<style>
/* 全局样式 */
</style>
5. 使用示例 (pages/index/index.vue)
<template>
<view class="container">
<view class="version-info">
<text>当前版本:{{ currentVersion }}</text>
<text>系统:{{ systemInfo.platform }} {{ systemInfo.version }}</text>
</view>
<button @click="checkVersion" class="check-btn">
检查更新
</button>
<!-- 强制更新组件 -->
<ForceUpdate ref="forceUpdate" />
</view>
</template>
<script>
import VersionUtils from '@/utils/version.js';
import versionService from '@/services/versionService.js';
import ForceUpdate from '@/components/ForceUpdate.vue';
export default {
components: {
ForceUpdate
},
data() {
return {
currentVersion: '',
systemInfo: {}
};
},
onLoad() {
this.initVersionInfo();
},
methods: {
/**
* 初始化版本信息
*/
initVersionInfo() {
this.currentVersion = VersionUtils.getCurrentVersion();
this.systemInfo = VersionUtils.getSystemInfo();
},
/**
* 手动检查更新
*/
async checkVersion() {
uni.showLoading({
title: '检查中...'
});
try {
const result = await versionService.checkVersion();
uni.hideLoading();
if (result.success) {
if (result.data.needUpdate) {
// 显示更新弹窗
this.$refs.forceUpdate.showUpdate(result.data);
} else {
uni.showToast({
title: '已是最新版本',
icon: 'success'
});
}
} else {
uni.showToast({
title: result.message || '检查失败',
icon: 'error'
});
}
} catch (error) {
uni.hideLoading();
uni.showToast({
title: '检查失败',
icon: 'error'
});
}
}
}
};
</script>
<style scoped>
.container {
padding: 20px;
}
.version-info {
background-color: #f5f5f5;
padding: 16px;
border-radius: 8px;
margin-bottom: 20px;
}
.version-info text {
display: block;
font-size: 14px;
color: #333;
line-height: 1.8;
}
.check-btn {
width: 100%;
height: 44px;
background-color: #007aff;
color: #fff;
border-radius: 22px;
font-size: 16px;
}
</style>
后端API接口格式
你的后端需要提供一个版本检查接口,返回格式如下:
{
"code": 200,
"message": "success",
"data": {
"serverVersion": "1.2.0",
"downloadUrl": "https://your-download-url.com",
"forceUpdate": true,
"updateMessage": "发现新版本,请更新到最新版本以获得更好的体验"
}
}
主要功能特点
-
自动版本检查 - App启动时自动检查版本
-
系统识别 - 自动识别iOS和Android系统
-
强制更新 - 支持强制更新和可选更新
-
外部浏览器跳转 - iOS跳转Safari,Android跳转系统浏览器
-
版本比较 - 智能版本号比较算法
-
错误处理 - 完善的错误处理和用户提示
使用说明
-
将上述文件复制到你的uniapp项目中
-
修改
services/versionService.js中的baseUrl为你的后端API地址 -
在
App.vue中引入ForceUpdate组件 -
确保后端提供正确的版本检查API接口
这样就完成了完整的版本检查和强制更新功能!

被折叠的 条评论
为什么被折叠?



