Files
aida_front/src/component/Canvas/CanvasEditor/commands/CrossLevelMoveCommands.js
2025-07-14 01:00:23 +08:00

713 lines
21 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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;
}
async 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("🎨 画布已刷新");
// }
await this.layerManager?.updateLayersObjectsInteractivity();
this.canvas?.renderAll();
// 生成缩略图
this.fromParentId &&
this.layerManager?.canvasManager?.thumbnailManager?.generateLayerThumbnail?.(
this.fromParentId
);
this.toParentId &&
this.layerManager?.canvasManager?.thumbnailManager?.generateLayerThumbnail?.(
this.toParentId
);
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;
}
}
async undo() {
if (!this.beforeState) {
throw new Error("没有保存的前置状态,无法撤销");
}
console.log("🔄 撤销跨层级移动命令");
try {
// 恢复图层结构
this.restoreLayerStructure(this.beforeState.layerStructure);
// 恢复fabric对象状态
this.restoreFabricObjectStates(this.beforeState.fabricObjects);
await this.layerManager?.updateLayersObjectsInteractivity();
// 刷新画布
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();
}
}
/**
* 重做命令
*/
async redo() {
if (!this.afterState) {
throw new Error("没有保存的后置状态,无法重做");
}
console.log("🔄 重做跨层级移动命令");
try {
// 恢复图层结构
this.restoreLayerStructure(this.afterState.layerStructure);
// 恢复fabric对象状态
this.restoreFabricObjectStates(this.afterState.fabricObjects);
await this.layerManager?.updateLayersObjectsInteractivity();
// 刷新画布
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);
}