231 lines
5.8 KiB
Vue
231 lines
5.8 KiB
Vue
<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>
|