|
@@ -1,47 +1,72 @@
|
|
import axios from "axios";
|
|
import axios from "axios";
|
|
import Router from "@/router";
|
|
import Router from "@/router";
|
|
-import { Message, Notification } from "@arco-design/web-vue";
|
|
|
|
|
|
+import { Notification } from "@arco-design/web-vue";
|
|
import { useSystemStore } from "@/store/modules/systemStore";
|
|
import { useSystemStore } from "@/store/modules/systemStore";
|
|
import moment from 'moment-timezone';
|
|
import moment from 'moment-timezone';
|
|
import { fn_logout } from "@/utils";
|
|
import { fn_logout } from "@/utils";
|
|
-import error from "@/i18n/zh/error";
|
|
|
|
|
|
+
|
|
|
|
+// 用于存储请求和对应的 AbortController
|
|
|
|
+const requestMap = new Map();
|
|
|
|
+const requestCountMap = new Map(); // 用于记录请求的次数
|
|
|
|
|
|
const axiosInstance = axios.create({
|
|
const axiosInstance = axios.create({
|
|
- // baseURL: `${import.meta.env.PROD? import.meta.env.VITE_PRO_PATH : ''}/api`,
|
|
|
|
- baseURL: import.meta.env.BASE_URL + "api",
|
|
|
|
- timeout: 300000,
|
|
|
|
|
|
+ baseURL: import.meta.env.BASE_URL + "api", // 设置 API 基础 URL
|
|
|
|
+ timeout: 300000, // 设置请求超时时间
|
|
});
|
|
});
|
|
|
|
|
|
const requestState = {
|
|
const requestState = {
|
|
- // 得到正确响应
|
|
|
|
success: [200],
|
|
success: [200],
|
|
- // token 跳转
|
|
|
|
beOverdue: [886],
|
|
beOverdue: [886],
|
|
- // 没有访问权限
|
|
|
|
NotAccessRight: [500],
|
|
NotAccessRight: [500],
|
|
- // 异常 code
|
|
|
|
exception: [400],
|
|
exception: [400],
|
|
};
|
|
};
|
|
|
|
|
|
const pathArr = ["/api/admin/system/login", "/api/logout"];
|
|
const pathArr = ["/api/admin/system/login", "/api/logout"];
|
|
|
|
+
|
|
axiosInstance.interceptors.request.use(
|
|
axiosInstance.interceptors.request.use(
|
|
(config) => {
|
|
(config) => {
|
|
const systemStore = useSystemStore();
|
|
const systemStore = useSystemStore();
|
|
systemStore.localLoading(true);
|
|
systemStore.localLoading(true);
|
|
|
|
|
|
- // 在发送请求之前做些什么
|
|
|
|
if (!pathArr.includes(config.url)) {
|
|
if (!pathArr.includes(config.url)) {
|
|
const token = localStorage.getItem("token");
|
|
const token = localStorage.getItem("token");
|
|
if (token && config.headers) {
|
|
if (token && config.headers) {
|
|
config.headers["Authorization"] = token;
|
|
config.headers["Authorization"] = token;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ const requestKey = `${config.url}?${JSON.stringify(config.params)}`;
|
|
|
|
+
|
|
|
|
+ // 判断同一个接口请求次数
|
|
|
|
+ const currentCount = requestCountMap.get(requestKey) || 0;
|
|
|
|
+ if (currentCount >= 5) {
|
|
|
|
+ // 如果请求次数大于等于5次,取消当前请求
|
|
|
|
+ const controller = requestMap.get(requestKey);
|
|
|
|
+ controller?.abort();
|
|
|
|
+ console.log(`请求 ${requestKey} 已被取消,超过请求次数限制`);
|
|
|
|
+ Notification.warning({
|
|
|
|
+ title: "请求频繁",
|
|
|
|
+ content: `请求 ${config.url} 过于频繁,已取消当前请求。`,
|
|
|
|
+ });
|
|
|
|
+ return Promise.reject("请求过于频繁,已取消");
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 更新请求次数
|
|
|
|
+ requestCountMap.set(requestKey, currentCount + 1);
|
|
|
|
+
|
|
|
|
+ // 创建新的 AbortController
|
|
|
|
+ const controller = new AbortController();
|
|
|
|
+ config.signal = controller.signal;
|
|
|
|
+
|
|
|
|
+ // 存储当前请求的 AbortController
|
|
|
|
+ requestMap.set(requestKey, controller);
|
|
|
|
+
|
|
return config;
|
|
return config;
|
|
},
|
|
},
|
|
(err) => {
|
|
(err) => {
|
|
const systemStore = useSystemStore();
|
|
const systemStore = useSystemStore();
|
|
systemStore.localLoading();
|
|
systemStore.localLoading();
|
|
- Promise.reject(err);
|
|
|
|
|
|
+ return Promise.reject(err);
|
|
}
|
|
}
|
|
);
|
|
);
|
|
|
|
|
|
@@ -51,17 +76,29 @@ axiosInstance.interceptors.response.use(
|
|
const systemStore = useSystemStore();
|
|
const systemStore = useSystemStore();
|
|
systemStore.localLoading();
|
|
systemStore.localLoading();
|
|
const { code, data, message: msg } = res.data;
|
|
const { code, data, message: msg } = res.data;
|
|
- // 成功
|
|
|
|
|
|
+
|
|
|
|
+ // 获取当前请求的 key
|
|
|
|
+ const requestKey = `${res.config.url}?${JSON.stringify(res.config.params)}`;
|
|
|
|
+
|
|
|
|
+ // 请求完成后移除 AbortController
|
|
|
|
+ if (requestMap.has(requestKey)) {
|
|
|
|
+ requestMap.delete(requestKey);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 清理请求次数
|
|
|
|
+ if (requestCountMap.has(requestKey)) {
|
|
|
|
+ requestCountMap.delete(requestKey);
|
|
|
|
+ }
|
|
|
|
+
|
|
if (code === 200) {
|
|
if (code === 200) {
|
|
const dataList = {
|
|
const dataList = {
|
|
code: code,
|
|
code: code,
|
|
message: res.data.msg,
|
|
message: res.data.msg,
|
|
- data: DataViewsProvider(data)
|
|
|
|
|
|
+ data: DataViewsProvider(data),
|
|
};
|
|
};
|
|
return Promise.resolve(dataList);
|
|
return Promise.resolve(dataList);
|
|
}
|
|
}
|
|
|
|
|
|
- // 服务端错误信息
|
|
|
|
if (requestState.NotAccessRight.includes(code)) {
|
|
if (requestState.NotAccessRight.includes(code)) {
|
|
Notification.warning({
|
|
Notification.warning({
|
|
title: "系统信息",
|
|
title: "系统信息",
|
|
@@ -70,7 +107,6 @@ axiosInstance.interceptors.response.use(
|
|
return Promise.reject(msg);
|
|
return Promise.reject(msg);
|
|
}
|
|
}
|
|
|
|
|
|
- // 异常 code
|
|
|
|
if (requestState.exception.includes(code)) {
|
|
if (requestState.exception.includes(code)) {
|
|
Notification.warning({
|
|
Notification.warning({
|
|
title: "系统提示",
|
|
title: "系统提示",
|
|
@@ -84,56 +120,56 @@ axiosInstance.interceptors.response.use(
|
|
(err) => {
|
|
(err) => {
|
|
const systemStore = useSystemStore();
|
|
const systemStore = useSystemStore();
|
|
systemStore.localLoading();
|
|
systemStore.localLoading();
|
|
- const res = err["response"];
|
|
|
|
- if (err.code === "ERR_CANCELED") {
|
|
|
|
- console.log("请求中断");
|
|
|
|
- return;
|
|
|
|
|
|
+
|
|
|
|
+ const requestKey = `${err.config.url}?${JSON.stringify(err.config.params)}`;
|
|
|
|
+
|
|
|
|
+ // 请求完成后移除 AbortController
|
|
|
|
+ if (requestMap.has(requestKey)) {
|
|
|
|
+ requestMap.delete(requestKey);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 清理请求次数
|
|
|
|
+ if (requestCountMap.has(requestKey)) {
|
|
|
|
+ requestCountMap.delete(requestKey);
|
|
}
|
|
}
|
|
|
|
+
|
|
const msg = err.response?.data ? err.response.data.message : "";
|
|
const msg = err.response?.data ? err.response.data.message : "";
|
|
Notification.warning({
|
|
Notification.warning({
|
|
title: "系统信息",
|
|
title: "系统信息",
|
|
- content: msg
|
|
|
|
|
|
+ content: msg,
|
|
});
|
|
});
|
|
- // token 失效
|
|
|
|
|
|
+
|
|
if (requestState.beOverdue.includes(err.status)) {
|
|
if (requestState.beOverdue.includes(err.status)) {
|
|
fn_logout(Router);
|
|
fn_logout(Router);
|
|
- // 直接终止请求
|
|
|
|
|
|
+ Router.push("/");
|
|
return undefined;
|
|
return undefined;
|
|
}
|
|
}
|
|
- Promise.reject(err);
|
|
|
|
|
|
+
|
|
|
|
+ return Promise.reject(err);
|
|
}
|
|
}
|
|
);
|
|
);
|
|
|
|
|
|
-
|
|
|
|
function timeLoadTemeYear(value) {
|
|
function timeLoadTemeYear(value) {
|
|
if (!value) return;
|
|
if (!value) return;
|
|
const systemStore = useSystemStore();
|
|
const systemStore = useSystemStore();
|
|
- const timezone = systemStore.getUserIp?.timezone || JSON.parse(localStorage.getItem('IPCONFIG'))?.timezone
|
|
|
|
|
|
+ const timezone = systemStore.getUserIp?.timezone || JSON.parse(localStorage.getItem('IPCONFIG'))?.timezone;
|
|
if (timezone) {
|
|
if (timezone) {
|
|
- // 转换 UTC 时间为用户的本地时间
|
|
|
|
let localDate = moment.utc(value).tz(timezone);
|
|
let localDate = moment.utc(value).tz(timezone);
|
|
|
|
|
|
if (!localDate.isValid()) {
|
|
if (!localDate.isValid()) {
|
|
- return null; // 如果时间无效,返回 null
|
|
|
|
|
|
+ return null;
|
|
}
|
|
}
|
|
|
|
|
|
- // 格式化并返回本地时间
|
|
|
|
const localTime = localDate.format('YYYY-MM-DD HH:mm:ss');
|
|
const localTime = localDate.format('YYYY-MM-DD HH:mm:ss');
|
|
return localTime;
|
|
return localTime;
|
|
}
|
|
}
|
|
|
|
|
|
- return value
|
|
|
|
-
|
|
|
|
|
|
+ return value;
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-// 转换数据格式
|
|
|
|
function DataViewsProvider(data) {
|
|
function DataViewsProvider(data) {
|
|
if (!data) return data;
|
|
if (!data) return data;
|
|
|
|
|
|
- // 如果数据是对象并且包含 records 字段
|
|
|
|
if (data.records && Array.isArray(data.records)) {
|
|
if (data.records && Array.isArray(data.records)) {
|
|
return {
|
|
return {
|
|
...data,
|
|
...data,
|
|
@@ -150,7 +186,6 @@ function DataViewsProvider(data) {
|
|
};
|
|
};
|
|
}
|
|
}
|
|
|
|
|
|
- // 如果数据本身是数组
|
|
|
|
if (Array.isArray(data)) {
|
|
if (Array.isArray(data)) {
|
|
return data.map(item => {
|
|
return data.map(item => {
|
|
const transformedItem = { ...item };
|
|
const transformedItem = { ...item };
|
|
@@ -164,11 +199,7 @@ function DataViewsProvider(data) {
|
|
});
|
|
});
|
|
}
|
|
}
|
|
|
|
|
|
- // 如果数据不是数组也不是包含 records 的对象,直接返回数据
|
|
|
|
return data;
|
|
return data;
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-export default axiosInstance;
|
|
|
|
|
|
+export default axiosInstance;
|