mirror of
https://github.com/fastapiadmin/FastapiAdmin.git
synced 2026-09-25 13:51:04 +00:00
发布v2.0.0分支
This commit is contained in:
@@ -0,0 +1,116 @@
|
||||
import axios, { type InternalAxiosRequestConfig, type AxiosResponse, type AxiosInstance, type AxiosError} from "axios";
|
||||
import qs from "qs";
|
||||
import { useUserStoreHook } from "@/store/modules/user.store";
|
||||
import { ResultEnum } from "@/enums/api/result.enum";
|
||||
import { Auth } from "@/utils/auth";
|
||||
import router from "@/router";
|
||||
|
||||
/**
|
||||
* 创建 HTTP 请求实例
|
||||
*/
|
||||
const httpRequest: AxiosInstance = axios.create({
|
||||
baseURL: import.meta.env.VITE_APP_BASE_API,
|
||||
timeout: import.meta.env.VITE_TIMEOUT,
|
||||
headers: { "Content-Type": "application/json;charset=utf-8" },
|
||||
paramsSerializer: (params) => qs.stringify(params),
|
||||
});
|
||||
|
||||
/**
|
||||
* 请求拦截器 - 添加 Authorization 头
|
||||
*/
|
||||
httpRequest.interceptors.request.use(
|
||||
(config: InternalAxiosRequestConfig) => {
|
||||
const accessToken = Auth.getAccessToken();
|
||||
|
||||
// 如果 Authorization 设置为 no-auth,则不携带 Token
|
||||
if (!config.headers.Authorization && accessToken) {
|
||||
config.headers.Authorization = `Bearer ${accessToken}`;
|
||||
} else {
|
||||
delete config.headers.Authorization;
|
||||
}
|
||||
|
||||
return config;
|
||||
},
|
||||
(error) => {
|
||||
console.error("请求异常:", error);
|
||||
ElMessage.error(error);
|
||||
return Promise.reject(error);
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* 响应拦截器 - 统一处理响应和错误
|
||||
*/
|
||||
httpRequest.interceptors.response.use(
|
||||
(response: AxiosResponse<ApiResponse>) => {
|
||||
// 如果响应是二进制流,则直接返回(用于文件下载、Excel 导出等)
|
||||
if (response?.config?.responseType === "blob") {
|
||||
return response;
|
||||
}
|
||||
|
||||
const data = response.data;
|
||||
|
||||
// 请求成功
|
||||
if (data.code === ResultEnum.SUCCESS) {
|
||||
ElMessage.success(data.msg);
|
||||
return response;
|
||||
} else if (data.code === ResultEnum.ERROR) {
|
||||
ElMessage.error(data.msg || "请求错误");
|
||||
return Promise.reject(new Error(data.msg || "请求错误"));
|
||||
} else if (data.code === ResultEnum.EXCEPTION) {
|
||||
ElMessage.error(data.msg || "服务异常");
|
||||
return Promise.reject(new Error(data.msg || "服务异常"));
|
||||
} else {
|
||||
ElMessage.error(data.msg || "请求异常");
|
||||
return Promise.reject(new Error(data.msg || "请求异常"));
|
||||
}
|
||||
},
|
||||
async (error: AxiosError) => {
|
||||
console.error("响应异常 " + error);
|
||||
|
||||
const { response } = error;
|
||||
|
||||
// 网络错误或服务器无响应
|
||||
if (!response) {
|
||||
ElMessage.error("网络连接失败,请检查网络设置");
|
||||
return Promise.reject(error);
|
||||
}
|
||||
|
||||
const { status_code, msg } = response.data as ApiResponse;
|
||||
|
||||
switch (status_code) {
|
||||
case ResultEnum.ACCESS_TOKEN_INVALID:
|
||||
// Access Token 过期
|
||||
await redirectToLogin("登录已过期,请重新登录");
|
||||
return Promise.reject(new Error(msg || "Refresh Token Invalid"));
|
||||
|
||||
default:
|
||||
ElMessage.error(msg || "响应错误");
|
||||
return Promise.reject(new Error(msg || "响应错误"));
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* 重定向到登录页面
|
||||
*/
|
||||
async function redirectToLogin(message: string = "请重新登录"): Promise<void> {
|
||||
try {
|
||||
ElNotification({
|
||||
title: "提示",
|
||||
message,
|
||||
type: "warning",
|
||||
duration: 3000,
|
||||
});
|
||||
|
||||
await useUserStoreHook().resetAllState();
|
||||
|
||||
// 跳转到登录页,保留当前路由用于登录后跳转
|
||||
const currentPath = router.currentRoute.value.fullPath;
|
||||
await router.push(`/login?redirect=${encodeURIComponent(currentPath)}`);
|
||||
} catch (error) {
|
||||
console.error("Redirect to login error:", error);
|
||||
}
|
||||
}
|
||||
|
||||
export default httpRequest;
|
||||
Reference in New Issue
Block a user