Files
JARVIS/frontend/src/api/index.ts

84 lines
2.4 KiB
TypeScript
Raw Normal View History

2026-03-21 10:13:35 +08:00
import axios from 'axios'
const api = axios.create({
baseURL: import.meta.env.VITE_API_URL || 'http://localhost:9527',
2026-03-21 10:13:35 +08:00
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<string, unknown>) {
if (!isDev()) return
console.debug(`[api:${stage}]`, payload)
}
2026-03-21 10:13:35 +08:00
// 请求拦截器:添加 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
2026-03-21 10:13:35 +08:00
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,
})
2026-03-21 10:13:35 +08:00
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
},
2026-03-21 10:13:35 +08:00
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
2026-03-21 10:13:35 +08:00
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
}
2026-03-21 10:13:35 +08:00
return Promise.reject(error)
}
)
export default api