From cf8af5a1af226c2998a8cfe54116288a0ef515c2 Mon Sep 17 00:00:00 2001 From: WindowBird <13870814+windows-bird@user.noreply.gitee.com> Date: Sat, 8 Nov 2025 13:36:04 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E5=AE=A2=E6=88=B7=E7=AE=A1?= =?UTF-8?q?=E7=90=86=E5=AE=A2=E6=88=B7=E5=88=97=E8=A1=A8=E4=B8=8B=E6=8B=89?= =?UTF-8?q?=E5=88=B7=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- common/api/customer.js | 11 ++ components/CustomerManagement.vue | 147 +++++++++++----------- composables/usePagination.js | 201 ++++++++++++++++++++++++++++++ pages/index/index.vue | 15 ++- 4 files changed, 299 insertions(+), 75 deletions(-) create mode 100644 composables/usePagination.js diff --git a/common/api/customer.js b/common/api/customer.js index 73256db..761629f 100644 --- a/common/api/customer.js +++ b/common/api/customer.js @@ -5,6 +5,8 @@ /** * 获取客户列表 * @param {Object} params 请求参数(可选) + * @param {number} params.pageNum 页码(从1开始) + * @param {number} params.pageSize 每页数量 * @param {string[]} params.statusList 客户状态列表:["1"] 正在跟进, ["2"] 待跟进 * @param {string} params.excludeld 排除id * @param {string[]} params.ids id列表 @@ -22,6 +24,15 @@ export const getCustomerList = (params = {}) => { const queryParams = []; + // 处理分页参数 + if (params.pageNum !== undefined && params.pageNum !== null) { + queryParams.push(`pageNum=${encodeURIComponent(params.pageNum)}`); + } + + if (params.pageSize !== undefined && params.pageSize !== null) { + queryParams.push(`pageSize=${encodeURIComponent(params.pageSize)}`); + } + // 处理数组参数 if (params.statusList && Array.isArray(params.statusList) && params.statusList.length > 0) { params.statusList.forEach(status => { diff --git a/components/CustomerManagement.vue b/components/CustomerManagement.vue index 7072d3d..c501460 100644 --- a/components/CustomerManagement.vue +++ b/components/CustomerManagement.vue @@ -34,15 +34,14 @@ - @@ -106,16 +105,23 @@ - + 暂无客户数据 - + 加载中... + + + + 加载中... + 没有更多数据了 + 上拉加载更多 - + + @@ -123,43 +129,32 @@ diff --git a/composables/usePagination.js b/composables/usePagination.js new file mode 100644 index 0000000..9a6e099 --- /dev/null +++ b/composables/usePagination.js @@ -0,0 +1,201 @@ +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, + } +} diff --git a/pages/index/index.vue b/pages/index/index.vue index 12f578e..d42d2c9 100644 --- a/pages/index/index.vue +++ b/pages/index/index.vue @@ -7,7 +7,7 @@ - +