feat: 删除无用数据与冗余逻辑以提升性能
This commit is contained in:
parent
e38770a496
commit
78737f6839
|
@ -44,7 +44,11 @@
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<!-- 渲染连线 -->
|
<!-- 渲染连线 -->
|
||||||
<svg class="wires-layer absolute top-0 left-0 w-full h-full z-50" width="10000" height="10000">
|
<svg
|
||||||
|
class="wires-layer absolute top-0 left-0 w-full h-full z-50"
|
||||||
|
width="10000"
|
||||||
|
height="10000"
|
||||||
|
>
|
||||||
<!-- 已完成的连线 -->
|
<!-- 已完成的连线 -->
|
||||||
<WireComponent
|
<WireComponent
|
||||||
v-for="(wire, index) in wireItems"
|
v-for="(wire, index) in wireItems"
|
||||||
|
@ -94,7 +98,9 @@
|
||||||
top: component.y + 'px',
|
top: component.y + 'px',
|
||||||
left: component.x + 'px',
|
left: component.x + 'px',
|
||||||
zIndex: component.index ?? 0,
|
zIndex: component.index ?? 0,
|
||||||
transform: component.rotate ? `rotate(${component.rotate}deg)` : 'none',
|
transform: component.rotate
|
||||||
|
? `rotate(${component.rotate}deg)`
|
||||||
|
: 'none',
|
||||||
opacity: component.isOn ? 1 : 0.6,
|
opacity: component.isOn ? 1 : 0.6,
|
||||||
display: 'block',
|
display: 'block',
|
||||||
}"
|
}"
|
||||||
|
@ -185,8 +191,6 @@ import {
|
||||||
saveDiagramData,
|
saveDiagramData,
|
||||||
updatePartPosition,
|
updatePartPosition,
|
||||||
updatePartAttribute,
|
updatePartAttribute,
|
||||||
deletePart,
|
|
||||||
deleteConnection,
|
|
||||||
parseConnectionPin,
|
parseConnectionPin,
|
||||||
connectionArrayToWireItem,
|
connectionArrayToWireItem,
|
||||||
validateDiagramData,
|
validateDiagramData,
|
||||||
|
@ -208,10 +212,7 @@ function handleContextMenu(e: MouseEvent) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 定义组件发出的事件
|
// 定义组件发出的事件
|
||||||
const emit = defineEmits([
|
const emit = defineEmits(["toggle-doc-panel", "open-components"]);
|
||||||
"toggle-doc-panel",
|
|
||||||
"open-components",
|
|
||||||
]);
|
|
||||||
|
|
||||||
// 定义组件接受的属性
|
// 定义组件接受的属性
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
|
@ -367,7 +368,7 @@ const isWireCreationEventActive = ref(false);
|
||||||
// 画布拖拽事件
|
// 画布拖拽事件
|
||||||
useEventListener(document, "mousemove", (e: MouseEvent) => {
|
useEventListener(document, "mousemove", (e: MouseEvent) => {
|
||||||
if (isDragEventActive.value) {
|
if (isDragEventActive.value) {
|
||||||
onDrag(e);
|
onCanvasDrag(e);
|
||||||
}
|
}
|
||||||
if (isComponentDragEventActive.value) {
|
if (isComponentDragEventActive.value) {
|
||||||
onComponentDrag(e);
|
onComponentDrag(e);
|
||||||
|
@ -469,7 +470,7 @@ function startMiddleDrag(e: MouseEvent) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 拖拽画布过程
|
// 拖拽画布过程
|
||||||
function onDrag(e: MouseEvent) {
|
function onCanvasDrag(e: MouseEvent) {
|
||||||
if (!isDragging.value && !isMiddleDragging.value) return;
|
if (!isDragging.value && !isMiddleDragging.value) return;
|
||||||
|
|
||||||
const newX = e.clientX - dragStart.x;
|
const newX = e.clientX - dragStart.x;
|
||||||
|
@ -579,8 +580,7 @@ function onComponentDrag(e: MouseEvent) {
|
||||||
const groupComponents = diagramParts.value.filter(
|
const groupComponents = diagramParts.value.filter(
|
||||||
(p) =>
|
(p) =>
|
||||||
p.group === draggedComponent.group &&
|
p.group === draggedComponent.group &&
|
||||||
p.id !== draggingComponentId.value &&
|
p.id !== draggingComponentId.value,
|
||||||
!p.positionlock,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// 更新这些组件的位置
|
// 更新这些组件的位置
|
||||||
|
@ -608,16 +608,12 @@ function onComponentDrag(e: MouseEvent) {
|
||||||
function stopComponentDrag() {
|
function stopComponentDrag() {
|
||||||
// 如果有组件被拖拽,保存当前状态
|
// 如果有组件被拖拽,保存当前状态
|
||||||
if (draggingComponentId.value) {
|
if (draggingComponentId.value) {
|
||||||
// console.log(`组件拖拽结束: ${draggingComponentId.value}`);
|
|
||||||
|
|
||||||
// 保存图表数据
|
|
||||||
saveDiagramData(diagramData.value);
|
|
||||||
|
|
||||||
// 清除拖动状态
|
|
||||||
draggingComponentId.value = null;
|
draggingComponentId.value = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
isComponentDragEventActive.value = false;
|
isComponentDragEventActive.value = false;
|
||||||
|
|
||||||
|
saveDiagramData(diagramData.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更新组件属性
|
// 更新组件属性
|
||||||
|
@ -637,7 +633,6 @@ function updateComponentProp(
|
||||||
propName,
|
propName,
|
||||||
value,
|
value,
|
||||||
);
|
);
|
||||||
saveDiagramData(diagramData.value);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -815,9 +810,6 @@ function handlePinClick(componentId: string, pinInfo: any, event: MouseEvent) {
|
||||||
connections: [...diagramData.value.connections, newConnection],
|
connections: [...diagramData.value.connections, newConnection],
|
||||||
};
|
};
|
||||||
|
|
||||||
// 保存图表数据
|
|
||||||
saveDiagramData(diagramData.value);
|
|
||||||
|
|
||||||
// 重置连线创建状态
|
// 重置连线创建状态
|
||||||
resetWireCreation();
|
resetWireCreation();
|
||||||
isWireCreationEventActive.value = false;
|
isWireCreationEventActive.value = false;
|
||||||
|
@ -863,12 +855,10 @@ function onCreatingWireMouseMove(e: MouseEvent) {
|
||||||
|
|
||||||
// 删除组件
|
// 删除组件
|
||||||
function deleteComponent(componentId: string) {
|
function deleteComponent(componentId: string) {
|
||||||
diagramData.value = deletePart(diagramData.value, componentId);
|
|
||||||
// 直接通过componentManager删除组件
|
// 直接通过componentManager删除组件
|
||||||
if (componentManager) {
|
if (componentManager) {
|
||||||
componentManager.deleteComponent(componentId);
|
componentManager.deleteComponent(componentId);
|
||||||
}
|
}
|
||||||
saveDiagramData(diagramData.value);
|
|
||||||
|
|
||||||
// 清除选中状态
|
// 清除选中状态
|
||||||
if (selectedComponentId.value === componentId) {
|
if (selectedComponentId.value === componentId) {
|
||||||
|
@ -922,9 +912,6 @@ function handleFileSelected(event: Event) {
|
||||||
// 更新画布数据
|
// 更新画布数据
|
||||||
diagramData.value = parsed as DiagramData;
|
diagramData.value = parsed as DiagramData;
|
||||||
|
|
||||||
// 保存到本地文件
|
|
||||||
saveDiagramData(diagramData.value);
|
|
||||||
|
|
||||||
alertStore?.show(`成功导入diagram文件`, "success");
|
alertStore?.show(`成功导入diagram文件`, "success");
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("解析JSON文件出错:", error);
|
console.error("解析JSON文件出错:", error);
|
||||||
|
@ -988,22 +975,6 @@ function exportDiagram() {
|
||||||
|
|
||||||
// --- 生命周期钩子 ---
|
// --- 生命周期钩子 ---
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
// 设置componentManager的画布引用
|
|
||||||
if (componentManager) {
|
|
||||||
// 创建一个包含必要方法的画布API对象
|
|
||||||
const canvasAPI = {
|
|
||||||
getDiagramData: () => diagramData.value,
|
|
||||||
updateDiagramDataDirectly: (data: DiagramData) => {
|
|
||||||
diagramData.value = data;
|
|
||||||
saveDiagramData(data);
|
|
||||||
},
|
|
||||||
getCanvasPosition: () => componentManager.getCanvasPosition(),
|
|
||||||
getScale: () => componentManager.getCanvasScale(),
|
|
||||||
$el: canvasContainer.value,
|
|
||||||
};
|
|
||||||
componentManager.setCanvasRef(canvasAPI);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 加载图表数据
|
// 加载图表数据
|
||||||
try {
|
try {
|
||||||
diagramData.value = await loadDiagramData();
|
diagramData.value = await loadDiagramData();
|
||||||
|
@ -1061,7 +1032,6 @@ function updateDiagramDataDirectly(data: DiagramData) {
|
||||||
}
|
}
|
||||||
|
|
||||||
diagramData.value = data;
|
diagramData.value = data;
|
||||||
saveDiagramData(data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 暴露方法给父组件
|
// 暴露方法给父组件
|
||||||
|
@ -1070,21 +1040,16 @@ defineExpose({
|
||||||
getDiagramData: () => diagramData.value,
|
getDiagramData: () => diagramData.value,
|
||||||
updateDiagramDataDirectly,
|
updateDiagramDataDirectly,
|
||||||
});
|
});
|
||||||
|
|
||||||
// 监视器 - 当图表数据更改时保存
|
|
||||||
watch(
|
|
||||||
diagramData,
|
|
||||||
(newData) => {
|
|
||||||
saveDiagramData(newData);
|
|
||||||
},
|
|
||||||
{ deep: true },
|
|
||||||
);
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
/* 基础容器样式 - 使用 Tailwind 类替代 */
|
/* 基础容器样式 - 使用 Tailwind 类替代 */
|
||||||
.diagram-container {
|
.diagram-container {
|
||||||
background-size: 20px 20px, 20px 20px, 100px 100px, 100px 100px;
|
background-size:
|
||||||
|
20px 20px,
|
||||||
|
20px 20px,
|
||||||
|
100px 100px,
|
||||||
|
100px 100px;
|
||||||
background-position: 0 0;
|
background-position: 0 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1130,7 +1095,13 @@ watch(
|
||||||
pointer-events: auto;
|
pointer-events: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.component-wrapper :deep(svg *:not([class*="interactive"]):not(rect.glow):not(circle[fill-opacity]):not([fill-opacity])) {
|
.component-wrapper
|
||||||
|
:deep(
|
||||||
|
svg
|
||||||
|
*:not([class*="interactive"]):not(rect.glow):not(
|
||||||
|
circle[fill-opacity]
|
||||||
|
):not([fill-opacity])
|
||||||
|
) {
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
import { ref, shallowRef, computed, reactive } from "vue";
|
import { ref, shallowRef, computed, reactive } from "vue";
|
||||||
import { createInjectionState } from "@vueuse/core";
|
import { createInjectionState } from "@vueuse/core";
|
||||||
import type { DiagramData, DiagramPart } from "./diagramManager";
|
import {
|
||||||
|
saveDiagramData,
|
||||||
|
type DiagramData,
|
||||||
|
type DiagramPart,
|
||||||
|
} from "./diagramManager";
|
||||||
import type { PropertyConfig } from "@/components/equipments/componentConfig";
|
import type { PropertyConfig } from "@/components/equipments/componentConfig";
|
||||||
import {
|
import {
|
||||||
generatePropertyConfigs,
|
generatePropertyConfigs,
|
||||||
|
@ -24,7 +28,9 @@ const [useProvideComponentManager, useComponentManager] = createInjectionState(
|
||||||
// --- 状态管理 ---
|
// --- 状态管理 ---
|
||||||
const componentModules = ref<Record<string, ComponentModule>>({});
|
const componentModules = ref<Record<string, ComponentModule>>({});
|
||||||
const selectedComponentId = ref<string | null>(null);
|
const selectedComponentId = ref<string | null>(null);
|
||||||
const selectedComponentConfig = shallowRef<{ props: PropertyConfig[] } | null>(null);
|
const selectedComponentConfig = shallowRef<{
|
||||||
|
props: PropertyConfig[];
|
||||||
|
} | null>(null);
|
||||||
const diagramCanvas = ref<any>(null);
|
const diagramCanvas = ref<any>(null);
|
||||||
const componentRefs = ref<Record<string, any>>({});
|
const componentRefs = ref<Record<string, any>>({});
|
||||||
|
|
||||||
|
@ -39,7 +45,11 @@ const [useProvideComponentManager, useComponentManager] = createInjectionState(
|
||||||
const canvasInstance = diagramCanvas.value as any;
|
const canvasInstance = diagramCanvas.value as any;
|
||||||
if (canvasInstance && canvasInstance.getDiagramData) {
|
if (canvasInstance && canvasInstance.getDiagramData) {
|
||||||
const data = canvasInstance.getDiagramData();
|
const data = canvasInstance.getDiagramData();
|
||||||
return data.parts.find((p: DiagramPart) => p.id === selectedComponentId.value) || null;
|
return (
|
||||||
|
data.parts.find(
|
||||||
|
(p: DiagramPart) => p.id === selectedComponentId.value,
|
||||||
|
) || null
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
|
@ -86,20 +96,30 @@ const [useProvideComponentManager, useComponentManager] = createInjectionState(
|
||||||
/**
|
/**
|
||||||
* 缩放到指定位置(以鼠标位置为中心)
|
* 缩放到指定位置(以鼠标位置为中心)
|
||||||
*/
|
*/
|
||||||
function zoomAtPosition(mouseX: number, mouseY: number, zoomFactor: number) {
|
function zoomAtPosition(
|
||||||
|
mouseX: number,
|
||||||
|
mouseY: number,
|
||||||
|
zoomFactor: number,
|
||||||
|
) {
|
||||||
// 计算鼠标在画布坐标系中的位置
|
// 计算鼠标在画布坐标系中的位置
|
||||||
const mouseXCanvas = (mouseX - canvasPosition.x) / canvasScale.value;
|
const mouseXCanvas = (mouseX - canvasPosition.x) / canvasScale.value;
|
||||||
const mouseYCanvas = (mouseY - canvasPosition.y) / canvasScale.value;
|
const mouseYCanvas = (mouseY - canvasPosition.y) / canvasScale.value;
|
||||||
|
|
||||||
// 计算新的缩放值
|
// 计算新的缩放值
|
||||||
const newScale = Math.max(0.2, Math.min(canvasScale.value * zoomFactor, 10.0));
|
const newScale = Math.max(
|
||||||
|
0.2,
|
||||||
|
Math.min(canvasScale.value * zoomFactor, 10.0),
|
||||||
|
);
|
||||||
|
|
||||||
// 计算新的位置,使鼠标指针位置在缩放前后保持不变
|
// 计算新的位置,使鼠标指针位置在缩放前后保持不变
|
||||||
canvasPosition.x = mouseX - mouseXCanvas * newScale;
|
canvasPosition.x = mouseX - mouseXCanvas * newScale;
|
||||||
canvasPosition.y = mouseY - mouseYCanvas * newScale;
|
canvasPosition.y = mouseY - mouseYCanvas * newScale;
|
||||||
canvasScale.value = newScale;
|
canvasScale.value = newScale;
|
||||||
|
|
||||||
return { scale: newScale, position: { x: canvasPosition.x, y: canvasPosition.y } };
|
return {
|
||||||
|
scale: newScale,
|
||||||
|
position: { x: canvasPosition.x, y: canvasPosition.y },
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -108,7 +128,7 @@ const [useProvideComponentManager, useComponentManager] = createInjectionState(
|
||||||
function screenToCanvas(screenX: number, screenY: number) {
|
function screenToCanvas(screenX: number, screenY: number) {
|
||||||
return {
|
return {
|
||||||
x: (screenX - canvasPosition.x) / canvasScale.value,
|
x: (screenX - canvasPosition.x) / canvasScale.value,
|
||||||
y: (screenY - canvasPosition.y) / canvasScale.value
|
y: (screenY - canvasPosition.y) / canvasScale.value,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,14 +138,18 @@ const [useProvideComponentManager, useComponentManager] = createInjectionState(
|
||||||
function canvasToScreen(canvasX: number, canvasY: number) {
|
function canvasToScreen(canvasX: number, canvasY: number) {
|
||||||
return {
|
return {
|
||||||
x: canvasX * canvasScale.value + canvasPosition.x,
|
x: canvasX * canvasScale.value + canvasPosition.x,
|
||||||
y: canvasY * canvasScale.value + canvasPosition.y
|
y: canvasY * canvasScale.value + canvasPosition.y,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 居中显示指定区域
|
* 居中显示指定区域
|
||||||
*/
|
*/
|
||||||
function centerView(bounds: { x: number, y: number, width: number, height: number }, containerWidth: number, containerHeight: number) {
|
function centerView(
|
||||||
|
bounds: { x: number; y: number; width: number; height: number },
|
||||||
|
containerWidth: number,
|
||||||
|
containerHeight: number,
|
||||||
|
) {
|
||||||
// 计算合适的缩放比例
|
// 计算合适的缩放比例
|
||||||
const scaleX = containerWidth / bounds.width;
|
const scaleX = containerWidth / bounds.width;
|
||||||
const scaleY = containerHeight / bounds.height;
|
const scaleY = containerHeight / bounds.height;
|
||||||
|
@ -139,7 +163,10 @@ const [useProvideComponentManager, useComponentManager] = createInjectionState(
|
||||||
canvasPosition.x = containerWidth / 2 - centerX * newScale;
|
canvasPosition.x = containerWidth / 2 - centerX * newScale;
|
||||||
canvasPosition.y = containerHeight / 2 - centerY * newScale;
|
canvasPosition.y = containerHeight / 2 - centerY * newScale;
|
||||||
|
|
||||||
return { scale: newScale, position: { x: canvasPosition.x, y: canvasPosition.y } };
|
return {
|
||||||
|
scale: newScale,
|
||||||
|
position: { x: canvasPosition.x, y: canvasPosition.y },
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- 组件模块管理 ---
|
// --- 组件模块管理 ---
|
||||||
|
@ -180,7 +207,7 @@ const [useProvideComponentManager, useComponentManager] = createInjectionState(
|
||||||
async function preloadComponentModules(componentTypes: string[]) {
|
async function preloadComponentModules(componentTypes: string[]) {
|
||||||
console.log("Preloading component modules:", componentTypes);
|
console.log("Preloading component modules:", componentTypes);
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
componentTypes.map((type) => loadComponentModule(type))
|
componentTypes.map((type) => loadComponentModule(type)),
|
||||||
);
|
);
|
||||||
console.log("All component modules loaded");
|
console.log("All component modules loaded");
|
||||||
}
|
}
|
||||||
|
@ -222,8 +249,10 @@ const [useProvideComponentManager, useComponentManager] = createInjectionState(
|
||||||
const viewportWidth = canvasContainer.clientWidth;
|
const viewportWidth = canvasContainer.clientWidth;
|
||||||
const viewportHeight = canvasContainer.clientHeight;
|
const viewportHeight = canvasContainer.clientHeight;
|
||||||
|
|
||||||
position.x = (viewportWidth / 2 - canvasPosition.x) / canvasScale.value;
|
position.x =
|
||||||
position.y = (viewportHeight / 2 - canvasPosition.y) / canvasScale.value;
|
(viewportWidth / 2 - canvasPosition.x) / canvasScale.value;
|
||||||
|
position.y =
|
||||||
|
(viewportHeight / 2 - canvasPosition.y) / canvasScale.value;
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("获取画布位置时出错:", error);
|
console.error("获取画布位置时出错:", error);
|
||||||
|
@ -264,17 +293,21 @@ const [useProvideComponentManager, useComponentManager] = createInjectionState(
|
||||||
};
|
};
|
||||||
|
|
||||||
// 通过画布实例添加组件
|
// 通过画布实例添加组件
|
||||||
if (canvasInstance.getDiagramData && canvasInstance.updateDiagramDataDirectly) {
|
if (
|
||||||
|
canvasInstance.getDiagramData &&
|
||||||
|
canvasInstance.updateDiagramDataDirectly
|
||||||
|
) {
|
||||||
const currentData = canvasInstance.getDiagramData();
|
const currentData = canvasInstance.getDiagramData();
|
||||||
currentData.parts.push(newComponent);
|
currentData.parts.push(newComponent);
|
||||||
|
|
||||||
// 使用 updateDiagramDataDirectly 避免触发加载状态
|
// 使用 updateDiagramDataDirectly 避免触发加载状态
|
||||||
canvasInstance.updateDiagramDataDirectly(currentData);
|
canvasInstance.updateDiagramDataDirectly(currentData);
|
||||||
|
saveDiagramData(currentData);
|
||||||
|
|
||||||
console.log("组件添加完成:", newComponent);
|
console.log("组件添加完成:", newComponent);
|
||||||
|
|
||||||
// 等待Vue的下一个tick,确保组件模块已经更新
|
// 等待Vue的下一个tick,确保组件模块已经更新
|
||||||
await new Promise(resolve => setTimeout(resolve, 50));
|
await new Promise((resolve) => setTimeout(resolve, 50));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -289,7 +322,10 @@ const [useProvideComponentManager, useComponentManager] = createInjectionState(
|
||||||
console.log("添加模板:", templateData);
|
console.log("添加模板:", templateData);
|
||||||
|
|
||||||
const canvasInstance = diagramCanvas.value as any;
|
const canvasInstance = diagramCanvas.value as any;
|
||||||
if (!canvasInstance?.getDiagramData || !canvasInstance?.updateDiagramDataDirectly) {
|
if (
|
||||||
|
!canvasInstance?.getDiagramData ||
|
||||||
|
!canvasInstance?.updateDiagramDataDirectly
|
||||||
|
) {
|
||||||
console.error("没有可用的画布实例添加模板");
|
console.error("没有可用的画布实例添加模板");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -309,8 +345,10 @@ const [useProvideComponentManager, useComponentManager] = createInjectionState(
|
||||||
if (canvasContainer) {
|
if (canvasContainer) {
|
||||||
const viewportWidth = canvasContainer.clientWidth;
|
const viewportWidth = canvasContainer.clientWidth;
|
||||||
const viewportHeight = canvasContainer.clientHeight;
|
const viewportHeight = canvasContainer.clientHeight;
|
||||||
viewportCenter.x = (viewportWidth / 2 - canvasPosition.x) / canvasScale.value;
|
viewportCenter.x =
|
||||||
viewportCenter.y = (viewportHeight / 2 - canvasPosition.y) / canvasScale.value;
|
(viewportWidth / 2 - canvasPosition.x) / canvasScale.value;
|
||||||
|
viewportCenter.y =
|
||||||
|
(viewportHeight / 2 - canvasPosition.y) / canvasScale.value;
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("获取视口中心位置时出错:", error);
|
console.error("获取视口中心位置时出错:", error);
|
||||||
|
@ -339,7 +377,10 @@ const [useProvideComponentManager, useComponentManager] = createInjectionState(
|
||||||
}
|
}
|
||||||
|
|
||||||
// 计算新位置
|
// 计算新位置
|
||||||
if (typeof newPart.x === "number" && typeof newPart.y === "number") {
|
if (
|
||||||
|
typeof newPart.x === "number" &&
|
||||||
|
typeof newPart.y === "number"
|
||||||
|
) {
|
||||||
const relativeX = part.x - mainPart.x;
|
const relativeX = part.x - mainPart.x;
|
||||||
const relativeY = part.y - mainPart.y;
|
const relativeY = part.y - mainPart.y;
|
||||||
newPart.x = viewportCenter.x + relativeX;
|
newPart.x = viewportCenter.x + relativeX;
|
||||||
|
@ -347,7 +388,7 @@ const [useProvideComponentManager, useComponentManager] = createInjectionState(
|
||||||
}
|
}
|
||||||
|
|
||||||
return newPart;
|
return newPart;
|
||||||
})
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
currentData.parts.push(...newParts);
|
currentData.parts.push(...newParts);
|
||||||
|
@ -359,32 +400,38 @@ const [useProvideComponentManager, useComponentManager] = createInjectionState(
|
||||||
idMap[part.id] = `${idPrefix}${part.id}`;
|
idMap[part.id] = `${idPrefix}${part.id}`;
|
||||||
});
|
});
|
||||||
|
|
||||||
const newConnections = templateData.template.connections.map((conn: any) => {
|
const newConnections = templateData.template.connections.map(
|
||||||
if (Array.isArray(conn)) {
|
(conn: any) => {
|
||||||
const [from, to, type, path] = conn;
|
if (Array.isArray(conn)) {
|
||||||
const fromParts = from.split(":");
|
const [from, to, type, path] = conn;
|
||||||
const toParts = to.split(":");
|
const fromParts = from.split(":");
|
||||||
|
const toParts = to.split(":");
|
||||||
|
|
||||||
if (fromParts.length === 2 && toParts.length === 2) {
|
if (fromParts.length === 2 && toParts.length === 2) {
|
||||||
const fromComponentId = fromParts[0];
|
const fromComponentId = fromParts[0];
|
||||||
const fromPinId = fromParts[1];
|
const fromPinId = fromParts[1];
|
||||||
const toComponentId = toParts[0];
|
const toComponentId = toParts[0];
|
||||||
const toPinId = toParts[1];
|
const toPinId = toParts[1];
|
||||||
|
|
||||||
const newFrom = `${idMap[fromComponentId] || fromComponentId}:${fromPinId}`;
|
const newFrom = `${idMap[fromComponentId] || fromComponentId}:${fromPinId}`;
|
||||||
const newTo = `${idMap[toComponentId] || toComponentId}:${toPinId}`;
|
const newTo = `${idMap[toComponentId] || toComponentId}:${toPinId}`;
|
||||||
|
|
||||||
return [newFrom, newTo, type, path];
|
return [newFrom, newTo, type, path];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
return conn;
|
||||||
return conn;
|
},
|
||||||
});
|
);
|
||||||
|
|
||||||
currentData.connections.push(...newConnections);
|
currentData.connections.push(...newConnections);
|
||||||
}
|
}
|
||||||
|
|
||||||
canvasInstance.updateDiagramDataDirectly(currentData);
|
canvasInstance.updateDiagramDataDirectly(currentData);
|
||||||
console.log("=== 更新图表数据完成,新组件数量:", currentData.parts.length);
|
console.log(
|
||||||
|
"=== 更新图表数据完成,新组件数量:",
|
||||||
|
currentData.parts.length,
|
||||||
|
);
|
||||||
|
saveDiagramData(currentData);
|
||||||
|
|
||||||
return { success: true, message: `已添加 ${templateData.name} 模板` };
|
return { success: true, message: `已添加 ${templateData.name} 模板` };
|
||||||
} else {
|
} else {
|
||||||
|
@ -398,12 +445,17 @@ const [useProvideComponentManager, useComponentManager] = createInjectionState(
|
||||||
*/
|
*/
|
||||||
function deleteComponent(componentId: string) {
|
function deleteComponent(componentId: string) {
|
||||||
const canvasInstance = diagramCanvas.value as any;
|
const canvasInstance = diagramCanvas.value as any;
|
||||||
if (!canvasInstance?.getDiagramData || !canvasInstance?.updateDiagramDataDirectly) {
|
if (
|
||||||
|
!canvasInstance?.getDiagramData ||
|
||||||
|
!canvasInstance?.updateDiagramDataDirectly
|
||||||
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const currentData = canvasInstance.getDiagramData();
|
const currentData = canvasInstance.getDiagramData();
|
||||||
const component = currentData.parts.find((p: DiagramPart) => p.id === componentId);
|
const component = currentData.parts.find(
|
||||||
|
(p: DiagramPart) => p.id === componentId,
|
||||||
|
);
|
||||||
|
|
||||||
if (!component) return;
|
if (!component) return;
|
||||||
|
|
||||||
|
@ -412,34 +464,47 @@ const [useProvideComponentManager, useComponentManager] = createInjectionState(
|
||||||
// 处理组件组
|
// 处理组件组
|
||||||
if (component.group && component.group !== "") {
|
if (component.group && component.group !== "") {
|
||||||
const groupMembers = currentData.parts.filter(
|
const groupMembers = currentData.parts.filter(
|
||||||
(p: DiagramPart) => p.group === component.group && p.id !== componentId
|
(p: DiagramPart) =>
|
||||||
|
p.group === component.group && p.id !== componentId,
|
||||||
);
|
);
|
||||||
componentsToDelete.push(...groupMembers.map((p: DiagramPart) => p.id));
|
componentsToDelete.push(...groupMembers.map((p: DiagramPart) => p.id));
|
||||||
console.log(`删除组件 ${componentId} 及其组 ${component.group} 中的 ${groupMembers.length} 个组件`);
|
console.log(
|
||||||
|
`删除组件 ${componentId} 及其组 ${component.group} 中的 ${groupMembers.length} 个组件`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 删除组件
|
// 删除组件
|
||||||
currentData.parts = currentData.parts.filter(
|
currentData.parts = currentData.parts.filter(
|
||||||
(p: DiagramPart) => !componentsToDelete.includes(p.id)
|
(p: DiagramPart) => !componentsToDelete.includes(p.id),
|
||||||
);
|
);
|
||||||
|
|
||||||
// 删除相关连接
|
// 删除相关连接
|
||||||
currentData.connections = currentData.connections.filter((connection: any) => {
|
currentData.connections = currentData.connections.filter(
|
||||||
for (const id of componentsToDelete) {
|
(connection: any) => {
|
||||||
if (connection[0].startsWith(`${id}:`) || connection[1].startsWith(`${id}:`)) {
|
for (const id of componentsToDelete) {
|
||||||
return false;
|
if (
|
||||||
|
connection[0].startsWith(`${id}:`) ||
|
||||||
|
connection[1].startsWith(`${id}:`)
|
||||||
|
) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
return true;
|
||||||
return true;
|
},
|
||||||
});
|
);
|
||||||
|
|
||||||
// 清除选中状态
|
// 清除选中状态
|
||||||
if (selectedComponentId.value && componentsToDelete.includes(selectedComponentId.value)) {
|
if (
|
||||||
|
selectedComponentId.value &&
|
||||||
|
componentsToDelete.includes(selectedComponentId.value)
|
||||||
|
) {
|
||||||
selectedComponentId.value = null;
|
selectedComponentId.value = null;
|
||||||
selectedComponentConfig.value = null;
|
selectedComponentConfig.value = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
canvasInstance.updateDiagramDataDirectly(currentData);
|
canvasInstance.updateDiagramDataDirectly(currentData);
|
||||||
|
|
||||||
|
saveDiagramData(currentData);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -470,16 +535,18 @@ const [useProvideComponentManager, useComponentManager] = createInjectionState(
|
||||||
// 添加组件直接属性
|
// 添加组件直接属性
|
||||||
const directPropConfigs = generatePropertyConfigs(componentData);
|
const directPropConfigs = generatePropertyConfigs(componentData);
|
||||||
const newDirectProps = directPropConfigs.filter(
|
const newDirectProps = directPropConfigs.filter(
|
||||||
(config) => !addedProps.has(config.name)
|
(config) => !addedProps.has(config.name),
|
||||||
);
|
);
|
||||||
propConfigs.push(...newDirectProps);
|
propConfigs.push(...newDirectProps);
|
||||||
|
|
||||||
// 添加 attrs 中的属性
|
// 添加 attrs 中的属性
|
||||||
if (componentData.attrs) {
|
if (componentData.attrs) {
|
||||||
const attrPropConfigs = generatePropsFromAttrs(componentData.attrs);
|
const attrPropConfigs = generatePropsFromAttrs(
|
||||||
|
componentData.attrs,
|
||||||
|
);
|
||||||
attrPropConfigs.forEach((attrConfig) => {
|
attrPropConfigs.forEach((attrConfig) => {
|
||||||
const existingIndex = propConfigs.findIndex(
|
const existingIndex = propConfigs.findIndex(
|
||||||
(p) => p.name === attrConfig.name
|
(p) => p.name === attrConfig.name,
|
||||||
);
|
);
|
||||||
if (existingIndex >= 0) {
|
if (existingIndex >= 0) {
|
||||||
propConfigs[existingIndex] = attrConfig;
|
propConfigs[existingIndex] = attrConfig;
|
||||||
|
@ -490,9 +557,15 @@ const [useProvideComponentManager, useComponentManager] = createInjectionState(
|
||||||
}
|
}
|
||||||
|
|
||||||
selectedComponentConfig.value = { props: propConfigs };
|
selectedComponentConfig.value = { props: propConfigs };
|
||||||
console.log(`Built config for ${componentData.type}:`, selectedComponentConfig.value);
|
console.log(
|
||||||
|
`Built config for ${componentData.type}:`,
|
||||||
|
selectedComponentConfig.value,
|
||||||
|
);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`Error building config for ${componentData.type}:`, error);
|
console.error(
|
||||||
|
`Error building config for ${componentData.type}:`,
|
||||||
|
error,
|
||||||
|
);
|
||||||
selectedComponentConfig.value = { props: [] };
|
selectedComponentConfig.value = { props: [] };
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -505,9 +578,16 @@ const [useProvideComponentManager, useComponentManager] = createInjectionState(
|
||||||
/**
|
/**
|
||||||
* 更新组件属性
|
* 更新组件属性
|
||||||
*/
|
*/
|
||||||
function updateComponentProp(componentId: string, propName: string, value: any) {
|
function updateComponentProp(
|
||||||
|
componentId: string,
|
||||||
|
propName: string,
|
||||||
|
value: any,
|
||||||
|
) {
|
||||||
const canvasInstance = diagramCanvas.value as any;
|
const canvasInstance = diagramCanvas.value as any;
|
||||||
if (!canvasInstance?.getDiagramData || !canvasInstance?.updateDiagramDataDirectly) {
|
if (
|
||||||
|
!canvasInstance?.getDiagramData ||
|
||||||
|
!canvasInstance?.updateDiagramDataDirectly
|
||||||
|
) {
|
||||||
console.error("没有可用的画布实例进行属性更新");
|
console.error("没有可用的画布实例进行属性更新");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -518,7 +598,9 @@ const [useProvideComponentManager, useComponentManager] = createInjectionState(
|
||||||
}
|
}
|
||||||
|
|
||||||
const currentData = canvasInstance.getDiagramData();
|
const currentData = canvasInstance.getDiagramData();
|
||||||
const part = currentData.parts.find((p: DiagramPart) => p.id === componentId);
|
const part = currentData.parts.find(
|
||||||
|
(p: DiagramPart) => p.id === componentId,
|
||||||
|
);
|
||||||
|
|
||||||
if (part) {
|
if (part) {
|
||||||
if (propName in part) {
|
if (propName in part) {
|
||||||
|
@ -531,27 +613,44 @@ const [useProvideComponentManager, useComponentManager] = createInjectionState(
|
||||||
}
|
}
|
||||||
|
|
||||||
canvasInstance.updateDiagramDataDirectly(currentData);
|
canvasInstance.updateDiagramDataDirectly(currentData);
|
||||||
console.log(`更新组件${componentId}的属性${propName}为:`, value, typeof value);
|
console.log(
|
||||||
|
`更新组件${componentId}的属性${propName}为:`,
|
||||||
|
value,
|
||||||
|
typeof value,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 更新组件直接属性
|
* 更新组件直接属性
|
||||||
*/
|
*/
|
||||||
function updateComponentDirectProp(componentId: string, propName: string, value: any) {
|
function updateComponentDirectProp(
|
||||||
|
componentId: string,
|
||||||
|
propName: string,
|
||||||
|
value: any,
|
||||||
|
) {
|
||||||
const canvasInstance = diagramCanvas.value as any;
|
const canvasInstance = diagramCanvas.value as any;
|
||||||
if (!canvasInstance?.getDiagramData || !canvasInstance?.updateDiagramDataDirectly) {
|
if (
|
||||||
|
!canvasInstance?.getDiagramData ||
|
||||||
|
!canvasInstance?.updateDiagramDataDirectly
|
||||||
|
) {
|
||||||
console.error("没有可用的画布实例进行属性更新");
|
console.error("没有可用的画布实例进行属性更新");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const currentData = canvasInstance.getDiagramData();
|
const currentData = canvasInstance.getDiagramData();
|
||||||
const part = currentData.parts.find((p: DiagramPart) => p.id === componentId);
|
const part = currentData.parts.find(
|
||||||
|
(p: DiagramPart) => p.id === componentId,
|
||||||
|
);
|
||||||
|
|
||||||
if (part) {
|
if (part) {
|
||||||
(part as any)[propName] = value;
|
(part as any)[propName] = value;
|
||||||
canvasInstance.updateDiagramDataDirectly(currentData);
|
canvasInstance.updateDiagramDataDirectly(currentData);
|
||||||
console.log(`更新组件${componentId}的直接属性${propName}为:`, value, typeof value);
|
console.log(
|
||||||
|
`更新组件${componentId}的直接属性${propName}为:`,
|
||||||
|
value,
|
||||||
|
typeof value,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -560,12 +659,17 @@ const [useProvideComponentManager, useComponentManager] = createInjectionState(
|
||||||
*/
|
*/
|
||||||
function moveComponent(moveData: { id: string; x: number; y: number }) {
|
function moveComponent(moveData: { id: string; x: number; y: number }) {
|
||||||
const canvasInstance = diagramCanvas.value as any;
|
const canvasInstance = diagramCanvas.value as any;
|
||||||
if (!canvasInstance?.getDiagramData || !canvasInstance?.updateDiagramDataDirectly) {
|
if (
|
||||||
|
!canvasInstance?.getDiagramData ||
|
||||||
|
!canvasInstance?.updateDiagramDataDirectly
|
||||||
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const currentData = canvasInstance.getDiagramData();
|
const currentData = canvasInstance.getDiagramData();
|
||||||
const part = currentData.parts.find((p: DiagramPart) => p.id === moveData.id);
|
const part = currentData.parts.find(
|
||||||
|
(p: DiagramPart) => p.id === moveData.id,
|
||||||
|
);
|
||||||
if (part) {
|
if (part) {
|
||||||
part.x = moveData.x;
|
part.x = moveData.x;
|
||||||
part.y = moveData.y;
|
part.y = moveData.y;
|
||||||
|
@ -606,7 +710,13 @@ const [useProvideComponentManager, useComponentManager] = createInjectionState(
|
||||||
if (canvasInstance && canvasInstance.getDiagramData) {
|
if (canvasInstance && canvasInstance.getDiagramData) {
|
||||||
return canvasInstance.getDiagramData();
|
return canvasInstance.getDiagramData();
|
||||||
}
|
}
|
||||||
return { parts: [], connections: [], version: 1, author: "admin", editor: "me" };
|
return {
|
||||||
|
parts: [],
|
||||||
|
connections: [],
|
||||||
|
version: 1,
|
||||||
|
author: "admin",
|
||||||
|
editor: "me",
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -722,7 +832,7 @@ const [useProvideComponentManager, useComponentManager] = createInjectionState(
|
||||||
canvasToScreen,
|
canvasToScreen,
|
||||||
centerView,
|
centerView,
|
||||||
};
|
};
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
export { useProvideComponentManager, useComponentManager };
|
export { useProvideComponentManager, useComponentManager };
|
||||||
|
|
|
@ -123,14 +123,6 @@ export function saveDiagramData(data: DiagramData): void {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 添加新组件到图表数据
|
|
||||||
export function addPart(data: DiagramData, part: DiagramPart): DiagramData {
|
|
||||||
return {
|
|
||||||
...data,
|
|
||||||
parts: [...data.parts, part]
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// 更新组件位置
|
// 更新组件位置
|
||||||
export function updatePartPosition(
|
export function updatePartPosition(
|
||||||
data: DiagramData,
|
data: DiagramData,
|
||||||
|
@ -171,42 +163,6 @@ export function updatePartAttribute(
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// 删除组件及同组组件
|
|
||||||
export function deletePart(data: DiagramData, partId: string): DiagramData {
|
|
||||||
// 首先找到要删除的组件
|
|
||||||
const component = data.parts.find(part => part.id === partId);
|
|
||||||
if (!component) return data;
|
|
||||||
|
|
||||||
// 收集需要删除的组件ID列表
|
|
||||||
const componentsToDelete: string[] = [partId];
|
|
||||||
|
|
||||||
// 如果组件属于一个组,则找出所有同组的组件
|
|
||||||
if (component.group && component.group !== '') {
|
|
||||||
const groupMembers = data.parts.filter(
|
|
||||||
p => p.group === component.group && p.id !== partId
|
|
||||||
);
|
|
||||||
|
|
||||||
// 将同组组件ID添加到删除列表
|
|
||||||
componentsToDelete.push(...groupMembers.map(p => p.id));
|
|
||||||
console.log(`删除组件 ${partId} 及其组 ${component.group} 中的 ${groupMembers.length} 个组件`);
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
...data,
|
|
||||||
// 删除所有标记的组件
|
|
||||||
parts: data.parts.filter(part => !componentsToDelete.includes(part.id)),
|
|
||||||
// 删除与这些组件相关的所有连接
|
|
||||||
connections: data.connections.filter(conn => {
|
|
||||||
const [startPin, endPin] = conn;
|
|
||||||
const startCompId = startPin.split(':')[0];
|
|
||||||
const endCompId = endPin.split(':')[0];
|
|
||||||
|
|
||||||
// 检查连接两端的组件是否在删除列表中
|
|
||||||
return !componentsToDelete.includes(startCompId) && !componentsToDelete.includes(endCompId);
|
|
||||||
})
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// 添加连接
|
// 添加连接
|
||||||
export function addConnection(
|
export function addConnection(
|
||||||
data: DiagramData,
|
data: DiagramData,
|
||||||
|
@ -256,25 +212,6 @@ export function findConnectionsByPart(
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 基于组的移动相关组件
|
|
||||||
export function moveGroupComponents(
|
|
||||||
data: DiagramData,
|
|
||||||
groupId: string,
|
|
||||||
deltaX: number,
|
|
||||||
deltaY: number
|
|
||||||
): DiagramData {
|
|
||||||
if (!groupId) return data;
|
|
||||||
|
|
||||||
return {
|
|
||||||
...data,
|
|
||||||
parts: data.parts.map(part =>
|
|
||||||
part.group === groupId
|
|
||||||
? { ...part, x: part.x + deltaX, y: part.y + deltaY }
|
|
||||||
: part
|
|
||||||
)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// 添加验证diagram.json文件的函数
|
// 添加验证diagram.json文件的函数
|
||||||
export function validateDiagramData(data: any): { isValid: boolean; errors: string[] } {
|
export function validateDiagramData(data: any): { isValid: boolean; errors: string[] } {
|
||||||
const errors: string[] = [];
|
const errors: string[] = [];
|
||||||
|
|
|
@ -98,7 +98,6 @@ const props = defineProps<{
|
||||||
const propertySectionExpanded = ref(false); // 基本属性区域默认展开
|
const propertySectionExpanded = ref(false); // 基本属性区域默认展开
|
||||||
const pinsSectionExpanded = ref(false); // 引脚配置区域默认折叠
|
const pinsSectionExpanded = ref(false); // 引脚配置区域默认折叠
|
||||||
const componentCapsExpanded = ref(true); // 组件功能区域默认展开
|
const componentCapsExpanded = ref(true); // 组件功能区域默认展开
|
||||||
const wireSectionExpanded = ref(false); // 连线管理区域默认折叠
|
|
||||||
|
|
||||||
const componentCaps = useTemplateRef("ComponentCapabilities");
|
const componentCaps = useTemplateRef("ComponentCapabilities");
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue