feat: 完善选区功能,新增组图层自由编辑

This commit is contained in:
bighuixiang
2025-07-08 01:08:45 +08:00
parent 0615ab31f9
commit 5cc93aeba4
7 changed files with 1751 additions and 161 deletions

View File

@@ -4,6 +4,7 @@ import { findLayerRecursively, isGroupLayer } from "../../utils/layerHelper";
import ContextMenu from "./ContextMenu.vue";
import LayerItem from "./LayerItem.vue";
import LayersList from "./LayersList.vue"; // 引入 LayersList 组件
import { createCrossLevelMoveCommand } from "../../commands/CrossLevelMoveCommands";
// // 导入命令类
// import {
// ReorderLayersCommand,
@@ -605,6 +606,7 @@ function handleLayerClick(layer, event) {
} else {
// 否则直接设置当前图层为活动图层
setActiveLayer(layer.id);
layerManager?.updateLayersObjectsInteractivity();
}
}
lastSelectedIndex.value = sortableRootLayers.value.findIndex(
@@ -1215,6 +1217,316 @@ function moveLayerToBottom(layerId) {
const forwardEvent = (eventName, ...args) => {
emit(eventName, ...args);
};
// 处理跨层级移动
async function handleCrossLevelMove(moveData) {
console.log("🔀 处理跨层级移动:", moveData);
const {
layerId,
fromContainerType,
toContainerType,
fromParentId,
toParentId,
newIndex,
oldIndex,
} = moveData;
// 基本验证
if (!layerId) {
console.error("❌ 缺少图层ID");
return;
}
try {
// 如果有命令管理器,使用命令模式
if (commandManager) {
console.log("📝 使用命令模式执行跨层级移动");
const command = createCrossLevelMoveCommand({
layers,
layerManager,
canvas: layerManager?.canvas,
layerId,
fromContainerType,
toContainerType,
fromParentId,
toParentId,
newIndex,
oldIndex,
});
// 执行命令
const result = await commandManager.executeCommand(command);
if (result) {
console.log("✅ 跨层级移动命令执行成功");
// 清除选择状态
clearSelection();
} else {
console.warn("⚠️ 跨层级移动命令执行失败");
}
return result;
} else {
// 回退方案:直接执行移动逻辑
console.log("📝 使用回退方案执行跨层级移动");
return await executeDirectMove(moveData);
}
} catch (error) {
console.error("❌ 跨层级移动失败:", error);
// 可以在这里添加用户友好的错误提示
const errorMessages = {
找不到要移动的图层: "无法找到要移动的图层,请刷新页面后重试",
背景层和固定层不能移动: "背景层和固定层无法移动",
不能将图层移动到自己的子层级中: "无法将图层移动到自己的子层级中",
目标图层不是组图层: "只能将图层移动到组图层中",
};
const userMessage =
errorMessages[error.message] || `移动失败: ${error.message}`;
// 这里可以触发一个全局的错误提示组件
// 暂时使用console.warn实际项目中应该替换为适当的提示方式
console.warn("用户提示:", userMessage);
}
}
// 直接执行移动的回退方案(保持原有逻辑)
async function executeDirectMove(moveData) {
const {
layerId,
fromContainerType,
toContainerType,
fromParentId,
toParentId,
newIndex,
oldIndex,
} = moveData;
// 查找被拖拽的图层
let draggedLayer = null;
let sourceParent = null;
// 根据源容器类型查找图层
if (fromContainerType === "root") {
draggedLayer = layers.value.find((layer) => layer.id === layerId);
} else if (fromContainerType === "child" && fromParentId) {
sourceParent = layers.value.find((layer) => layer.id === fromParentId);
if (sourceParent && sourceParent.children) {
draggedLayer = sourceParent.children.find(
(child) => child.id === layerId
);
}
}
if (!draggedLayer) {
throw new Error("找不到要移动的图层");
}
// 检查是否允许移动(背景层和固定层不能移动)
if (draggedLayer.isBackground || draggedLayer.isFixed) {
throw new Error("背景层和固定层不能移动");
}
// 情况1: 从顶级图层移动到组图层内
if (fromContainerType === "root" && toContainerType === "child") {
await moveRootToGroup(draggedLayer, toParentId, newIndex);
}
// 情况2: 从组图层内移动到顶级图层
else if (fromContainerType === "child" && toContainerType === "root") {
await moveGroupToRoot(draggedLayer, fromParentId, newIndex);
}
// 情况3: 在不同组之间移动
else if (
fromContainerType === "child" &&
toContainerType === "child" &&
fromParentId !== toParentId
) {
await moveGroupToGroup(draggedLayer, fromParentId, toParentId, newIndex);
}
// 刷新画布渲染
if (layerManager?.canvas) {
layerManager.canvas.renderAll();
}
// 清除选择状态
clearSelection();
console.log("✅ 跨层级移动完成");
return true;
}
// 从顶级图层移动到组图层内
async function moveRootToGroup(draggedLayer, toParentId, newIndex) {
console.log("📥 顶级图层移动到组内:", {
layerId: draggedLayer.id,
toParentId,
newIndex,
});
// 找到目标父图层
const targetParent = layers.value.find((layer) => layer.id === toParentId);
if (!targetParent) {
throw new Error(`找不到目标父图层: ${toParentId}`);
}
// 检查目标父图层是否为组
if (!isGroupLayerType(targetParent)) {
throw new Error("目标图层不是组图层");
}
// 确保父图层有children数组
if (!targetParent.children) {
targetParent.children = [];
}
// 从顶级图层数组中移除
const rootIndex = layers.value.findIndex(
(layer) => layer.id === draggedLayer.id
);
if (rootIndex !== -1) {
layers.value.splice(rootIndex, 1);
}
// 使用 layerManager 的方法移动图层到组内
if (layerManager?.moveLayerToGroup) {
await layerManager.moveLayerToGroup(draggedLayer.id, toParentId, newIndex);
} else {
// 回退方案:手动更新图层关系
draggedLayer.parentId = toParentId;
targetParent.children.splice(newIndex, 0, draggedLayer);
// 处理 fabricObject 的层级关系
if (draggedLayer.fabricObject && targetParent.fabricObject) {
if (layerManager?.canvas) {
layerManager.canvas.remove(draggedLayer.fabricObject);
}
targetParent.fabricObject.add(draggedLayer.fabricObject);
}
}
console.log("✅ 成功将图层移动到组内");
}
// 从组图层内移动到顶级图层
async function moveGroupToRoot(draggedLayer, fromParentId, newIndex) {
console.log("📤 组内图层移动到顶级:", {
layerId: draggedLayer.id,
fromParentId,
newIndex,
});
// 找到源父图层
const sourceParent = layers.value.find((layer) => layer.id === fromParentId);
if (!sourceParent || !sourceParent.children) {
throw new Error(`找不到源父图层或其children数组: ${fromParentId}`);
}
// 使用 layerManager 的方法移动图层到顶级
if (layerManager?.moveLayerToRoot) {
await layerManager.moveLayerToRoot(draggedLayer.id, newIndex);
} else {
// 回退方案:手动更新图层关系
// 从源父图层的children中移除
const childIndex = sourceParent.children.findIndex(
(child) => child.id === draggedLayer.id
);
if (childIndex !== -1) {
sourceParent.children.splice(childIndex, 1);
}
// 处理 fabricObject 的层级关系
if (draggedLayer.fabricObject && sourceParent.fabricObject) {
sourceParent.fabricObject.remove(draggedLayer.fabricObject);
if (layerManager?.canvas) {
layerManager.canvas.add(draggedLayer.fabricObject);
}
}
// 清除图层的parentId
delete draggedLayer.parentId;
// 计算在顶级图层中的插入位置
const targetIndex = Math.min(newIndex, layers.value.length);
// 将图层添加到顶级图层的指定位置
layers.value.splice(targetIndex, 0, draggedLayer);
}
console.log("✅ 成功将图层移动到顶级");
}
// 在不同组之间移动
async function moveGroupToGroup(
draggedLayer,
fromParentId,
toParentId,
newIndex
) {
console.log("🔄 在不同组间移动:", {
layerId: draggedLayer.id,
fromParentId,
toParentId,
newIndex,
});
// 找到源父图层和目标父图层
const sourceParent = layers.value.find((layer) => layer.id === fromParentId);
const targetParent = layers.value.find((layer) => layer.id === toParentId);
if (!sourceParent || !targetParent) {
throw new Error("找不到源父图层或目标父图层");
}
if (!isGroupLayerType(targetParent)) {
throw new Error("目标图层不是组图层");
}
// 使用 layerManager 的方法在组间移动
if (layerManager?.moveLayerBetweenGroups) {
await layerManager.moveLayerBetweenGroups(
draggedLayer.id,
fromParentId,
toParentId,
newIndex
);
} else {
// 回退方案:手动更新图层关系
// 从源父图层中移除
const childIndex = sourceParent.children.findIndex(
(child) => child.id === draggedLayer.id
);
if (childIndex !== -1) {
sourceParent.children.splice(childIndex, 1);
// 从源父组的fabricObject中移除
if (draggedLayer.fabricObject && sourceParent.fabricObject) {
sourceParent.fabricObject.remove(draggedLayer.fabricObject);
}
}
// 更新图层的parentId
draggedLayer.parentId = toParentId;
// 确保目标父图层有children数组
if (!targetParent.children) {
targetParent.children = [];
}
// 将图层添加到目标组
targetParent.children.splice(newIndex, 0, draggedLayer);
// 将图层的fabricObject添加到目标父组中
if (draggedLayer.fabricObject && targetParent.fabricObject) {
targetParent.fabricObject.add(draggedLayer.fabricObject);
}
}
console.log("✅ 成功在不同组间移动图层");
}
</script>
<template>
@@ -1327,6 +1639,7 @@ const forwardEvent = (eventName, ...args) => {
@update:editing-name="editingLayerName = $event"
@root-layers-sort="handleRootLayersSort"
@child-layers-sort="handleChildLayersSort"
@cross-level-move="handleCrossLevelMove"
@select-child-layer="selectChildLayer"
@start-child-layer-edit="startChildLayerEdit"
@child-context-menu="showChildLayerContextMenu"