596 lines
14 KiB
Vue
Raw Normal View History

2025-04-09 18:55:14 +08:00
<template>
<view class="mask flex-center">
2025-04-09 18:55:14 +08:00
<view class="content botton-radius">
<view class="content-top">
<text class="content-top-text">{{title}}</text>
<image class="content-top" style="top: 0;" width="100%" height="100%"
src="/uni_modules/uni-upgrade-center-app/static/bg_top.png">
</image>
2025-04-09 18:55:14 +08:00
</view>
<view class="content-header"></view>
<view class="content-body">
<view class="title" v-if="patternId === '101'">
<text>{{upDataPage.versionName}}</text>
<text class="content-body-version">{{upDataPage.versionName}}</text>
</view>
<view class="title" v-if="patternId === '103'">
<text>{{upDataPage.versionName}}</text>
<text class="content-body-version">{{upDataPage.taiGuoVersion}}</text>
2025-04-09 18:55:14 +08:00
</view>
<view class="body">
<scroll-view class="box-des-scroll" scroll-y="true">
<text class="box-des">
{{upDataPage.note}}
2025-04-09 18:55:14 +08:00
</text>
</scroll-view>
</view>
<view class="footer flex-center">
<template v-if="!isAppStore">
<button class="content-button" style="border: none;color: #fff;" plain @click="jumpToAppStore">
立即更新
2025-04-09 18:55:14 +08:00
</button>
</template>
<template v-else>
<template v-if="!downloadSuccess">
<view class="progress-box flex-column" v-if="downloading">
<progress class="progress" :percent="downLoadPercent" activeColor="#3DA7FF" show-info
stroke-width="10" />
<view style="width:100%;font-size: 28rpx;display: flex;justify-content: space-around;">
<text>{{downLoadingText}}</text>
<text>({{downloadedSize}}/{{packageFileSize}}M)</text>
2025-04-09 18:55:14 +08:00
</view>
</view>
<button v-else class="content-button" style="border: none;color: #fff;" plain
@click="updateApp">
{{downLoadBtnText}}
2025-04-09 18:55:14 +08:00
</button>
</template>
<button v-else-if="downloadSuccess && !installed" class="content-button"
style="border: none;color: #fff;" plain :loading="installing" :disabled="installing"
@click="installPackage">
{{installing ? '正在安装……' : '下载完成,立即安装'}}
2025-04-09 18:55:14 +08:00
</button>
<button v-else-if="installed && !isWGT" class="content-button" style="border: none;color: #fff;"
plain :loading="installing" :disabled="installing" @click="installPackage">
2025-04-09 18:55:14 +08:00
安装未完成点击安装
</button>
<button v-else-if="installed && isWGT" class="content-button" style="border: none;color: #fff;"
plain @click="restart">
安装完毕点击重启
</button>
2025-04-09 18:55:14 +08:00
</template>
</view>
</view>
<image v-if="upDataPage.State !== 1" class="close-img"
src="/uni_modules/uni-upgrade-center-app/static/app_update_close.png" @click.stop="closeUpdate">
</image>
2025-04-09 18:55:14 +08:00
</view>
</view>
</template>
<script>
// #ifdef APP
import {
createNotificationProgress,
cancelNotificationProgress,
finishNotificationProgress
} from '@/uni_modules/uts-progressNotification'
// #endif
const localFilePathKey = 'UNI_ADMIN_UPGRADE_CENTER_LOCAL_FILE_PATH'
const platform_iOS = 'iOS';
const platform_Android = 'Android';
let downloadTask = null;
let openSchemePromise
function compare(v1 = '0', v2 = '0') {
v1 = String(v1).split('.')
v2 = String(v2).split('.')
const minVersionLens = Math.min(v1.length, v2.length);
let result = 0;
for (let i = 0; i < minVersionLens; i++) {
const curV1 = Number(v1[i])
const curV2 = Number(v2[i])
if (curV1 > curV2) {
result = 1
break;
} else if (curV1 < curV2) {
result = -1
break;
}
2025-04-09 18:55:14 +08:00
}
if (result === 0 && (v1.length !== v2.length)) {
const v1BiggerThenv2 = v1.length > v2.length;
const maxLensVersion = v1BiggerThenv2 ? v1 : v2;
for (let i = minVersionLens; i < maxLensVersion.length; i++) {
const curVersion = Number(maxLensVersion[i])
if (curVersion > 0) {
v1BiggerThenv2 ? result = 1 : result = -1
break;
}
}
2025-04-09 18:55:14 +08:00
}
return result;
}
export default {
data() {
return {
installForBeforeFilePath: '',
installed: false,
installing: false,
downloadSuccess: false,
downloading: false,
downLoadPercent: 0,
downloadedSize: 0,
packageFileSize: 0,
tempFilePath: '',
title: '版本更新',
contents: '',
is_mandatory: false,
subTitle: '发现新版本',
downLoadBtnTextiOS: '立即跳转更新',
downLoadBtnText: '立即下载更新',
downLoadingText: '安装包下载中,请稍后',
upDataPage: {},
patternId:''
2025-04-09 18:55:14 +08:00
}
},
onLoad({
local_storage_key,
patternId
}) {
this.patternId = patternId
console.log(local_storage_key);
if (!local_storage_key) {
console.error('local_storage_key为空请检查后重试')
uni.navigateBack()
return;
};
const localPackageInfo = uni.getStorageSync(local_storage_key);
console.log(localPackageInfo,'====================================>');
if (!localPackageInfo) {
console.error('安装包信息为空,请检查后重试')
uni.navigateBack()
return;
};
this.upDataPage = localPackageInfo
if (this.upDataPage.State === 1) {
this.is_mandatory = true
} else {
this.is_mandatory = false
2025-04-09 18:55:14 +08:00
}
this.checkLocalStoragePackage()
2025-04-09 18:55:14 +08:00
},
onBackPress() {
// 强制更新不允许返回
if (this.is_mandatory) return true
if (!this.needNotificationProgress) downloadTask && downloadTask.abort()
2025-04-09 18:55:14 +08:00
},
onHide() {
openSchemePromise = null
2025-04-09 18:55:14 +08:00
},
computed: {
isWGT() {
return this.type === 'wgt'
},
isAppStore() {
let url = ''
if(this.patternId === '101'){
url = this.upDataPage.url
2025-04-09 18:55:14 +08:00
}
if(this.patternId === '103'){
url = this.upDataPage.taiGuoUrl
2025-04-09 18:55:14 +08:00
}
return url.indexOf('.apk') === -1
},
2025-04-09 18:55:14 +08:00
},
methods: {
checkLocalStoragePackage() {
// 如果已经有下载好的包,则直接提示安装
const localFilePathRecord = uni.getStorageSync(localFilePathKey)
if (localFilePathRecord) {
const {
version,
savedFilePath,
installed
} = localFilePathRecord
// 比对版本
if (!installed && compare(version, this.version) === 0) {
this.downloadSuccess = true;
this.installForBeforeFilePath = savedFilePath;
this.tempFilePath = savedFilePath
2025-04-09 18:55:14 +08:00
} else {
// 如果保存的包版本小 或 已安装过,则直接删除
this.deleteSavedFile(savedFilePath)
2025-04-09 18:55:14 +08:00
}
}
},
askAbortDownload() {
uni.showModal({
title: '是否取消下载?',
cancelText: '否',
confirmText: '是',
success: res => {
if (res.confirm) {
downloadTask && downloadTask.abort()
cancelNotificationProgress()
uni.navigateBack()
2025-04-09 18:55:14 +08:00
}
}
});
},
async closeUpdate() {
if (this.downloading) {
if (this.is_mandatory) {
return uni.showToast({
title: '下载中,请稍后……',
icon: 'none',
duration: 500
})
}
if (!this.needNotificationProgress) {
this.askAbortDownload()
return;
}
2025-04-09 18:55:14 +08:00
}
if (!this.needNotificationProgress && this.downloadSuccess && this.tempFilePath) {
// 包已经下载完毕,稍后安装,将包保存在本地
await this.saveFile(this.tempFilePath, this.upDataPage.version)
}
2025-04-09 18:55:14 +08:00
uni.navigateBack()
},
updateApp() {
this.checkStoreScheme()
.catch(() => {
//调用在线升级
this.downloadPackage()
})
.finally(() => {
//释放升级
openSchemePromise = null
})
},
// 检查应用商店
checkStoreScheme() {
const storeList = (this.store_list || []).filter(item => item.enable)
if (storeList && storeList.length) {
storeList
.sort((cur, next) => next.priority - cur.priority)
.map(item => item.scheme)
.reduce((promise, cur, curIndex) => {
openSchemePromise = (promise || (promise = Promise.reject())).catch(() => {
return new Promise((resolve, reject) => {
plus.runtime.openURL(cur, (err) => {
reject(err)
})
})
})
return openSchemePromise
}, openSchemePromise)
return openSchemePromise
}
return Promise.reject()
},
downloadPackage() {
this.downloading = true;
//下载包
downloadTask = uni.downloadFile({
url: this.patternId === '101' ? this.upDataPage.url : this.upDataPage.taiGuoUrl,
success: res => {
if (res.statusCode == 200) {
// fix: wgt 文件下载完成后后缀不是 wgt
if (res.tempFilePath.split('.').slice(-1)[0] !== 'wgt') {
const failCallback = (e) => {
console.log('文件重命名失败', JSON.stringify(e));
}
plus.io.resolveLocalFileSystemURL(res.tempFilePath, (entry) => {
entry.getParent((parent) => {
const newName = `new_wgt_${Date.now()}.wgt`
entry.copyTo(parent, newName, (res) => {
this.tempFilePath = res.fullPath
this.downLoadComplete()
}, failCallback)
}, failCallback)
}, failCallback);
} else {
this.tempFilePath = res.tempFilePath
this.downLoadComplete()
}
}
}
2025-04-09 18:55:14 +08:00
});
//进度条显示
downloadTask.onProgressUpdate(res => {
this.downLoadPercent = res.progress;
this.downloadedSize = (res.totalBytesWritten / Math.pow(1024, 2)).toFixed(2);
this.packageFileSize = (res.totalBytesExpectedToWrite / Math.pow(1024, 2)).toFixed(2);
if (this.needNotificationProgress && !this.downloadSuccess) {
createNotificationProgress({
title: "升级中心正在下载安装包……",
content: `${this.downLoadPercent}%`,
progress: this.downLoadPercent,
onClick: () => {
this.askAbortDownload()
}
})
}
});
if (this.needNotificationProgress) {
uni.navigateBack()
}
},
//强制更新
downLoadComplete() {
this.downloadSuccess = true;
this.downloading = false;
this.downLoadPercent = 0
this.downloadedSize = 0
this.packageFileSize = 0
downloadTask = null;
if (this.needNotificationProgress) {
finishNotificationProgress({
title: "安装升级包",
content: "下载完成"
})
this.installPackage();
return
}
// 强制更新,直接安装
if (this.is_mandatory) {
this.installPackage();
}
},
//应用包安装
installPackage() {
// #ifdef APP-PLUS
// wgt资源包安装
if (this.isWGT) {
this.installing = true;
}
plus.runtime.install(this.tempFilePath, {
2025-04-09 18:55:14 +08:00
force: false
}, async res => {
2025-04-09 18:55:14 +08:00
this.installing = false;
this.installed = true;
// wgt包安装后会提示 安装成功,是否重启
if (this.isWGT) {
// 强制更新安装完成重启
if (this.is_mandatory) {
uni.showLoading({
icon: 'none',
title: '安装成功,正在重启……'
})
2025-04-09 18:55:14 +08:00
setTimeout(() => {
uni.hideLoading()
2025-04-09 18:55:14 +08:00
this.restart();
}, 1000)
2025-04-09 18:55:14 +08:00
}
} else {
const localFilePathRecord = uni.getStorageSync(localFilePathKey)
2025-04-09 18:55:14 +08:00
uni.setStorageSync(localFilePathKey, {
...localFilePathRecord,
installed: true
})
2025-04-09 18:55:14 +08:00
}
}, async err => {
2025-04-09 18:55:14 +08:00
// 如果是安装之前的包,安装失败后删除之前的包
if (this.installForBeforeFilePath) {
await this.deleteSavedFile(this.installForBeforeFilePath)
2025-04-09 18:55:14 +08:00
this.installForBeforeFilePath = '';
}
// 安装失败需要重新下载安装包
this.installing = false;
this.installed = false;
uni.showModal({
title: '更新失败,请重新下载',
content: err.message,
showCancel: false
});
});
2025-04-09 18:55:14 +08:00
// 非wgt包安装跳出覆盖安装此处直接返回上一页
if (!this.isWGT && !this.is_mandatory) {
uni.navigateBack()
2025-04-09 18:55:14 +08:00
}
// #endif
},
restart() {
this.installed = false;
// #ifdef APP-PLUS
//更新完重启app
plus.runtime.restart();
// #endif
},
saveFile(tempFilePath, version) {
return new Promise((resolve, reject) => {
uni.saveFile({
tempFilePath,
success({
2025-04-09 18:55:14 +08:00
savedFilePath
}) {
uni.setStorageSync(localFilePathKey, {
version,
savedFilePath
})
},
complete() {
resolve()
}
})
})
},
deleteSavedFile(filePath) {
uni.removeStorageSync(localFilePathKey)
return uni.removeSavedFile({
filePath
})
},
jumpToAppStore() {
console.log(1);
plus.runtime.openURL(this.patternId === '101' ? this.upDataPage.url : this.upDataPage.taiGuoUrl);
}
2025-04-09 18:55:14 +08:00
}
}
</script>
<style>
page {
background: transparent;
}
.flex-center {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
justify-content: center;
align-items: center;
}
.mask {
position: fixed;
left: 0;
top: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, .65);
}
.botton-radius {
border-bottom-left-radius: 30rpx;
border-bottom-right-radius: 30rpx;
}
.content {
position: relative;
top: 0;
width: 600rpx;
background-color: #fff;
box-sizing: border-box;
padding: 0 50rpx;
font-family: Source Han Sans CN;
}
.text {
/* #ifndef APP-NVUE */
display: block;
/* #endif */
line-height: 200px;
text-align: center;
color: #FFFFFF;
}
.content-top {
position: absolute;
top: -195rpx;
left: 0;
width: 600rpx;
height: 270rpx;
}
.content-top-text {
font-size: 45rpx;
font-weight: bold;
color: #F8F8FA;
position: absolute;
top: 120rpx;
left: 50rpx;
z-index: 1;
}
.content-header {
height: 70rpx;
}
.title {
font-size: 33rpx;
font-weight: bold;
color: #3DA7FF;
display: flex;
align-items: center;
/* line-height: 38px; */
}
.content-body-version {
color: #fff;
font-size: 12px;
margin-left: 5px;
padding: 2px 6px 2px 6px;
border-radius: 4px;
display: flex;
background: #50aefd;
}
.footer {
height: 150rpx;
display: flex;
align-items: center;
justify-content: space-around;
}
.box-des-scroll {
box-sizing: border-box;
/* padding: 0 40rpx; */
height: 200rpx;
text-align: left;
}
.box-des {
font-size: 26rpx;
color: #000000;
line-height: 50rpx;
}
.progress-box {
width: 100%;
}
.progress {
width: 90%;
height: 40rpx;
/* border-radius: 35px; */
}
.close-img {
width: 70rpx;
height: 70rpx;
z-index: 1000;
position: absolute;
bottom: -120rpx;
left: calc(50% - 70rpx / 2);
}
.content-button {
text-align: center;
flex: 1;
font-size: 30rpx;
font-weight: 400;
color: #FFFFFF;
border-radius: 40rpx;
margin: 0 18rpx;
height: 80rpx;
line-height: 80rpx;
background: linear-gradient(to right, #1785ff, #3DA7FF);
}
.flex-column {
display: flex;
flex-direction: column;
align-items: center;
}
</style>