Browse Source

feat: 实现用例集完整的CRUD功能 - 添加创建用例集命令和处理器 - 添加更新用例集命令和处理器 - 添加删除用例集命令和处理器 - 添加启用用例集命令和处理器 - 添加禁用用例集命令和处理器 - 更新控制器添加所有CRUD API接口 - 完善仓储接口和实现

feature/x1-owen-debug
test 4 weeks ago
parent
commit
d86aa7097e
  1. 55
      src/X1.Application/Features/TestCaseSets/Commands/CreateTestCaseSet/CreateTestCaseSetCommand.cs
  2. 111
      src/X1.Application/Features/TestCaseSets/Commands/CreateTestCaseSet/CreateTestCaseSetCommandHandler.cs
  3. 57
      src/X1.Application/Features/TestCaseSets/Commands/CreateTestCaseSet/CreateTestCaseSetResponse.cs
  4. 18
      src/X1.Application/Features/TestCaseSets/Commands/DeleteTestCaseSet/DeleteTestCaseSetCommand.cs
  5. 96
      src/X1.Application/Features/TestCaseSets/Commands/DeleteTestCaseSet/DeleteTestCaseSetCommandHandler.cs
  6. 18
      src/X1.Application/Features/TestCaseSets/Commands/DisableTestCaseSet/DisableTestCaseSetCommand.cs
  7. 103
      src/X1.Application/Features/TestCaseSets/Commands/DisableTestCaseSet/DisableTestCaseSetCommandHandler.cs
  8. 18
      src/X1.Application/Features/TestCaseSets/Commands/EnableTestCaseSet/EnableTestCaseSetCommand.cs
  9. 103
      src/X1.Application/Features/TestCaseSets/Commands/EnableTestCaseSet/EnableTestCaseSetCommandHandler.cs
  10. 62
      src/X1.Application/Features/TestCaseSets/Commands/UpdateTestCaseSet/UpdateTestCaseSetCommand.cs
  11. 121
      src/X1.Application/Features/TestCaseSets/Commands/UpdateTestCaseSet/UpdateTestCaseSetCommandHandler.cs
  12. 57
      src/X1.Application/Features/TestCaseSets/Commands/UpdateTestCaseSet/UpdateTestCaseSetResponse.cs
  13. 18
      src/X1.Application/Features/TestCaseSets/Queries/GetTestCaseSetById/GetTestCaseSetByIdQuery.cs
  14. 84
      src/X1.Application/Features/TestCaseSets/Queries/GetTestCaseSetById/GetTestCaseSetByIdQueryHandler.cs
  15. 67
      src/X1.Application/Features/TestCaseSets/Queries/GetTestCaseSetById/GetTestCaseSetByIdResponse.cs
  16. 40
      src/X1.Application/Features/TestCaseSets/Queries/GetTestCaseSets/GetTestCaseSetsQuery.cs
  17. 111
      src/X1.Application/Features/TestCaseSets/Queries/GetTestCaseSets/GetTestCaseSetsQueryHandler.cs
  18. 44
      src/X1.Application/Features/TestCaseSets/Queries/GetTestCaseSets/GetTestCaseSetsResponse.cs
  19. 148
      src/X1.Domain/Entities/Device/TestCaseSet.cs
  20. 73
      src/X1.Domain/Repositories/Device/ITestCaseSetRepository.cs
  21. 32
      src/X1.Infrastructure/Configurations/Device/TestCaseSetConfiguration.cs
  22. 5
      src/X1.Infrastructure/Context/AppDbContext.cs
  23. 1
      src/X1.Infrastructure/DependencyInjection.cs
  24. 149
      src/X1.Infrastructure/Repositories/Device/TestCaseSetRepository.cs
  25. 175
      src/X1.Presentation/Controllers/TestCaseSetsController.cs

55
src/X1.Application/Features/TestCaseSets/Commands/CreateTestCaseSet/CreateTestCaseSetCommand.cs

@ -0,0 +1,55 @@
using CellularManagement.Domain.Common;
using MediatR;
using System.ComponentModel.DataAnnotations;
namespace CellularManagement.Application.Features.TestCaseSets.Commands.CreateTestCaseSet;
/// <summary>
/// 创建用例集命令
/// </summary>
public class CreateTestCaseSetCommand : IRequest<OperationResult<CreateTestCaseSetResponse>>
{
/// <summary>
/// 用例集编码
/// </summary>
[Required(ErrorMessage = "用例集编码不能为空")]
[MaxLength(50, ErrorMessage = "用例集编码长度不能超过50个字符")]
public string Code { get; set; } = null!;
/// <summary>
/// 用例集名称
/// </summary>
[Required(ErrorMessage = "用例集名称不能为空")]
[MaxLength(100, ErrorMessage = "用例集名称长度不能超过100个字符")]
public string Name { get; set; } = null!;
/// <summary>
/// 用例集说明
/// </summary>
[MaxLength(1000, ErrorMessage = "用例集说明长度不能超过1000个字符")]
public string? Description { get; set; }
/// <summary>
/// 用例集版本
/// </summary>
[Required(ErrorMessage = "用例集版本不能为空")]
[MaxLength(20, ErrorMessage = "用例集版本长度不能超过20个字符")]
public string Version { get; set; } = null!;
/// <summary>
/// 版本更新信息
/// </summary>
[MaxLength(500, ErrorMessage = "版本更新信息长度不能超过500个字符")]
public string? VersionUpdateInfo { get; set; }
/// <summary>
/// 是否禁用
/// </summary>
public bool IsDisabled { get; set; } = false;
/// <summary>
/// 备注
/// </summary>
[MaxLength(1000, ErrorMessage = "备注长度不能超过1000个字符")]
public string? Remarks { get; set; }
}

111
src/X1.Application/Features/TestCaseSets/Commands/CreateTestCaseSet/CreateTestCaseSetCommandHandler.cs

@ -0,0 +1,111 @@
using MediatR;
using Microsoft.Extensions.Logging;
using CellularManagement.Domain.Common;
using CellularManagement.Domain.Entities.Device;
using CellularManagement.Domain.Repositories.Device;
using CellularManagement.Domain.Repositories.Base;
using CellularManagement.Domain.Services;
namespace CellularManagement.Application.Features.TestCaseSets.Commands.CreateTestCaseSet;
/// <summary>
/// 创建用例集命令处理器
/// </summary>
public class CreateTestCaseSetCommandHandler : IRequestHandler<CreateTestCaseSetCommand, OperationResult<CreateTestCaseSetResponse>>
{
private readonly ITestCaseSetRepository _testCaseSetRepository;
private readonly ILogger<CreateTestCaseSetCommandHandler> _logger;
private readonly IUnitOfWork _unitOfWork;
private readonly ICurrentUserService _currentUserService;
/// <summary>
/// 初始化命令处理器
/// </summary>
public CreateTestCaseSetCommandHandler(
ITestCaseSetRepository testCaseSetRepository,
ILogger<CreateTestCaseSetCommandHandler> logger,
IUnitOfWork unitOfWork,
ICurrentUserService currentUserService)
{
_testCaseSetRepository = testCaseSetRepository;
_logger = logger;
_unitOfWork = unitOfWork;
_currentUserService = currentUserService;
}
/// <summary>
/// 处理创建用例集命令
/// </summary>
public async Task<OperationResult<CreateTestCaseSetResponse>> Handle(CreateTestCaseSetCommand request, CancellationToken cancellationToken)
{
try
{
_logger.LogInformation("开始创建用例集,用例集编码: {Code}, 用例集名称: {Name}, 版本: {Version}",
request.Code, request.Name, request.Version);
// 检查用例集编码是否已存在
if (await _testCaseSetRepository.CodeExistsAsync(request.Code, cancellationToken))
{
_logger.LogWarning("用例集编码已存在: {Code}", request.Code);
return OperationResult<CreateTestCaseSetResponse>.CreateFailure($"用例集编码 {request.Code} 已存在");
}
// 检查用例集版本是否已存在
if (await _testCaseSetRepository.VersionExistsAsync(request.Version, cancellationToken))
{
_logger.LogWarning("用例集版本已存在: {Version}", request.Version);
return OperationResult<CreateTestCaseSetResponse>.CreateFailure($"用例集版本 {request.Version} 已存在");
}
// 获取当前用户ID
var currentUserId = _currentUserService.GetCurrentUserId();
if (string.IsNullOrEmpty(currentUserId))
{
_logger.LogError("无法获取当前用户ID,用户可能未认证");
return OperationResult<CreateTestCaseSetResponse>.CreateFailure("用户未认证,无法创建用例集");
}
// 创建用例集实体
var testCaseSet = TestCaseSet.Create(
code: request.Code,
name: request.Name,
version: request.Version,
createdBy: currentUserId,
description: request.Description,
versionUpdateInfo: request.VersionUpdateInfo,
isDisabled: request.IsDisabled,
remarks: request.Remarks);
// 保存用例集
await _testCaseSetRepository.AddTestCaseSetAsync(testCaseSet, cancellationToken);
// 保存更改到数据库
await _unitOfWork.SaveChangesAsync(cancellationToken);
// 构建响应
var response = new CreateTestCaseSetResponse
{
TestCaseSetId = testCaseSet.Id,
Code = testCaseSet.Code,
Name = testCaseSet.Name,
Description = testCaseSet.Description,
Version = testCaseSet.Version,
VersionUpdateInfo = testCaseSet.VersionUpdateInfo,
IsDisabled = testCaseSet.IsDisabled,
Remarks = testCaseSet.Remarks,
CreatedAt = testCaseSet.CreatedAt,
CreatedBy = testCaseSet.CreatedBy
};
_logger.LogInformation("用例集创建成功,用例集ID: {TestCaseSetId}, 用例集编码: {Code}, 用例集名称: {Name}, 版本: {Version}",
testCaseSet.Id, testCaseSet.Code, testCaseSet.Name, testCaseSet.Version);
return OperationResult<CreateTestCaseSetResponse>.CreateSuccess(response);
}
catch (Exception ex)
{
_logger.LogError(ex, "创建用例集时发生错误,用例集编码: {Code}, 用例集名称: {Name}, 版本: {Version}",
request.Code, request.Name, request.Version);
return OperationResult<CreateTestCaseSetResponse>.CreateFailure($"创建用例集时发生错误: {ex.Message}");
}
}
}

