更新上号系统需求文档,添加版本信息、项目概述、角色与权限、术语与规则及业务流程等内容,同时修改链接生成规则和请求拦截器以支持公开API的身份验证,新增路由配置以支持上号任务页面。
This commit is contained in:
47
src/api/play.js
Normal file
47
src/api/play.js
Normal file
@@ -0,0 +1,47 @@
|
||||
import http from '@/plugins/http'
|
||||
|
||||
/**
|
||||
* 用户端游戏页面 API
|
||||
*/
|
||||
|
||||
// 获取链接状态
|
||||
export function getLinkStatus(code) {
|
||||
return http.get('/api/link/status', {
|
||||
params: { code }
|
||||
})
|
||||
}
|
||||
|
||||
// 选择区域
|
||||
export function selectRegion(payload) {
|
||||
// payload: { code: string, region: string }
|
||||
return http.post('/api/link/select-region', payload)
|
||||
}
|
||||
|
||||
// 刷新链接
|
||||
export function refreshLink(code) {
|
||||
return http.post('/api/link/refresh', {
|
||||
code
|
||||
})
|
||||
}
|
||||
|
||||
// 轮询登录状态
|
||||
export function pollLoginStatus(code) {
|
||||
return http.get('/api/link/poll-login', {
|
||||
params: { code }
|
||||
})
|
||||
}
|
||||
|
||||
// 获取游戏进度
|
||||
export function getGameProgress(code) {
|
||||
return http.get('/api/link/progress', {
|
||||
params: { code }
|
||||
})
|
||||
}
|
||||
|
||||
// 获取二维码图片(可选,用于代理二维码避免混合内容问题)
|
||||
export function getQRCode(code) {
|
||||
return http.get('/api/link/qr.png', {
|
||||
params: { code },
|
||||
responseType: 'blob'
|
||||
})
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
// 链接地址生成规则
|
||||
export const LINK_CONFIG = {
|
||||
// 基础域名
|
||||
BASE_URL: 'https://yourdomain.com',
|
||||
BASE_URL: 'http://localhost:5173',
|
||||
|
||||
// 游戏页面路径
|
||||
GAME_PATH: '/play',
|
||||
|
||||
@@ -27,11 +27,22 @@ function onRefreshed(newToken, tokenType) {
|
||||
// 请求拦截:附加 Authorization
|
||||
http.interceptors.request.use(
|
||||
(config) => {
|
||||
const token = getAccessToken()
|
||||
const type = getTokenType()
|
||||
if (token) {
|
||||
config.headers = config.headers || {}
|
||||
config.headers.Authorization = `${type} ${token}`
|
||||
// 跳过公开API的身份验证(只跳过用户端游戏相关的公开接口)
|
||||
const publicAPIs = [
|
||||
'/api/link/status',
|
||||
'/api/link/select-region',
|
||||
'/api/link/poll-login',
|
||||
'/api/link/progress'
|
||||
]
|
||||
const isPublicAPI = publicAPIs.some(api => config.url?.includes(api))
|
||||
|
||||
if (!isPublicAPI) {
|
||||
const token = getAccessToken()
|
||||
const type = getTokenType()
|
||||
if (token) {
|
||||
config.headers = config.headers || {}
|
||||
config.headers.Authorization = `${type} ${token}`
|
||||
}
|
||||
}
|
||||
return config
|
||||
},
|
||||
@@ -58,10 +69,17 @@ http.interceptors.response.use(
|
||||
const status = response?.status
|
||||
const url = config?.url || ''
|
||||
|
||||
// 避免对登录/刷新自身进行重复刷新
|
||||
// 避免对登录/刷新自身和公开API进行重复刷新
|
||||
const isAuthPath = /\/auth\/(login|refresh)/.test(url || '')
|
||||
const publicAPIs = [
|
||||
'/api/link/status',
|
||||
'/api/link/select-region',
|
||||
'/api/link/poll-login',
|
||||
'/api/link/progress'
|
||||
]
|
||||
const isPublicAPI = publicAPIs.some(api => url?.includes(api))
|
||||
|
||||
if (status === 401 && !isAuthPath) {
|
||||
if (status === 401 && !isAuthPath && !isPublicAPI) {
|
||||
if (!isRefreshing) {
|
||||
isRefreshing = true
|
||||
try {
|
||||
|
||||
@@ -14,10 +14,12 @@ const Settings = () => import('@/views/settings/Settings.vue')
|
||||
const LinkGenerate = () => import('@/views/links/LinkGenerate.vue')
|
||||
const ErrorTest = () => import('@/views/ErrorTest.vue')
|
||||
const PermissionTest = () => import('@/views/PermissionTest.vue')
|
||||
const Play = () => import('@/views/Play.vue')
|
||||
const NotFound = () => import('@/views/NotFound.vue')
|
||||
|
||||
export const routes = [
|
||||
{ path: '/login', name: 'Login', component: Login, meta: { public: true, title: '登录' } },
|
||||
{ path: '/play', name: 'Play', component: Play, meta: { public: true, title: '上号任务' } },
|
||||
{
|
||||
path: '/',
|
||||
component: AdminLayout,
|
||||
|
||||
1171
src/views/Play.vue
Normal file
1171
src/views/Play.vue
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user