mirror of
https://gitee.com/ByteDance/flowgram.ai.git
synced 2025-07-07 17:43:29 +08:00
fix(auto-layout): branches with multi sub nodes (#272)
This commit is contained in:
parent
755aaf2223
commit
9ae858b363
@ -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 { LayoutEdge, LayoutNode, LayoutParams } from './type';
|
||||
@ -15,6 +19,8 @@ export class LayoutStore {
|
||||
|
||||
private store: LayoutStoreData;
|
||||
|
||||
private container: WorkflowNodeEntity;
|
||||
|
||||
public get initialized(): boolean {
|
||||
return this.init;
|
||||
}
|
||||
@ -47,11 +53,9 @@ export class LayoutStore {
|
||||
}
|
||||
|
||||
/** 创建布局数据 */
|
||||
private createStore(params: {
|
||||
nodes: WorkflowNodeEntity[];
|
||||
edges: WorkflowLineEntity[];
|
||||
}): LayoutStoreData {
|
||||
const { nodes, edges } = params;
|
||||
private createStore(params: LayoutParams): LayoutStoreData {
|
||||
const { nodes, edges, container } = params;
|
||||
this.container = container;
|
||||
const layoutNodes = this.createLayoutNodes(nodes);
|
||||
const layoutEdges = this.createEdgesStore(edges);
|
||||
const virtualEdges = this.createVirtualEdges(params);
|
||||
@ -211,30 +215,42 @@ export class LayoutStore {
|
||||
nodeIdList.push(node.id);
|
||||
});
|
||||
|
||||
const sameFromEdges = new Map<string, LayoutEdge[]>();
|
||||
// 第2级排序:被连线节点排序靠后
|
||||
this.edges.forEach((edge) => {
|
||||
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坐标排序
|
||||
sameFromEdges.forEach((edges, from) => {
|
||||
const sortedEdges = edges.sort((a, b) => {
|
||||
const aPort = a.entity.fromPort;
|
||||
const bPort = b.entity.fromPort;
|
||||
// 第3级排序:按照从开始节点进行遍历排序
|
||||
const visited = new Set<string>();
|
||||
const visit = (node: WorkflowNodeEntity) => {
|
||||
if (visited.has(node.id)) {
|
||||
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) {
|
||||
return aPort.point.y - bPort.point.y;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
sortedEdges.forEach((edge) => {
|
||||
nodeIdList.push(edge.to);
|
||||
sortedLines.forEach((line) => {
|
||||
const { to } = line;
|
||||
if (!to) {
|
||||
return;
|
||||
}
|
||||
visit(to);
|
||||
});
|
||||
});
|
||||
};
|
||||
visit(this.container);
|
||||
|
||||
// 使用 reduceRight 去重并保留最后一个出现的节点 id
|
||||
const uniqueNodeIds: string[] = nodeIdList.reduceRight((acc: string[], nodeId: string) => {
|
||||
|
||||
@ -61,6 +61,7 @@ export interface DagreNode {
|
||||
export interface LayoutParams {
|
||||
nodes: WorkflowNodeEntity[];
|
||||
edges: WorkflowLineEntity[];
|
||||
container: WorkflowNodeEntity;
|
||||
}
|
||||
|
||||
export interface LayoutOptions {
|
||||
|
||||
@ -30,7 +30,7 @@ export class AutoLayoutService {
|
||||
await Promise.all(nodes.map(async (child) => this.layoutNode(child, options)));
|
||||
|
||||
const layout = new Layout();
|
||||
layout.init({ nodes, edges }, options);
|
||||
layout.init({ nodes, edges, container: node }, options);
|
||||
layout.layout();
|
||||
await layout.position();
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user