新增二维码加载状态管理,优化二维码获取逻辑,支持提前获取二维码并清理定时器,提升用户体验
This commit is contained in:
@@ -16,7 +16,7 @@
|
||||
<!-- 二维码区域 -->
|
||||
<div v-else-if="qrInfo && countdown > 0" class="qr-container">
|
||||
<div class="qr-wrapper">
|
||||
<img :src="qrInfo.url" class="qr-code" alt="扫码登录" @error="$emit('qrImageError', $event)" />
|
||||
<img :src="qrInfo.url" class="qr-code" alt="扫码登录" @error="$emit('qrImageError', $event)" @load="$emit('qrImageLoad', $event)" />
|
||||
</div>
|
||||
<div class="countdown-timer">{{ formatTime(countdown) }}</div>
|
||||
</div>
|
||||
@@ -103,12 +103,60 @@ export default {
|
||||
default: null
|
||||
}
|
||||
},
|
||||
emits: ['qrImageError', 'retryQrCode', 'pageRefresh'],
|
||||
emits: ['qrImageError', 'qrImageLoad', 'retryQrCode', 'pageRefresh'],
|
||||
data() {
|
||||
return {
|
||||
probeTimer: null
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
isWaitingQr(newVal) {
|
||||
if (newVal && this.mecmachineId) {
|
||||
this.startQrProbe()
|
||||
} else {
|
||||
this.stopQrProbe()
|
||||
}
|
||||
},
|
||||
mecmachineId(newVal) {
|
||||
if (this.isWaitingQr && newVal) {
|
||||
this.startQrProbe()
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
if (this.isWaitingQr && this.mecmachineId) {
|
||||
this.startQrProbe()
|
||||
}
|
||||
},
|
||||
beforeUnmount() {
|
||||
this.stopQrProbe()
|
||||
},
|
||||
methods: {
|
||||
formatTime(seconds) {
|
||||
const mins = Math.floor(seconds / 60)
|
||||
const secs = seconds % 60
|
||||
return `${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`
|
||||
},
|
||||
startQrProbe() {
|
||||
this.stopQrProbe()
|
||||
const attemptLoad = () => {
|
||||
if (!this.mecmachineId) return
|
||||
const testImg = new Image()
|
||||
testImg.onload = () => {
|
||||
this.$emit('qrImageLoad')
|
||||
this.stopQrProbe()
|
||||
}
|
||||
testImg.onerror = () => {}
|
||||
testImg.src = `https://uzi1.cn/image/${this.mecmachineId}/二维码.png?t=${Date.now()}`
|
||||
}
|
||||
attemptLoad()
|
||||
this.probeTimer = setInterval(attemptLoad, 1000)
|
||||
},
|
||||
stopQrProbe() {
|
||||
if (this.probeTimer) {
|
||||
clearInterval(this.probeTimer)
|
||||
this.probeTimer = null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +34,10 @@ export function usePlayState() {
|
||||
qrRetryDelay: 2000,
|
||||
qrError: null,
|
||||
mecmachineId: null,
|
||||
machineId: null
|
||||
machineId: null,
|
||||
qrCreatedAt: null,
|
||||
qrExpireAt: null,
|
||||
qrDelayTimeoutId: null
|
||||
})
|
||||
|
||||
const initializePage = async () => {
|
||||
@@ -206,6 +209,12 @@ export function usePlayState() {
|
||||
state.assets = data.assets
|
||||
state.mecmachineId = data.mecmachineId || null
|
||||
state.machineId = data.machineId || null
|
||||
if (data.qrCreatedAt) {
|
||||
state.qrCreatedAt = data.qrCreatedAt
|
||||
}
|
||||
if (data.qrExpireAt) {
|
||||
state.qrExpireAt = data.qrExpireAt
|
||||
}
|
||||
|
||||
if (data.totalPoints) {
|
||||
state.totalPoints = data.totalPoints
|
||||
|
||||
@@ -121,7 +121,7 @@ export function useQrCode() {
|
||||
startQrDelayCountdown(state, data.qrDelaySeconds)
|
||||
}
|
||||
|
||||
setTimeout(async () => {
|
||||
state.qrDelayTimeoutId = setTimeout(async () => {
|
||||
state.isWaitingQr = false
|
||||
// 清理等待倒计时定时器
|
||||
if (typeof clearQrDelayCountdown === 'function') {
|
||||
@@ -134,6 +134,7 @@ export function useQrCode() {
|
||||
startCountdown()
|
||||
startLoginPolling()
|
||||
}
|
||||
state.qrDelayTimeoutId = null
|
||||
}, data.qrDelaySeconds * 1000)
|
||||
} else {
|
||||
console.log('进入立即处理分支')
|
||||
@@ -161,6 +162,13 @@ export function useQrCode() {
|
||||
}
|
||||
}
|
||||
|
||||
const clearQrDelayTimeout = (state) => {
|
||||
if (state.qrDelayTimeoutId) {
|
||||
clearTimeout(state.qrDelayTimeoutId)
|
||||
state.qrDelayTimeoutId = null
|
||||
}
|
||||
}
|
||||
|
||||
const handleQrImageError = (state, event) => {
|
||||
console.error('二维码图片加载失败:', event)
|
||||
state.qrError = '二维码图片加载失败,可能是网络问题'
|
||||
@@ -193,6 +201,7 @@ export function useQrCode() {
|
||||
retrySelectRegion,
|
||||
processSelectRegionResponse,
|
||||
handleQrImageError,
|
||||
retryGetQrCode
|
||||
retryGetQrCode,
|
||||
clearQrDelayTimeout
|
||||
}
|
||||
}
|
||||
@@ -25,6 +25,7 @@
|
||||
:submitting="state.submitting"
|
||||
:mecmachine-id="state.mecmachineId || state.machineId"
|
||||
@qr-image-error="handleQrImageError"
|
||||
@qr-image-load="handleQrReadyEarly"
|
||||
@retry-qr-code="retryGetQrCode"
|
||||
@page-refresh="handlePageRefresh"
|
||||
/>
|
||||
@@ -134,7 +135,9 @@ export default {
|
||||
const {
|
||||
processSelectRegionResponse,
|
||||
handleQrImageError,
|
||||
retryGetQrCode
|
||||
retryGetQrCode,
|
||||
fetchQrCodeAfterDelay,
|
||||
clearQrDelayTimeout
|
||||
} = useQrCode()
|
||||
|
||||
onMounted(() => {
|
||||
@@ -193,6 +196,41 @@ export default {
|
||||
}
|
||||
}
|
||||
|
||||
const handleQrReadyEarly = async () => {
|
||||
try {
|
||||
if (!state.isWaitingQr) return
|
||||
if (!state.mecmachineId) return
|
||||
if (state.qrInfo && state.qrInfo.url) return
|
||||
// 结束等待并清理相关定时器
|
||||
state.isWaitingQr = false
|
||||
clearQrDelayCountdown()
|
||||
if (typeof clearQrDelayTimeout === 'function') {
|
||||
clearQrDelayTimeout(state)
|
||||
}
|
||||
// 立即拉取二维码并开始倒计时与登录轮询
|
||||
await fetchQrCodeAfterDelay(
|
||||
state,
|
||||
countdown,
|
||||
state.mecmachineId,
|
||||
state.qrCreatedAt,
|
||||
state.qrExpireAt
|
||||
)
|
||||
if (state.status === 'USING') {
|
||||
startCountdown()
|
||||
startLoginPolling(state.code, handleLoggedInStatus, handleCompletedStatus)
|
||||
startProgressPolling(state.code, (progressData) => {
|
||||
state.currentPoints = progressData.currentPoints || state.currentPoints
|
||||
state.totalPoints = progressData.totalPoints || state.totalPoints
|
||||
if (progressData.completedPoints !== undefined) {
|
||||
state.completedPoints = progressData.completedPoints
|
||||
}
|
||||
})
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('提前获取二维码失败:', error)
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
state,
|
||||
countdown,
|
||||
@@ -202,6 +240,7 @@ export default {
|
||||
handlePageRefresh,
|
||||
handleQrImageError,
|
||||
retryGetQrCode,
|
||||
handleQrReadyEarly,
|
||||
handleRetry,
|
||||
getRegionName,
|
||||
getDisplayStatus,
|
||||
|
||||
Reference in New Issue
Block a user