You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

207 lines
4.4 KiB

<template>
<div class="pagination flex gap10">
<!-- 首页按钮 -->
<GuipButton size="form" v-if="showFirstPage" @click="goToFirstPage" :disabled="currentPage === 1">
首页
</GuipButton>
<!-- 上一页按钮 -->
<GuipButton size="form" v-if="showPrevPage" @click="goToPrevPage" :disabled="currentPage === 1">
上一页
</GuipButton>
<!-- 当前页码 -->
<span v-if="showCurrentPage">第{{ currentPage }}页</span>
<!-- 下一页按钮 -->
<GuipButton size="form" v-if="showNextPage" @click="goToNextPage" :disabled="!hasNextPage">
下一页
</GuipButton>
<!-- 尾页按钮 -->
<GuipButton size="form" v-if="showLastPage" @click="goToLastPage">
尾页
</GuipButton>
<!-- 跳转输入 -->
<div class="page-jump flex gap10" v-if="showJump">
<input type="number" v-model.number="jumpPage" min="1" :max="totalPages">
<GuipButton size="form" @click="handleJump">跳转</GuipButton>
</div>
<!-- 总记录数 -->
<span v-if="showTotalRecords" class="total-records">
{{ totalRecords }}条记录
</span>
</div>
</template>
<script>
import GuipButton from '@/components/GuipButton.vue';
export default {
name: 'Pagination',
components: { GuipButton },
props: {
// 当前页码
currentPage: {
type: Number,
default: 1
},
// 是否有下一页
hasNextPage: {
type: Boolean,
default: false
},
// 总记录数
totalRecords: {
type: [Number, String],
default: 0
},
// 每页条数
pageSize: {
type: Number,
default: 10
},
// 是否正在加载
isLoading: {
type: Boolean,
default: false
}
},
data() {
return {
jumpPage: this.currentPage,
endPage: false
}
},
computed: {
// 总页数
totalPages() {
return Math.ceil(this.totalRecords / this.pageSize)
},
// 是否显示首页按钮
showFirstPage() {
return this.currentPage > 2;
},
// 是否显示上一页按钮
showPrevPage() {
return this.currentPage > 1 || this.endPage
},
// 是否显示当前页码
showCurrentPage() {
return true
},
// 是否显示下一页按钮
showNextPage() {
return this.hasNextPage && !this.endPage
},
// 是否显示尾页按钮
showLastPage() {
return !this.endPage
},
// 是否显示跳转
showJump() {
return true
},
// 是否显示总记录数
showTotalRecords() {
return Number(this.totalRecords) > 0
}
},
watch: {
currentPage(newVal) {
this.jumpPage = newVal
}
},
methods: {
// 跳转到首页
goToFirstPage() {
if (this.currentPage === 1 || this.isLoading) return
this.endPage = false
this.$emit('page-change', {
page: 1,
endPage: false,
direction: 'first'
})
},
// 跳转到上一页
goToPrevPage() {
if (this.currentPage <= 1 || this.isLoading) return
this.endPage = false
this.$emit('page-change', {
page: this.currentPage - 1,
endPage: false,
direction: 'prev'
})
},
// 跳转到下一页
goToNextPage() {
if (!this.hasNextPage || this.isLoading) return
this.endPage = false
this.$emit('page-change', {
page: this.currentPage + 1,
endPage: false,
direction: 'next'
})
},
// 跳转到尾页
goToLastPage() {
if (this.endPage || this.isLoading) return
this.endPage = true
this.$emit('page-change', {
page: this.totalPages,
endPage: true,
direction: 'last'
})
},
// 处理跳转
handleJump() {
let page = parseInt(this.jumpPage)
if (isNaN(page)) page = 1
// 限制最大页数
if (page > this.totalPages) {
page = this.totalPages
this.jumpPage = page
}
if (page === this.currentPage || this.isLoading) return
this.endPage = false
this.$emit('page-change', {
page,
endPage: false,
direction: 'jump'
})
}
}
}
</script>
<style scoped>
.pagination {
display: flex;
align-items: center;
justify-content: flex-end;
margin: 20px 0;
gap: 10px;
}
.page-jump input {
width: 50px;
padding: 5px;
border: 1px solid #ddd;
border-radius: 3px;
text-align: center;
}
.total-records {
margin-left: 10px;
color: #666;
}
</style>