持久化支持

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

View File

@@ -189,18 +189,6 @@ onUnmounted(() => {
const lastActiveFile = ref(filesStore.activeFile); const lastActiveFile = ref(filesStore.activeFile);
const flowEditorRef = ref(); 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> </script>
<template> <template>
@@ -209,8 +197,8 @@ watch(
<!-- 中间流程图区域 --> <!-- 中间流程图区域 -->
<div class="flow-container"> <div class="flow-container">
<VueFlow <VueFlow
:nodes="filesStore.activeFileNodes" :nodes="props.nodes"
:edges="filesStore.activeFileEdges" :edges="props.edges"
@nodes-change="handleNodesChange" @nodes-change="handleNodesChange"
@edges-change="handleEdgesChange" @edges-change="handleEdgesChange"
@connect="handleConnect" @connect="handleConnect"

View File

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