import axios from 'axios' const api = axios.create({ baseURL: import.meta.env.VITE_API_URL || 'http://localhost:9527', timeout: 30000, }) function createRequestId() { if (typeof crypto !== 'undefined' && 'randomUUID' in crypto) { return crypto.randomUUID() } return `req-${Date.now()}-${Math.random().toString(16).slice(2)}` } function isDev() { return Boolean(import.meta.env.DEV) } function debugLog(stage: string, payload: Record) { if (!isDev()) return console.debug(`[api:${stage}]`, payload) } // 请求拦截器:添加 Token api.interceptors.request.use((config) => { const token = localStorage.getItem('access_token') const requestId = createRequestId() config.headers = config.headers || {} config.headers['X-Request-ID'] = requestId if (token) { config.headers.Authorization = `Bearer ${token}` } ;(config as typeof config & { metadata?: { startedAt: number; requestId: string } }).metadata = { startedAt: Date.now(), requestId, } debugLog('request', { requestId, method: config.method, url: config.url, params: config.params, data: config.data, }) return config }) // 响应拦截器:处理错误 api.interceptors.response.use( (response) => { const metadata = (response.config as typeof response.config & { metadata?: { startedAt: number; requestId: string } }).metadata debugLog('response', { requestId: response.headers['x-request-id'] || metadata?.requestId, method: response.config.method, url: response.config.url, status: response.status, durationMs: metadata ? Date.now() - metadata.startedAt : undefined, data: response.data, }) return response }, async (error) => { const metadata = (error.config as typeof error.config & { metadata?: { startedAt: number; requestId: string } })?.metadata const requestId = error.response?.headers?.['x-request-id'] || metadata?.requestId if (error.response?.status === 401) { localStorage.removeItem('access_token') window.location.href = '/login' } debugLog('error', { requestId, method: error.config?.method, url: error.config?.url, status: error.response?.status, durationMs: metadata ? Date.now() - metadata.startedAt : undefined, detail: error.response?.data, }) if (requestId) { error.requestId = requestId } return Promise.reject(error) } ) export default api