From 99231ce52c224d9721551e437c8b00b8b23c0ab0 Mon Sep 17 00:00:00 2001 From: rookie4show Date: Fri, 11 Jul 2025 17:15:25 +0800 Subject: [PATCH] =?UTF-8?q?FlowEditor.vue=E9=87=8D=E5=86=99=EF=BC=8C?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E7=BB=93=E6=9E=84=E8=B0=83=E6=95=B4=EF=BC=8C?= =?UTF-8?q?=E9=87=8D=E6=96=B0=E5=AE=9E=E7=8E=B0=E6=95=B0=E6=8D=AE=E6=8C=81?= =?UTF-8?q?=E4=B9=85=E5=8C=96=E5=92=8C=E7=94=BB=E5=B8=83=E7=BC=A9=E6=94=BE?= =?UTF-8?q?=E4=BF=9D=E5=AD=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/App.vue | 44 ++-- src/components/flow/FlowEditor.vue | 408 +++++++++-------------------- src/ts/useStore.ts | 109 ++++++-- 3 files changed, 248 insertions(+), 313 deletions(-) diff --git a/src/App.vue b/src/App.vue index 1e81d94..b5d00f1 100644 --- a/src/App.vue +++ b/src/App.vue @@ -10,11 +10,11 @@ import FlowEditor from './components/flow/FlowEditor.vue'; import ShikigamiSelect from './components/flow/nodes/yys/ShikigamiSelect.vue'; import YuhunSelect from './components/flow/nodes/yys/YuhunSelect.vue'; import PropertySelect from './components/flow/nodes/yys/PropertySelect.vue'; -import { useVueFlow } from '@vue-flow/core'; +// import { useVueFlow } from '@vue-flow/core'; import DialogManager from './components/DialogManager.vue'; const filesStore = useFilesStore(); -const { updateNode,toObject,fromObject } = useVueFlow(); +// const { updateNode,toObject,fromObject } = useVueFlow(); const width = ref('100%'); const height = ref('100vh'); @@ -89,23 +89,37 @@ const handleAddNode = (nodeData) => { } }; -const handleSaveViewport = (viewport) => { - filesStore.updateFileViewport(filesStore.activeFile, viewport); -}; -const handleRequestViewport = () => { - return filesStore.getFileViewport(filesStore.activeFile); -}; - watch( () => filesStore.activeFile, - (newVal, oldVal) => { - // 切换前保存旧 tab 的 viewport - if (oldVal && flowEditorRef.value && flowEditorRef.value.getViewport) { - const viewport = flowEditorRef.value.getViewport(); - filesStore.updateFileViewport(oldVal, viewport); - filesStore.updateFileFlowData(oldVal, toObject()); + async (newVal, oldVal) => { + // 切换前保存旧 tab 的数据和视口 + if (oldVal && flowEditorRef.value) { + if (flowEditorRef.value.getGraphRawData) { + const rawData = flowEditorRef.value.getGraphRawData(); + filesStore.updateFileFlowData(oldVal, rawData); + } + if (flowEditorRef.value.getViewport) { + const viewport = flowEditorRef.value.getViewport(); + console.log(`[Tab切换] 切换前保存 tab "${oldVal}" 的视口信息:`, viewport); + filesStore.updateFileViewport(oldVal, viewport); + } } lastActiveFile.value = newVal; + + // 切换后恢复新 tab 的数据和视口 + if (newVal && flowEditorRef.value) { + if (flowEditorRef.value.renderRawData) { + const newRawData = filesStore.getFileFlowData(newVal); + if (newRawData) flowEditorRef.value.renderRawData(newRawData); + } + if (flowEditorRef.value.setViewport) { + const newViewport = filesStore.getFileViewport(newVal); + console.log(`[Tab切换] 切换后恢复 tab "${newVal}" 的视口信息:`, newViewport); + requestAnimationFrame(() => { + flowEditorRef.value.setViewport(newViewport); + }); + } + } } ); diff --git a/src/components/flow/FlowEditor.vue b/src/components/flow/FlowEditor.vue index 5810db9..2e2ab1a 100644 --- a/src/components/flow/FlowEditor.vue +++ b/src/components/flow/FlowEditor.vue @@ -1,283 +1,137 @@ - - + + \ No newline at end of file + \ No newline at end of file diff --git a/src/ts/useStore.ts b/src/ts/useStore.ts index 7a9248a..16a9176 100644 --- a/src/ts/useStore.ts +++ b/src/ts/useStore.ts @@ -1,6 +1,6 @@ import { defineStore } from 'pinia'; import { ref, computed } from 'vue'; -import type { Edge, Node, ViewportTransform } from '@vue-flow/core'; +// import type { Edge, Node, ViewportTransform } from '@vue-flow/core'; import { ElMessageBox } from "element-plus"; import { useGlobalMessage } from "./useGlobalMessage"; @@ -8,24 +8,88 @@ const { showMessage } = useGlobalMessage(); function getDefaultState() { return { - fileList: [{ - "label": "File 1", - "name": "1", - "visible": true, - "type": "FLOW", - "groups": [ - { - "shortDescription": "", - "groupInfo": [{}, {}, {}, {}, {}], - "details": "" + fileList: [ + { + label: "File 1", + name: "1", + visible: true, + type: "FLOW", + groups: [ + { + shortDescription: "File 1 Group", + groupInfo: [{}, {}, {}, {}, {}], + details: "File 1 详情" + } + ], + flowData: { + nodes: [ + { + id: "node-1", + type: "rect", + x: 100, + y: 100, + text: "File1-矩形节点" + }, + { + id: "node-2", + type: "ellipse", + x: 350, + y: 120, + text: "File1-圆形节点" + } + ], + edges: [ + { + id: "edge-1", + type: "polyline", + sourceNodeId: "node-1", + targetNodeId: "node-2" + } + ], + viewport: { x: 0, y: 0, zoom: 1 } + } + }, + { + label: "File 2", + name: "2", + visible: true, + type: "FLOW", + groups: [ + { + shortDescription: "File 2 Group", + groupInfo: [{}, {}, {}, {}, {}], + details: "File 2 详情" + } + ], + flowData: { + nodes: [ + { + id: "node-1", + type: "rect", + x: 100, + y: 100, + text: "File2-矩形节点" + }, + { + id: "node-2", + type: "ellipse", + x: 350, + y: 120, + text: "File2222-圆形节点" + } + ], + edges: [ + { + id: "edge-1", + type: "polyline", + sourceNodeId: "node-1", + targetNodeId: "node-2" + } + ], + viewport: { x: 0, y: 0, zoom: 1 } } - ], - "flowData": { - "nodes": [], - "edges": [], - "viewport": { "x": 0, "y": 0, "zoom": 1 } } - }], + ], activeFile: "1", }; } @@ -157,7 +221,7 @@ export const useFilesStore = defineStore('files', () => { }; // 添加边 - const addEdge = (edge: Edge) => { + const addEdge = (edge) => { const file = fileList.value.find(f => f.name === activeFile.value); if (!file) return; if (!file.flowData) file.flowData = { nodes: [], edges: [], viewport: { x: 0, y: 0, zoom: 1 } }; @@ -191,14 +255,17 @@ export const useFilesStore = defineStore('files', () => { // 更新文件的 viewport const updateFileViewport = (fileName: string, viewport: { x: number; y: number; zoom: number }) => { const file = fileList.value.find(f => f.name === fileName); - if (file && file.flowData) file.flowData.viewport = viewport; + if (file && file.flowData) { + console.log(`[updateFileViewport] 保存 tab "${fileName}" 的视口信息:`, viewport); + file.flowData.viewport = viewport; + } }; - const getFileViewport = (fileName: string): ViewportTransform => { + const getFileViewport = (fileName: string) => { const file = fileList.value.find(f => f.name === fileName); const v = file?.flowData?.viewport; if (v && typeof v.x === 'number' && typeof v.y === 'number' && typeof v.zoom === 'number') { - return v as ViewportTransform; + return v ; } return { x: 0, y: 0, zoom: 1 }; };