Files
cz-web/src/views/project/cpns/ProjectPager.vue
wangzzpeng 6eb2bfcbfd first1
2026-09-28 09:27:51 +08:00

118 lines
2.9 KiB
Vue
Raw 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 } from 'vue'
/**
* 项目中心分页器(按设计稿:小方块、当前页为**蓝色描边**而非填充)。
*
* <p>为什么不复用公共 `PaginationBar`:那个是 32px 实心选中态、服务多个页面,
* 与项目中心设计稿的 20px 描边样式不同,改它会波及其它页面。</p>
*/
interface Props {
page: number
pageSize: number
total: number
}
const props = defineProps<Props>()
const emit = defineEmits<{ pageChange: [page: number] }>()
const pageCount = computed(() => Math.max(1, Math.ceil(props.total / props.pageSize)))
/** 页码序列:≤7 全部展示,否则首尾 + 当前页窗口(… 省略) */
const pages = computed<Array<number | '...'>>(() => {
const n = pageCount.value
const { page } = props
if (n <= 7) return Array.from({ length: n }, (_, i) => i + 1)
const window: Array<number | '...'> = []
for (let p = page - 1; p <= page + 1; p++) {
if (p >= 1 && p <= n) window.push(p)
}
if (page > 3) window.unshift('...')
if (page < n - 2) window.push('...')
return [1, ...window.filter((item) => item !== 1 && item !== n), n].filter(
(item, index, arr) => arr.indexOf(item) === index,
)
})
function go(page: number): void {
if (page < 1 || page > pageCount.value || page === props.page) return
emit('pageChange', page)
}
</script>
<template>
<nav class="project-pager" aria-label="分页">
<button
type="button"
class="project-pager__btn"
:disabled="page <= 1"
@click="go(page - 1)"
>
‹
</button>
<button
v-for="(item, index) in pages"
:key="`${item}-${index}`"
type="button"
class="project-pager__btn"
:class="{ 'is-active': item === page, 'is-ellipsis': item === '...' }"
:disabled="item === '...'"
@click="go(item as number)"
>
{{ item }}
</button>
<button
type="button"
class="project-pager__btn"
:disabled="page >= pageCount"
@click="go(page + 1)"
>
›
</button>
</nav>
</template>
<style lang="less" scoped>
.project-pager {
.flex(row, flex-end, center);
gap: 4px;
margin-top: 15px;
&__btn {
.flex(row, center, center);
width: 20px;
height: 20px;
border: 1px solid @border-color-dark;
border-radius: 2px;
background: @white;
color: @heading-color;
font-size: @font-size-sm;
transition: border-color 0.2s, color 0.2s;
&:hover:not(:disabled):not(.is-ellipsis) {
border-color: @primary-color;
color: @primary-color;
}
// 设计稿:当前页是描边态(蓝框 + 蓝字),不是实心
&.is-active {
border-color: @primary-color;
color: @primary-color;
}
&.is-ellipsis {
border-color: transparent;
background: transparent;
cursor: default;
}
&:disabled:not(.is-ellipsis) {
opacity: 0.4;
cursor: not-allowed;
}
}
}
</style>