HomeLease/composables/usePagination.js
2025-08-26 11:24:47 +08:00

214 lines
5.0 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)
if (!response || response.code !== 200) {
throw new Error(response?.message || '获取数据失败')
}
const { rows = [], total = 0 } = response
// 数据转换将API返回的用户数据转换为页面需要的格式
const transformedData = rows.map(user => ({
...user,
isExpanded: false, // 默认收起
// 将orders转换为devices格式
devices: user.orders
? user.orders.map(order => ({
type: order.typeName || '未知设备',
amount: order.amount || 0,
rentDate: formatDate(order.leaseTime),
period: order.suitName || '未知周期',
expiryDate: formatDate(order.expirationTime),
}))
: [],
}))
if (reset) {
list.value = transformedData
} else {
list.value.push(...transformedData)
}
// 更新分页信息
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}页,共${transformedData.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,
}
}