This commit is contained in:
2025-08-12 15:04:01 +08:00
parent df3f5f5269
commit 6708fb8eeb
544 changed files with 75169 additions and 17 deletions
@@ -0,0 +1,111 @@
export default {
props: {
// 当前页码
// #ifdef VUE3
modelValue: {
type: Number,
default: ()=> uni.$u.props.pagination.modelValue
},
// #endif
// v-model 的别名
value: {
type: Number,
default: ()=> uni.$u.props.pagination.modelValue
},
// 总记录数,用于计算总页数
total: {
type: Number,
default: ()=> uni.$u.props.pagination.total
},
// 每页显示的记录数
pageSize: {
type: Number,
default: ()=> uni.$u.props.pagination.pageSize
},
// 显示的页码按钮数量
pagerCount: {
type: Number,
default: ()=> uni.$u.props.pagination.pagerCount
},
// 是否禁用分页
disabled: {
type: Boolean,
default: ()=> uni.$u.props.pagination.disabled
},
// 是否显示省略号
forceEllipses: {
type: Boolean,
default: ()=> uni.$u.props.pagination.forceEllipses
},
// 是否为简单分页
simple: {
type: Boolean,
default: ()=> uni.$u.props.pagination.simple
},
// 是否展示上一页按钮
showPrevButton: {
type: Boolean,
default: ()=> uni.$u.props.pagination.showPrevButton
},
// 是否展示下一页按钮
showNextButton: {
type: Boolean,
default: ()=> uni.$u.props.pagination.showNextButton
},
// 上一页按钮文字
prevText: {
type: String,
default: ()=> uni.$u.$t('uPagination.prevText')
},
// 下一页按钮文字
nextText: {
type: String,
default: ()=> uni.$u.$t('uPagination.nextText')
},
// 背景色
bgColor: {
type: [String, Boolean],
default: ()=> uni.$u.props.pagination.bgColor
},
// 文本色
color: {
type: String,
default: ()=> uni.$u.props.pagination.color
},
// 激活背景色
activeBgColor: {
type: [String, Boolean],
default: ()=> uni.$u.props.pagination.activeBgColor
},
// 激活文本色
activeColor: {
type: [String, Boolean],
default: ()=> uni.$u.props.pagination.activeColor
},
// 字体尺寸
fontSize: {
type: String,
default: ()=> uni.$u.props.pagination.fontSize
},
// 圆角
round: {
type: String,
default: ()=> uni.$u.props.pagination.round
},
// 描边色
borderColor: {
type: [String, Boolean],
default: ()=> uni.$u.props.pagination.borderColor
},
// 每项宽度
itemWidth: {
type: String,
default: ()=> uni.$u.props.pagination.itemWidth
},
// 每项高度
itemHeight: {
type: String,
default: ()=> uni.$u.props.pagination.itemHeight
}
}
}
@@ -0,0 +1,392 @@
<template>
<view
class="u-pagination"
:class="[disabled && 'u-pagination--disabled', simple && 'u-pagination--simple']"
:style="[$u.addStyle(customStyle)]"
>
<!-- 上一页按钮 -->
<view
v-if="showPrevButton"
class="u-pagination__prev"
:class="[{ 'u-pagination__item--disabled': isFirstPage || disabled }]"
:style="[itemStyle()]"
@click="prevPage"
>
<slot name="prev" :disabled="isFirstPage || disabled">
<text :style="[textStyle]">{{ prevText }}</text>
</slot>
</view>
<!-- 简单模式 -->
<text v-if="simple" class="u-pagination__simple" :style="[textStyle]">
{{ innerValue }} / {{ totalPages }}
</text>
<!-- 完整模式页码列表 -->
<template v-if="!simple">
<view
v-for="(page, index) in pageItems"
:key="index"
class="u-pagination__item"
:class="[{
'u-pagination__item--active': page.isActive,
'u-pagination__item--disabled': disabled,
'u-pagination__item--ellipsis': page.type == 'ellipsis'
}]"
:style="[page.isActive ? activeItemStyle(true) : itemStyle(true)]"
@click="handlePageClick(page)"
>
<slot name="page" :label="page.label" :active="page.isActive">
<text :style="[page.isActive ? activeTextStyle : textStyle]">{{ page.label }}</text>
</slot>
</view>
</template>
<!-- 下一页按钮 -->
<view
v-if="showNextButton"
class="u-pagination__next"
:class="{ 'u-pagination__item--disabled': isLastPage || disabled }"
:style="[itemStyle()]"
@click="nextPage"
>
<slot name="next" :disabled="isLastPage || disabled">
<text :style="textStyle">{{ nextText }}</text>
</slot>
</view>
</view>
</template>
<script>
import props from './props.js';
import mixin from '../../libs/mixin/mixin';
import mpMixin from '../../libs/mixin/mpMixin';
/**
* Pagination 分页
* @description 分页器用于分隔长列表,每次只加载一个页面
* @tutorial https://uview.d3u.cn/components/pagination.html
* @property {Number} modelValue 当前页码(默认 1 )
* @property {Number} total 总记录数(默认 0 )
* @property {Number} pageSize 每页显示的记录数(默认 10 )
* @property {Number} pagerCount 显示的页码按钮数量(默认 5 )
* @property {Boolean} disabled 是否禁用分页(默认 false )
* @property {Boolean} forceEllipses 是否显示省略号(默认 false )
* @property {Boolean} simple 是否为简单分页(默认 false )
* @property {Boolean} showPrevButton 是否展示上一页按钮(默认 true )
* @property {Boolean} showNextButton 是否展示下一页按钮(默认 true )
* @property {String} prevText 上一页按钮文字(默认 '上一页' )
* @property {String} nextText 下一页按钮文字(默认 '下一页' )
* @property {String} bgColor 背景色(默认 '#f7f7f7' )
* @property {String} color 文本色(默认 '#606266' )
* @property {String} activeBgColor 激活背景色(默认 '#2979ff' )
* @property {String} activeColor 激活文本色(默认 '#ffffff' )
* @property {String} fontSize 字体尺寸(默认 '14px' )
* @property {String} round 圆角(默认 '4px' )
* @property {String} borderColor 描边色(默认 '#e4e7ed' )
* @property {String} itemWidth 每项宽度(默认 '40px' )
* @property {String} itemHeight 每项高度(默认 '40px' )
* @property {Object} customStyle 自定义样式
* @event {Function} change 切换分页触发
* @example <u-pagination v-model="currentPage" :total="100" :page-size="10"></u-pagination>
*/
export default {
name: "u-pagination",
mixins: [mpMixin, mixin, props],
data() {
return {
innerValue: 0
}
},
computed: {
// 总页数
totalPages() {
return Math.max(1, Math.ceil(this.total / this.pageSize));
},
// 是否为第一页
isFirstPage() {
return this.innerValue <= 1;
},
// 是否为最后一页
isLastPage() {
return this.innerValue >= this.totalPages;
},
// 页码项目列表
pageItems() {
const pageList = [];
const totalPageCount = this.totalPages;
const visiblePageCount = this.pagerCount;
const currentPageNum = this.innerValue;
let firstPage = 1;
let lastPage = totalPageCount;
const shouldLimitPages = visiblePageCount < totalPageCount;
if (shouldLimitPages) {
const halfVisible = Math.floor(visiblePageCount / 2);
firstPage = Math.max(currentPageNum - halfVisible, 1);
lastPage = firstPage + visiblePageCount - 1;
if (lastPage > totalPageCount) {
lastPage = totalPageCount;
firstPage = lastPage - visiblePageCount + 1;
}
}
// 生成基础页码列表
for (let pageNum = firstPage; pageNum <= lastPage; pageNum++) {
pageList.push({
pageNumber: pageNum,
label: `${pageNum}`,
isActive: pageNum === currentPageNum,
type: 'page'
});
}
// 处理省略号显示逻辑
if (shouldLimitPages && visiblePageCount > 0 && this.forceEllipses) {
// 添加左侧省略号和首页
if (firstPage > 1) {
pageList.shift();
// 添加左侧省略号
pageList.unshift({
pageNumber: firstPage - 1,
label: '...',
isActive: false,
type: 'ellipsis'
});
// 添加首页
pageList.unshift({
pageNumber: 1,
label: '1',
isActive: currentPageNum === 1,
type: 'page'
});
}
// 添加右侧省略号和末页
if (lastPage < totalPageCount) {
pageList.pop();
// 添加右侧省略号
pageList.push({
pageNumber: lastPage + 1,
label: '...',
isActive: false,
type: 'ellipsis'
});
// 添加末页
pageList.push({
pageNumber: totalPageCount,
label: `${totalPageCount}`,
isActive: currentPageNum === totalPageCount,
type: 'page'
});
}
}
return pageList;
},
// 项目样式
itemStyle(isItem) {
return (isItem) => {
let style = {
height: this.itemHeight,
borderRadius: this.round
}
if(this.bgColor){
style.backgroundColor = this.bgColor
}
if(this.borderColor){
style.border = '1px solid ' + this.borderColor
}
if(isItem){
style.width = this.itemWidth
}
return style;
}
},
// 激活项目样式
activeItemStyle(isItem) {
return (isItem) => {
let style = {
height: this.itemHeight,
borderRadius: this.round
}
if(this.activeBgColor){
style.backgroundColor = this.activeBgColor
}
if(this.activeColor){
style.color = this.activeColor
}
if(isItem){
style.width = this.itemWidth
}
return style;
}
},
// 文本样式
textStyle() {
return {
color: this.color,
fontSize: this.fontSize
};
},
// 激活文本样式
activeTextStyle() {
return {
color: this.activeColor,
fontSize: this.fontSize
};
}
},
watch: {
// #ifdef VUE3
modelValue: {
immediate: true,
handler(val) {
// 只在初始化或外部主动改变时更新内部状态
if (val && val !== this.innerValue) {
this.innerValue = val;
}
}
},
// #endif
value: {
immediate: true,
handler(val) {
// 只在没有modelValue且value有效时更新
if (val && !this.modelValue) {
this.innerValue = val;
}
}
}
},
// #ifdef VUE3
emits: ["update:modelValue", "change"],
// #endif
methods: {
// 更新页码
updatePage(page) {
if (this.disabled) return;
const newPage = Math.max(1, Math.min(page, this.totalPages));
if (newPage !== this.innerValue) {
this.innerValue = newPage;
// #ifdef VUE2
this.$emit('input', newPage);
// #endif
// #ifdef VUE3
this.$emit('update:modelValue', newPage);
// #endif
this.$emit('change', newPage);
}
},
// 上一页
prevPage() {
if (this.isFirstPage || this.disabled) return;
this.updatePage(this.innerValue - 1);
},
// 下一页
nextPage() {
if (this.isLastPage || this.disabled) return;
this.updatePage(this.innerValue + 1);
},
// 处理页码点击
handlePageClick(page) {
if (this.disabled || page.isActive) return;
this.updatePage(page.pageNumber);
}
}
}
</script>
<style lang="scss" scoped>
@import "../../libs/css/components.scss";
.u-pagination {
@include flex;
align-items: center;
justify-content: center;
&--simple {
.u-pagination__simple {
margin: 0 12px;
}
}
&--disabled {
opacity: 0.8;
// #ifdef H5
pointer-events: none;
// #endif
}
&__item,
&__prev,
&__next {
@include flex;
align-items: center;
justify-content: center;
// #ifndef APP-NVUE
user-select: none;
// #endif
// #ifdef H5
cursor: pointer;
// #endif
&--active {
border-color: transparent;
}
&--disabled {
opacity: 0.5;
// #ifdef H5
cursor: not-allowed;
// #endif
}
&--ellipsis {
// #ifdef H5
cursor: pointer;
// #endif
}
}
&__prev {
margin-right: 3px;
}
&__next {
margin-left: 3px;
}
&__prev,
&__next {
padding: 0 10px;
&:active {
opacity: 0.8;
}
}
&__item {
margin: 0 3px;
}
}
</style>