57
src/X1.Application/Features/TestCaseSets/Commands/CreateTestCaseSet/CreateTestCaseSetResponse.cs

@ -0,0 +1,57 @@
namespace CellularManagement.Application.Features.TestCaseSets.Commands.CreateTestCaseSet;
/// <summary>
/// 创建用例集响应
/// </summary>
public class CreateTestCaseSetResponse
{
/// <summary>
/// 用例集ID
/// </summary>
public string TestCaseSetId { get; set; } = null!;
/// <summary>
/// 用例集编码
/// </summary>
public string Code { get; set; } = null!;
/// <summary>
/// 用例集名称
/// </summary>
public string Name { get; set; } = null!;
/// <summary>
/// 用例集说明
/// </summary>
public string? Description { get; set; }
/// <summary>
/// 用例集版本
/// </summary>
public string Version { get; set; } = null!;
/// <summary>
/// 版本更新信息
/// </summary>
public string? VersionUpdateInfo { get; set; }
/// <summary>
/// 是否禁用
/// </summary>
public bool IsDisabled { get; set; }
/// <summary>
/// 备注
/// </summary>
public string? Remarks { get; set; }
/// <summary>
/// 创建时间
/// </summary>
public DateTime CreatedAt { get; set; }
/// <summary>
/// 创建人
/// </summary>
public string CreatedBy { get; set; } = null!;
}

18
src/X1.Application/Features/TestCaseSets/Commands/DeleteTestCaseSet/DeleteTestCaseSetCommand.cs

@ -0,0 +1,18 @@
using CellularManagement.Domain.Common;
using MediatR;
using System.ComponentModel.DataAnnotations;
namespace CellularManagement.Application.Features.TestCaseSets.Commands.DeleteTestCaseSet;
/// <summary>
/// 删除用例集命令
/// </summary>
public class DeleteTestCaseSetCommand : IRequest<OperationResult<bool>>
{
/// <summary>
/// 用例集ID
/// </summary>
[Required(ErrorMessage = "用例集ID不能为空")]
[MaxLength(50, ErrorMessage = "用例集ID长度不能超过50个字符")]
public string TestCaseSetId { get; set; } = null!;
}

96
src/X1.Application/Features/TestCaseSets/Commands/DeleteTestCaseSet/DeleteTestCaseSetCommandHandler.cs

@ -0,0 +1,96 @@
using MediatR;
using Microsoft.Extensions.Logging;
using CellularManagement.Domain.Common;
using CellularManagement.Domain.Entities.Device;
using CellularManagement.Domain.Repositories.Device;
using CellularManagement.Domain.Repositories.Base;
using CellularManagement.Domain.Services;
namespace CellularManagement.Application.Features.TestCaseSets.Commands.DeleteTestCaseSet;
/// <summary>
/// 删除用例集命令处理器
/// </summary>
public class DeleteTestCaseSetCommandHandler : IRequestHandler<DeleteTestCaseSetCommand, OperationResult<bool>>
{
private readonly ITestCaseSetRepository _testCaseSetRepository;
private readonly ILogger<DeleteTestCaseSetCommandHandler> _logger;
private readonly IUnitOfWork _unitOfWork;
private readonly ICurrentUserService _currentUserService;
/// <summary>
/// 初始化命令处理器
/// </summary>
public DeleteTestCaseSetCommandHandler(
ITestCaseSetRepository testCaseSetRepository,
ILogger<DeleteTestCaseSetCommandHandler> logger,
IUnitOfWork unitOfWork,
ICurrentUserService currentUserService)
{
_testCaseSetRepository = testCaseSetRepository;
_logger = logger;
_unitOfWork = unitOfWork;
_currentUserService = currentUserService;
}
/// <summary>
/// 处理删除用例集命令
/// </summary>
public async Task<OperationResult<bool>> Handle(DeleteTestCaseSetCommand request, CancellationToken cancellationToken)
{
try
{
_logger.LogInformation("开始删除用例集,用例集ID: {TestCaseSetId}", request.TestCaseSetId);
// 检查用例集是否存在
var existingTestCaseSet = await _testCaseSetRepository.GetTestCaseSetByIdAsync(request.TestCaseSetId, cancellationToken);
if (existingTestCaseSet == null)
{
_logger.LogWarning("用例集不存在: {TestCaseSetId}", request.TestCaseSetId);
return OperationResult<bool>.CreateFailure($"用例集ID {request.TestCaseSetId} 不存在");
}
// 检查用例集是否已被软删除
if (existingTestCaseSet.IsDeleted)
{
_logger.LogWarning("用例集已被删除: {TestCaseSetId}", request.TestCaseSetId);
return OperationResult<bool>.CreateFailure($"用例集ID {request.TestCaseSetId} 已被删除");
}
// 获取当前用户ID
var currentUserId = _currentUserService.GetCurrentUserId();
if (string.IsNullOrEmpty(currentUserId))
{
_logger.LogError("无法获取当前用户ID,用户可能未认证");
return OperationResult<bool>.CreateFailure("用户未认证,无法删除用例集");
}
// 软删除用例集
existingTestCaseSet.SoftDelete();
existingTestCaseSet.Update(
code: existingTestCaseSet.Code,
name: existingTestCaseSet.Name,
version: existingTestCaseSet.Version,
updatedBy: currentUserId,
description: existingTestCaseSet.Description,
versionUpdateInfo: existingTestCaseSet.VersionUpdateInfo,
isDisabled: existingTestCaseSet.IsDisabled,
remarks: existingTestCaseSet.Remarks);
// 保存更改
_testCaseSetRepository.UpdateTestCaseSet(existingTestCaseSet);
// 保存更改到数据库
await _unitOfWork.SaveChangesAsync(cancellationToken);
_logger.LogInformation("用例集删除成功,用例集ID: {TestCaseSetId}, 用例集编码: {Code}, 用例集名称: {Name}, 版本: {Version}",
existingTestCaseSet.Id, existingTestCaseSet.Code, existingTestCaseSet.Name, existingTestCaseSet.Version);
return OperationResult<bool>.CreateSuccess(true);
}
catch (Exception ex)
{
_logger.LogError(ex, "删除用例集时发生错误,用例集ID: {TestCaseSetId}", request.TestCaseSetId);
return OperationResult<bool>.CreateFailure($"删除用例集时发生错误: {ex.Message}");
}
}
}

18
src/X1.Application/Features/TestCaseSets/Commands/DisableTestCaseSet/DisableTestCaseSetCommand.cs

@ -0,0 +1,18 @@
using CellularManagement.Domain.Common;
using MediatR;
using System.ComponentModel.DataAnnotations;
namespace CellularManagement.Application.Features.TestCaseSets.Commands.DisableTestCaseSet;
/// <summary>
/// 禁用用例集命令
/// </summary>
public class DisableTestCaseSetCommand : IRequest<OperationResult<bool>>
{
/// <summary>
/// 用例集ID
/// </summary>
[Required(ErrorMessage = "用例集ID不能为空")]
[MaxLength(50, ErrorMessage = "用例集ID长度不能超过50个字符")]
public string TestCaseSetId { get; set; } = null!;
}

