From 6f702693227180e2f69cded8a325d1b1491688d8 Mon Sep 17 00:00:00 2001 From: rookie4show Date: Sun, 28 Dec 2025 13:08:58 +0800 Subject: [PATCH] =?UTF-8?q?feat(flow):=20=E5=A2=9E=E5=8A=A0=E6=98=BE?= =?UTF-8?q?=E7=A4=BA=E5=85=A8=E9=83=A8=E6=8C=89=E9=92=AE=E5=B9=B6=E7=BB=9F?= =?UTF-8?q?=E4=B8=80=E5=8F=AF=E6=93=8D=E4=BD=9C=E8=8A=82=E7=82=B9=E8=BF=87?= =?UTF-8?q?=E6=BB=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/flow/FlowEditor.vue | 52 ++++++++++++++++++++++++------ 1 file changed, 43 insertions(+), 9 deletions(-) diff --git a/src/components/flow/FlowEditor.vue b/src/components/flow/FlowEditor.vue index 05d95e1..bc580a6 100644 --- a/src/components/flow/FlowEditor.vue +++ b/src/components/flow/FlowEditor.vue @@ -14,6 +14,7 @@ 对齐线已开启 已选 {{ selectedCount }} +
对齐
@@ -184,6 +185,19 @@ function updateNodeMeta(model: BaseNodeModel, updater: (meta: Record { + const meta = ensureMeta((model.getProperties?.() as any)?.meta ?? (model as any)?.properties?.meta); + if (!includeHidden && meta.visible === false) return false; + if (!includeLocked && meta.locked) return false; + return true; + }); +} + function getSelectedNodeModels() { const graphModel = lf.value?.graphModel; if (!graphModel) return []; @@ -214,7 +228,7 @@ function collectGroupNodeIds(models: BaseNodeModel[]) { function moveSelectedNodes(deltaX: number, deltaY: number) { const graphModel = lf.value?.graphModel; if (!graphModel) return; - const targets = collectGroupNodeIds(getSelectedNodeModels()); + const targets = collectGroupNodeIds(getSelectedNodeModelsFiltered()); if (!targets.length) return; graphModel.moveNodes(targets, deltaX, deltaY); } @@ -224,7 +238,8 @@ function deleteSelectedElements(event?: KeyboardEvent) { const lfInstance = lf.value; if (!lfInstance) return true; - const { nodes, edges } = lfInstance.getSelectElements(true); + const { edges } = lfInstance.getSelectElements(true); + const nodes = getSelectedNodeModelsFiltered({ includeHidden: false, includeLocked: true }); const lockedNodes = nodes.filter((node) => ensureMeta((node as any).properties?.meta).locked); edges.forEach((edge) => edge.id && lfInstance.deleteEdge(edge.id)); nodes @@ -258,7 +273,7 @@ function toggleLockSelected(event?: KeyboardEvent) { function toggleVisibilitySelected(event?: KeyboardEvent) { if (shouldSkipShortcut(event)) return true; - const models = getSelectedNodeModels(); + const models = getSelectedNodeModelsFiltered({ includeLocked: true }); if (!models.length) { showMessage('info', '请选择节点后再执行显示/隐藏'); return true; @@ -274,9 +289,31 @@ function toggleVisibilitySelected(event?: KeyboardEvent) { return false; } +function showAllNodes() { + const lfInstance = lf.value; + if (!lfInstance) return; + let changed = 0; + lfInstance.graphModel?.nodes.forEach((model: BaseNodeModel) => { + const props = (model.getProperties?.() as any) ?? (model as any)?.properties ?? {}; + const meta = ensureMeta(props.meta); + if (meta.visible === false) { + meta.visible = true; + lfInstance.setProperties(model.id, { ...props, meta }); + applyMetaToModel(model, meta); + changed += 1; + } + }); + if (changed > 0) { + showMessage('success', `已显示 ${changed} 个节点`); + } else { + showMessage('info', '没有隐藏的节点'); + } + updateSelectedCount(); +} + function groupSelectedNodes(event?: KeyboardEvent) { if (shouldSkipShortcut(event)) return true; - const models = getSelectedNodeModels().filter((model) => !ensureMeta((model.getProperties?.() as any)?.meta).locked); + const models = getSelectedNodeModelsFiltered(); if (models.length < 2) { showMessage('warning', '请选择至少两个未锁定的节点进行分组'); return true; @@ -406,11 +443,8 @@ function applySnapGrid(enabled: boolean) { function getSelectedRects() { const lfInstance = lf.value; if (!lfInstance) return []; - const unlocked = lfInstance.graphModel.selectNodes.filter((model: BaseNodeModel) => { - const meta = ensureMeta((model.getProperties?.() as any)?.meta ?? (model as any)?.properties?.meta); - return !meta.locked && meta.visible !== false; - }); - return unlocked.map((model: BaseNodeModel) => { + const actionable = getSelectedNodeModelsFiltered(); + return actionable.map((model: BaseNodeModel) => { const bounds = model.getBounds(); const width = bounds.maxX - bounds.minX; const height = bounds.maxY - bounds.minY;