fix(editor): 组件树中将容器拖入自身中会导致容器丢失

fix #622
This commit is contained in:
roymondchen 2024-07-25 17:20:36 +08:00
parent c456798751
commit 16d4eff385
3 changed files with 48 additions and 6 deletions

View File

@ -4,6 +4,8 @@
class="m-editor-tree-node" class="m-editor-tree-node"
:draggable="draggable" :draggable="draggable"
:data-node-id="data.id" :data-node-id="data.id"
:data-parent-id="parent?.id"
:data-parents-id="parentsId"
:data-is-container="Array.isArray(data.items)" :data-is-container="Array.isArray(data.items)"
@dragstart="handleDragStart" @dragstart="handleDragStart"
@dragleave="handleDragLeave" @dragleave="handleDragLeave"
@ -40,6 +42,8 @@
v-for="item in data.items" v-for="item in data.items"
:key="item.id" :key="item.id"
:data="item" :data="item"
:parent="data"
:parentsId="[...parentsId, data.id]"
:node-status-map="nodeStatusMap" :node-status-map="nodeStatusMap"
:indent="indent + 11" :indent="indent + 11"
> >
@ -91,11 +95,14 @@ const treeEmit = inject<typeof emit>('treeEmit');
const props = withDefaults( const props = withDefaults(
defineProps<{ defineProps<{
data: TreeNodeData; data: TreeNodeData;
parent?: TreeNodeData;
parentsId?: Id[];
nodeStatusMap: Map<Id, LayerNodeStatus>; nodeStatusMap: Map<Id, LayerNodeStatus>;
indent?: number; indent?: number;
}>(), }>(),
{ {
indent: 0, indent: 0,
parentsId: () => [],
}, },
); );

View File

@ -10,6 +10,7 @@ const dragState: {
dragOverNodeId: Id; dragOverNodeId: Id;
dropType: NodeDropType | ''; dropType: NodeDropType | '';
container: HTMLElement | null; container: HTMLElement | null;
nodeId?: Id;
} = { } = {
dragOverNodeId: '', dragOverNodeId: '',
dropType: '', dropType: '',
@ -50,6 +51,7 @@ export const useDrag = (services: Services | undefined) => {
if (!targetEl || targetEl !== event.currentTarget) return; if (!targetEl || targetEl !== event.currentTarget) return;
event.dataTransfer.effectAllowed = 'move'; event.dataTransfer.effectAllowed = 'move';
dragState.nodeId = targetEl.dataset.nodeId;
try { try {
event.dataTransfer.setData( event.dataTransfer.setData(
@ -70,30 +72,52 @@ export const useDrag = (services: Services | undefined) => {
const labelEl = targetEl.children[0]; const labelEl = targetEl.children[0];
if (!labelEl) return; if (!labelEl) return;
removeClassName(labelEl, 'drag-before', 'drag-after', 'drag-inner');
const { top: targetTop, height: targetHeight } = labelEl.getBoundingClientRect(); const { top: targetTop, height: targetHeight } = labelEl.getBoundingClientRect();
const distance = event.clientY - targetTop; const distance = event.clientY - targetTop;
const isContainer = targetEl.dataset.isContainer === 'true'; const isContainer = targetEl.dataset.isContainer === 'true';
const targetNodeId = targetEl.dataset.nodeId;
const { nodeId } = dragState;
const parentsId = targetEl.dataset.parentsId?.split(',');
if (!targetNodeId) {
return;
}
// 如果是悬浮在拖动的节点上方,则不响应
if (parentsId) {
let targetIdIndex = -1;
for (let i = 0, l = parentsId.length; i < l; i++) {
const id = parentsId[i];
if (nodeId === id) {
targetIdIndex = i;
}
if (parentsId.includes(`${nodeId}`) && i >= targetIdIndex) {
return;
}
}
}
if (distance < targetHeight / 3) { if (distance < targetHeight / 3) {
dragState.dropType = 'before'; dragState.dropType = 'before';
addClassName(labelEl, globalThis.document, 'drag-before'); addClassName(labelEl, globalThis.document, 'drag-before');
removeClassName(labelEl, 'drag-after', 'drag-inner');
} else if (distance > (targetHeight * 2) / 3) { } else if (distance > (targetHeight * 2) / 3) {
dragState.dropType = 'after'; dragState.dropType = 'after';
addClassName(labelEl, globalThis.document, 'drag-after'); addClassName(labelEl, globalThis.document, 'drag-after');
removeClassName(labelEl, 'drag-before', 'drag-inner');
} else if (isContainer) { } else if (isContainer) {
dragState.dropType = 'inner'; dragState.dropType = 'inner';
addClassName(labelEl, globalThis.document, 'drag-inner'); addClassName(labelEl, globalThis.document, 'drag-inner');
removeClassName(labelEl, 'drag-before', 'drag-after');
} }
if (!dragState.dropType) { if (!dragState.dropType) {
return; return;
} }
dragState.dragOverNodeId = targetEl.dataset.nodeId || ''; dragState.dragOverNodeId = targetNodeId;
dragState.container = event.currentTarget as HTMLElement; dragState.container = event.currentTarget as HTMLElement;
event.preventDefault(); event.preventDefault();

View File

@ -899,9 +899,20 @@ class Editor extends BaseService {
const newLayout = await this.getLayout(targetParent); const newLayout = await this.getLayout(targetParent);
for (const config of configs) { // eslint-disable-next-line no-restricted-syntax
forConfigs: for (const config of configs) {
const { parent, node: curNode } = this.getNodeInfo(config.id, false); const { parent, node: curNode } = this.getNodeInfo(config.id, false);
if (!parent || !curNode) throw new Error('找不要删除的节点'); if (!parent || !curNode) {
continue;
}
const path = getNodePath(curNode.id, parent.items);
for (const node of path) {
if (targetParent.id === node.id) {
continue forConfigs;
}
}
const index = getNodeIndex(curNode.id, parent); const index = getNodeIndex(curNode.id, parent);