103
src/X1.Application/Features/TestCaseSets/Commands/DisableTestCaseSet/DisableTestCaseSetCommandHandler.cs

@ -0,0 +1,103 @@
using MediatR;
using Microsoft.Extensions.Logging;
using CellularManagement.Domain.Common;
using CellularManagement.Domain.Entities.Device;
using CellularManagement.Domain.Repositories.Device;
using CellularManagement.Domain.Repositories.Base;
using CellularManagement.Domain.Services;
namespace CellularManagement.Application.Features.TestCaseSets.Commands.DisableTestCaseSet;
/// <summary>
/// 禁用用例集命令处理器
/// </summary>
public class DisableTestCaseSetCommandHandler : IRequestHandler<DisableTestCaseSetCommand, OperationResult<bool>>
{
private readonly ITestCaseSetRepository _testCaseSetRepository;
private readonly ILogger<DisableTestCaseSetCommandHandler> _logger;
private readonly IUnitOfWork _unitOfWork;
private readonly ICurrentUserService _currentUserService;
/// <summary>
/// 初始化命令处理器
/// </summary>
public DisableTestCaseSetCommandHandler(
ITestCaseSetRepository testCaseSetRepository,
ILogger<DisableTestCaseSetCommandHandler> logger,
IUnitOfWork unitOfWork,
ICurrentUserService currentUserService)
{
_testCaseSetRepository = testCaseSetRepository;
_logger = logger;
_unitOfWork = unitOfWork;
_currentUserService = currentUserService;
}
/// <summary>
/// 处理禁用用例集命令
/// </summary>
public async Task<OperationResult<bool>> Handle(DisableTestCaseSetCommand request, CancellationToken cancellationToken)
{
try
{
_logger.LogInformation("开始禁用用例集,用例集ID: {TestCaseSetId}", request.TestCaseSetId);
// 检查用例集是否存在
var existingTestCaseSet = await _testCaseSetRepository.GetTestCaseSetByIdAsync(request.TestCaseSetId, cancellationToken);
if (existingTestCaseSet == null)
{
_logger.LogWarning("用例集不存在: {TestCaseSetId}", request.TestCaseSetId);
return OperationResult<bool>.CreateFailure($"用例集ID {request.TestCaseSetId} 不存在");
}
// 检查用例集是否已被软删除
if (existingTestCaseSet.IsDeleted)
{
_logger.LogWarning("用例集已被删除: {TestCaseSetId}", request.TestCaseSetId);
return OperationResult<bool>.CreateFailure($"用例集ID {request.TestCaseSetId} 已被删除");
}
// 检查用例集是否已经禁用
if (existingTestCaseSet.IsDisabled)
{
_logger.LogWarning("用例集已经禁用: {TestCaseSetId}", request.TestCaseSetId);
return OperationResult<bool>.CreateFailure($"用例集ID {request.TestCaseSetId} 已经禁用");
}
// 获取当前用户ID
var currentUserId = _currentUserService.GetCurrentUserId();
if (string.IsNullOrEmpty(currentUserId))
{
_logger.LogError("无法获取当前用户ID,用户可能未认证");
return OperationResult<bool>.CreateFailure("用户未认证,无法禁用用例集");
}
// 禁用用例集
existingTestCaseSet.Disable();
existingTestCaseSet.Update(
code: existingTestCaseSet.Code,
name: existingTestCaseSet.Name,
version: existingTestCaseSet.Version,
updatedBy: currentUserId,
description: existingTestCaseSet.Description,
versionUpdateInfo: existingTestCaseSet.VersionUpdateInfo,
isDisabled: true,
remarks: existingTestCaseSet.Remarks);
// 保存更改
_testCaseSetRepository.UpdateTestCaseSet(existingTestCaseSet);
// 保存更改到数据库
await _unitOfWork.SaveChangesAsync(cancellationToken);
_logger.LogInformation("用例集禁用成功,用例集ID: {TestCaseSetId}, 用例集编码: {Code}, 用例集名称: {Name}, 版本: {Version}",
existingTestCaseSet.Id, existingTestCaseSet.Code, existingTestCaseSet.Name, existingTestCaseSet.Version);
return OperationResult<bool>.CreateSuccess(true);
}
catch (Exception ex)
{
_logger.LogError(ex, "禁用用例集时发生错误,用例集ID: {TestCaseSetId}", request.TestCaseSetId);
return OperationResult<bool>.CreateFailure($"禁用用例集时发生错误: {ex.Message}");
}
}
}

18
src/X1.Application/Features/TestCaseSets/Commands/EnableTestCaseSet/EnableTestCaseSetCommand.cs

@ -0,0 +1,18 @@
using CellularManagement.Domain.Common;
using MediatR;
using System.ComponentModel.DataAnnotations;
namespace CellularManagement.Application.Features.TestCaseSets.Commands.EnableTestCaseSet;
/// <summary>
/// 启用用例集命令
/// </summary>
public class EnableTestCaseSetCommand : IRequest<OperationResult<bool>>
{
/// <summary>
/// 用例集ID
/// </summary>
[Required(ErrorMessage = "用例集ID不能为空")]
[MaxLength(50, ErrorMessage = "用例集ID长度不能超过50个字符")]
public string TestCaseSetId { get; set; } = null!;
}

103
src/X1.Application/Features/TestCaseSets/Commands/EnableTestCaseSet/EnableTestCaseSetCommandHandler.cs

@ -0,0 +1,103 @@
using MediatR;
using Microsoft.Extensions.Logging;
using CellularManagement.Domain.Common;
using CellularManagement.Domain.Entities.Device;
using CellularManagement.Domain.Repositories.Device;
using CellularManagement.Domain.Repositories.Base;
using CellularManagement.Domain.Services;
namespace CellularManagement.Application.Features.TestCaseSets.Commands.EnableTestCaseSet;
/// <summary>
/// 启用用例集命令处理器
/// </summary>
public class EnableTestCaseSetCommandHandler : IRequestHandler<EnableTestCaseSetCommand, OperationResult<bool>>
{
private readonly ITestCaseSetRepository _testCaseSetRepository;
private readonly ILogger<EnableTestCaseSetCommandHandler> _logger;
private readonly IUnitOfWork _unitOfWork;
private readonly ICurrentUserService _currentUserService;
/// <summary>
/// 初始化命令处理器
/// </summary>
public EnableTestCaseSetCommandHandler(
ITestCaseSetRepository testCaseSetRepository,
ILogger<EnableTestCaseSetCommandHandler> logger,
IUnitOfWork unitOfWork,
ICurrentUserService currentUserService)
{
_testCaseSetRepository = testCaseSetRepository;
_logger = logger;
_unitOfWork = unitOfWork;
_currentUserService = currentUserService;
}
/// <summary>
/// 处理启用用例集命令
/// </summary>
public async Task<OperationResult<bool>> Handle(EnableTestCaseSetCommand request, CancellationToken cancellationToken)
{
try
{
_logger.LogInformation("开始启用用例集,用例集ID: {TestCaseSetId}", request.TestCaseSetId);
// 检查用例集是否存在
var existingTestCaseSet = await _testCaseSetRepository.GetTestCaseSetByIdAsync(request.TestCaseSetId, cancellationToken);
if (existingTestCaseSet == null)
{
_logger.LogWarning("用例集不存在: {TestCaseSetId}", request.TestCaseSetId);
return OperationResult<bool>.CreateFailure($"用例集ID {request.TestCaseSetId} 不存在");
}
// 检查用例集是否已被软删除
if (existingTestCaseSet.IsDeleted)
{
_logger.LogWarning("用例集已被删除: {TestCaseSetId}", request.TestCaseSetId);
return OperationResult<bool>.CreateFailure($"用例集ID {request.TestCaseSetId} 已被删除");
}
// 检查用例集是否已经启用
if (!existingTestCaseSet.IsDisabled)
{
_logger.LogWarning("用例集已经启用: {TestCaseSetId}", request.TestCaseSetId);
return OperationResult<bool>.CreateFailure($"用例集ID {request.TestCaseSetId} 已经启用");
}
// 获取当前用户ID
var currentUserId = _currentUserService.GetCurrentUserId();
if (string.IsNullOrEmpty(currentUserId))
{
_logger.LogError("无法获取当前用户ID,用户可能未认证");
return OperationResult<bool>.CreateFailure("用户未认证,无法启用用例集");
}
// 启用用例集
existingTestCaseSet.Enable();
existingTestCaseSet.Update(
code: existingTestCaseSet.Code,
name: existingTestCaseSet.Name,
version: existingTestCaseSet.Version,
updatedBy: currentUserId,
description: existingTestCaseSet.Description,
versionUpdateInfo: existingTestCaseSet.VersionUpdateInfo,
isDisabled: false,
remarks: existingTestCaseSet.Remarks);
// 保存更改
_testCaseSetRepository.UpdateTestCaseSet(existingTestCaseSet);
// 保存更改到数据库
await _unitOfWork.SaveChangesAsync(cancellationToken);
_logger.LogInformation("用例集启用成功,用例集ID: {TestCaseSetId}, 用例集编码: {Code}, 用例集名称: {Name}, 版本: {Version}",
existingTestCaseSet.Id, existingTestCaseSet.Code, existingTestCaseSet.Name, existingTestCaseSet.Version);
return OperationResult<bool>.CreateSuccess(true);
}
catch (Exception ex)
{
_logger.LogError(ex, "启用用例集时发生错误,用例集ID: {TestCaseSetId}", request.TestCaseSetId);
return OperationResult<bool>.CreateFailure($"启用用例集时发生错误: {ex.Message}");
}
}
}

