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
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;
|
|
}
|
|
}
|
|
|