118 lines
3.4 KiB
TypeScript
118 lines
3.4 KiB
TypeScript
import { Table } from "antd";
|
|
import type { ColumnsType, TablePaginationConfig, TableRowSelection } from "antd/es/table";
|
|
import "./ListTable.css";
|
|
|
|
export type ListTableProps<T extends Record<string, any>> = {
|
|
columns: ColumnsType<T>;
|
|
dataSource: T[];
|
|
rowKey?: string;
|
|
selectedRowKeys?: React.Key[];
|
|
onSelectionChange?: (keys: React.Key[]) => void;
|
|
isAllPagesSelected?: boolean;
|
|
totalCount?: number;
|
|
onSelectAllPages?: () => void;
|
|
onClearSelection?: () => void;
|
|
pagination?: TablePaginationConfig | false;
|
|
scroll?: { x?: number | true | string };
|
|
onRowClick?: (record: T) => void;
|
|
selectedRow?: T | null;
|
|
loading?: boolean;
|
|
className?: string;
|
|
};
|
|
|
|
function ListTable<T extends Record<string, any>>({
|
|
columns,
|
|
dataSource,
|
|
rowKey = "id",
|
|
selectedRowKeys = [],
|
|
onSelectionChange,
|
|
isAllPagesSelected = false,
|
|
totalCount,
|
|
onSelectAllPages,
|
|
onClearSelection,
|
|
pagination = {
|
|
pageSize: 10,
|
|
showSizeChanger: true,
|
|
showQuickJumper: true,
|
|
},
|
|
scroll = { x: 1200 },
|
|
onRowClick,
|
|
selectedRow,
|
|
loading = false,
|
|
className = "",
|
|
}: ListTableProps<T>) {
|
|
const rowSelection: TableRowSelection<T> | undefined = onSelectionChange
|
|
? {
|
|
selectedRowKeys,
|
|
onChange: (newSelectedRowKeys) => {
|
|
onSelectionChange?.(newSelectedRowKeys);
|
|
},
|
|
getCheckboxProps: () => ({
|
|
disabled: isAllPagesSelected,
|
|
}),
|
|
}
|
|
: undefined;
|
|
|
|
const mergedPagination =
|
|
pagination === false
|
|
? false
|
|
: {
|
|
...pagination,
|
|
showTotal: (total: number) => (
|
|
<div className="table-selection-info">
|
|
{isAllPagesSelected ? (
|
|
<>
|
|
<span className="selection-count">
|
|
已选择 <span className="count-highlight">{totalCount || total}</span> 项
|
|
</span>
|
|
{onClearSelection && (
|
|
<a onClick={onClearSelection} className="selection-action">
|
|
清除选择
|
|
</a>
|
|
)}
|
|
</>
|
|
) : selectedRowKeys.length > 0 ? (
|
|
<>
|
|
<span className="selection-count">
|
|
已选择 <span className="count-highlight">{selectedRowKeys.length}</span> 项
|
|
</span>
|
|
{onSelectAllPages && selectedRowKeys.length < (totalCount || total) && (
|
|
<a onClick={onSelectAllPages} className="selection-action">
|
|
选择全部 {totalCount || total} 项
|
|
</a>
|
|
)}
|
|
{onClearSelection && (
|
|
<a onClick={onClearSelection} className="selection-action">
|
|
清除
|
|
</a>
|
|
)}
|
|
</>
|
|
) : (
|
|
<span className="selection-count">已选择 0 项</span>
|
|
)}
|
|
</div>
|
|
),
|
|
};
|
|
|
|
return (
|
|
<div className={`list-table-container ${className}`}>
|
|
<Table
|
|
size="middle"
|
|
rowSelection={rowSelection}
|
|
columns={columns}
|
|
dataSource={dataSource}
|
|
rowKey={rowKey}
|
|
pagination={mergedPagination}
|
|
scroll={scroll}
|
|
loading={loading}
|
|
onRow={(record) => ({
|
|
onClick: () => onRowClick?.(record),
|
|
className: selectedRow?.[rowKey] === record[rowKey] ? "row-selected" : "",
|
|
})}
|
|
/>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export default ListTable;
|