赞
踩
cnpm i react-resizable --save
cnpm i ahooks
cnpm i --save-dev @types/react-resizable
import React, { useEffect, useMemo, useRef, useState, useCallback } from 'react'; import { createUseStyles } from 'react-jss'; import { Resizable } from 'react-resizable'; import { ColumnType } from 'antd/lib/table'; import { Table, Button } from 'antd'; import type { ButtonProps, TableProps } from 'antd'; import { useSize } from 'ahooks'; export interface ICommonTableProps<RecordType> extends TableProps<RecordType> { onCreate?: () => void; onEdit?: () => void; deleteBtn?: { props?: ButtonProps; onDelete?: () => void; }; isDrag?: boolean; // 控制table是否展示 可拖拽的表头 } const useCommonTableStyles = createUseStyles({ wrapper: { background: '#fff', marginTop: '12px', padding: '12px 12px' }, header: { display: 'flex', marginTop: '8px', marginBottom: '20px' }, tablActions: { display: 'flex', flex: 1, justifyContent: 'flex-end', alignItems: 'center' }, headerBtn: { marginLeft: '16px' }, resizableHandle : { position: 'absolute', right: '-5px', bottom: 0, zIndex: 1, width: '10px', height: '100%', cursor: 'col-resize' } }); // 表头拖拽组件 const ResizableTitle = (props: any ) => { const { onResize, width, ...restProps } = props const classes = useCommonTableStyles(); if (!width) { return (<th {...restProps} />) }; return ( <Resizable width={parseInt(width)} height={0} handle={ <span className={classes.resizableHandle} onClick={e => { e.stopPropagation() }} /> } onResize={onResize} draggableOpts={{ enableUserSelectHack: false }} > <th {...restProps} style={{ ...restProps?.style, userSelect: 'none' }} /> </Resizable> ); }; export const CommonTable = <RecordType extends Record<string, any> = any>( props: ICommonTableProps<RecordType> ) => { const { onCreate, onEdit, deleteBtn, isDrag = true } = props; const classes = useCommonTableStyles(); const wrapperRef = useRef<HTMLDivElement>(null); const bodyRef = useRef(document.body); const size = useSize(bodyRef); const [scroll, setScroll] = useState<TableProps<any>['scroll']>({ x: 'max-content' }); const [rescolumns, setResColumns] = useState<ColumnType<RecordType>[]>(props.columns || []); const handleResize = (index: number): ((_: any, Resize: { size: { width: any } }) => void) => { return (_: any, Resize: { size: { width: any; }; }) => { const temp = [...rescolumns]; temp[index] = { ...temp[index], width: Resize.size.width }; setResColumns(temp); }; }; // 把 columns 用 map 重组为支持可拖拽的cell const columnsMap: any[] = useMemo(() => { return ( rescolumns?.map((column:any,index:any) => ({ ...column, onHeaderCell: (col: { width: any; }) => ({ width: col.width, onResize: handleResize(index) }), title: column.title, })) || [] ); }, [rescolumns]); useEffect(() => { if (wrapperRef.current) { const { top } = wrapperRef.current?.getBoundingClientRect(); setScroll({ x: 'max-content', y: innerHeight - top - 210 }); } }, [wrapperRef, size]); return ( <div className={classes.wrapper} ref={wrapperRef}> <div className={classes.header}> <div className={classes.tablActions}> {onCreate && ( <Button className={classes.headerBtn} type='primary' onClick={onCreate}> 新增 </Button> )} {onEdit && ( <Button className={classes.headerBtn} type='default'> 编辑 </Button> )} {deleteBtn && ( <Button {...deleteBtn.props} className={classes.headerBtn} type='default' danger onClick={deleteBtn.onDelete} > 删除 </Button> )} </div> </div> <Table scroll={scroll} {...props} components={isDrag ? { header: { cell: ResizableTitle } } : undefined} columns={columnsMap} /> </div> ); };
import { createUseStyles } from 'react-jss'; import type { TableRowSelection } from 'antd/lib/table/interface'; import type { ColumnsType } from 'antd/lib/table'; import { useEffect, useMemo, useState, useRef } from 'react'; import { CommonTable } from '../components/CommonTable/index'; const useStyles = createUseStyles({ table: { background: '#fff', padding: '16px', marginTop: '16px', width: '100%', }, textBtn: { color: '#0068FF', cursor: 'pointer', userSelect: 'none', }, }); const TablePage = () => { const [tableData, setTableData] = useState<any>([]); const [currentPage, setCurrentPage] = useState<number>(1); const [currentSize, setCurrentSize] = useState<number>(20); const classes = useStyles(); const [tableLoading, setTableLoading] = useState(false); const [tableDataTotal, setTableDataTotal] = useState(0); const [selectedRow, setSelectedRow] = useState([] as any); //控制表格是否已选 useEffect(() => { const resTable = [ { id: 1, type: 1, status: '草稿' }, { id: 2, type: 0, status: '已完成' }, { id: 3, type: 1, status: '草稿' }, ]; setTableData(resTable); }, []); const rowSelection: TableRowSelection<any> = { onChange: (selectedRowKeys, selectedRows) => { setSelectedRow(selectedRowKeys); }, }; // 分页 const handlePageChange = (page: number, size: number) => { setCurrentPage(page); setCurrentSize(size); // getList({ page, size, param: queryData }); // 获取table数据 }; const tableColumns: ColumnsType<any> = useMemo(() => { return [ { title: '操作', dataIndex: 'code', fixed: 'left', width: '100px', render: (text, record) => ( <div className={classes.textBtn} onClick={() => { console.log('onClick', text,"record",record); }} > {record['status'] === '草稿' ? '编辑' : '查看'} </div> ), }, { title: '序号', dataIndex: 'id', width: '60px', render: (_, __, index) => index + 1 + (currentPage - 1) * currentSize, }, { title: '来源', dataIndex: 'type', // width: '130px', // 最后一个宽度不传 render: (_, __, index) => (_ === 1 ? '系统' : '手工'), }, ]; }, [classes.textBtn, currentPage, currentSize]); return ( <> <CommonTable rowKey={'id'} className={classes.table} columns={tableColumns} scroll={{ x: 'max-content', }} pagination={{ showTotal: () => `共 ${tableDataTotal} 条记录`, onChange: (page, size) => handlePageChange(page, size), hideOnSinglePage: false, showQuickJumper: true, showSizeChanger: true, current: currentPage, pageSize: currentSize, total: tableDataTotal, }} dataSource={tableData} loading={tableLoading} rowSelection={rowSelection} /> <CommonTable rowKey={'id'} isDrag={false} className={classes.table} columns={tableColumns} scroll={{ x: 'max-content', }} pagination={{ showTotal: () => `共 ${tableDataTotal} 条记录`, onChange: (page, size) => handlePageChange(page, size), hideOnSinglePage: false, showQuickJumper: true, showSizeChanger: true, current: currentPage, pageSize: currentSize, total: tableDataTotal, }} dataSource={tableData} loading={tableLoading} rowSelection={rowSelection} /> </> ); }; export default TablePage;
import React, { useMemo, useCallback } from 'react'; interface Args { handleEdit: (r: any) => void; handleSeeDetail: (r: any) => void; } export const useColumns = ({ handleEdit, handleSeeDetail }: Args) => { const handleEvent = useCallback( (v: string, record: any, e) => { e.stopPropagation(); if (v === '编辑') { handleEdit(record); } else { handleSeeDetail(record); } }, [handleSeeDetail, handleEdit], ); // 渲染查看 || 编辑 const showPop = useCallback( (record: any) => { if (record.status === '1') { return ( <span onClick={(e) => handleEvent('编辑', record, e)} className="check-btn" > 编辑 </span> ); } else { return ( <span onClick={(e) => handleEvent('查看', record, e)} className="check-btn" > 查看 </span> ); } }, [handleEvent], ); const columnsData: any = useMemo(() => { const columns = [ { title: '操作', width: '100px', fixed: 'left', render: (_: any, record: any) => showPop(record), }, { title: '序号', width: '60px', render: (_: any, record: any, index: number) => `${index + 1}`, }, { title: '名称', dataIndex: 'name', width: '130px', }, { title: '年龄', dataIndex: 'age', }, ]; return columns; }, [showPop]); return columnsData; }; export default useColumns;
import { createUseStyles } from 'react-jss'; import type { TableRowSelection } from 'antd/lib/table/interface'; import type { ColumnsType } from 'antd/lib/table'; import { useEffect, useMemo, useState, useRef } from 'react'; import { CommonTable } from '../components/CommonTable/index'; import useColumns from "./useColumns" const useStyles = createUseStyles({ table: { background: '#fff', padding: '16px', marginTop: '16px', width: '100%', }, textBtn: { color: '#0068FF', cursor: 'pointer', userSelect: 'none', }, }); const TablePage = () => { const testData = [ { name: '测试1',age: 10 }, { name: '测试1',age: 20 }, { name: '测试1',age: 30 }, ] const handleSeeDetail = (row:any) => { console.log('查看', row); } const handleEdit = (row:any) => { console.log('编辑', row); } return ( <> <CommonTable rowKey={'id'} className={classes.table} dataSource={testData} scroll={{ x: 'max-content', }} columns={useColumns({ handleSeeDetail, handleEdit })} /> </> ); }; export default TablePage;
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。