公告列表采用分页组件

This commit is contained in:
WindowBird 2025-08-26 09:25:40 +08:00
parent 5e09db3d16
commit de2ac5d37c
3 changed files with 91 additions and 119 deletions

View File

@ -6,11 +6,11 @@
<view class="loading-spinner"></view>
<text class="loading-text">{{ loadingText }}</text>
</view>
<view v-else-if="noMore && list.length > 0" class="no-more-state">
<text class="no-more-text">{{ noMoreText }}</text>
</view>
<view v-else-if="list.length === 0 && !loading" class="empty-state">
<view class="empty-icon">{{ emptyIcon }}</view>
<text class="empty-text">{{ emptyText }}</text>
@ -24,19 +24,19 @@
{{ total }} {{ currentPage }} / {{ totalPages }}
</text>
</view>
<view class="pager-controls">
<button
class="pager-btn prev-btn"
<button
class="pager-btn prev-btn"
:disabled="currentPage <= 1"
@click="handlePageChange(currentPage - 1)"
>
上一页
</button>
<view class="page-numbers">
<button
v-for="page in visiblePages"
<button
v-for="page in visiblePages"
:key="page"
:class="['page-btn', { active: page === currentPage }]"
@click="handlePageChange(page)"
@ -44,9 +44,9 @@
{{ page }}
</button>
</view>
<button
class="pager-btn next-btn"
<button
class="pager-btn next-btn"
:disabled="currentPage >= totalPages"
@click="handlePageChange(currentPage + 1)"
>
@ -65,114 +65,114 @@ export default {
mode: {
type: String,
default: 'loadMore',
validator: value => ['loadMore', 'pager'].includes(value)
validator: value => ['loadMore', 'pager'].includes(value),
},
//
list: {
type: Array,
default: () => []
default: () => [],
},
//
total: {
type: Number,
default: 0
default: 0,
},
//
currentPage: {
type: Number,
default: 1
default: 1,
},
//
pageSize: {
type: Number,
default: 10
default: 10,
},
//
loading: {
type: Boolean,
default: false
default: false,
},
//
noMore: {
type: Boolean,
default: false
default: false,
},
//
loadingText: {
type: String,
default: '正在加载...'
default: '正在加载...',
},
noMoreText: {
type: String,
default: '没有更多数据了'
default: '没有更多数据了',
},
emptyText: {
type: String,
default: '暂无数据'
default: '暂无数据',
},
emptyIcon: {
type: String,
default: '📋'
default: '📋',
},
//
visiblePageCount: {
type: Number,
default: 5
}
default: 5,
},
},
computed: {
//
totalPages() {
return Math.ceil(this.total / this.pageSize)
},
//
visiblePages() {
const pages = []
const half = Math.floor(this.visiblePageCount / 2)
let start = Math.max(1, this.currentPage - half)
let end = Math.min(this.totalPages, start + this.visiblePageCount - 1)
//
if (end - start + 1 < this.visiblePageCount) {
start = Math.max(1, end - this.visiblePageCount + 1)
}
for (let i = start; i <= end; i++) {
pages.push(i)
}
return pages
}
},
},
methods: {
//
handlePageChange(page) {
if (page < 1 || page > this.totalPages || page === this.currentPage) {
return
}
this.$emit('page-change', page)
},
//
reset() {
this.$emit('reset')
}
}
},
},
}
</script>
@ -192,7 +192,7 @@ export default {
align-items: center;
justify-content: center;
padding: 20rpx 0;
.loading-spinner {
width: 40rpx;
height: 40rpx;
@ -202,7 +202,7 @@ export default {
animation: spin 1s linear infinite;
margin-right: 20rpx;
}
.loading-text {
font-size: 28rpx;
color: #666;
@ -211,7 +211,7 @@ export default {
.no-more-state {
padding: 20rpx 0;
.no-more-text {
font-size: 24rpx;
color: #999;
@ -220,12 +220,12 @@ export default {
.empty-state {
padding: 40rpx 0;
.empty-icon {
font-size: 80rpx;
margin-bottom: 20rpx;
}
.empty-text {
font-size: 28rpx;
color: #999;
@ -242,7 +242,7 @@ export default {
.pager-info {
text-align: center;
margin-bottom: 20rpx;
.pager-text {
font-size: 24rpx;
color: #666;
@ -264,13 +264,13 @@ export default {
background: #fff;
color: #333;
font-size: 26rpx;
&:disabled {
color: #ccc;
background: #f5f5f5;
border-color: #d9d9d9;
}
&:not(:disabled):active {
background: #f0f0f0;
}
@ -289,20 +289,24 @@ export default {
background: #fff;
color: #333;
font-size: 26rpx;
&.active {
background: #1890ff;
color: #fff;
border-color: #1890ff;
}
&:not(.active):active {
background: #f0f0f0;
}
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
</style>
</style>

View File

@ -4,61 +4,33 @@
<uni-card :extra="item.createTime" :title="item.title" @click="detail(item)"></uni-card>
</view>
<!-- 加载更多状态 -->
<view v-if="noData && list.length > 0" class="load-more">
<text class="no-more-text">没有更多数据了</text>
</view>
<!-- 分页组件 -->
<pagination
:current-page="pagination.currentPage"
:list="list"
:loading="loading"
:mode="'loadMore'"
:no-more="noMore"
:page-size="pagination.pageSize"
:total="pagination.total"
@page-change="handlePageChange"
/>
</view>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import { onMounted } from 'vue'
import { getArticleList } from '@/api/article/article.js'
import { onUnload, onReachBottom } from '@dcloudio/uni-app'
import { onReachBottom } from '@dcloudio/uni-app'
import { usePagination } from '@/composables/usePagination.js'
const list = ref([])
const noData = ref(false)
const loading = ref(false)
//data
const queryParams = {
pageNum: 1,
pageSize: 6,
}
//
const getList = async () => {
if (loading.value) return
try {
loading.value = true
let res = await getArticleList(queryParams)
// res.data
const newData = res?.rows || []
//
if (queryParams.pageNum === 1) {
list.value = newData
} else {
list.value = [...list.value, ...newData]
}
if (queryParams.pageNum * queryParams.pageSize >= res.total) {
noData.value = true
}
console.log('订单列表:', list.value)
} catch (error) {
console.error('获取订单列表失败:', error)
uni.showToast({
title: '获取订单列表失败',
icon: 'none',
})
} finally {
loading.value = false
}
}
// 使
const { list, loading, noMore, pagination, getList, loadMore } = usePagination({
fetchData: getArticleList,
defaultParams: {},
mode: 'loadMore',
pageSize: 9,
})
const detail = item => {
uni.navigateTo({
@ -71,18 +43,15 @@ onMounted(() => {
getList()
})
onUnload(() => {
//
list.value = []
noData.value = false
loading.value = false
//
onReachBottom(() => {
loadMore()
})
onReachBottom(() => {
if (noData.value || loading.value) return
queryParams.pageNum++
getList()
})
//
const handlePageChange = page => {
console.log('页码变化:', page)
}
</script>
<style lang="scss" scoped>

View File

@ -73,7 +73,6 @@ import { onMounted } from 'vue'
import { onReachBottom } from '@dcloudio/uni-app'
import { usePagination } from '@/composables/usePagination.js'
import { getMyOrder } from '@/api/order/myOrder.js'
import Pagination from '@/components/pagination/pagination.vue'
// 使
const { list, loading, noMore, pagination, getList, loadMore } = usePagination({