refactor:持续解耦合

This commit is contained in:
2025-07-09 16:32:17 +08:00
parent 91b00a977c
commit 3a292c0a98
10 changed files with 183 additions and 231 deletions

View File

@@ -83,15 +83,15 @@
}
">
<!-- 动态渲染组件 -->
<component :is="getComponentDefinition(component.type)"
v-if="props.componentModules[component.type] && getComponentDefinition(component.type)"
v-bind="prepareComponentProps(component.attrs || {}, component.id)" @update:bindKey="
<component :is="componentManager.getComponentDefinition(component.type)"
v-if="componentManager.componentModules.value[component.type] && componentManager.getComponentDefinition(component.type)"
v-bind="componentManager.prepareComponentProps(component.attrs || {}, component.id)" @update:bindKey="
(value: string) =>
updateComponentProp(component.id, 'bindKey', value)
" @pin-click="
(pinInfo: any) =>
handlePinClick(component.id, pinInfo, pinInfo.originalEvent)
" :ref="(el: any) => setComponentRef(component.id, el)" />
" :ref="(el: any) => componentManager.setComponentRef(component.id, el)" />
<!-- Fallback if component module not loaded yet -->
<div v-else
@@ -99,7 +99,7 @@
<div class="flex flex-col items-center">
<div class="loading loading-spinner loading-xs mb-1"></div>
<span>Loading {{ component.type }}...</span>
<small class="mt-1 text-xs">{{ props.componentModules[component.type] ? 'Module loaded but invalid' : 'Module not found' }}</small>
<small class="mt-1 text-xs">{{ componentManager.componentModules.value[component.type] ? 'Module loaded but invalid' : 'Module not found' }}</small>
</div>
</div>
</div>
@@ -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<string, any>;
showDocPanel?: boolean; // 添加属性接收文档面板的显示状态
}>();
@@ -214,8 +214,8 @@ const diagramData = ref<DiagramData>({
connections: [],
});
// 组件引用跟踪
const componentRefs = ref<Record<string, any>>({});
// 组件引用跟踪(保留以便向后兼容)
const componentRefs = computed(() => componentManager?.componentRefs.value || {});
// 计算属性:从 diagramData 中提取组件列表并按index属性排序
const diagramParts = computed<DiagramPart[]>(() => {
@@ -259,7 +259,7 @@ const wireItems = computed<WireItem[]>(() => {
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<WireItem[]>(() => {
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<HTMLInputElement | null>(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<string, any>,
componentId?: string,
): Record<string, any> {
const result: Record<string, any> = { ...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 },
);
</script>
<style scoped>