重构 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:
437
src/composables/usePlayState.js
Normal file
437
src/composables/usePlayState.js
Normal file
@@ -0,0 +1,437 @@
|
||||
import { reactive } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import {
|
||||
getLinkStatus,
|
||||
selectRegion as selectRegionAPI,
|
||||
refreshLink as refreshLinkAPI,
|
||||
pollLoginStatus,
|
||||
getGameProgress,
|
||||
getGameInterface as getGameInterfaceAPI
|
||||
} from '@/api/play'
|
||||
|
||||
export function usePlayState() {
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
|
||||
const state = reactive({
|
||||
code: '',
|
||||
status: 'NEW',
|
||||
loading: true,
|
||||
submitting: false,
|
||||
needRefresh: false,
|
||||
region: null,
|
||||
qrInfo: null,
|
||||
assets: null,
|
||||
currentPoints: 0,
|
||||
totalPoints: 1000,
|
||||
completedPoints: 0,
|
||||
error: null,
|
||||
qrDelaySeconds: 0,
|
||||
isWaitingQr: false,
|
||||
qrRetryCount: 0,
|
||||
maxQrRetries: 3,
|
||||
qrRetryDelay: 2000,
|
||||
qrError: null,
|
||||
mecmachineId: null
|
||||
})
|
||||
|
||||
const initializePage = async () => {
|
||||
try {
|
||||
await fetchStatus()
|
||||
} catch (error) {
|
||||
handleError(error)
|
||||
} finally {
|
||||
state.loading = false
|
||||
}
|
||||
}
|
||||
|
||||
const fetchStatus = async () => {
|
||||
try {
|
||||
const response = await getLinkStatus(state.code)
|
||||
const data = response.data
|
||||
await updateStateFromResponse(data)
|
||||
} catch (error) {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
const getGameInterface = async () => {
|
||||
try {
|
||||
console.log('调用游戏界面接口,code:', state.code)
|
||||
const response = await getGameInterfaceAPI(state.code)
|
||||
console.log('游戏界面接口响应:', response.data)
|
||||
return response
|
||||
} catch (error) {
|
||||
console.error('获取游戏界面数据失败:', error)
|
||||
ElMessage.error('获取游戏界面数据失败')
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
const handleLoggedInStatus = async () => {
|
||||
try {
|
||||
console.log('检测到LOGGED_IN状态,获取游戏界面数据')
|
||||
const gameResponse = await getGameInterface()
|
||||
const gameData = gameResponse.data
|
||||
|
||||
console.log('游戏界面数据:', gameData)
|
||||
|
||||
state.status = 'LOGGED_IN'
|
||||
|
||||
if(gameData.status == "COMPLETED"){
|
||||
state.assets = {
|
||||
homepageUrl: gameData.homepageUrl,
|
||||
firstRewardUrl: gameData.firstRewardUrl,
|
||||
midRewardUrl: gameData.midRewardUrl,
|
||||
endRewardUrl: gameData.endRewardUrl,
|
||||
qrCodeUrl: gameData.mecmachineId ? `https://2.uzi0.cc/image/${gameData.mecmachineId}/二维码.png?t=${new Date().getTime()}` : null,
|
||||
...(gameData.assets || {})
|
||||
}
|
||||
} else {
|
||||
state.assets = {
|
||||
homepageUrl: gameData.mecmachineId ? `https://2.uzi0.cc/image/${gameData.mecmachineId}/首次主页.png?t=${new Date().getTime()}` : null,
|
||||
firstRewardUrl: gameData.mecmachineId ? `https://2.uzi0.cc/image/${gameData.mecmachineId}/首次赏金.png?t=${new Date().getTime()}` : null,
|
||||
midRewardUrl: gameData.mecmachineId ? `https://2.uzi0.cc/image/${gameData.mecmachineId}/中途赏金.png?t=${new Date().getTime()}` : null,
|
||||
endRewardUrl: gameData.mecmachineId ? `https://2.uzi0.cc/image/${gameData.mecmachineId}/结束赏金.png?t=${new Date().getTime()}` : null,
|
||||
qrCodeUrl: gameData.mecmachineId ? `https://2.uzi0.cc/image/${gameData.mecmachineId}/二维码.png?t=${new Date().getTime()}` : null,
|
||||
...(gameData.assets || {})
|
||||
}
|
||||
}
|
||||
|
||||
console.log('更新区域信息:', {
|
||||
gameDataRegion: gameData.region,
|
||||
originalStateRegion: state.region
|
||||
})
|
||||
if (gameData.region) {
|
||||
state.region = gameData.region
|
||||
console.log('已设置 state.region =', state.region)
|
||||
} else {
|
||||
console.log('gameData.region 为空,未更新 state.region')
|
||||
}
|
||||
|
||||
if (gameData.mecmachineId) {
|
||||
state.mecmachineId = gameData.mecmachineId
|
||||
}
|
||||
|
||||
if (gameData.totalPoints) {
|
||||
state.totalPoints = gameData.totalPoints
|
||||
} else if (gameData.assets && gameData.assets.totalPoints) {
|
||||
state.totalPoints = gameData.assets.totalPoints
|
||||
}
|
||||
|
||||
state.completedPoints = gameData.completedPoints || 0
|
||||
state.currentPoints = 0
|
||||
|
||||
console.log('handleLoggedInStatus 执行完成,最终状态:', {
|
||||
status: state.status,
|
||||
region: state.region,
|
||||
totalPoints: state.totalPoints,
|
||||
completedPoints: state.completedPoints,
|
||||
mecmachineId: state.mecmachineId
|
||||
})
|
||||
|
||||
ElMessage.success('登录成功,正在进入游戏界面...')
|
||||
|
||||
} catch (error) {
|
||||
console.error('获取游戏界面数据失败:', error)
|
||||
ElMessage.error('获取游戏数据失败,请稍后重试')
|
||||
}
|
||||
}
|
||||
|
||||
const handleCompletedStatus = async () => {
|
||||
try {
|
||||
const gameResponse = await getGameInterfaceAPI(state.code)
|
||||
const gameData = gameResponse.data
|
||||
|
||||
console.log('已完成状态 - 游戏界面数据:', gameData)
|
||||
|
||||
state.status = 'COMPLETED'
|
||||
|
||||
state.assets = {
|
||||
homepageUrl: gameData.homepageUrl,
|
||||
firstRewardUrl: gameData.firstRewardUrl,
|
||||
midRewardUrl: gameData.midRewardUrl,
|
||||
endRewardUrl: gameData.endRewardUrl,
|
||||
qrCodeUrl: gameData.mecmachineId ? `https://2.uzi0.cc/image/${gameData.mecmachineId}/二维码.png?t=${Date.now()}` : null
|
||||
}
|
||||
|
||||
state.totalPoints = gameData.totalPoints || 50
|
||||
state.completedPoints = gameData.completedPoints || state.totalPoints
|
||||
state.currentPoints = state.totalPoints
|
||||
|
||||
console.log('已完成状态更新完成:', {
|
||||
status: state.status,
|
||||
totalPoints: state.totalPoints,
|
||||
completedPoints: state.completedPoints,
|
||||
currentPoints: state.currentPoints,
|
||||
assets: !!state.assets
|
||||
})
|
||||
|
||||
} catch (error) {
|
||||
console.error('获取已完成状态游戏数据失败:', error)
|
||||
state.status = 'COMPLETED'
|
||||
ElMessage.error('获取游戏数据失败,但订单已完成')
|
||||
}
|
||||
}
|
||||
|
||||
const updateStateFromResponse = async (data, skipQrProcessing = false) => {
|
||||
if (data.status === 'LOGGED_IN') {
|
||||
await handleLoggedInStatus()
|
||||
return
|
||||
}
|
||||
|
||||
if (data.status === 'COMPLETED') {
|
||||
await handleCompletedStatus()
|
||||
return
|
||||
}
|
||||
|
||||
state.status = data.status
|
||||
state.needRefresh = data.needRefresh || false
|
||||
state.region = data.region
|
||||
state.assets = data.assets
|
||||
state.mecmachineId = data.mecmachineId || null
|
||||
|
||||
if (data.totalPoints) {
|
||||
state.totalPoints = data.totalPoints
|
||||
}
|
||||
|
||||
if (data.completedPoints !== undefined) {
|
||||
state.completedPoints = data.completedPoints
|
||||
}
|
||||
|
||||
if (data.assets && data.assets.totalPoints) {
|
||||
state.totalPoints = data.assets.totalPoints
|
||||
if (state.currentPoints === undefined) {
|
||||
state.currentPoints = 0
|
||||
}
|
||||
}
|
||||
|
||||
console.log('updateStateFromResponse:', {
|
||||
status: data.status,
|
||||
dataRegion: data.region,
|
||||
stateRegion: state.region,
|
||||
mecmachineId: data.mecmachineId,
|
||||
totalPoints: state.totalPoints,
|
||||
completedPoints: state.completedPoints,
|
||||
skipQrProcessing
|
||||
})
|
||||
|
||||
if (skipQrProcessing) {
|
||||
return
|
||||
}
|
||||
|
||||
if (data.mecmachineId) {
|
||||
const qrUrl = `https://2.uzi0.cc/image/${data.mecmachineId}/二维码.png?t=${Date.now()}`
|
||||
state.qrInfo = {
|
||||
url: qrUrl,
|
||||
createdAt: data.qrCreatedAt,
|
||||
expireAt: data.qrExpireAt
|
||||
}
|
||||
} else if (data.qr) {
|
||||
state.qrInfo = data.qr
|
||||
}
|
||||
}
|
||||
|
||||
const selectRegion = async (region) => {
|
||||
if (state.submitting) return
|
||||
|
||||
state.submitting = true
|
||||
state.qrRetryCount = 0
|
||||
|
||||
try {
|
||||
const response = await selectRegionAPI({ code: state.code, region })
|
||||
const data = response.data
|
||||
|
||||
console.log('selectRegion 响应数据:', data)
|
||||
return data
|
||||
|
||||
} catch (error) {
|
||||
handleError(error)
|
||||
throw error
|
||||
} finally {
|
||||
state.submitting = false
|
||||
}
|
||||
}
|
||||
|
||||
const handleRefresh = async (clearAllTimers) => {
|
||||
try {
|
||||
const response = await refreshLinkAPI(state.code)
|
||||
const data = response.data
|
||||
|
||||
if (clearAllTimers) {
|
||||
clearAllTimers()
|
||||
}
|
||||
|
||||
state.needRefresh = false
|
||||
state.status = 'NEW'
|
||||
|
||||
return data
|
||||
|
||||
} catch (error) {
|
||||
handleError(error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
const handlePageRefresh = () => {
|
||||
window.location.reload()
|
||||
}
|
||||
|
||||
const handleRetry = () => {
|
||||
state.error = null
|
||||
state.loading = true
|
||||
initializePage()
|
||||
}
|
||||
|
||||
const handleError = (error) => {
|
||||
console.error('API错误:', error)
|
||||
|
||||
const status = error?.response?.status
|
||||
|
||||
if (status === 401) {
|
||||
console.log('检测到401错误,跳转到登录页面')
|
||||
router.replace({
|
||||
name: 'Login',
|
||||
query: { redirect: route.fullPath }
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if (status === 400 || status === 403) {
|
||||
state.error = 'INVALID_CODE'
|
||||
} else if (status === 410) {
|
||||
state.error = 'EXPIRED'
|
||||
} else {
|
||||
state.error = 'NETWORK_ERROR'
|
||||
}
|
||||
}
|
||||
|
||||
const formatTime = (seconds) => {
|
||||
const mins = Math.floor(seconds / 60)
|
||||
const secs = seconds % 60
|
||||
return `${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`
|
||||
}
|
||||
|
||||
const getRegionName = () => {
|
||||
return state.region === 'Q' ? 'QQ区' : state.region === 'V' ? '微信区' : ''
|
||||
}
|
||||
|
||||
const getCurrentUrl = () => {
|
||||
return window.location.href
|
||||
}
|
||||
|
||||
const getGameStatus = () => {
|
||||
if (state.currentPoints >= state.totalPoints) {
|
||||
return '已打完'
|
||||
} else if (state.currentPoints > 0) {
|
||||
return '代练中'
|
||||
} else {
|
||||
return '空闲'
|
||||
}
|
||||
}
|
||||
|
||||
const getStatusClass = () => {
|
||||
const status = getGameStatus()
|
||||
return {
|
||||
'status-completed': status === '已打完',
|
||||
'status-playing': status === '代练中',
|
||||
'status-idle': status === '空闲'
|
||||
}
|
||||
}
|
||||
|
||||
const getDisplayStatus = () => {
|
||||
if (state.status === 'COMPLETED') {
|
||||
return '已完成'
|
||||
} else if (state.status === 'LOGGED_IN') {
|
||||
return '代练中'
|
||||
} else {
|
||||
return '状态'
|
||||
}
|
||||
}
|
||||
|
||||
const getStatusMessage = () => {
|
||||
if (state.status === 'COMPLETED') {
|
||||
return '代练已完成!感谢您的使用,订单已结束。'
|
||||
} else if (state.status === 'LOGGED_IN') {
|
||||
return '正在代练中,期间请勿操号,耐心等待代练完成......'
|
||||
} else {
|
||||
return '正在代练中,期间请勿操号,耐心等待代练完成......'
|
||||
}
|
||||
}
|
||||
|
||||
const getStatusMessageClass = () => {
|
||||
if (state.status === 'COMPLETED') {
|
||||
return 'status-message-completed'
|
||||
} else {
|
||||
return ''
|
||||
}
|
||||
}
|
||||
|
||||
const getProgressPercent = () => {
|
||||
if (!state.totalPoints) return 0
|
||||
return Math.min(100, (state.currentPoints / state.totalPoints) * 100)
|
||||
}
|
||||
|
||||
const getCurrentGameImage = () => {
|
||||
if (!state.assets) return null
|
||||
|
||||
const progress = getProgressPercent()
|
||||
if (progress === 0) {
|
||||
return state.assets.homepageUrl
|
||||
} else if (progress < 50) {
|
||||
return state.assets.firstRewardUrl
|
||||
} else if (progress < 100) {
|
||||
return state.assets.midRewardUrl
|
||||
} else {
|
||||
return state.assets.endRewardUrl
|
||||
}
|
||||
}
|
||||
|
||||
const getErrorTitle = () => {
|
||||
const titles = {
|
||||
'INVALID_CODE': '链接无效',
|
||||
'EXPIRED': '链接已过期',
|
||||
'REFUNDED': '订单已退单',
|
||||
'NETWORK_ERROR': '网络错误'
|
||||
}
|
||||
return titles[state.error] || '出现错误'
|
||||
}
|
||||
|
||||
const getErrorMessage = () => {
|
||||
const messages = {
|
||||
'INVALID_CODE': '请联系商家获取有效链接',
|
||||
'EXPIRED': '请联系商家重新获取链接',
|
||||
'REFUNDED': '该订单已被退单,无法继续使用',
|
||||
'NETWORK_ERROR': '网络连接失败,请检查网络后重试'
|
||||
}
|
||||
return messages[state.error] || '请稍后重试或联系客服'
|
||||
}
|
||||
|
||||
|
||||
return {
|
||||
state,
|
||||
initializePage,
|
||||
fetchStatus,
|
||||
updateStateFromResponse,
|
||||
handleLoggedInStatus,
|
||||
handleCompletedStatus,
|
||||
selectRegion,
|
||||
handleRefresh,
|
||||
handlePageRefresh,
|
||||
handleRetry,
|
||||
handleError,
|
||||
formatTime,
|
||||
getRegionName,
|
||||
getCurrentUrl,
|
||||
getGameStatus,
|
||||
getStatusClass,
|
||||
getDisplayStatus,
|
||||
getStatusMessage,
|
||||
getStatusMessageClass,
|
||||
getProgressPercent,
|
||||
getCurrentGameImage,
|
||||
getErrorTitle,
|
||||
getErrorMessage
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user