fix(auto-layout): branches with multi sub nodes (#272)

This commit is contained in:
Louis Young 2025-05-26 16:12:59 +08:00 committed by GitHub
parent 755aaf2223
commit 9ae858b363
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 37 additions and 20 deletions

View File

@ -1,4 +1,8 @@
import { WorkflowLineEntity, WorkflowNodeEntity } from '@flowgram.ai/free-layout-core'; import {
WorkflowLineEntity,
WorkflowNodeEntity,
WorkflowNodeLinesData,
} from '@flowgram.ai/free-layout-core';
import { FlowNodeBaseType, FlowNodeTransformData } from '@flowgram.ai/document'; import { FlowNodeBaseType, FlowNodeTransformData } from '@flowgram.ai/document';
import { LayoutEdge, LayoutNode, LayoutParams } from './type'; import { LayoutEdge, LayoutNode, LayoutParams } from './type';
@ -15,6 +19,8 @@ export class LayoutStore {
private store: LayoutStoreData; private store: LayoutStoreData;
private container: WorkflowNodeEntity;
public get initialized(): boolean { public get initialized(): boolean {
return this.init; return this.init;
} }
@ -47,11 +53,9 @@ export class LayoutStore {
} }
/** 创建布局数据 */ /** 创建布局数据 */
private createStore(params: { private createStore(params: LayoutParams): LayoutStoreData {
nodes: WorkflowNodeEntity[]; const { nodes, edges, container } = params;
edges: WorkflowLineEntity[]; this.container = container;
}): LayoutStoreData {
const { nodes, edges } = params;
const layoutNodes = this.createLayoutNodes(nodes); const layoutNodes = this.createLayoutNodes(nodes);
const layoutEdges = this.createEdgesStore(edges); const layoutEdges = this.createEdgesStore(edges);
const virtualEdges = this.createVirtualEdges(params); const virtualEdges = this.createVirtualEdges(params);
@ -211,30 +215,42 @@ export class LayoutStore {
nodeIdList.push(node.id); nodeIdList.push(node.id);
}); });
const sameFromEdges = new Map<string, LayoutEdge[]>();
// 第2级排序被连线节点排序靠后 // 第2级排序被连线节点排序靠后
this.edges.forEach((edge) => { this.edges.forEach((edge) => {
nodeIdList.push(edge.to); nodeIdList.push(edge.to);
if (edge.entity.info.fromPort) {
const edgesForFrom = sameFromEdges.get(edge.from) || [];
sameFromEdges.set(edge.from, [...edgesForFrom, edge]);
}
}); });
// 第3级排序相同 from 的节点的不同 port根据 port y坐标排序 // 第3级排序按照从开始节点进行遍历排序
sameFromEdges.forEach((edges, from) => { const visited = new Set<string>();
const sortedEdges = edges.sort((a, b) => { const visit = (node: WorkflowNodeEntity) => {
const aPort = a.entity.fromPort; if (visited.has(node.id)) {
const bPort = b.entity.fromPort; return;
}
visited.add(node.id);
nodeIdList.push(node.id);
// 访问子节点
node.blocks.forEach((child) => {
visit(child);
});
// 访问后续节点
const { outputLines } = node.getData(WorkflowNodeLinesData);
const sortedLines = outputLines.sort((a, b) => {
const aPort = a.fromPort;
const bPort = b.fromPort;
if (aPort && bPort) { if (aPort && bPort) {
return aPort.point.y - bPort.point.y; return aPort.point.y - bPort.point.y;
} }
return 0; return 0;
}); });
sortedEdges.forEach((edge) => { sortedLines.forEach((line) => {
nodeIdList.push(edge.to); const { to } = line;
if (!to) {
return;
}
visit(to);
}); });
}); };
visit(this.container);
// 使用 reduceRight 去重并保留最后一个出现的节点 id // 使用 reduceRight 去重并保留最后一个出现的节点 id
const uniqueNodeIds: string[] = nodeIdList.reduceRight((acc: string[], nodeId: string) => { const uniqueNodeIds: string[] = nodeIdList.reduceRight((acc: string[], nodeId: string) => {

View File

@ -61,6 +61,7 @@ export interface DagreNode {
export interface LayoutParams { export interface LayoutParams {
nodes: WorkflowNodeEntity[]; nodes: WorkflowNodeEntity[];
edges: WorkflowLineEntity[]; edges: WorkflowLineEntity[];
container: WorkflowNodeEntity;
} }
export interface LayoutOptions { export interface LayoutOptions {

View File

@ -30,7 +30,7 @@ export class AutoLayoutService {
await Promise.all(nodes.map(async (child) => this.layoutNode(child, options))); await Promise.all(nodes.map(async (child) => this.layoutNode(child, options)));
const layout = new Layout(); const layout = new Layout();
layout.init({ nodes, edges }, options); layout.init({ nodes, edges, container: node }, options);
layout.layout(); layout.layout();
await layout.position(); await layout.position();
} }