first commit

This commit is contained in:
wtq
2025-11-13 10:16:36 +08:00
commit cbdb6758a0
394 changed files with 57767 additions and 0 deletions

View File

@@ -0,0 +1,463 @@
<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>