UNPKG

magiccube-vue3

Version:

vue3-js版组件库

289 lines (273 loc) 11.3 kB
import { ref, onMounted, computed, watchEffect } from 'vue' const Pagination = { name: 'McPagination', props: { total: { type: [Number, String], default: 0 }, pageSize: { type: [Number, String], default: 20 }, simple: { type: Boolean, default: false }, startRow: { type: [Number, String], default: 0 }, changePageSize: { type: Boolean, default: true }, showTotal: { type: Boolean, default: true }, maxPageSize: { type: Number, default: 100 }, align: { type: String, default: 'center' } }, emits: ['change', 'error'], setup(props, { emit }) { const current = ref(1) const jump = ref('') const pageSizeEl = ref(null) const gotoEl = ref(null) const handlePage = (number) => { if (props.startRow === number) return false const params = { pageSize: props.pageSize, startRow: (number - 1) * props.pageSize } emit('change', params) } const handleClick = (type, number) => { switch (type) { case 'page': { if (current.value === number) return false const params = { pageSize: props.pageSize, startRow: (number - 1) * props.pageSize } emit('change', params) break } case 'prev': { if (current.value <= 1) return false const params = { pageSize: props.pageSize, startRow: (current.value - 2) * props.pageSize } emit('change', params) break } case 'next': { const len = pageList.value.length if (current.value >= pageList.value[len - 1]) return false const params = { pageSize: props.pageSize, startRow: current.value * props.pageSize } emit('change', params) break } case 'amount': { const params = { pageSize: props.pageSize, startRow: (pageAmount.value - 1) * props.pageSize } emit('change', params) break } case 'first': { const params = { pageSize: props.pageSize, startRow: 0 } emit('change', params) break } } current.value = number } const invalidNumber = n => !Number(n) || parseInt(n) !== Number(n) || Number(n) < 0 const handleChangePageSize = (e) => { if (e.keyCode !== 13) return let val = e.target.value // 不能输入小数、负数、和非数字内容 if (invalidNumber(val)) { e.target.value= props.pageSize emit('error', new Error('请输入正确的数值')) return } if(Number(val) > props.maxPageSize){ emit('error', new Error(`每页最多${props.maxPageSize}条数据`)) val = props.maxPageSize e.target.value = props.maxPageSize } const params = { pageSize: Number(val), startRow: 0 } if (pageSizeEl.value) pageSizeEl.value.blur() emit('change', params) } const handleJump = (e) => { if (e.keyCode !== 13) return // 不能输入小数、负数、和非数字内容 if (invalidNumber(jump.value)) { jump.value = '' emit('error', new Error('请输入正确的数值')) return } let _jump = Number(jump.value) || 1 const pageTotalCount = Math.ceil(props.total / props.pageSize) if (_jump > pageTotalCount) _jump = pageTotalCount const params = { pageSize: props.pageSize, startRow: (_jump - 1) * props.pageSize } current.value = _jump jump.value = '' gotoEl.value.blur() emit('change', params) } const showNumber = (num) => { if (current.value < 3) { return num <= 5 } else if (current.value > pageAmount.value - 3) { return num >= pageAmount.value - 4 } else { return (num < current.value + 3 && num > current.value - 3) || num === current.value } } const showEllipsis = (type) => { if (type === 'front') { return current.value - 3 >= 1 } else { return pageList.value.length < pageAmount.value && pageAmount.value - current.value >= 3 } } const pageList = computed(() => { const p = Math.ceil(props.total / props.pageSize) const list = [] for (let i = 1; i <= p; i++) list.push(i) return list.filter(page => showNumber(page)) }) const pageAmount = computed(() => { return Math.ceil(props.total / props.pageSize) || 0 }) watchEffect(() => { current.value = props.startRow / props.pageSize + 1 }) return () => { if (props.total) { return ( ( <div class={[ 'mc-pagination', `mc-pagination__align--${props.align}` ]}> { props.showTotal ? ( <div class="mc-pagination__total"> <span></span> <em class="mc-pagination__amount">{props.total}</em> <span></span> </div> ) : '' } { !props.simple && props.changePageSize ? ( <div class="mc-pagination__size"> <span>每页</span> <span class="mc-pagination__input"> <input class="mc-pagination__input--inner" ref={pageSizeEl} value={props.pageSize} autocomplete="off" onKeypress={handleChangePageSize} /> </span> <span></span> </div> ) : '' } <div class="mc-pagination__pages"> <div class={[ 'page-prev', { disabled: current.value === 1 } ]} onClick={() => handleClick('prev', current.value - 1)}></div> { showEllipsis('front') ? ( <div class="ellipsis"> <i class="page-tip" onClick={() => handleClick('first', 1)}>1</i> ... </div> ) : '' } <div style="display:flex;align-items:center;"> { pageList.value.map((page, idx) => ( <span class={[ 'page-number', { 'simple': props.simple }, { 'active': page === current.value } ]} key={idx} onClick={() => handleClick('page', page)}> {page} </span> )) } </div> { showEllipsis('behind') ? ( <div class="ellipsis"> ... <i class="page-tip" onClick={() => handleClick('amount', pageAmount.value)}>{pageAmount.value}</i> </div> ) : '' } <div class={[ 'page-next', { disabled: pageAmount.value - current.value <= 0 } ]} onClick={() => handleClick('next', current.value + 1)}></div> </div> { !props.simple ? ( <div class="mc-pagination__goto"> <span>前往</span> <span class="mc-pagination__input"> <input class="mc-pagination__input--inner" ref={gotoEl} v-model={jump.value} autocomplete="off" onKeypress={handleJump} /> </span> <span></span> </div> ) : '' } </div> ) ) } else { return '' } } } } Pagination.install = (app) => { app.component(Pagination.name, Pagination) } const McPagination = Pagination export { McPagination, McPagination as default }