持久化支持

This commit is contained in:
2025-07-08 17:42:42 +08:00
parent edac10174c
commit 7d07e98e76
3 changed files with 49 additions and 53 deletions

View File

@@ -14,7 +14,7 @@ import { useVueFlow } from '@vue-flow/core';
import DialogManager from './components/DialogManager.vue';
const filesStore = useFilesStore();
const { updateNode } = useVueFlow();
const { updateNode,toObject,fromObject } = useVueFlow();
const width = ref('100%');
const height = ref('100vh');
@@ -100,6 +100,7 @@ watch(
if (oldVal && flowEditorRef.value && flowEditorRef.value.getViewport) {
const viewport = flowEditorRef.value.getViewport();
filesStore.updateFileViewport(oldVal, viewport);
filesStore.updateFileFlowData(oldVal, toObject());
}
lastActiveFile.value = newVal;
}
@@ -135,9 +136,9 @@ watch(
<FlowEditor
ref="flowEditorRef"
:height="contentHeight"
:nodes="filesStore.activeFileNodes"
:edges="filesStore.activeFileEdges"
:viewport="filesStore.getFileViewport(filesStore.activeFile)"
:nodes="filesStore.getFileFlowData(filesStore.activeFile)?.nodes || []"
:edges="filesStore.getFileFlowData(filesStore.activeFile)?.edges || []"
:viewport="filesStore.getFileFlowData(filesStore.activeFile)?.viewport || { x: 0, y: 0, zoom: 1 }"
:key="filesStore.activeFile"
/>
</div>

View File

@@ -189,18 +189,6 @@ onUnmounted(() => {
const lastActiveFile = ref(filesStore.activeFile);
const flowEditorRef = ref();
watch(
() => filesStore.activeFile,
(newVal, oldVal) => {
// 切换前保存旧 tab 的 viewport
if (oldVal && flowEditorRef.value && flowEditorRef.value.getViewport) {
const viewport = flowEditorRef.value.getViewport();
filesStore.updateFileViewport(oldVal, viewport);
}
lastActiveFile.value = newVal;
}
);
</script>
<template>
@@ -209,8 +197,8 @@ watch(
<!-- 中间流程图区域 -->
<div class="flow-container">
<VueFlow
:nodes="filesStore.activeFileNodes"
:edges="filesStore.activeFileEdges"
:nodes="props.nodes"
:edges="props.edges"
@nodes-change="handleNodesChange"
@edges-change="handleEdgesChange"
@connect="handleConnect"

View File

@@ -15,9 +15,7 @@ interface FlowFile {
visible: boolean;
type: string;
groups: FileGroup[];
nodes?: Node[];
edges?: Edge[];
viewport?: { x: number; y: number; zoom: number };
flowData?: any;
}
export const useFilesStore = defineStore('files', () => {
@@ -33,21 +31,23 @@ export const useFilesStore = defineStore('files', () => {
// 获取当前活动文件的节点和边
const activeFileNodes = computed(() => {
const file = fileList.value.find(f => f.name === activeFile.value);
return file?.nodes || [];
return file?.flowData?.nodes || [];
});
const activeFileEdges = computed(() => {
const file = fileList.value.find(f => f.name === activeFile.value);
return file?.edges || [];
return file?.flowData?.edges || [];
});
// 添加新文件
const addFile = (file: FlowFile) => {
// 确保新文件包含空的节点和边数组
const newFile = {
...file,
flowData: {
nodes: [],
edges: []
edges: [],
viewport: { x: 0, y: 0, zoom: 1 }
}
};
fileList.value.push(newFile);
activeFile.value = file.name;
@@ -72,21 +72,18 @@ export const useFilesStore = defineStore('files', () => {
const addNode = (node: Node) => {
const file = fileList.value.find(f => f.name === activeFile.value);
if (!file) return;
if (!file.nodes) file.nodes = [];
file.nodes.push(node);
if (!file.flowData) file.flowData = { nodes: [], edges: [], viewport: { x: 0, y: 0, zoom: 1 } };
file.flowData.nodes.push(node);
};
// 更新节点
const updateNode = (nodeId: string, updateData: Partial<Node>) => {
const file = fileList.value.find(f => f.name === activeFile.value);
if (!file || !file.nodes) return;
const nodeIndex = file.nodes.findIndex(n => n.id === nodeId);
if (!file || !file.flowData || !file.flowData.nodes) return;
const nodeIndex = file.flowData.nodes.findIndex(n => n.id === nodeId);
if (nodeIndex === -1) return;
file.nodes[nodeIndex] = {
...file.nodes[nodeIndex],
file.flowData.nodes[nodeIndex] = {
...file.flowData.nodes[nodeIndex],
...updateData,
};
};
@@ -94,12 +91,11 @@ export const useFilesStore = defineStore('files', () => {
// 删除节点
const removeNode = (nodeId: string) => {
const file = fileList.value.find(f => f.name === activeFile.value);
if (!file || !file.nodes) return;
file.nodes = file.nodes.filter(n => n.id !== nodeId);
if (!file || !file.flowData || !file.flowData.nodes) return;
file.flowData.nodes = file.flowData.nodes.filter(n => n.id !== nodeId);
// 同时删除相关的边
if (file.edges) {
file.edges = file.edges.filter(e => e.source !== nodeId && e.target !== nodeId);
if (file.flowData.edges) {
file.flowData.edges = file.flowData.edges.filter(e => e.source !== nodeId && e.target !== nodeId);
}
};
@@ -107,25 +103,22 @@ export const useFilesStore = defineStore('files', () => {
const addEdge = (edge: Edge) => {
const file = fileList.value.find(f => f.name === activeFile.value);
if (!file) return;
if (!file.edges) file.edges = [];
file.edges.push(edge);
if (!file.flowData) file.flowData = { nodes: [], edges: [], viewport: { x: 0, y: 0, zoom: 1 } };
file.flowData.edges.push(edge);
};
// 删除边
const removeEdge = (edgeId: string) => {
const file = fileList.value.find(f => f.name === activeFile.value);
if (!file || !file.edges) return;
file.edges = file.edges.filter(e => e.id !== edgeId);
if (!file || !file.flowData || !file.flowData.edges) return;
file.flowData.edges = file.flowData.edges.filter(e => e.id !== edgeId);
};
// 更新节点位置
const updateNodePosition = (nodeId: string, position: { x: number; y: number }) => {
const file = fileList.value.find(f => f.name === activeFile.value);
if (!file || !file.nodes) return;
const node = file.nodes.find(n => n.id === nodeId);
if (!file || !file.flowData || !file.flowData.nodes) return;
const node = file.flowData.nodes.find(n => n.id === nodeId);
if (node) {
node.position = position;
}
@@ -134,25 +127,37 @@ export const useFilesStore = defineStore('files', () => {
// 更新节点顺序
const updateNodesOrder = (nodes: Node[]) => {
const file = fileList.value.find(f => f.name === activeFile.value);
if (!file) return;
file.nodes = nodes;
if (!file || !file.flowData) return;
file.flowData.nodes = nodes;
};
// 更新文件的 viewport
const updateFileViewport = (fileName: string, viewport: { x: number; y: number; zoom: number }) => {
const file = fileList.value.find(f => f.name === fileName);
if (file) file.viewport = viewport;
if (file && file.flowData) file.flowData.viewport = viewport;
};
const getFileViewport = (fileName: string): ViewportTransform => {
const file = fileList.value.find(f => f.name === fileName);
const v = file?.viewport;
const v = file?.flowData?.viewport;
if (v && typeof v.x === 'number' && typeof v.y === 'number' && typeof v.zoom === 'number') {
return v as ViewportTransform;
}
return { x: 0, y: 0, zoom: 1 };
};
// 更新文件的 flowData
const updateFileFlowData = (fileName: string, flowData: any) => {
const file = fileList.value.find(f => f.name === fileName);
if (file) file.flowData = flowData;
};
// 获取文件的 flowData
const getFileFlowData = (fileName: string): any => {
const file = fileList.value.find(f => f.name === fileName);
return file?.flowData;
};
return {
fileList,
activeFile,
@@ -170,5 +175,7 @@ export const useFilesStore = defineStore('files', () => {
updateNodesOrder,
updateFileViewport,
getFileViewport,
updateFileFlowData,
getFileFlowData,
};
});