/** * apiClient - API 请求客户端 * * 功能描述: * 封装 Axios 请求客户端,处理: * - 请求拦截(添加 Token) * - 响应拦截(错误处理) * - Token 刷新 * - 网络状态检测 * * @author Timeline Team * @date 2024 */ import axios, { AxiosInstance, AxiosError, InternalAxiosRequestConfig } from 'axios'; import { useAuthStore } from '@stores/authStore'; import NetInfo from '@react-native-community/netinfo'; // API 基础配置 const BASE_URL = __DEV__ ? 'http://10.0.2.2:8080' // Android 模拟器 : 'https://api.timeline.com'; const TIMEOUT = 30000; /** * 创建 Axios 实例 */ const apiClient: AxiosInstance = axios.create({ baseURL: BASE_URL, timeout: TIMEOUT, headers: { 'Content-Type': 'application/json', }, }); /** * 请求拦截器 * 添加 Token 到请求头 */ apiClient.interceptors.request.use( async (config: InternalAxiosRequestConfig) => { // 检查网络状态 const netInfo = await NetInfo.fetch(); if (!netInfo.isConnected) { return Promise.reject(new Error('网络不可用,请检查网络连接')); } // 添加 Token const token = useAuthStore.getState().token; if (token && config.headers) { config.headers.Authorization = `Bearer ${token}`; } return config; }, (error: AxiosError) => { return Promise.reject(error); } ); /** * 响应拦截器 * 处理错误和 Token 刷新 */ apiClient.interceptors.response.use( (response) => { return response.data; }, async (error: AxiosError) => { const originalRequest = error.config as InternalAxiosRequestConfig & { _retry?: boolean }; // 处理 401 未授权错误 if (error.response?.status === 401 && !originalRequest._retry) { originalRequest._retry = true; try { // 尝试刷新 Token const refreshToken = useAuthStore.getState().refreshToken; if (refreshToken) { const response = await axios.post(`${BASE_URL}/auth/refresh`, { refreshToken, }); const { token } = response.data; useAuthStore.getState().setToken(token); // 重试原请求 if (originalRequest.headers) { originalRequest.headers.Authorization = `Bearer ${token}`; } return apiClient(originalRequest); } } catch (refreshError) { // Token 刷新失败,登出 useAuthStore.getState().logout(); return Promise.reject(refreshError); } } // 处理其他错误 const errorMessage = getErrorMessage(error); return Promise.reject(new Error(errorMessage)); } ); /** * 获取错误消息 */ function getErrorMessage(error: AxiosError): string { if (error.message === 'Network Error') { return '网络错误,请检查网络连接'; } if (error.response) { const status = error.response.status; const data: any = error.response.data; switch (status) { case 400: return data?.message || '请求参数错误'; case 401: return '登录已过期,请重新登录'; case 403: return '没有权限访问'; case 404: return '请求的资源不存在'; case 500: return '服务器错误,请稍后重试'; default: return data?.message || `请求失败 (${status})`; } } return error.message || '未知错误'; } export default apiClient;