172 lines
3.4 KiB
JavaScript
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
|
|
}
|
|
}
|