import { ref, reactive } from 'vue' import tool from '@/common/utils/tool.js' /** * 通用请求Hook * @param {Function} apiFunction API函数 * @param {Object} options 配置选项 * @returns {Object} 请求相关状态和方法 */ export function useRequest(apiFunction, options = {}) { const { manual = false, // 是否手动触发 defaultParams = [], // 默认参数 onSuccess = () => {}, // 成功回调 onError = () => {}, // 失败回调 loadingDelay = 0, // loading延迟时间 } = options // 状态 const data = ref(null) const loading = ref(false) const error = ref(null) const params = ref([]) // loading延迟定时器 let loadingTimer = null /** * 执行请求 * @param {...any} args 请求参数 */ async function run(...args) { // 清除之前的loading延迟定时器 if (loadingTimer) { clearTimeout(loadingTimer) loadingTimer = null } // 设置参数 params.value = args // 如果有loading延迟,先启动定时器 if (loadingDelay > 0) { loadingTimer = setTimeout(() => { loading.value = true }, loadingDelay) } else { loading.value = true } try { const result = await apiFunction(...args) // 清除loading延迟定时器 if (loadingTimer) { clearTimeout(loadingTimer) loadingTimer = null } data.value = result error.value = null onSuccess(result, args) return result } catch (err) { // 清除loading延迟定时器 if (loadingTimer) { clearTimeout(loadingTimer) loadingTimer = null } error.value = err data.value = null console.error('请求失败:', err) onError(err, args) throw err } finally { loading.value = false } } /** * 取消请求 */ function cancel() { if (loadingTimer) { clearTimeout(loadingTimer) loadingTimer = null } loading.value = false } /** * 重新执行请求 */ function refresh() { return run(...params.value) } // 如果不是手动触发,立即执行 if (!manual) { // 使用nextTick确保在组件挂载后执行 Promise.resolve().then(() => { run(...defaultParams) }) } return { data, loading, error, params, run, cancel, refresh, } }