修复转换数据不完整问题
This commit is contained in:
@@ -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('当前决策树不存在');
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 智能推断通信关系的策略类型
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user