| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178 |
- import React from 'react';
- import { useSearchParams } from 'react-router-dom';
- interface PaginationProps {
- total: number;
- totalPages: number;
- currentPage: number;
- onPageChange?: (page: number) => void;
- showTotal?: boolean;
- scrollToTop?: boolean;
- pageSize?: number;
- pageSizeOptions?: number[];
- onPageSizeChange?: (size: number) => void;
- }
- const Pagination: React.FC<PaginationProps> = ({
- total,
- totalPages,
- currentPage,
- onPageChange,
- showTotal = true,
- scrollToTop = true,
- pageSize = 10,
- pageSizeOptions = [],
- onPageSizeChange,
- }) => {
- const [searchParams, setSearchParams] = useSearchParams();
- // 更新 URL 页码的辅助函数
- const updatePageInUrl = (page: number) => {
- setSearchParams(prev => {
- const newParams = new URLSearchParams(prev);
- if (page === 1) {
- newParams.delete('page');
- } else {
- newParams.set('page', page.toString());
- }
- return newParams;
- });
- // 如果提供了自定义的 onPageChange 回调,也调用它
- if (onPageChange) onPageChange(page);
- // 滚动到顶部
- if (scrollToTop) {
- const mainElement = document.querySelector('main');
- if (mainElement) {
- mainElement.scrollTop = 0;
- }
- }
- };
- // 如果只有一页,不显示分页
- if (totalPages <= 1 && (!pageSizeOptions || pageSizeOptions.length === 0)) {
- return null;
- }
- // 生成页码数组
- const generatePages = (): (number | string)[] => {
- const pages: (number | string)[] = [];
-
- if (totalPages <= 7) {
- // 如果总页数少于等于7,显示所有页码
- for (let i = 1; i <= totalPages; i++) {
- pages.push(i);
- }
- } else {
- // 如果总页数大于7,显示带省略号的页码
- if (currentPage <= 3) {
- // 当前页在前3页
- for (let i = 1; i <= 4; i++) {
- pages.push(i);
- }
- pages.push('...');
- pages.push(totalPages);
- } else if (currentPage >= totalPages - 2) {
- // 当前页在后3页
- pages.push(1);
- pages.push('...');
- for (let i = totalPages - 3; i <= totalPages; i++) {
- pages.push(i);
- }
- } else {
- // 当前页在中间
- pages.push(1);
- pages.push('...');
- for (let i = currentPage - 1; i <= currentPage + 1; i++) {
- pages.push(i);
- }
- pages.push('...');
- pages.push(totalPages);
- }
- }
-
- return pages;
- };
- const pages = generatePages();
- return (
- <div className="flex items-center justify-center gap-2 mt-6">
- {showTotal && (
- <span className="text-sm text-gray-600 mr-2">
- 共{total}条
- </span>
- )}
- {pageSizeOptions && pageSizeOptions.length > 0 && (
- <div className="flex items-center gap-2 mr-4">
- <span className="text-sm text-gray-600">每页</span>
- <select
- value={pageSize}
- onChange={(e) => {
- const size = Number(e.target.value);
- if (onPageSizeChange) onPageSizeChange(size);
- // 重置到第一页
- updatePageInUrl(1);
- }}
- className="border border-gray-200 rounded-lg px-2 py-1 text-sm"
- >
- {pageSizeOptions.map((opt) => (
- <option key={opt} value={opt}>{opt}</option>
- ))}
- </select>
- </div>
- )}
- <div className="flex items-center gap-1">
- {pages.map((page, index) => {
- if (page === '...') {
- return (
- <span key={`ellipsis-${index}`} className="px-2 text-gray-400">
- …
- </span>
- );
- }
- const pageNum = page as number;
- return (
- <button
- key={pageNum}
- onClick={() => updatePageInUrl(pageNum)}
- className={`px-3 py-1.5 text-sm font-bold rounded-lg transition-colors ${
- pageNum === currentPage
- ? 'bg-blue-600 text-white'
- : 'bg-white border border-gray-200 text-gray-600 hover:bg-gray-50'
- }`}
- >
- {pageNum}
- </button>
- );
- })}
- </div>
- <button
- onClick={() => {
- if (currentPage > 1) {
- updatePageInUrl(currentPage - 1);
- }
- }}
- disabled={currentPage === 1}
- className="px-4 py-2 bg-white border border-gray-200 rounded-lg text-sm font-bold disabled:opacity-50 disabled:cursor-not-allowed hover:bg-gray-50 transition-colors"
- >
- 上一页
- </button>
- <button
- onClick={() => {
- if (currentPage < totalPages) {
- updatePageInUrl(currentPage + 1);
- }
- }}
- disabled={currentPage === totalPages}
- className="px-4 py-2 bg-white border border-gray-200 rounded-lg text-sm font-bold disabled:opacity-50 disabled:cursor-not-allowed hover:bg-gray-50 transition-colors"
- >
- 下一页
- </button>
- </div>
- );
- };
- export default Pagination;
|