2025-08-25 18:06:33 +08:00
|
|
|
|
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 = {}) {
|
2025-08-26 09:11:00 +08:00
|
|
|
|
const { fetchData, defaultParams = {}, mode = 'loadMore', pageSize = 10 } = options
|
2025-08-25 18:06:33 +08:00
|
|
|
|
|
|
|
|
|
|
// 基础状态
|
|
|
|
|
|
const list = ref([])
|
|
|
|
|
|
const loading = ref(false)
|
|
|
|
|
|
const error = ref(null)
|
2025-08-26 09:11:00 +08:00
|
|
|
|
|
2025-08-25 18:06:33 +08:00
|
|
|
|
// 分页参数
|
|
|
|
|
|
const queryParams = ref({
|
|
|
|
|
|
pageNum: 1,
|
|
|
|
|
|
pageSize,
|
2025-08-26 09:11:00 +08:00
|
|
|
|
...defaultParams,
|
2025-08-25 18:06:33 +08:00
|
|
|
|
})
|
2025-08-26 09:11:00 +08:00
|
|
|
|
|
2025-08-25 18:06:33 +08:00
|
|
|
|
// 分页信息
|
|
|
|
|
|
const pagination = ref({
|
|
|
|
|
|
total: 0,
|
|
|
|
|
|
currentPage: 1,
|
|
|
|
|
|
pageSize,
|
2025-08-26 09:11:00 +08:00
|
|
|
|
totalPages: 0,
|
2025-08-25 18:06:33 +08:00
|
|
|
|
})
|
2025-08-26 09:11:00 +08:00
|
|
|
|
|
2025-08-25 18:06:33 +08:00
|
|
|
|
// 上拉加载相关
|
|
|
|
|
|
const noMore = ref(false)
|
2025-08-26 09:11:00 +08:00
|
|
|
|
|
2025-08-25 18:06:33 +08:00
|
|
|
|
// 计算属性
|
|
|
|
|
|
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)
|
2025-08-26 09:11:00 +08:00
|
|
|
|
|
2025-08-25 18:06:33 +08:00
|
|
|
|
/**
|
2025-08-26 10:57:33 +08:00
|
|
|
|
* 获取数据
|
|
|
|
|
|
* @param {boolean} reset - 是否重置列表
|
2025-08-25 18:06:33 +08:00
|
|
|
|
*/
|
2025-08-26 10:57:33 +08:00
|
|
|
|
const getList = async (reset = false) => {
|
2025-08-25 18:06:33 +08:00
|
|
|
|
if (loading.value) return
|
2025-08-26 09:11:00 +08:00
|
|
|
|
|
2025-08-26 10:57:33 +08:00
|
|
|
|
if (reset) {
|
|
|
|
|
|
list.value = []
|
|
|
|
|
|
queryParams.value.pageNum = 1
|
|
|
|
|
|
noMore.value = false
|
|
|
|
|
|
}
|
2025-08-26 09:11:00 +08:00
|
|
|
|
|
2025-08-26 10:57:33 +08:00
|
|
|
|
loading.value = true
|
|
|
|
|
|
error.value = null
|
2025-08-26 09:11:00 +08:00
|
|
|
|
|
2025-08-26 10:57:33 +08:00
|
|
|
|
try {
|
|
|
|
|
|
const response = await fetchData(queryParams.value)
|
2025-08-26 11:24:37 +08:00
|
|
|
|
|
2025-08-26 10:57:33 +08:00
|
|
|
|
if (!response || response.code !== 200) {
|
|
|
|
|
|
throw new Error(response?.message || '获取数据失败')
|
|
|
|
|
|
}
|
2025-08-26 09:11:00 +08:00
|
|
|
|
|
2025-08-26 10:57:33 +08:00
|
|
|
|
const { rows = [], total = 0 } = response
|
|
|
|
|
|
|
|
|
|
|
|
if (reset) {
|
2025-08-26 11:24:37 +08:00
|
|
|
|
list.value = rows
|
2025-08-26 10:57:33 +08:00
|
|
|
|
} else {
|
2025-08-26 11:24:37 +08:00
|
|
|
|
list.value.push(...rows)
|
2025-08-26 10:57:33 +08:00
|
|
|
|
}
|
2025-08-26 09:11:00 +08:00
|
|
|
|
|
2025-08-25 18:06:33 +08:00
|
|
|
|
// 更新分页信息
|
|
|
|
|
|
pagination.value = {
|
|
|
|
|
|
total,
|
|
|
|
|
|
currentPage: queryParams.value.pageNum,
|
|
|
|
|
|
pageSize,
|
2025-08-26 09:11:00 +08:00
|
|
|
|
totalPages: Math.ceil(total / pageSize),
|
2025-08-25 18:06:33 +08:00
|
|
|
|
}
|
2025-08-26 09:11:00 +08:00
|
|
|
|
|
2025-08-25 18:06:33 +08:00
|
|
|
|
// 检查是否还有更多数据
|
|
|
|
|
|
if (mode === 'loadMore') {
|
|
|
|
|
|
noMore.value = queryParams.value.pageNum * pageSize >= total
|
2025-08-26 11:24:37 +08:00
|
|
|
|
console.log(
|
|
|
|
|
|
`noMore状态: ${noMore.value}, 当前页: ${queryParams.value.pageNum}, 每页: ${pageSize}, 总数: ${total}`
|
|
|
|
|
|
)
|
2025-08-25 18:06:33 +08:00
|
|
|
|
}
|
2025-08-26 09:11:00 +08:00
|
|
|
|
|
2025-08-26 11:24:37 +08:00
|
|
|
|
console.log(`获取数据成功: 第${queryParams.value.pageNum}页,共${rows.length}条`)
|
2025-08-25 18:06:33 +08:00
|
|
|
|
} catch (err) {
|
|
|
|
|
|
console.error('获取数据失败:', err)
|
|
|
|
|
|
error.value = err
|
2025-08-26 09:11:00 +08:00
|
|
|
|
|
2025-08-25 18:06:33 +08:00
|
|
|
|
// 显示错误提示
|
|
|
|
|
|
uni.showToast({
|
|
|
|
|
|
title: '数据加载失败',
|
2025-08-26 09:11:00 +08:00
|
|
|
|
icon: 'none',
|
2025-08-25 18:06:33 +08:00
|
|
|
|
})
|
|
|
|
|
|
} finally {
|
|
|
|
|
|
loading.value = false
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-08-26 09:11:00 +08:00
|
|
|
|
|
2025-08-25 18:06:33 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 刷新数据
|
|
|
|
|
|
*/
|
|
|
|
|
|
const refresh = () => {
|
|
|
|
|
|
getList(true)
|
|
|
|
|
|
}
|
2025-08-26 09:11:00 +08:00
|
|
|
|
|
2025-08-25 18:06:33 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 加载下一页(上拉加载模式)
|
|
|
|
|
|
*/
|
|
|
|
|
|
const loadMore = () => {
|
|
|
|
|
|
if (!canLoadMore.value) return
|
2025-08-26 09:11:00 +08:00
|
|
|
|
|
2025-08-25 18:06:33 +08:00
|
|
|
|
queryParams.value.pageNum++
|
|
|
|
|
|
getList()
|
|
|
|
|
|
}
|
2025-08-26 09:11:00 +08:00
|
|
|
|
|
2025-08-25 18:06:33 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 跳转到指定页(分页器模式)
|
|
|
|
|
|
* @param {number} page - 目标页码
|
|
|
|
|
|
*/
|
2025-08-26 09:11:00 +08:00
|
|
|
|
const goToPage = page => {
|
2025-08-25 18:06:33 +08:00
|
|
|
|
if (page < 1 || page > pagination.value.totalPages || page === queryParams.value.pageNum) {
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
2025-08-26 09:11:00 +08:00
|
|
|
|
|
2025-08-25 18:06:33 +08:00
|
|
|
|
queryParams.value.pageNum = page
|
|
|
|
|
|
getList(true)
|
|
|
|
|
|
}
|
2025-08-26 09:11:00 +08:00
|
|
|
|
|
2025-08-25 18:06:33 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 重置分页状态
|
|
|
|
|
|
*/
|
|
|
|
|
|
const reset = () => {
|
|
|
|
|
|
list.value = []
|
|
|
|
|
|
loading.value = false
|
|
|
|
|
|
error.value = null
|
|
|
|
|
|
noMore.value = false
|
|
|
|
|
|
queryParams.value.pageNum = 1
|
|
|
|
|
|
pagination.value = {
|
|
|
|
|
|
total: 0,
|
|
|
|
|
|
currentPage: 1,
|
|
|
|
|
|
pageSize,
|
2025-08-26 09:11:00 +08:00
|
|
|
|
totalPages: 0,
|
2025-08-25 18:06:33 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-08-26 09:11:00 +08:00
|
|
|
|
|
2025-08-25 18:06:33 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 更新查询参数
|
|
|
|
|
|
* @param {Object} newParams - 新的查询参数
|
|
|
|
|
|
*/
|
2025-08-26 09:11:00 +08:00
|
|
|
|
const updateParams = newParams => {
|
2025-08-25 18:06:33 +08:00
|
|
|
|
queryParams.value = {
|
|
|
|
|
|
...queryParams.value,
|
|
|
|
|
|
...newParams,
|
2025-08-26 09:11:00 +08:00
|
|
|
|
pageNum: 1, // 重置页码
|
2025-08-25 18:06:33 +08:00
|
|
|
|
}
|
|
|
|
|
|
reset()
|
|
|
|
|
|
getList()
|
|
|
|
|
|
}
|
2025-08-26 09:11:00 +08:00
|
|
|
|
|
2025-08-26 10:57:33 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 格式化日期
|
|
|
|
|
|
* @param {string} dateString - 日期字符串
|
|
|
|
|
|
* @returns {string} 格式化后的日期
|
|
|
|
|
|
*/
|
2025-08-26 11:24:37 +08:00
|
|
|
|
const formatDate = dateString => {
|
2025-08-26 10:57:33 +08:00
|
|
|
|
if (!dateString) return '未知'
|
|
|
|
|
|
const date = new Date(dateString)
|
|
|
|
|
|
return `${date.getFullYear()}.${String(date.getMonth() + 1).padStart(2, '0')}.${String(date.getDate()).padStart(2, '0')}`
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-25 18:06:33 +08:00
|
|
|
|
return {
|
|
|
|
|
|
// 状态
|
|
|
|
|
|
list,
|
|
|
|
|
|
loading,
|
|
|
|
|
|
error,
|
|
|
|
|
|
noMore,
|
|
|
|
|
|
pagination,
|
|
|
|
|
|
queryParams,
|
2025-08-26 09:11:00 +08:00
|
|
|
|
|
2025-08-25 18:06:33 +08:00
|
|
|
|
// 计算属性
|
|
|
|
|
|
hasData,
|
|
|
|
|
|
isEmpty,
|
|
|
|
|
|
canLoadMore,
|
2025-08-26 09:11:00 +08:00
|
|
|
|
|
2025-08-25 18:06:33 +08:00
|
|
|
|
// 方法
|
|
|
|
|
|
getList,
|
|
|
|
|
|
refresh,
|
|
|
|
|
|
loadMore,
|
|
|
|
|
|
goToPage,
|
|
|
|
|
|
reset,
|
2025-08-26 09:11:00 +08:00
|
|
|
|
updateParams,
|
2025-08-25 18:06:33 +08:00
|
|
|
|
}
|
2025-08-26 09:11:00 +08:00
|
|
|
|
}
|