Files
2026-01-05 12:47:14 +08:00

137 lines
3.8 KiB
Vue
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<script setup lang="ts">
import { computed, defineComponent, toRefs, watchEffect } from 'vue'
import { CHANGE_EVENT, PREFIX, UPDATE_MODEL_EVENT } from '../_constants'
import { getMainClass } from '../_utils'
import { useTranslate } from '../../locale'
import { paginationEmits, paginationProps } from './pagination'
const props = defineProps(paginationProps)
const emit = defineEmits(paginationEmits)
const { modelValue, mode, showPageSize, forceEllipses } = toRefs(props)
const classes = computed(() => {
return getMainClass(props, componentName)
})
// 计算页面的数量
const countRef = computed(() => {
const { pageCount, totalItems, itemsPerPage } = toRefs(props)
const num = +pageCount.value || Math.ceil(+totalItems.value / +itemsPerPage.value)
return Math.max(1, num)
})
// 点击选择page
function select(curPage: number, isSelect: boolean) {
if (curPage > countRef.value || curPage < 1)
return
if (curPage !== modelValue.value)
emit(UPDATE_MODEL_EVENT, curPage)
if (isSelect)
emit(CHANGE_EVENT, curPage)
}
// set page 对象
function setPage(number: number, text: string | number, active = false) {
return { number, text, active }
}
// 生成pages数组用来遍历
const pages = computed(() => {
if (mode.value === 'simple')
return
const items = []
const pageCount = countRef.value // 总的页面数量
const pageSize = +showPageSize.value // 展示的页面个数
let startPage = 1
let endPage = pageCount
const partialShow = pageCount > pageSize
if (partialShow) {
// 选中的page在展示的page中间
startPage = Math.max(modelValue.value - Math.floor(pageSize / 2), 1)
endPage = startPage + +pageSize - 1
if (endPage > pageCount) {
endPage = pageCount
startPage = endPage - +pageSize + 1
}
}
// 遍历生成数组
for (let i = startPage; i <= endPage; i++) {
const page = setPage(i, i, modelValue.value === i)
items.push(page)
}
// 判断是否有折叠
if (partialShow && pageSize > 0 && forceEllipses.value) {
if (startPage > 1) {
const prevPage = setPage(startPage - 1, '...')
items.unshift(prevPage)
}
if (endPage < pageCount) {
const nextPage = setPage(endPage + 1, '...')
items.push(nextPage)
}
}
return items
})
// 监听选中的page变化
watchEffect(() => {
select(modelValue.value, false)
})
</script>
<script lang="ts">
const componentName = `${PREFIX}-pagination`
const { translate } = useTranslate(componentName)
export default defineComponent({
name: componentName,
options: {
virtualHost: true,
addGlobalClass: true,
styleIsolation: 'shared',
},
})
</script>
<template>
<view :class="classes" :style="customStyle">
<view
class="nut-pagination-prev"
:class="[mode === 'multi' ? '' : 'simple-border', modelValue === 1 ? 'disabled' : '']"
@click="select(modelValue - 1, true)"
>
<slot name="prevText">
{{ prevText || translate('prev') }}
</slot>
</view>
<view v-if="mode === 'multi'" class="nut-pagination-contain">
<view
v-for="(item, index) of pages"
:key="`${index}pagination`"
class="nut-pagination-item"
:class="[item.active ? 'active' : '']"
@click="select(item.number, true)"
>
<slot name="page" :item="item">
{{ item.text }}
</slot>
</view>
</view>
<view v-if="mode === 'simple'" class="nut-pagination-contain">
<view class="nut-pagination-simple">
{{ modelValue }}/{{ countRef }}
</view>
</view>
<view
class="nut-pagination-next"
:class="[modelValue >= countRef ? 'disabled' : '']"
@click="select(modelValue + 1, true)"
>
<slot name="nextText">
{{ nextText || translate('next') }}
</slot>
</view>
</view>
</template>
<style lang="scss">
@import './index';
</style>