refactor(web): 工作区布局与技能库 - 完成侧栏导航、分页与卡片一致性改造

This commit is contained in:
ddCat committed 2026-08-20 10:15:44 +08:00
commit 6228e530a9
16 files changed
+1331 -650

No files matched your search

+28 -13
View File
@@ -1,5 +1,5 @@
import { Button, Pagination } from "antd";
import { ListFilter, RotateCcw } from "lucide-react";
import { Button, Select } from "antd";
import { ChevronLeft, ChevronRight, ListFilter, RotateCcw } from "lucide-react";
import type { ReactNode } from "react";
import { useEffect, useState } from "react";
@@ -67,24 +67,39 @@ export function CollectionGrid({ children, className }: { children: ReactNode; c
return <div className={cn("mt-4 grid grid-cols-1 gap-4 sm:grid-cols-[repeat(auto-fill,minmax(248px,1fr))]", className)}>{children}</div>;
}
/* 自研轻量分页:页码胶囊 + 省略号 + 每页条数 + 总数,替代 AntD Pagination(无 AntD 残留样式,与工具栏容器同语言)。 */
function pageItems(current: number, pages: number): (number | "…")[] {
if (pages <= 7) return Array.from({ length: pages }, (_, i) => i + 1);
if (current <= 4) return [1, 2, 3, 4, 5, "…", pages];
if (current >= pages - 3) return [1, "…", pages - 4, pages - 3, pages - 2, pages - 1, pages];
return [1, "…", current - 1, current, current + 1, "…", pages];
}
export function PaginationBar({ current, pageSize, total, onChange, pageSizeOptions = [20, 50, 100], alwaysShow = false }: { current: number; pageSize: number; total: number; onChange: (page: number, pageSize: number) => void; pageSizeOptions?: number[]; alwaysShow?: boolean }) {
if (!alwaysShow && total <= pageSize && current === 1) return null;
const pages = Math.max(1, Math.ceil(total / pageSize));
const start = total === 0 ? 0 : (current - 1) * pageSize + 1;
const end = total === 0 ? 0 : Math.min(current * pageSize, total);
const end = total === 0 ? 0 : Math.min(total, current * pageSize);
const items = pageItems(current, pages);
return (
<div className="app-pagination-bar admin-pagination-bar min-w-0">
<div className="app-pagination-bar admin-pagination-bar mt-4 flex min-h-10 min-w-0 items-center justify-end gap-2 px-2 py-1.5">
<span className="admin-pagination-total">{total === 0 ? "共 0 条" : `${start}-${end} / 共 ${total} 条`}</span>
<Pagination
<Select
size="small"
current={current}
pageSize={pageSize}
total={total}
showSizeChanger={pageSizeOptions.length > 1}
responsive
showLessItems
pageSizeOptions={pageSizeOptions.map(String)}
onChange={onChange}
value={pageSize}
className="app-pagination-size"
options={pageSizeOptions.map((size) => ({ value: size, label: `${size} 条/页` }))}
onChange={(value) => onChange(1, Number(value))}
/>
<div className="app-pagination-pages" role="navigation" aria-label="分页">
<button type="button" className="app-pagination-btn app-pagination-prev" disabled={current <= 1} aria-label="上一页" onClick={() => onChange(current - 1, pageSize)}><ChevronLeft className="size-4" /></button>
{items.map((item) => item === "…" ? (
<span key={`ellipsis-${items.indexOf(item)}`} className="app-pagination-ellipsis">…</span>
) : (
<button key={item} type="button" className={`app-pagination-btn${item === current ? " is-active" : ""}`} aria-current={item === current ? "page" : undefined} onClick={() => onChange(item, pageSize)}>{item}</button>
))}
<button type="button" className="app-pagination-btn app-pagination-next" disabled={current >= pages} aria-label="下一页" onClick={() => onChange(current + 1, pageSize)}><ChevronRight className="size-4" /></button>
</div>
</div>
);
}