136 lines
3.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import type { AxiosError, AxiosInstance, AxiosRequestConfig, AxiosResponse, InternalAxiosRequestConfig } from 'axios'
import axios from 'axios'
import qs from 'qs'
import type { Ref } from 'vue'
import { ElNotification } from 'element-plus'
import { ref } from 'vue'
// 创建 axios 实例
let service: AxiosInstance
export interface AxiosResponseData {
code: number
content: string
}
export function initService() {
service = axios.create({
baseURL: '/api',
timeout: 50000,
headers: { 'Content-Type': 'application/json;charset=utf-8' },
paramsSerializer: (params) => {
return qs.stringify(params)
},
})
// 请求拦截器
service.interceptors.request.use(
(config: InternalAxiosRequestConfig) => {
return config
},
(error: Error) => {
return Promise.reject(error)
},
)
// 响应拦截器
service.interceptors.response.use(
(response: AxiosResponse<AxiosResponseData, unknown>) => {
// 判断响应状态码是否为2xx
if (response.status < 200 || response.status >= 300) {
throw new Error(response.data?.content)
}
// 检查配置的响应类型是否为二进制类型('blob' 或 'arraybuffer', 如果是,直接返回响应对象
if (
response.config.responseType === 'blob' ||
response.config.responseType === 'arraybuffer'
) {
return response as unknown as AxiosResponse
}
return response.data as unknown as AxiosResponse
},
(error: AxiosError<AxiosResponseData | string>) => {
let message: string = ''
if (error.response && error.response.status === 500) {
message = '系统错误'
}
// if (error.config?.url === '/irs/data-do' && error.config?.method === 'get') {
// return Promise.reject(new Error(message))
// }
return Promise.reject(new Error(message))
},
)
}
export interface UseAxiosOption {
// 错误时不弹窗
hideErrorTip?: boolean
}
// 导出 axios 实例
export async function request<T = unknown, R = AxiosResponse<T>, D = unknown>(
config: AxiosRequestConfig<D>,
{ hideErrorTip = false } = {} as UseAxiosOption,
): Promise<R> {
try {
return await service<T, R, D>(config)
} catch (error) {
if (!hideErrorTip) {
ElNotification({
showClose: true,
message: (error as Error)?.message,
type: 'error',
})
}
return Promise.reject(error)
}
}
export default request
export interface UseRequestOption<R> extends UseAxiosOption {
defaultData?: R
}
export interface UseRequestResult<R> {
data: Ref<R>
error: Ref<Error | undefined>
loading: Ref<boolean>
refresh: () => Promise<void>
}
export function useRequest<T = unknown, R = AxiosResponse<T>, D = unknown>(
config: AxiosRequestConfig<D>,
{ defaultData = {} as R, ...rest } = {} as UseRequestOption<R>,
) {
const data = ref<R>(defaultData) as Ref<R>
const loading = ref<boolean>(false)
const error = ref<Error>()
const fetchResource = async (conf = config): Promise<void> => {
loading.value = true
try {
data.value = await request<T, R, D>(conf, rest)
} catch (e) {
error.value = e as Error
} finally {
loading.value = false
}
}
const promise = new Promise((resolve) => {
void fetchResource().finally(() => resolve({ data, error, loading, refresh: fetchResource }))
}) as unknown as UseRequestResult<R> & Promise<UseRequestResult<R>>
promise.data = data
promise.error = error
promise.loading = loading
promise.refresh = fetchResource
return promise
}