| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124 |
- import axios from 'axios';
- import type {
- InternalAxiosRequestConfig,
- AxiosResponse,
- AxiosRequestHeaders,
- } from 'axios';
- import router from '@/router';
- import { Message, Modal } from '@arco-design/web-vue';
- import { useUserStore } from '@/store';
- 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: '/',
- });
- // 新增一个独立的函数来处理 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 {
- isRefreshing = false;
- clearToken();
- router.push({ name: 'login' });
- 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) => {
- // let each request carry token
- // this example using the JWT token
- // Authorization is a custom headers key
- // please modify it according to the actual situation
- const token = getToken();
- if (token) {
- if (!config.headers) {
- config.headers = {} as AxiosRequestHeaders;
- }
- config.headers.Authorization = `${token}`;
- }
- return config;
- },
- error => {
- // do something
- return Promise.reject(error);
- }
- );
- // 响应拦截器修复版本
- instance.interceptors.response.use(
- (response: AxiosResponse) => {
- return response;
- },
- 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);
- }
- );
- export default instance;
|