import { type ColumnDef, flexRender, getCoreRowModel, useReactTable, } from "@tanstack/react-table" import { Loader } from "lucide-react" import { useMemo } from "react" import { Checkbox } from "@/components/ui/checkbox" import { Pagination, type PaginationProps } from "@/components/ui/pagination" import { TableBody, TableCell, TableHead, TableHeader, Table as TableRoot, TableRow, } from "@/components/ui/table" import { cn } from "@/lib/utils" export type DataTableProps = { data: T[] status: "load" | "done" | "fail" columns: ColumnDef[] pagination?: PaginationProps classNames?: { headRow?: string dataRow?: string } enableSelection?: boolean rowSelection?: Record onSelectionChange?: (selection: Record) => void getRowId?: (row: T, index: number) => string stickyHeader?: boolean maxHeight?: string } export default function DataTable>( props: DataTableProps, ) { // 动态注入复选框列 const finalColumns = useMemo[]>(() => { if (!props.enableSelection) return props.columns const selectColumn: ColumnDef = { id: "select", size: 40, enableSorting: false, enableHiding: false, header: ({ table }) => ( table.toggleAllPageRowsSelected(!!value)} aria-label="全选当前页" className="rounded-none translate-y-0.5" /> ), cell: ({ row }) => ( row.toggleSelected(!!value)} aria-label="选择行" className="rounded-none translate-y-0.5" /> ), } return [selectColumn, ...props.columns] }, [props.enableSelection, props.columns]) const table = useReactTable({ data: props.data, columns: finalColumns, getCoreRowModel: getCoreRowModel(), manualPagination: true, rowCount: props.pagination?.total ?? props.data.length, // 行选择核心配置 enableRowSelection: props.enableSelection ?? false, getRowId: props.getRowId, onRowSelectionChange: updaterOrValue => { if (!props.onSelectionChange) return const newSelection = typeof updaterOrValue === "function" ? updaterOrValue(props.rowSelection ?? {}) : updaterOrValue props.onSelectionChange(newSelection) }, state: { pagination: { pageIndex: props.pagination?.page ?? 0, pageSize: props.pagination?.size ?? props.data.length, }, columnFilters: [], ...(props.rowSelection !== undefined && { rowSelection: props.rowSelection, }), }, autoResetPageIndex: false, }) return ( <> {/* 数据表 */}
{table.getHeaderGroups().map(group => ( {group.headers.map(header => ( {header.isPlaceholder ? null : flexRender( header.column.columnDef.header, header.getContext(), )} ))} ))} {props.status === "fail" ? ( 加载失败 ) : !props.data?.length ? ( 暂无数据 ) : ( table.getRowModel().rows.map(row => ( {row.getVisibleCells().map(cell => ( {flexRender( cell.column.columnDef.cell, cell.getContext(), )} ))} )) )} {props.status === "load" && (
加载中
)}
{/* 分页器 */} {props.pagination && } ) }