Files
login_task_web/src/composables/useQrCode.js

185 lines
6.1 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { ElMessage } from 'element-plus'
import { selectRegion as selectRegionAPI } from '@/api/play'
export function useQrCode() {
const validateQrCodeUrl = async (url) => {
try {
console.log('开始验证二维码URL:', url)
if (!url || typeof url !== 'string') {
console.error('无效的二维码URL:', url)
return false
}
if (process.env.NODE_ENV === 'production') {
console.log('生产环境跳过URL验证')
return true
}
const controller = new AbortController()
const timeoutId = setTimeout(() => {
controller.abort()
console.log('URL验证超时')
}, 3000)
const response = await fetch(url, {
method: 'HEAD',
signal: controller.signal,
mode: 'no-cors'
})
clearTimeout(timeoutId)
console.log('URL验证响应:', response.status)
return true
} catch (error) {
console.warn('二维码URL验证失败:', error.name, error.message)
return true
}
}
const fetchQrCodeAfterDelay = async (state, countdown, mecmachineId, qrCreatedAt, qrExpireAt, retryCount = 0) => {
try {
const qrCodeUrl = `https://uzi1.cn/image/${mecmachineId}/二维码.png?t=${Date.now()}`
console.log(`尝试获取二维码 (第${retryCount + 1}次):`, qrCodeUrl)
const isUrlValid = await validateQrCodeUrl(qrCodeUrl)
console.log('URL验证结果:', isUrlValid)
if (!isUrlValid) {
throw new Error('二维码URL无法访问')
}
console.log('设置二维码信息:', { qrCodeUrl, qrCreatedAt, qrExpireAt })
state.qrInfo = {
url: qrCodeUrl,
createdAt: qrCreatedAt,
expireAt: qrExpireAt
}
const now = Date.now()
const expireTime = new Date(qrExpireAt).getTime()
countdown.value = Math.max(0, Math.floor((expireTime - now) / 1000))
state.qrRetryCount = 0
state.isWaitingQr = false
console.log('二维码设置完成countdown:', countdown.value)
ElMessage.success('二维码已准备就绪,请扫码登录')
} catch (error) {
console.error(`二维码获取失败 (第${retryCount + 1}次):`, error.message || error)
if (retryCount < state.maxQrRetries) {
state.qrRetryCount = retryCount + 1
const delay = state.qrRetryDelay * Math.pow(2, retryCount)
console.log(`${delay}ms后进行第${retryCount + 2}次重试`)
ElMessage.warning(`二维码获取失败,${delay/1000}秒后重试...`)
setTimeout(() => {
fetchQrCodeAfterDelay(state, countdown, mecmachineId, qrCreatedAt, qrExpireAt, retryCount + 1)
}, delay)
} else {
console.error('二维码获取重试次数用完,显示错误状态')
state.qrRetryCount = 0
state.isWaitingQr = false
state.qrError = `二维码获取失败,已重试${state.maxQrRetries}次。可能是网络问题或服务器繁忙,请稍后重试。`
ElMessage.error('二维码获取失败,请点击重新获取按钮')
}
}
}
const retrySelectRegion = async (state, code, region) => {
try {
console.log('重试选择区域:', region)
const response = await selectRegionAPI({ code, region })
const data = response.data
console.log('retrySelectRegion 响应数据:', data)
return data
} catch (error) {
console.error('重试选择区域失败:', error)
ElMessage.error('重新请求二维码失败,请手动刷新页面')
throw error
}
}
const processSelectRegionResponse = async (state, countdown, data, startCountdown, startLoginPolling, updateStateFromResponse) => {
if (data.qrDelaySeconds && data.qrDelaySeconds > 0 && data.mecmachineId) {
console.log('进入延迟分支')
await updateStateFromResponse(data, true)
state.qrDelaySeconds = data.qrDelaySeconds
state.isWaitingQr = true
console.log('设置状态:', { status: state.status, isWaitingQr: state.isWaitingQr })
ElMessage.info(`正在准备二维码,请等待 ${data.qrDelaySeconds} 秒...`)
setTimeout(async () => {
state.isWaitingQr = false
await fetchQrCodeAfterDelay(state, countdown, data.mecmachineId, data.qrCreatedAt, data.qrExpireAt)
if (state.status === 'USING') {
startCountdown()
startLoginPolling()
}
}, data.qrDelaySeconds * 1000)
} else {
console.log('进入立即处理分支')
await updateStateFromResponse(data)
state.isWaitingQr = false
console.log('设置状态:', { status: state.status, isWaitingQr: state.isWaitingQr, qrInfo: !!state.qrInfo })
if (state.qrInfo && state.qrInfo.url) {
const isUrlValid = await validateQrCodeUrl(state.qrInfo.url)
if (!isUrlValid) {
console.warn('立即获取的二维码URL无法访问尝试重试')
state.qrInfo = null
await fetchQrCodeAfterDelay(state, countdown, data.mecmachineId, data.qrCreatedAt, data.qrExpireAt)
}
}
if (state.status === 'USING') {
startCountdown()
startLoginPolling()
}
}
}
const handleQrImageError = (state, event) => {
console.error('二维码图片加载失败:', event)
state.qrError = '二维码图片加载失败,可能是网络问题'
ElMessage.error('二维码图片加载失败')
}
const retryGetQrCode = async (state, selectRegion) => {
if (state.submitting) return
state.submitting = true
state.qrError = null
state.isWaitingQr = true
state.qrRetryCount = 0
try {
if (state.region) {
await selectRegion(state.region)
}
} catch (error) {
console.error('重新获取二维码失败:', error)
state.qrError = '重新获取失败,请刷新页面重试'
} finally {
state.submitting = false
}
}
return {
validateQrCodeUrl,
fetchQrCodeAfterDelay,
retrySelectRegion,
processSelectRegionResponse,
handleQrImageError,
retryGetQrCode
}
}