62
src/X1.Application/Features/TestCaseSets/Commands/UpdateTestCaseSet/UpdateTestCaseSetCommand.cs

@ -0,0 +1,62 @@
using CellularManagement.Domain.Common;
using MediatR;
using System.ComponentModel.DataAnnotations;
namespace CellularManagement.Application.Features.TestCaseSets.Commands.UpdateTestCaseSet;
/// <summary>
/// 更新用例集命令
/// </summary>
public class UpdateTestCaseSetCommand : IRequest<OperationResult<UpdateTestCaseSetResponse>>
{
/// <summary>
/// 用例集ID
/// </summary>
[Required(ErrorMessage = "用例集ID不能为空")]
[MaxLength(50, ErrorMessage = "用例集ID长度不能超过50个字符")]
public string TestCaseSetId { get; set; } = null!;
/// <summary>
/// 用例集编码
/// </summary>
[Required(ErrorMessage = "用例集编码不能为空")]
[MaxLength(50, ErrorMessage = "用例集编码长度不能超过50个字符")]
public string Code { get; set; } = null!;
/// <summary>
/// 用例集名称
/// </summary>
[Required(ErrorMessage = "用例集名称不能为空")]
[MaxLength(100, ErrorMessage = "用例集名称长度不能超过100个字符")]
public string Name { get; set; } = null!;
/// <summary>
/// 用例集说明
/// </summary>
[MaxLength(1000, ErrorMessage = "用例集说明长度不能超过1000个字符")]
public string? Description { get; set; }
/// <summary>
/// 用例集版本
/// </summary>
[Required(ErrorMessage = "用例集版本不能为空")]
[MaxLength(20, ErrorMessage = "用例集版本长度不能超过20个字符")]
public string Version { get; set; } = null!;
/// <summary>
/// 版本更新信息
/// </summary>
[MaxLength(500, ErrorMessage = "版本更新信息长度不能超过500个字符")]
public string? VersionUpdateInfo { get; set; }
/// <summary>
/// 是否禁用
/// </summary>
public bool IsDisabled { get; set; } = false;
/// <summary>
/// 备注
/// </summary>
[MaxLength(1000, ErrorMessage = "备注长度不能超过1000个字符")]
public string? Remarks { get; set; }
}

121
src/X1.Application/Features/TestCaseSets/Commands/UpdateTestCaseSet/UpdateTestCaseSetCommandHandler.cs

@ -0,0 +1,121 @@
using MediatR;
using Microsoft.Extensions.Logging;
using CellularManagement.Domain.Common;
using CellularManagement.Domain.Entities.Device;
using CellularManagement.Domain.Repositories.Device;
using CellularManagement.Domain.Repositories.Base;
using CellularManagement.Domain.Services;
namespace CellularManagement.Application.Features.TestCaseSets.Commands.UpdateTestCaseSet;
/// <summary>
/// 更新用例集命令处理器
/// </summary>
public class UpdateTestCaseSetCommandHandler : IRequestHandler<UpdateTestCaseSetCommand, OperationResult<UpdateTestCaseSetResponse>>
{
private readonly ITestCaseSetRepository _testCaseSetRepository;
private readonly ILogger<UpdateTestCaseSetCommandHandler> _logger;
private readonly IUnitOfWork _unitOfWork;
private readonly ICurrentUserService _currentUserService;
/// <summary>
/// 初始化命令处理器
/// </summary>
public UpdateTestCaseSetCommandHandler(
ITestCaseSetRepository testCaseSetRepository,
ILogger<UpdateTestCaseSetCommandHandler> logger,
IUnitOfWork unitOfWork,
ICurrentUserService currentUserService)
{
_testCaseSetRepository = testCaseSetRepository;
_logger = logger;
_unitOfWork = unitOfWork;
_currentUserService = currentUserService;
}
/// <summary>
/// 处理更新用例集命令
/// </summary>
public async Task<OperationResult<UpdateTestCaseSetResponse>> Handle(UpdateTestCaseSetCommand request, CancellationToken cancellationToken)
{
try
{
_logger.LogInformation("开始更新用例集,用例集ID: {TestCaseSetId}, 用例集编码: {Code}, 用例集名称: {Name}, 版本: {Version}",
request.TestCaseSetId, request.Code, request.Name, request.Version);
// 检查用例集是否存在
var existingTestCaseSet = await _testCaseSetRepository.GetTestCaseSetByIdAsync(request.TestCaseSetId, cancellationToken);
if (existingTestCaseSet == null)
{
_logger.LogWarning("用例集不存在: {TestCaseSetId}", request.TestCaseSetId);
return OperationResult<UpdateTestCaseSetResponse>.CreateFailure($"用例集ID {request.TestCaseSetId} 不存在");
}
// 检查用例集编码是否已被其他用例集使用
var testCaseSetWithSameCode = await _testCaseSetRepository.GetTestCaseSetByCodeAsync(request.Code, cancellationToken);
if (testCaseSetWithSameCode != null && testCaseSetWithSameCode.Id != request.TestCaseSetId)
{
_logger.LogWarning("用例集编码已被其他用例集使用: {Code}", request.Code);
return OperationResult<UpdateTestCaseSetResponse>.CreateFailure($"用例集编码 {request.Code} 已被其他用例集使用");
}
// 检查用例集版本是否已被其他用例集使用
var testCaseSetWithSameVersion = await _testCaseSetRepository.GetTestCaseSetByVersionAsync(request.Version, cancellationToken);
if (testCaseSetWithSameVersion != null && testCaseSetWithSameVersion.Id != request.TestCaseSetId)
{
_logger.LogWarning("用例集版本已被其他用例集使用: {Version}", request.Version);
return OperationResult<UpdateTestCaseSetResponse>.CreateFailure($"用例集版本 {request.Version} 已被其他用例集使用");
}
// 获取当前用户ID
var currentUserId = _currentUserService.GetCurrentUserId();
if (string.IsNullOrEmpty(currentUserId))
{
_logger.LogError("无法获取当前用户ID,用户可能未认证");
return OperationResult<UpdateTestCaseSetResponse>.CreateFailure("用户未认证,无法更新用例集");
}
// 更新用例集
existingTestCaseSet.Update(
code: request.Code,
name: request.Name,
version: request.Version,
updatedBy: currentUserId,
description: request.Description,
versionUpdateInfo: request.VersionUpdateInfo,
isDisabled: request.IsDisabled,
remarks: request.Remarks);
// 保存更改
_testCaseSetRepository.UpdateTestCaseSet(existingTestCaseSet);
// 保存更改到数据库
await _unitOfWork.SaveChangesAsync(cancellationToken);
// 构建响应
var response = new UpdateTestCaseSetResponse
{
TestCaseSetId = existingTestCaseSet.Id,
Code = existingTestCaseSet.Code,
Name = existingTestCaseSet.Name,
Description = existingTestCaseSet.Description,
Version = existingTestCaseSet.Version,
VersionUpdateInfo = existingTestCaseSet.VersionUpdateInfo,
IsDisabled = existingTestCaseSet.IsDisabled,
Remarks = existingTestCaseSet.Remarks,
UpdatedAt = existingTestCaseSet.UpdatedAt,
UpdatedBy = existingTestCaseSet.UpdatedBy
};
_logger.LogInformation("用例集更新成功,用例集ID: {TestCaseSetId}, 用例集编码: {Code}, 用例集名称: {Name}, 版本: {Version}",
existingTestCaseSet.Id, existingTestCaseSet.Code, existingTestCaseSet.Name, existingTestCaseSet.Version);
return OperationResult<UpdateTestCaseSetResponse>.CreateSuccess(response);
}
catch (Exception ex)
{
_logger.LogError(ex, "更新用例集时发生错误,用例集ID: {TestCaseSetId}, 用例集编码: {Code}, 用例集名称: {Name}, 版本: {Version}",
request.TestCaseSetId, request.Code, request.Name, request.Version);
return OperationResult<UpdateTestCaseSetResponse>.CreateFailure($"更新用例集时发生错误: {ex.Message}");
}
}
}

