import { ref, reactive, watch, isRef, nextTick } from 'vue' export function usePagination( requestFn, transformFn, options = {} ) { const list = ref([]) const loading = ref(false) const error = ref(false) const finished = ref(false) const firstLoading = ref(true) const empty = ref(false) const { pageSize = 10, search = {}, autoWatchSearch = false, debounceTime = 300, autoFetch = false, // 字段映射 dataKey = 'rows', totalKey = 'total', // 分页字段名映射 pageField = 'current', sizeField = 'pageSize', onBeforeRequest, onAfterRequest } = options const pageState = reactive({ page: 1, pageSize: isRef(pageSize) ? pageSize.value : pageSize, total: 0, maxPage: 1, search: isRef(search) ? search.value : search }) let debounceTimer = null const fetchData = async (type = 'refresh') => { if (loading.value) return Promise.resolve() console.log(type) loading.value = true error.value = false if (typeof onBeforeRequest === 'function') { try { onBeforeRequest(type, pageState) } catch (err) { console.warn('onBeforeRequest 执行异常:', err) } } if (type === 'refresh') { pageState.page = 1 finished.value = false if (list.value.length === 0) { firstLoading.value = true } } else if (type === 'loadMore') { if (pageState.page >= pageState.maxPage) { loading.value = false finished.value = true return Promise.resolve('no more') } pageState.page += 1 } const params = { ...pageState.search, [pageField]: pageState.page, [sizeField]: pageState.pageSize, } try { const res = await requestFn(params) const rawData = res[dataKey] const total = res[totalKey] || 99999999 console.log(total, rawData) const data = typeof transformFn === 'function' ? transformFn(rawData) : rawData if (type === 'refresh') { list.value = data } else { list.value.push(...data) } pageState.total = total pageState.maxPage = Math.ceil(total / pageState.pageSize) finished.value = list.value.length >= total empty.value = list.value.length === 0 } catch (err) { console.error('分页请求失败:', err) error.value = true } finally { loading.value = false firstLoading.value = false if (typeof onAfterRequest === 'function') { try { onAfterRequest(type, pageState, { error: error.value }) } catch (err) { console.warn('onAfterRequest 执行异常:', err) } } } } const refresh = () => fetchData('refresh') const loadMore = () => fetchData('loadMore') const resetPagination = () => { list.value = [] pageState.page = 1 pageState.total = 0 pageState.maxPage = 1 finished.value = false error.value = false firstLoading.value = true empty.value = false } if (autoWatchSearch && isRef(search)) { watch(search, (newVal) => { pageState.search = newVal clearTimeout(debounceTimer) debounceTimer = setTimeout(() => { refresh() }, debounceTime) }, { deep: true }) } watch(pageSize, (newVal) => { pageState.pageSize = newVal }, { deep: true }) if (autoFetch) { nextTick(() => { refresh() }) } return { list, loading, error, finished, firstLoading, empty, pageState, refresh, loadMore, resetPagination } }