UPDATE: VERSION-20260316
This commit is contained in:
134
modeler/src/views/decision/communication/relation.ts
Normal file
134
modeler/src/views/decision/communication/relation.ts
Normal file
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* 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 { Graph, Node,Edge } from '@antv/x6';
|
||||
import type { Platform, PlatformComponent, PlatformRelation } 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;
|
||||
}
|
||||
Reference in New Issue
Block a user