Files
xh-medical-sign-web/clinical-web/src/utils/request.ts
T
yelan a5e0a80191 feat(auth): 接入 MEDISIGN 登录接口
- 新增认证 API、类型与本地会话存储
- 登录页改为真实账号密码登录并移除验证码
- 请求拦截器改用 X-Token 并处理 401 跳转
- 添加 Vite /api 开发代理配置
2026-08-31 10:50:01 +08:00

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