135 lines
4.7 KiB
TypeScript
135 lines
4.7 KiB
TypeScript
/*
|
||
* This file is part of the kernelstudio package.
|
||
*
|
||
* (c) 2014-2026 zlin <admin@kernelstudio.com>
|
||
*
|
||
* For the full copyright and license information, please view the LICENSE file
|
||
* that was distributed with this source code.
|
||
*/
|
||
|
||
import { Edge, Graph, Node } from '@antv/x6';
|
||
import type { PlatformRelation } from './types';
|
||
import type { Platform, PlatformComponent } from '../types';
|
||
import type { GraphTaskElement } from '../graph';
|
||
|
||
/**
|
||
* 解析节点端口连接关系(去重版)
|
||
* @param graph X6 画布实例
|
||
* @returns 去重后的端口连接关系列表
|
||
*/
|
||
export function resolveConnectionRelation(graph: Graph): PlatformRelation[] {
|
||
const edges: Edge[] = graph.getEdges();
|
||
const items: PlatformRelation[] = [];
|
||
const existsKeys: Set<string> = new Set(); // 改用 Set 提升查询性能
|
||
const tempEdgeIds: Set<string> = new Set(); // 存储临时边 ID
|
||
|
||
// 过滤无效/临时边
|
||
const validEdges = edges.filter(edge => {
|
||
// 过滤临时边(X6 拖拽连线时生成的未完成边)
|
||
const isTempEdge = edge?.attr('line/stroke') === 'transparent' || edge.id.includes('temp');
|
||
if (isTempEdge) {
|
||
tempEdgeIds.add(edge.id);
|
||
return false;
|
||
}
|
||
|
||
// 过滤未正确关联节点的边
|
||
const sourceCell = edge.getSourceCell();
|
||
const targetCell = edge.getTargetCell();
|
||
if (!sourceCell || !targetCell || !(sourceCell instanceof Node) || !(targetCell instanceof Node)) {
|
||
return false;
|
||
}
|
||
|
||
// 过滤端口 ID 为空的边
|
||
const sourcePortId = edge.getSourcePortId();
|
||
const targetPortId = edge.getTargetPortId();
|
||
if (!sourcePortId || !targetPortId) {
|
||
return false;
|
||
}
|
||
|
||
return true;
|
||
});
|
||
|
||
validEdges.forEach(edge => {
|
||
try {
|
||
const sourceCell = edge.getSourceCell() as Node;
|
||
const targetCell = edge.getTargetCell() as Node;
|
||
|
||
const sourcePortId = edge.getSourcePortId()!;
|
||
const targetPortId = edge.getTargetPortId()!;
|
||
|
||
// 1. 获取端口 DOM 元素和数据
|
||
const sourceView = graph.findViewByCell(sourceCell);
|
||
const targetView = graph.findViewByCell(targetCell);
|
||
if (!sourceView || !targetView) return;
|
||
|
||
const sourcePortEl = sourceView.container.querySelector(`[data-port="${sourcePortId}"]`);
|
||
const targetPortEl = targetView.container.querySelector(`[data-port="${targetPortId}"]`);
|
||
if (!sourcePortEl || !targetPortEl) return;
|
||
|
||
// 2. 解析端口数据
|
||
let sourcePortData: PlatformComponent | null = null;
|
||
let targetPortData: PlatformComponent | null = null;
|
||
try {
|
||
const sourceDataAttr = sourcePortEl.getAttribute('data-item');
|
||
sourcePortData = sourceDataAttr ? JSON.parse(sourceDataAttr) : null;
|
||
} catch (e) {
|
||
console.warn(`解析源节点 ${sourceCell.id} 端口 ${sourcePortId} 数据失败`, e);
|
||
return; // 数据解析失败直接跳过
|
||
}
|
||
try {
|
||
const targetDataAttr = targetPortEl.getAttribute('data-item');
|
||
targetPortData = targetDataAttr ? JSON.parse(targetDataAttr) : null;
|
||
} catch (e) {
|
||
console.warn(`解析目标节点 ${targetCell.id} 端口 ${targetPortId} 数据失败`, e);
|
||
return; // 数据解析失败直接跳过
|
||
}
|
||
|
||
// 过滤端口数据为空的情况
|
||
if (!sourcePortData || !targetPortData) return;
|
||
|
||
// 解析节点平台数据
|
||
const sourceData = sourceCell.getData() as GraphTaskElement;
|
||
const targetData = targetCell.getData() as GraphTaskElement;
|
||
|
||
// 过滤平台数据不完整的节点
|
||
if (!sourceData.platformId || !targetData.platformId) return;
|
||
|
||
const sourcePlatform: Platform = {
|
||
id: sourceData.platformId as number,
|
||
key: sourceData.key,
|
||
name: sourceData.name,
|
||
description: sourceData.description,
|
||
scenarioId: sourceData.scenarioId as number,
|
||
};
|
||
|
||
const targetPlatform: Platform = {
|
||
id: targetData.platformId as number,
|
||
key: targetData.key,
|
||
name: targetData.name,
|
||
description: targetData.description,
|
||
scenarioId: targetData.scenarioId as number,
|
||
};
|
||
|
||
// 生成唯一标识(支持单向/双向去重
|
||
const uniqueKey = `${sourceCell.id}@${sourcePortId}->${targetCell.id}@${targetPortId}`;
|
||
|
||
if (!existsKeys.has(uniqueKey)) {
|
||
existsKeys.add(uniqueKey);
|
||
items.push({
|
||
sourceId: sourceCell.id,
|
||
sourcePort: sourcePortId,
|
||
sourcePlatform: sourcePlatform,
|
||
sourceComponent: sourcePortData,
|
||
targetId: targetCell.id,
|
||
targetPort: targetPortId,
|
||
targetPlatform: targetPlatform,
|
||
targetComponent: targetPortData,
|
||
edgeId: edge.id,
|
||
});
|
||
}
|
||
} catch (error) {
|
||
console.error(`解析边 ${edge.id} 连接关系失败`, error);
|
||
}
|
||
});
|
||
return items;
|
||
} |