Files
jiang13-bbs/frontend/components/Pagination.tsx
freefire 40bbad2c82 公开页补齐自引用 Canonical 与按类型的结构化数据,图片补上说明文字。
后台设置和内容编辑改成可导航布局;部署用访客 origin 生成 Canonical,避免落到容器地址。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-20 00:11:24 +08:00

94 lines
2.5 KiB
TypeScript

"use client";
import Link from "next/link";
import { ChevronLeft, ChevronRight } from "lucide-react";
interface PaginationProps {
total: number;
page: number;
size: number;
basePath: string;
query?: Record<string, string>;
onChange?: (page: number) => void;
}
export default function Pagination({ total, page, size, basePath, query = {}, onChange }: PaginationProps) {
const totalPages = Math.max(1, Math.ceil(total / size));
if (totalPages <= 1) return null;
const buildHref = (p: number) => {
const params = new URLSearchParams(query);
if (p > 1) params.set("page", String(p));
else params.delete("page");
const qs = params.toString();
return qs ? `${basePath}?${qs}` : basePath;
};
const handleClick = (p: number, e: React.MouseEvent) => {
if (onChange) {
e.preventDefault();
onChange(p);
}
};
const pages: (number | "...")[] = [];
const add = (p: number | "...") => pages.push(p);
if (totalPages <= 7) {
for (let i = 1; i <= totalPages; i++) add(i);
} else {
add(1);
if (page > 4) add("...");
const start = Math.max(2, page - 1);
const end = Math.min(totalPages - 1, page + 1);
for (let i = start; i <= end; i++) add(i);
if (page < totalPages - 3) add("...");
add(totalPages);
}
const cls =
"pager-btn min-w-[38px] h-9 px-1 flex items-center justify-center font-semibold text-[13px] rounded-full border transition-colors duration-150";
return (
<nav className="flex items-center justify-center gap-1.5 mt-10 flex-wrap" aria-label="分页">
{page > 1 && (
<Link
href={buildHref(page - 1)}
onClick={(e) => handleClick(page - 1, e)}
className={`${cls} px-3 gap-1`}
>
<ChevronLeft size={14} /> 上一页
</Link>
)}
{pages.map((p, i) =>
p === "..." ? (
<span key={`e${i}`} className="px-1 meta">
—
</span>
) : (
<Link
key={p}
href={buildHref(p)}
onClick={(e) => handleClick(p, e)}
aria-current={p === page ? "page" : undefined}
className={`${cls} ${p === page ? "is-current" : ""}`}
>
{p}
</Link>
)
)}
{page < totalPages && (
<Link
href={buildHref(page + 1)}
onClick={(e) => handleClick(page + 1, e)}
className={`${cls} px-3 gap-1`}
>
下一页 <ChevronRight size={14} />
</Link>
)}
</nav>
);
}