zy-vue-library/axios/index.js

409 lines
13 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

import axios from "axios";
import { ElMessage } from "element-plus";
import dayjs from 'dayjs'
import useRequestLoading from "../hooks/useRequestLoading/index.js";
import { getBaseUrl } from "../utils/index.js";
import CryptoJS from "crypto-js";
import {aesDecrypt} from "../aesSecret/index.js";
/**
* Axios服务类
*/
class AxiosService {
constructor() {
/**
* Axios配置选项
*/
this.config = {
router: null,
store: null,
tokenRefreshUrl: '/sys/refreshToken',
loginPath: '/login',
tokenRefreshInterval: 5, // 分钟
baseURL: getBaseUrl(),
timeout: 1000 * 60 * 10,
requestParamsSign: {
use: false,
key: ''
},
responseParamsDecrypt: {
use: false,
}
};
this.loading = useRequestLoading();
this.isTipTokenFailure = false;
}
/**
* 配置axios插件
* @param {Object} [config] - 配置选项
* @param {Object} config.router - Vue Router实例
* @param {Object} config.store - token的piniaStore
* @param {string} [config.tokenRefreshUrl="/sys/refreshToken"] - token刷新接口URL
* @param {string} [config.loginPath="/login"] - 登录页面路由
* @param {number} [config.tokenRefreshInterval=5] - token刷新间隔分钟
* @param {string} [config.baseURL=getBaseUrl()] - API基础URL
* @param {number} [config.timeout=60000] - 请求超时时间(毫秒)
* @param {Object} [config.requestParamsSign] - 请求参数是否签名
* @param {boolean} [config.requestParamsSign.use=false] - 是否使用签名
* @param {string} [config.requestParamsSign.key] - 签名密钥
* @param {Object} [config.responseParamsDecrypt] - 响应参数是否需要解密
* @param {boolean} [config.responseParamsDecrypt.use=false] - 是否需要解密
*/
configure(config = {}) {
if (!config.router) throw new Error('router 参数必传');
if (!config.store) throw new Error('store 参数必传');
this.config = { ...this.config, ...config };
// 设置默认配置
axios.defaults.baseURL = this.config.baseURL;
axios.defaults.timeout = this.config.timeout;
// 清除现有拦截器
axios.interceptors.request.clear();
axios.interceptors.response.clear();
// 重新设置拦截器
this.setupInterceptors();
}
/**
* token刷新逻辑
*/
async refreshToken() {
const currentRoute = this.config.router.currentRoute?.value;
if (currentRoute?.meta?.isLogin) {
const store = this.config.store;
if (store.getTokenTime) {
const diffMinutes = dayjs().diff(dayjs(store.getTokenTime), "minute");
if (diffMinutes >= this.config.tokenRefreshInterval) {
await store.setTokenTime(dayjs().format("YYYY-MM-DD HH:mm:ss"));
await this.postRequest(this.config.tokenRefreshUrl);
}
}
}
}
/**
* 请求参数签名
*/
requestParamsSign(params) {
if (!this.config.requestParamsSign.key) throw new Error('请传入签名密钥');
const Timestamp = new Date().getTime();
const cloneParams = { ...params };
const keys = Object.keys(cloneParams).sort();
const sortData = {};
for (let i = 0; i < keys.length; i++) {
if (cloneParams[keys[i]] !== null && cloneParams[keys[i]] !== undefined) {
sortData[keys[i]] = cloneParams[keys[i]];
}
}
const Sign = CryptoJS.MD5(
Timestamp +
JSON.stringify(sortData) +
this.config.requestParamsSign.key
).toString();
return {
Sign,
Timestamp,
};
}
/**
* 设置拦截器
*/
setupInterceptors() {
// 请求拦截器
axios.interceptors.request.use(
async (request) => {
request.headers.Token = this.config.store.getToken;
let params = request.data || request.params || {};
// 根据配置决定是否启用参数签名
if (this.config.requestParamsSign.use) {
const { Timestamp, Sign } = this.requestParamsSign(params);
request.headers.Timestamp = Timestamp;
request.headers.Sign = Sign;
}
this.loading.value = true;
return request;
},
(error) => Promise.reject(error)
);
// 响应拦截器
axios.interceptors.response.use(
(response) => {
if (this.config.responseParamsDecrypt.use) response.data = { ...response.data, ...aesDecrypt(response.data.data)}
this.loading.value = false;
if (response.data.code === 401) {
if (!this.isTipTokenFailure) {
this.isTipTokenFailure = true;
ElMessage.error("登录失效,请重新登录");
this.config.router.push(this.config.loginPath);
this.isTipTokenFailure = false;
}
return Promise.reject(response.data.msg);
} else {
this.refreshToken().then();
}
return response;
},
(error) => {
if (error && error.response) {
if (import.meta.env.DEV) ElMessage.error(`连接错误${error.response.status}`);
} else ElMessage.error(error.message);
return Promise.reject(error.message);
}
);
}
/**
* 发送POST请求
* @param {string} url - 请求URL
* @param {Object} params - 请求参数
* @returns {Promise} - 返回Promise对象包含请求结果
*/
postRequest(url, params = {}) {
return new Promise((resolve, reject) => {
axios
.post(url, params)
.then((res) => {
if (res.data.result === "success") {
resolve(res.data);
} else {
ElMessage.error(res.data.msg || "系统开小差了");
reject(res.data);
}
})
.catch((err) => {
reject(err);
});
});
}
/**
* 获取GET请求
* @param {string} url - 请求URL
* @param {Object} params - 请求参数
* @param {string} splicingURL - URL拼接字符串
* @returns {Promise} - 返回Promise对象包含请求结果
*/
getRequest(url, params = {}, splicingURL = "") {
return new Promise((resolve, reject) => {
axios
.get(url + (splicingURL ? "/" + splicingURL : ""), {
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
params,
})
.then((res) => {
if (res.data.result === "success") {
resolve(res.data);
} else {
ElMessage.error(res.data.msg || "系统开小差了");
reject(res.data);
}
})
.catch((err) => {
reject(err);
});
});
}
/**
* 获取PUT请求
* @param {string} url - 请求URL
* @param {Object} params - 请求参数
* @returns {Promise} - 返回Promise对象包含请求结果
*/
putRequest(url, params = {}) {
return new Promise((resolve, reject) => {
axios
.put(url, params)
.then((res) => {
if (res.data.result === "success") {
resolve(res.data);
} else {
ElMessage.error(res.data.msg || "系统开小差了");
reject(res.data);
}
})
.catch((err) => {
reject(err);
});
});
}
/**
* 获取DELETE请求
* @param {string} url - 请求URL
* @param {Object} params - 删除参数
* @param {string} splicingURL - URL拼接字符串
* @returns {Promise} - 返回Promise对象包含请求结果
*/
deleteRequest(url, params = {}, splicingURL = "") {
return new Promise((resolve, reject) => {
axios
.delete(url + (splicingURL ? "/" + splicingURL : ""), { data: params })
.then((res) => {
if (res.data.result === "success") {
resolve(res.data);
} else {
ElMessage.error(res.data.msg || "系统开小差了");
reject(res.data);
}
})
.catch((err) => {
reject(err);
});
});
}
/**
* 获取PATCH请求
* @param {string} url - 请求URL
* @param {Object} params - 请求参数
* @param {string} splicingURL - URL拼接字符串
* @returns {Promise} - 返回Promise对象包含请求结果
*/
patchRequest(url, params = {}, splicingURL = "") {
return new Promise((resolve, reject) => {
axios
.patch(url + (splicingURL ? "/" + splicingURL : ""), params)
.then((res) => {
if (res.data.result === "success") {
resolve(res.data);
} else {
ElMessage.error(res.data.msg || "系统开小差了")
reject(res.data);
}
})
.catch((err) => {
reject(err);
});
});
}
/**
* 上传文件请求
* @param {string} url - 请求URL
* @param {Object} params - 请求参数
* @returns {Promise} - 返回Promise对象包含请求结果
*/
uploadRequest(url, params = {}) {
return new Promise((resolve, reject) => {
axios
.post(url, params, {
headers: {
"Content-Type": "multipart/form-data",
},
})
.then((res) => {
if (res.data.result === "success") {
resolve(res.data);
} else {
ElMessage.error(res.data.msg || "系统开小差了");
reject(res.data);
}
})
.catch((err) => {
reject(err);
});
});
}
}
/**
* 配置axios插件
* @param {Object} [config] - 配置选项
* @param {Object} config.router - Vue Router实例
* @param {Object} config.store - token的piniaStore
* @param {string} [config.tokenRefreshUrl="/sys/refreshToken"] - token刷新接口URL
* @param {string} [config.loginPath="/login"] - 登录页面路由
* @param {number} [config.tokenRefreshInterval=5] - token刷新间隔分钟
* @param {string} [config.baseURL=getBaseUrl()] - API基础URL
* @param {number} [config.timeout=60000] - 请求超时时间(毫秒)
* @param {Object} [config.requestParamsSign] - 请求参数是否签名
* @param {boolean} [config.requestParamsSign.use=false] - 是否使用签名
* @param {string} [config.requestParamsSign.key] - 签名密钥
* @param {Object} [config.responseParamsDecrypt] - 响应参数是否需要解密
* @param {boolean} [config.responseParamsDecrypt.use=false] - 是否需要解密
*/
export function configureAxios(config = {}) {
if(!window.axiosService) window.axiosService = new AxiosService();
return axiosService.configure(config);
}
/**
* 发送POST请求
* @param {string} url - 请求URL
* @param {Object} params - 请求参数
* @returns {Promise} - 返回Promise对象包含请求结果
*/
export function postRequest(url, params = {}) {
if (!window.axiosService) throw new Error('未配置Axios请先调用 configureAxios');
return window.axiosService.postRequest(url, params);
}
/**
* 获取GET请求
* @param {string} url - 请求URL
* @param {Object} params - 请求参数
* @param {string} splicingURL - URL拼接字符串
* @returns {Promise} - 返回Promise对象包含请求结果
*/
export function getRequest(url, params = {}, splicingURL = "") {
if (!window.axiosService) throw new Error('未配置Axios请先调用 configureAxios');
return window.axiosService.getRequest(url, params, splicingURL);
}
/**
* 获取PUT请求
* @param {string} url - 请求URL
* @param {Object} params - 请求参数
* @returns {Promise} - 返回Promise对象包含请求结果
*/
export function putRequest(url, params = {}) {
if (!window.axiosService) throw new Error('未配置Axios请先调用 configureAxios');
return window.axiosService.putRequest(url, params);
}
/**
* 获取DELETE请求
* @param {string} url - 请求URL
* @param {Object} params - 删除参数
* @param {string} splicingURL - URL拼接字符串
* @returns {Promise} - 返回Promise对象包含请求结果
*/
export function deleteRequest(url, params = {}, splicingURL = "") {
if (!window.axiosService) throw new Error('未配置Axios请先调用 configureAxios');
return window.axiosService.deleteRequest(url, params, splicingURL);
}
/**
* 获取PATCH请求
* @param {string} url - 请求URL
* @param {Object} params - 请求参数
* @param {string} splicingURL - URL拼接字符串
* @returns {Promise} - 返回Promise对象包含请求结果
*/
export function patchRequest(url, params = {}, splicingURL = "") {
if (!window.axiosService) throw new Error('未配置Axios请先调用 configureAxios');
return window.axiosService.patchRequest(url, params, splicingURL);
}
/**
* 上传文件请求
* @param {string} url - 请求URL
* @param {Object} params - 请求参数
* @returns {Promise} - 返回Promise对象包含请求结果
*/
export function uploadRequest(url, params = {}) {
if (!window.axiosService) throw new Error('未配置Axios请先调用 configureAxios');
return window.axiosService.uploadRequest(url, params);
}