You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

178 lines
5.6 KiB

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 = <T = any, D = any>(url: string, data?: D, config?: AxiosRequestConfig<D>) => Promise<IApiResult<T>>
interface RequestMethods extends Pick<AxiosInstance, 'get' | 'post' | 'put' | 'delete' | 'request' | 'postForm' | 'patch' | 'patchForm' | 'putForm' | 'options'> {
download: (url: string, data?: any) => Promise<BlobPart>
}
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 <T = any, D = any>(url: string, data?: D, config?: AxiosRequestConfig<D>) => {
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<IApiResult<T>>) => {
if (response.data.code !== 200 && response.data.code !== 0) {
throw new Error(response.data.message)
}
return response.data as IApiResult<T>
})
.catch((err) => {
throw err
})
}
}
return methods as Record<keyof RequestMethods, FetchMethod>
}
export const request = createFetchMethods()
export default request