You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

348 lines
14 KiB

using Microsoft.Extensions.Logging;
using X1.Domain.Entities.TestCase;
using X1.Domain.Repositories.TestCase;
using X1.Domain.Repositories.Base;
using X1.Domain.Models;
using Newtonsoft.Json;
namespace X1.Application.Features.TestCaseFlow.Commands.CreateTestCaseFlow;
/// <summary>
/// 测试用例流程构建器
/// </summary>
public class TestCaseFlowBuilder
{
private readonly ITestCaseNodeRepository _testCaseNodeRepository;
private readonly ITestCaseEdgeRepository _testCaseEdgeRepository;
private readonly IImsiRegistrationRecordRepository _imsiRegistrationRecordRepository;
private readonly ILogger<TestCaseFlowBuilder> _logger;
/// <summary>
/// 初始化测试用例流程构建器
/// </summary>
public TestCaseFlowBuilder(
ITestCaseNodeRepository testCaseNodeRepository,
ITestCaseEdgeRepository testCaseEdgeRepository,
IImsiRegistrationRecordRepository imsiRegistrationRecordRepository,
ILogger<TestCaseFlowBuilder> logger)
{
_testCaseNodeRepository = testCaseNodeRepository;
_testCaseEdgeRepository = testCaseEdgeRepository;
_imsiRegistrationRecordRepository = imsiRegistrationRecordRepository;
_logger = logger;
}
/// <summary>
/// 构建测试用例流程(创建节点和连线)
/// </summary>
/// <param name="testCaseId">测试用例ID</param>
/// <param name="nodes">节点数据</param>
/// <param name="edges">连线数据</param>
/// <param name="cancellationToken">取消令牌</param>
public async Task BuildAsync(string testCaseId, List<NodeData>? nodes, List<EdgeData>? edges, CancellationToken cancellationToken)
{
// 创建节点
if (nodes != null && nodes.Any())
{
await CreateNodesAsync(testCaseId, nodes, cancellationToken);
}
// 创建连线
if (edges != null && edges.Any())
{
await CreateEdgesAsync(testCaseId, edges, cancellationToken);
}
_logger.LogInformation("测试用例流程构建完成,ID: {TestCaseId}, 节点数量: {NodeCount}, 连线数量: {EdgeCount}",
testCaseId, nodes?.Count ?? 0, edges?.Count ?? 0);
}
/// <summary>
/// 创建测试用例节点
/// </summary>
private async Task CreateNodesAsync(string testCaseId, List<NodeData> nodes, CancellationToken cancellationToken)
{
// 预处理节点数据
var processedNodes = PreprocessNodes(nodes);
// 创建节点实体
await CreateNodeEntitiesAsync(testCaseId, processedNodes, cancellationToken);
}
/// <summary>
/// 预处理节点数据
/// </summary>
/// <param name="nodes">原始节点数据</param>
/// <returns>预处理后的节点数据</returns>
private List<ProcessedNodeData> PreprocessNodes(List<NodeData> nodes)
{
return nodes.Select(nodeData => new ProcessedNodeData
{
NodeData = nodeData,
FormDataJson = nodeData.FormData?.ToString(),
HasFormData = nodeData.IsFormEnabled == true && nodeData.FormData is not null
}).ToList();
}
/// <summary>
/// 创建节点实体
/// </summary>
/// <param name="testCaseId">测试用例ID</param>
/// <param name="processedNodes">预处理后的节点数据</param>
/// <param name="cancellationToken">取消令牌</param>
private async Task CreateNodeEntitiesAsync(string testCaseId, List<ProcessedNodeData> processedNodes, CancellationToken cancellationToken)
{
var sequenceNumber = 1;
var nodeIdMapping = new Dictionary<string, string>(); // 前端节点ID -> 数据库节点ID的映射
foreach (var processedNode in processedNodes)
{
var nodeData = processedNode.NodeData;
var testCaseNode = TestCaseNode.Create(
testCaseId: testCaseId,
nodeId: nodeData.Id,
sequenceNumber: sequenceNumber++,
positionX: nodeData.PositionX,
positionY: nodeData.PositionY,
stepId: nodeData.StepId,
width: nodeData.Width ?? 100,
height: nodeData.Height ?? 50,
isSelected: nodeData.Selected ?? false,
positionAbsoluteX: nodeData.PositionAbsoluteX,
positionAbsoluteY: nodeData.PositionAbsoluteY,
isDragging: nodeData.Dragging ?? false);
await _testCaseNodeRepository.AddTestCaseNodeAsync(testCaseNode, cancellationToken);
// 保存前端节点ID到数据库节点ID的映射
nodeIdMapping[nodeData.Id] = testCaseNode.Id;
}
// 将映射传递给表单数据处理方法
await ProcessFormDataBatchAsync(testCaseId, processedNodes, nodeIdMapping, cancellationToken);
}
/// <summary>
/// 批量处理表单数据
/// </summary>
private async Task ProcessFormDataBatchAsync(string testCaseId, List<ProcessedNodeData> processedNodes, Dictionary<string, string> nodeIdMapping, CancellationToken cancellationToken)
{
// 同步处理:组装所有需要保存的实体
var entities = BuildFormDataEntities(testCaseId, processedNodes, nodeIdMapping);
// 异步处理:批量保存到数据库
if (entities.HasAnyEntities())
{
await SaveFormDataEntitiesAsync(entities, cancellationToken);
_logger.LogInformation("成功处理表单数据,测试用例ID: {TestCaseId}", testCaseId);
}
}
/// <summary>
/// 组装表单数据实体(同步操作)
/// </summary>
private FormDataEntities BuildFormDataEntities(string testCaseId, List<ProcessedNodeData> processedNodes, Dictionary<string, string> nodeIdMapping)
{
var entities = new FormDataEntities();
foreach (var processedNode in processedNodes)
{
if (!processedNode.HasFormData || string.IsNullOrEmpty(processedNode.FormDataJson))
{
continue;
}
try
{
var nodeData = processedNode.NodeData;
// 获取数据库节点ID
if (!nodeIdMapping.TryGetValue(nodeData.Id, out var databaseNodeId))
{
_logger.LogWarning("未找到节点ID映射,前端节点ID: {NodeId}", nodeData.Id);
continue;
}
switch (nodeData.FormType)
{
case (int)FormType.DeviceRegistrationForm:
_logger.LogDebug("开始反序列化设备注册表单数据,JSON: {Json}", processedNode.FormDataJson);
// 使用 Newtonsoft.Json 处理转义的 JSON 字符串
var deviceRegistrationData = JsonConvert.DeserializeObject<DeviceRegistrationFormData>(
System.Text.Json.Nodes.JsonObject.Parse(processedNode.FormDataJson).ToString());
if (deviceRegistrationData != null)
{
_logger.LogDebug("设备注册表单数据反序列化成功,前端节点ID: {FrontendNodeId}, 数据库节点ID: {DatabaseNodeId}",
deviceRegistrationData.NodeId, databaseNodeId);
var imsiRecord = BuildImsiRegistrationRecord(testCaseId, databaseNodeId, deviceRegistrationData);
entities.ImsiRegistrationRecords.Add(imsiRecord);
}
else
{
_logger.LogWarning("设备注册表单数据反序列化返回null,前端节点ID: {NodeId}", nodeData.Id);
}
break;
// 可以在这里添加其他表单类型的处理
// case (int)FormType.NetworkConnectivityForm:
// var networkData = JsonConvert.DeserializeObject<NetworkConnectivityFormData>(
// System.Text.Json.Nodes.JsonObject.Parse(processedNode.FormDataJson).ToString());
// if (networkData != null)
// {
// var networkEntity = BuildNetworkConnectivityEntity(testCaseId, databaseNodeId, networkData);
// entities.NetworkConnectivityEntities.Add(networkEntity);
// }
// break;
default:
_logger.LogInformation("未处理的表单类型: {FormType}, 前端节点ID: {NodeId}", nodeData.FormType, nodeData.Id);
break;
}
}
catch (JsonException jsonEx)
{
_logger.LogError(jsonEx, "JSON反序列化失败,前端节点ID: {NodeId}, JSON: {Json}",
processedNode.NodeData.Id, processedNode.FormDataJson);
}
catch (Exception ex)
{
_logger.LogError(ex, "组装表单数据实体失败,前端节点ID: {NodeId}, 表单类型: {FormType}",
processedNode.NodeData.Id, processedNode.NodeData.FormType);
}
}
return entities;
}
/// <summary>
/// 批量保存表单数据实体(异步操作)
/// </summary>
private async Task SaveFormDataEntitiesAsync(FormDataEntities entities, CancellationToken cancellationToken)
{
// 保存 IMSI 注册记录
if (entities.ImsiRegistrationRecords.Any())
{
foreach (var imsiRecord in entities.ImsiRegistrationRecords)
{
await _imsiRegistrationRecordRepository.AddAsync(imsiRecord, cancellationToken);
}
}
// 可以在这里添加其他实体类型的保存
// if (entities.NetworkConnectivityEntities.Any())
// {
// foreach (var networkEntity in entities.NetworkConnectivityEntities)
// {
// saveTasks.Add(_networkConnectivityRepository.AddAsync(networkEntity, cancellationToken));
// }
// }
}
/// <summary>
/// 组装 IMSI 注册记录
/// </summary>
private static ImsiRegistrationRecord BuildImsiRegistrationRecord(string testCaseId, string nodeId, DeviceRegistrationFormData deviceRegistrationData)
{
return ImsiRegistrationRecord.Create(
testCaseId: testCaseId,
nodeId: nodeId,
isDualSim: deviceRegistrationData.IsDualSim,
sim1Plmn: deviceRegistrationData.Sim1Plmn,
sim1CellId: deviceRegistrationData.Sim1CellId,
sim1RegistrationWaitTime: deviceRegistrationData.Sim1RegistrationWaitTime,
sim2Plmn: deviceRegistrationData.Sim2Plmn,
sim2CellId: deviceRegistrationData.Sim2CellId,
sim2RegistrationWaitTime: deviceRegistrationData.Sim2RegistrationWaitTime
);
}
/// <summary>
/// 创建测试用例连线
/// </summary>
private async Task CreateEdgesAsync(string testCaseId, List<EdgeData> edges, CancellationToken cancellationToken)
{
foreach (var edgeData in edges)
{
var testCaseEdge = TestCaseEdge.Create(
testCaseId: testCaseId,
edgeId: edgeData.Id,
sourceNodeId: edgeData.Source,
targetNodeId: edgeData.Target,
sourceHandle: edgeData.SourceHandle,
targetHandle: edgeData.TargetHandle,
edgeType: edgeData.Type,
condition: edgeData.Condition,
isAnimated: edgeData.Animated ?? false,
style: edgeData.Style);
await _testCaseEdgeRepository.AddTestCaseEdgeAsync(testCaseEdge, cancellationToken);
}
_logger.LogInformation("成功创建 {Count} 个测试用例连线,测试用例ID: {TestCaseId}", edges.Count, testCaseId);
}
}
/// <summary>
/// 预处理后的节点数据
/// </summary>
public class ProcessedNodeData
{
/// <summary>
/// 原始节点数据
/// </summary>
public NodeData NodeData { get; set; } = null!;
/// <summary>
/// 序列化后的表单数据JSON字符串
/// </summary>
public string? FormDataJson { get; set; }
/// <summary>
/// 是否有表单数据需要处理
/// </summary>
public bool HasFormData { get; set; }
}
/// <summary>
/// 表单数据实体集合
/// </summary>
public class FormDataEntities
{
/// <summary>
/// IMSI 注册记录集合
/// </summary>
public List<ImsiRegistrationRecord> ImsiRegistrationRecords { get; set; } = new();
// 可以在这里添加其他实体类型的集合
// public List<NetworkConnectivityEntity> NetworkConnectivityEntities { get; set; } = new();
// public List<NetworkPerformanceEntity> NetworkPerformanceEntities { get; set; } = new();
// public List<VoiceCallEntity> VoiceCallEntities { get; set; } = new();
/// <summary>
/// 检查是否有任何实体需要保存
/// </summary>
/// <returns>是否有实体</returns>
public bool HasAnyEntities()
{
return ImsiRegistrationRecords.Any();
// || NetworkConnectivityEntities.Any()
// || NetworkPerformanceEntities.Any()
// || VoiceCallEntities.Any();
}
/// <summary>
/// 获取所有实体的总数量
/// </summary>
/// <returns>实体总数量</returns>
public int GetTotalEntityCount()
{
return ImsiRegistrationRecords.Count;
// + NetworkConnectivityEntities.Count
// + NetworkPerformanceEntities.Count
// + VoiceCallEntities.Count;
}
}