126 lines
2.9 KiB
TypeScript
126 lines
2.9 KiB
TypeScript
|
|
import { ref, computed } from 'vue'
|
||
|
|
import { ElMessage } from 'element-plus'
|
||
|
|
|
||
|
|
/**
|
||
|
|
* API 请求封装
|
||
|
|
* @param apiFunc - API 请求函数
|
||
|
|
* @param options - 配置选项
|
||
|
|
*/
|
||
|
|
export function useApi<T = any>(
|
||
|
|
apiFunc: (...args: any[]) => Promise<Response>,
|
||
|
|
options: {
|
||
|
|
showError?: boolean
|
||
|
|
showSuccess?: boolean
|
||
|
|
successMessage?: string
|
||
|
|
errorMessage?: string
|
||
|
|
} = {}
|
||
|
|
) {
|
||
|
|
const { showError = true, showSuccess = false, successMessage, errorMessage } = options
|
||
|
|
|
||
|
|
const loading = ref(false)
|
||
|
|
const data = ref<T | null>(null)
|
||
|
|
const error = ref<Error | null>(null)
|
||
|
|
|
||
|
|
const execute = async (...args: any[]) => {
|
||
|
|
loading.value = true
|
||
|
|
error.value = null
|
||
|
|
|
||
|
|
try {
|
||
|
|
const response = await apiFunc(...args)
|
||
|
|
|
||
|
|
if (!response.ok) {
|
||
|
|
throw new Error(`HTTP ${response.status}`)
|
||
|
|
}
|
||
|
|
|
||
|
|
const result = await response.json()
|
||
|
|
|
||
|
|
if (result.success || response.ok) {
|
||
|
|
data.value = result
|
||
|
|
|
||
|
|
if (showSuccess) {
|
||
|
|
ElMessage.success(successMessage || result.message || '操作成功')
|
||
|
|
}
|
||
|
|
|
||
|
|
return result
|
||
|
|
} else {
|
||
|
|
if (showError) {
|
||
|
|
ElMessage.error(errorMessage || result.message || '操作失败')
|
||
|
|
}
|
||
|
|
throw new Error(result.message || '操作失败')
|
||
|
|
}
|
||
|
|
} catch (err: any) {
|
||
|
|
error.value = err
|
||
|
|
|
||
|
|
if (showError) {
|
||
|
|
ElMessage.error(errorMessage || err.message || '请求失败')
|
||
|
|
}
|
||
|
|
|
||
|
|
throw err
|
||
|
|
} finally {
|
||
|
|
loading.value = false
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return {
|
||
|
|
loading: computed(() => loading.value),
|
||
|
|
data: computed(() => data.value),
|
||
|
|
error: computed(() => error.value),
|
||
|
|
execute,
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 简单的 CRUD 操作封装
|
||
|
|
*/
|
||
|
|
export function useCrud<T = any>(baseUrl: string) {
|
||
|
|
const API_BASE = baseUrl
|
||
|
|
|
||
|
|
const fetchList = async (params?: any) => {
|
||
|
|
const query = params ? '?' + new URLSearchParams(params).toString() : ''
|
||
|
|
const response = await fetch(`${API_BASE}${query}`)
|
||
|
|
const result = await response.json()
|
||
|
|
return result
|
||
|
|
}
|
||
|
|
|
||
|
|
const fetchById = async (id: string) => {
|
||
|
|
const response = await fetch(`${API_BASE}/${id}`)
|
||
|
|
const result = await response.json()
|
||
|
|
return result
|
||
|
|
}
|
||
|
|
|
||
|
|
const create = async (data: Partial<T>) => {
|
||
|
|
const response = await fetch(API_BASE, {
|
||
|
|
method: 'POST',
|
||
|
|
headers: { 'Content-Type': 'application/json' },
|
||
|
|
body: JSON.stringify(data),
|
||
|
|
})
|
||
|
|
const result = await response.json()
|
||
|
|
return result
|
||
|
|
}
|
||
|
|
|
||
|
|
const update = async (id: string, data: Partial<T>) => {
|
||
|
|
const response = await fetch(`${API_BASE}/${id}`, {
|
||
|
|
method: 'PUT',
|
||
|
|
headers: { 'Content-Type': 'application/json' },
|
||
|
|
body: JSON.stringify(data),
|
||
|
|
})
|
||
|
|
const result = await response.json()
|
||
|
|
return result
|
||
|
|
}
|
||
|
|
|
||
|
|
const remove = async (id: string) => {
|
||
|
|
const response = await fetch(`${API_BASE}/${id}`, {
|
||
|
|
method: 'DELETE',
|
||
|
|
})
|
||
|
|
return response.ok
|
||
|
|
}
|
||
|
|
|
||
|
|
return {
|
||
|
|
fetchList,
|
||
|
|
fetchById,
|
||
|
|
create,
|
||
|
|
update,
|
||
|
|
remove,
|
||
|
|
}
|
||
|
|
}
|