refactor(knowledge): restructure knowledge detail page with new components feat(components): add FileUploadDialog for file upload functionality feat(hooks): implement document management hooks for CRUD operations
174 lines
4.6 KiB
TypeScript
174 lines
4.6 KiB
TypeScript
import { Authorization } from '@/constants/authorization';
|
||
import type { ResponseType } from '@/interfaces/database/base';
|
||
import i18n from '@/locales';
|
||
import axios from 'axios';
|
||
import type { AxiosRequestConfig, AxiosInstance, AxiosResponse, InternalAxiosRequestConfig } from 'axios';
|
||
|
||
import { snackbar, notification } from '@/utils/snackbarInstance';
|
||
|
||
const FAILED_TO_FETCH = 'Failed to fetch';
|
||
|
||
export const RetcodeMessage = {
|
||
200: i18n.t('message.200'),
|
||
201: i18n.t('message.201'),
|
||
202: i18n.t('message.202'),
|
||
204: i18n.t('message.204'),
|
||
400: i18n.t('message.400'),
|
||
401: i18n.t('message.401'),
|
||
403: i18n.t('message.403'),
|
||
404: i18n.t('message.404'),
|
||
406: i18n.t('message.406'),
|
||
410: i18n.t('message.410'),
|
||
413: i18n.t('message.413'),
|
||
422: i18n.t('message.422'),
|
||
500: i18n.t('message.500'),
|
||
502: i18n.t('message.502'),
|
||
503: i18n.t('message.503'),
|
||
504: i18n.t('message.504'),
|
||
};
|
||
|
||
export type ResultCode =
|
||
| 200
|
||
| 201
|
||
| 202
|
||
| 204
|
||
| 400
|
||
| 401
|
||
| 403
|
||
| 404
|
||
| 406
|
||
| 410
|
||
| 413
|
||
| 422
|
||
| 500
|
||
| 502
|
||
| 503
|
||
| 504;
|
||
|
||
// 获取授权token
|
||
const getAuthorization = (): string => {
|
||
return localStorage.getItem(Authorization) || '';
|
||
};
|
||
|
||
// 重定向到登录页
|
||
const redirectToLogin = (): void => {
|
||
localStorage.removeItem(Authorization);
|
||
window.location.href = '/login';
|
||
};
|
||
|
||
// 转换对象键为snake_case
|
||
const convertTheKeysOfTheObjectToSnake = (obj: any): any => {
|
||
if (!obj || typeof obj !== 'object') return obj;
|
||
|
||
if (Array.isArray(obj)) {
|
||
return obj.map(convertTheKeysOfTheObjectToSnake);
|
||
}
|
||
|
||
const result: any = {};
|
||
Object.keys(obj).forEach(key => {
|
||
const snakeKey = key.replace(/[A-Z]/g, letter => `_${letter.toLowerCase()}`);
|
||
result[snakeKey] = convertTheKeysOfTheObjectToSnake(obj[key]);
|
||
});
|
||
|
||
return result;
|
||
};
|
||
|
||
// 创建axios实例
|
||
const request: AxiosInstance = axios.create({
|
||
baseURL: import.meta.env.VITE_API_BASE_URL,
|
||
timeout: 300000,
|
||
headers: {
|
||
'Content-Type': 'application/json',
|
||
},
|
||
});
|
||
|
||
// 请求拦截器
|
||
request.interceptors.request.use(
|
||
(config: InternalAxiosRequestConfig) => {
|
||
// 转换数据格式 - 跳过FormData对象
|
||
if (config.data && !(config.data instanceof FormData)) {
|
||
config.data = convertTheKeysOfTheObjectToSnake(config.data);
|
||
}
|
||
if (config.params) {
|
||
config.params = convertTheKeysOfTheObjectToSnake(config.params);
|
||
}
|
||
|
||
// 对于FormData,删除默认的Content-Type让浏览器自动设置
|
||
if (config.data instanceof FormData) {
|
||
delete config.headers['Content-Type'];
|
||
}
|
||
|
||
// 添加授权头
|
||
const authorization = getAuthorization();
|
||
if (authorization && !config.headers?.skipToken) {
|
||
config.headers.Authorization = authorization;
|
||
}
|
||
|
||
return config;
|
||
},
|
||
(error) => {
|
||
return Promise.reject(error);
|
||
}
|
||
);
|
||
|
||
// 响应拦截器
|
||
request.interceptors.response.use(
|
||
(response: AxiosResponse) => {
|
||
const { status } = response;
|
||
|
||
// 处理特定状态码
|
||
if (status === 413 || status === 504) {
|
||
snackbar.error(RetcodeMessage[status as ResultCode]);
|
||
}
|
||
|
||
// 处理blob类型响应
|
||
if (response.config.responseType === 'blob') {
|
||
return response;
|
||
}
|
||
console.log('interceptors.response ------ response', response);
|
||
const data: ResponseType = response.data;
|
||
|
||
// 处理业务错误码
|
||
if (data?.code === 100) {
|
||
snackbar.error(data?.message);
|
||
} else if (data?.code === 401) {
|
||
notification.error(data?.message);
|
||
redirectToLogin();
|
||
} else if (data?.code !== 0) {
|
||
notification.error(`${i18n.t('message.hint')} : ${data?.code}`, data?.message);
|
||
}
|
||
|
||
return response;
|
||
},
|
||
(error) => {
|
||
// 处理网络错误
|
||
if (error.message === FAILED_TO_FETCH || !error.response) {
|
||
notification.error(i18n.t('message.networkAnomaly'), i18n.t('message.networkAnomalyDescription'));
|
||
} else if (error.response) {
|
||
const { status, statusText } = error.response;
|
||
const errorText = RetcodeMessage[status as ResultCode] || statusText;
|
||
notification.error(`${i18n.t('message.requestError')} ${status}`, errorText);
|
||
}
|
||
|
||
return Promise.reject(error);
|
||
}
|
||
);
|
||
|
||
export default request;
|
||
|
||
// 便捷方法
|
||
export const get = (url: string, config?: AxiosRequestConfig) => {
|
||
return request.get(url, config);
|
||
};
|
||
|
||
export const post = (url: string, data?: any, config?: AxiosRequestConfig) => {
|
||
return request.post(url, data, config);
|
||
};
|
||
|
||
export const put = (url: string, data?: any, config?: AxiosRequestConfig) => {
|
||
return request.put(url, data, config);
|
||
};
|
||
|
||
export const del = (url: string, config?: AxiosRequestConfig) => {
|
||
return request.delete(url, config);
|
||
}; |