优化API请求,移除时间戳参数以简化链接生成,更新二维码提示信息,调整区域选择按钮样式,提升用户交互体验
This commit is contained in:
@@ -6,7 +6,7 @@ import http from '@/plugins/http'
|
|||||||
|
|
||||||
// 获取链接状态
|
// 获取链接状态
|
||||||
export function getLinkStatus(code) {
|
export function getLinkStatus(code) {
|
||||||
return http.get(`/api/link/status?t=${Date.now()}`, {
|
return http.get('/api/link/status', {
|
||||||
params: { code }
|
params: { code }
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -34,12 +34,12 @@ export function pollLoginStatus(code) {
|
|||||||
|
|
||||||
// 获取游戏界面数据
|
// 获取游戏界面数据
|
||||||
export function getGameInterface(code) {
|
export function getGameInterface(code) {
|
||||||
return http.get(`/api/link/${code}/game-interface?t=${Date.now()}`)
|
return http.get(`/api/link/${code}/game-interface`)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取二维码图片(可选,用于代理二维码避免混合内容问题)
|
// 获取二维码图片(可选,用于代理二维码避免混合内容问题)
|
||||||
export function getQRCode(code) {
|
export function getQRCode(code) {
|
||||||
return http.get(`/api/link/qr.png?t=${Date.now()}`, {
|
return http.get('/api/link/qr.png', {
|
||||||
params: { code },
|
params: { code },
|
||||||
responseType: 'blob'
|
responseType: 'blob'
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<!-- 二维码区域 -->
|
<!-- 二维码区域 -->
|
||||||
<div v-else-if="qrInfo && countdown > 0" class="qr-container">
|
<div v-else-if="qrInfo && countdown > 0" class="qr-container">
|
||||||
<div class="qr-section">
|
<div class="qr-section">
|
||||||
<div class="qr-title">回验证码扫码</div>
|
<div class="qr-title">请尽快完成扫码!</div>
|
||||||
<div class="qr-wrapper">
|
<div class="qr-wrapper">
|
||||||
<img :src="qrInfo.url" class="qr-code" alt="扫码登录" @error="$emit('qrImageError', $event)" @load="$emit('qrImageLoad', $event)" />
|
<img :src="qrInfo.url" class="qr-code" alt="扫码登录" @error="$emit('qrImageError', $event)" @load="$emit('qrImageLoad', $event)" />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -33,8 +33,10 @@
|
|||||||
@click="confirmSelection"
|
@click="confirmSelection"
|
||||||
class="confirm-btn"
|
class="confirm-btn"
|
||||||
:disabled="!selectedRegion || submitting"
|
:disabled="!selectedRegion || submitting"
|
||||||
|
:class="{ 'loading': submitting }"
|
||||||
>
|
>
|
||||||
确认选择
|
<span v-if="submitting" class="loading-spinner"></span>
|
||||||
|
<span>{{ submitting ? '正在连接...' : '确认选择' }}</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -44,6 +46,7 @@
|
|||||||
@click="selectRegionOption('Q')"
|
@click="selectRegionOption('Q')"
|
||||||
class="option-btn qq-option"
|
class="option-btn qq-option"
|
||||||
:class="{ 'selected': selectedRegion === 'QQ区' }"
|
:class="{ 'selected': selectedRegion === 'QQ区' }"
|
||||||
|
:disabled="submitting"
|
||||||
>
|
>
|
||||||
<div class="option-icon qq-icon">
|
<div class="option-icon qq-icon">
|
||||||
<svg viewBox="0 0 24 24" width="32" height="32" fill="currentColor">
|
<svg viewBox="0 0 24 24" width="32" height="32" fill="currentColor">
|
||||||
@@ -57,6 +60,7 @@
|
|||||||
@click="selectRegionOption('V')"
|
@click="selectRegionOption('V')"
|
||||||
class="option-btn wx-option"
|
class="option-btn wx-option"
|
||||||
:class="{ 'selected': selectedRegion === '微信区' }"
|
:class="{ 'selected': selectedRegion === '微信区' }"
|
||||||
|
:disabled="submitting"
|
||||||
>
|
>
|
||||||
<div class="option-icon wx-icon">
|
<div class="option-icon wx-icon">
|
||||||
<svg viewBox="0 0 24 24" width="32" height="32" fill="currentColor">
|
<svg viewBox="0 0 24 24" width="32" height="32" fill="currentColor">
|
||||||
@@ -241,6 +245,10 @@ export default {
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: all 0.3s ease;
|
transition: all 0.3s ease;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.confirm-btn:hover:not(:disabled) {
|
.confirm-btn:hover:not(:disabled) {
|
||||||
@@ -253,6 +261,27 @@ export default {
|
|||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.confirm-btn.loading {
|
||||||
|
opacity: 0.8;
|
||||||
|
cursor: wait;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Loading Spinner */
|
||||||
|
.loading-spinner {
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
border: 2px solid rgba(255, 255, 255, 0.3);
|
||||||
|
border-top-color: white;
|
||||||
|
border-radius: 50%;
|
||||||
|
animation: spin 0.8s linear infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes spin {
|
||||||
|
to {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* 选择区域按钮 */
|
/* 选择区域按钮 */
|
||||||
.region-options {
|
.region-options {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
@@ -278,11 +307,16 @@ export default {
|
|||||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
.option-btn:hover {
|
.option-btn:hover:not(:disabled) {
|
||||||
transform: translateY(-2px);
|
transform: translateY(-2px);
|
||||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.option-btn:disabled {
|
||||||
|
opacity: 0.5;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
.option-icon {
|
.option-icon {
|
||||||
width: 60px;
|
width: 60px;
|
||||||
height: 60px;
|
height: 60px;
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ export function usePlayState() {
|
|||||||
state.status = 'LOGGED_IN'
|
state.status = 'LOGGED_IN'
|
||||||
|
|
||||||
state.assets = {
|
state.assets = {
|
||||||
qrCodeUrl: gameData.mecmachineId ? `https://uzi1.cn/image/${gameData.mecmachineId}/二维码.png?t=${new Date().getTime()}` : null,
|
qrCodeUrl: gameData.mecmachineId ? `https://uzi1.cn/image/${gameData.mecmachineId}/二维码.png?t=${Date.now()}` : null,
|
||||||
...(gameData.assets || {})
|
...(gameData.assets || {})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ export function useTimers() {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('轮询错误:', error)
|
console.error('轮询错误:', error)
|
||||||
}
|
}
|
||||||
}, 1000)
|
}, 3000) // 修改:轮询间隔从1秒改为3秒
|
||||||
}
|
}
|
||||||
|
|
||||||
const startProgressPolling = (code, onProgressUpdate) => {
|
const startProgressPolling = (code, onProgressUpdate) => {
|
||||||
|
|||||||
@@ -5,19 +5,17 @@ export const LINK_CONFIG = {
|
|||||||
// 基础域名 - 生产环境需要修改为实际域名
|
// 基础域名 - 生产环境需要修改为实际域名
|
||||||
BASE_URL: import.meta.env.VITE_BASE_URL || 'http://localhost:5173',
|
BASE_URL: import.meta.env.VITE_BASE_URL || 'http://localhost:5173',
|
||||||
|
|
||||||
// 游戏页面路径
|
// 游戏页面路径(已缩短为空,新生成的链接使用短格式,旧链接 /play/:code 仍然兼容)
|
||||||
GAME_PATH: '/play',
|
GAME_PATH: '',
|
||||||
|
|
||||||
// 机器编号参数名
|
// 机器编号参数名
|
||||||
CODE_PARAM: 'code',
|
CODE_PARAM: 'code',
|
||||||
|
|
||||||
// 链接地址模板
|
// 链接地址模板
|
||||||
getLinkUrl: (codeNo) => {
|
getLinkUrl: (codeNo) => {
|
||||||
// 生成随机参数:时间戳 + 随机字符串
|
// 如果 GAME_PATH 为空,直接拼接;否则添加斜杠
|
||||||
const timestamp = Date.now()
|
const path = LINK_CONFIG.GAME_PATH ? `${LINK_CONFIG.GAME_PATH}/${codeNo}` : `/${codeNo}`
|
||||||
const random = Math.random().toString(36).substring(2, 8)
|
return `${LINK_CONFIG.BASE_URL}${path}`
|
||||||
const randomParam = `${timestamp}${random}`
|
|
||||||
return `${LINK_CONFIG.BASE_URL}${LINK_CONFIG.GAME_PATH}/${codeNo}?t=${randomParam}`
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,8 +15,9 @@ const NotFound = () => import('@/views/NotFound.vue')
|
|||||||
|
|
||||||
export const routes = [
|
export const routes = [
|
||||||
{ path: '/login', name: 'Login', component: Login, meta: { public: true, title: '登录' } },
|
{ path: '/login', name: 'Login', component: Login, meta: { public: true, title: '登录' } },
|
||||||
{ path: '/play/:code', name: 'Play', component: Play, meta: { public: true, title: '上号任务' } },
|
// 保留旧的 /play/:code 路由用于兼容旧链接
|
||||||
{ path: '/play', name: 'PlayLegacy', component: Play, meta: { public: true, title: '上号任务' } },
|
{ path: '/play/:code', name: 'PlayLegacy', component: Play, meta: { public: true, title: '上号任务' } },
|
||||||
|
{ path: '/play', name: 'PlayLegacyNoCode', component: Play, meta: { public: true, title: '上号任务' } },
|
||||||
{
|
{
|
||||||
path: '/',
|
path: '/',
|
||||||
component: AdminLayout,
|
component: AdminLayout,
|
||||||
@@ -41,6 +42,8 @@ export const routes = [
|
|||||||
{ path: 'announcements', name: 'Announcements', component: AnnouncementList, meta: { title: '公告管理' } },
|
{ path: 'announcements', name: 'Announcements', component: AnnouncementList, meta: { title: '公告管理' } },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
// 新的短链接路由(放在最后,NotFound之前),用于新生成的链接
|
||||||
|
{ path: '/:code', name: 'Play', component: Play, meta: { public: true, title: '上号任务' } },
|
||||||
{ path: '/:pathMatch(.*)*', name: 'NotFound', component: NotFound, meta: { public: true, title: '未找到' } },
|
{ path: '/:pathMatch(.*)*', name: 'NotFound', component: NotFound, meta: { public: true, title: '未找到' } },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@@ -325,18 +325,18 @@ export default {
|
|||||||
midRewardUrl: gameData.midRewardUrl,
|
midRewardUrl: gameData.midRewardUrl,
|
||||||
endRewardUrl: gameData.endRewardUrl,
|
endRewardUrl: gameData.endRewardUrl,
|
||||||
|
|
||||||
qrCodeUrl: gameData.mecmachineId ? `https://uzi1.cn/image/${gameData.mecmachineId}/二维码.png?t=${new Date().getTime()}` : null,
|
qrCodeUrl: gameData.mecmachineId ? `https://uzi1.cn/image/${gameData.mecmachineId}/二维码.png?t=${Date.now()}` : null,
|
||||||
// 保留原有的assets数据(如果存在)
|
// 保留原有的assets数据(如果存在)
|
||||||
...(gameData.assets || {})
|
...(gameData.assets || {})
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
state.assets = {
|
state.assets = {
|
||||||
homepageUrl: gameData.mecmachineId ? `https://uzi1.cn/image/${gameData.mecmachineId}/首次主页.png?t=${new Date().getTime()}` : null,
|
homepageUrl: gameData.mecmachineId ? `https://uzi1.cn/image/${gameData.mecmachineId}/首次主页.png?t=${Date.now()}` : null,
|
||||||
firstRewardUrl: gameData.mecmachineId ? `https://uzi1.cn/image/${gameData.mecmachineId}/首次赏金.png?t=${new Date().getTime()}` : null,
|
firstRewardUrl: gameData.mecmachineId ? `https://uzi1.cn/image/${gameData.mecmachineId}/首次赏金.png?t=${Date.now()}` : null,
|
||||||
midRewardUrl: gameData.mecmachineId ? `https://uzi1.cn/image/${gameData.mecmachineId}/中途赏金.png?t=${new Date().getTime()}` : null,
|
midRewardUrl: gameData.mecmachineId ? `https://uzi1.cn/image/${gameData.mecmachineId}/中途赏金.png?t=${Date.now()}` : null,
|
||||||
endRewardUrl: gameData.mecmachineId ? `https://uzi1.cn/image/${gameData.mecmachineId}/结束赏金.png?t=${new Date().getTime()}` : null,
|
endRewardUrl: gameData.mecmachineId ? `https://uzi1.cn/image/${gameData.mecmachineId}/结束赏金.png?t=${Date.now()}` : null,
|
||||||
|
|
||||||
qrCodeUrl: gameData.mecmachineId ? `https://uzi1.cn/image/${gameData.mecmachineId}/二维码.png?t=${new Date().getTime()}` : null,
|
qrCodeUrl: gameData.mecmachineId ? `https://uzi1.cn/image/${gameData.mecmachineId}/二维码.png?t=${Date.now()}` : null,
|
||||||
// 保留原有的assets数据(如果存在)
|
// 保留原有的assets数据(如果存在)
|
||||||
...(gameData.assets || {})
|
...(gameData.assets || {})
|
||||||
|
|
||||||
@@ -791,7 +791,7 @@ export default {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('轮询错误:', error)
|
console.error('轮询错误:', error)
|
||||||
}
|
}
|
||||||
}, 1000)
|
}, 3000) // 修改:轮询间隔从1秒改为3秒
|
||||||
}
|
}
|
||||||
|
|
||||||
// 开始进度轮询
|
// 开始进度轮询
|
||||||
|
|||||||
Reference in New Issue
Block a user