|
|
@@ -4,13 +4,55 @@ import type {
|
|
|
AxiosResponse,
|
|
|
AxiosRequestHeaders,
|
|
|
} from 'axios';
|
|
|
+import router from '@/router';
|
|
|
import { Message, Modal } from '@arco-design/web-vue';
|
|
|
import { useUserStore } from '@/store';
|
|
|
-import { getToken } from '@/utils/auth';
|
|
|
+import useAuth from '@/utils/auth';
|
|
|
+import { refreshToken } from '@/api/user';
|
|
|
+const { getToken, getRefreshToken, setToken, clearToken } = useAuth();
|
|
|
+
|
|
|
+let isRefreshing = false;
|
|
|
+let subscribers: ((token: string) => void)[] = [];
|
|
|
+
|
|
|
+function subscribeTokenRefresh(cb: (token: string) => void) {
|
|
|
+ subscribers.push(cb);
|
|
|
+}
|
|
|
+
|
|
|
+function onRefreshed(token: string) {
|
|
|
+ subscribers.forEach(cb => cb(token));
|
|
|
+ subscribers = [];
|
|
|
+}
|
|
|
|
|
|
const instance = axios.create({
|
|
|
baseURL: import.meta.env.VITE_API_BASE_URL,
|
|
|
});
|
|
|
+// 新增一个独立的函数来处理 Token 刷新
|
|
|
+async function handleTokenRefresh(
|
|
|
+ refreshTokenValue: string,
|
|
|
+ originalConfig: InternalAxiosRequestConfig
|
|
|
+) {
|
|
|
+ isRefreshing = true;
|
|
|
+ try {
|
|
|
+ const res = await refreshToken({ token: refreshTokenValue });
|
|
|
+ if (res && res.data && res.success) {
|
|
|
+ const { token: newAccessToken, refreshToken: newRefreshToken } = res.data;
|
|
|
+ setToken(newAccessToken, newRefreshToken);
|
|
|
+ onRefreshed(newAccessToken);
|
|
|
+ // 重试原始请求
|
|
|
+ originalConfig.headers.Authorization = `${newAccessToken}`;
|
|
|
+ return instance(originalConfig);
|
|
|
+ } else {
|
|
|
+ throw new Error('Invalid token refresh response');
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ Message.error('登录状态已过期,请重新登录');
|
|
|
+ clearToken();
|
|
|
+ router.push({ name: 'login' });
|
|
|
+ throw error; // 重新抛出错误,让外部拦截器可以继续处理
|
|
|
+ } finally {
|
|
|
+ isRefreshing = false;
|
|
|
+ }
|
|
|
+}
|
|
|
|
|
|
instance.interceptors.request.use(
|
|
|
(config: InternalAxiosRequestConfig) => {
|
|
|
@@ -23,7 +65,7 @@ instance.interceptors.request.use(
|
|
|
if (!config.headers) {
|
|
|
config.headers = {} as AxiosRequestHeaders;
|
|
|
}
|
|
|
- config.headers.Authorization = `Bearer ${token}`;
|
|
|
+ config.headers.Authorization = `${token}`;
|
|
|
}
|
|
|
return config;
|
|
|
},
|
|
|
@@ -35,28 +77,44 @@ instance.interceptors.request.use(
|
|
|
// 响应拦截器修复版本
|
|
|
instance.interceptors.response.use(
|
|
|
(response: AxiosResponse) => {
|
|
|
- const res = response.data;
|
|
|
- console.log('res', res);
|
|
|
- if (response.status === 401) {
|
|
|
- Modal.error({
|
|
|
- title: 'Confirm logout',
|
|
|
- content:
|
|
|
- 'You have been logged out, you can cancel to stay on this page, or log in again',
|
|
|
- okText: 'Re-Login',
|
|
|
- async onOk() {
|
|
|
- const userStore = useUserStore();
|
|
|
- await userStore.logout();
|
|
|
- window.location.reload();
|
|
|
- },
|
|
|
- });
|
|
|
- }
|
|
|
return response;
|
|
|
},
|
|
|
- error => {
|
|
|
- Message.error({
|
|
|
- content: error.message || 'Request Error',
|
|
|
- duration: 5 * 1000,
|
|
|
- });
|
|
|
+ async error => {
|
|
|
+ const { config, response } = error;
|
|
|
+ const refreshTokenValue = getRefreshToken();
|
|
|
+ if (!response) {
|
|
|
+ // 网络错误处理
|
|
|
+ Message.error('网络连接异常');
|
|
|
+ return Promise.reject(error);
|
|
|
+ }
|
|
|
+ if (response.status === 401) {
|
|
|
+ if (!isRefreshing) {
|
|
|
+ isRefreshing = true;
|
|
|
+ config._retry = true;
|
|
|
+ if (refreshTokenValue) {
|
|
|
+ return handleTokenRefresh(refreshTokenValue, config);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ return new Promise(resolve => {
|
|
|
+ subscribeTokenRefresh((token: string) => {
|
|
|
+ config.headers.Authorization = `${token}`;
|
|
|
+ resolve(axios(config));
|
|
|
+ });
|
|
|
+ });
|
|
|
+ }
|
|
|
+ } else if (response.status === 403) {
|
|
|
+ Message.error('没有权限执行此操作');
|
|
|
+ // 可选:跳转到权限不足页面或首页
|
|
|
+ // router.push({ name: 'forbidden' });
|
|
|
+ } else if (response.status === 404) {
|
|
|
+ Message.error('请求的资源不存在');
|
|
|
+ } else if (response.status >= 500) {
|
|
|
+ Message.error('服务器内部错误,请稍后再试');
|
|
|
+ } else {
|
|
|
+ Message.error(
|
|
|
+ error.response?.data?.message || `请求错误: ${response.status}`
|
|
|
+ );
|
|
|
+ }
|
|
|
return Promise.reject(error);
|
|
|
}
|
|
|
);
|