519 lines
14 KiB
JavaScript
519 lines
14 KiB
JavaScript
import { reactive } from 'vue'
|
||
import { useRoute, useRouter } from 'vue-router'
|
||
import { ElMessage } from 'element-plus'
|
||
import {
|
||
getLinkStatus,
|
||
selectRegion as selectRegionAPI,
|
||
refreshLink as refreshLinkAPI,
|
||
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,
|
||
regionDesc: null,
|
||
qrInfo: null,
|
||
assets: null,
|
||
currentPoints: 0,
|
||
totalPoints: null, // 修改:初始值改为null,等待从API获取真实数据
|
||
completedPoints: 0,
|
||
progressDisplayFormat: '1',
|
||
error: null,
|
||
qrDelaySeconds: 0,
|
||
isWaitingQr: false,
|
||
qrRetryCount: 0,
|
||
maxQrRetries: 3,
|
||
qrRetryDelay: 2000,
|
||
qrError: null,
|
||
mecmachineId: null,
|
||
machineId: null,
|
||
qrCreatedAt: null,
|
||
qrExpireAt: null,
|
||
qrDelayTimeoutId: null,
|
||
completedAt: null,
|
||
isCompletedExpired: false
|
||
})
|
||
|
||
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)
|
||
|
||
// 如果是NEW状态,尝试获取游戏界面数据以获取totalPoints
|
||
if (data.status === 'NEW') {
|
||
try {
|
||
const gameResponse = await getGameInterfaceAPI(state.code)
|
||
const gameData = gameResponse.data
|
||
console.log('NEW状态 - 游戏界面数据:', gameData)
|
||
|
||
// 更新totalPoints和其他可用数据
|
||
if (gameData.totalPoints !== undefined && gameData.totalPoints !== null) {
|
||
state.totalPoints = gameData.totalPoints
|
||
console.log('从游戏界面获取到totalPoints:', state.totalPoints)
|
||
}
|
||
|
||
if (gameData.completedPoints !== undefined) {
|
||
state.completedPoints = gameData.completedPoints
|
||
}
|
||
|
||
if (gameData.progressDisplayFormat) {
|
||
state.progressDisplayFormat = String(gameData.progressDisplayFormat)
|
||
}
|
||
} catch (gameError) {
|
||
// 游戏界面数据获取失败不影响主流程,只记录日志
|
||
console.log('NEW状态获取游戏界面数据失败(这是正常的):', gameError.message)
|
||
}
|
||
}
|
||
} 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'
|
||
|
||
state.assets = {
|
||
qrCodeUrl: gameData.mecmachineId ? `https://uzi1.cn/image/${gameData.mecmachineId}/二维码.png?t=${Date.now()}` : 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.regionDesc) {
|
||
state.regionDesc = gameData.regionDesc
|
||
}
|
||
|
||
if (gameData.mecmachineId) {
|
||
state.mecmachineId = gameData.mecmachineId
|
||
}
|
||
|
||
if (gameData.machineId) {
|
||
state.machineId = gameData.machineId
|
||
}
|
||
|
||
if (gameData.totalPoints) {
|
||
state.totalPoints = gameData.totalPoints
|
||
} else if (gameData.assets && gameData.assets.totalPoints) {
|
||
state.totalPoints = gameData.assets.totalPoints
|
||
}
|
||
|
||
state.completedPoints = gameData.completedPoints || 0
|
||
if (gameData.progressDisplayFormat) {
|
||
state.progressDisplayFormat = String(gameData.progressDisplayFormat)
|
||
}
|
||
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'
|
||
|
||
// 保存完成时间戳
|
||
if (gameData.completedAt) {
|
||
state.completedAt = gameData.completedAt
|
||
|
||
// 判断是否超过24小时
|
||
const now = Math.floor(Date.now() / 1000) // 当前时间戳(秒)
|
||
const completedTime = gameData.completedAt
|
||
const hoursPassed = (now - completedTime) / 3600 // 转换为小时
|
||
|
||
state.isCompletedExpired = hoursPassed > 24
|
||
|
||
console.log('完成时间判断:', {
|
||
completedAt: completedTime,
|
||
now: now,
|
||
hoursPassed: hoursPassed.toFixed(2),
|
||
isExpired: state.isCompletedExpired
|
||
})
|
||
}
|
||
|
||
// 更新区域和机器信息
|
||
if (gameData.region) {
|
||
state.region = gameData.region
|
||
}
|
||
|
||
if (gameData.regionDesc) {
|
||
state.regionDesc = gameData.regionDesc
|
||
}
|
||
|
||
if (gameData.mecmachineId) {
|
||
state.mecmachineId = gameData.mecmachineId
|
||
}
|
||
|
||
if (gameData.machineId) {
|
||
state.machineId = gameData.machineId
|
||
}
|
||
|
||
state.assets = {
|
||
qrCodeUrl: gameData.mecmachineId ? `https://uzi1.cn/image/${gameData.mecmachineId}/二维码.png?t=${Date.now()}` : null
|
||
}
|
||
|
||
state.totalPoints = gameData.totalPoints || 50
|
||
state.completedPoints = gameData.completedPoints || state.totalPoints
|
||
if (gameData.progressDisplayFormat) {
|
||
state.progressDisplayFormat = String(gameData.progressDisplayFormat)
|
||
}
|
||
state.currentPoints = state.totalPoints
|
||
|
||
console.log('已完成状态更新完成:', {
|
||
status: state.status,
|
||
totalPoints: state.totalPoints,
|
||
completedPoints: state.completedPoints,
|
||
currentPoints: state.currentPoints,
|
||
completedAt: state.completedAt,
|
||
isCompletedExpired: state.isCompletedExpired,
|
||
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.regionDesc = data.regionDesc || null
|
||
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
|
||
}
|
||
|
||
// 优先使用 data.totalPoints,确保在NEW状态也能获取到目标点数
|
||
if (data.totalPoints !== undefined && data.totalPoints !== null) {
|
||
state.totalPoints = data.totalPoints
|
||
}
|
||
|
||
if (data.completedPoints !== undefined) {
|
||
state.completedPoints = data.completedPoints
|
||
}
|
||
|
||
if (data.progressDisplayFormat) {
|
||
state.progressDisplayFormat = String(data.progressDisplayFormat)
|
||
}
|
||
|
||
// 如果assets中有totalPoints,也更新
|
||
if (data.assets && data.assets.totalPoints !== undefined && data.assets.totalPoints !== null) {
|
||
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,
|
||
dataTotalPoints: data.totalPoints,
|
||
stateTotalPoints: state.totalPoints,
|
||
completedPoints: state.completedPoints,
|
||
skipQrProcessing
|
||
})
|
||
|
||
if (skipQrProcessing) {
|
||
return
|
||
}
|
||
|
||
if (data.mecmachineId) {
|
||
const qrUrl = `https://uzi1.cn/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.machineId) return null
|
||
|
||
const progress = getProgressPercent()
|
||
const baseUrl = 'https://uzi1.cn/image'
|
||
|
||
if (progress === 0) {
|
||
return `${baseUrl}/${state.machineId}/首次主页.png`
|
||
} else if (progress < 50) {
|
||
return `${baseUrl}/${state.machineId}/首次赏金.png`
|
||
} else if (progress < 100) {
|
||
return `${baseUrl}/${state.machineId}/中途赏金.png`
|
||
} else {
|
||
return `${baseUrl}/${state.machineId}/结束赏金.png`
|
||
}
|
||
}
|
||
|
||
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
|
||
}
|
||
} |