import React, { useState, useMemo } from 'react'; import { AutoSizer, List } from 'react-virtualized'; import { Mark } from '../mock/collection'; import { TableProps, SortState } from './types'; import './table.css'; // 虚拟滚动常量 const DEFAULT_ROW_HEIGHT = 48; // 每行高度 const HEADER_HEIGHT = 48; // 表头高度 export const Table: React.FC = ({ data, columns, loading = false, rowSelection, virtualScroll, actions, onSort }) => { const rowHeight = virtualScroll?.rowHeight || DEFAULT_ROW_HEIGHT; const [sortState, setSortState] = useState({ field: null, order: null }); // 处理排序 const handleSort = (field: string) => { let newOrder: 'asc' | 'desc' | null = 'asc'; if (sortState.field === field) { if (sortState.order === 'asc') { newOrder = 'desc'; } else if (sortState.order === 'desc') { newOrder = null; } } const newSortState = { field: newOrder ? field : null, order: newOrder }; setSortState(newSortState); onSort?.(newSortState.field!, newSortState.order!); }; // 排序后的数据 const sortedData = useMemo(() => { if (!sortState.field || !sortState.order) return data; return [...data].sort((a, b) => { const aVal = getNestedValue(a, sortState.field!); const bVal = getNestedValue(b, sortState.field!); if (aVal < bVal) return sortState.order === 'asc' ? -1 : 1; if (aVal > bVal) return sortState.order === 'asc' ? 1 : -1; return 0; }); }, [data, sortState]); // 当前显示的数据(移除分页,直接使用排序后的数据) const displayData = sortedData; // 全选/取消全选 const handleSelectAll = (checked: boolean) => { if (!rowSelection) return; const allKeys = displayData.map(item => item.id); const selectedKeys = checked ? allKeys : []; const selectedRows = checked ? displayData : []; rowSelection.onChange?.(selectedKeys, selectedRows); }; // 单行选择 const handleRowSelect = (record: Mark, checked: boolean) => { if (!rowSelection) return; const currentKeys = rowSelection.selectedRowKeys || []; const newKeys = checked ? [...currentKeys, record.id] : currentKeys.filter(key => key !== record.id); const selectedRows = data.filter(item => newKeys.includes(item.id)); rowSelection.onChange?.(newKeys, selectedRows); }; // 获取嵌套值 const getNestedValue = (obj: any, path: string) => { return path.split('.').reduce((o, p) => o?.[p], obj); }; // 渲染虚拟滚动行 const rowRenderer = ({ index, key, style }: any) => { const record = displayData[index]; return (
{rowSelection && (
handleRowSelect(record, e.target.checked)} disabled={rowSelection.getCheckboxProps?.(record)?.disabled} />
)} {columns.map(column => (
{column.render ? column.render(getNestedValue(record, column.dataIndex), record, index) : getNestedValue(record, column.dataIndex) }
))} {actions && actions.length > 0 && (
{actions.map(action => ( ))}
)}
); }; if (loading) { return (
加载中...
); } const selectedKeys = rowSelection?.selectedRowKeys || []; const isAllSelected = displayData.length > 0 && displayData.every(item => selectedKeys.includes(item.id)); const isIndeterminate = selectedKeys.length > 0 && !isAllSelected; return (
{/* 表格工具栏 */} {rowSelection && selectedKeys.length > 0 && (
已选择 {selectedKeys.length} 项
)} {/* 表格 */}
{/* 固定表头 */}
{rowSelection && (
{ if (input) input.indeterminate = isIndeterminate; }} onChange={(e) => handleSelectAll(e.target.checked)} />
)} {columns.map(column => (
{column.title} {column.sortable && (
handleSort(column.dataIndex)} >
)}
))} {actions && actions.length > 0 && (
操作
)}
{/* 虚拟滚动内容区域 */}
{displayData.length > 0 ? ( {({ height, width }) => ( )} ) : (
📭

暂无数据

)}
); };