DataTablePagination.tsx 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. import React from 'react';
  2. import {
  3. Pagination,
  4. PaginationContent,
  5. PaginationEllipsis,
  6. PaginationItem,
  7. PaginationLink,
  8. PaginationNext,
  9. PaginationPrevious,
  10. } from '@/client/components/ui/pagination';
  11. interface DataTablePaginationProps {
  12. currentPage: number;
  13. totalCount: number;
  14. pageSize: number;
  15. onPageChange: (page: number, pageSize: number) => void;
  16. }
  17. export const DataTablePagination: React.FC<DataTablePaginationProps> = ({
  18. currentPage,
  19. totalCount,
  20. pageSize,
  21. onPageChange,
  22. }) => {
  23. const totalPages = Math.ceil(totalCount / pageSize);
  24. const getPageNumbers = () => {
  25. const pages = [];
  26. if (totalPages <= 7) {
  27. // 如果总页数小于等于7,显示所有页码
  28. for (let i = 1; i <= totalPages; i++) {
  29. pages.push(i);
  30. }
  31. } else {
  32. // 显示当前页附近的页码
  33. const startPage = Math.max(1, currentPage - 2);
  34. const endPage = Math.min(totalPages, currentPage + 2);
  35. // 始终显示第一页
  36. pages.push(1);
  37. // 添加省略号和中间页码
  38. if (startPage > 2) {
  39. pages.push('...');
  40. }
  41. for (let i = Math.max(2, startPage); i <= Math.min(totalPages - 1, endPage); i++) {
  42. pages.push(i);
  43. }
  44. if (endPage < totalPages - 1) {
  45. pages.push('...');
  46. }
  47. // 始终显示最后一页
  48. pages.push(totalPages);
  49. }
  50. return pages;
  51. };
  52. const pageNumbers = getPageNumbers();
  53. return (
  54. <div className="flex justify-between items-center mt-4">
  55. <div className="text-sm text-muted-foreground">
  56. 第 {currentPage} 页,共 {totalPages} 页,共 {totalCount} 条记录
  57. </div>
  58. <Pagination>
  59. <PaginationContent>
  60. <PaginationItem>
  61. <PaginationPrevious
  62. href="#"
  63. onClick={(e) => {
  64. e.preventDefault();
  65. if (currentPage > 1) {
  66. onPageChange(currentPage - 1, pageSize);
  67. }
  68. }}
  69. aria-disabled={currentPage <= 1}
  70. className={currentPage <= 1 ? "pointer-events-none opacity-50" : ""}
  71. >
  72. 上一页
  73. </PaginationPrevious>
  74. </PaginationItem>
  75. {pageNumbers.map((page, index) => {
  76. if (page === '...') {
  77. return (
  78. <PaginationItem key={`ellipsis-${index}`}>
  79. <PaginationEllipsis />
  80. </PaginationItem>
  81. );
  82. }
  83. return (
  84. <PaginationItem key={page}>
  85. <PaginationLink
  86. href="#"
  87. isActive={page === currentPage}
  88. onClick={(e) => {
  89. e.preventDefault();
  90. onPageChange(page as number, pageSize);
  91. }}
  92. >
  93. {page}
  94. </PaginationLink>
  95. </PaginationItem>
  96. );
  97. })}
  98. <PaginationItem>
  99. <PaginationNext
  100. href="#"
  101. onClick={(e) => {
  102. e.preventDefault();
  103. if (currentPage < totalPages) {
  104. onPageChange(currentPage + 1, pageSize);
  105. }
  106. }}
  107. aria-disabled={currentPage >= totalPages}
  108. className={currentPage >= totalPages ? "pointer-events-none opacity-50" : ""}
  109. >
  110. 下一页
  111. </PaginationNext>
  112. </PaginationItem>
  113. </PaginationContent>
  114. </Pagination>
  115. </div>
  116. );
  117. };