162 lines
4.0 KiB
TypeScript
162 lines
4.0 KiB
TypeScript
import type { Method } from 'alova'
|
||
import type { AxiosError } from 'axios'
|
||
import { axiosRequestAdapter } from '@alova/adapter-axios'
|
||
import { createAlova } from 'alova'
|
||
import { router } from 'expo-router'
|
||
import { useUserStore } from '@/store/user'
|
||
import { toast } from '@/utils/toast'
|
||
|
||
enum HttpCode {
|
||
Success = 200,
|
||
Unauthorized = 401,
|
||
RefreshToken = 402,
|
||
Fail = 500,
|
||
}
|
||
|
||
const WhiteList = [
|
||
'/auth/login/**',
|
||
'/auth/register/**',
|
||
'/auth/refresh/token',
|
||
]
|
||
|
||
function isWhiteListed(url: string) {
|
||
return WhiteList.some((pattern) => {
|
||
if (pattern.endsWith('/**')) {
|
||
const base = pattern.slice(0, -3)
|
||
return url.startsWith(base)
|
||
}
|
||
return url === pattern
|
||
})
|
||
}
|
||
|
||
const alovaInstance = createAlova({
|
||
// baseURL: 'http://192.168.5.6:8085/app',
|
||
baseURL: 'http://192.168.1.136:8085/app',
|
||
requestAdapter: axiosRequestAdapter(),
|
||
timeout: 5000,
|
||
cacheFor: null,
|
||
responded: {
|
||
onSuccess: async (response, method: Method) => {
|
||
const resData = response.data as ResponseData<any>
|
||
|
||
const result = {
|
||
...resData,
|
||
isSuccess: resData.code === HttpCode.Success,
|
||
}
|
||
|
||
console.log(resData)
|
||
|
||
// Access Token 失效 → 重新登录
|
||
if (resData.code === HttpCode.Unauthorized) {
|
||
router.replace('/auth/login')
|
||
return
|
||
}
|
||
|
||
// Access Token 过期但 Refresh Token 有效 → 刷新 token 并重试
|
||
if (resData.code === HttpCode.RefreshToken) {
|
||
try {
|
||
const refreshToken = useUserStore.getState().userInfo?.refreshToken
|
||
if (!refreshToken) {
|
||
router.replace('/auth/login')
|
||
return
|
||
}
|
||
|
||
// 调用刷新接口
|
||
const res = await alovaInstance.Get<ResponseData<string>>('/auth/refresh/token', {
|
||
headers: { refreshToken },
|
||
}).send()
|
||
|
||
const newToken = res.data
|
||
|
||
// 更新 store
|
||
useUserStore.getState().setUserInfo({
|
||
...useUserStore.getState().userInfo!,
|
||
token: newToken,
|
||
})
|
||
|
||
// 重试原请求
|
||
method.config.headers.token = newToken
|
||
const retryResult = await method.send() // ✅ 获取结果
|
||
|
||
return retryResult // ✅ 一定要 return!
|
||
}
|
||
catch (err) {
|
||
return Promise.reject(err)
|
||
}
|
||
}
|
||
|
||
return result
|
||
},
|
||
onError: (error: AxiosError, _method) => {
|
||
console.log('===跳转到error了===')
|
||
console.log(error.status)
|
||
|
||
switch (error.status) {
|
||
case 400:
|
||
toast.show({
|
||
title: '请求错误,请检查输入参数',
|
||
})
|
||
break
|
||
case 401:
|
||
toast.show({
|
||
title: '未授权,请重新登录',
|
||
})
|
||
break
|
||
case 403:
|
||
toast.show({
|
||
title: '没有权限访问该资源',
|
||
})
|
||
break
|
||
case 404:
|
||
toast.show({
|
||
title: '请求丢失啦,请稍后再试!',
|
||
})
|
||
break
|
||
case 500:
|
||
toast.show({
|
||
title: '服务器出错啦,请稍后重试',
|
||
})
|
||
break
|
||
case 502:
|
||
toast.show({
|
||
title: '网关错误,请稍后重试',
|
||
})
|
||
break
|
||
case 503:
|
||
toast.show({
|
||
title: '服务暂不可用,请稍后再试',
|
||
})
|
||
break
|
||
case 504:
|
||
toast.show({
|
||
title: '网关超时,请稍后再试',
|
||
})
|
||
break
|
||
default:
|
||
toast.show({
|
||
title: `服务器出错啦,请稍后重试`,
|
||
})
|
||
break
|
||
}
|
||
return Promise.reject(error)
|
||
},
|
||
},
|
||
beforeRequest(method) {
|
||
if (isWhiteListed(method.url))
|
||
return
|
||
|
||
if (!useUserStore.getState().isLoggedIn()) {
|
||
toast.show({
|
||
title: '尚未登录,请先登录',
|
||
})
|
||
|
||
router.replace('/auth/login')
|
||
return Promise.reject(new Error('未登录'))
|
||
}
|
||
|
||
method.config.headers.token = useUserStore.getState().userInfo?.token ?? ''
|
||
},
|
||
})
|
||
|
||
export default alovaInstance
|