¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view class="uni-pagination"> |
| | | <!-- #ifndef MP --> |
| | | <picker v-if="showPageSize === true || showPageSize === 'true'" class="select-picker" mode="selector" |
| | | :value="pageSizeIndex" :range="pageSizeRange" @change="pickerChange" @cancel="pickerClick" |
| | | @click.native="pickerClick"> |
| | | <button type="default" size="mini" :plain="true"> |
| | | <text>{{pageSizeRange[pageSizeIndex]}} {{piecePerPage}}</text> |
| | | <uni-icons class="select-picker-icon" type="arrowdown" size="12" color="#999"></uni-icons> |
| | | </button> |
| | | </picker> |
| | | <!-- #endif --> |
| | | <!-- #ifndef APP-NVUE --> |
| | | <view class="uni-pagination__total is-phone-hide">å
± {{ total }} æ¡</view> |
| | | <!-- #endif --> |
| | | <view class="uni-pagination__btn" |
| | | :class="currentIndex === 1 ? 'uni-pagination--disabled' : 'uni-pagination--enabled'" |
| | | :hover-class="currentIndex === 1 ? '' : 'uni-pagination--hover'" :hover-start-time="20" |
| | | :hover-stay-time="70" @click="clickLeft"> |
| | | <template v-if="showIcon === true || showIcon === 'true'"> |
| | | <uni-icons color="#666" size="16" type="left" /> |
| | | </template> |
| | | <template v-else> |
| | | <text class="uni-pagination__child-btn">{{ prevPageText }}</text> |
| | | </template> |
| | | </view> |
| | | <view class="uni-pagination__num uni-pagination__num-flex-none"> |
| | | <view class="uni-pagination__num-current"> |
| | | <text class="uni-pagination__num-current-text is-pc-hide current-index-text">{{ currentIndex }}</text> |
| | | <text class="uni-pagination__num-current-text is-pc-hide">/{{ maxPage || 0 }}</text> |
| | | <!-- #ifndef APP-NVUE --> |
| | | <view v-for="(item, index) in paper" :key="index" :class="{ 'page--active': item === currentIndex }" |
| | | class="uni-pagination__num-tag tag--active is-phone-hide" @click.top="selectPage(item, index)"> |
| | | <text>{{ item }}</text> |
| | | </view> |
| | | <!-- #endif --> |
| | | |
| | | </view> |
| | | </view> |
| | | <view class="uni-pagination__btn" |
| | | :class="currentIndex >= maxPage ? 'uni-pagination--disabled' : 'uni-pagination--enabled'" |
| | | :hover-class="currentIndex === maxPage ? '' : 'uni-pagination--hover'" :hover-start-time="20" |
| | | :hover-stay-time="70" @click="clickRight"> |
| | | <template v-if="showIcon === true || showIcon === 'true'"> |
| | | <uni-icons color="#666" size="16" type="right" /> |
| | | </template> |
| | | <template v-else> |
| | | <text class="uni-pagination__child-btn">{{ nextPageText }}</text> |
| | | </template> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script> |
| | | /** |
| | | * Pagination åé¡µå¨ |
| | | * @description å页å¨ç»ä»¶ï¼ç¨äºå±ç¤ºé¡µç ãè¯·æ±æ°æ®ç |
| | | * @tutorial https://ext.dcloud.net.cn/plugin?id=32 |
| | | * @property {String} prevText 左侧æé®æå |
| | | * @property {String} nextText å³ä¾§æé®æå |
| | | * @property {String} piecePerPageText æ¡/页æå |
| | | * @property {Number} current å½å页 |
| | | * @property {Number} total æ°æ®æ»é |
| | | * @property {Number} pageSize æ¯é¡µæ°æ®é |
| | | * @property {Boolean} showIcon = [true|false] æ¯å¦ä»¥ icon å½¢å¼å±ç¤ºæé® |
| | | * @property {Boolean} showPageSize = [true|false] æ¯å¦å±ç¤ºæ¯é¡µæ¡æ° |
| | | * @property {Array} pageSizeRange = [20, 50, 100, 500] æ¯é¡µæ¡æ°éæ¡ |
| | | * @event {Function} change ç¹å»é¡µç æé®æ¶è§¦å ,e={type,current} current为å½å页ï¼typeå¼ä¸ºï¼next/prevï¼è¡¨ç¤ºç¹å»çæ¯ä¸ä¸é¡µè¿æ¯ä¸ä¸ä¸ª |
| | | * * @event {Function} pageSizeChange å½åæ¯é¡µæ¡æ°æ¹åæ¶è§¦å ,e={pageSize} pageSize 为å½åæéçæ¯é¡µæ¡æ° |
| | | */ |
| | | |
| | | import { |
| | | initVueI18n |
| | | } from '@dcloudio/uni-i18n' |
| | | import messages from './i18n/index.js' |
| | | const { |
| | | t |
| | | } = initVueI18n(messages) |
| | | export default { |
| | | name: 'UniPagination', |
| | | emits: ['update:modelValue', 'input', 'change', 'pageSizeChange'], |
| | | props: { |
| | | value: { |
| | | type: [Number, String], |
| | | default: 1 |
| | | }, |
| | | modelValue: { |
| | | type: [Number, String], |
| | | default: 1 |
| | | }, |
| | | prevText: { |
| | | type: String, |
| | | }, |
| | | nextText: { |
| | | type: String, |
| | | }, |
| | | piecePerPageText: { |
| | | type: String |
| | | }, |
| | | current: { |
| | | type: [Number, String], |
| | | default: 1 |
| | | }, |
| | | total: { |
| | | // æ°æ®æ»é |
| | | type: [Number, String], |
| | | default: 0 |
| | | }, |
| | | pageSize: { |
| | | // æ¯é¡µæ°æ®é |
| | | type: [Number, String], |
| | | default: 10 |
| | | }, |
| | | showIcon: { |
| | | // æ¯å¦ä»¥ icon å½¢å¼å±ç¤ºæé® |
| | | type: [Boolean, String], |
| | | default: false |
| | | }, |
| | | showPageSize: { |
| | | // æ¯å¦ä»¥ icon å½¢å¼å±ç¤ºæé® |
| | | type: [Boolean, String], |
| | | default: false |
| | | }, |
| | | pagerCount: { |
| | | type: Number, |
| | | default: 7 |
| | | }, |
| | | pageSizeRange: { |
| | | type: Array, |
| | | default: () => [20, 50, 100, 500] |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | pageSizeIndex: 0, |
| | | currentIndex: 1, |
| | | paperData: [], |
| | | pickerShow: false |
| | | } |
| | | }, |
| | | computed: { |
| | | piecePerPage() { |
| | | return this.piecePerPageText || t('uni-pagination.piecePerPage') |
| | | }, |
| | | prevPageText() { |
| | | return this.prevText || t('uni-pagination.prevText') |
| | | }, |
| | | nextPageText() { |
| | | return this.nextText || t('uni-pagination.nextText') |
| | | }, |
| | | maxPage() { |
| | | let maxPage = 1 |
| | | let total = Number(this.total) |
| | | let pageSize = Number(this.pageSize) |
| | | if (total && pageSize) { |
| | | maxPage = Math.ceil(total / pageSize) |
| | | } |
| | | return maxPage |
| | | }, |
| | | paper() { |
| | | const num = this.currentIndex |
| | | // TODO æå¤§é¡µæ° |
| | | const pagerCount = this.pagerCount |
| | | // const total = 181 |
| | | const total = this.total |
| | | const pageSize = this.pageSize |
| | | let totalArr = [] |
| | | let showPagerArr = [] |
| | | let pagerNum = Math.ceil(total / pageSize) |
| | | for (let i = 0; i < pagerNum; i++) { |
| | | totalArr.push(i + 1) |
| | | } |
| | | showPagerArr.push(1) |
| | | const totalNum = totalArr[totalArr.length - (pagerCount + 1) / 2] |
| | | totalArr.forEach((item, index) => { |
| | | if ((pagerCount + 1) / 2 >= num) { |
| | | if (item < pagerCount + 1 && item > 1) { |
| | | showPagerArr.push(item) |
| | | } |
| | | } else if (num + 2 <= totalNum) { |
| | | if (item > num - (pagerCount + 1) / 2 && item < num + (pagerCount + 1) / 2) { |
| | | showPagerArr.push(item) |
| | | } |
| | | } else { |
| | | if ((item > num - (pagerCount + 1) / 2 || pagerNum - pagerCount < item) && item < totalArr[ |
| | | totalArr.length - 1]) { |
| | | showPagerArr.push(item) |
| | | } |
| | | } |
| | | }) |
| | | if (pagerNum > pagerCount) { |
| | | if ((pagerCount + 1) / 2 >= num) { |
| | | showPagerArr[showPagerArr.length - 1] = '...' |
| | | } else if (num + 2 <= totalNum) { |
| | | showPagerArr[1] = '...' |
| | | showPagerArr[showPagerArr.length - 1] = '...' |
| | | } else { |
| | | showPagerArr[1] = '...' |
| | | } |
| | | showPagerArr.push(totalArr[totalArr.length - 1]) |
| | | } else { |
| | | if ((pagerCount + 1) / 2 >= num) {} else if (num + 2 <= totalNum) {} else { |
| | | showPagerArr.shift() |
| | | showPagerArr.push(totalArr[totalArr.length - 1]) |
| | | } |
| | | } |
| | | |
| | | return showPagerArr |
| | | } |
| | | }, |
| | | watch: { |
| | | current: { |
| | | immediate: true, |
| | | handler(val, old) { |
| | | if (val < 1) { |
| | | this.currentIndex = 1 |
| | | } else { |
| | | this.currentIndex = val |
| | | } |
| | | } |
| | | }, |
| | | value: { |
| | | immediate: true, |
| | | handler(val) { |
| | | if (Number(this.current) !== 1) return |
| | | if (val < 1) { |
| | | this.currentIndex = 1 |
| | | } else { |
| | | this.currentIndex = val |
| | | } |
| | | } |
| | | }, |
| | | pageSizeIndex(val) { |
| | | this.$emit('pageSizeChange', this.pageSizeRange[val]) |
| | | } |
| | | }, |
| | | methods: { |
| | | pickerChange(e) { |
| | | this.pageSizeIndex = e.detail.value |
| | | this.pickerClick() |
| | | }, |
| | | pickerClick() { |
| | | // #ifdef H5 |
| | | const body = document.querySelector('body') |
| | | if (!body) return |
| | | |
| | | const className = 'uni-pagination-picker-show' |
| | | this.pickerShow = !this.pickerShow |
| | | |
| | | if (this.pickerShow) { |
| | | body.classList.add(className) |
| | | } else { |
| | | setTimeout(() => body.classList.remove(className), 300) |
| | | } |
| | | // #endif |
| | | }, |
| | | // éæ©æ ç¾ |
| | | selectPage(e, index) { |
| | | if (parseInt(e)) { |
| | | this.currentIndex = e |
| | | this.change('current') |
| | | } else { |
| | | let pagerNum = Math.ceil(this.total / this.pageSize) |
| | | // let pagerNum = Math.ceil(181 / this.pageSize) |
| | | // ä¸ä¸é¡µ |
| | | if (index <= 1) { |
| | | if (this.currentIndex - 5 > 1) { |
| | | this.currentIndex -= 5 |
| | | } else { |
| | | this.currentIndex = 1 |
| | | } |
| | | return |
| | | } |
| | | // ä¸ä¸é¡µ |
| | | if (index >= 6) { |
| | | if (this.currentIndex + 5 > pagerNum) { |
| | | this.currentIndex = pagerNum |
| | | } else { |
| | | this.currentIndex += 5 |
| | | } |
| | | return |
| | | } |
| | | } |
| | | }, |
| | | clickLeft() { |
| | | if (Number(this.currentIndex) === 1) { |
| | | return |
| | | } |
| | | this.currentIndex -= 1 |
| | | this.change('prev') |
| | | }, |
| | | clickRight() { |
| | | if (Number(this.currentIndex) >= this.maxPage) { |
| | | return |
| | | } |
| | | this.currentIndex += 1 |
| | | this.change('next') |
| | | }, |
| | | change(e) { |
| | | this.$emit('input', this.currentIndex) |
| | | this.$emit('update:modelValue', this.currentIndex) |
| | | this.$emit('change', { |
| | | type: e, |
| | | current: this.currentIndex |
| | | }) |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | $uni-primary: #2979ff !default; |
| | | .uni-pagination { |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | /* #endif */ |
| | | position: relative; |
| | | overflow: hidden; |
| | | flex-direction: row; |
| | | justify-content: center; |
| | | align-items: center; |
| | | } |
| | | |
| | | .uni-pagination__total { |
| | | font-size: 14px; |
| | | color: #999; |
| | | margin-right: 15px; |
| | | } |
| | | |
| | | .uni-pagination__btn { |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | cursor: pointer; |
| | | /* #endif */ |
| | | padding: 0 8px; |
| | | line-height: 30px; |
| | | font-size: 12px; |
| | | position: relative; |
| | | background-color: #F0F0F0; |
| | | flex-direction: row; |
| | | justify-content: center; |
| | | align-items: center; |
| | | text-align: center; |
| | | border-radius: 5px; |
| | | // border-width: 1px; |
| | | // border-style: solid; |
| | | // border-color: $uni-border-color; |
| | | } |
| | | |
| | | .uni-pagination__child-btn { |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | /* #endif */ |
| | | font-size: 12px; |
| | | position: relative; |
| | | flex-direction: row; |
| | | justify-content: center; |
| | | align-items: center; |
| | | text-align: center; |
| | | color: #666; |
| | | font-size: 12px; |
| | | } |
| | | |
| | | .uni-pagination__num { |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | /* #endif */ |
| | | flex: 1; |
| | | flex-direction: row; |
| | | justify-content: center; |
| | | align-items: center; |
| | | height: 30px; |
| | | line-height: 30px; |
| | | font-size: 12px; |
| | | color: #666; |
| | | margin: 0 5px; |
| | | } |
| | | |
| | | .uni-pagination__num-tag { |
| | | /* #ifdef H5 */ |
| | | cursor: pointer; |
| | | min-width: 30px; |
| | | /* #endif */ |
| | | margin: 0 5px; |
| | | height: 30px; |
| | | text-align: center; |
| | | line-height: 30px; |
| | | // border: 1px red solid; |
| | | color: #999; |
| | | border-radius: 4px; |
| | | // border-width: 1px; |
| | | // border-style: solid; |
| | | // border-color: $uni-border-color; |
| | | } |
| | | |
| | | .uni-pagination__num-current { |
| | | /* #ifndef APP-NVUE */ |
| | | display: flex; |
| | | /* #endif */ |
| | | flex-direction: row; |
| | | } |
| | | |
| | | .uni-pagination__num-current-text { |
| | | font-size: 15px; |
| | | } |
| | | |
| | | .current-index-text{ |
| | | color: $uni-primary; |
| | | } |
| | | |
| | | .uni-pagination--enabled { |
| | | color: #333333; |
| | | opacity: 1; |
| | | } |
| | | |
| | | .uni-pagination--disabled { |
| | | opacity: 0.5; |
| | | /* #ifdef H5 */ |
| | | cursor: default; |
| | | /* #endif */ |
| | | } |
| | | |
| | | .uni-pagination--hover { |
| | | color: rgba(0, 0, 0, 0.6); |
| | | background-color: #eee; |
| | | } |
| | | |
| | | .tag--active:hover { |
| | | color: $uni-primary; |
| | | } |
| | | |
| | | .page--active { |
| | | color: #fff; |
| | | background-color: $uni-primary; |
| | | } |
| | | |
| | | .page--active:hover { |
| | | color: #fff; |
| | | } |
| | | |
| | | /* #ifndef APP-NVUE */ |
| | | .is-pc-hide { |
| | | display: block; |
| | | } |
| | | |
| | | .is-phone-hide { |
| | | display: none; |
| | | } |
| | | |
| | | @media screen and (min-width: 450px) { |
| | | .is-pc-hide { |
| | | display: none; |
| | | } |
| | | |
| | | .is-phone-hide { |
| | | display: block; |
| | | } |
| | | |
| | | .uni-pagination__num-flex-none { |
| | | flex: none; |
| | | } |
| | | } |
| | | |
| | | /* #endif */ |
| | | </style> |