185 lines
6.1 KiB
JavaScript
185 lines
6.1 KiB
JavaScript
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
|
||
}
|
||
} |