mirror of
https://gitee.com/mirrors/AllinSSL.git
synced 2026-03-20 21:08:57 +08:00
【同步】前端项目源码
【修复】工作流兼容问题
This commit is contained in:
290
frontend/packages/vue/hooks/src/axios/index.ts
Normal file
290
frontend/packages/vue/hooks/src/axios/index.ts
Normal file
@@ -0,0 +1,290 @@
|
||||
import { AxiosError, AxiosResponse } from 'axios'
|
||||
import { ref, shallowRef, computed, watch, effectScope, onScopeDispose } from 'vue'
|
||||
import type { Ref, ShallowRef, ComputedRef } from 'vue'
|
||||
import { useLoadingMask, useDialog, useMessage } from '@baota/naive-ui/hooks'
|
||||
import { HttpClient, type Middleware } from './model'
|
||||
import { useError } from '../error'
|
||||
import { cancelRequest, removeAllAbortController } from './model/axios-cancel'
|
||||
|
||||
import type { CustomDialogOptions } from '@baota/naive-ui/types/dialog'
|
||||
import type { LoadingMaskOptions } from '@baota/naive-ui/types/loadingMask'
|
||||
|
||||
export type HttpStatusCode = 200 | 201 | 204 | 400 | 401 | 403 | 404 | 500 | 502 | 504
|
||||
|
||||
/**
|
||||
* @description API响应类型
|
||||
*/
|
||||
export interface ApiResponse<T = unknown> {
|
||||
status: boolean
|
||||
message: string
|
||||
code: HttpStatusCode
|
||||
data: T
|
||||
}
|
||||
|
||||
export interface useAxiosReturn<T, Z> {
|
||||
/** 加载遮罩 */
|
||||
loadingMask: Ref<{ status: boolean } & LoadingMaskOptions>
|
||||
/** 消息提示 */
|
||||
message: Ref<boolean>
|
||||
/** 确认框 */
|
||||
dialog: Ref<{ status: boolean } & CustomDialogOptions>
|
||||
/** 响应式状态 */
|
||||
loading: Ref<boolean>
|
||||
/** 错误 */
|
||||
error: ShallowRef<Error | null | string>
|
||||
/** 响应 */
|
||||
response: ShallowRef<AxiosResponse<T> | null>
|
||||
/** 响应数据 */
|
||||
data: Ref<T>
|
||||
/** 默认数据 */
|
||||
defaultData: Ref<T>
|
||||
/** HTTP状态码 */
|
||||
statusCode: ComputedRef<HttpStatusCode | null>
|
||||
/** 是否被中断 */
|
||||
aborted: Ref<boolean>
|
||||
/** URL和参数 */
|
||||
urlRef: Ref<string>
|
||||
/** 请求参数 */
|
||||
paramsRef: Ref<Z>
|
||||
/** 执行请求 */
|
||||
execute: (url: string, params?: Z) => Promise<T>
|
||||
/** 设置参数 */
|
||||
setParams: (params: Z) => Promise<T>
|
||||
/** 设置URL */
|
||||
setUrl: (url: string, params?: Z) => Promise<T>
|
||||
/** 取消请求 */
|
||||
cancel: (url: string) => void
|
||||
/** 取消所有请求 */
|
||||
cancelAll: () => void
|
||||
/** 发起请求 */
|
||||
fetch: (params?: Z) => Promise<T>
|
||||
}
|
||||
|
||||
/**
|
||||
* @description axios hooks
|
||||
* @param instance HTTP客户端实例
|
||||
* @param config 配置项
|
||||
* @returns 响应式对象和方法
|
||||
*/
|
||||
const useAxios = <T = unknown, Z = Record<string, unknown>>(instance: HttpClient): useAxiosReturn<T, Z> => {
|
||||
const { open, close, update } = useLoadingMask() // 加载遮罩
|
||||
|
||||
// 请求状态
|
||||
const loadingMaskRefs = ref<{ status: boolean } & LoadingMaskOptions>({
|
||||
status: false, // 是否启用遮罩过渡
|
||||
text: '正在处理,请稍后...', // 加载文本
|
||||
})
|
||||
|
||||
// 响应数据
|
||||
const dialogRefs = ref<{ status: boolean } & CustomDialogOptions>({
|
||||
status: false, // 是否启动确认框
|
||||
}) // 消息提示
|
||||
|
||||
const loadingRef = ref(false) // 是否正在加载
|
||||
const messageRef = ref(false) // 消息提示
|
||||
const loadingInstance = shallowRef<unknown>(null) // 加载实例
|
||||
|
||||
// 响应数据
|
||||
const errorRef = shallowRef<Error | null | string>(null) // 错误
|
||||
const response = shallowRef<AxiosResponse<T> | null>(null) // 原始响应
|
||||
const statusCode = computed<HttpStatusCode | null>(() => (response.value?.status as HttpStatusCode) || null) // HTTP状态码
|
||||
const dataRef = ref<T>({} as T) // 处理后的数据
|
||||
const defaultData = ref<T>({} as T) // 默认数据
|
||||
|
||||
// 请求参数
|
||||
const urlRef = ref('') // url
|
||||
const paramsRef = ref<Z>({} as Z) // 参数
|
||||
// const replayRef = ref({ url: '', params: {} as Z }) // 重放请求
|
||||
const aborted = ref(false) // 是否被中断
|
||||
|
||||
// 控制加载遮罩
|
||||
const showLoadingMask = () => {
|
||||
if (loadingMaskRefs.value.status && !loadingInstance.value) {
|
||||
update({ ...loadingMaskRefs.value }) // 更新加载文本
|
||||
open() // 打开加载遮罩
|
||||
}
|
||||
}
|
||||
|
||||
// 关闭加载遮罩
|
||||
const closeLoadingMask = () => {
|
||||
if (loadingInstance.value) {
|
||||
close() // 关闭加载遮罩
|
||||
loadingInstance.value = null
|
||||
}
|
||||
}
|
||||
|
||||
// 显示响应消息
|
||||
const showResponseMessage = () => {
|
||||
if (!messageRef.value || !dataRef.value) return
|
||||
if (dataRef.value && typeof dataRef.value === 'object') {
|
||||
if ('status' in dataRef.value && 'message' in dataRef.value) {
|
||||
const { request } = useMessage() // 消息提示
|
||||
console.log(dataRef.value, '+++++++')
|
||||
const { status, message } = dataRef.value
|
||||
if (message) request({ status, message })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 处理请求错误
|
||||
const handleApiError = (err: AxiosError) => {
|
||||
const { handleError } = useError()
|
||||
if (typeof err === 'boolean') return
|
||||
aborted.value = (err as Error)?.name === 'AbortError' || false // 是否被中断
|
||||
// 检查是否为服务器错误
|
||||
if (err.status != 200 && err.status != 404 && err?.response) {
|
||||
const { message } = err.response?.data as { status: number; message: string }
|
||||
return handleError(new Error(message))
|
||||
} else {
|
||||
handleError(err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行请求
|
||||
* @param {string} url 请求地址
|
||||
* @param params 请求参数
|
||||
* @returns 响应数据
|
||||
*/
|
||||
const execute = async (url: string, params?: Z) => {
|
||||
// 避免空URL请求
|
||||
if (!url.trim()) return
|
||||
|
||||
try {
|
||||
// 重置状态
|
||||
errorRef.value = null
|
||||
aborted.value = false
|
||||
loadingRef.value = true
|
||||
|
||||
// 保留请求信息
|
||||
urlRef.value = url
|
||||
paramsRef.value = params || {}
|
||||
|
||||
// 是否显示提示框
|
||||
if (dialogRefs.value.status) {
|
||||
const { create } = useDialog()
|
||||
await create({
|
||||
type: 'info',
|
||||
...dialogRefs.value,
|
||||
})
|
||||
}
|
||||
|
||||
// 显示加载遮罩
|
||||
if (loadingMaskRefs.value.status) showLoadingMask()
|
||||
// 执行请求
|
||||
const res = await instance.post<T>(url, params as Record<string, unknown>)
|
||||
// 保存响应
|
||||
response.value = res
|
||||
// 处理响应数据
|
||||
if (res.data) dataRef.value = { ...defaultData.value, ...res.data }
|
||||
// 显示响应消息
|
||||
if (messageRef.value) showResponseMessage()
|
||||
return res.data
|
||||
} catch (err: unknown) {
|
||||
handleApiError(err as AxiosError)
|
||||
} finally {
|
||||
// 关闭加载状态
|
||||
loadingRef.value = false
|
||||
// 关闭加载遮罩
|
||||
if (loadingMaskRefs.value.text) closeLoadingMask()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置请求参数,并执行请求
|
||||
* @param params 请求参数
|
||||
*/
|
||||
const setParams = (params: Z) => {
|
||||
paramsRef.value = params
|
||||
return execute(urlRef.value, params)
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置请求地址,并执行请求
|
||||
* @param url 请求地址
|
||||
* @param params 请求参数
|
||||
*/
|
||||
const setUrl = (url: string, params: Z) => {
|
||||
urlRef.value = url
|
||||
paramsRef.value = params || {}
|
||||
return execute(url, paramsRef.value)
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消特定请求
|
||||
* @param url 请求地址
|
||||
*/
|
||||
const cancel = (url: string) => {
|
||||
aborted.value = true
|
||||
return cancelRequest(url)
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消所有请求
|
||||
*/
|
||||
const cancelAll = () => {
|
||||
aborted.value = true
|
||||
return removeAllAbortController()
|
||||
}
|
||||
|
||||
/**
|
||||
* 重放上一次请求
|
||||
*/
|
||||
const fetch = (params?: Z) => {
|
||||
if (!urlRef.value) return
|
||||
return execute(urlRef.value, params || paramsRef.value)
|
||||
}
|
||||
|
||||
const scope = effectScope()
|
||||
scope.run(() => {
|
||||
// 监听 loadingMask 变化
|
||||
watch(loadingMaskRefs, (newVal) => {
|
||||
if (newVal && loadingRef.value) {
|
||||
showLoadingMask()
|
||||
} else if (!newVal) {
|
||||
closeLoadingMask()
|
||||
}
|
||||
})
|
||||
onScopeDispose(() => {
|
||||
scope.stop()
|
||||
})
|
||||
})
|
||||
|
||||
// 封装响应式状态
|
||||
const state = {
|
||||
// 集成组件状态
|
||||
loadingMask: loadingMaskRefs,
|
||||
dialog: dialogRefs,
|
||||
message: messageRef,
|
||||
|
||||
// 响应式状态
|
||||
|
||||
loading: loadingRef,
|
||||
error: errorRef,
|
||||
response,
|
||||
data: dataRef,
|
||||
defaultData,
|
||||
statusCode,
|
||||
aborted,
|
||||
urlRef,
|
||||
paramsRef,
|
||||
}
|
||||
|
||||
// 封装方法
|
||||
const methods = {
|
||||
execute,
|
||||
setParams,
|
||||
setUrl,
|
||||
cancel,
|
||||
cancelAll,
|
||||
fetch,
|
||||
}
|
||||
|
||||
return <useAxiosReturn<T, Z>>{
|
||||
...state,
|
||||
...methods,
|
||||
}
|
||||
}
|
||||
|
||||
export { HttpClient, useAxios, type Middleware }
|
||||
Reference in New Issue
Block a user