import React, { useState, useEffect, useRef } from 'react'; import { Table } from 'antd'; import { HTML5Backend } from 'react-dnd-html5-backend'; import { DndProvider, useDrag, useDrop } from 'react-dnd'; import classnames from 'classnames'; import styles from './index.less'; const DraggableBodyRow = ({ name, index, moveRow, className, style, tableType, ItemTypes, ...restProps }) => { const [type, setType] = useState(''); const ref = useRef(); useEffect(() => { if (ItemTypes) { setType(ItemTypes); } }, [ItemTypes]); const [{ isOver, dropClassName }, drop] = useDrop({ accept: type, collect: monitor => { const { index: dragIndex } = monitor.getItem() || {}; if (dragIndex === index) { return {}; } return { isOver: monitor.isOver(), canDrop: monitor.canDrop(), dropClassName: dragIndex < index ? 'drop-over-downward' : 'drop-over-upward', }; }, drop: item => { moveRow(item.index, index, tableType); }, }); const [, drag] = useDrag({ type, item: { index }, collect: monitor => ({ isDragging: monitor.isDragging(), }), }); drop(drag(ref)); return ( <tr ref={ref} className={classnames({ [className]: true, [styles[dropClassName]]: isOver, })} style={{ cursor: 'move', ...style }} {...restProps} /> ); }; const DragTable = props => { const { columns, dataSource, dragCallBack, ItemTypes } = props; // const [data, setData] = useState(null); // 分组后的数组 const components = { body: { row: DraggableBodyRow, }, }; // useEffect(() => { // if (dataSource.length > 0) { // setData(dataSource); // } // }, [dataSource]); // 每次拖拽后返回 // useEffect(() => { // dragCallBack(data); // }, [data]); // 移动数组元素到指定位置 const moveInArray = (arr, from, to) => { // 确保是有效数组 if (Object.prototype.toString.call(arr) !== '[object Array]') { throw new Error('Please provide a valid array'); } // 删除当前的位置 let item = arr.splice(from, 1); // 确保还剩有元素移动 if (!item.length) { throw new Error(`There is no item in the array at index ${from}`); } // 移动元素到指定位置 arr.splice(to, 0, item[0]); return arr; }; // 拖拽表格 const moveRow = (dragIndex, hoverIndex) => { // setData(val => { // let newData = JSON.parse(JSON.stringify(val)); // newData = moveInArray(newData, dragIndex, hoverIndex); // return newData; // }); let newData = JSON.parse(JSON.stringify(dataSource)) newData = moveInArray(newData, dragIndex, hoverIndex) dragCallBack(newData) } return ( <DndProvider backend={HTML5Backend}> <Table size='small' columns={columns} dataSource={dataSource} components={components} onRow={(record, index) => ({ index, ItemTypes, moveRow, onClick: () => props.onClick && props.onClick(record), })} {...props} /> </DndProvider> ) } export default DragTable;