import { Command } from "./Command"; import { isGroupLayer } from "../utils/layerHelper"; /** * 跨层级移动命令基类 */ export class CrossLevelMoveCommand extends Command { constructor(options) { super({ name: "跨层级移动", undoable: true, }); this.layers = options.layers; this.layerManager = options.layerManager; this.canvas = options.canvas; // 移动相关参数 this.layerId = options.layerId; this.fromContainerType = options.fromContainerType; // 'root' | 'child' this.toContainerType = options.toContainerType; // 'root' | 'child' this.fromParentId = options.fromParentId; this.toParentId = options.toParentId; this.newIndex = options.newIndex; this.oldIndex = options.oldIndex; // 保存状态用于撤销 this.beforeState = null; this.afterState = null; } /** * 保存移动前的状态 */ saveBeforeState() { this.beforeState = { layerStructure: this.cloneLayerStructure(), fabricObjects: this.saveFabricObjectStates(), }; } /** * 保存移动后的状态 */ saveAfterState() { this.afterState = { layerStructure: this.cloneLayerStructure(), fabricObjects: this.saveFabricObjectStates(), }; } /** * 克隆图层结构 */ cloneLayerStructure() { return JSON.parse( JSON.stringify( this.layers.value.map((layer) => ({ id: layer.id, name: layer.name, parentId: layer.parentId, children: layer.children ? layer.children.map((child) => ({ id: child.id, name: child.name, parentId: child.parentId, })) : [], isBackground: layer.isBackground, isFixed: layer.isFixed, visible: layer.visible, locked: layer.locked, })) ) ); } /** * 保存fabric对象状态 */ saveFabricObjectStates() { const states = {}; // 只保存fabric对象的容器关系,不保存具体的属性 this.layers.value.forEach((layer) => { if (layer.fabricObject) { states[layer.id] = { isInCanvas: this.canvas ? this.canvas.contains(layer.fabricObject) : false, parentGroupId: null, visible: layer.fabricObject.visible, }; // 检查是否在某个组中 this.layers.value.forEach((otherLayer) => { if ( otherLayer.fabricObject && otherLayer.fabricObject.type === "group" && otherLayer.fabricObject.contains && otherLayer.fabricObject.contains(layer.fabricObject) ) { states[layer.id].parentGroupId = otherLayer.id; states[layer.id].isInCanvas = false; } }); } }); return states; } /** * 查找图层 */ findLayer(layerId, containerType, parentId) { if (containerType === "root") { return this.layers.value.find((layer) => layer.id === layerId); } else if (containerType === "child" && parentId) { const parent = this.layers.value.find((layer) => layer.id === parentId); return parent?.children?.find((child) => child.id === layerId); } return null; } /** * 验证移动的有效性 */ validateMove() { const layer = this.findLayer( this.layerId, this.fromContainerType, this.fromParentId ); if (!layer) { throw new Error(`找不到要移动的图层: ${this.layerId}`); } // 检查是否为不可移动的图层 if (layer.isBackground || layer.isFixed) { throw new Error("背景层和固定层不能移动"); } // 检查是否试图将图层移动到自己的子层级中(防止循环引用) if ( this.toContainerType === "child" && this.toParentId && this.isDescendantOf(this.toParentId, this.layerId) ) { throw new Error("不能将图层移动到自己的子层级中"); } // 检查目标父图层是否为组 if (this.toContainerType === "child") { const targetParent = this.layers.value.find( (layer) => layer.id === this.toParentId ); if (!targetParent || !isGroupLayer(targetParent)) { throw new Error("目标图层不是组图层"); } } return layer; } /** * 检查是否为子层级关系(防止循环引用) */ isDescendantOf(ancestorId, layerId) { const checkChildren = (children) => { if (!children) return false; for (const child of children) { if (child.id === layerId) return true; if (child.children && checkChildren(child.children)) return true; } return false; }; const ancestor = this.layers.value.find((layer) => layer.id === ancestorId); return ancestor ? checkChildren(ancestor.children) : false; } execute() { console.log("🎯 执行跨层级移动命令:", { layerId: this.layerId, from: this.fromContainerType, to: this.toContainerType, fromParentId: this.fromParentId, toParentId: this.toParentId, }); // 验证移动 const draggedLayer = this.validateMove(); // 保存移动前状态 this.saveBeforeState(); try { // 根据移动类型执行对应操作 if ( this.fromContainerType === "root" && this.toContainerType === "child" ) { this.moveRootToGroup(draggedLayer); } else if ( this.fromContainerType === "child" && this.toContainerType === "root" ) { this.moveGroupToRoot(draggedLayer); } else if ( this.fromContainerType === "child" && this.toContainerType === "child" && this.fromParentId !== this.toParentId ) { this.moveGroupToGroup(draggedLayer); } // 保存移动后状态 this.saveAfterState(); // 刷新画布 if (this.canvas) { this.canvas.renderAll(); console.log("🎨 画布已刷新"); } console.log("✅ 跨层级移动命令执行成功"); return true; } catch (error) { console.error("❌ 跨层级移动命令执行失败:", error); // 如果执行失败,尝试恢复到之前的状态 if (this.beforeState) { try { this.restoreLayerStructure(this.beforeState.layerStructure); this.restoreFabricObjectStates(this.beforeState.fabricObjects); if (this.canvas) { this.canvas.renderAll(); } console.log("🔄 已恢复到移动前状态"); } catch (restoreError) { console.error("❌ 恢复状态失败:", restoreError); } } throw error; } } undo() { if (!this.beforeState) { throw new Error("没有保存的前置状态,无法撤销"); } console.log("🔄 撤销跨层级移动命令"); try { // 恢复图层结构 this.restoreLayerStructure(this.beforeState.layerStructure); // 恢复fabric对象状态 this.restoreFabricObjectStates(this.beforeState.fabricObjects); // 刷新画布 if (this.canvas) { // 使用 requestAnimationFrame 确保DOM更新完成后再渲染 requestAnimationFrame(() => { this.canvas.renderAll(); }); } console.log("✅ 跨层级移动命令撤销成功"); return true; } catch (error) { console.error("❌ 跨层级移动命令撤销失败:", error); // 尝试基本的恢复操作 try { console.log("🔄 尝试基本恢复操作"); this.basicRestore(); } catch (restoreError) { console.error("❌ 基本恢复也失败:", restoreError); } throw error; } } /** * 基本恢复操作(当标准撤销失败时使用) */ basicRestore() { // 重新组织所有图层的fabric对象 this.layers.value.forEach((layer) => { if (layer.fabricObject) { try { // 先从所有容器中移除 this.removeFromAllContainers(layer.fabricObject); // 根据图层的parentId重新放置 if (layer.parentId) { const parentLayer = this.layers.value.find( (l) => l.id === layer.parentId ); if ( parentLayer && parentLayer.fabricObject && parentLayer.fabricObject.type === "group" ) { this.safeAddToContainer( layer.fabricObject, parentLayer.fabricObject, `父组${layer.parentId}` ); } } else { this.safeAddToContainer(layer.fabricObject, this.canvas, "画布"); } } catch (error) { console.error(`❌ 基本恢复图层 ${layer.id} 失败:`, error); } } }); if (this.canvas) { this.canvas.renderAll(); } } /** * 重做命令 */ redo() { if (!this.afterState) { throw new Error("没有保存的后置状态,无法重做"); } console.log("🔄 重做跨层级移动命令"); try { // 恢复图层结构 this.restoreLayerStructure(this.afterState.layerStructure); // 恢复fabric对象状态 this.restoreFabricObjectStates(this.afterState.fabricObjects); // 刷新画布 if (this.canvas) { // 使用 requestAnimationFrame 确保DOM更新完成后再渲染 requestAnimationFrame(() => { this.canvas.renderAll(); }); } console.log("✅ 跨层级移动命令重做成功"); return true; } catch (error) { console.error("❌ 跨层级移动命令重做失败:", error); // 尝试基本的恢复操作 try { console.log("🔄 尝试基本恢复操作"); this.basicRestore(); } catch (restoreError) { console.error("❌ 基本恢复也失败:", restoreError); } throw error; } } /** * 恢复图层结构 */ restoreLayerStructure(layerStructure) { // 保存原始图层数组的引用 const originalLayers = [...this.layers.value]; // 清空当前图层 this.layers.value.splice(0); // 重建图层结构 layerStructure.forEach((layerData) => { // 首先从原始图层数组中查找图层 let layer = originalLayers.find((l) => l.id === layerData.id); // 如果没找到,尝试在嵌套结构中查找 if (!layer) { layer = this.findLayerInOriginalStructure(layerData.id, originalLayers); } if (layer) { // 更新图层属性 layer.parentId = layerData.parentId; layer.visible = layerData.visible; layer.locked = layerData.locked; // 重建children数组 if (layerData.children && layerData.children.length > 0) { layer.children = layerData.children .map((childData) => { // 从原始图层数组中查找子图层 let childLayer = originalLayers.find( (l) => l.id === childData.id ); if (!childLayer) { childLayer = this.findLayerInOriginalStructure( childData.id, originalLayers ); } if (childLayer) { // 更新子图层属性 childLayer.parentId = childData.parentId; childLayer.visible = childData.visible; childLayer.locked = childData.locked; return childLayer; } return null; }) .filter(Boolean); } else { layer.children = []; } this.layers.value.push(layer); } }); } /** * 在原始结构中查找图层 */ findLayerInOriginalStructure(layerId, layers = null) { const layersToSearch = layers || this.layers.value; const findInLayers = (layersList) => { for (const layer of layersList) { if (layer.id === layerId) return layer; if (layer.children) { const found = findInLayers(layer.children); if (found) return found; } } return null; }; return findInLayers(layersToSearch); } /** * 恢复fabric对象状态 */ restoreFabricObjectStates(fabricStates) { if (!this.canvas || !fabricStates) return; console.log("🔧 开始恢复fabric对象状态"); // 重新组织fabric对象的层级关系 this.layers.value.forEach((layer) => { if (layer.fabricObject && fabricStates[layer.id]) { const targetState = fabricStates[layer.id]; console.log(`🔍 恢复图层 ${layer.id} 的fabric对象状态:`, targetState); try { // 首先从所有容器中移除对象 this.removeFromAllContainers(layer.fabricObject); // 根据目标状态放置对象 if (targetState.parentGroupId) { // 应该在特定组中 const parentLayer = this.layers.value.find( (l) => l.id === targetState.parentGroupId ); if ( parentLayer && parentLayer.fabricObject && parentLayer.fabricObject.type === "group" ) { this.safeAddToContainer( layer.fabricObject, parentLayer.fabricObject, `父组${targetState.parentGroupId}` ); } } else if (targetState.isInCanvas) { // 应该在画布中 this.safeAddToContainer(layer.fabricObject, this.canvas, "画布"); } // 恢复可见性 if (layer.fabricObject.visible !== targetState.visible) { layer.fabricObject.visible = targetState.visible; } } catch (error) { console.error(`❌ 恢复图层 ${layer.id} 的fabric对象时出错:`, error); } } }); // 强制重新渲染画布 if (this.canvas) { this.canvas.renderAll(); console.log("✅ 画布已重新渲染"); } } /** * 安全地处理fabric对象操作 */ safeFabricOperation(operation, operationName = "fabric操作") { try { return operation(); } catch (error) { console.error(`❌ ${operationName}失败:`, error); return false; } } /** * 安全地添加fabric对象到容器 */ safeAddToContainer(fabricObject, container, containerName) { return this.safeFabricOperation(() => { if (container && container.add && !container.contains(fabricObject)) { container.add(fabricObject); console.log(`✅ 成功将对象添加到${containerName}`); return true; } return false; }, `添加对象到${containerName}`); } /** * 安全地从容器移除fabric对象 */ safeRemoveFromContainer(fabricObject, container, containerName) { return this.safeFabricOperation(() => { if ( container && container.remove && container.contains && container.contains(fabricObject) ) { container.remove(fabricObject); console.log(`✅ 成功从${containerName}移除对象`); return true; } return false; }, `从${containerName}移除对象`); } /** * 从所有容器中移除fabric对象 */ removeFromAllContainers(fabricObject) { // 从画布中移除 this.safeRemoveFromContainer(fabricObject, this.canvas, "画布"); // 从所有组中移除 this.layers.value.forEach((layer) => { if (layer.fabricObject && layer.fabricObject.type === "group") { this.safeRemoveFromContainer( fabricObject, layer.fabricObject, `组${layer.id}` ); } }); } /** * 从顶级图层移动到组图层内 */ moveRootToGroup(draggedLayer) { console.log("📥 执行顶级图层移动到组内:", { layerId: draggedLayer.id, toParentId: this.toParentId, newIndex: this.newIndex, }); const targetParent = this.layers.value.find( (layer) => layer.id === this.toParentId ); if (!targetParent) { throw new Error(`找不到目标父图层: ${this.toParentId}`); } // 确保父图层有children数组 if (!targetParent.children) { targetParent.children = []; } // 从顶级图层数组中移除 const rootIndex = this.layers.value.findIndex( (layer) => layer.id === draggedLayer.id ); if (rootIndex !== -1) { this.layers.value.splice(rootIndex, 1); console.log(`🗑️ 从顶级图层数组中移除图层 ${draggedLayer.id}`); } // 更新图层关系 draggedLayer.parentId = this.toParentId; targetParent.children.splice(this.newIndex, 0, draggedLayer); console.log( `📂 将图层 ${draggedLayer.id} 添加到父图层 ${this.toParentId} 的children中` ); // 处理fabric对象的层级关系 if (draggedLayer.fabricObject && targetParent.fabricObject) { console.log(`🎨 处理fabric对象层级关系`); // 从画布中移除 this.safeRemoveFromContainer( draggedLayer.fabricObject, this.canvas, "画布" ); // 添加到父组 this.safeAddToContainer( draggedLayer.fabricObject, targetParent.fabricObject, `父组${this.toParentId}` ); } console.log("✅ 顶级图层移动到组内完成"); } /** * 从组图层内移动到顶级图层 */ moveGroupToRoot(draggedLayer) { console.log("📤 执行组内图层移动到顶级:", { layerId: draggedLayer.id, fromParentId: this.fromParentId, newIndex: this.newIndex, }); const sourceParent = this.layers.value.find( (layer) => layer.id === this.fromParentId ); if (!sourceParent || !sourceParent.children) { throw new Error(`找不到源父图层或其children数组: ${this.fromParentId}`); } // 从源父图层的children中移除 const childIndex = sourceParent.children.findIndex( (child) => child.id === draggedLayer.id ); if (childIndex !== -1) { sourceParent.children.splice(childIndex, 1); console.log( `🗑️ 从父图层 ${this.fromParentId} 的children中移除图层 ${draggedLayer.id}` ); } // 处理fabric对象的层级关系 if (draggedLayer.fabricObject && sourceParent.fabricObject) { console.log(`🎨 处理fabric对象层级关系`); // 从父组中移除 this.safeRemoveFromContainer( draggedLayer.fabricObject, sourceParent.fabricObject, `父组${this.fromParentId}` ); // 添加到画布 this.safeAddToContainer(draggedLayer.fabricObject, this.canvas, "画布"); } // 清除图层的parentId delete draggedLayer.parentId; console.log(`🔗 清除图层 ${draggedLayer.id} 的parentId`); // 计算在顶级图层中的插入位置 const targetIndex = Math.min(this.newIndex, this.layers.value.length); this.layers.value.splice(targetIndex, 0, draggedLayer); console.log( `📂 将图层 ${draggedLayer.id} 添加到顶级图层数组位置 ${targetIndex}` ); console.log("✅ 组内图层移动到顶级完成"); } /** * 在不同组之间移动 */ moveGroupToGroup(draggedLayer) { console.log("🔄 执行在不同组间移动:", { layerId: draggedLayer.id, fromParentId: this.fromParentId, toParentId: this.toParentId, newIndex: this.newIndex, }); const sourceParent = this.layers.value.find( (layer) => layer.id === this.fromParentId ); const targetParent = this.layers.value.find( (layer) => layer.id === this.toParentId ); if (!sourceParent || !targetParent) { throw new Error("找不到源父图层或目标父图层"); } // 从源父图层中移除 const childIndex = sourceParent.children.findIndex( (child) => child.id === draggedLayer.id ); if (childIndex !== -1) { sourceParent.children.splice(childIndex, 1); console.log( `🗑️ 从源父图层 ${this.fromParentId} 中移除图层 ${draggedLayer.id}` ); // 从源父组的fabricObject中移除 if (draggedLayer.fabricObject && sourceParent.fabricObject) { this.safeRemoveFromContainer( draggedLayer.fabricObject, sourceParent.fabricObject, `源父组${this.fromParentId}` ); } } // 更新图层的parentId draggedLayer.parentId = this.toParentId; console.log( `🔗 更新图层 ${draggedLayer.id} 的parentId为 ${this.toParentId}` ); // 确保目标父图层有children数组 if (!targetParent.children) { targetParent.children = []; } // 将图层添加到目标组 targetParent.children.splice(this.newIndex, 0, draggedLayer); console.log( `📂 将图层 ${draggedLayer.id} 添加到目标父图层 ${this.toParentId} 的位置 ${this.newIndex}` ); // 将图层的fabricObject添加到目标父组中 if (draggedLayer.fabricObject && targetParent.fabricObject) { this.safeAddToContainer( draggedLayer.fabricObject, targetParent.fabricObject, `目标父组${this.toParentId}` ); } console.log("✅ 不同组间移动完成"); } } /** * 创建跨层级移动命令的工厂函数 */ export function createCrossLevelMoveCommand(options) { return new CrossLevelMoveCommand(options); }