<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> 
 |