Luxx/dashboard/src/utils/useApi.js

172 lines
3.4 KiB
JavaScript

/**
* API 请求组合式函数
* 提供统一的错误处理和加载状态管理
*/
import { ref } from 'vue'
export function useApi() {
const loading = ref(false)
const error = ref(null)
/**
* 执行 API 请求
* @param {Function} apiFn - API 函数
* @param {Object} options - 配置选项
* @returns {Promise<Object>} 响应数据
*/
const request = async (apiFn, options = {}) => {
const { showLoading = true, errorMessage = '请求失败' } = options
loading.value = true
error.value = null
try {
const response = await apiFn()
if (response.success) {
return response.data
} else {
throw new Error(response.message || errorMessage)
}
} catch (err) {
error.value = err.message || errorMessage
throw err
} finally {
loading.value = false
}
}
/**
* 重置状态
*/
const reset = () => {
loading.value = false
error.value = null
}
return {
loading,
error,
request,
reset
}
}
/**
* 分页组合式函数
*/
export function usePagination(initialPage = 1, initialPageSize = 20) {
const page = ref(initialPage)
const pageSize = ref(initialPageSize)
const total = ref(0)
const totalPages = () => Math.ceil(total.value / pageSize.value)
const nextPage = () => {
if (page.value < totalPages()) {
page.value++
}
}
const prevPage = () => {
if (page.value > 1) {
page.value--
}
}
const goToPage = (p) => {
if (p >= 1 && p <= totalPages()) {
page.value = p
}
}
const resetPagination = () => {
page.value = initialPage
total.value = 0
}
return {
page,
pageSize,
total,
totalPages,
nextPage,
prevPage,
goToPage,
resetPagination
}
}
/**
* 表单组合式函数
*/
export function useForm(initialData = {}) {
const formData = ref({ ...initialData })
const errors = ref({})
const submitting = ref(false)
const updateField = (field, value) => {
formData.value[field] = value
// 清除字段错误
if (errors.value[field]) {
delete errors.value[field]
}
}
const setFieldError = (field, message) => {
errors.value[field] = message
}
const setErrors = (errorObj) => {
errors.value = errorObj
}
const clearErrors = () => {
errors.value = {}
}
const resetForm = (newData = {}) => {
formData.value = { ...initialData, ...newData }
errors.value = {}
}
const validate = (rules) => {
const newErrors = {}
for (const [field, rule] of Object.entries(rules)) {
const value = formData.value[field]
if (rule.required && !value) {
newErrors[field] = rule.message || `${field}不能为空`
}
if (rule.minLength && value && value.length < rule.minLength) {
newErrors[field] = rule.message || `${field}长度不能少于${rule.minLength}`
}
if (rule.maxLength && value && value.length > rule.maxLength) {
newErrors[field] = rule.message || `${field}长度不能超过${rule.maxLength}`
}
if (rule.pattern && value && !rule.pattern.test(value)) {
newErrors[field] = rule.message || `${field}格式不正确`
}
}
setErrors(newErrors)
return Object.keys(newErrors).length === 0
}
return {
formData,
errors,
submitting,
updateField,
setFieldError,
setErrors,
clearErrors,
resetForm,
validate
}
}