diff --git a/src/components/LabCanvas/DiagramCanvas.vue b/src/components/LabCanvas/DiagramCanvas.vue index 5014645..2c4cc0c 100644 --- a/src/components/LabCanvas/DiagramCanvas.vue +++ b/src/components/LabCanvas/DiagramCanvas.vue @@ -83,15 +83,15 @@ } "> - + " :ref="(el: any) => componentManager.setComponentRef(component.id, el)" />
Loading {{ component.type }}... - {{ props.componentModules[component.type] ? 'Module loaded but invalid' : 'Module not found' }} + {{ componentManager.componentModules.value[component.type] ? 'Module loaded but invalid' : 'Module not found' }}
@@ -138,6 +138,7 @@ import { watch, provide, } from "vue"; +import { useEventListener } from "@vueuse/core"; import WireComponent from "@/components/equipments/Wire.vue"; // 导入 diagram 管理器 @@ -151,17 +152,17 @@ import { parseConnectionPin, connectionArrayToWireItem, validateDiagramData, -} from "./diagramManager"; +} from "./composable/diagramManager"; import type { DiagramData, DiagramPart, ConnectionArray, WireItem, -} from "./diagramManager"; +} from "./composable/diagramManager"; import { CanvasCurrentSelectedComponentID } from "../InjectKeys"; -import { useComponentManager } from "./componentManager"; +import { useComponentManager } from "./composable/componentManager"; // 右键菜单处理函数 function handleContextMenu(e: MouseEvent) { @@ -179,7 +180,6 @@ const emit = defineEmits([ // 定义组件接受的属性 const props = defineProps<{ - componentModules: Record; showDocPanel?: boolean; // 添加属性接收文档面板的显示状态 }>(); @@ -214,8 +214,8 @@ const diagramData = ref({ connections: [], }); -// 组件引用跟踪 -const componentRefs = ref>({}); +// 组件引用跟踪(保留以便向后兼容) +const componentRefs = computed(() => componentManager?.componentRefs.value || {}); // 计算属性:从 diagramData 中提取组件列表,并按index属性排序 const diagramParts = computed(() => { @@ -259,7 +259,7 @@ const wireItems = computed(() => { startPos.y = startComp.y; // 尝试获取引脚精确位置(如果有实现) - const startCompRef = componentRefs.value?.[startCompId]; + const startCompRef = componentManager?.getComponentRef(startCompId); if (startCompRef && typeof startCompRef.getPinPosition === "function") { try { const pinPos = startCompRef.getPinPosition(startPinId); @@ -285,7 +285,7 @@ const wireItems = computed(() => { endPos.y = endComp.y; // 尝试获取引脚精确位置 - const endCompRef = componentRefs.value?.[endCompId]; + const endCompRef = componentManager?.getComponentRef(endCompId); if (endCompRef && typeof endCompRef.getPinPosition === "function") { try { const pinPos = endCompRef.getPinPosition(endPinId); @@ -330,6 +330,37 @@ const toastTimers: number[] = []; // 文件选择引用 const fileInput = ref(null); +// VueUse事件监听器状态管理 +const isDragEventActive = ref(false); +const isComponentDragEventActive = ref(false); +const isWireCreationEventActive = ref(false); + +// 使用VueUse设置事件监听器 +// 画布拖拽事件 +useEventListener(document, 'mousemove', (e: MouseEvent) => { + if (isDragEventActive.value) { + onDrag(e); + } + if (isComponentDragEventActive.value) { + onComponentDrag(e); + } + if (isWireCreationEventActive.value) { + onCreatingWireMouseMove(e); + } +}); + +useEventListener(document, 'mouseup', () => { + if (isDragEventActive.value) { + stopDrag(); + } + if (isComponentDragEventActive.value) { + stopComponentDrag(); + } +}); + +// 键盘事件 +useEventListener(window, 'keydown', handleKeyDown); + // --- 缩放功能 --- const MIN_SCALE = 0.2; const MAX_SCALE = 10.0; @@ -367,76 +398,6 @@ function onZoom(e: WheelEvent) { scale.value = newScale; } -// --- 动态组件渲染 --- -const getComponentDefinition = (type: string) => { - const module = props.componentModules[type]; - - if (!module) { - console.warn(`No module found for component type: ${type}`); - // 尝试异步加载组件模块 - loadComponentModule(type); - return null; - } - - // 确保我们返回一个有效的组件定义 - if (module.default) { - return module.default; - } else if (module.__esModule && module.default) { - // 有时 Vue 的动态导入会将默认导出包装在 __esModule 属性下 - return module.default; - } else { - console.warn( - `Module for ${type} found but default export is missing`, - module, - ); - return null; - } -}; - -function prepareComponentProps( - attrs: Record, - componentId?: string, -): Record { - const result: Record = { ...attrs }; - if (componentId) { - result.componentId = componentId; - } - // console.log(`组件属性 ID: ${componentId}`, result); - return result; -} - -// 设置组件引用 -function setComponentRef(componentId: string, el: any) { - if (componentRefs.value) { - if (el) { - componentRefs.value[componentId] = el; - } else { - delete componentRefs.value[componentId]; - } - } -} - -// 重置组件引用缓存 -function resetComponentRefs() { - componentRefs.value = {}; -} - -// 加载组件模块 -async function loadComponentModule(type: string) { - if (!props.componentModules[type]) { - try { - // 直接通过componentManager加载组件模块 - if (componentManager) { - await componentManager.loadComponentModule(type); - // 强制更新当前组件,确保新加载的模块能被识别 - console.log(`Component module ${type} loaded successfully`); - } - } catch (error) { - console.error(`Failed to request component module ${type}:`, error); - } - } -} - // --- 画布交互逻辑 --- function handleCanvasMouseDown(e: MouseEvent) { // 如果是直接点击画布(而不是元器件),清除选中状态 @@ -468,8 +429,7 @@ function startDrag(e: MouseEvent) { dragStart.x = e.clientX - position.x; dragStart.y = e.clientY - position.y; - document.addEventListener("mousemove", onDrag); - document.addEventListener("mouseup", stopDrag); + isDragEventActive.value = true; e.preventDefault(); } @@ -484,8 +444,7 @@ function startMiddleDrag(e: MouseEvent) { dragStart.x = e.clientX - position.x; dragStart.y = e.clientY - position.y; - document.addEventListener("mousemove", onDrag); - document.addEventListener("mouseup", stopDrag); + isDragEventActive.value = true; e.preventDefault(); } @@ -501,9 +460,7 @@ function onDrag(e: MouseEvent) { function stopDrag() { isDragging.value = false; isMiddleDragging.value = false; - - document.removeEventListener("mousemove", onDrag); - document.removeEventListener("mouseup", stopDrag); + isDragEventActive.value = false; } // --- 组件拖拽交互 --- @@ -558,9 +515,8 @@ function startComponentDrag(e: MouseEvent, component: DiagramPart) { componentDragOffset.x = mouseX_canvas - component.x; componentDragOffset.y = mouseY_canvas - component.y; - // 添加全局监听器 - document.addEventListener("mousemove", onComponentDrag); - document.addEventListener("mouseup", stopComponentDrag); + // 激活组件拖拽事件监听 + isComponentDragEventActive.value = true; } // 拖拽组件过程 @@ -589,14 +545,6 @@ function onComponentDrag(e: MouseEvent) { ); if (!draggedComponent) return; - // 更新组件位置 - // diagramData.value = updatePartPosition( - // diagramData.value, - // draggingComponentId.value, - // Math.round(newX), - // Math.round(newY), - // ); - // 如果组件属于组,移动组内所有其他组件 if (draggedComponent.group) { const deltaX = Math.round(newX) - draggedComponent.x; @@ -647,8 +595,7 @@ function stopComponentDrag() { draggingComponentId.value = null; } - document.removeEventListener("mousemove", onComponentDrag); - document.removeEventListener("mouseup", stopComponentDrag); + isComponentDragEventActive.value = false; } // 更新组件属性 @@ -700,8 +647,6 @@ function handlePinClick(componentId: string, pinInfo: any, event: MouseEvent) { console.log("鼠标位置:", mousePosition); if (!isCreatingWire.value) { - // 开始创建连线 - const containerRect = canvasContainer.value.getBoundingClientRect(); // 获取初始位置信息 let pinPosition = pinInfo.position; console.log("Pin信息:", pinInfo); @@ -710,7 +655,7 @@ function handlePinClick(componentId: string, pinInfo: any, event: MouseEvent) { console.log("引脚ID:", pinId); // 从组件引用中获取组件实例 - const component = componentRefs.value[componentId]; + const component = componentManager?.getComponentRef(componentId); console.log("组件引用:", component); // 查找组件部件对象以获取组件位置 @@ -771,7 +716,7 @@ function handlePinClick(componentId: string, pinInfo: any, event: MouseEvent) { pinId, pinInfo.constraint, ); - document.addEventListener("mousemove", onCreatingWireMouseMove); + isWireCreationEventActive.value = true; } else { // 完成连线创建 if ( @@ -786,7 +731,7 @@ function handlePinClick(componentId: string, pinInfo: any, event: MouseEvent) { // 获取终点引脚位置 let endPosition = { x: 0, y: 0 }; const componentPart = diagramParts.value.find((p) => p.id === componentId); - const endComponent = componentRefs.value[componentId]; + const endComponent = componentManager?.getComponentRef(componentId); console.log("终点组件部件:", componentPart); console.log("终点组件引用:", endComponent); @@ -848,7 +793,7 @@ function handlePinClick(componentId: string, pinInfo: any, event: MouseEvent) { // 重置连线创建状态 resetWireCreation(); - document.removeEventListener("mousemove", onCreatingWireMouseMove); + isWireCreationEventActive.value = false; } } @@ -881,7 +826,7 @@ function resetWireCreation() { // 取消连线创建 function cancelWireCreation() { resetWireCreation(); - document.removeEventListener("mousemove", onCreatingWireMouseMove); + isWireCreationEventActive.value = false; } // 连线创建过程中的鼠标移动 @@ -1053,9 +998,6 @@ function showToast( // --- 生命周期钩子 --- onMounted(async () => { - // 重置组件引用 - resetComponentRefs(); - // 设置componentManager的画布引用 if (componentManager) { // 创建一个包含必要方法的画布API对象 @@ -1102,9 +1044,6 @@ onMounted(async () => { position.x = canvasContainer.value.clientWidth / 2 - 5000; // 画布宽度的一半 position.y = canvasContainer.value.clientHeight / 2 - 5000; // 画布高度的一半 } - - // 添加键盘事件监听器 - window.addEventListener("keydown", handleKeyDown); }); // 处理键盘事件 @@ -1123,32 +1062,15 @@ function handleKeyDown(e: KeyboardEvent) { } onUnmounted(() => { - // 清理事件监听器 - document.removeEventListener("mousemove", onComponentDrag); - document.removeEventListener("mouseup", stopComponentDrag); - document.removeEventListener("mousemove", onDrag); - document.removeEventListener("mouseup", stopDrag); - document.removeEventListener("mousemove", onCreatingWireMouseMove); - - // 移除键盘事件监听器 - window.removeEventListener("keydown", handleKeyDown); - // 清除所有toast定时器 toastTimers.forEach((timerId) => clearTimeout(timerId)); + + // 重置事件状态 + isDragEventActive.value = false; + isComponentDragEventActive.value = false; + isWireCreationEventActive.value = false; }); -// --- 对外API --- -// 获取当前图表数据 -function getDiagramData() { - return diagramData.value; -} - -// 设置图表数据 -function setDiagramData(data: DiagramData) { - diagramData.value = data; - emit("diagram-updated", data); -} - // 无加载动画的数据更新方法 function updateDiagramDataDirectly(data: DiagramData) { // 检查组件是否仍然挂载 @@ -1218,15 +1140,6 @@ watch( }, { deep: true }, ); - -// 当组件模块加载完成后,确保组件引用正确建立 -watch( - () => props.componentModules, - () => { - // 这里不需要特别处理,Vue 会自动通过 setComponentRef 函数更新引用 - }, - { deep: true }, -);