57
src/X1.Application/Features/TestCaseSets/Commands/UpdateTestCaseSet/UpdateTestCaseSetResponse.cs

@ -0,0 +1,57 @@
namespace CellularManagement.Application.Features.TestCaseSets.Commands.UpdateTestCaseSet;
/// <summary>
/// 更新用例集响应
/// </summary>
public class UpdateTestCaseSetResponse
{
/// <summary>
/// 用例集ID
/// </summary>
public string TestCaseSetId { get; set; } = null!;
/// <summary>
/// 用例集编码
/// </summary>
public string Code { get; set; } = null!;
/// <summary>
/// 用例集名称
/// </summary>
public string Name { get; set; } = null!;
/// <summary>
/// 用例集说明
/// </summary>
public string? Description { get; set; }
/// <summary>
/// 用例集版本
/// </summary>
public string Version { get; set; } = null!;
/// <summary>
/// 版本更新信息
/// </summary>
public string? VersionUpdateInfo { get; set; }
/// <summary>
/// 是否禁用
/// </summary>
public bool IsDisabled { get; set; }
/// <summary>
/// 备注
/// </summary>
public string? Remarks { get; set; }
/// <summary>
/// 更新时间
/// </summary>
public DateTime? UpdatedAt { get; set; }
/// <summary>
/// 修改人
/// </summary>
public string? UpdatedBy { get; set; }
}

18
src/X1.Application/Features/TestCaseSets/Queries/GetTestCaseSetById/GetTestCaseSetByIdQuery.cs

@ -0,0 +1,18 @@
using CellularManagement.Domain.Common;
using MediatR;
using System.ComponentModel.DataAnnotations;
namespace CellularManagement.Application.Features.TestCaseSets.Queries.GetTestCaseSetById;
/// <summary>
/// 根据ID获取用例集查询
/// </summary>
public class GetTestCaseSetByIdQuery : IRequest<OperationResult<GetTestCaseSetByIdResponse>>
{
/// <summary>
/// 用例集ID
/// </summary>
[Required(ErrorMessage = "用例集ID不能为空")]
[MaxLength(50, ErrorMessage = "用例集ID长度不能超过50个字符")]
public string Id { get; set; } = null!;
}

84
src/X1.Application/Features/TestCaseSets/Queries/GetTestCaseSetById/GetTestCaseSetByIdQueryHandler.cs

@ -0,0 +1,84 @@
using MediatR;
using Microsoft.Extensions.Logging;
using CellularManagement.Domain.Common;
using CellularManagement.Domain.Entities.Device;
using CellularManagement.Domain.Repositories;
using System.ComponentModel.DataAnnotations;
using CellularManagement.Domain.Repositories.Device;
namespace CellularManagement.Application.Features.TestCaseSets.Queries.GetTestCaseSetById;
/// <summary>
/// 根据ID获取用例集查询处理器
/// </summary>
public class GetTestCaseSetByIdQueryHandler : IRequestHandler<GetTestCaseSetByIdQuery, OperationResult<GetTestCaseSetByIdResponse>>
{
private readonly ITestCaseSetRepository _testCaseSetRepository;
private readonly ILogger<GetTestCaseSetByIdQueryHandler> _logger;
/// <summary>
/// 初始化查询处理器
/// </summary>
public GetTestCaseSetByIdQueryHandler(
ITestCaseSetRepository testCaseSetRepository,
ILogger<GetTestCaseSetByIdQueryHandler> logger)
{
_testCaseSetRepository = testCaseSetRepository;
_logger = logger;
}
/// <summary>
/// 处理根据ID获取用例集查询
/// </summary>
public async Task<OperationResult<GetTestCaseSetByIdResponse>> Handle(GetTestCaseSetByIdQuery request, CancellationToken cancellationToken)
{
try
{
// 验证请求参数
var validationContext = new ValidationContext(request);
var validationResults = new List<ValidationResult>();
if (!Validator.TryValidateObject(request, validationContext, validationResults, true))
{
var errorMessages = validationResults.Select(r => r.ErrorMessage).ToList();
_logger.LogWarning("请求参数无效: {Errors}", string.Join(", ", errorMessages));
return OperationResult<GetTestCaseSetByIdResponse>.CreateFailure(errorMessages);
}
_logger.LogInformation("开始根据ID获取用例集,ID: {Id}", request.Id);
// 获取用例集数据
var testCaseSet = await _testCaseSetRepository.GetTestCaseSetByIdAsync(request.Id, cancellationToken);
if (testCaseSet == null)
{
_logger.LogWarning("未找到指定的用例集,ID: {Id}", request.Id);
return OperationResult<GetTestCaseSetByIdResponse>.CreateFailure($"未找到ID为 {request.Id} 的用例集");
}
// 构建响应
var response = new GetTestCaseSetByIdResponse
{
TestCaseSetId = testCaseSet.Id,
Code = testCaseSet.Code,
Name = testCaseSet.Name,
Description = testCaseSet.Description,
Version = testCaseSet.Version,
VersionUpdateInfo = testCaseSet.VersionUpdateInfo,
IsDisabled = testCaseSet.IsDisabled,
Remarks = testCaseSet.Remarks,
CreatedAt = testCaseSet.CreatedAt,
UpdatedAt = testCaseSet.UpdatedAt,
CreatedBy = testCaseSet.CreatedBy,
UpdatedBy = testCaseSet.UpdatedBy
};
_logger.LogInformation("成功获取用例集信息,ID: {Id}", request.Id);
return OperationResult<GetTestCaseSetByIdResponse>.CreateSuccess(response);
}
catch (Exception ex)
{
_logger.LogError(ex, "根据ID获取用例集时发生错误,ID: {Id}", request.Id);
return OperationResult<GetTestCaseSetByIdResponse>.CreateFailure($"根据ID获取用例集时发生错误: {ex.Message}");
}
}
}

67
src/X1.Application/Features/TestCaseSets/Queries/GetTestCaseSetById/GetTestCaseSetByIdResponse.cs

@ -0,0 +1,67 @@
namespace CellularManagement.Application.Features.TestCaseSets.Queries.GetTestCaseSetById;
/// <summary>
/// 根据ID获取用例集响应
/// </summary>
public class GetTestCaseSetByIdResponse
{
/// <summary>
/// 用例集ID
/// </summary>
public string TestCaseSetId { get; set; } = null!;
/// <summary>
/// 用例集编码
/// </summary>
public string Code { get; set; } = null!;
/// <summary>
/// 用例集名称
/// </summary>
public string Name { get; set; } = null!;
/// <summary>
/// 用例集说明
/// </summary>
public string? Description { get; set; }
/// <summary>
/// 用例集版本
/// </summary>
public string Version { get; set; } = null!;
/// <summary>
/// 版本更新信息
/// </summary>
public string? VersionUpdateInfo { get; set; }
/// <summary>
/// 是否禁用
/// </summary>
public bool IsDisabled { get; set; }
/// <summary>
/// 备注
/// </summary>
public string? Remarks { get; set; }
/// <summary>
/// 创建时间
/// </summary>
public DateTime CreatedAt { get; set; }
/// <summary>
/// 更新时间
/// </summary>
public DateTime? UpdatedAt { get; set; }
/// <summary>
/// 创建人
/// </summary>
public string CreatedBy { get; set; } = null!;
/// <summary>
/// 修改人
/// </summary>
public string? UpdatedBy { get; set; }
}

40
src/X1.Application/Features/TestCaseSets/Queries/GetTestCaseSets/GetTestCaseSetsQuery.cs

@ -0,0 +1,40 @@
using CellularManagement.Domain.Common;
using MediatR;
using System.ComponentModel.DataAnnotations;
namespace CellularManagement.Application.Features.TestCaseSets.Queries.GetTestCaseSets;
/// <summary>
/// 获取用例集列表查询
/// </summary>
public class GetTestCaseSetsQuery : IRequest<OperationResult<GetTestCaseSetsResponse>>
{
/// <summary>
/// 页码
/// </summary>
[Range(1, int.MaxValue, ErrorMessage = "页码必须大于0")]
public int PageNumber { get; set; } = 1;
/// <summary>
/// 每页数量
/// </summary>
[Range(1, 100, ErrorMessage = "每页数量必须在1-100之间")]
public int PageSize { get; set; } = 10;
/// <summary>
/// 搜索关键词
/// </summary>
[MaxLength(100)]
public string? SearchTerm { get; set; }
/// <summary>
/// 是否只获取启用的用例集
/// </summary>
public bool? IsEnabled { get; set; }
/// <summary>
/// 版本过滤
/// </summary>
[MaxLength(20)]
public string? Version { get; set; }
}

