项目初始化
This commit is contained in:
194
src/utils/request.js
Normal file
194
src/utils/request.js
Normal file
@@ -0,0 +1,194 @@
|
||||
import axios from "axios";
|
||||
import {
|
||||
ElNotification,
|
||||
ElMessageBox,
|
||||
ElMessage,
|
||||
} from "element-plus";
|
||||
import { tansParams } from "@/utils/ruoyi";
|
||||
import cache from "@/plugins/cache";
|
||||
import { getToken, removeToken } from "@/utils/auth";
|
||||
import router from '@/router';
|
||||
import { useMeterStore } from '@/stores/modules/meter'
|
||||
|
||||
axios.defaults.headers["Content-Type"] = "application/json;charset=utf-8";
|
||||
const meterStore = useMeterStore()
|
||||
meterStore.initUdid()
|
||||
// 创建axios实例
|
||||
const service = axios.create({
|
||||
// axios中请求配置有baseURL选项,表示请求URL公共部分
|
||||
baseURL: import.meta.env.VITE_APP_BASE_API,
|
||||
// 超时
|
||||
timeout: 10000,
|
||||
});
|
||||
|
||||
// request拦截器
|
||||
service.interceptors.request.use(
|
||||
(config) => {
|
||||
|
||||
// 是否需要设置 token
|
||||
const isToken = (config.headers || {}).isToken === false;
|
||||
if (getToken() && !isToken) {
|
||||
config.headers["Authorization"] = "Bearer " + getToken(); // 让每个请求携带自定义token 请根据实际情况自行修改
|
||||
}
|
||||
|
||||
// 是否需要防止数据重复提交
|
||||
const isRepeatSubmit = (config.headers || {}).repeatSubmit === false;
|
||||
if (meterStore.getSudid()) {
|
||||
config.headers["X-User-Agent"] = `gxtech/web 1.0.0: c=GxTech, udid=${meterStore.getSudid()}, sv=15.4.1, app=stt`;
|
||||
}
|
||||
// get请求映射params参数
|
||||
if (config.method === "get" && config.params) {
|
||||
|
||||
let url = config.url + "?" + tansParams(config.params);
|
||||
url = url.slice(0, -1);
|
||||
config.params = {};
|
||||
config.url = url;
|
||||
}
|
||||
if (
|
||||
!isRepeatSubmit &&
|
||||
(config.method === "post" || config.method === "put")
|
||||
) {
|
||||
const requestObj = {
|
||||
url: config.url,
|
||||
data:
|
||||
typeof config.data === "object"
|
||||
? JSON.stringify(config.data)
|
||||
: config.data,
|
||||
time: new Date().getTime(),
|
||||
};
|
||||
const requestSize = Object.keys(JSON.stringify(requestObj)).length; // 请求数据大小
|
||||
const limitSize = 5 * 1024 * 1024; // 限制存放数据5M
|
||||
if (requestSize >= limitSize) {
|
||||
console.warn(
|
||||
`[${config.url}]: ` +
|
||||
"请求数据大小超出允许的5M限制,无法进行防重复提交验证。"
|
||||
);
|
||||
return config;
|
||||
}
|
||||
const sessionObj = cache.session.getJSON("sessionObj");
|
||||
if (
|
||||
sessionObj === undefined ||
|
||||
sessionObj === null ||
|
||||
sessionObj === ""
|
||||
) {
|
||||
cache.session.setJSON("sessionObj", requestObj);
|
||||
} else {
|
||||
const s_url = sessionObj.url; // 请求地址
|
||||
const s_data = sessionObj.data; // 请求数据
|
||||
const s_time = sessionObj.time; // 请求时间
|
||||
const interval = 1000; // 间隔时间(ms),小于此时间视为重复提交
|
||||
if (
|
||||
s_data === requestObj.data &&
|
||||
requestObj.time - s_time < interval &&
|
||||
s_url === requestObj.url
|
||||
) {
|
||||
const message = "数据正在处理,请勿重复提交";
|
||||
console.warn(`[${s_url}]: ` + message);
|
||||
return Promise.reject(new Error(message));
|
||||
} else {
|
||||
cache.session.setJSON("sessionObj", requestObj);
|
||||
}
|
||||
}
|
||||
}
|
||||
return config;
|
||||
},
|
||||
(error) => {
|
||||
Promise.reject(error);
|
||||
}
|
||||
);
|
||||
|
||||
service.interceptors.response.use(
|
||||
(response) => {
|
||||
// 1. 检查响应是否存在
|
||||
if (!response) {
|
||||
ElMessage.error('无响应数据');
|
||||
return Promise.reject(new Error('无响应数据'));
|
||||
}
|
||||
// 2. 安全获取响应数据和状态码
|
||||
const responseData = response.data || {};
|
||||
const statusCode = response.status;
|
||||
const businessCode = responseData.meta?.code || statusCode;
|
||||
|
||||
// 3. 二进制数据直接返回
|
||||
if (
|
||||
response.request.responseType === 'blob' ||
|
||||
response.request.responseType === 'arraybuffer'
|
||||
) {
|
||||
return responseData;
|
||||
}
|
||||
|
||||
// 4. 根据业务码处理不同情况
|
||||
switch (businessCode) {
|
||||
case 200:
|
||||
case 201:
|
||||
return Promise.resolve(responseData);
|
||||
|
||||
case 401:
|
||||
return handleUnauthorized().then(() => {
|
||||
return Promise.reject({ code: 401, message: '未授权' });
|
||||
});
|
||||
|
||||
case 500:
|
||||
const serverErrorMsg = responseData.meta?.message || '服务器内部错误';
|
||||
ElMessage({ message: serverErrorMsg, type: 'error' });
|
||||
return Promise.reject({ code: 500, message: serverErrorMsg });
|
||||
|
||||
default:
|
||||
const errorMsg = responseData.meta?.message || `业务错误 (${businessCode})`;
|
||||
ElNotification.error({ title: errorMsg });
|
||||
return Promise.reject({ code: businessCode, message: errorMsg });
|
||||
}
|
||||
},
|
||||
(error) => {
|
||||
console.error('请求错误:', error);
|
||||
let { message } = error;
|
||||
let code = error?.response?.status || -1;
|
||||
|
||||
if (message == 'Network Error') {
|
||||
message = '后端接口连接异常';
|
||||
ElMessage({ message, type: 'error', duration: 5 * 1000 });
|
||||
} else if (message.includes('timeout')) {
|
||||
message = '系统接口请求超时';
|
||||
ElMessage({ message, type: 'error', duration: 5 * 1000 });
|
||||
} else if (message.includes('Request failed with status code')) {
|
||||
// message = '系统接口' + message.substr(message.length - 3) + '异常';
|
||||
}
|
||||
|
||||
// 返回结构化错误
|
||||
return Promise.reject({
|
||||
code,
|
||||
message,
|
||||
raw: error // 保留原始 error
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
// 单独处理401未授权
|
||||
function handleUnauthorized() {
|
||||
return ElMessageBox.confirm(
|
||||
'认证信息已失效,您可以继续留在该页面,或者重新登录',
|
||||
'系统提示',
|
||||
{
|
||||
confirmButtonText: '重新登录',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
}
|
||||
)
|
||||
.then(() => {
|
||||
removeToken()
|
||||
if (router.currentRoute.path !== '/login') {
|
||||
router.push({
|
||||
path: '/login',
|
||||
query: { redirect: router.currentRoute.fullPath }
|
||||
});
|
||||
} else {
|
||||
// 如果在登录页,强制刷新以清除残留状态
|
||||
window.location.reload();
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
return Promise.reject('用户取消操作');
|
||||
});
|
||||
}
|
||||
|
||||
export default service;
|
||||
Reference in New Issue
Block a user