464 lines
12 KiB
Plaintext
464 lines
12 KiB
Plaintext
<template>
|
||
<varsion-popup
|
||
:show="show"
|
||
direction="center"
|
||
:mask-close="release.isForceUpdate"
|
||
>
|
||
<view class="view box-size">
|
||
<image :src="defaultBg" class="box-size absolute"></image>
|
||
<view class="view box-size absolute desc line-4">
|
||
<view class="find-new-version">发现新版本V{{ release.version }}</view>
|
||
<varsion-text
|
||
:color="textColor"
|
||
:text="release.description"
|
||
:lines="lines"
|
||
/>
|
||
</view>
|
||
<view
|
||
class="absolute footer"
|
||
:style="{ marginTop: `${release.isForceUpdate ? 540 : 520}rpx` }"
|
||
>
|
||
<varsion-button
|
||
size="32"
|
||
:disabled="!btnVisible"
|
||
@click="handleUpdate"
|
||
:color="btnTextColor"
|
||
:background="btnBgColor"
|
||
:width="400"
|
||
:radius="40"
|
||
:text="btnText"
|
||
></varsion-button>
|
||
<view
|
||
v-if="!release.isForceUpdate && btnVisible"
|
||
class="items-center-close"
|
||
>
|
||
<view class="blose-btn" @click="close">
|
||
<jx-icon icon="shanchu" :size="90" color="#eee" />
|
||
</view>
|
||
</view>
|
||
<view v-if="!btnVisible" style="margin-top: 10rpx"
|
||
><progress :percent="percent" :color="btnBgColor"></progress
|
||
></view>
|
||
</view>
|
||
</view>
|
||
</varsion-popup>
|
||
</template>
|
||
<script lang="ts" setup>
|
||
import { checkUpdate, downloadFile } from '../../js/api.js'
|
||
import varsionButton from '../varsion-button/varsion-button.nvue'
|
||
import varsionText from '../varsion-text/varsion-text.nvue'
|
||
import varsionPopup from '../varsion-popup/varsion-popup.nvue'
|
||
import defaultBgImg from '../../js/img'
|
||
import { computed, onMounted, ref } from 'vue'
|
||
import { store } from '@/store'
|
||
/**
|
||
* version-update 版本更新
|
||
* @description 版本更新组件
|
||
* @property {String} id 应用id
|
||
* @property {String} version 是否手动传入版本号而不使用系统自动获取的版本
|
||
* @property {Boolean} loading 是否显示加载
|
||
* @property {String} loadingText 加载中文本,默认'检查更新中'
|
||
* @property {String} loadingMask 加载点击遮罩关闭功能是否关闭
|
||
* @property {String, Number} loadingDelay 加载框多久出现,默认1500ms
|
||
* @property {String, Number} lines 超出行省略
|
||
*
|
||
* @property {String, Number} btnBgColor 按钮背景颜色
|
||
* @property {String, Number} btnTextColor 按钮文字颜色
|
||
* @property {String, Number} secondaryBtnText 暂不更新按钮文字,默认以后再说
|
||
* @property {String, Number} secondaryBtnTextColor 暂不更新按钮文字颜色
|
||
*
|
||
* @property {String, Number} textColor 更新说明文字颜色
|
||
* @property {String, Number} bgImage 自定义背景图
|
||
*
|
||
* @property {String, Number} errTimes 安装错误次数超过此值提示打开浏览器下载,一般若由高版本降回低版本会出现无法安装的情况
|
||
* @property {String, Number} auto 是否自动检查新版本,默认true
|
||
*
|
||
* @event {Function()} check 检查事件,获取到版本数据就会触发,适合需要自定义更新弹窗出现逻辑的
|
||
* @event {Function()} finish 完成事件,获取到版本且不用更新触发
|
||
* @event {Function()} error 错误事件,发生错误触发
|
||
*/
|
||
|
||
interface propsType {
|
||
id: string
|
||
apiUrl?: string
|
||
pageUrl?: string
|
||
loading?: boolean
|
||
loadingText?: string
|
||
loadingMask?: boolean
|
||
loadingDelay?: string | number
|
||
lines?: number
|
||
version?: string
|
||
bgImage?: string
|
||
textColor?: string
|
||
btnBgColor?: string
|
||
btnTextColor?: string
|
||
secondaryBtnText?: string
|
||
secondaryBtnTextColor?: string
|
||
errToast?: boolean
|
||
errTimes?: number
|
||
auto?: boolean
|
||
uniqueId?: string
|
||
}
|
||
|
||
const props = withDefaults(defineProps<propsType>(), {
|
||
id: '',
|
||
apiUrl: 'https://wx.jxc4.com/v2/version/GetVersionController',
|
||
pageUrl: 'http://www.jxc4.com/managerApp/downApp.html',
|
||
loading: true,
|
||
loadingText: '检查更新中',
|
||
loadingMask: true,
|
||
loadingDelay: 1500,
|
||
lines: 5,
|
||
textColor: '#1e1e1e',
|
||
btnBgColor: '#04c260',
|
||
btnTextColor: '#FFFFFF',
|
||
secondaryBtnText: '以后再说',
|
||
secondaryBtnTextColor: '#afafaf',
|
||
errToast: true,
|
||
errTimes: 2,
|
||
auto: true,
|
||
})
|
||
|
||
function close() {
|
||
show.value = false
|
||
emit('close', '')
|
||
}
|
||
|
||
const show = ref<boolean>(false)
|
||
const init = ref<boolean>(false)
|
||
const release = ref<AnyObject>({
|
||
needUpdate: true,
|
||
isHBuildUpdate: false,
|
||
isForceUpdate: true,
|
||
version: '0.1.0',
|
||
description: '',
|
||
pkgUrl: '',
|
||
wgtUrl: '',
|
||
})
|
||
const btnVisible = ref<boolean>(true)
|
||
const btnText = ref<string>('立即升级')
|
||
const percent = ref<number>(0)
|
||
const tempPath = ref<string>('')
|
||
const installFlag = ref<boolean>(false)
|
||
const defaultBg = ref<string>(defaultBgImg)
|
||
const nowVersion = ref<string>('')
|
||
const openCount = ref<number>(0)
|
||
|
||
const config = computed(() => {
|
||
return {
|
||
id: props.id,
|
||
apiUrl: props.apiUrl,
|
||
uniqueId: props.uniqueId,
|
||
loading: props.loading,
|
||
loadingText: props.loadingText,
|
||
loadingMask: props.loadingMask,
|
||
loadingDelay: props.loadingDelay,
|
||
}
|
||
})
|
||
|
||
const downUrl = computed(() => {
|
||
if (!release.value.needUpdate) {
|
||
return undefined
|
||
}
|
||
if (!release.value.isHBuildUpdate) {
|
||
return release.value.wgtUrl
|
||
}
|
||
return release.value.pkgUrl
|
||
})
|
||
const isHot = computed(() => {
|
||
return !release.value.isHBuildUpdate
|
||
})
|
||
|
||
const sysInfo = ref<any>('')
|
||
onMounted(() => {
|
||
if (percent.value == 100) {
|
||
btnText.value = '马上安装'
|
||
}
|
||
|
||
if (!props.id) {
|
||
uni.showToast({
|
||
title: '请传入应用id',
|
||
icon: 'none',
|
||
duration: 4000,
|
||
})
|
||
return
|
||
}
|
||
|
||
if (props.auto) {
|
||
init.value = true
|
||
}
|
||
uni.getSystemInfo({
|
||
success: (info) => {
|
||
sysInfo.value = info
|
||
nowVersion.value = sysInfo.value.appWgtVersion || sysInfo.value.appVersion
|
||
check()
|
||
},
|
||
})
|
||
})
|
||
|
||
const emit = defineEmits<{
|
||
(e: 'check', data: any): void
|
||
(e: 'finish', data: any): void
|
||
(e: 'error', data: any): void
|
||
(e: 'close', data: any): void
|
||
}>()
|
||
function check() {
|
||
checkUpdate(props.version || nowVersion.value, sysInfo.value, config.value)
|
||
.then((res) => {
|
||
|
||
if(sysInfo.value.platform === 'ios' && res.appleId.length){
|
||
let str = res.appleId
|
||
res.appleId = str.split(',')[0]
|
||
res.version = str.split(',')[1]
|
||
}
|
||
|
||
release.value = res
|
||
emit('check', res)
|
||
if (res.needUpdate) {
|
||
if (init.value) {
|
||
show.value = true
|
||
}
|
||
} else {
|
||
if (res.isTest) {
|
||
console.log('测试版' + (props.version || nowVersion.value))
|
||
}
|
||
emit('finish', res)
|
||
}
|
||
init.value = true
|
||
})
|
||
.catch((err) => {
|
||
emit('error', err)
|
||
if (props.errToast) {
|
||
uni.showToast({
|
||
title: err,
|
||
icon: 'none',
|
||
duration: 4000,
|
||
})
|
||
}
|
||
})
|
||
}
|
||
|
||
function handleUpdate() {
|
||
if (
|
||
sysInfo.value.uniPlatform === 'web' ||
|
||
sysInfo.value.uniPlatform === 'h5'
|
||
) {
|
||
uni.showToast({
|
||
icon: 'none',
|
||
title: '非app无法安装',
|
||
})
|
||
btnVisible.value = true
|
||
return
|
||
}
|
||
// 如果是ios并且非热更新
|
||
if (sysInfo.value.platform === 'ios' && !isHot.value) {
|
||
if (release.value.appleId) {
|
||
plus.runtime.launchApplication(
|
||
{
|
||
action: `https://apps.apple.com/cn/app/%E4%BA%AC%E8%A5%BF%E8%8F%9C%E5%B8%82%E5%95%86%E5%AE%B6%E7%89%88/${release.value.appleId}`,
|
||
},
|
||
(e) => {
|
||
uni.jxConfirm({
|
||
title: '跳转到appStore失败',
|
||
content: '请向app反馈,错误信息:' + e.message,
|
||
confirmText: '复制错误信息',
|
||
success: () => {
|
||
uni.setClipboardData({
|
||
data: e.message,
|
||
success: () => {},
|
||
})
|
||
},
|
||
})
|
||
}
|
||
)
|
||
} else {
|
||
uni.showToast({
|
||
title: '未配置appleId无法跳转到appStore,请向app反馈',
|
||
icon: 'none',
|
||
duration: 4000,
|
||
})
|
||
}
|
||
return
|
||
}
|
||
if (tempPath.value !== '') {
|
||
openFile()
|
||
return
|
||
}
|
||
if (btnVisible.value) {
|
||
btnVisible.value = false
|
||
downloadFile({
|
||
url: downUrl.value,
|
||
success: (filePath: any) => {
|
||
percent.value = 100
|
||
tempPath.value = filePath
|
||
store.commit('serveInfo/setAppFilePath', filePath)
|
||
btnText.value = '马上安装'
|
||
openFile()
|
||
},
|
||
fail: (e: any) => {
|
||
console.error('下载文件', e)
|
||
installFail()
|
||
btnVisible.value = true
|
||
},
|
||
progress: (progress: any) => {
|
||
percent.value = progress
|
||
if (progress == 100) {
|
||
btnText.value = '马上安装'
|
||
}
|
||
let port = uni.getSystemInfoSync().platform
|
||
switch (port) {
|
||
case 'android':
|
||
const notify = uni.requireNativePlugin('Ba-Notify')
|
||
notify.show({
|
||
extend: progress,
|
||
channelID: '6',
|
||
channelName: '进度通知',
|
||
ID: 6,
|
||
notifyType: 6,
|
||
ticker: 'Ticker',
|
||
title: '京西到家更新',
|
||
content: '正在下载',
|
||
isSound: false,
|
||
isVibrate: false,
|
||
maxProgress: 100,
|
||
progress: progress, //当前进度
|
||
indeterminate: false, //是否模糊进度显示
|
||
finishText: '下载完成',
|
||
})
|
||
break
|
||
case 'ios':
|
||
console.log('iOS不支持此功能')
|
||
break
|
||
}
|
||
},
|
||
})
|
||
}
|
||
}
|
||
|
||
function openFile() {
|
||
btnVisible.value = true
|
||
if (!installFlag.value) {
|
||
installFlag.value = true
|
||
uni.showToast({
|
||
icon: 'none',
|
||
title: isHot.value ? '正在安装中' : '正在打开安装程序',
|
||
success: () => {
|
||
uni.navigateBack()
|
||
},
|
||
})
|
||
if (isHot.value) {
|
||
//热更新
|
||
plus.runtime.install(
|
||
tempPath.value,
|
||
{
|
||
force: false,
|
||
},
|
||
() => {
|
||
uni.hideToast()
|
||
setTimeout(() => {
|
||
plus.runtime.restart()
|
||
}, 100)
|
||
},
|
||
(e) => {
|
||
console.error('热更新失败', e)
|
||
uni.hideToast()
|
||
installFail()
|
||
}
|
||
)
|
||
} else {
|
||
setTimeout(() => {
|
||
uni.openDocument({
|
||
filePath: tempPath.value,
|
||
fail: (e) => {
|
||
console.error('打开apk失败', e)
|
||
installFail()
|
||
},
|
||
complete: () => {
|
||
uni.hideToast()
|
||
installFlag.value = false
|
||
openCount.value++
|
||
if (openCount.value > props.errTimes) {
|
||
installFail()
|
||
}
|
||
},
|
||
})
|
||
}, 500)
|
||
}
|
||
}
|
||
}
|
||
|
||
function installFail() {
|
||
uni.jxConfirm({
|
||
title: '温馨提醒',
|
||
content:
|
||
'请问是否出现安装包损坏或其他原因导致无法正常安装新版本的情况?请前往浏览器下载最新版本手动安装',
|
||
confirmText: '立刻前往',
|
||
success: () => {
|
||
plus.runtime.openURL(props.pageUrl, () => {
|
||
openUrlFail()
|
||
})
|
||
},
|
||
})
|
||
}
|
||
|
||
function openUrlFail() {
|
||
uni.jxConfirm({
|
||
title: '温馨提醒',
|
||
content: '打开浏览器失败,请复制下载地址,手动打开手机浏览器输入地址下载',
|
||
confirmText: '复制',
|
||
success: () => {
|
||
uni.setClipboardData({
|
||
data: props.pageUrl,
|
||
success: () => {},
|
||
})
|
||
},
|
||
})
|
||
}
|
||
</script>
|
||
<style lang="scss" scoped>
|
||
@import '../../css/index.scss';
|
||
|
||
.box-size {
|
||
width: 500rpx;
|
||
height: 650rpx;
|
||
border-radius: 0 0 10rpx 10rpx;
|
||
}
|
||
|
||
.desc {
|
||
margin-top: 250rpx;
|
||
padding: 0 30rpx;
|
||
width: 431rpx;
|
||
}
|
||
|
||
.find-new-version {
|
||
text-align: center;
|
||
margin-bottom: 20rpx;
|
||
font-weight: bold;
|
||
}
|
||
|
||
.desc-text {
|
||
line-height: 44rpx;
|
||
font-size: 30rpx;
|
||
}
|
||
|
||
.items-center-close {
|
||
align-items: center !important;
|
||
/* #ifndef APP-NVUE */
|
||
position: absolute;
|
||
display: flex;
|
||
flex-direction: column;
|
||
width: 500rpx;
|
||
bottom: -200rpx;
|
||
margin-left: -50rpx;
|
||
/* #endif */
|
||
|
||
.blose-btn {
|
||
text-align: center;
|
||
}
|
||
}
|
||
|
||
.footer {
|
||
margin-left: 50rpx;
|
||
}
|
||
</style>
|