Files
fzu-product/components/Pagination.vue
2023-07-22 02:08:14 +08:00

150 lines
3.8 KiB
Vue

<script setup>
import { computed } from 'vue';
const props = defineProps(['modelValue', 'pageTotal'])
const emit = defineEmits(['update:modelValue'])
const onPrev = () => {
if (props.modelValue <= 1) return; // 限制上一页翻页按钮的边界
emit('update:modelValue', props.modelValue - 1)
}
const onNext = () => {
if (props.modelValue >= props.pageTotal) return; // 限制下一页翻页按钮的边界
emit('update:modelValue', props.modelValue + 1)
}
const setPageNum = (pageNum) => {
if (typeof pageNum !== 'number') return; //如果pageNum不是数值类型则返回
if (pageNum < 1) return; // 限制上一页翻页按钮的边界
if (pageNum > props.pageTotal) return; // 限制下一页翻页按钮的边界
emit('update:modelValue', pageNum)
}
const genPageArray = (current, total, size) => {
let arr = []
if (total < size + 2) {
arr = Array.from({ length: total }, (v, k) => k + 1)
} else if (current < size - 2) {
arr = Array.from(function* gen(i, l) { while (i < l) yield i++; }(1, size - 2 + 1))
arr.push('...')
arr.push(total)
} else if (total - current < size - 2) {
arr.push(1)
arr.push('...')
arr = arr.concat(Array.from(function* gen(i, l) { while (i < l) yield i++; }(total - size + 2, total + 1)))
} else {
arr.push(1)
arr.push('...')
arr = arr.concat(Array.from(function* gen(i, l) { while (i < l) yield i++; }(current - Math.floor((size - 4) / 2), current - Math.floor((size - 4) / 2) + size - 4 + 1)))
arr.push('...')
arr.push(total)
}
return arr
}
const pageArrayLg = computed(() => {
const current = props.modelValue
const total = props.pageTotal
return genPageArray(current, total, 17)
})
const pageArrayMd = computed(() => {
const current = props.modelValue
const total = props.pageTotal
return genPageArray(current, total, 10)
})
const pageArraySm = computed(() => {
const current = props.modelValue
const total = props.pageTotal
return genPageArray(current, total, 6)
})
</script>
<template>
<div>
<div class="container" v-if="props.pageTotal > 1">
<div class="paper-item" @click="onPrev" style="display: flex;">&lt;</div>
<div v-for="(item, index) in pageArrayLg" :key="index" @click="setPageNum(item)" class="paper-item paper-lg"
:class="{ 'active': item == props.modelValue }">{{ item }}</div>
<div v-for="(item, index) in pageArrayMd" :key="index" @click="setPageNum(item)" class="paper-item paper-md"
:class="{ 'active': item == props.modelValue }">{{ item }}</div>
<div v-for="(item, index) in pageArraySm" :key="index" @click="setPageNum(item)" class="paper-item paper-sm"
:class="{ 'active': item == props.modelValue }">{{ item }}</div>
<div class="paper-item" @click="onNext" style="display: flex;">></div>
</div>
</div>
</template>
<style scoped>
.container {
margin: 1rem 0;
width: 100%;
display: flex;
justify-content: center;
/* font-weight: 600; */
}
@media screen and (min-width: 780px) {
.paper-lg,
.paper-sm {
display: none;
}
.paper-md {
display: flex;
}
}
@media screen and (min-width: 1024px) {
.paper-md,
.paper-sm {
display: none;
}
.paper-lg {
display: flex;
}
}
@media screen and (max-width: 780px) {
.paper-lg,
.paper-md {
display: none;
}
.paper-sm {
display: flex;
}
}
.paper-item {
height: 2rem;
width: 2rem;
margin: 0 .5rem;
padding: 0rem .25rem;
align-items: center;
justify-content: center;
background-color: #f6f6f7;
border-radius: .25rem;
cursor: pointer;
}
.paper-item:hover {
background-color: #0099ff0d;
--un-text-opacity: 1;
color: #0099ff;
}
.paper-item.active {
background-color: #0099ff0d;
--un-text-opacity: 1;
color: #0099ff;
}
@media (prefers-color-scheme: dark) {
.paper-item {
background-color: #9ca3af0d;
}
}</style>