144 lines
4.2 KiB
TypeScript
Raw Normal View History

2025-05-27 19:31:37 +08:00
import { useAccessStore, useUserStore } from '@vben/stores';
import { message as Message } from 'ant-design-vue';
import { postApiAppAccountRefreshToken } from '#/api-client';
import { $t } from '#/locales';
import { antdLocale } from '#/locales/index';
import { useAuthStore } from '#/store';
import { client } from '../api-client/services.gen';
client.setConfig({
baseURL: import.meta.env.DEV
? '/proxy/'
: import.meta.env.VITE_APP_API_ADDRESS,
timeout: 1000 * 60,
responseType: 'json',
throwOnError: true,
});
// 是否正在刷新token
let isRefreshing = false;
// 刷新token队列
let refreshTokenQueue: ((token: string) => void)[] = [];
client.instance.interceptors.request.use((request) => {
// 全局拦截请求发送前提交的参数
const userStore = useUserStore();
const accessStore = useAccessStore();
const token = accessStore.getAccessToken();
// 设置请求头
if (request.headers) {
request.headers.__tenant = userStore.tenant?.tenantId;
// todo vben5 没有提供统一获取当前语言的方式
request.headers['accept-language'] = antdLocale.value.locale;
}
// 如果token过期则跳转到登录页面
if (
request.url !== undefined &&
request.url.includes('/api/app/account/login')
) {
return request;
}
// 设置请求头
if (request.headers) {
request.headers.Authorization = `Bearer ${token}`;
}
return request;
});
client.instance.interceptors.response.use(
(response) => {
return Promise.resolve(response);
},
async (error) => {
let message = error.message;
if (message === 'Network Error') {
message = $t('common.mesage500');
} else if (message.includes('timeout')) {
message = $t('common.timeOut');
} else
switch (error.status) {
case 400: {
message = error.response.data.error?.validationErrors[0].message;
break;
}
case 401: {
message = $t('common.mesage401');
const { config } = error;
const originalRequest = config;
if (isRefreshing) {
return new Promise((resolve) => {
refreshTokenQueue.push((token) => {
originalRequest.headers.Authorization = `Bearer ${token}`;
resolve(client.request(originalRequest));
});
});
} else {
isRefreshing = true;
try {
const newToken = await refreshTokenAsync();
// 处理队列中的请求
refreshTokenQueue.forEach((callback) => callback(newToken));
// 清空队列
refreshTokenQueue = [];
return client.request(originalRequest);
} catch (refreshError) {
// 如果刷新 token 失败,处理错误(如强制登出或跳转登录页面)
message = $t('common.mesage401');
refreshTokenQueue = [];
const authStore = useAuthStore();
authStore.logout();
console.error(refreshError);
} finally {
isRefreshing = false;
}
}
break;
}
case 403: {
message = $t('common.mesage403');
break;
}
case 500: {
message = error.response.data.error?.message;
break;
}
default: {
if (message.includes('Request failed with status code')) {
message = $t('common.mesage500');
}
}
}
Message.error(message);
throw error;
},
);
async function refreshTokenAsync(): Promise<string> {
try {
const userStore = useUserStore();
const accessStore = useAccessStore();
const refreshToken = accessStore.getRefreshToken();
if (!refreshToken) return '';
const res = await postApiAppAccountRefreshToken({
body: {
userId: userStore.userInfo?.id,
refreshToken,
},
});
if (res?.data?.success) {
accessStore.setAccessToken(res.data.token as string);
accessStore.setRefreshToken(res.data.refreshToken as string);
return res.data.token as string;
} else {
throw new Error('get refreshToken error');
}
} catch {
throw new Error($t('common.mesage401'));
}
}
export default client;