Files
leaudit-platform-frontend/app/components/ui/Pagination.tsx
T

111 lines
3.4 KiB
TypeScript

// app/components/ui/Pagination.tsx
interface PaginationProps {
currentPage: number;
total: number;
pageSize: number;
onChange: (page: number) => void;
onPageSizeChange?: (pageSize: number) => void;
pageSizeOptions?: number[];
showTotal?: boolean;
showPageSizeChanger?: boolean;
}
export function Pagination({
currentPage,
total,
pageSize,
onChange,
onPageSizeChange,
pageSizeOptions = [10, 20, 50],
showTotal = true,
showPageSizeChanger = true
}: PaginationProps) {
const totalPages = Math.ceil(total / pageSize);
// 生成页码数组
const getPageNumbers = () => {
const pages = [];
const maxVisiblePages = 5;
if (totalPages <= maxVisiblePages) {
// 总页数小于等于最大可见页数,显示所有页码
for (let i = 1; i <= totalPages; i++) {
pages.push(i);
}
} else if (currentPage <= 3) {
// 当前页靠近开始
for (let i = 1; i <= maxVisiblePages; i++) {
pages.push(i);
}
} else if (currentPage >= totalPages - 2) {
// 当前页靠近结尾
for (let i = totalPages - maxVisiblePages + 1; i <= totalPages; i++) {
pages.push(i);
}
} else {
// 当前页在中间
for (let i = currentPage - 2; i <= currentPage + 2; i++) {
pages.push(i);
}
}
return pages;
};
return (
<div className="flex flex-wrap justify-between items-center p-4 gap-4">
{showTotal && (
<div className="ant-pagination-options">
<span className="text-sm font-normal"> {total} </span>
{onPageSizeChange && showPageSizeChanger && (
<div className="flex items-center ml-3">
<select
className="form-select ant-pagination-options-size-changer"
value={pageSize}
onChange={(e) => onPageSizeChange(Number(e.target.value))}
aria-label="每页显示条数"
>
{pageSizeOptions.map(size => (
<option key={size} value={size}>{size} /</option>
))}
</select>
</div>
)}
</div>
)}
<div className="ant-pagination">
<button
className={`ant-pagination-item ant-pagination-prev ${currentPage <= 1 ? 'ant-pagination-disabled' : ''}`}
onClick={() => currentPage > 1 && onChange(currentPage - 1)}
disabled={currentPage <= 1}
aria-label="上一页"
>
<i className="ri-arrow-left-s-line"></i>
</button>
{getPageNumbers().map(page => (
<button
key={page}
className={`ant-pagination-item ${page === currentPage ? 'ant-pagination-item-active' : ''}`}
onClick={() => onChange(page)}
aria-label={`${page}`}
aria-current={page === currentPage ? 'page' : undefined}
>
{page}
</button>
))}
<button
className={`ant-pagination-item ant-pagination-next ${currentPage >= totalPages ? 'ant-pagination-disabled' : ''}`}
onClick={() => currentPage < totalPages && onChange(currentPage + 1)}
disabled={currentPage >= totalPages}
aria-label="下一页"
>
<i className="ri-arrow-right-s-line"></i>
</button>
</div>
</div>
);
}