109 lines
2.9 KiB
TypeScript
Executable File
109 lines
2.9 KiB
TypeScript
Executable File
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>
|
||
);
|
||
}
|