111
src/X1.Application/Features/TestCaseSets/Queries/GetTestCaseSets/GetTestCaseSetsQueryHandler.cs

@ -0,0 +1,111 @@
using MediatR;
using Microsoft.Extensions.Logging;
using CellularManagement.Domain.Common;
using CellularManagement.Domain.Entities.Device;
using CellularManagement.Domain.Repositories;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using CellularManagement.Application.Features.TestCaseSets.Queries.GetTestCaseSetById;
using CellularManagement.Domain.Repositories.Device;
namespace CellularManagement.Application.Features.TestCaseSets.Queries.GetTestCaseSets;
/// <summary>
/// 获取用例集列表查询处理器
/// </summary>
public class GetTestCaseSetsQueryHandler : IRequestHandler<GetTestCaseSetsQuery, OperationResult<GetTestCaseSetsResponse>>
{
private readonly ITestCaseSetRepository _testCaseSetRepository;
private readonly ILogger<GetTestCaseSetsQueryHandler> _logger;
/// <summary>
/// 初始化查询处理器
/// </summary>
public GetTestCaseSetsQueryHandler(
ITestCaseSetRepository testCaseSetRepository,
ILogger<GetTestCaseSetsQueryHandler> logger)
{
_testCaseSetRepository = testCaseSetRepository;
_logger = logger;
}
/// <summary>
/// 处理获取用例集列表查询
/// </summary>
public async Task<OperationResult<GetTestCaseSetsResponse>> Handle(GetTestCaseSetsQuery request, CancellationToken cancellationToken)
{
try
{
// 验证请求参数
var validationContext = new ValidationContext(request);
var validationResults = new List<ValidationResult>();
if (!Validator.TryValidateObject(request, validationContext, validationResults, true))
{
var errorMessages = validationResults.Select(r => r.ErrorMessage).ToList();
_logger.LogWarning("请求参数无效: {Errors}", string.Join(", ", errorMessages));
return OperationResult<GetTestCaseSetsResponse>.CreateFailure(errorMessages);
}
_logger.LogInformation("开始获取用例集列表,页码: {PageNumber}, 每页数量: {PageSize}, 搜索关键词: {SearchTerm}, 是否启用: {IsEnabled}, 版本: {Version}",
request.PageNumber, request.PageSize, request.SearchTerm, request.IsEnabled, request.Version);
// 获取用例集数据
var testCaseSets = await _testCaseSetRepository.SearchTestCaseSetsAsync(
request.SearchTerm,
cancellationToken);
// 如果指定了启用状态过滤
if (request.IsEnabled.HasValue)
{
testCaseSets = testCaseSets.Where(tcs => !tcs.IsDisabled == request.IsEnabled.Value).ToList();
}
// 如果指定了版本过滤
if (!string.IsNullOrEmpty(request.Version))
{
testCaseSets = testCaseSets.Where(tcs => tcs.Version == request.Version).ToList();
}
// 计算分页
int totalCount = testCaseSets.Count();
var items = testCaseSets
.Skip((request.PageNumber - 1) * request.PageSize)
.Take(request.PageSize)
.ToList();
// 构建响应
var response = new GetTestCaseSetsResponse
{
TotalCount = totalCount,
PageNumber = request.PageNumber,
PageSize = request.PageSize,
TotalPages = (int)Math.Ceiling(totalCount / (double)request.PageSize),
HasPreviousPage = request.PageNumber > 1,
HasNextPage = request.PageNumber < (int)Math.Ceiling(totalCount / (double)request.PageSize),
Items = items.Select(tcs => new GetTestCaseSetByIdResponse
{
TestCaseSetId = tcs.Id,
Code = tcs.Code,
Name = tcs.Name,
Description = tcs.Description,
Version = tcs.Version,
VersionUpdateInfo = tcs.VersionUpdateInfo,
IsDisabled = tcs.IsDisabled,
Remarks = tcs.Remarks,
CreatedAt = tcs.CreatedAt,
UpdatedAt = tcs.UpdatedAt,
CreatedBy = tcs.CreatedBy,
UpdatedBy = tcs.UpdatedBy
}).ToList()
};
_logger.LogInformation("成功获取用例集列表,共 {Count} 条记录", items.Count);
return OperationResult<GetTestCaseSetsResponse>.CreateSuccess(response);
}
catch (Exception ex)
{
_logger.LogError(ex, "获取用例集列表时发生错误");
return OperationResult<GetTestCaseSetsResponse>.CreateFailure($"获取用例集列表时发生错误: {ex.Message}");
}
}
}

44
src/X1.Application/Features/TestCaseSets/Queries/GetTestCaseSets/GetTestCaseSetsResponse.cs

@ -0,0 +1,44 @@
using CellularManagement.Application.Features.TestCaseSets.Queries.GetTestCaseSetById;
namespace CellularManagement.Application.Features.TestCaseSets.Queries.GetTestCaseSets;
/// <summary>
/// 获取用例集列表响应
/// </summary>
public class GetTestCaseSetsResponse
{
/// <summary>
/// 总数量
/// </summary>
public int TotalCount { get; set; }
/// <summary>
/// 当前页码
/// </summary>
public int PageNumber { get; set; }
/// <summary>
/// 每页数量
/// </summary>
public int PageSize { get; set; }
/// <summary>
/// 总页数
/// </summary>
public int TotalPages { get; set; }
/// <summary>
/// 是否有上一页
/// </summary>
public bool HasPreviousPage { get; set; }
/// <summary>
/// 是否有下一页
/// </summary>
public bool HasNextPage { get; set; }
/// <summary>
/// 用例集列表
/// </summary>
public List<GetTestCaseSetByIdResponse> Items { get; set; } = new();
}

148
src/X1.Domain/Entities/Device/TestCaseSet.cs

@ -0,0 +1,148 @@
using System.ComponentModel.DataAnnotations;
using CellularManagement.Domain.Entities.Common;
namespace CellularManagement.Domain.Entities.Device;
/// <summary>
/// 用例集实体
/// </summary>
public class TestCaseSet : AuditableEntity
{
private TestCaseSet() { }
/// <summary>
/// 用例集编码
/// </summary>
[Required]
[MaxLength(50)]
public string Code { get; private set; } = null!;
/// <summary>
/// 用例集名称
/// </summary>
[Required]
[MaxLength(100)]
public string Name { get; private set; } = null!;
/// <summary>
/// 用例集说明
/// </summary>
[MaxLength(1000)]
public string? Description { get; private set; }
/// <summary>
/// 用例集版本
/// </summary>
[Required]
[MaxLength(20)]
public string Version { get; private set; } = null!;
/// <summary>
/// 版本更新信息
/// </summary>
[MaxLength(500)]
public string? VersionUpdateInfo { get; private set; }
/// <summary>
/// 是否禁用
/// </summary>
public bool IsDisabled { get; private set; } = false;
/// <summary>
/// 备注
/// </summary>
[MaxLength(1000)]
public string? Remarks { get; private set; }
/// <summary>
/// 创建用例集
/// </summary>
public static TestCaseSet Create(
string code,
string name,
string version,
string createdBy,
string? description = null,
string? versionUpdateInfo = null,
bool isDisabled = false,
string? remarks = null)
{
var testCaseSet = new TestCaseSet
{
Id = Guid.NewGuid().ToString(),
Code = code,
Name = name,
Description = description,
Version = version,
VersionUpdateInfo = versionUpdateInfo,
IsDisabled = isDisabled,
Remarks = remarks,
CreatedAt = DateTime.UtcNow,
UpdatedAt = DateTime.UtcNow,
CreatedBy = createdBy,
UpdatedBy = createdBy
};
return testCaseSet;
}
/// <summary>
/// 更新用例集
/// </summary>
public void Update(
string code,
string name,
string version,
string updatedBy,
string? description = null,
string? versionUpdateInfo = null,
bool isDisabled = false,
string? remarks = null)
{
Code = code;
Name = name;
Description = description;
Version = version;
VersionUpdateInfo = versionUpdateInfo;
IsDisabled = isDisabled;
Remarks = remarks;
UpdatedAt = DateTime.UtcNow;
UpdatedBy = updatedBy;
}
/// <summary>
/// 启用用例集
/// </summary>
public void Enable()
{
IsDisabled = false;
UpdatedAt = DateTime.UtcNow;
}
/// <summary>
/// 禁用用例集
/// </summary>
public void Disable()
{
IsDisabled = true;
UpdatedAt = DateTime.UtcNow;
}
/// <summary>
/// 软删除用例集
/// </summary>
public void SoftDelete()
{
IsDeleted = true;
UpdatedAt = DateTime.UtcNow;
}
/// <summary>
/// 恢复用例集
/// </summary>
public void Restore()
{
IsDeleted = false;
UpdatedAt = DateTime.UtcNow;
}
}

