diff --git a/components/apolloTable/component/DragSorted.tsx b/components/apolloTable/component/DragSorted.tsx index a29499eb149ce5d70f8ff989a85bc8ff1ff64bb4..e4b9dc4d4d7bee73d9705e9eaaf260d7527b3d70 100644 --- a/components/apolloTable/component/DragSorted.tsx +++ b/components/apolloTable/component/DragSorted.tsx @@ -1,9 +1,14 @@ -import React, { useCallback } from 'react'; +import React, { useCallback, useRef } from 'react'; import classNames from 'classnames'; -import s from './DragSorted.less'; const DragSorted = (props: any) => { - const { className, style, columnConfig, onDropFinish, onScroll } = props; + const { + className, style, columnName, orderNo, onDropFinish, onScroll, + } = props; + // 长按计时器 + const timer: any = useRef(null); + // 表格滚动计时器 + const timerInterval: any = useRef(null); // 表格 const container: any = document.querySelector('#tableContainer'); // 拖拽列时的影子div @@ -14,115 +19,161 @@ const DragSorted = (props: any) => { const divider: any = document.querySelector('#divider'); // 左侧固定列分割线 const leftFixedHandleWrap: any = document.querySelector('#leftFixedHandleWrap'); - // ? 拖动目标事件 - // 开始拖动 - const onDragStart = useCallback((e) => { - // 表格初始位置x点 - const originLeft = container.getBoundingClientRect().x || 0; - // 拖动列矩形 - const targetRect = e.target.getBoundingClientRect(); - // 影子div显示 - columnCopyDiv.style.display = 'block'; - // 影子div初始x位置=拖动列x点-表格x点 - columnCopyDiv.style.left = `${targetRect.x - originLeft}px`; - // 影子div宽度=拖动列宽度 - columnCopyDiv.style.width = `${targetRect.width}px`; - // 鼠标x点与拖动列x点之间的距离(记录下来方便后续使用) - const detaX = e.clientX - targetRect.x; - columnCopyDiv.setAttribute('data-deta-x', detaX); - // 将拖动列信息加入拖拽事件dataTransfer中,方便后续使用 - e.dataTransfer.setData('dragColumn', JSON.stringify(columnConfig)); - // debugger - - divider.style.left = `${targetRect.x - originLeft}px`; - dividerWrap.style.display = 'block'; - }, [columnConfig.columnName]); - // 拖动中 - const onDragUpdate = useCallback((e) => { - // 拖动列矩形 - const targetRect = e.target.getBoundingClientRect(); + // 监听鼠标移动 + const onMouseMove = useCallback((e) => { const tableRect = container.getBoundingClientRect(); const detaX = columnCopyDiv.getAttribute('data-deta-x'); - const left = e.clientX - tableRect.x - detaX; - console.log('left: ', left); - // 影子div随鼠标移动 - columnCopyDiv.style.left = `${left}px`; - }, []); - // 停止拖动 - const onDragEnd = useCallback((e) => { - // 停止拖动时隐藏影子div - columnCopyDiv.style.display = 'none'; - dividerWrap.style.display = 'none'; - console.log('stop: '); - }, []); - // ? 投放目标事件 - // 在投放目标中移动 - const onDragOver = useCallback((e) => { - const tableRect = container.getBoundingClientRect(); - const targetRect = e.target.getBoundingClientRect(); - const columnCopyDivRect = columnCopyDiv.getBoundingClientRect(); + // 所有列 + const draggableColumns = document.querySelectorAll('.draggableColumn'); const leftFixedHandleWrapRect = leftFixedHandleWrap.getBoundingClientRect(); - const targetWidth = targetRect.width; - const targetX = targetRect.x; + + const columnCopyDivRect = columnCopyDiv.getBoundingClientRect(); const columnCopyDivWidth = columnCopyDivRect.width; const columnCopyDivX = columnCopyDivRect.x; // 影子div中间点的x坐标 - const columnCopyDivMid = columnCopyDivX + (columnCopyDivWidth / 2); - if (columnCopyDivMid > targetX && columnCopyDivMid < targetX + targetWidth) { - // 影子div中点在投放目标中 - divider.style.left = `${targetRect.x - tableRect.x}px`; - } + const columnCopyDivMid = columnCopyDivX + columnCopyDivWidth / 2; + + draggableColumns.forEach((dom) => { + const domRect = dom.getBoundingClientRect(); + if (columnCopyDivMid > domRect.x && columnCopyDivMid < domRect.x + domRect.width) { + // 影子div中点在投放目标中 + divider.style.left = `${domRect.x - tableRect.x}px`; + // 收集投放目标的信息 + const dropColumn = dom.getAttribute('data-column-name') || ''; + const dropColumnOrder = dom.getAttribute('data-column-order') || ''; + divider.setAttribute('data-drop-column', dropColumn); + divider.setAttribute('data-drop-order', dropColumnOrder); + } + }); + + const left = e.clientX - tableRect.x - Number(detaX); + // 影子div随鼠标移动 + columnCopyDiv.style.left = `${left}px`; + if (typeof onScroll === 'function') { + let dir = ''; + let step = 10; + // 设置鼠标超出表格左右两侧时的滚动事件 if (e.clientX > tableRect.right - 30) { - onScroll('right', 100); + dir = 'right'; + step = 100; } else if (e.clientX > tableRect.right - 100) { - onScroll('right', 10); + dir = 'right'; + step = 10; } else if (e.clientX < leftFixedHandleWrapRect.x + 100) { - onScroll('left', 10); + dir = 'left'; + step = 10; } else if (e.clientX < leftFixedHandleWrapRect.x + 30) { - onScroll('left', 100); + dir = 'left'; + step = 100; + } else { + dir = ''; } - } - - // 元素默认是不能够投放,需在目标元素的dragover事件中取消默认事件 - var event = e || window.event; - event.preventDefault() - }, []); - // 在投放目标中松开鼠标 - const onDrop = useCallback((e) => { - const targetRect = e.target.getBoundingClientRect(); - const columnCopyDivRect = columnCopyDiv.getBoundingClientRect(); - const targetWidth = targetRect.width; - const targetX = targetRect.x; - const columnCopyDivWidth = columnCopyDivRect.width; - const columnCopyDivX = columnCopyDivRect.x; - // 影子div中间点的x坐标 - const columnCopyDivMid = columnCopyDivX + (columnCopyDivWidth / 2); - if (columnCopyDivMid > targetX && columnCopyDivMid < targetX + targetWidth) { - // 影子div中点在投放目标中 - try { - const dragColumn = JSON.parse(e.dataTransfer.getData('dragColumn')); - const dropColumn = columnConfig; - if (typeof onDropFinish === 'function') { - onDropFinish(dragColumn, dropColumn); + if (dir) { + // 需要滚动,如果已有计时器,先清除再重新设置计时器 + if (timerInterval.current) { + clearInterval(timerInterval.current); + } + timerInterval.current = setInterval(() => { + onScroll(dir, step); + }, 350); + } else { + // 需要停止,清除已有计时器 + // eslint-disable-next-line no-lonely-if + if (timerInterval.current) { + clearInterval(timerInterval.current); + timerInterval.current = null; } - } catch (e) { - console.error('json解析失败') } } - }, [columnConfig.columnName]); - + }, []); + // 监听鼠标抬起 + const onMouseUp = useCallback(() => { + // 清空计时器 + if (timer.current) { + clearTimeout(timer.current); + timer.current = null; + } + if (timerInterval.current) { + clearInterval(timerInterval.current); + timerInterval.current = null; + } + // 移除全局事件 + document.body.removeEventListener('mousemove', onMouseMove, false); + document.body.removeEventListener('mouseup', onMouseUp, false); + // 停止拖动时隐藏影子div + columnCopyDiv.style.display = 'none'; + dividerWrap.style.display = 'none'; + // 获取分割线上挂载的拖动列和投放列信息 + const dragColumn = divider.getAttribute('data-drag-column'); + const dragColumnOrder = divider.getAttribute('data-drag-order'); + const dropColumn = divider.getAttribute('data-drop-column'); + const dropColumnOrder = divider.getAttribute('data-drop-order'); + // 没有列信息 + if (!dragColumn || !dropColumn) { + return; + } + // 没有拖动 + if (Number(dropColumnOrder) === Number(dragColumnOrder)) { + return; + } + // 拖动没有产生移动 + if (Number(dropColumnOrder) - Number(dragColumnOrder) === 1) { + return; + } + // 拖动回调 + if (typeof onDropFinish === 'function') { + onDropFinish( + { columnName: dragColumn, orderNo: Number(dragColumnOrder) }, + { columnName: dropColumn, orderNo: Number(dropColumnOrder) }, + ); + } + }, []); + // 监听鼠标按下 + const onMouseDown = useCallback( + (e) => { + // 表格初始位置x点 + const originLeft = container.getBoundingClientRect().x || 0; + // 拖动列矩形 + const targetRect = e.currentTarget.getBoundingClientRect(); + const curX = e.clientX; + // 500ms长按事件,表示想要拖拽 + timer.current = setTimeout(() => { + // 影子div显示 + columnCopyDiv.style.display = 'block'; + // 影子div初始x位置=拖动列x点-表格x点 + columnCopyDiv.style.left = `${targetRect.x - originLeft}px`; + // 影子div宽度=拖动列宽度 + columnCopyDiv.style.width = `${targetRect.width}px`; + // 鼠标x点与拖动列x点之间的距离(记录下来方便后续使用) + const detaX = curX - targetRect.x; + columnCopyDiv.setAttribute('data-deta-x', String(detaX)); + // 分割线初始位置为当前列 + divider.style.left = `${targetRect.x - originLeft}px`; + dividerWrap.style.display = 'block'; + // 给分割线设置拖动列信息,移除投放列信息 + divider.setAttribute('data-drag-column', columnName); + divider.setAttribute('data-drag-order', orderNo); + divider.removeAttribute('data-drop-column'); + divider.removeAttribute('data-drop-order'); + // 全局添加监听鼠标移动和松开事件 + document.body.addEventListener('mousemove', onMouseMove, false); + document.body.addEventListener('mouseup', onMouseUp, false); + }, 500); + // 阻止默认行为 + e.preventDefault(); + }, + [columnName, orderNo], + ); return (
{props.children}
diff --git a/components/apolloTable/component/Table.less b/components/apolloTable/component/Table.less index ebc698076a9be080d65f3c53591051b3a876bab5..1146620bff234c6e61bdaf9a454a0cc8c6027022 100644 --- a/components/apolloTable/component/Table.less +++ b/components/apolloTable/component/Table.less @@ -142,6 +142,7 @@ bottom: 0; background: rgba(0,0,0,0.3); z-index: 5; - pointer-events: none; + //pointer-events: none; display: none; -} \ No newline at end of file + cursor: grab; +} diff --git a/components/apolloTable/component/Table.tsx b/components/apolloTable/component/Table.tsx index 2657ac4e9a5fcb6719bfe77cb0c8d1fa167c961f..a80902e1db3b103804484b20286e59915fd7cffe 100644 --- a/components/apolloTable/component/Table.tsx +++ b/components/apolloTable/component/Table.tsx @@ -317,9 +317,10 @@ export default class AirTable extends Component { questionText, icon, requiredFlag, + orderNo, } = showColumns[columnIndex]; return ( - + { }} /> -
+
); }}