shop-applet/uni_modules/guyue-updater/pages/updater.vue

348 lines
6.7 KiB
Vue
Raw Normal View History

2024-05-14 17:25:13 +08:00
<template>
<view class="container">
<view class="main" @click.stop="">
<view class="header">
<image src="../assets/bg1.png" class="bg1" />
<image src="../assets/bg2.png" class="bg2" />
<view class="version-title">{{ updateParams.title }}</view>
<view class="version-name" v-if="updateParams.versionName">V{{ updateParams.versionName }}</view>
</view>
<view class="title">更新内容</view>
<view class="content">
<rich-text :nodes="content" />
</view>
<view class="progress" v-if="downloading">
<view class="slider">
<view class="active-slider" :style="{ width: `${progress}%` }">
<view class="bar" />
<view class="dot">
<view class="text">{{ progress }}%</view>
<view class="circle" />
</view>
</view>
</view>
</view>
<view class="button" :class="{'active': !downloading || downloadError}" @click="handleButton">
{{ downloadText }}
</view>
</view>
<view class="bottom" v-if="!updateParams.force" @click="back">
<view class="line" />
<image src="../assets/close.png" class="close" />
</view>
</view>
</template>
<script>
import {
download,
install
} from "../updater";
export default {
data() {
const data = {
updateParams: {},
progress: 0,
downloading: false,
downloadSucc: false,
downloadError: false,
};
return data;
},
computed: {
content() {
return (this.updateParams.content || '').replace(/[\r\n]/gim, '<br/>');
},
downloadText() {
if (this.downloadSucc) {
return this.updateParams.downSucTip;
}
if (this.downloadError) {
return this.updateParams.downErrorTip;
}
if (this.downloading) {
return this.updateParams.downMsgTip;
}
return this.updateParams.updateBtnText;
},
},
onLoad(params) {
const data = {
title: '发现新版本',
updateBtnText: '立即升级',
downMsgTip: '下载中,请稍后',
downSucTip: '下载完成,安装中',
downErrorTip: '下载失败,请重试',
quiet: false,
force: false,
...(JSON.parse(decodeURIComponent(params.data)))
};
this.updateParams = data;
},
onBackPress() {
return this.updateParams.force;
},
methods: {
back() {
if (!this.updateParams.force) {
uni.navigateBack();
}
},
// 开始更新
start() {
if (!this.updateParams.downUrl) {
return;
}
// ios 跳转到appstore.apk、.wgt 直接安装更新
const isResource = ['.apk', '.wgt'].some(ext => this.updateParams.downUrl.toLocaleLowerCase().includes(
ext));
if (plus.os.name !== "Android" || !isResource) {
plus.runtime.openURL(this.updateParams.downUrl);
return;
}
this.downloading = true;
const self = this;
download({
url: self.updateParams.downUrl,
onProgress(progress) {
self.progress = progress;
},
onSuccess(filePath) {
self.downloadSucc = true;
self.downloadError = false;
install(filePath, true);
},
onFail() {
self.downloading = false;
self.downloadSucc = false;
self.downloadError = true;
},
});
},
handleButton() {
if (this.updateParams.brand.length > 0) {
if (plus.os.name == "Android") {
// 跳转安卓应用市场
let appurl = this.updateParams.downUrl //这个是通用应用市场如果想指定某个应用商店需要单独查这个应用商店的包名或scheme及参数
plus.runtime.openURL(appurl)
setTimeout((res) => {
this.back()
}, 1000)
} else {
// 跳转AppStore
plus.runtime.launchApplication({
action: this.updateParams.downUrl,
})
setTimeout((res) => {
this.back()
}, 1000)
}
} else {
if (!this.downloading) {
return this.start();
}
if (this.downloadError) {
this.progress = 0;
this.downloading = false;
this.downloadSucc = false;
this.downloadError = true;
return this.start();
}
}
},
},
};
</script>
<style lang="less">
page {
width: 100vw;
height: 100vh;
background: transparent;
}
.container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.3);
}
.main {
width: 75%;
background-color: #fff;
border-radius: 8rpx;
padding-bottom: 10rpx;
}
.header {
position: relative;
.bg1 {
width: 100%;
height: calc(100vw * 0.375);
border-top-left-radius: 8rpx;
border-top-right-radius: 8rpx;
}
.bg2 {
position: absolute;
top: -40%;
right: 13%;
width: 35.9%;
height: calc(100vw * 0.5441);
}
.version-title {
position: absolute;
top: 13%;
left: 8%;
color: #961c00;
font-size: 40rpx;
}
.version-name {
position: absolute;
top: 36%;
left: 24%;
background-color: #e54139;
color: #fff;
font-size: 26rpx;
line-height: 26rpx;
padding: 8rpx 20rpx;
border-radius: 20rpx;
}
}
.title {
background-color: #ff6d42;
color: #fff;
display: inline-block;
margin-top: 12rpx;
margin-left: 30rpx;
font-size: 26rpx;
line-height: 26rpx;
padding: 8rpx 20rpx;
border-radius: 8rpx;
}
.content {
margin-top: 12rpx;
margin-left: 30rpx;
font-size: 28rpx;
line-height: 2;
max-height: 240rpx;
overflow-y: auto;
}
.button {
margin: 20rpx 30rpx;
background-color: #ffaa00;
color: #fff;
font-size: 30rpx;
text-align: center;
padding: 20rpx 0;
border-radius: 14rpx;
opacity: 0.5;
pointer-events: none;
&:active {
opacity: 0.6;
}
&.active {
opacity: 1;
pointer-events: initial;
}
}
.progress {
padding: 50rpx 50rpx 18rpx;
.slider {
position: relative;
width: 100%;
height: 10rpx;
border-radius: 5rpx;
background-color: #e2e2e2;
.active-slider {
display: flex;
flex-direction: row;
align-items: center;
position: absolute;
left: 0;
top: 0;
width: 0%;
height: 10rpx;
border-radius: 5rpx;
.bar {
flex: 1;
height: 100%;
background-color: #e84116;
border-top-left-radius: 5rpx;
border-bottom-left-radius: 5rpx;
}
.dot {
position: relative;
margin-left: -12rpx;
.text {
position: absolute;
top: -34rpx;
left: -50%;
color: #e84116;
font-size: 24rpx;
font-weight: 500;
}
.circle {
width: 12rpx;
height: 12rpx;
border: 6rpx solid #e84116;
border-radius: 50%;
background-color: #fff;
}
}
}
}
}
.bottom {
display: flex;
flex-direction: column;
align-items: center;
.line {
width: 3rpx;
height: 50rpx;
background-color: #fff;
}
.close {
width: 64rpx;
height: 64rpx;
margin-top: -4rpx;
}
}
</style>