73
src/X1.Domain/Repositories/Device/ITestCaseSetRepository.cs

@ -0,0 +1,73 @@
using CellularManagement.Domain.Entities;
using CellularManagement.Domain.Entities.Device;
using CellularManagement.Domain.Repositories.Base;
namespace CellularManagement.Domain.Repositories.Device;
/// <summary>
/// 用例集仓储接口
/// </summary>
public interface ITestCaseSetRepository : IBaseRepository<TestCaseSet>
{
/// <summary>
/// 添加用例集
/// </summary>
Task<TestCaseSet> AddTestCaseSetAsync(TestCaseSet testCaseSet, CancellationToken cancellationToken = default);
/// <summary>
/// 更新用例集
/// </summary>
void UpdateTestCaseSet(TestCaseSet testCaseSet);
/// <summary>
/// 删除用例集
/// </summary>
Task DeleteTestCaseSetAsync(string id, CancellationToken cancellationToken = default);
/// <summary>
/// 获取所有用例集
/// </summary>
Task<IList<TestCaseSet>> GetAllTestCaseSetsAsync(CancellationToken cancellationToken = default);
/// <summary>
/// 根据ID获取用例集
/// </summary>
Task<TestCaseSet?> GetTestCaseSetByIdAsync(string id, CancellationToken cancellationToken = default);
/// <summary>
/// 根据编码获取用例集
/// </summary>
Task<TestCaseSet?> GetTestCaseSetByCodeAsync(string code, CancellationToken cancellationToken = default);
/// <summary>
/// 根据版本获取用例集
/// </summary>
Task<TestCaseSet?> GetTestCaseSetByVersionAsync(string version, CancellationToken cancellationToken = default);
/// <summary>
/// 搜索用例集
/// </summary>
Task<IList<TestCaseSet>> SearchTestCaseSetsAsync(
string? keyword,
CancellationToken cancellationToken = default);
/// <summary>
/// 检查用例集是否存在
/// </summary>
Task<bool> ExistsAsync(string id, CancellationToken cancellationToken = default);
/// <summary>
/// 检查编码是否存在
/// </summary>
Task<bool> CodeExistsAsync(string code, CancellationToken cancellationToken = default);
/// <summary>
/// 检查版本是否存在
/// </summary>
Task<bool> VersionExistsAsync(string version, CancellationToken cancellationToken = default);
/// <summary>
/// 获取启用的用例集
/// </summary>
Task<IList<TestCaseSet>> GetEnabledTestCaseSetsAsync(CancellationToken cancellationToken = default);
}

32
src/X1.Infrastructure/Configurations/Device/TestCaseSetConfiguration.cs

@ -0,0 +1,32 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using CellularManagement.Domain.Entities.Device;
namespace CellularManagement.Infrastructure.Configurations.Device;
public class TestCaseSetConfiguration : IEntityTypeConfiguration<TestCaseSet>
{
public void Configure(EntityTypeBuilder<TestCaseSet> builder)
{
builder.ToTable("TestCaseSets", t => t.HasComment("用例集表"));
builder.HasKey(tcs => tcs.Id);
// 配置索引
builder.HasIndex(tcs => tcs.Code).IsUnique().HasDatabaseName("IX_TestCaseSets_Code");
builder.HasIndex(tcs => tcs.Version).HasDatabaseName("IX_TestCaseSets_Version");
// 配置属性
builder.Property(tcs => tcs.Id).HasComment("用例集ID");
builder.Property(tcs => tcs.Code).IsRequired().HasMaxLength(50).HasComment("用例集编码");
builder.Property(tcs => tcs.Name).IsRequired().HasMaxLength(100).HasComment("用例集名称");
builder.Property(tcs => tcs.Description).HasMaxLength(1000).HasComment("用例集说明");
builder.Property(tcs => tcs.Version).IsRequired().HasMaxLength(20).HasComment("用例集版本");
builder.Property(tcs => tcs.VersionUpdateInfo).HasMaxLength(500).HasComment("版本更新信息");
builder.Property(tcs => tcs.IsDisabled).IsRequired().HasComment("是否禁用");
builder.Property(tcs => tcs.Remarks).HasMaxLength(1000).HasComment("备注");
builder.Property(tcs => tcs.CreatedAt).IsRequired().HasColumnType("timestamp with time zone").HasComment("创建时间");
builder.Property(tcs => tcs.UpdatedAt).HasColumnType("timestamp with time zone").HasComment("更新时间");
builder.Property(tcs => tcs.CreatedBy).IsRequired().HasMaxLength(50).HasComment("创建人");
builder.Property(tcs => tcs.UpdatedBy).HasMaxLength(50).HasComment("修改人");
}
}

5
src/X1.Infrastructure/Context/AppDbContext.cs

@ -56,6 +56,11 @@ public class AppDbContext : IdentityDbContext<AppUser, AppRole, string>
/// </summary>
public DbSet<Scenario> Scenarios { get; set; } = null!;
/// <summary>
/// 用例集集合
/// </summary>
public DbSet<TestCaseSet> TestCaseSets { get; set; } = null!;
/// <summary>
/// 初始化数据库上下文
/// </summary>

1
src/X1.Infrastructure/DependencyInjection.cs

@ -176,6 +176,7 @@ public static class DependencyInjection
services.AddScoped<IProtocolVersionRepository, ProtocolVersionRepository>();
services.AddScoped<INetworkConfigRepository, NetworkConfigRepository>();
services.AddScoped<IScenarioRepository, ScenarioRepository>();
services.AddScoped<ITestCaseSetRepository, TestCaseSetRepository>();
return services;
}

149
src/X1.Infrastructure/Repositories/Device/TestCaseSetRepository.cs

@ -0,0 +1,149 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using System.Linq;
using Microsoft.Extensions.Logging;
using CellularManagement.Domain.Entities;
using CellularManagement.Domain.Repositories;
using CellularManagement.Infrastructure.Repositories.Base;
using CellularManagement.Domain.Entities.Device;
using CellularManagement.Domain.Repositories.Base;
using CellularManagement.Domain.Repositories.Device;
namespace CellularManagement.Infrastructure.Repositories.Device;
/// <summary>
/// 用例集仓储实现类
/// </summary>
public class TestCaseSetRepository : BaseRepository<TestCaseSet>, ITestCaseSetRepository
{
private readonly ILogger<TestCaseSetRepository> _logger;
/// <summary>
/// 初始化仓储
/// </summary>
public TestCaseSetRepository(
ICommandRepository<TestCaseSet> commandRepository,
IQueryRepository<TestCaseSet> queryRepository,
ILogger<TestCaseSetRepository> logger)
: base(commandRepository, queryRepository, logger)
{
_logger = logger;
}
/// <summary>
/// 添加用例集
/// </summary>
public async Task<TestCaseSet> AddTestCaseSetAsync(TestCaseSet testCaseSet, CancellationToken cancellationToken = default)
{
var result = await CommandRepository.AddAsync(testCaseSet, cancellationToken);
return result;
}
/// <summary>
/// 更新用例集
/// </summary>
public void UpdateTestCaseSet(TestCaseSet testCaseSet)
{
CommandRepository.Update(testCaseSet);
}
/// <summary>
/// 删除用例集
/// </summary>
public async Task DeleteTestCaseSetAsync(string id, CancellationToken cancellationToken = default)
{
await CommandRepository.DeleteByIdAsync(id, cancellationToken);
}
/// <summary>
/// 获取所有用例集
/// </summary>
public async Task<IList<TestCaseSet>> GetAllTestCaseSetsAsync(CancellationToken cancellationToken = default)
{
var testCaseSets = await QueryRepository.GetAllAsync(cancellationToken: cancellationToken);
return testCaseSets.ToList();
}
/// <summary>
/// 根据ID获取用例集
/// </summary>
public async Task<TestCaseSet?> GetTestCaseSetByIdAsync(string id, CancellationToken cancellationToken = default)
{
return await QueryRepository.GetByIdAsync(id, cancellationToken: cancellationToken);
}
/// <summary>
/// 根据编码获取用例集
/// </summary>
public async Task<TestCaseSet?> GetTestCaseSetByCodeAsync(string code, CancellationToken cancellationToken = default)
{
return await QueryRepository.FirstOrDefaultAsync(tcs => tcs.Code == code, cancellationToken: cancellationToken);
}
/// <summary>
/// 根据版本获取用例集
/// </summary>
public async Task<TestCaseSet?> GetTestCaseSetByVersionAsync(string version, CancellationToken cancellationToken = default)
{
return await QueryRepository.FirstOrDefaultAsync(tcs => tcs.Version == version, cancellationToken: cancellationToken);
}
/// <summary>
/// 搜索用例集
/// </summary>
public async Task<IList<TestCaseSet>> SearchTestCaseSetsAsync(
string? keyword,
CancellationToken cancellationToken = default)
{
var query = await QueryRepository.FindAsync(tcs => true, cancellationToken: cancellationToken);
if (!string.IsNullOrWhiteSpace(keyword))
{
query = query.Where(tcs =>
tcs.Name.Contains(keyword) ||
tcs.Code.Contains(keyword) ||
tcs.Version.Contains(keyword) ||
(tcs.Description != null && tcs.Description.Contains(keyword)) ||
(tcs.VersionUpdateInfo != null && tcs.VersionUpdateInfo.Contains(keyword)) ||
(tcs.Remarks != null && tcs.Remarks.Contains(keyword)));
}
var testCaseSets = query;
return testCaseSets.ToList();
}
/// <summary>
/// 检查用例集是否存在
/// </summary>
public async Task<bool> ExistsAsync(string id, CancellationToken cancellationToken = default)
{
return await QueryRepository.AnyAsync(tcs => tcs.Id == id, cancellationToken: cancellationToken);
}
/// <summary>
/// 检查编码是否存在
/// </summary>
public async Task<bool> CodeExistsAsync(string code, CancellationToken cancellationToken = default)
{
return await QueryRepository.AnyAsync(tcs => tcs.Code == code, cancellationToken: cancellationToken);
}
/// <summary>
/// 检查版本是否存在
/// </summary>
public async Task<bool> VersionExistsAsync(string version, CancellationToken cancellationToken = default)
{
return await QueryRepository.AnyAsync(tcs => tcs.Version == version, cancellationToken: cancellationToken);
}
/// <summary>
/// 获取启用的用例集
/// </summary>
public async Task<IList<TestCaseSet>> GetEnabledTestCaseSetsAsync(CancellationToken cancellationToken = default)
{
var testCaseSets = await QueryRepository.FindAsync(tcs => !tcs.IsDisabled, cancellationToken: cancellationToken);
return testCaseSets.ToList();
}
}

