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

109 lines
2.9 KiB
TypeScript
Executable File
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.

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>
);
}