mirror of https://github.com/msgbyte/tailchat
refactor: 抽离群详情拖拽相关的问题
parent
0b83fa0456
commit
b243f64227
@ -0,0 +1,144 @@
|
||||
import { useCallback, useRef } from 'react';
|
||||
import { showToasts, t, GroupPanel as GroupPanelInfo } from 'tailchat-shared';
|
||||
import type { NodeDragEventParams } from 'rc-tree/lib/contextTypes';
|
||||
import type { DataNode, EventDataNode } from 'antd/lib/tree';
|
||||
import type { Key } from 'rc-tree/lib/interface';
|
||||
import type { AllowDrop } from 'rc-tree/lib/Tree';
|
||||
import _cloneDeep from 'lodash/cloneDeep';
|
||||
import { rebuildGroupPanelOrder } from './utils';
|
||||
|
||||
export function useGroupPanelTreeDrag(
|
||||
groupPanels: GroupPanelInfo[],
|
||||
onChangeGroupPanels: (newGroupPanels: GroupPanelInfo[]) => void
|
||||
) {
|
||||
const draggingNode = useRef<DataNode | null>(null);
|
||||
|
||||
const handleDragStart = useCallback(
|
||||
(info: NodeDragEventParams<HTMLDivElement>) => {
|
||||
draggingNode.current = info.node;
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
||||
const handleDragEnd = useCallback(() => {
|
||||
draggingNode.current = null;
|
||||
}, []);
|
||||
|
||||
const handleAllowDrop = useCallback(
|
||||
({ dropNode, dropPosition }: Parameters<AllowDrop>[0]) => {
|
||||
if (draggingNode.current?.isLeaf === true) {
|
||||
// 如果正在拖拽的节点是面板
|
||||
if (dropPosition === 0) {
|
||||
return !dropNode.isLeaf; // 如果为分组则允许拖动
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
// 正在拖拽的节点是分组
|
||||
if (dropPosition === 0) {
|
||||
// 不允许容器之间产生父子节点
|
||||
return false;
|
||||
}
|
||||
|
||||
// 仅允许拖拽到分组的上下
|
||||
return !dropNode.isLeaf;
|
||||
}
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
||||
const handleDrop = useCallback(
|
||||
(
|
||||
info: NodeDragEventParams & {
|
||||
dragNode: EventDataNode;
|
||||
dragNodesKeys: Key[];
|
||||
dropPosition: number;
|
||||
dropToGap: boolean;
|
||||
}
|
||||
) => {
|
||||
const newGroupPanels = _cloneDeep(groupPanels);
|
||||
const dropNodePos = newGroupPanels.findIndex(
|
||||
(panel) => panel.id === info.node.key
|
||||
);
|
||||
const dropGroupPanel = newGroupPanels[dropNodePos];
|
||||
if (dropNodePos === -1) {
|
||||
showToasts('异常, 目标节点未找到', 'error');
|
||||
}
|
||||
|
||||
const dragPanelPos = newGroupPanels.findIndex(
|
||||
(panel) => panel.id === info.dragNode.key
|
||||
);
|
||||
|
||||
if (draggingNode.current?.isLeaf === true) {
|
||||
// 如果拖拽节点是面板且目标也是面板
|
||||
if (info.node.isLeaf === true) {
|
||||
// 如果目标也是面板
|
||||
// 则更新它的父节点id为目标节点的父节点id
|
||||
info.dragNodesKeys
|
||||
// 获取所有的移动节点的位置
|
||||
.map((key) => newGroupPanels.findIndex((panel) => panel.id === key))
|
||||
// 过滤掉没找到的
|
||||
.filter((index) => index !== -1)
|
||||
.forEach((pos) => {
|
||||
newGroupPanels[pos].parentId = dropGroupPanel.parentId;
|
||||
});
|
||||
} else if (info.dropToGap === false && info.node.isLeaf === false) {
|
||||
// 如果目标是组节点且拖动到内部
|
||||
// 则更新它的父节点id为目标节点的id
|
||||
info.dragNodesKeys
|
||||
// 获取所有的移动节点的位置
|
||||
.map((key) => newGroupPanels.findIndex((panel) => panel.id === key))
|
||||
// 过滤掉没找到的
|
||||
.filter((index) => index !== -1)
|
||||
.forEach((pos) => {
|
||||
newGroupPanels[pos].parentId = dropGroupPanel.id;
|
||||
});
|
||||
} else if (info.dropToGap === true && info.node.isLeaf === false) {
|
||||
// 如果目标是组节点但是拖动到兄弟节点
|
||||
// 则更新它的父节点id为空
|
||||
info.dragNodesKeys
|
||||
// 获取所有的移动节点的位置
|
||||
.map((key) => newGroupPanels.findIndex((panel) => panel.id === key))
|
||||
// 过滤掉没找到的
|
||||
.filter((index) => index !== -1)
|
||||
.forEach((pos) => {
|
||||
newGroupPanels[pos].parentId = undefined;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const fromPos = dragPanelPos;
|
||||
let toPos: number;
|
||||
if (info.node.dragOverGapTop === true) {
|
||||
// 移动到目标节点之前
|
||||
toPos = dropNodePos;
|
||||
} else {
|
||||
// 移动到目标节点之后或之内
|
||||
toPos = dropNodePos + 1;
|
||||
}
|
||||
|
||||
// 应用移动, 先添加再删除
|
||||
if (fromPos < toPos) {
|
||||
// 如果是将数组中前面的数拿到后面
|
||||
newGroupPanels.splice(toPos, 0, newGroupPanels[fromPos]);
|
||||
newGroupPanels.splice(fromPos, 1);
|
||||
} else if (fromPos > toPos) {
|
||||
// 把后面的数拿到前面
|
||||
const [tmp] = newGroupPanels.splice(fromPos, 1);
|
||||
newGroupPanels.splice(toPos, 0, tmp);
|
||||
}
|
||||
|
||||
if (typeof onChangeGroupPanels === 'function') {
|
||||
const res = rebuildGroupPanelOrder(newGroupPanels);
|
||||
onChangeGroupPanels(res);
|
||||
}
|
||||
},
|
||||
[groupPanels, onChangeGroupPanels]
|
||||
);
|
||||
|
||||
return {
|
||||
handleDragStart,
|
||||
handleDragEnd,
|
||||
handleAllowDrop,
|
||||
handleDrop,
|
||||
};
|
||||
}
|
Loading…
Reference in New Issue