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 { 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) => {
|
||||||
|
|||||||
@ -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 {
|
||||||
|
|||||||
@ -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();
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user