import type { ProTableProps } from '@jetlinks/pro-table'; import ProTable from '@jetlinks/pro-table'; import type { ParamsType } from '@ant-design/pro-provider'; import React, { useCallback, useEffect, useRef, useState } from 'react'; import { isFunction } from 'lodash'; import { Empty, Pagination, Space } from 'antd'; import { AppstoreOutlined, BarsOutlined } from '@ant-design/icons'; import classNames from 'classnames'; import LoadingComponent from '@ant-design/pro-layout/es/PageLoading'; import './index.less'; import { useDomFullHeight } from '@/hooks'; enum ModelEnum { TABLE = 'TABLE', CARD = 'CARD', } const Default_Size = 6; type ModelType = keyof typeof ModelEnum; interface ProTableCardProps { cardRender?: (data: T) => JSX.Element | React.ReactNode; gridColumn?: number; /** * 用于不同分辨率 * gridColumns[0] 1366 ~ 1440 分辨率; * gridColumns[1] 1440 ~ 1600 分辨率; * gridColumns[2] > 1600 分辨率; */ gridColumns?: [number, number, number]; height?: 'none'; } const ProTableCard = < T extends Record, U extends ParamsType = ParamsType, ValueType = 'text', >( props: ProTableCardProps & ProTableProps, ) => { const { cardRender, toolBarRender, request, ...extraProps } = props; const [model, setModel] = useState(ModelEnum.CARD); const [total, setTotal] = useState(0); const [current, setCurrent] = useState(1); // 当前页 const [pageIndex, setPageIndex] = useState(0); const [pageSize, setPageSize] = useState(Default_Size * 2); // 每页条数 const [column, setColumn] = useState(props.gridColumn || 4); const [loading, setLoading] = useState(false); const [dataLength, setDataLength] = useState(0); const domRef = useRef(null); const { minHeight } = useDomFullHeight(domRef); /** * 处理 Card * @param dataSource */ const handleCard = useCallback( (dataSource: readonly T[] | undefined, rowSelection?: any): JSX.Element => { setDataLength(dataSource ? dataSource.length : 0); const Item = (dom: React.ReactNode) => { if (!rowSelection || (rowSelection && !rowSelection.selectedRowKeys)) { return dom; } const { selectedRowKeys, onChange } = rowSelection; // @ts-ignore const id = dom.props.id; // @ts-ignore return React.cloneElement(dom, { // @ts-ignore className: classNames(dom.props.className, { 'item-active': selectedRowKeys && selectedRowKeys.includes(id), }), key: id, onClick: (e: any) => { e.stopPropagation(); if (onChange) { const isSelect = selectedRowKeys.includes(id); if (isSelect) { const nowRowKeys = selectedRowKeys.filter((key: string) => key !== id); onChange( nowRowKeys, dataSource!.filter((item) => nowRowKeys.includes(item.id)), ); } else { const nowRowKeys = [...selectedRowKeys, id]; onChange( nowRowKeys, dataSource!.filter((item) => nowRowKeys.includes(item.id)), ); } } }, }); }; return ( <> {dataSource && dataSource.length ? (
{dataSource.map((item) => cardRender && isFunction(cardRender) ? Item(cardRender(item)) : null, )}
) : (
)} ); }, [minHeight], ); const windowChange = () => { if (window.innerWidth <= 1440) { const _column = props.gridColumn && props.gridColumn < 2 ? props.gridColumn : 2; setColumn(props.gridColumns ? props.gridColumns[0] : _column); } else if (window.innerWidth > 1440 && window.innerWidth <= 1600) { const _column = props.gridColumn && props.gridColumn < 3 ? props.gridColumn : 3; setColumn(props.gridColumns ? props.gridColumns[1] : _column); } else if (window.innerWidth > 1600) { const _column = props.gridColumn && props.gridColumn < 4 ? props.gridColumn : 4; setColumn(props.gridColumns ? props.gridColumns[2] : _column); } }; useEffect(() => { window.addEventListener('resize', windowChange); windowChange(); return () => { window.removeEventListener('resize', windowChange); }; }, [props.gridColumns]); const pageSizeOptions = [Default_Size * 2, Default_Size * 4, Default_Size * 8, Default_Size * 16]; useEffect(() => { setCurrent(1); setPageIndex(0); }, [props.params]); return (
{...extraProps} params={ { ...props.params, current: current, pageIndex: pageIndex, pageSize, } as any } columnEmptyText={''} className={'pro-table-card-body'} options={model === ModelEnum.CARD ? false : props.options} request={async (param, sort, filter) => { if (request) { const resp = await request(param, sort, filter); setLoading(false); setTotal(resp.result ? resp.result.total : 0); return { code: resp.message, result: { data: resp.result ? resp.result.data : [], pageIndex: resp.result ? resp.result.pageIndex : 0, pageSize: resp.result ? resp.result.pageSize : 0, total: resp.result ? resp.result.total : 0, }, status: resp.status, }; } return {}; }} onLoadingChange={(l) => { setLoading(!!l); }} pagination={{ onChange: (page, size) => { setCurrent(page); setPageIndex(page - 1); setPageSize(size); }, pageSize: pageSize, current: current, pageSizeOptions: pageSizeOptions, }} toolBarRender={(action, row) => { const oldBar = toolBarRender ? toolBarRender(action, row) : []; return [ ...oldBar, { setModel(ModelEnum.TABLE); }} > , { setModel(ModelEnum.CARD); }} > , ]; }} tableViewRender={ model === ModelEnum.CARD ? (tableProps) => { return handleCard(tableProps.dataSource, extraProps?.rowSelection); } : undefined } /> {model === ModelEnum.CARD && ( <>
{!!dataLength && ( { setCurrent(page); setPageIndex(page - 1); setPageSize(size); }} pageSizeOptions={pageSizeOptions} pageSize={pageSize} showTotal={(num) => { const minSize = pageIndex * pageSize + 1; const MaxSize = (pageIndex + 1) * pageSize; return `第 ${minSize} - ${MaxSize > num ? num : MaxSize} 条/总共 ${num} 条`; }} /> )} )}
); }; export default ProTableCard;