效果图
interceptors.ts
/** axios封装
* 请求拦截、相应拦截、错误统一处理
*/
import Axios from "axios";
import { ElMessage, ElLoading } from "element-plus";
import _ from "lodash";
const axios = Axios.create({
// baseURL: process.env.VUE_APP_URL, // url = base url + request url
// timeout: 50000 // request timeout
});
// loading对象
let loadingInstance: { close: () => void } | null;
// 请求合并只出现一次loading
// 当前正在请求的数量
let loadingRequestCount = 0;
// post请求头
axios.defaults.headers.post["Content-Type"] = "application/json;charset=UTF-8";
// request interceptor
axios.interceptors.request.use(
(config: any) => {
let loadingTarget = "body";
if (config.headers.loadingTarget) {
loadingTarget = config.headers.loadingTarget;
}
const isShowLoading = config.headers.isShowLoading;
const target = document.querySelector(loadingTarget);
if (target && isShowLoading) {
// 请求拦截进来调用显示loading效果
showLoading(loadingTarget);
}
// do something before request is sent
if (sessionStorage.getItem("token")) {
config.headers.Authorization =
"Bearer " + sessionStorage.getItem("token"); // 让每个请求携带自定义 token 请根据实际情况自行修改
}
return config;
},
(error) => {
// do something with request error
console.log(error); // for debug
return Promise.reject(error);
}
);
// http response 拦截器
axios.interceptors.response.use(
(response) => {
setTimeout(() => {
hideLoading();
}, 200);
const data = response.data;
return data;
},
(err) => {
setTimeout(() => {
hideLoading();
}, 200);
// 返回状态码不为200时候的错误处理
ElMessage({
message: err.toString(),
type: "error",
duration: 5 * 1000,
});
return Promise.resolve(err);
}
);
// 显示loading的函数 并且记录请求次数 ++
const showLoading = (target: any) => {
if (loadingRequestCount === 0) {
loadingInstance = ElLoading.service({
lock: true,
text: "加载中...",
target: target,
background: "rgba(255,255,255,0.5)",
});
}
loadingRequestCount++;
};
// 隐藏loading的函数,并且记录请求次数
const hideLoading = () => {
if (loadingRequestCount <= 0) return;
loadingRequestCount--;
if (loadingRequestCount === 0) {
toHideLoading();
}
};
// 防抖:将 300ms 间隔内的关闭 loading 便合并为一次. 防止连续请求时, loading闪烁的问题。
const toHideLoading = _.debounce(() => {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
loadingInstance.close();
loadingInstance = null;
}, 300);
export default axios;
request.ts
import instance from "./interceptors";
import { ElMessage } from "element-plus";
export default class baseRequest {
private url: any;
private params: any;
constructor(url: any, params: any) {
this.url = url;
this.params = typeof params === "undefined" ? {} : params;
}
get(...params: any[]) {
return instance
.get(this.url, {
params: this.params,
headers: {
loadingTarget: params[0],
isShowLoading: params[1] === undefined ? true : params[1],
},
})
.then((res: any) => {
if (res.code === "200") {
return Promise.resolve(res.entitys);
} else {
ElMessage({
message: res.entitys[Object.keys(res.entitys)[0]],
type: "error",
duration: 5 * 1000,
});
return Promise.resolve(false);
}
})
.catch((e) => {
ElMessage({
message: e,
type: "error",
duration: 5 * 1000,
});
Promise.resolve(false);
});
}
post(...params: any[]) {
return instance
.post(this.url, this.params, {
headers: {
loadingTarget: params[0],
isShowLoading: params[1] === undefined ? true : params[1],
},
})
.then((res: any) => {
if (res.code === "200") {
return Promise.resolve(res.entitys);
} else {
ElMessage({
message: res.entitys[Object.keys(res.entitys)[0]],
type: "error",
duration: 5 * 1000,
});
Promise.resolve(false);
}
})
.catch((e) => {
ElMessage({
message: e,
type: "error",
duration: 5 * 1000,
});
Promise.resolve(false);
});
}
put(...params: any[]) {
return instance
.put(this.url, this.params, {
headers: {
loadingTarget: params[0],
isShowLoading: params[1] === undefined ? true : params[1],
},
})
.then((res: any) => {
if (res.code === "200") {
return Promise.resolve(res.entitys);
} else {
ElMessage({
message: res.entitys[Object.keys(res.entitys)[0]],
type: "error",
duration: 5 * 1000,
});
Promise.resolve(false);
}
})
.catch((e) => {
ElMessage({
message: e,
type: "error",
duration: 5 * 1000,
});
Promise.resolve(false);
});
}
delete(...params: any[]) {
return instance
.delete(this.url, {
params: this.params,
headers: {
loadingTarget: params[0],
isShowLoading: params[1] === undefined ? true : params[1],
},
})
.then((res: any) => {
if (res.code === "200") {
return Promise.resolve(res.entitys);
} else {
ElMessage({
message: res.entitys[Object.keys(res.entitys)[0]],
type: "error",
duration: 5 * 1000,
});
Promise.resolve(false);
}
})
.catch((e) => {
ElMessage({
message: e,
type: "error",
duration: 5 * 1000,
});
Promise.resolve(false);
});
}
upfile(...params: any[]) {
return instance
.post(this.url, this.params, {
headers: {
"Content-Type": "multipart/form-data",
"X-Requested-With": "XMLHttpRequest",
loadingTarget: params[0],
isShowLoading: params[1] === undefined ? true : params[1],
},
})
.then((res: any) => {
if (res.code === "200") {
return Promise.resolve(res.entitys);
} else {
ElMessage({
message: res.entitys[Object.keys(res.entitys)[0]],
type: "error",
duration: 5 * 1000,
});
Promise.resolve(false);
}
})
.catch((e) => {
ElMessage({
message: e,
type: "error",
duration: 5 * 1000,
});
Promise.resolve(false);
});
}
downfile(...params: any[]) {
return instance
.post(this.url, this.params, { responseType: "blob" })
.then((res: any) => {
const fileReader = new FileReader();
fileReader.onload = function (e: any) {
try {
const jsonData = JSON.parse(e.target.result); // 说明是普通对象数据,后台转换失败
if (jsonData.code) {
ElMessage({
message: jsonData.message,
type: "error",
duration: 5 * 1000,
});
Promise.resolve(false);
}
} catch (err) {
// 解析成对象失败,说明是正常的文件流
const url = window.URL.createObjectURL(res);
const eleLink = document.createElement("a");
eleLink.href = url;
eleLink.download = params[2];
// eleLink.download = "1.xls";
document.body.appendChild(eleLink);
eleLink.click();
window.URL.revokeObjectURL(url);
}
};
fileReader.readAsText(res);
})
.catch((e) => {
ElMessage({
message: e,
type: "error",
duration: 5 * 1000,
});
Promise.resolve(false);
});
}
}
使用
方法中可以传递三个参数,依次为,loadingTarget,isShowLoading,downloadFlileName
- loadingTarget:默认在body上显示lodaing,可以传入html标签的id
- isShowLoading:是否显示lodaing,默认为true,
- downloadFlileName:文件下载名称;需要传入文件格式,如 文本.txt
import BaseRequest from "@/request/request";
const loginApi = {
/**
* 查询
*/
login(params: any): any {
const url = `/api/staff/login`;
const BaseRequestFun = new BaseRequest(url, params);
return BaseRequestFun.post();
},
/**
* 查询菜单
*/
queryMenuByRoleCode(rolecode: any): any {
const url = `/api/rolepopedom/menus/${rolecode}`;
const BaseRequestFun = new BaseRequest(url, "");
return BaseRequestFun.get();
},
};
export default loginApi;