Initial comitof pe project
This commit is contained in:
238
src/utils/api/index.js
Normal file
238
src/utils/api/index.js
Normal file
@@ -0,0 +1,238 @@
|
||||
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;
|
||||
Reference in New Issue
Block a user