- 新增认证 API、类型与本地会话存储 - 登录页改为真实账号密码登录并移除验证码 - 请求拦截器改用 X-Token 并处理 401 跳转 - 添加 Vite /api 开发代理配置
100 lines
2.3 KiB
TypeScript
100 lines
2.3 KiB
TypeScript
import axios, {
|
|
type AxiosInstance,
|
|
type AxiosRequestConfig,
|
|
type AxiosResponse,
|
|
type InternalAxiosRequestConfig,
|
|
} from 'axios'
|
|
|
|
import { clearAuthStorage, AUTH_TOKEN_KEY } from '@/utils/auth-storage'
|
|
|
|
const DEFAULT_TIMEOUT = 15_000
|
|
const DEFAULT_API_BASE_URL = '/api'
|
|
|
|
function redirectToLogin() {
|
|
if (typeof window === 'undefined' || window.location.pathname === '/login') {
|
|
return
|
|
}
|
|
|
|
const redirect = `${window.location.pathname}${window.location.search}${window.location.hash}`
|
|
window.location.assign(`/login?redirect=${encodeURIComponent(redirect)}`)
|
|
}
|
|
|
|
class Request {
|
|
private readonly instance: AxiosInstance
|
|
|
|
constructor(
|
|
baseURL = import.meta.env.VITE_API_BASE_URL || DEFAULT_API_BASE_URL,
|
|
timeout = DEFAULT_TIMEOUT,
|
|
) {
|
|
this.instance = axios.create({
|
|
baseURL,
|
|
timeout,
|
|
withCredentials: false,
|
|
})
|
|
|
|
this.instance.interceptors.request.use((config: InternalAxiosRequestConfig) => {
|
|
const token = localStorage.getItem(AUTH_TOKEN_KEY)
|
|
|
|
if (token) {
|
|
config.headers.set('X-Token', token)
|
|
}
|
|
|
|
return config
|
|
})
|
|
|
|
this.instance.interceptors.response.use(
|
|
(response: AxiosResponse) => response,
|
|
(error: unknown) => {
|
|
if (axios.isAxiosError(error) && error.response?.status === 401) {
|
|
clearAuthStorage()
|
|
redirectToLogin()
|
|
}
|
|
|
|
return Promise.reject(error)
|
|
},
|
|
)
|
|
}
|
|
|
|
request<T = unknown>(config: AxiosRequestConfig): Promise<T> {
|
|
return this.instance.request<T, AxiosResponse<T>>(config).then((response) => response.data)
|
|
}
|
|
|
|
get<T = unknown>(url: string, config: AxiosRequestConfig = {}): Promise<T> {
|
|
return this.request<T>({
|
|
...config,
|
|
url,
|
|
method: 'GET',
|
|
})
|
|
}
|
|
|
|
post<T = unknown>(url: string, data?: unknown, config: AxiosRequestConfig = {}): Promise<T> {
|
|
return this.request<T>({
|
|
...config,
|
|
url,
|
|
data,
|
|
method: 'POST',
|
|
})
|
|
}
|
|
|
|
put<T = unknown>(url: string, data?: unknown, config: AxiosRequestConfig = {}): Promise<T> {
|
|
return this.request<T>({
|
|
...config,
|
|
url,
|
|
data,
|
|
method: 'PUT',
|
|
})
|
|
}
|
|
|
|
delete<T = unknown>(url: string, config: AxiosRequestConfig = {}): Promise<T> {
|
|
return this.request<T>({
|
|
...config,
|
|
url,
|
|
method: 'DELETE',
|
|
})
|
|
}
|
|
}
|
|
|
|
export const request = new Request()
|
|
|
|
export default request
|