更新 Play.vue 组件,增加二维码获取失败提示和重试功能;优化状态显示逻辑,新增机器ID信息展示;更新 .env.production 文件,添加 IMAGE_BASE_URL 配置。
This commit is contained in:
@@ -17,18 +17,22 @@
|
||||
@click="selectRegion('Q')"
|
||||
class="region-btn qq-btn"
|
||||
:disabled="state.submitting"
|
||||
:class="{ 'loading': state.submitting }"
|
||||
>
|
||||
<div class="btn-icon">Q</div>
|
||||
<span class="btn-text">QQ区</span>
|
||||
<div v-if="state.submitting" class="loading-spinner small"></div>
|
||||
<div v-else class="btn-icon">Q</div>
|
||||
<span class="btn-text">{{ state.submitting ? '正在连接...' : 'QQ区' }}</span>
|
||||
</button>
|
||||
|
||||
<button
|
||||
@click="selectRegion('V')"
|
||||
class="region-btn wx-btn"
|
||||
:disabled="state.submitting"
|
||||
:class="{ 'loading': state.submitting }"
|
||||
>
|
||||
<div class="btn-icon">V</div>
|
||||
<span class="btn-text">微信区</span>
|
||||
<div v-if="state.submitting" class="loading-spinner small"></div>
|
||||
<div v-else class="btn-icon">V</div>
|
||||
<span class="btn-text">{{ state.submitting ? '正在连接...' : '微信区' }}</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -57,11 +61,25 @@
|
||||
<!-- 二维码区域 -->
|
||||
<div v-else-if="state.qrInfo && countdown > 0" class="qr-container">
|
||||
<div class="qr-wrapper">
|
||||
<img :src="state.qrInfo.url" class="qr-code" alt="扫码登录" />
|
||||
<img :src="state.qrInfo.url" class="qr-code" alt="扫码登录" @error="handleQrImageError" />
|
||||
</div>
|
||||
<div class="countdown-timer">{{ formatTime(countdown) }}</div>
|
||||
</div>
|
||||
|
||||
<!-- 二维码获取失败 -->
|
||||
<div v-else-if="state.qrError" class="qr-error">
|
||||
<div class="error-icon">❌</div>
|
||||
<p class="error-text">二维码获取失败</p>
|
||||
<p class="error-desc">{{ state.qrError }}</p>
|
||||
<button
|
||||
@click="retryGetQrCode"
|
||||
class="retry-btn"
|
||||
:disabled="state.submitting"
|
||||
>
|
||||
重新获取
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- 二维码过期 -->
|
||||
<div v-else class="qr-expired">
|
||||
<div class="warning-icon">⚠️</div>
|
||||
@@ -207,7 +225,8 @@ export default {
|
||||
isWaitingQr: false,
|
||||
qrRetryCount: 0,
|
||||
maxQrRetries: 3,
|
||||
qrRetryDelay: 2000
|
||||
qrRetryDelay: 2000,
|
||||
qrError: null // 二维码错误信息
|
||||
})
|
||||
|
||||
// 计时器
|
||||
@@ -298,7 +317,7 @@ export default {
|
||||
firstRewardUrl: gameData.firstRewardUrl,
|
||||
midRewardUrl: gameData.midRewardUrl,
|
||||
endRewardUrl: gameData.endRewardUrl,
|
||||
qrCodeUrl: gameData.qrCodeUrl,
|
||||
qrCodeUrl: gameData.mecmachineId ? `https://2.uzi0.cc/image/${gameData.mecmachineId}/二维码.png` : null,
|
||||
// 保留原有的assets数据(如果存在)
|
||||
...(gameData.assets || {})
|
||||
}
|
||||
@@ -345,7 +364,7 @@ export default {
|
||||
firstRewardUrl: gameData.firstRewardUrl,
|
||||
midRewardUrl: gameData.midRewardUrl,
|
||||
endRewardUrl: gameData.endRewardUrl,
|
||||
qrCodeUrl: gameData.qrCodeUrl
|
||||
qrCodeUrl: gameData.mecmachineId ? `https://2.uzi0.cc/image/${gameData.mecmachineId}/二维码.png` : null
|
||||
}
|
||||
|
||||
// 设置点数信息 - 已完成时当前点数等于目标点数
|
||||
@@ -404,7 +423,7 @@ export default {
|
||||
console.log('updateStateFromResponse:', {
|
||||
status: data.status,
|
||||
region: data.region,
|
||||
qrCodeUrl: data.qrCodeUrl,
|
||||
mecmachineId: data.mecmachineId,
|
||||
skipQrProcessing
|
||||
})
|
||||
|
||||
@@ -414,9 +433,10 @@ export default {
|
||||
}
|
||||
|
||||
// 处理二维码信息
|
||||
if (data.qrCodeUrl) {
|
||||
if (data.mecmachineId) {
|
||||
const qrUrl = `https://2.uzi0.cc/image/${data.mecmachineId}/二维码.png`
|
||||
state.qrInfo = {
|
||||
url: data.qrCodeUrl,
|
||||
url: qrUrl,
|
||||
createdAt: data.qrCreatedAt,
|
||||
expireAt: data.qrExpireAt
|
||||
}
|
||||
@@ -436,38 +456,63 @@ export default {
|
||||
}
|
||||
}
|
||||
|
||||
// 验证二维码URL是否可访问
|
||||
// 验证二维码URL是否可访问(生产环境优化版本)
|
||||
const validateQrCodeUrl = async (url) => {
|
||||
try {
|
||||
console.log('开始验证二维码URL:', url)
|
||||
|
||||
// 检查URL格式
|
||||
if (!url || typeof url !== 'string') {
|
||||
console.error('无效的二维码URL:', url)
|
||||
return false
|
||||
}
|
||||
|
||||
// 在生产环境中,跳过HEAD请求验证,直接返回true
|
||||
// 因为某些服务器可能不支持HEAD请求或存在CORS问题
|
||||
if (process.env.NODE_ENV === 'production') {
|
||||
console.log('生产环境跳过URL验证')
|
||||
return true
|
||||
}
|
||||
|
||||
// 开发环境进行完整验证
|
||||
const controller = new AbortController()
|
||||
const timeoutId = setTimeout(() => controller.abort(), 5000)
|
||||
const timeoutId = setTimeout(() => {
|
||||
controller.abort()
|
||||
console.log('URL验证超时')
|
||||
}, 3000) // 减少超时时间到3秒
|
||||
|
||||
const response = await fetch(url, {
|
||||
method: 'HEAD',
|
||||
signal: controller.signal
|
||||
signal: controller.signal,
|
||||
mode: 'no-cors' // 添加no-cors模式避免CORS问题
|
||||
})
|
||||
|
||||
clearTimeout(timeoutId)
|
||||
return response.ok
|
||||
console.log('URL验证响应:', response.status)
|
||||
return true // no-cors模式下无法检查status,直接返回true
|
||||
} catch (error) {
|
||||
console.warn('二维码URL验证失败:', error)
|
||||
return false
|
||||
console.warn('二维码URL验证失败:', error.name, error.message)
|
||||
// 即使验证失败,也返回true,让用户尝试加载图片
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
// 延迟获取二维码(带重试机制)
|
||||
const fetchQrCodeAfterDelay = async (qrCodeUrl, qrCreatedAt, qrExpireAt, retryCount = 0) => {
|
||||
const fetchQrCodeAfterDelay = async (mecmachineId, qrCreatedAt, qrExpireAt, retryCount = 0) => {
|
||||
try {
|
||||
const qrCodeUrl = `https://2.uzi0.cc/image/${mecmachineId}/二维码.png`
|
||||
console.log(`尝试获取二维码 (第${retryCount + 1}次):`, qrCodeUrl)
|
||||
|
||||
// 验证二维码URL是否可访问
|
||||
const isUrlValid = await validateQrCodeUrl(qrCodeUrl)
|
||||
console.log('URL验证结果:', isUrlValid)
|
||||
|
||||
if (!isUrlValid) {
|
||||
throw new Error('二维码URL无法访问')
|
||||
}
|
||||
|
||||
// URL验证通过,设置二维码信息
|
||||
console.log('设置二维码信息:', { qrCodeUrl, qrCreatedAt, qrExpireAt })
|
||||
state.qrInfo = {
|
||||
url: qrCodeUrl,
|
||||
createdAt: qrCreatedAt,
|
||||
@@ -478,14 +523,15 @@ export default {
|
||||
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('二维码已准备就绪,请扫码登录')
|
||||
console.log('二维码获取成功')
|
||||
|
||||
} catch (error) {
|
||||
console.error(`二维码获取失败 (第${retryCount + 1}次):`, error)
|
||||
console.error(`二维码获取失败 (第${retryCount + 1}次):`, error.message || error)
|
||||
|
||||
// 如果还有重试次数,则进行重试
|
||||
if (retryCount < state.maxQrRetries) {
|
||||
@@ -496,18 +542,15 @@ export default {
|
||||
ElMessage.warning(`二维码获取失败,${delay/1000}秒后重试...`)
|
||||
|
||||
setTimeout(() => {
|
||||
fetchQrCodeAfterDelay(qrCodeUrl, qrCreatedAt, qrExpireAt, retryCount + 1)
|
||||
fetchQrCodeAfterDelay(mecmachineId, qrCreatedAt, qrExpireAt, retryCount + 1)
|
||||
}, delay)
|
||||
} else {
|
||||
// 重试次数用完,重新请求新的二维码
|
||||
console.error('二维码获取重试次数用完,重新请求区域选择')
|
||||
ElMessage.error('二维码获取失败,正在重新请求...')
|
||||
// 重试次数用完,显示错误状态而不是重新请求
|
||||
console.error('二维码获取重试次数用完,显示错误状态')
|
||||
state.qrRetryCount = 0
|
||||
|
||||
// 重新调用区域选择API
|
||||
if (state.region) {
|
||||
retrySelectRegion(state.region)
|
||||
}
|
||||
state.isWaitingQr = false
|
||||
state.qrError = `二维码获取失败,已重试${state.maxQrRetries}次。可能是网络问题或服务器繁忙,请稍后重试。`
|
||||
ElMessage.error('二维码获取失败,请点击重新获取按钮')
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -532,8 +575,8 @@ export default {
|
||||
|
||||
// 处理选择区域响应的通用逻辑
|
||||
const processSelectRegionResponse = async (data) => {
|
||||
// 如果返回了延迟时间和二维码URL,需要延迟处理
|
||||
if (data.qrDelaySeconds && data.qrDelaySeconds > 0 && data.qrCodeUrl) {
|
||||
// 如果返回了延迟时间和机器ID,需要延迟处理
|
||||
if (data.qrDelaySeconds && data.qrDelaySeconds > 0 && data.mecmachineId) {
|
||||
console.log('进入延迟分支')
|
||||
// 跳过二维码处理,只更新基本状态
|
||||
await updateStateFromResponse(data, true)
|
||||
@@ -547,7 +590,7 @@ export default {
|
||||
state.isWaitingQr = false
|
||||
|
||||
// 延迟后获取二维码(带重试机制)
|
||||
await fetchQrCodeAfterDelay(data.qrCodeUrl, data.qrCreatedAt, data.qrExpireAt)
|
||||
await fetchQrCodeAfterDelay(data.mecmachineId, data.qrCreatedAt, data.qrExpireAt)
|
||||
|
||||
if (state.status === 'USING') {
|
||||
startCountdown()
|
||||
@@ -568,7 +611,7 @@ export default {
|
||||
console.warn('立即获取的二维码URL无法访问,尝试重试')
|
||||
// 清除当前二维码信息,触发重试
|
||||
state.qrInfo = null
|
||||
await fetchQrCodeAfterDelay(data.qrCodeUrl, data.qrCreatedAt, data.qrExpireAt)
|
||||
await fetchQrCodeAfterDelay(data.mecmachineId, data.qrCreatedAt, data.qrExpireAt)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -629,6 +672,34 @@ export default {
|
||||
window.location.reload()
|
||||
}
|
||||
|
||||
// 处理二维码图片加载错误
|
||||
const handleQrImageError = (event) => {
|
||||
console.error('二维码图片加载失败:', event)
|
||||
state.qrError = '二维码图片加载失败,可能是网络问题'
|
||||
ElMessage.error('二维码图片加载失败')
|
||||
}
|
||||
|
||||
// 重新获取二维码
|
||||
const retryGetQrCode = async () => {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
// 开始倒计时
|
||||
const startCountdown = () => {
|
||||
clearTimer('countdown')
|
||||
@@ -868,6 +939,8 @@ export default {
|
||||
selectRegion,
|
||||
handleRefresh,
|
||||
handlePageRefresh,
|
||||
handleQrImageError,
|
||||
retryGetQrCode,
|
||||
handleRetry,
|
||||
formatTime,
|
||||
getRegionName,
|
||||
@@ -921,6 +994,14 @@ export default {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.loading-spinner.small {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border: 2px solid #f3f3f3;
|
||||
border-top: 2px solid #667eea;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
0% { transform: rotate(0deg); }
|
||||
100% { transform: rotate(360deg); }
|
||||
@@ -994,6 +1075,17 @@ export default {
|
||||
transform: none;
|
||||
}
|
||||
|
||||
.region-btn.loading {
|
||||
opacity: 0.8;
|
||||
cursor: not-allowed;
|
||||
transform: none;
|
||||
}
|
||||
|
||||
.region-btn.loading:hover {
|
||||
transform: none;
|
||||
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
.btn-icon {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
@@ -1089,7 +1181,7 @@ export default {
|
||||
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.qr-expired {
|
||||
.qr-expired, .qr-error {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -1100,24 +1192,24 @@ export default {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.warning-icon {
|
||||
.warning-icon, .error-icon {
|
||||
font-size: 48px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.expired-text {
|
||||
.expired-text, .error-text {
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
margin: 0 0 8px 0;
|
||||
}
|
||||
|
||||
.expired-desc {
|
||||
.expired-desc, .error-desc {
|
||||
font-size: 16px;
|
||||
margin: 0 0 24px 0;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.refresh-btn {
|
||||
.refresh-btn, .retry-btn {
|
||||
background: white;
|
||||
color: #667eea;
|
||||
border: none;
|
||||
|
||||
Reference in New Issue
Block a user