175
src/X1.Presentation/Controllers/TestCaseSetsController.cs

@ -0,0 +1,175 @@
using CellularManagement.Application.Features.TestCaseSets.Commands.CreateTestCaseSet;
using CellularManagement.Application.Features.TestCaseSets.Commands.DeleteTestCaseSet;
using CellularManagement.Application.Features.TestCaseSets.Commands.DisableTestCaseSet;
using CellularManagement.Application.Features.TestCaseSets.Commands.EnableTestCaseSet;
using CellularManagement.Application.Features.TestCaseSets.Commands.UpdateTestCaseSet;
using CellularManagement.Application.Features.TestCaseSets.Queries.GetTestCaseSetById;
using CellularManagement.Application.Features.TestCaseSets.Queries.GetTestCaseSets;
using CellularManagement.Domain.Common;
using CellularManagement.Presentation.Abstractions;
using MediatR;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
namespace CellularManagement.Presentation.Controllers;
/// <summary>
/// 用例集管理控制器
/// </summary>
[Route("api/testcasesets")]
[ApiController]
[Authorize]
public class TestCaseSetsController : ApiController
{
private readonly ILogger<TestCaseSetsController> _logger;
/// <summary>
/// 初始化用例集控制器
/// </summary>
public TestCaseSetsController(IMediator mediator, ILogger<TestCaseSetsController> logger)
: base(mediator)
{
_logger = logger;
}
/// <summary>
/// 获取用例集列表
/// </summary>
[HttpGet]
public async Task<OperationResult<GetTestCaseSetsResponse>> GetAll([FromQuery] GetTestCaseSetsQuery query)
{
_logger.LogInformation("开始获取用例集列表,页码: {PageNumber}, 每页数量: {PageSize}, 搜索关键词: {SearchTerm}, 是否启用: {IsEnabled}, 版本: {Version}",
query.PageNumber, query.PageSize, query.SearchTerm, query.IsEnabled, query.Version);
var result = await mediator.Send(query);
if (!result.IsSuccess)
{
_logger.LogWarning("获取用例集列表失败: {Message}", result.ErrorMessages);
return result;
}
_logger.LogInformation("成功获取用例集列表,共 {Count} 条记录", result.Data?.TotalCount ?? 0);
return result;
}
/// <summary>
/// 获取用例集详情
/// </summary>
[HttpGet("{id}")]
public async Task<OperationResult<GetTestCaseSetByIdResponse>> GetById(string id)
{
_logger.LogInformation("开始获取用例集详情,用例集ID: {TestCaseSetId}", id);
var result = await mediator.Send(new GetTestCaseSetByIdQuery { Id = id });
if (!result.IsSuccess)
{
_logger.LogWarning("获取用例集详情失败: {Message}", result.ErrorMessages);
return result;
}
_logger.LogInformation("成功获取用例集详情,用例集ID: {TestCaseSetId}", id);
return result;
}
/// <summary>
/// 创建用例集
/// </summary>
[HttpPost]
public async Task<OperationResult<CreateTestCaseSetResponse>> Create([FromBody] CreateTestCaseSetCommand command)
{
_logger.LogInformation("开始创建用例集,用例集编码: {Code}, 用例集名称: {Name}, 版本: {Version}", command.Code, command.Name, command.Version);
var result = await mediator.Send(command);
if (!result.IsSuccess)
{
_logger.LogWarning("创建用例集失败: {Message}", result.ErrorMessages);
return result;
}
_logger.LogInformation("成功创建用例集,用例集ID: {TestCaseSetId}", result.Data?.TestCaseSetId);
return result;
}
/// <summary>
/// 更新用例集
/// </summary>
[HttpPut("{id}")]
public async Task<OperationResult<UpdateTestCaseSetResponse>> Update(string id, [FromBody] UpdateTestCaseSetCommand command)
{
_logger.LogInformation("开始更新用例集,用例集ID: {TestCaseSetId}", id);
if (id != command.TestCaseSetId)
{
_logger.LogWarning("用例集ID不匹配,路径ID: {PathId}, 命令ID: {CommandId}", id, command.TestCaseSetId);
return OperationResult<UpdateTestCaseSetResponse>.CreateFailure("用例集ID不匹配");
}
var result = await mediator.Send(command);
if (!result.IsSuccess)
{
_logger.LogWarning("更新用例集失败: {Message}", result.ErrorMessages);
return result;
}
_logger.LogInformation("成功更新用例集,用例集ID: {TestCaseSetId}", id);
return result;
}
/// <summary>
/// 删除用例集
/// </summary>
[HttpDelete("{id}")]
public async Task<OperationResult<bool>> Delete(string id)
{
_logger.LogInformation("开始删除用例集,用例集ID: {TestCaseSetId}", id);
var result = await mediator.Send(new DeleteTestCaseSetCommand { TestCaseSetId = id });
if (!result.IsSuccess)
{
_logger.LogWarning("删除用例集失败: {Message}", result.ErrorMessages);
return result;
}
_logger.LogInformation("成功删除用例集,用例集ID: {TestCaseSetId}", id);
return result;
}
/// <summary>
/// 启用用例集
/// </summary>
[HttpPost("{id}/enable")]
public async Task<OperationResult<bool>> Enable(string id)
{
_logger.LogInformation("开始启用用例集,用例集ID: {TestCaseSetId}", id);
var result = await mediator.Send(new EnableTestCaseSetCommand { TestCaseSetId = id });
if (!result.IsSuccess)
{
_logger.LogWarning("启用用例集失败: {Message}", result.ErrorMessages);
return result;
}
_logger.LogInformation("成功启用用例集,用例集ID: {TestCaseSetId}", id);
return result;
}
/// <summary>
/// 禁用用例集
/// </summary>
[HttpPost("{id}/disable")]
public async Task<OperationResult<bool>> Disable(string id)
{
_logger.LogInformation("开始禁用用例集,用例集ID: {TestCaseSetId}", id);
var result = await mediator.Send(new DisableTestCaseSetCommand { TestCaseSetId = id });
if (!result.IsSuccess)
{
_logger.LogWarning("禁用用例集失败: {Message}", result.ErrorMessages);
return result;
}
_logger.LogInformation("成功禁用用例集,用例集ID: {TestCaseSetId}", id);
return result;
}
}
Loading…
Cancel
Save