6fed499d78
- 新增VimpRequestOptions配置接口,支持自定义请求、响应及错误拦截器 - 补充get、put、delete请求方法并封装统一响应格式 - 添加默认请求拦截器自动携带公共认证参数 - 实现401错误拦截,超时自动跳转登录页并重置用户状态
153 lines
5.5 KiB
TypeScript
153 lines
5.5 KiB
TypeScript
import type { AxiosError, AxiosRequestConfig, AxiosResponse, CreateAxiosDefaults, InternalAxiosRequestConfig } from 'axios';
|
|
import axios, { isAxiosError } from 'axios';
|
|
import type { VimpResponse, VimpResult } from '../../types';
|
|
import { useUserStore } from '@/stores';
|
|
import { getAppEnvConfig } from '@/utils';
|
|
import router from '@/router';
|
|
|
|
export interface VimpRequestOptions extends CreateAxiosDefaults {
|
|
requestInterceptor?: (config: InternalAxiosRequestConfig) => InternalAxiosRequestConfig | Promise<InternalAxiosRequestConfig>;
|
|
responseInterceptor?: (resp: AxiosResponse) => AxiosResponse | Promise<AxiosResponse>;
|
|
responseErrorInterceptor?: (error: any) => any;
|
|
}
|
|
|
|
export const createVimpClient = (config?: VimpRequestOptions) => {
|
|
const defaultRequestInterceptor = (config: InternalAxiosRequestConfig) => config;
|
|
const defaultResponseInterceptor = (response: AxiosResponse) => response;
|
|
const defaultResponseErrorInterceptor = (error: any) => {
|
|
if (isAxiosError(error)) {
|
|
if (error.status === 401) {
|
|
// 处理 401 错误
|
|
}
|
|
if (error.status === 404) {
|
|
// 处理 404 错误
|
|
}
|
|
}
|
|
return Promise.reject(error);
|
|
};
|
|
|
|
const requestInterceptor = config?.requestInterceptor ?? defaultRequestInterceptor;
|
|
const responseInterceptor = config?.responseInterceptor ?? defaultResponseInterceptor;
|
|
const responseErrorInterceptor = config?.responseErrorInterceptor ?? defaultResponseErrorInterceptor;
|
|
|
|
const instance = axios.create(config);
|
|
instance.interceptors.request.use(requestInterceptor);
|
|
instance.interceptors.response.use(responseInterceptor, responseErrorInterceptor);
|
|
|
|
const vimpGet = <T>(url: string, options?: AxiosRequestConfig & { retRaw?: boolean }): Promise<VimpResponse<T>> => {
|
|
const { retRaw, ...reqConfig } = options ?? {};
|
|
return new Promise((resolve) => {
|
|
instance
|
|
.get(url, {
|
|
...reqConfig,
|
|
})
|
|
.then((res) => {
|
|
if (retRaw) {
|
|
resolve([null, res.data as T, null]);
|
|
} else {
|
|
const resData = res.data as VimpResult<T>;
|
|
resolve([null, resData.data, resData]);
|
|
}
|
|
})
|
|
.catch((err) => {
|
|
resolve([err as AxiosError, null, null]);
|
|
});
|
|
});
|
|
};
|
|
|
|
const vimpPost = <T>(url: string, data?: AxiosRequestConfig['data'], options?: Partial<Omit<AxiosRequestConfig, 'data'>> & { retRaw?: boolean; upload?: boolean }): Promise<VimpResponse<T>> => {
|
|
const { retRaw, upload, ...reqConfig } = options ?? {};
|
|
return new Promise((resolve) => {
|
|
instance
|
|
.post(url, data, { headers: { 'content-type': upload ? 'multipart/form-data' : 'application/json' }, ...reqConfig })
|
|
.then((res) => {
|
|
const resData = res.data;
|
|
if (retRaw) {
|
|
resolve([null, resData as T, null]);
|
|
} else {
|
|
resolve([null, resData.data as T, resData as VimpResult<T>]);
|
|
}
|
|
})
|
|
.catch((err) => {
|
|
resolve([err as AxiosError, null, null]);
|
|
});
|
|
});
|
|
};
|
|
|
|
const httpPut = <T>(url: string, data?: AxiosRequestConfig['data'], options?: Partial<Omit<AxiosRequestConfig, 'data'>>): Promise<VimpResponse<T>> => {
|
|
const reqConfig = options ?? {};
|
|
return new Promise((resolve) => {
|
|
instance
|
|
.put<VimpResult<T>>(url, data, { ...reqConfig })
|
|
.then((res) => {
|
|
resolve([null, res.data.data, res.data]);
|
|
})
|
|
.catch((err) => {
|
|
resolve([err as AxiosError, null, null]);
|
|
});
|
|
});
|
|
};
|
|
|
|
const httpDelete = <T>(url: string, idList: string[], options?: Partial<Omit<AxiosRequestConfig, 'data'>>): Promise<VimpResponse<T>> => {
|
|
const reqConfig = options ?? {};
|
|
return new Promise((resolve) => {
|
|
instance
|
|
.delete<VimpResult<T>>(url, { ...reqConfig, data: idList })
|
|
.then((res) => {
|
|
resolve([null, res.data.data, res.data]);
|
|
})
|
|
.catch((err) => {
|
|
resolve([err as AxiosError, null, null]);
|
|
});
|
|
});
|
|
};
|
|
|
|
return {
|
|
instance,
|
|
get: vimpGet,
|
|
post: vimpPost,
|
|
put: httpPut,
|
|
delete: httpDelete,
|
|
};
|
|
};
|
|
|
|
export const unwrapVimpResponse = <T>(resp: VimpResponse<T>) => {
|
|
const [err, data, result] = resp;
|
|
if (err) throw err;
|
|
if (result) {
|
|
const { code, msg } = result;
|
|
if (code !== 0 && code !== 200) throw new Error(`${msg || '请求失败'}`);
|
|
}
|
|
return data;
|
|
};
|
|
|
|
export const vimpClient = createVimpClient({
|
|
baseURL: `/vimp/api/client`,
|
|
requestInterceptor: (config) => {
|
|
const userStore = useUserStore();
|
|
const { lampAuthorization, lampClientId, lampClientSecret } = getAppEnvConfig();
|
|
const newAuthorization = window.btoa(`${lampClientId}:${lampClientSecret}`);
|
|
const authorization = lampAuthorization.trim() !== '' ? lampAuthorization : newAuthorization;
|
|
config.headers.set('accept-language', 'zh-CN,zh;q=0.9');
|
|
config.headers.set('accept', 'application/json, text/plain, */*');
|
|
config.headers.set('Applicationid', '');
|
|
config.headers.set('Tenantid', '1');
|
|
config.headers.set('Authorization', authorization);
|
|
config.headers.set('token', userStore.userLoginResult?.token ?? '');
|
|
return config;
|
|
},
|
|
responseInterceptor: (response) => {
|
|
return response;
|
|
},
|
|
responseErrorInterceptor: (error) => {
|
|
const err = error as AxiosError;
|
|
if (err.response?.status === 401) {
|
|
window.$message.error('登录超时,请重新登录');
|
|
const userStore = useUserStore();
|
|
userStore.resetStore();
|
|
router.push({ path: '/login' });
|
|
}
|
|
return Promise.reject(error);
|
|
},
|
|
});
|