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
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
|