import axios from "axios"; import crypto from "@/utils/crypto"; import Cookies from 'js-cookie'; import { ElMessage, ElLoading } from 'element-plus'; // 获取基础 API 地址 const API_BASE_URL = import.meta.env.VITE_APP_API_BASE_URL; if (!API_BASE_URL) { console.warn('API基础地址未配置,请在环境变量中设置VITE_APP_API_BASE_URL'); } // 创建axios实例 const api = axios.create({ baseURL: API_BASE_URL, timeout: 15000, // 请求超时时间 headers: { 'Content-Type': 'application/json' } }); // 加载状态管理 let loadingInstance = null; let requestCount = 0; // 显示加载状态 const showLoading = () => { if (requestCount === 0) { loadingInstance = ElLoading.service({ lock: true, text: '加载中...', background: 'rgba(0, 0, 0, 0.1)' }); } requestCount++; }; // 隐藏加载状态 const hideLoading = () => { requestCount--; if (requestCount <= 0 && loadingInstance) { loadingInstance.close(); loadingInstance = null; requestCount = 0; } }; // 请求拦截器 api.interceptors.request.use( (config) => { // 如果需要显示加载状态 if (config.showLoading !== false) { showLoading(); } // 添加认证token const accessToken = Cookies.get('access_token'); if (accessToken) { config.headers['Authorization'] = `Bearer ${accessToken}`; } // 处理POST请求加密 if (config.method?.toLowerCase() === 'post' && !config.isEncrypted) { try { // 添加用户信息 let requestData = { ...config.data }; const storedUserInfo = localStorage.getItem('info'); if (storedUserInfo) { const info = JSON.parse(crypto.decrypt(storedUserInfo)); requestData['user_id'] = info.id; } // 加密数据 config.data = { postdata: crypto.encrypt(JSON.stringify(requestData)) }; // 标记为已加密 config.isEncrypted = true; } catch (error) { console.error('请求数据加密失败:', error); } } return config; }, (error) => { hideLoading(); ElMessage.error('请求配置错误'); return Promise.reject(error); } ); // 响应拦截器 api.interceptors.response.use( (response) => { hideLoading(); // 处理业务逻辑错误 const { data } = response; // 根据实际后端规范调整 if (data.code && data.code !== 200) { ElMessage.error(data.message || '操作失败'); return Promise.reject(new Error(data.message || '请求失败')); } return data; }, async (error) => { hideLoading(); // 处理网络错误 if (!error.response) { ElMessage.error('网络连接异常,请检查网络'); return Promise.reject(error); } const { status, data } = error.response; // 处理不同状态码 switch (status) { case 401: // 未授权,处理token过期逻辑 ElMessage.error('登录已过期,请重新登录'); // 清除登录状态 Cookies.remove('access_token'); localStorage.removeItem('info'); // 跳转到登录页(假设使用vue-router) if (window.router) { window.router.push('/'); } break; case 403: ElMessage.error('没有权限执行此操作'); break; case 404: ElMessage.error('请求的资源不存在'); break; case 500: ElMessage.error('服务器内部错误,请稍后再试'); break; default: ElMessage.error(data?.message || `请求错误 (${status})`); } return Promise.reject(error); } ); // 封装请求方法 const request = { /** * GET请求 * @param {string} url 请求地址 * @param {object} params 请求参数 * @param {object} config 额外配置 * @returns {Promise} */ get: (url, params = {}, config = {}) => { return api({ url, method: 'get', params, ...config }); }, /** * POST请求 * @param {string} url 请求地址 * @param {object} data 请求数据 * @param {object} config 额外配置 * @returns {Promise} */ post: (url, data = {}, config = {}) => { return api({ url, method: 'post', data, ...config }); }, /** * PUT请求 * @param {string} url 请求地址 * @param {object} data 请求数据 * @param {object} config 额外配置 * @returns {Promise} */ put: (url, data = {}, config = {}) => { return api({ url, method: 'put', data, ...config }); }, /** * DELETE请求 * @param {string} url 请求地址 * @param {object} params 请求参数 * @param {object} config 额外配置 * @returns {Promise} */ delete: (url, params = {}, config = {}) => { return api({ url, method: 'delete', params, ...config }); }, /** * 不加密的POST请求 * @param {string} url 请求地址 * @param {object} data 请求数据 * @param {object} config 额外配置 * @returns {Promise} */ postWithoutEncryption: (url, data = {}, config = {}) => { return api({ url, method: 'post', data, isEncrypted: true, // 标记为已加密,跳过加密处理 ...config }); } }; // 暴露axios实例和请求方法 export { api, request }; export default request;