OfficeSystem/composables/usePagination.js
2025-11-08 13:36:04 +08:00

202 lines
4.5 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { ref, computed } from 'vue'
/**
* 分页管理组合式函数
* @param {Object} options - 配置选项
* @param {Function} options.fetchData - 获取数据的API函数
* @param {Object} options.defaultParams - 默认查询参数
* @param {string} options.mode - 分页模式:'loadMore' 或 'pager'
* @param {number} options.pageSize - 每页数量
* @returns {Object} 分页相关的状态和方法
*/
export function usePagination(options = {}) {
const { fetchData, defaultParams = {}, mode = 'loadMore', pageSize = 10 } = options
// 基础状态
const list = ref([])
const loading = ref(false)
const error = ref(null)
// 分页参数
const queryParams = ref({
pageNum: 1,
pageSize,
...defaultParams,
})
// 分页信息
const pagination = ref({
total: 0,
currentPage: 1,
pageSize,
totalPages: 0,
})
// 上拉加载相关
const noMore = ref(false)
// 计算属性
const hasData = computed(() => list.value.length > 0)
const isEmpty = computed(() => !loading.value && list.value.length === 0)
const canLoadMore = computed(() => mode === 'loadMore' && !noMore.value && !loading.value)
/**
* 获取数据
* @param {boolean} reset - 是否重置列表
*/
const getList = async (reset = false) => {
if (loading.value) return
if (reset) {
list.value = []
queryParams.value.pageNum = 1
noMore.value = false
}
loading.value = true
error.value = null
try {
const response = await fetchData(queryParams.value)
// 响应拦截器已经处理了错误情况如果请求成功返回response 就是数据对象
// 不再包含 code 和 msg 字段(已被拦截器过滤)
if (!response) {
throw new Error('获取数据失败:响应为空')
}
const { rows = [], total = 0 } = response
if (reset) {
list.value = rows
} else {
list.value.push(...rows)
}
// 更新分页信息
pagination.value = {
total,
currentPage: queryParams.value.pageNum,
pageSize,
totalPages: Math.ceil(total / pageSize),
}
// 检查是否还有更多数据
if (mode === 'loadMore') {
noMore.value = queryParams.value.pageNum * pageSize >= total
console.log(
`noMore状态: ${noMore.value}, 当前页: ${queryParams.value.pageNum}, 每页: ${pageSize}, 总数: ${total}`
)
}
console.log(`获取数据成功: 第${queryParams.value.pageNum}页,共${rows.length}`)
} catch (err) {
console.error('获取数据失败:', err)
error.value = err
// 显示错误提示
uni.showToast({
title: '数据加载失败',
icon: 'none',
})
} finally {
loading.value = false
}
}
/**
* 刷新数据
*/
const refresh = () => {
getList(true)
}
/**
* 加载下一页(上拉加载模式)
*/
const loadMore = () => {
if (!canLoadMore.value) return
queryParams.value.pageNum++
getList()
}
/**
* 跳转到指定页(分页器模式)
* @param {number} page - 目标页码
*/
const goToPage = page => {
if (page < 1 || page > pagination.value.totalPages || page === queryParams.value.pageNum) {
return
}
queryParams.value.pageNum = page
getList(true)
}
/**
* 重置分页状态
*/
const reset = () => {
list.value = []
loading.value = false
error.value = null
noMore.value = false
queryParams.value.pageNum = 1
pagination.value = {
total: 0,
currentPage: 1,
pageSize,
totalPages: 0,
}
}
/**
* 更新查询参数
* @param {Object} newParams - 新的查询参数
*/
const updateParams = newParams => {
queryParams.value = {
...queryParams.value,
...newParams,
pageNum: 1, // 重置页码
}
reset()
getList()
}
/**
* 格式化日期
* @param {string} dateString - 日期字符串
* @returns {string} 格式化后的日期
*/
const formatDate = dateString => {
if (!dateString) return '未知'
const date = new Date(dateString)
return `${date.getFullYear()}.${String(date.getMonth() + 1).padStart(2, '0')}.${String(date.getDate()).padStart(2, '0')}`
}
return {
// 状态
list,
loading,
error,
noMore,
pagination,
queryParams,
// 计算属性
hasData,
isEmpty,
canLoadMore,
// 方法
getList,
refresh,
loadMore,
goToPage,
reset,
updateParams,
}
}