import { type AccessorKeyColumnDef, type Column, type ColumnDef, flexRender, getCoreRowModel, useReactTable, } from "@tanstack/react-table" import { Loader } from "lucide-react" import type { CSSProperties } from "react" import { Pagination, type PaginationProps } from "@/components/ui/pagination" import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "@/components/ui/table" import { cn } from "@/lib/utils" export type DataTableProps = { data: T[] status: "load" | "done" | "fail" columns: ColumnDef[] pagination?: PaginationProps classNames?: { root?: string headRow?: string dataRow?: string } serial?: boolean } export function DataTable>( props: DataTableProps, ) { const table = useReactTable({ data: props.data, columns: [ { id: "serial", header: "#", cell: ({ row }) => row.index + 1, }, ...props.columns, ], getCoreRowModel: getCoreRowModel(), manualPagination: true, rowCount: props.pagination?.total, state: { pagination: props.pagination && { pageIndex: props.pagination.page, pageSize: props.pagination.size, }, columnFilters: [], }, initialState: { columnPinning: { left: props.columns .map(column => (column.meta as Record)?.pin === "left" ? column.id || (column as AccessorKeyColumnDef).accessorKey : undefined, ) .filter(Boolean) as string[], right: props.columns .map(column => (column.meta as Record)?.pin === "right" ? column.id || (column as AccessorKeyColumnDef).accessorKey : undefined, ) .filter(Boolean) as string[], }, }, }) const pinStyle = (column: Column, header?: boolean) => { const pinned = column.getIsPinned() if (!pinned) return {} return { left: { left: column.getStart(pinned), boxShadow: header ? "inset -1px -1px var(--border)" : "inset -1px 0 var(--border)", } as CSSProperties, right: { right: column.getAfter(pinned), boxShadow: header ? "inset 1px -1px var(--border)" : "inset 1px 0 var(--border)", } as CSSProperties, }[pinned] } 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 && ( )}
) }