From 97e1f5aca3935c53b02943210bb18a9df21f6336 Mon Sep 17 00:00:00 2001 From: Rylan Date: Mon, 25 May 2026 11:14:00 +0800 Subject: [PATCH] fix(Tree): drop indicator still showing when allowDrop returns false --- packages/common | 2 +- .../tree/hooks/TreeDraggableContext.tsx | 3 ++ .../components/tree/hooks/useDraggable.tsx | 47 +++++++++++-------- 3 files changed, 32 insertions(+), 20 deletions(-) diff --git a/packages/common b/packages/common index 1c930580be..b771986dfc 160000 --- a/packages/common +++ b/packages/common @@ -1 +1 @@ -Subproject commit 1c930580be92a98e431ec3ef76af0b7d98c529d6 +Subproject commit b771986dfcaaadd4baec23bbd8fbc8ba438441b2 diff --git a/packages/components/tree/hooks/TreeDraggableContext.tsx b/packages/components/tree/hooks/TreeDraggableContext.tsx index e0dc924bc7..bcf47719d7 100644 --- a/packages/components/tree/hooks/TreeDraggableContext.tsx +++ b/packages/components/tree/hooks/TreeDraggableContext.tsx @@ -101,12 +101,15 @@ export const TreeDraggableContext = createHookContext((value: Value) => { }); }; + const getDragNode = () => dragNode.current; + return { onDragStart, onDragEnd, onDragOver, onDragLeave, onDrop, + getDragNode, }; }); diff --git a/packages/components/tree/hooks/useDraggable.tsx b/packages/components/tree/hooks/useDraggable.tsx index 9a586d7474..b35b1730ef 100644 --- a/packages/components/tree/hooks/useDraggable.tsx +++ b/packages/components/tree/hooks/useDraggable.tsx @@ -15,7 +15,7 @@ export default function useDraggable(props: { allowDrop?: TdTreeProps['allowDrop']; }) { const { nodeRef, node, allowDrop } = props; - const { onDragStart, onDragEnd, onDragLeave, onDragOver, onDrop } = useTreeDraggableContext(); + const { onDragStart, onDragEnd, onDragLeave, onDragOver, onDrop, getDragNode } = useTreeDraggableContext(); const [state, setState] = useState<{ isDragOver: boolean; @@ -34,23 +34,35 @@ export default function useDraggable(props: { })); }); + const calcDropPosition = (e: DragEvent): DropPosition => { + if (!window || !nodeRef.current) return 0; + const rect = nodeRef.current.getBoundingClientRect(); + const offsetY = window.scrollY + rect.top; + const { pageY } = e; + // 节点上 1/4 视为前置,下 1/4 视为后置,中间为子节点 + const gapHeight = rect.height / 4; + const diff = pageY - offsetY; + if (diff < gapHeight) return -1; + if (diff < rect.height - gapHeight) return 0; + return 1; + }; + const updateDropPosition = useRef( throttle((e: DragEvent) => { - if (!nodeRef.current) return; - - const rect = nodeRef.current.getBoundingClientRect(); - const offsetY = window.pageYOffset + rect.top; - const { pageY } = e; - const gapHeight = rect.height / 4; - const diff = pageY - offsetY; - - if (diff < gapHeight) { - setPartialState({ dropPosition: -1 }); - } else if (diff < rect.height - gapHeight) { - setPartialState({ dropPosition: 0 }); - } else { - setPartialState({ dropPosition: 1 }); - } + const dropPosition = calcDropPosition(e); + // 通过 allowDrop 判断当前位置是否允许放置 + // 从而决定提示线是否显示 + const dragNode = getDragNode?.(); + const isAllowed = + !allowDrop || + !dragNode || + allowDrop({ + e, + dragNode: dragNode.getModel(), + dropNode: node.getModel(), + dropPosition, + }) !== false; + setPartialState({ dropPosition, isDragOver: isAllowed }); }), ).current; @@ -76,9 +88,6 @@ export default function useDraggable(props: { onDragEnd?.({ node, e }); break; case 'dragOver': - setPartialState({ - isDragOver: true, - }); updateDropPosition(e); onDragOver?.({ node, dropPosition: state.dropPosition, e }); break;