144 lines
4.2 KiB
TypeScript
144 lines
4.2 KiB
TypeScript
|
|
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;
|