import axios from "axios";
import { ElMessage } from "element-plus";
import { startLoading, endLoading } from "@/utils/loading";
import {
SET_TOKEN,
GET_TOKEN,
SET_USERINFO,
GET_LANG,
} from "@/utils/localStorage.js";
import { checkStatus } from "./checkStatus";
import router from "../router";
const NETWORK_ERROR = "网络错误, 请稍后再试";
const LoadingInstance = {
_count: 0,
};
function http(
axioxConfig,
customOptions,
loadingOptions = { text: "loading…" }
) {
// 基础配置
const service = axios.create({
// baseURL: window.location.protocol + import.meta.env.VITE_SERVE,
baseURL: import.meta.env.VITE_SERVE,
timeout: 200000,
useTokenAuthorization: true,
headers: {
"Content-Type": "application/json",
"Accept-Language": GET_LANG() || "zh_CN",
},
});
// 自定义配置
let custom_options = Object.assign(
{
repeat_request_cancel: true, // 是否开启取消重复请求, 默认为 true
loading: true, // 是否开启loading层效果, 默认为true
error_message_show: true, // 是否开启 处理错误状态码
reduct_data_format: true, // 是否开启简洁的数据结构响应, 默认为false
code_message_show: true, // 是否开启code不为200时的信息提示, 默认为true
is_token: true, // 是否要token
delet_invalid_data: false, //是否去除data中无效的参数。例如‘’,默认不去除
},
customOptions
);
// 请求拦截器
service.interceptors.request.use(
(config) => {
const token = GET_TOKEN();
const isToken = custom_options?.is_token;
// 自动携带token
if (token && typeof window !== "undefined") {
if (isToken) {
config.headers.Authorization = `Bearer ${token}`;
}
}
// 取消重复请求代码
removePending(config);
custom_options.repeat_request_cancel && addPending(config);
// 创建loading实例
if (custom_options.loading) {
LoadingInstance._count++;
if (LoadingInstance._count === 1) {
startLoading(loadingOptions.text);
}
}
if (custom_options.delet_invalid_data) {
//去除请求数据无效属性
if (config.data) {
for (let k in config.data) {
if (
config.data[k] === undefined ||
config.data[k] === "" ||
config.data[k] === null
) {
delete config.data[k];
}
}
}
}
return config;
},
(error) => {
return Promise.reject(error);
}
);
// 返回拦截器
service.interceptors.response.use(
(response) => {
// 关闭loading
custom_options.loading && closeLoading(custom_options);
let fileName = "";
if (response.headers["content-disposition"]) {
const fileStr = response.headers["content-disposition"];
// .split("=")[1]
// .slice(7);
fileName = decodeURI(fileStr);
if (fileName.includes("utf-8")) {
fileName = fileName.split("utf-8")[1].slice(2).replace("%2C", " ");
} else {
fileName = fileName.split("=")[1];
}
sessionStorage.setItem("excel-name", fileName);
}
// 取消重复请求代码
removePending(response.config, custom_options);
if (response.config.responseType == "blob") {
return custom_options.reduct_data_format ? response.data : response;
}
const { code, msg } = response?.data;
const message = msg || NETWORK_ERROR; // 获取错误信息
if (
custom_options.code_message_show &&
response.data &&
response.data.code !== 200
) {
ElMessage.closeAll();
// 1002000009 用户密码输入错误次数太多,账户锁定5分钟,请稍后再试
if (
code === 1002000004 || //调出图形验证码
code === 1002000008 ||
code === 1002030004 || //文件不存在
code === 51013 //远程抄表超时处理
) {
return custom_options.reduct_data_format ? response.data : response;
}
ElMessage.error(msg);
if (code === 401) {
// 退出登录
SET_TOKEN("");
SET_USERINFO({});
router.replace("/log/login");
}
// code不等于200, 页面具体逻辑就不执行了
return Promise.reject(message);
}
if (code === 200) {
return custom_options.reduct_data_format ? response.data : response;
}
},
(error) => {
custom_options.loading && closeLoading(custom_options);
error.config && removePending(error.config);
// 处理错误状态码
custom_options.error_message_show && checkStatus(error?.response?.status);
return Promise.reject(error);
}
);
return service(axioxConfig);
}
const pendingMap = new Map();
// 生成每个请求唯一的键
function getPendingKey(config) {
let { url, method, params, data } = config;
if (typeof data === "string") data = JSON.parse(data); // response里面返回的config.data是个字符串对象
return [url, method, JSON.stringify(params), JSON.stringify(data)].join("&");
}
// 储存每个请求唯一值,也就是cancel()方法,用于取消请求
function addPending(config) {
const pendingKey = getPendingKey(config);
config.cancelToken =
config?.cancelToken ||
new axios.CancelToken((cancel) => {
if (!pendingMap.has(pendingKey)) {
pendingMap.set(pendingKey, cancel);
}
});
}
// 取消重复请求并删除队列
function removePending(config, custom_options) {
custom_options?.loading && closeLoading(custom_options);
const pendingKey = getPendingKey(config);
if (pendingMap.has(pendingKey)) {
const cancelToken = pendingMap.get(pendingKey);
cancelToken(pendingKey);
pendingMap.delete(pendingKey);
}
}
function closeLoading(_options) {
if (_options.loading && LoadingInstance._count > 0) LoadingInstance._count--;
if (LoadingInstance._count === 0) {
setTimeout(() => {
endLoading();
}, 500);
}
}
export default http;
封装的详细的接口请求http.js
最新推荐文章于 2024-07-19 16:38:23 发布