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

View File

@ -10,6 +10,7 @@ const dragState: {
dragOverNodeId: Id;
dropType: NodeDropType | '';
container: HTMLElement | null;
nodeId?: Id;
} = {
dragOverNodeId: '',
dropType: '',
@ -50,6 +51,7 @@ export const useDrag = (services: Services | undefined) => {
if (!targetEl || targetEl !== event.currentTarget) return;
event.dataTransfer.effectAllowed = 'move';
dragState.nodeId = targetEl.dataset.nodeId;
try {
event.dataTransfer.setData(
@ -70,30 +72,52 @@ export const useDrag = (services: Services | undefined) => {
const labelEl = targetEl.children[0];
if (!labelEl) return;
removeClassName(labelEl, 'drag-before', 'drag-after', 'drag-inner');
const { top: targetTop, height: targetHeight } = labelEl.getBoundingClientRect();
const distance = event.clientY - targetTop;
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) {
dragState.dropType = 'before';
addClassName(labelEl, globalThis.document, 'drag-before');
removeClassName(labelEl, 'drag-after', 'drag-inner');
} else if (distance > (targetHeight * 2) / 3) {
dragState.dropType = 'after';
addClassName(labelEl, globalThis.document, 'drag-after');
removeClassName(labelEl, 'drag-before', 'drag-inner');
} else if (isContainer) {
dragState.dropType = 'inner';
addClassName(labelEl, globalThis.document, 'drag-inner');
removeClassName(labelEl, 'drag-before', 'drag-after');
}
if (!dragState.dropType) {
return;
}
dragState.dragOverNodeId = targetEl.dataset.nodeId || '';
dragState.dragOverNodeId = targetNodeId;
dragState.container = event.currentTarget as HTMLElement;
event.preventDefault();

View File

@ -899,9 +899,20 @@ class Editor extends BaseService {
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);
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);