import { getToken, setToken } from '@/store/system.ts' import { IApiResult } from '@/global' import { Record } from '@icon-park/react' import { message } from 'antd' import axios, { AxiosRequestConfig, AxiosInstance, AxiosResponse, } from 'axios' export type { AxiosRequestConfig } type FetchMethod = (url: string, data?: D, config?: AxiosRequestConfig) => Promise> interface RequestMethods extends Pick { download: (url: string, data?: any) => Promise } const axiosInstance = axios.create({ baseURL: '/api/v1', // timeout: 1000, headers: { 'Content-Type': 'application/json', }, validateStatus: status => { return status >= 200 && status < 300 } }) //拦截request,添加token axiosInstance.interceptors.request.use((config) => { const token = getToken() if (token) { config.headers.Authorization = `Bearer ${token}` } return config }, (error) => { console.log('error', error) return Promise.reject(error) }) //拦截response,返回data axiosInstance.interceptors.response.use( (response) => { // console.log('response', response.data) message.destroy() const result = response.data as IApiResult switch (result.code) { case 0: case 200: //login if (response.config.url?.includes('/sys/login')) { setToken(result.data.token) const search = new URLSearchParams(window.location.search) // eslint-disable-next-line no-case-declarations const redirect = search.get('redirect') if (redirect) { window.location.href = redirect } } return response case 401: setToken('') if (window.location.pathname === '/login') { return Promise.reject(new Error('to login')) } // 401: 未登录 message.error('登录失败,跳转重新登录') // eslint-disable-next-line no-case-declarations const search = new URLSearchParams(window.location.search) // eslint-disable-next-line no-case-declarations let redirect = window.location.pathname if (search.toString() !== '') { redirect = window.location.pathname + '?=' + search.toString() } window.location.href = `/login?redirect=${encodeURIComponent(redirect)}` return Promise.reject(new Error('to login')) default: message.error(result.message ?? '请求失败') return Promise.reject(response) } }, (error) => { // console.log('error', error) message.destroy() const { response } = error if (response) { switch (response.status) { case 401: if (window.location.pathname === '/login') { return } setToken('') // 401: 未登录 message.error('登录失败,跳转重新登录') // eslint-disable-next-line no-case-declarations const search = new URLSearchParams(window.location.search) // eslint-disable-next-line no-case-declarations let redirect = window.location.pathname if (search.toString() !== '') { redirect = window.location.pathname + '?=' + search.toString() } window.location.href = `/login?redirect=${encodeURIComponent(redirect)}` return case 403: message.error('没有权限') break case 404: message.error('请求的资源不存在') break default: message.error(response.data.message ?? response.data ?? error.message ?? '请求失败') return Promise.reject(response) } } return Promise.reject(error) }) //扩展download方法 // @ts-ignore fix download axiosInstance.download = (url: string, data?: any) => { const formData = new FormData() for (const key in data) { formData.append(key, data[key]) } const config = { method: 'post', url, data: formData, responseType: 'blob', timeout: 40 * 1000, } as AxiosRequestConfig return axiosInstance.request(config) } //创建返回IApiResult类型的request export const createFetchMethods = () => { const methods = {} for (const method of Object.keys(axiosInstance)) { methods[method] = async (url: string, data?: D, config?: AxiosRequestConfig) => { config = config ?? {} config.url = url config.method = method const isGet = method === 'get' if (isGet) { config.params = data } else { config.data = data } return axiosInstance(config) .then((response: AxiosResponse>) => { if (response.data.code !== 200 && response.data.code !== 0) { throw new Error(response.data.message) } return response.data as IApiResult }) .catch((err) => { throw err }) } } return methods as Record } export const request = createFetchMethods() export default request