casualroom/apps/fenghuo/web/components/articles/article-pagination.tsx

109 lines
2.9 KiB
TypeScript
Raw Normal View History

2025-07-28 07:50:50 +08:00
import { Button } from '@nice/ui/components/button';
import { IconChevronLeft, IconChevronRight } from '@tabler/icons-react';
import { useArticlesContext } from './context';
export function ArticlePagination() {
const { pagination, setCurrentPage } = useArticlesContext();
const { currentPage, pageSize, totalPages, totalCount } = pagination;
if (totalPages <= 1) {
return null;
}
const startItem = (currentPage - 1) * pageSize + 1;
const endItem = Math.min(currentPage * pageSize, totalCount || 0);
// 生成页码数组
const getPageNumbers = (): number[] => {
const pages: number[] = [];
const maxVisible = 5; // 最多显示5个页码
if (totalPages <= maxVisible) {
// 总页数不超过最大显示数,显示全部
for (let i = 1; i <= totalPages; i++) {
pages.push(i);
}
} else {
// 总页数超过最大显示数,需要智能显示
if (currentPage <= 3) {
// 当前页在前面显示前4页和最后一页
for (let i = 1; i <= 4; i++) {
pages.push(i);
}
pages.push(-1); // 省略号
pages.push(totalPages);
} else if (currentPage >= totalPages - 2) {
// 当前页在后面显示第一页和后4页
pages.push(1);
pages.push(-1); // 省略号
for (let i = totalPages - 3; i <= totalPages; i++) {
pages.push(i);
}
} else {
// 当前页在中间,显示第一页、当前页前后各一页、最后一页
pages.push(1);
pages.push(-1); // 省略号
for (let i = currentPage - 1; i <= currentPage + 1; i++) {
pages.push(i);
}
pages.push(-2); // 省略号
pages.push(totalPages);
}
}
return pages;
};
return (
<div className="flex items-center justify-between p-4 border-t bg-muted/10">
<div className="text-sm text-muted-foreground">
{startItem} {endItem} {totalCount || 0}
</div>
<div className="flex items-center gap-2">
<Button
variant="outline"
size="sm"
onClick={() => setCurrentPage(currentPage - 1)}
disabled={currentPage === 1}
className="h-9 px-3"
>
<IconChevronLeft className="h-4 w-4 mr-1" />
</Button>
<div className="flex items-center gap-1">
{getPageNumbers().map((page, index) =>
page === -1 || page === -2 ? (
<span key={`ellipsis-${index}`} className="px-2 text-muted-foreground">
...
</span>
) : (
<Button
key={page}
variant={currentPage === page ? 'default' : 'outline'}
size="sm"
onClick={() => setCurrentPage(page)}
className="h-9 w-9"
>
{page}
</Button>
),
)}
</div>
<Button
variant="outline"
size="sm"
onClick={() => setCurrentPage(currentPage + 1)}
disabled={currentPage === totalPages}
className="h-9 px-3"
>
<IconChevronRight className="h-4 w-4 ml-1" />
</Button>
</div>
</div>
);
}