fix: 修复条件节点收起后分支连线丢失
- 在 tinyflow 条件节点收起态保留分支 handle,避免连线因 DOM 卸载消失 - 在节点折叠切换后刷新 xyflow 内部信息,确保连线锚点位置同步
This commit is contained in:
@@ -1,5 +1,12 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import {Handle, type NodeProps, NodeToolbar, Position, useSvelteFlow} from '@xyflow/svelte';
|
import {
|
||||||
|
Handle,
|
||||||
|
type NodeProps,
|
||||||
|
NodeToolbar,
|
||||||
|
Position,
|
||||||
|
useSvelteFlow,
|
||||||
|
useUpdateNodeInternals
|
||||||
|
} from '@xyflow/svelte';
|
||||||
import {Button, Collapse, FloatingTrigger, Input, Textarea} from '../base';
|
import {Button, Collapse, FloatingTrigger, Input, Textarea} from '../base';
|
||||||
import {type Snippet} from 'svelte';
|
import {type Snippet} from 'svelte';
|
||||||
import {useDeleteNode} from '../utils/useDeleteNode.svelte';
|
import {useDeleteNode} from '../utils/useDeleteNode.svelte';
|
||||||
@@ -41,6 +48,7 @@
|
|||||||
|
|
||||||
let activeKeys = data.expand ? ['key'] : [];
|
let activeKeys = data.expand ? ['key'] : [];
|
||||||
const { updateNodeData, getNode } = useSvelteFlow();
|
const { updateNodeData, getNode } = useSvelteFlow();
|
||||||
|
const updateNodeInternals = useUpdateNodeInternals();
|
||||||
|
|
||||||
const items = $derived.by(() => {
|
const items = $derived.by(() => {
|
||||||
return [{
|
return [{
|
||||||
@@ -244,6 +252,7 @@
|
|||||||
<div class="tf-node-wrapper-body">
|
<div class="tf-node-wrapper-body">
|
||||||
<Collapse {items} activeKeys={activeKeys} onChange={(_,actionKeys) => {
|
<Collapse {items} activeKeys={activeKeys} onChange={(_,actionKeys) => {
|
||||||
updateNodeData(id, {expand: actionKeys?.includes('key')})
|
updateNodeData(id, {expand: actionKeys?.includes('key')})
|
||||||
|
updateNodeInternals(id);
|
||||||
onCollapse?.(actionKeys?.includes('key') ? 'key' : '')
|
onCollapse?.(actionKeys?.includes('key') ? 'key' : '')
|
||||||
}} />
|
}} />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,6 +1,13 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import NodeWrapper from '../core/NodeWrapper.svelte';
|
import NodeWrapper from '../core/NodeWrapper.svelte';
|
||||||
import {type Edge, Handle, type NodeProps, Position, useSvelteFlow} from '@xyflow/svelte';
|
import {
|
||||||
|
type Edge,
|
||||||
|
Handle,
|
||||||
|
type NodeProps,
|
||||||
|
Position,
|
||||||
|
useSvelteFlow,
|
||||||
|
useUpdateNodeInternals
|
||||||
|
} from '@xyflow/svelte';
|
||||||
import {Button, Input, MixedInput, Select} from '../base';
|
import {Button, Input, MixedInput, Select} from '../base';
|
||||||
import ParamTokenEditor from '../core/ParamTokenEditor.svelte';
|
import ParamTokenEditor from '../core/ParamTokenEditor.svelte';
|
||||||
import {getCurrentNodeId} from '#components/utils/NodeUtils';
|
import {getCurrentNodeId} from '#components/utils/NodeUtils';
|
||||||
@@ -75,6 +82,7 @@
|
|||||||
|
|
||||||
const currentNodeId = getCurrentNodeId();
|
const currentNodeId = getCurrentNodeId();
|
||||||
const { updateNodeData } = useSvelteFlow();
|
const { updateNodeData } = useSvelteFlow();
|
||||||
|
const updateNodeInternals = useUpdateNodeInternals();
|
||||||
const refOptions = useRefOptions(false);
|
const refOptions = useRefOptions(false);
|
||||||
|
|
||||||
let activeBranchId = $state('');
|
let activeBranchId = $state('');
|
||||||
@@ -214,6 +222,18 @@
|
|||||||
return label || `条件分支${index + 1}`;
|
return label || `条件分支${index + 1}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const isExpanded = () => Boolean(data?.expand);
|
||||||
|
|
||||||
|
const collapsedHandleTop = (index: number, count: number) => {
|
||||||
|
if (count <= 1) {
|
||||||
|
return '54px';
|
||||||
|
}
|
||||||
|
const start = 38;
|
||||||
|
const end = 74;
|
||||||
|
const step = (end - start) / (count - 1);
|
||||||
|
return `${start + index * step}px`;
|
||||||
|
};
|
||||||
|
|
||||||
const syncManagedEdges = (branches: ConditionBranch[]) => {
|
const syncManagedEdges = (branches: ConditionBranch[]) => {
|
||||||
const branchMap = new Map(branches.map((branch) => [branch.id, branch]));
|
const branchMap = new Map(branches.map((branch) => [branch.id, branch]));
|
||||||
const currentEdges = store.getEdges();
|
const currentEdges = store.getEdges();
|
||||||
@@ -568,6 +588,12 @@
|
|||||||
|
|
||||||
syncManagedEdges(normalized.branches);
|
syncManagedEdges(normalized.branches);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$effect(() => {
|
||||||
|
branches.map((branch) => branch.id).join('|');
|
||||||
|
isExpanded();
|
||||||
|
updateNodeInternals(currentNodeId);
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<NodeWrapper {data} {...rest} showSourceHandle={false} allowSettingOfCondition={false}>
|
<NodeWrapper {data} {...rest} showSourceHandle={false} allowSettingOfCondition={false}>
|
||||||
@@ -577,6 +603,20 @@
|
|||||||
</svg>
|
</svg>
|
||||||
{/snippet}
|
{/snippet}
|
||||||
|
|
||||||
|
{#snippet handle()}
|
||||||
|
{#if !isExpanded()}
|
||||||
|
{#each branches as branch, index}
|
||||||
|
<Handle
|
||||||
|
type="source"
|
||||||
|
position={Position.Right}
|
||||||
|
id={`branch_${branch.id}`}
|
||||||
|
class="condition-branch-handle condition-branch-handle-collapsed"
|
||||||
|
style={`right: -28px; top: ${collapsedHandleTop(index, branches.length)};`}
|
||||||
|
/>
|
||||||
|
{/each}
|
||||||
|
{/if}
|
||||||
|
{/snippet}
|
||||||
|
|
||||||
<div class="condition-node-content">
|
<div class="condition-node-content">
|
||||||
<div class="condition-rail-head">
|
<div class="condition-rail-head">
|
||||||
<div class="condition-rail-title">分支出口</div>
|
<div class="condition-rail-title">分支出口</div>
|
||||||
@@ -644,13 +684,15 @@
|
|||||||
</svg>
|
</svg>
|
||||||
</Button>
|
</Button>
|
||||||
{/if}
|
{/if}
|
||||||
<Handle
|
{#if isExpanded()}
|
||||||
type="source"
|
<Handle
|
||||||
position={Position.Right}
|
type="source"
|
||||||
id={`branch_${branch.id}`}
|
position={Position.Right}
|
||||||
class="condition-branch-handle"
|
id={`branch_${branch.id}`}
|
||||||
style="right: -28px; top: 50%; transform: translateY(-50%);"
|
class="condition-branch-handle"
|
||||||
/>
|
style="right: -28px; top: 50%; transform: translateY(-50%);"
|
||||||
|
/>
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
@@ -876,6 +918,10 @@
|
|||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:global(.condition-branch-handle-collapsed) {
|
||||||
|
transform: translateY(-50%);
|
||||||
|
}
|
||||||
|
|
||||||
.condition-editor-actions-inline {
|
.condition-editor-actions-inline {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|||||||
Reference in New Issue
Block a user