107 lines
4.0 KiB
JavaScript
107 lines
4.0 KiB
JavaScript
|
// 导入必要的模块和函数
|
|||
|
import { useRouter } from "vue-router"; // 用于路由导航
|
|||
|
import Request from "@/service/request/index.js"; // 自定义请求类
|
|||
|
import { message } from '@/components/x-message/useMessage.js';
|
|||
|
import {authStore} from "~/stores/auth/index.js"; // 消息提示组件
|
|||
|
|
|||
|
// 初始化路由
|
|||
|
const router = useRouter();
|
|||
|
let isRefreshing = false; // 标记是否正在刷新token
|
|||
|
let refreshSubscribers = []; // 存储刷新token的回调函数
|
|||
|
const config = useRuntimeConfig(); // 获取运行时配置
|
|||
|
|
|||
|
// 创建请求实例
|
|||
|
const request = new Request({
|
|||
|
baseURL: config.public.NUXT_PUBLIC_API_BASE, // 基础URL
|
|||
|
timeout: 1000 * 60 * 5, // 超时时间设置为5分钟
|
|||
|
showMsg: true, // 是否显示消息提示
|
|||
|
interceptors: {
|
|||
|
// 请求拦截器
|
|||
|
requestInterceptors: (config) => {
|
|||
|
// 根据是否是表单数据设置Content-Type
|
|||
|
const contentType = config.isFormData ? 'multipart/form-data' : config.contentType || 'application/json';
|
|||
|
config.headers = {
|
|||
|
"Content-Type": contentType,
|
|||
|
"Authorization": localStorage.getItem('token') || '' // 从本地存储获取token
|
|||
|
};
|
|||
|
return config; // 返回修改后的配置
|
|||
|
},
|
|||
|
// 响应拦截器
|
|||
|
responseInterceptors: async (response) => {
|
|||
|
// 如果需要显示消息且状态为1,显示警告消息
|
|||
|
if (response.config.showMsg && response.data.status === 1) {
|
|||
|
message.warning(response.data.msg);
|
|||
|
}
|
|||
|
// 如果响应码为401,尝试刷新token
|
|||
|
if (response.data.code === 401) {
|
|||
|
return getRefreshToken(response);
|
|||
|
}
|
|||
|
// 如果响应状态为200, 201, 204,直接返回响应
|
|||
|
if ([200, 201, 204].includes(response.status)) {
|
|||
|
return response.config.responseType === "blob" ? response : response;
|
|||
|
} else {
|
|||
|
// 处理其他错误情况
|
|||
|
const errorMsg = response.data.msg || 'An error occurred.';
|
|||
|
message.error(errorMsg);
|
|||
|
return Promise.reject(new Error(errorMsg));
|
|||
|
}
|
|||
|
},
|
|||
|
},
|
|||
|
});
|
|||
|
|
|||
|
// 刷新token的函数
|
|||
|
async function getRefreshToken(response) {
|
|||
|
const {token,RefreshToken,userInfo}= authStore()
|
|||
|
if (!isRefreshing) {
|
|||
|
isRefreshing = true; // 标记正在刷新
|
|||
|
const refreshToken = RefreshToken.value; // 获取刷新token
|
|||
|
if (refreshToken) {
|
|||
|
try {
|
|||
|
// 发送请求刷新token
|
|||
|
const res = await request.post("/user/refresh/token", { refreshToken });
|
|||
|
if (res.code === 200) {
|
|||
|
// 更新本地存储的token和用户信息
|
|||
|
token.value = res.data.Token;
|
|||
|
userInfo.value=res.data.AccountInfo
|
|||
|
RefreshToken.value = res.data.RefreshToken;
|
|||
|
response.config.headers["Authorization"] = res.data.Token; // 更新请求头的token
|
|||
|
return request.request(response.config); // 重新发送原始请求
|
|||
|
} else {
|
|||
|
handleAuthError(res); // 处理认证错误
|
|||
|
}
|
|||
|
} catch (error) {
|
|||
|
throw error; // 抛出错误
|
|||
|
} finally {
|
|||
|
isRefreshing = false; // 重置刷新标记
|
|||
|
refreshSubscribers.forEach(callback => callback()); // 执行所有等待的回调
|
|||
|
refreshSubscribers = []; // 清空回调列表
|
|||
|
}
|
|||
|
} else {
|
|||
|
handleAuthError(); // 没有刷新token时处理错误
|
|||
|
}
|
|||
|
} else {
|
|||
|
// 如果正在刷新,返回一个Promise,等待刷新完成后重新发送请求
|
|||
|
return new Promise(resolve => {
|
|||
|
refreshSubscribers.push(() => resolve(request.request(response.config)));
|
|||
|
});
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// 处理认证错误的函数
|
|||
|
function handleAuthError(res = {}) {
|
|||
|
router.push("/login"); // 跳转到登录页面
|
|||
|
const errorMsg = res.message || res.msg || "No refresh token available."; // 错误消息
|
|||
|
message.error(errorMsg); // 显示错误消息
|
|||
|
throw new Error(errorMsg); // 抛出错误
|
|||
|
}
|
|||
|
|
|||
|
// 发送请求的函数
|
|||
|
const fontRequest = (config) => {
|
|||
|
// 如果是GET请求,将data作为params
|
|||
|
if (["get", "GET"].includes(config.method)) {
|
|||
|
config.params = config.data;
|
|||
|
}
|
|||
|
return request.request(config); // 发送请求
|
|||
|
};
|
|||
|
|
|||
|
export default fontRequest; // 导出请求函数
|