修复转换数据不完整问题

This commit is contained in:
2026-04-15 10:50:02 +08:00
parent 949e059c8f
commit e555c95058
2 changed files with 163 additions and 69 deletions

View File

@@ -72,7 +72,7 @@ import { createGraphScenarioElement, createGraphTaskElementFromScenario } from '
import PlatformCard from './platform-card.vue';
import NodesCard from './nodes-card.vue';
import { findOneScenarioById, saveScenario, findRelations, getAllBehaviorTreesBySceneId } from './api';
import { findOneScenarioById, saveScenario, findRelations, getAllBehaviorTreesBySceneId, findPlatformWithComponents } from './api';
import { resolveConnectionRelation } from './relation';
import { generateRandomCommunicationData } from './random-data-generator';
import { convertRecordsToGraphContainer, type CommunicationRecord } from './data-converter';
@@ -278,8 +278,45 @@ export default defineComponent({
console.log('标准化后的第一条记录:', normalizedRelations[0]);
// 转换为图数据
const convertedGraph = convertRecordsToGraphContainer(normalizedRelations);
// 获取平台列表(包含完整的组件信息)
message.loading({ content: '正在获取平台信息...', key: 'loading-platforms' });
const platformResponse = await findPlatformWithComponents(currentScenario.value.id);
if (!platformResponse.data || platformResponse.data.length === 0) {
console.warn('未能获取平台列表,将使用简化的组件信息');
message.destroy('loading-platforms');
// 即使没有平台数据也继续转换传入场景ID
const convertedGraph = convertRecordsToGraphContainer(
normalizedRelations,
undefined,
undefined,
currentScenario.value.id
);
console.log('转换后的图数据:', convertedGraph);
currentScenario.value.graph = convertedGraph;
currentScenario.value.communicationGraph = JSON.stringify(convertedGraph);
message.success({ content: `成功加载 ${normalizedRelations.length} 条通信关系(无详细组件信息)`, key: 'loading-relations' });
return;
}
console.log(`获取到 ${platformResponse.data.length} 个平台的完整数据`);
platformResponse.data.forEach(platform => {
console.log(` 平台 "${platform.name}" (ID=${platform.id}) 有 ${platform.components?.length || 0} 个组件:`,
platform.components?.map(c => c.name));
});
// 转换为图数据传入完整的平台数据数组和场景ID
const convertedGraph = convertRecordsToGraphContainer(
normalizedRelations,
undefined,
platformResponse.data,
currentScenario.value.id
);
// 验证转换后的节点数据结构
console.log('转换后的图数据:', convertedGraph);
// 更新当前场景的图数据
@@ -469,10 +506,12 @@ export default defineComponent({
const handleSave = () => {
const graphData: GraphContainer = resolveGraph(graph.value as Graph);
console.log(graph.value);
const relations = resolveConnectionRelation(graph.value as Graph);
console.error('relations',relations)
console.info('handleSave', graphData);
if (!currentScenario.value) {
message.error('当前决策树不存在');

View File

@@ -9,6 +9,8 @@
import type { GraphTaskElement, GraphContainer, GraphEdgeElement } from '../graph';
import { generateKey } from '@/utils/strings';
import { createLineOptions } from '../graph/line';
import type { PlatformWithComponents } from '../types/platform';
// ==================== 类型定义 ====================
@@ -121,11 +123,15 @@ const createVerticalMapper = (params: LayoutParams): CoordinateMapper => ({
* 从数据库记录转换为 GraphContainer 格式
* @param records 数据库通信关系记录数组
* @param config 布局配置(可选),默认为水平布局
* @param platformsData 完整的平台数据数组包含components如果提供则优先使用
* @param scenarioId 场景ID用于设置节点的scenarioId字段
* @returns GraphContainer 格式的节点和边数据
*/
export const convertRecordsToGraphContainer = (
records: CommunicationRecord[],
config?: Partial<LayoutConfig>
config?: Partial<LayoutConfig>,
platformsData?: PlatformWithComponents[],
scenarioId?: number
): GraphContainer => {
if (!records || records.length === 0) {
return { nodes: [], edges: [] };
@@ -140,6 +146,19 @@ export const convertRecordsToGraphContainer = (
startPosition: typeof config?.startPosition === 'number' ? config.startPosition : 80,
};
// 构建平台名称到完整数据的映射
const platformDataMap = new Map<string, PlatformWithComponents>();
if (platformsData && platformsData.length > 0) {
platformsData.forEach(platform => {
if (platform.name) {
platformDataMap.set(platform.name, platform);
}
});
console.log(`[convertRecordsToGraphContainer] 提供了 ${platformDataMap.size} 个平台的完整数据`);
} else {
console.warn('[convertRecordsToGraphContainer] 未提供平台完整数据,将使用简化的组件信息');
}
// 收集所有唯一的平台名称(过滤无效值)
const platformSet = new Set<string>();
records.forEach(record => {
@@ -221,8 +240,8 @@ export const convertRecordsToGraphContainer = (
mapper
);
// 创建节点对象
const nodeMap = createNodeObjects(levelsMap, nodePositions);
// 创建节点对象传入完整的平台数据映射和场景ID
const nodeMap = createNodeObjects(levelsMap, nodePositions, platformDataMap, scenarioId);
console.log(` 分量 ${componentIndex + 1} 创建了 ${nodeMap.size} 个节点:`, Array.from(nodeMap.keys()));
@@ -230,7 +249,7 @@ export const convertRecordsToGraphContainer = (
if (!nodeMap.has(rootPlatformName)) {
console.warn(` 根节点 "${rootPlatformName}" 未在 levelsMap 中找到,手动创建`);
}
createRootNode(nodeMap, rootPlatformName, parentToChildren, layoutParams, mapper);
createRootNode(nodeMap, rootPlatformName, parentToChildren, layoutParams, mapper, platformDataMap, scenarioId);
console.log(` 最终节点数: ${nodeMap.size}`);
@@ -238,7 +257,7 @@ export const convertRecordsToGraphContainer = (
const componentEdges = filterEdgesForComponent(records, component);
const edges = createEdges(componentEdges, nodeMap);
// 添加到总结果
// 将GraphTaskElement直接添加到总结果GraphContainer需要的是GraphTaskElement[]
allNodes.push(...Array.from(nodeMap.values()));
allEdges.push(...edges);
@@ -679,43 +698,58 @@ const restoreIsoscelesTriangles = (
const createNodeObjects = (
levelsMap: Map<number, string[]>,
nodePositions: Map<string, NodePosition>
nodePositions: Map<string, NodePosition>,
platformDataMap: Map<string, PlatformWithComponents>,
scenarioId?: number
): Map<string, GraphTaskElement> => {
const nodeMap = new Map<string, GraphTaskElement>();
levelsMap.forEach((platformsInLevel, level) => {
platformsInLevel.forEach(platform => {
const pos = nodePositions.get(platform)!;
const componentId = 1;
// 从映射表中获取平台完整数据
const platformData = platformDataMap.get(platform);
const platformId = platformData?.id || 0;
// 优先使用platformData自带的scenarioId其次使用传入的参数
const nodeScenarioId = platformData?.scenarioId ?? scenarioId ?? 0;
// 使用真实的组件数据(保持完整结构),如果没有则创建默认组件
const components = platformData?.components && platformData.components.length > 0
? platformData.components // 直接使用完整组件数组,不做字段筛选
: [
{
id: 1,
name: `${platform}_comm`,
type: 'communication',
description: `通信组件`
}
];
console.log(`[createNodeObjects] 平台 "${platform}" 有 ${components.length} 个组件:`, components.map(c => c.name));
const node: GraphTaskElement = {
id: 0,
key: generateKey(),
type: 'scenario',
name: platform,
platformId: 0,
scenarioId: 0,
components: [
{
id: componentId,
name: `${platform}_comm`,
type: 'communication',
description: `通信组件`
}
],
platformId: platformId,
scenarioId: nodeScenarioId, // 修复优先使用platformData.scenarioId
components: components,
template: 0,
templateType: null,
category: null,
multiable: false,
group: null,
description: platform,
description: platformData?.description || platform,
order: 0,
position: {
x: Math.round(pos.x),
y: Math.round(pos.y),
},
width: 250,
height: 145,
height: 120,
inputs: null,
outputs: null,
parameters: [],
@@ -736,7 +770,9 @@ const createRootNode = (
rootPlatformName: string,
parentToChildren: Map<string, string[]>,
params: LayoutParams,
mapper: CoordinateMapper
mapper: CoordinateMapper,
platformDataMap: Map<string, PlatformWithComponents>,
scenarioId?: number
): void => {
if (nodeMap.size === 0 || !rootPlatformName) return;
@@ -766,31 +802,45 @@ const createRootNode = (
centerSecondaryCoord = (minCoord + maxCoord) / 2;
}
const rootNode: GraphTaskElement = {
id: 0,
key: generateKey(),
type: 'scenario',
name: rootPlatformName,
platformId: 0,
scenarioId: 0,
components: [
// 从映射表中获取平台完整数据
const platformData = platformDataMap.get(rootPlatformName);
const platformId = platformData?.id || 0;
// 优先使用platformData自带的scenarioId其次使用传入的参数
const rootNodeScenarioId = platformData?.scenarioId ?? scenarioId ?? 0;
// 使用真实的组件数据(保持完整结构),如果没有则创建默认组件
const components = platformData?.components && platformData.components.length > 0
? platformData.components // 直接使用完整组件数组,不做字段筛选
: [
{
id: 1,
name: `${rootPlatformName}_comm`,
type: 'communication',
description: `通信组件`
}
],
];
console.log(`[createRootNode] 根节点 "${rootPlatformName}" 有 ${components.length} 个组件:`, components.map(c => c.name));
const rootNode: GraphTaskElement = {
id: 0,
key: generateKey(),
type: 'scenario',
name: rootPlatformName,
platformId: platformId,
scenarioId: rootNodeScenarioId, // 修复优先使用platformData.scenarioId
components: components,
template: 0,
templateType: null,
category: null,
multiable: false,
group: null,
description: rootPlatformName,
description: platformData?.description || rootPlatformName,
order: 0,
position: mapper.setCoords(params.ROOT_POSITION, Math.round(centerSecondaryCoord)),
width: 250,
height: 145,
height: 120,
inputs: null,
outputs: null,
parameters: [],
@@ -813,19 +863,48 @@ const createEdges = (
const targetNode = nodeMap.get(record.subordinate_platform);
if (sourceNode && targetNode && sourceNode.key && targetNode.key) {
const sourceCompId = sourceNode.components?.[0]?.id || 1;
const targetCompId = targetNode.components?.[0]?.id || 1;
// 根据通信组件名称查找对应的组件
const sourceComp = sourceNode.components?.find(
comp => comp.name === record.command_comm
);
const targetComp = targetNode.components?.find(
comp => comp.name === record.subordinate_comm
);
if (!sourceComp || !targetComp) {
console.warn(`无法找到匹配的组件 - 记录 ${index + 1}:`, {
record,
sourceComps: sourceNode.components?.map(c => c.name),
targetComps: targetNode.components?.map(c => c.name),
});
return;
}
// 根据node.vue的命名规则生成端口ID
// 格式out-{comp.id} 或 in-{comp.id}
const sourcePortId = `out-${sourceComp.id}`;
const targetPortId = `in-${targetComp.id}`;
edges.push({
id: index + 1,
key: generateKey(),
source: sourceNode.key,
target: targetNode.key,
sourcePort: `out-${sourceCompId}`,
targetPort: `in-${targetCompId}`,
attrs: {},
router: { name: 'normal' },
connector: { name: 'smooth' },
source: {
cell: sourceNode.key,
port: sourcePortId,
},
target: {
cell: targetNode.key,
port: targetPortId,
},
...createLineOptions(), // 应用标准边样式配置
});
} else {
console.warn(`无法创建边 ${index + 1}:`, {
record,
sourceNodeExists: !!sourceNode,
targetNodeExists: !!targetNode,
sourceKey: sourceNode?.key,
targetKey: targetNode?.key,
});
}
});
@@ -835,30 +914,6 @@ const createEdges = (
// ==================== 新增功能:平台数据转通信关系 ====================
/**
* 平台组件接口来自后端API
*/
export interface PlatformComponent {
id: number;
name: string | null;
type: string | null;
description: string | null;
platformId: number;
[key: string]: unknown;
}
/**
* 带组件的平台接口来自后端API
*/
export interface PlatformWithComponents {
id: number;
name: string | null;
description: string | null;
scenarioId: number;
components: PlatformComponent[];
[key: string]: unknown;
}
/**
* 智能推断通信关系的策略类型
*/