重构 Play.vue 组件,拆分为多个子组件,提升代码可维护性和可读性。

主要变更:
- 将 Play.vue 拆分为 LoadingOverlay、SelectRegion、ScanPage、GamePage、RefreshWaitPage、ErrorPage 等组件
- 新增 composables 目录,分离业务逻辑(usePlayState、useTimers、useQrCode)
- 优化代码结构,提升开发效率和维护性

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
zyh
2025-08-29 19:03:56 +08:00
parent a8083088c6
commit 7497817640
12 changed files with 3578 additions and 1612 deletions

View File

@@ -0,0 +1,185 @@
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://2.uzi0.cc/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
}
}