Files
sbu4pe/src/utils/api/index.js
2025-08-13 01:55:49 +00:00

239 lines
5.4 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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;