import axios, { type AxiosInstance, type AxiosRequestConfig } from 'axios' import { ElMessage } from 'element-plus' /** 令牌在 localStorage 中的键名 */ const TOKEN_KEY = 'lab-token' /** * 读取本地令牌。 * * @returns JWT 字符串或空串 */ export function getToken(): string { return localStorage.getItem(TOKEN_KEY) ?? '' } /** * 写入本地令牌。 * * @param token JWT 字符串 */ export function setToken(token: string): void { localStorage.setItem(TOKEN_KEY, token) } /** 清除本地令牌 */ export function clearToken(): void { localStorage.removeItem(TOKEN_KEY) } /** axios 实例,统一以 /api 为前缀(开发环境由 Vite 代理) */ const request: AxiosInstance = axios.create({ baseURL: '/api', timeout: 15000 }) /** * 请求拦截器:附加 Bearer 令牌。 */ request.interceptors.request.use((config) => { const token = getToken() if (token) { config.headers.Authorization = `Bearer ${token}` } return config }) /** * 响应拦截器:统一解包业务码,401 时跳转登录页。 */ request.interceptors.response.use( (response) => { const body = response.data if (body && typeof body.code === 'number' && body.code !== 0) { ElMessage.error(body.message || '请求失败') return Promise.reject(new Error(body.message)) } return response }, (error) => { const status = error?.response?.status if (status === 401) { clearToken() ElMessage.error('登录已失效,请重新登录') if (window.location.pathname !== '/login') { window.location.href = '/login' } } else if (status === 403) { ElMessage.error('无权限执行该操作') } else { ElMessage.error(error?.response?.data?.message || error.message || '网络异常') } return Promise.reject(error) } ) /** * 发起 GET 请求。 * * @param url 接口路径 * @param params 查询参数 * @returns 业务数据 */ export async function get(url: string, params?: Record): Promise { const { data } = await request.get(url, { params }) return data.data as T } /** * 发起 POST 请求。 * * @param url 接口路径 * @param body 请求体 * @param config 额外配置 * @returns 业务数据 */ export async function post(url: string, body?: unknown, config?: AxiosRequestConfig): Promise { const { data } = await request.post(url, body, config) return data.data as T } /** * 发起 PUT 请求。 * * @param url 接口路径 * @param body 请求体 * @returns 业务数据 */ export async function put(url: string, body?: unknown): Promise { const { data } = await request.put(url, body) return data.data as T } /** * 发起 PATCH 请求。 * * @param url 接口路径 * @param body 请求体 * @returns 业务数据 */ export async function patch(url: string, body?: unknown): Promise { const { data } = await request.patch(url, body) return data.data as T } /** * 发起 DELETE 请求。 * * @param url 接口路径 * @returns 业务数据 */ export async function del(url: string): Promise { const { data } = await request.delete(url) return data.data as T } export default request