import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse, InternalAxiosRequestConfig, AxiosHeaders } from 'axios'; import { BASE_URL } from './constants' // 创建 axios 实例 const request: AxiosInstance = axios.create({ baseURL: BASE_URL, // 设置基础URL timeout: 10000, // 请求超时时间 headers: { 'Content-Type': 'application/json', }, }); // 请求拦截器 request.interceptors.request.use( (config: InternalAxiosRequestConfig) => { // 从 localStorage 获取 token const token = localStorage.getItem('token') || 'mock-token'; if (token && config.headers) { (config.headers as AxiosHeaders).set('Authorization', `Bearer ${token}`); } return config; }, (error) => { return Promise.reject(error); } ); // 响应拦截器 request.interceptors.response.use( (response: AxiosResponse) => { // 直接返回响应数据 return response.data; }, (error) => { if (error.response) { switch (error.response.status) { case 401: // 未授权,清除 token 并跳转到登录页 localStorage.removeItem('token'); window.location.href = '/login'; break; case 403: // 权限不足 console.error('没有权限访问该资源'); break; case 404: // 资源不存在 console.error('请求的资源不存在'); break; case 500: // 服务器错误 console.error('服务器错误'); break; default: console.error('请求失败:', error.response.data.message || '未知错误'); } } else if (error.request) { // 请求已发出但没有收到响应 console.error('网络错误,请检查您的网络连接'); } else { // 请求配置出错 console.error('请求配置错误:', error.message); } return Promise.reject(error); } ); // 封装 GET 请求 export const get = (url: string, config?: AxiosRequestConfig): Promise => { return request.get(url, config); }; // 封装 POST 请求 export const post = (url: string, data?: any, config?: AxiosRequestConfig): Promise => { return request.post(url, data, config); }; // 封装 PUT 请求 export const put = (url: string, data?: any, config?: AxiosRequestConfig): Promise => { return request.put(url, data, config); }; // 封装 DELETE 请求 export const del = (url: string, config?: AxiosRequestConfig): Promise => { return request.delete(url, config); }; // 封装流式数据请求 export const stream = async ({ url, method = 'POST', data, onMessage, onError, onComplete, }: { url: string; method?: 'GET' | 'POST'; data?: any; onMessage: (data: T) => void; onError?: (error: any) => void; onComplete?: () => void; }) => { try { const config: AxiosRequestConfig = { url, method, data, responseType: 'stream', headers: { 'Accept': 'text/event-stream', 'Cache-Control': 'no-cache', 'Connection': 'keep-alive', }, onDownloadProgress: (progressEvent: any) => { const responseText = progressEvent.event?.target?.responseText; if (!responseText) return; // 处理接收到的数据 const lines: string[] = responseText.split('\n'); lines.forEach((line: string) => { if (line.startsWith('data: ')) { try { const data = JSON.parse(line.slice(6)); onMessage(data); } catch (e) { console.warn('Failed to parse stream data:', e); } } }); }, }; const response = await request(config); onComplete?.(); return response; } catch (error) { onError?.(error); throw error; } }; // 封装文件下载流请求 export const downloadStream = async ( url: string, filename: string, config?: AxiosRequestConfig ) => { try { const response = await request({ url, method: 'GET', responseType: 'blob', ...config, }); // 创建下载链接 const blob = new Blob([response.data], { type: response.headers['content-type'] }); const downloadUrl = window.URL.createObjectURL(blob); const link = document.createElement('a'); link.href = downloadUrl; link.download = filename; document.body.appendChild(link); link.click(); document.body.removeChild(link); window.URL.revokeObjectURL(downloadUrl); return response; } catch (error) { console.error('文件下载失败:', error); throw error; } }; // 导出 request 实例 export default request;