update:添加分页、成员添加优化
This commit is contained in:
@@ -0,0 +1,117 @@
|
||||
import { ChevronLeft, ChevronRight } from "lucide-react";
|
||||
|
||||
import { Button } from "~/components/ui/button";
|
||||
|
||||
/** Build a compact page number list with ellipsis, e.g. 1 … 4 5 6 … 20 */
|
||||
function visiblePages(current: number, total: number): Array<number | "ellipsis"> {
|
||||
if (total <= 7) {
|
||||
return Array.from({ length: total }, (_, index) => index + 1);
|
||||
}
|
||||
const pages = new Set<number>([1, total, current, current - 1, current + 1]);
|
||||
if (current <= 3) {
|
||||
pages.add(2);
|
||||
pages.add(3);
|
||||
pages.add(4);
|
||||
}
|
||||
if (current >= total - 2) {
|
||||
pages.add(total - 1);
|
||||
pages.add(total - 2);
|
||||
pages.add(total - 3);
|
||||
}
|
||||
const sorted = [...pages].filter((p) => p >= 1 && p <= total).sort((a, b) => a - b);
|
||||
const result: Array<number | "ellipsis"> = [];
|
||||
for (const page of sorted) {
|
||||
const prev = result[result.length - 1];
|
||||
if (typeof prev === "number" && page - prev > 1) {
|
||||
result.push("ellipsis");
|
||||
}
|
||||
result.push(page);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
export function AdminPagination({
|
||||
page,
|
||||
totalPages,
|
||||
totalCount,
|
||||
loading,
|
||||
hasMore,
|
||||
canGoToPage,
|
||||
onPrev,
|
||||
onNext,
|
||||
onGoToPage,
|
||||
}: {
|
||||
page: number;
|
||||
totalPages: number;
|
||||
totalCount: number;
|
||||
loading?: boolean;
|
||||
hasMore: boolean;
|
||||
canGoToPage: (page: number) => boolean;
|
||||
onPrev: () => void;
|
||||
onNext: () => void;
|
||||
onGoToPage: (page: number) => void;
|
||||
}) {
|
||||
if (totalCount === 0) return null;
|
||||
|
||||
const pages = visiblePages(page, totalPages);
|
||||
|
||||
return (
|
||||
<div className="mt-3 flex flex-wrap items-center justify-between gap-2 text-[11px] text-[#5d7186]">
|
||||
<span>
|
||||
共 <strong className="text-[#27394d]">{totalCount}</strong> 条,第 {page}/{totalPages} 页
|
||||
</span>
|
||||
<div className="flex items-center gap-1">
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
size="xs"
|
||||
disabled={loading || page <= 1}
|
||||
onClick={onPrev}
|
||||
className="h-7 gap-0.5 rounded-[5px] border-[#d9e3ec] bg-white px-2 text-[11px] text-[#4c6c88]"
|
||||
>
|
||||
<ChevronLeft size={14} />
|
||||
上一页
|
||||
</Button>
|
||||
{pages.map((item, index) =>
|
||||
item === "ellipsis" ? (
|
||||
<span key={`e-${index}`} className="px-1 text-[#94a2b3]">
|
||||
…
|
||||
</span>
|
||||
) : (
|
||||
<Button
|
||||
key={item}
|
||||
type="button"
|
||||
variant="outline"
|
||||
size="xs"
|
||||
disabled={loading || !canGoToPage(item)}
|
||||
onClick={() => onGoToPage(item)}
|
||||
className={`h-7 min-w-7 rounded-[5px] px-2 text-[11px] ${
|
||||
item === page
|
||||
? "border-brand bg-brand-soft font-semibold text-brand"
|
||||
: "border-[#d9e3ec] bg-white text-[#4c6c88] disabled:opacity-40"
|
||||
}`}
|
||||
title={
|
||||
canGoToPage(item)
|
||||
? undefined
|
||||
: "请先通过上一页/下一页依次访问该页"
|
||||
}
|
||||
>
|
||||
{item}
|
||||
</Button>
|
||||
),
|
||||
)}
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
size="xs"
|
||||
disabled={loading || !hasMore}
|
||||
onClick={onNext}
|
||||
className="h-7 gap-0.5 rounded-[5px] border-[#d9e3ec] bg-white px-2 text-[11px] text-[#4c6c88]"
|
||||
>
|
||||
下一页
|
||||
<ChevronRight size={14} />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user