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

231 lines
5.8 KiB
Vue

1 year ago
<template>
<view class="tm-pagination flex-center">
<view v-if="tal" class="flex-start flex-wrap flex-between fulled">
<tm-button :fllowTheme="false" :shadow="4" :icon-size="24"
:font-color="nowIndex==1||disabled?'grey':color_tmeme" :black="black_tmeme" @click="tv_pre"
:disabled="nowIndex==1||disabled" theme="white" :item-class="round?'rounded':''" block height="64" width="64"
icon="icon-angle-left"></tm-button>
<block v-for="(item,index) in items " :key="index">
<tm-button :fllowTheme="false" :shadow="4" :disabled="disabled" :black="black_tmeme"
:theme="item==nowIndex?color_tmeme:'white'" @click="clicPages(item)" block
:item-class="round?'rounded':''" height="64" width="64">
{{item}}
</tm-button>
</block>
<tm-button :fllowTheme="false" :shadow="4" :icon-size="24"
:font-color="nowIndex==tal||disabled?'grey':color_tmeme" :black="black_tmeme" theme="white"
@click="tv_next" :disabled="nowIndex==tal||disabled?true:false" :item-class="round?'rounded':''" block
height="64" width="64" icon="icon-angle-right">
</tm-button>
</view>
</view>
</template>
<script>
/**
* 分页
* @property {Function} change 页面改变时触发
* @property {Number} page = [] 默认1当前页码必须使用page.sync
* @property {Number} total-visible = [] 默认5最大可见页数
* @property {Number} total = [] 默认0总条数
* @property {Number} size = [] 默认8每页的数量
* @property {Boolean} round = [] 默认false,是否圆形按钮
* @property {Boolean} black = [] 默认false,是否暗黑模式
* @property {Boolean} disabled = [] 默认false,禁用
* @property {String} color = [] 默认primary,选中的主题色
* @example <tm-pagination :page.sync="page" :total="100"></tm-pagination>
*/
import tmButton from "@/tm-vuetify/components/tm-button/tm-button.vue"
export default {
components: {
tmButton
},
name: "tm-pagination",
props: {
total: {
type: Number,
default: 0
},
// 最大可见按钮数量。
totalVisible: {
type: Number,
default: 5
},
// 当前页码。需要page.sync同步。
page: {
type: Number,
default: 1
},
// 每页的数量 。
size: {
type: Number,
default: 10
},
// 是否圆形按钮。
round: {
type: Boolean,
default: false
},
// 是否暗黑模式
black: {
type: Boolean | String,
default: null
},
// 主题色
color: {
type: String,
default: 'primary'
},
disabled: {
type: Boolean,
default: false
},
// 跟随主题色的改变而改变。
fllowTheme: {
type: Boolean | String,
default: true
}
},
watch: {
page: function(val) {
this.init()
}
},
computed: {
black_tmeme: function() {
if (this.black !== null) return this.black;
return this.$tm.vx.state().tmVuetify.black;
},
color_tmeme: function() {
if (this.$tm.vx.state().tmVuetify.color !== null && this.$tm.vx.state().tmVuetify.color && this
.fllowTheme) {
return this.$tm.vx.state().tmVuetify.color;
}
return this.color;
},
//总共的页码。
tal: function() {
if (this.total <= this.size) return 1;
let isInt = this.total % this.size;
let ds = this.total / this.size;
return isInt == 0 ? Math.floor(ds) : Math.floor(ds) + 1;
},
items: function() {
const totalVisible = parseInt(this.totalVisible, 10)<=5?5:parseInt(this.totalVisible, 10);
if(this.tal<=totalVisible){
return this.range(1, this.tal)
}
if (totalVisible === 0) {
return []
}
const maxLength = Math.min(
Math.max(0, totalVisible) || this.tal,
Math.max(0, this.maxButtons) || this.tal,
this.tal
)
if (this.tal <= maxLength) {
return this.range(1, this.tal)
}
const even = maxLength % 2 === 0 ? 1 : 0
const left = Math.floor(maxLength / 2)
const right = this.tal - left + 1 + even
if (this.page > left && this.page < right) {
const firstItem = 1
const lastItem = this.tal
const start = this.page - left + 2
const end = this.page + left - 2 - even
const secondItem = start - 1 === firstItem + 1 ? 2 : '...'
const beforeLastItem = end + 1 === lastItem - 1 ? end + 1 : '...'
return [1, secondItem, ...this.range(start, end), beforeLastItem, this.tal]
} else if (this.page === left) {
const end = this.page + left - 1 - even
return [...this.range(1, end), '...', this.tal]
} else if (this.page === right) {
const start = this.page - left + 1
return [1, '...', ...this.range(start, this.tal)]
} else {
return [
...this.range(1, left),
'...',
...this.range(right, this.tal),
]
}
},
},
data() {
return {
nowIndex: 1,
maxButtons: 0,
};
},
mounted() {
let t = this;
this.$Querey('.tm-pagination').then(res => {
let w = res[0].width;
t.maxButtons = Math.floor((w - uni.upx2px(20)) / uni.upx2px(64))
})
},
methods: {
clicPages(index) {
if (index == '...') return;
this.$emit('input', index)
this.$emit('update:page', index)
this.$emit('prev')
this.$emit('change',index)
},
tv_pre() {
this.$emit('input', this.page - 1)
this.$emit('update:page', this.page - 1)
this.$emit('prev')
this.$emit('change',this.page - 1)
},
tv_next() {
this.$emit('input', this.page + 1)
this.$emit('update:page', this.page + 1)
this.$emit('next')
this.$emit('change',this.page + 1)
},
range(from = 1, to) {
const range = []
from = from > 0 ? from : 1
for (let i = from; i <= to; i++) {
range.push(i)
}
return range
},
init() {
this.nowIndex = null;
uni.$tm.sleep(100).then(() => (this.nowIndex = this.page))
},
},
}
</script>
<style lang="scss">
</style>