import { App, Button, Dropdown, Table } from "antd"; import type { ButtonProps, MenuProps, TableProps } from "antd"; import { saveAs } from "file-saver"; import { CheckSquare2, ChevronDown, ChevronLeft, ChevronRight, Download, ListFilter, RotateCcw, SearchX, X } from "lucide-react"; import { useEffect, useState, type ReactNode } from "react"; import { cn } from "@/lib/utils"; import { Select } from "@/components/ui/base/select"; export const configuredSecretText = "已配置 · 留空不改"; export type AdminStatusTone = "neutral" | "success" | "warning" | "error" | "info"; export function AdminStatusBadge({ label, tone = "neutral", title }: { label: string; tone?: AdminStatusTone; title?: string; variant?: string }) { return ( {label} ); } export function AdminStatTile({ label, value, detail, trend }: { label: string; value: string | number; detail?: string; trend?: { value: string; tone?: AdminStatusTone } }) { return (
{label}
{value}
{trend || detail ? (
{trend ? : null} {trend && detail ? · : null} {detail ? {detail} : null}
) : null}
); } export function ListToolbar({ children, filters, filtersAlwaysVisible = false, activeFilters, trailing, active, onReset, className, }: { children: ReactNode; filters?: ReactNode; filtersAlwaysVisible?: boolean; activeFilters?: ReactNode; trailing?: ReactNode; active?: boolean; onReset?: () => void; className?: string; }) { const [filtersOpen, setFiltersOpen] = useState(false); useEffect(() => { if (active) setFiltersOpen(true); }, [active]); return (
{children} {filters ? ( <> {!filtersAlwaysVisible ? ( ) : null}
{filters}
) : null} {activeFilters ?
{activeFilters}
: null}
{active && onReset ? ( ) : null} {trailing}
); } function pageItems(current: number, pages: number): Array { if (pages <= 7) return Array.from({ length: pages }, (_, index) => index + 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, itemLabel = "条", }: { current: number; pageSize: number; total: number; onChange: (page: number, pageSize: number) => void; pageSizeOptions?: number[]; alwaysShow?: boolean; itemLabel?: string; }) { 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(total, current * pageSize); const items = pageItems(current, pages); return (
{total === 0 ? `共 0 ${itemLabel}` : `${start}-${end} / 共 ${total} ${itemLabel}`}