Files
schisandra-cloud-album-front/src/utils/alova/service.ts
2024-09-24 01:14:50 +08:00

104 lines
3.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import {createAlova} from 'alova';
import VueHook from 'alova/vue';
import useStore from "@/store";
import {localforageStorageAdapter} from "@/utils/alova/adapter/localforageStorageAdapter.ts";
import {createServerTokenAuthentication} from "alova/client";
import {AxiosError, AxiosResponse} from "axios";
import {handleCode} from "@/utils/errorCode/errorCodeHandler.ts";
import {message, Modal} from "ant-design-vue";
import i18n from "@/locales";
import {axiosRequestAdapter} from "@alova/adapter-axios";
import {refreshToken} from "@/api/user";
let hasShownNetworkError: boolean = false;
const {onAuthRequired, onResponseRefreshToken} = createServerTokenAuthentication<typeof VueHook,
typeof axiosRequestAdapter>({
refreshTokenOnSuccess: {
// 在请求前触发将接收到method参数并返回boolean表示token是否过期
isExpired: (response: AxiosResponse<any, any>, _method: any) => {
const code = response.data.code;
return code === 401;
},
// 当token过期时触发在此函数中触发刷新token
handler: async () => {
// 刷新token
const user = useStore().user;
const res: any = await refreshToken(user.user?.refreshToken);
if (res.code === 200 && res.data) {
const {access_token, refresh_token, uid} = res.data;
user.user.accessToken = access_token;
user.user.refreshToken = refresh_token;
user.user.uid = uid;
} else {
message.error(i18n.global.t('error.loginExpired'));
localStorage.removeItem('user');
setTimeout(() => {
window.location.href = '/login';
}, 2000);
}
}
}
});
export const service = createAlova({
timeout: 5000,
baseURL: import.meta.env.VITE_APP_BASE_API,
statesHook: VueHook,
// 请求适配器
requestAdapter: axiosRequestAdapter(),
l2Cache: localforageStorageAdapter,
cacheLogger: import.meta.env.VITE_NODE_ENV === 'development',
cacheFor: {},
// 设置全局的请求拦截器
beforeRequest: onAuthRequired(async (method: any) => {
if (!method.meta?.ignoreToken) {
const user = useStore().user;
method.config.headers.Authorization = `${import.meta.env.VITE_APP_TOKEN_KEY} ${user.user.accessToken}`;
method.config.headers['X-UID'] = user.user.uid;
}
const lang = useStore().lang;
method.config.headers['Accept-Language'] = lang.lang || 'zh';
}),
// 响应拦截器
responded: onResponseRefreshToken({
onSuccess: async (response: AxiosResponse, _method: any) => {
if (response.data instanceof Blob) {
return response;
}
const {code} = response.data;
if (code === 403) {
localStorage.removeItem('user');
Modal.warning({
title: i18n.global.t('error.loginExpired'),
content: i18n.global.t('error.authTokenExpired'),
onOk() {
window.location.href = '/login';
},
onCancel() {
window.location.href = '/login';
}
});
return Promise.reject(response.data);
}
return response.data;
},
onError:
(error: AxiosError, _method: any) => {
const {response} = error;
if (response && !hasShownNetworkError) {
hasShownNetworkError = true;
handleCode(response.status);
}
if (!window.navigator.onLine) {
message.error(i18n.global.t('error.networkError')).then();
return Promise.reject(error);
}
},
}),
});