diff --git a/components/apolloTable/component/DragSorted.tsx b/components/apolloTable/component/DragSorted.tsx index 9f3e2bfb2017146369f09ff57cadf1076ae7406d..ef98cd63bddf4ab6fde959cb0c8336cd18ba16b4 100644 --- a/components/apolloTable/component/DragSorted.tsx +++ b/components/apolloTable/component/DragSorted.tsx @@ -17,11 +17,17 @@ const DragSorted = (props: any) => { position, columnChsName, } = props; - if (!canSorted || position === 'left' || position === 'right') { + if (!canSorted) { return
{props.children}
; } - // 长按计时器 - const timer: any = useRef(null); + // 按下鼠标 + const pressed: any = useRef(false); + // copyDiv显示 + const copyDivShow: any = useRef(false); + // 拖动列 + const dragCol: any = useRef(); + // 放置列 + const dropCol: any = useRef(); // 表格滚动计时器 const timerInterval: any = useRef(null); // 表格 @@ -37,6 +43,15 @@ const DragSorted = (props: any) => { const rightFixedHandleWrap: any = document.querySelector('#rightFixedHandleWrap'); // 监听鼠标移动 const onMouseMove = useCallback((e) => { + if (!pressed.current) { + // 移除全局事件 + document.body.removeEventListener('mousemove', onMouseMove, false); + document.body.removeEventListener('mouseup', onMouseUp, false); + return; + } + if (!copyDivShow.current) { + initCopyDiv(e); + } const tableRect = container.getBoundingClientRect(); const detaX = columnCopyDiv.getAttribute('data-deta-x'); // 所有列 @@ -45,33 +60,33 @@ const DragSorted = (props: any) => { const rightFixedHandleWrapRectX = (rightFixedHandleWrap && rightFixedHandleWrap.getBoundingClientRect().x) || tableRect.right; - const columnCopyDivRect = columnCopyDiv.getBoundingClientRect(); - const columnCopyDivWidth = columnCopyDivRect.width; - const columnCopyDivX = columnCopyDivRect.x; - // 影子div中间点的x坐标 - const columnCopyDivMid = columnCopyDivX + columnCopyDivWidth / 2; const left = e.clientX - tableRect.x - Number(detaX); // 影子div随鼠标移动 // 鼠标在左侧固定列与右侧固定列之间有效 - if (e.clientX > leftFixedHandleWrapRectX && e.clientX < rightFixedHandleWrapRectX) { + if (e.clientX > tableRect.x && e.clientX < tableRect.right) { columnCopyDiv.style.left = `${left}px`; } draggableColumns.forEach((dom) => { const domRect = dom.getBoundingClientRect(); // 当前节点在左侧固定列与右侧固定列之间有效 - if ( - domRect.x > leftFixedHandleWrapRectX && - domRect.x < rightFixedHandleWrapRectX && - columnCopyDivMid > domRect.x && - columnCopyDivMid < domRect.x + domRect.width - ) { + if (e.clientX > domRect.x && e.clientX < domRect.x + domRect.width / 2) { // 影子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); + dropCol.current = { + columnName: dropColumn, + move: -1, + }; + } else if (e.clientX > domRect.x + domRect.width / 2 && e.clientX < domRect.x + domRect.width) { + // 影子div中点在投放目标中 + divider.style.left = `${domRect.x - tableRect.x + domRect.width}px`; + // 收集投放目标的信息 + const dropColumn = dom.getAttribute('data-column-name') || ''; + dropCol.current = { + columnName: dropColumn, + move: 1, + }; } }); @@ -79,16 +94,16 @@ const DragSorted = (props: any) => { let dir = ''; let step = 10; // 设置鼠标超出表格左右固定列两侧时的滚动事件 - if (columnCopyDivX + columnCopyDivWidth > rightFixedHandleWrapRectX - 50) { + if (e.clientX > rightFixedHandleWrapRectX - 50) { dir = 'right'; step = 100; - } else if (columnCopyDivX + columnCopyDivWidth > rightFixedHandleWrapRectX - 100) { + } else if (e.clientX > rightFixedHandleWrapRectX - 100) { dir = 'right'; step = 30; - } else if (columnCopyDivX < leftFixedHandleWrapRectX + 100) { + } else if (e.clientX < leftFixedHandleWrapRectX + 100) { dir = 'left'; step = 30; - } else if (columnCopyDivX < leftFixedHandleWrapRectX + 50) { + } else if (e.clientX < leftFixedHandleWrapRectX + 50) { dir = 'left'; step = 100; } else { @@ -114,81 +129,48 @@ const DragSorted = (props: any) => { }, []); // 监听鼠标抬起 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'); + const dragColumn = dragCol.current && dragCol.current.columnName; + const dropColumn = dropCol.current && dropCol.current.columnName; + const dropMove = dropCol.current && dropCol.current.move; + // 清理操作 + clean(); // 没有列信息 if (!dragColumn || !dropColumn) { return; } - // 没有拖动 - if (Number(dropColumnOrder) === Number(dragColumnOrder)) { - return; - } - // 拖动没有产生移动 - if (Number(dropColumnOrder) - Number(dragColumnOrder) === 1) { - return; - } // 拖动回调 - const newColumns: any[] = []; - // 从右往左拖 - if (Number(dragColumnOrder) > Number(dropColumnOrder)) { - // columns已排序 - columns.map((item: any, i: number) => { - if (item.orderNo >= Number(dropColumnOrder) && item.orderNo <= Number(dragColumnOrder)) { - if (item.columnName === dragColumn) { - newColumns.push({ - ...item, - orderNo: Number(dropColumnOrder), - }); - } else { - newColumns.push({ - ...item, - orderNo: columns[i + 1].orderNo, - }); - } - } else { - newColumns.push(item); - } - }); - } else { - // 从左往右拖 - const index = columns.findIndex((item: any) => { - return item.columnName === dropColumn; - }); - columns.map((item: any, i: number) => { - if (item.columnName === dragColumn) { - newColumns.push({ - ...item, - orderNo: columns[index - 1].orderNo, - }); - } else if (item.orderNo > Number(dragColumnOrder) && item.orderNo < Number(dropColumnOrder)) { - newColumns.push({ - ...item, - orderNo: columns[i - 1].orderNo, - }); - } else { - newColumns.push(item); - } - }); - } + let newColumns: any[] = [...columns]; + const dragIndex = newColumns.findIndex((item) => item.columnName === dragColumn); + const dragObj = newColumns[dragIndex]; + newColumns.splice(dragIndex, 1); + const dropIndex = newColumns.findIndex((item) => item.columnName === dropColumn); + newColumns.splice(dropIndex + dropMove + 1, 0, dragObj); + const lenLeft = newColumns.filter((item) => item.fixed === 'left').length; + const lenRight = newColumns.filter((item) => item.fixed === 'right').length; + const len = newColumns.length; + newColumns = newColumns.map((item: any, i: number) => { + if (i < lenLeft) { + return { + ...item, + orderNo: i + 1, + fixed: 'left', + }; + } + if (i >= len - lenRight) { + return { + ...item, + orderNo: i + 1, + fixed: 'right', + }; + } + return { + ...item, + orderNo: i + 1, + fixed: '', + }; + }); + if (cachedFeAttr) { const cachedCols = getCache({ tableId }); if (cachedCols) { @@ -196,6 +178,7 @@ const DragSorted = (props: any) => { cachedCols[item.columnName] = { ...cachedCols[item.columnName], orderNo: item.orderNo, + fixed: item.fixed, }; }); saveCache({ tableId, data: cachedCols }); @@ -215,40 +198,62 @@ const DragSorted = (props: any) => { if (e.button !== 0) { return; } + // 鼠标按下标记 + pressed.current = true; + // 记录拖动列 + dragCol.current = { + columnName, + orderNo, + }; + // 全局添加监听鼠标移动和松开事件 + document.body.addEventListener('mousemove', onMouseMove, false); + document.body.addEventListener('mouseup', onMouseUp, false); + }, + [onMouseMove, onMouseUp], + ); + // 初始化影子div位置 + const initCopyDiv = useCallback( + (e) => { // 表格初始位置x点 const originLeft = container.getBoundingClientRect().x || 0; // 拖动列矩形 - const targetRect = e.currentTarget.getBoundingClientRect(); + const targetRect = e.target.offsetParent.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`; - columnCopyDiv.innerText = columnChsName; - // 鼠标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(); + // 影子div显示 + columnCopyDiv.style.display = 'block'; + // 影子div初始x位置=拖动列x点-表格x点 + columnCopyDiv.style.left = `${targetRect.x - originLeft}px`; + // 影子div宽度=拖动列宽度 + columnCopyDiv.style.width = `${targetRect.width}px`; + columnCopyDiv.innerText = columnChsName; + // 鼠标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'; + copyDivShow.current = true; }, - [columnName, orderNo, onMouseMove, onMouseUp], + [columnName, orderNo], ); + const clean = useCallback(() => { + // 鼠标松开 + pressed.current = false; + // 清空计时器 + 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'; + copyDivShow.current = false; + dragCol.current = null; + dropCol.current = null; + }, [onMouseMove, onMouseUp]); return (