diff --git a/src/X1.Application/Features/TestCaseSets/Commands/CreateTestCaseSet/CreateTestCaseSetCommand.cs b/src/X1.Application/Features/TestCaseSets/Commands/CreateTestCaseSet/CreateTestCaseSetCommand.cs
new file mode 100644
index 0000000..c177f08
--- /dev/null
+++ b/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;
+
+///
+/// 创建用例集命令
+///
+public class CreateTestCaseSetCommand : IRequest>
+{
+ ///
+ /// 用例集编码
+ ///
+ [Required(ErrorMessage = "用例集编码不能为空")]
+ [MaxLength(50, ErrorMessage = "用例集编码长度不能超过50个字符")]
+ public string Code { get; set; } = null!;
+
+ ///
+ /// 用例集名称
+ ///
+ [Required(ErrorMessage = "用例集名称不能为空")]
+ [MaxLength(100, ErrorMessage = "用例集名称长度不能超过100个字符")]
+ public string Name { get; set; } = null!;
+
+ ///
+ /// 用例集说明
+ ///
+ [MaxLength(1000, ErrorMessage = "用例集说明长度不能超过1000个字符")]
+ public string? Description { get; set; }
+
+ ///
+ /// 用例集版本
+ ///
+ [Required(ErrorMessage = "用例集版本不能为空")]
+ [MaxLength(20, ErrorMessage = "用例集版本长度不能超过20个字符")]
+ public string Version { get; set; } = null!;
+
+ ///
+ /// 版本更新信息
+ ///
+ [MaxLength(500, ErrorMessage = "版本更新信息长度不能超过500个字符")]
+ public string? VersionUpdateInfo { get; set; }
+
+ ///
+ /// 是否禁用
+ ///
+ public bool IsDisabled { get; set; } = false;
+
+ ///
+ /// 备注
+ ///
+ [MaxLength(1000, ErrorMessage = "备注长度不能超过1000个字符")]
+ public string? Remarks { get; set; }
+}
\ No newline at end of file
diff --git a/src/X1.Application/Features/TestCaseSets/Commands/CreateTestCaseSet/CreateTestCaseSetCommandHandler.cs b/src/X1.Application/Features/TestCaseSets/Commands/CreateTestCaseSet/CreateTestCaseSetCommandHandler.cs
new file mode 100644
index 0000000..e9f3f02
--- /dev/null
+++ b/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;
+
+///
+/// 创建用例集命令处理器
+///
+public class CreateTestCaseSetCommandHandler : IRequestHandler>
+{
+ private readonly ITestCaseSetRepository _testCaseSetRepository;
+ private readonly ILogger _logger;
+ private readonly IUnitOfWork _unitOfWork;
+ private readonly ICurrentUserService _currentUserService;
+
+ ///
+ /// 初始化命令处理器
+ ///
+ public CreateTestCaseSetCommandHandler(
+ ITestCaseSetRepository testCaseSetRepository,
+ ILogger logger,
+ IUnitOfWork unitOfWork,
+ ICurrentUserService currentUserService)
+ {
+ _testCaseSetRepository = testCaseSetRepository;
+ _logger = logger;
+ _unitOfWork = unitOfWork;
+ _currentUserService = currentUserService;
+ }
+
+ ///
+ /// 处理创建用例集命令
+ ///
+ public async Task> 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.CreateFailure($"用例集编码 {request.Code} 已存在");
+ }
+
+ // 检查用例集版本是否已存在
+ if (await _testCaseSetRepository.VersionExistsAsync(request.Version, cancellationToken))
+ {
+ _logger.LogWarning("用例集版本已存在: {Version}", request.Version);
+ return OperationResult.CreateFailure($"用例集版本 {request.Version} 已存在");
+ }
+
+ // 获取当前用户ID
+ var currentUserId = _currentUserService.GetCurrentUserId();
+ if (string.IsNullOrEmpty(currentUserId))
+ {
+ _logger.LogError("无法获取当前用户ID,用户可能未认证");
+ return OperationResult.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.CreateSuccess(response);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "创建用例集时发生错误,用例集编码: {Code}, 用例集名称: {Name}, 版本: {Version}",
+ request.Code, request.Name, request.Version);
+ return OperationResult.CreateFailure($"创建用例集时发生错误: {ex.Message}");
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/X1.Application/Features/TestCaseSets/Commands/CreateTestCaseSet/CreateTestCaseSetResponse.cs b/src/X1.Application/Features/TestCaseSets/Commands/CreateTestCaseSet/CreateTestCaseSetResponse.cs
new file mode 100644
index 0000000..f665b0b
--- /dev/null
+++ b/src/X1.Application/Features/TestCaseSets/Commands/CreateTestCaseSet/CreateTestCaseSetResponse.cs
@@ -0,0 +1,57 @@
+namespace CellularManagement.Application.Features.TestCaseSets.Commands.CreateTestCaseSet;
+
+///
+/// 创建用例集响应
+///
+public class CreateTestCaseSetResponse
+{
+ ///
+ /// 用例集ID
+ ///
+ public string TestCaseSetId { get; set; } = null!;
+
+ ///
+ /// 用例集编码
+ ///
+ public string Code { get; set; } = null!;
+
+ ///
+ /// 用例集名称
+ ///
+ public string Name { get; set; } = null!;
+
+ ///
+ /// 用例集说明
+ ///
+ public string? Description { get; set; }
+
+ ///
+ /// 用例集版本
+ ///
+ public string Version { get; set; } = null!;
+
+ ///
+ /// 版本更新信息
+ ///
+ public string? VersionUpdateInfo { get; set; }
+
+ ///
+ /// 是否禁用
+ ///
+ public bool IsDisabled { get; set; }
+
+ ///
+ /// 备注
+ ///
+ public string? Remarks { get; set; }
+
+ ///
+ /// 创建时间
+ ///
+ public DateTime CreatedAt { get; set; }
+
+ ///
+ /// 创建人
+ ///
+ public string CreatedBy { get; set; } = null!;
+}
\ No newline at end of file
diff --git a/src/X1.Application/Features/TestCaseSets/Commands/DeleteTestCaseSet/DeleteTestCaseSetCommand.cs b/src/X1.Application/Features/TestCaseSets/Commands/DeleteTestCaseSet/DeleteTestCaseSetCommand.cs
new file mode 100644
index 0000000..0e823fc
--- /dev/null
+++ b/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;
+
+///
+/// 删除用例集命令
+///
+public class DeleteTestCaseSetCommand : IRequest>
+{
+ ///
+ /// 用例集ID
+ ///
+ [Required(ErrorMessage = "用例集ID不能为空")]
+ [MaxLength(50, ErrorMessage = "用例集ID长度不能超过50个字符")]
+ public string TestCaseSetId { get; set; } = null!;
+}
\ No newline at end of file
diff --git a/src/X1.Application/Features/TestCaseSets/Commands/DeleteTestCaseSet/DeleteTestCaseSetCommandHandler.cs b/src/X1.Application/Features/TestCaseSets/Commands/DeleteTestCaseSet/DeleteTestCaseSetCommandHandler.cs
new file mode 100644
index 0000000..26d5dd6
--- /dev/null
+++ b/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;
+
+///
+/// 删除用例集命令处理器
+///
+public class DeleteTestCaseSetCommandHandler : IRequestHandler>
+{
+ private readonly ITestCaseSetRepository _testCaseSetRepository;
+ private readonly ILogger _logger;
+ private readonly IUnitOfWork _unitOfWork;
+ private readonly ICurrentUserService _currentUserService;
+
+ ///
+ /// 初始化命令处理器
+ ///
+ public DeleteTestCaseSetCommandHandler(
+ ITestCaseSetRepository testCaseSetRepository,
+ ILogger logger,
+ IUnitOfWork unitOfWork,
+ ICurrentUserService currentUserService)
+ {
+ _testCaseSetRepository = testCaseSetRepository;
+ _logger = logger;
+ _unitOfWork = unitOfWork;
+ _currentUserService = currentUserService;
+ }
+
+ ///
+ /// 处理删除用例集命令
+ ///
+ public async Task> 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.CreateFailure($"用例集ID {request.TestCaseSetId} 不存在");
+ }
+
+ // 检查用例集是否已被软删除
+ if (existingTestCaseSet.IsDeleted)
+ {
+ _logger.LogWarning("用例集已被删除: {TestCaseSetId}", request.TestCaseSetId);
+ return OperationResult.CreateFailure($"用例集ID {request.TestCaseSetId} 已被删除");
+ }
+
+ // 获取当前用户ID
+ var currentUserId = _currentUserService.GetCurrentUserId();
+ if (string.IsNullOrEmpty(currentUserId))
+ {
+ _logger.LogError("无法获取当前用户ID,用户可能未认证");
+ return OperationResult.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.CreateSuccess(true);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "删除用例集时发生错误,用例集ID: {TestCaseSetId}", request.TestCaseSetId);
+ return OperationResult.CreateFailure($"删除用例集时发生错误: {ex.Message}");
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/X1.Application/Features/TestCaseSets/Commands/DisableTestCaseSet/DisableTestCaseSetCommand.cs b/src/X1.Application/Features/TestCaseSets/Commands/DisableTestCaseSet/DisableTestCaseSetCommand.cs
new file mode 100644
index 0000000..a0323fc
--- /dev/null
+++ b/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;
+
+///
+/// 禁用用例集命令
+///
+public class DisableTestCaseSetCommand : IRequest>
+{
+ ///
+ /// 用例集ID
+ ///
+ [Required(ErrorMessage = "用例集ID不能为空")]
+ [MaxLength(50, ErrorMessage = "用例集ID长度不能超过50个字符")]
+ public string TestCaseSetId { get; set; } = null!;
+}
\ No newline at end of file
diff --git a/src/X1.Application/Features/TestCaseSets/Commands/DisableTestCaseSet/DisableTestCaseSetCommandHandler.cs b/src/X1.Application/Features/TestCaseSets/Commands/DisableTestCaseSet/DisableTestCaseSetCommandHandler.cs
new file mode 100644
index 0000000..07d1075
--- /dev/null
+++ b/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;
+
+///
+/// 禁用用例集命令处理器
+///
+public class DisableTestCaseSetCommandHandler : IRequestHandler>
+{
+ private readonly ITestCaseSetRepository _testCaseSetRepository;
+ private readonly ILogger _logger;
+ private readonly IUnitOfWork _unitOfWork;
+ private readonly ICurrentUserService _currentUserService;
+
+ ///
+ /// 初始化命令处理器
+ ///
+ public DisableTestCaseSetCommandHandler(
+ ITestCaseSetRepository testCaseSetRepository,
+ ILogger logger,
+ IUnitOfWork unitOfWork,
+ ICurrentUserService currentUserService)
+ {
+ _testCaseSetRepository = testCaseSetRepository;
+ _logger = logger;
+ _unitOfWork = unitOfWork;
+ _currentUserService = currentUserService;
+ }
+
+ ///
+ /// 处理禁用用例集命令
+ ///
+ public async Task> 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.CreateFailure($"用例集ID {request.TestCaseSetId} 不存在");
+ }
+
+ // 检查用例集是否已被软删除
+ if (existingTestCaseSet.IsDeleted)
+ {
+ _logger.LogWarning("用例集已被删除: {TestCaseSetId}", request.TestCaseSetId);
+ return OperationResult.CreateFailure($"用例集ID {request.TestCaseSetId} 已被删除");
+ }
+
+ // 检查用例集是否已经禁用
+ if (existingTestCaseSet.IsDisabled)
+ {
+ _logger.LogWarning("用例集已经禁用: {TestCaseSetId}", request.TestCaseSetId);
+ return OperationResult.CreateFailure($"用例集ID {request.TestCaseSetId} 已经禁用");
+ }
+
+ // 获取当前用户ID
+ var currentUserId = _currentUserService.GetCurrentUserId();
+ if (string.IsNullOrEmpty(currentUserId))
+ {
+ _logger.LogError("无法获取当前用户ID,用户可能未认证");
+ return OperationResult.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.CreateSuccess(true);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "禁用用例集时发生错误,用例集ID: {TestCaseSetId}", request.TestCaseSetId);
+ return OperationResult.CreateFailure($"禁用用例集时发生错误: {ex.Message}");
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/X1.Application/Features/TestCaseSets/Commands/EnableTestCaseSet/EnableTestCaseSetCommand.cs b/src/X1.Application/Features/TestCaseSets/Commands/EnableTestCaseSet/EnableTestCaseSetCommand.cs
new file mode 100644
index 0000000..8f08f31
--- /dev/null
+++ b/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;
+
+///
+/// 启用用例集命令
+///
+public class EnableTestCaseSetCommand : IRequest>
+{
+ ///
+ /// 用例集ID
+ ///
+ [Required(ErrorMessage = "用例集ID不能为空")]
+ [MaxLength(50, ErrorMessage = "用例集ID长度不能超过50个字符")]
+ public string TestCaseSetId { get; set; } = null!;
+}
\ No newline at end of file
diff --git a/src/X1.Application/Features/TestCaseSets/Commands/EnableTestCaseSet/EnableTestCaseSetCommandHandler.cs b/src/X1.Application/Features/TestCaseSets/Commands/EnableTestCaseSet/EnableTestCaseSetCommandHandler.cs
new file mode 100644
index 0000000..be8bf6c
--- /dev/null
+++ b/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;
+
+///
+/// 启用用例集命令处理器
+///
+public class EnableTestCaseSetCommandHandler : IRequestHandler>
+{
+ private readonly ITestCaseSetRepository _testCaseSetRepository;
+ private readonly ILogger _logger;
+ private readonly IUnitOfWork _unitOfWork;
+ private readonly ICurrentUserService _currentUserService;
+
+ ///
+ /// 初始化命令处理器
+ ///
+ public EnableTestCaseSetCommandHandler(
+ ITestCaseSetRepository testCaseSetRepository,
+ ILogger logger,
+ IUnitOfWork unitOfWork,
+ ICurrentUserService currentUserService)
+ {
+ _testCaseSetRepository = testCaseSetRepository;
+ _logger = logger;
+ _unitOfWork = unitOfWork;
+ _currentUserService = currentUserService;
+ }
+
+ ///
+ /// 处理启用用例集命令
+ ///
+ public async Task> 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.CreateFailure($"用例集ID {request.TestCaseSetId} 不存在");
+ }
+
+ // 检查用例集是否已被软删除
+ if (existingTestCaseSet.IsDeleted)
+ {
+ _logger.LogWarning("用例集已被删除: {TestCaseSetId}", request.TestCaseSetId);
+ return OperationResult.CreateFailure($"用例集ID {request.TestCaseSetId} 已被删除");
+ }
+
+ // 检查用例集是否已经启用
+ if (!existingTestCaseSet.IsDisabled)
+ {
+ _logger.LogWarning("用例集已经启用: {TestCaseSetId}", request.TestCaseSetId);
+ return OperationResult.CreateFailure($"用例集ID {request.TestCaseSetId} 已经启用");
+ }
+
+ // 获取当前用户ID
+ var currentUserId = _currentUserService.GetCurrentUserId();
+ if (string.IsNullOrEmpty(currentUserId))
+ {
+ _logger.LogError("无法获取当前用户ID,用户可能未认证");
+ return OperationResult.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.CreateSuccess(true);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "启用用例集时发生错误,用例集ID: {TestCaseSetId}", request.TestCaseSetId);
+ return OperationResult.CreateFailure($"启用用例集时发生错误: {ex.Message}");
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/X1.Application/Features/TestCaseSets/Commands/UpdateTestCaseSet/UpdateTestCaseSetCommand.cs b/src/X1.Application/Features/TestCaseSets/Commands/UpdateTestCaseSet/UpdateTestCaseSetCommand.cs
new file mode 100644
index 0000000..6fdff34
--- /dev/null
+++ b/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;
+
+///
+/// 更新用例集命令
+///
+public class UpdateTestCaseSetCommand : IRequest>
+{
+ ///
+ /// 用例集ID
+ ///
+ [Required(ErrorMessage = "用例集ID不能为空")]
+ [MaxLength(50, ErrorMessage = "用例集ID长度不能超过50个字符")]
+ public string TestCaseSetId { get; set; } = null!;
+
+ ///
+ /// 用例集编码
+ ///
+ [Required(ErrorMessage = "用例集编码不能为空")]
+ [MaxLength(50, ErrorMessage = "用例集编码长度不能超过50个字符")]
+ public string Code { get; set; } = null!;
+
+ ///
+ /// 用例集名称
+ ///
+ [Required(ErrorMessage = "用例集名称不能为空")]
+ [MaxLength(100, ErrorMessage = "用例集名称长度不能超过100个字符")]
+ public string Name { get; set; } = null!;
+
+ ///
+ /// 用例集说明
+ ///
+ [MaxLength(1000, ErrorMessage = "用例集说明长度不能超过1000个字符")]
+ public string? Description { get; set; }
+
+ ///
+ /// 用例集版本
+ ///
+ [Required(ErrorMessage = "用例集版本不能为空")]
+ [MaxLength(20, ErrorMessage = "用例集版本长度不能超过20个字符")]
+ public string Version { get; set; } = null!;
+
+ ///
+ /// 版本更新信息
+ ///
+ [MaxLength(500, ErrorMessage = "版本更新信息长度不能超过500个字符")]
+ public string? VersionUpdateInfo { get; set; }
+
+ ///
+ /// 是否禁用
+ ///
+ public bool IsDisabled { get; set; } = false;
+
+ ///
+ /// 备注
+ ///
+ [MaxLength(1000, ErrorMessage = "备注长度不能超过1000个字符")]
+ public string? Remarks { get; set; }
+}
\ No newline at end of file
diff --git a/src/X1.Application/Features/TestCaseSets/Commands/UpdateTestCaseSet/UpdateTestCaseSetCommandHandler.cs b/src/X1.Application/Features/TestCaseSets/Commands/UpdateTestCaseSet/UpdateTestCaseSetCommandHandler.cs
new file mode 100644
index 0000000..5475945
--- /dev/null
+++ b/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;
+
+///
+/// 更新用例集命令处理器
+///
+public class UpdateTestCaseSetCommandHandler : IRequestHandler>
+{
+ private readonly ITestCaseSetRepository _testCaseSetRepository;
+ private readonly ILogger _logger;
+ private readonly IUnitOfWork _unitOfWork;
+ private readonly ICurrentUserService _currentUserService;
+
+ ///
+ /// 初始化命令处理器
+ ///
+ public UpdateTestCaseSetCommandHandler(
+ ITestCaseSetRepository testCaseSetRepository,
+ ILogger logger,
+ IUnitOfWork unitOfWork,
+ ICurrentUserService currentUserService)
+ {
+ _testCaseSetRepository = testCaseSetRepository;
+ _logger = logger;
+ _unitOfWork = unitOfWork;
+ _currentUserService = currentUserService;
+ }
+
+ ///
+ /// 处理更新用例集命令
+ ///
+ public async Task> 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.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.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.CreateFailure($"用例集版本 {request.Version} 已被其他用例集使用");
+ }
+
+ // 获取当前用户ID
+ var currentUserId = _currentUserService.GetCurrentUserId();
+ if (string.IsNullOrEmpty(currentUserId))
+ {
+ _logger.LogError("无法获取当前用户ID,用户可能未认证");
+ return OperationResult.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.CreateSuccess(response);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "更新用例集时发生错误,用例集ID: {TestCaseSetId}, 用例集编码: {Code}, 用例集名称: {Name}, 版本: {Version}",
+ request.TestCaseSetId, request.Code, request.Name, request.Version);
+ return OperationResult.CreateFailure($"更新用例集时发生错误: {ex.Message}");
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/X1.Application/Features/TestCaseSets/Commands/UpdateTestCaseSet/UpdateTestCaseSetResponse.cs b/src/X1.Application/Features/TestCaseSets/Commands/UpdateTestCaseSet/UpdateTestCaseSetResponse.cs
new file mode 100644
index 0000000..a638e66
--- /dev/null
+++ b/src/X1.Application/Features/TestCaseSets/Commands/UpdateTestCaseSet/UpdateTestCaseSetResponse.cs
@@ -0,0 +1,57 @@
+namespace CellularManagement.Application.Features.TestCaseSets.Commands.UpdateTestCaseSet;
+
+///
+/// 更新用例集响应
+///
+public class UpdateTestCaseSetResponse
+{
+ ///
+ /// 用例集ID
+ ///
+ public string TestCaseSetId { get; set; } = null!;
+
+ ///
+ /// 用例集编码
+ ///
+ public string Code { get; set; } = null!;
+
+ ///
+ /// 用例集名称
+ ///
+ public string Name { get; set; } = null!;
+
+ ///
+ /// 用例集说明
+ ///
+ public string? Description { get; set; }
+
+ ///
+ /// 用例集版本
+ ///
+ public string Version { get; set; } = null!;
+
+ ///
+ /// 版本更新信息
+ ///
+ public string? VersionUpdateInfo { get; set; }
+
+ ///
+ /// 是否禁用
+ ///
+ public bool IsDisabled { get; set; }
+
+ ///
+ /// 备注
+ ///
+ public string? Remarks { get; set; }
+
+ ///
+ /// 更新时间
+ ///
+ public DateTime? UpdatedAt { get; set; }
+
+ ///
+ /// 修改人
+ ///
+ public string? UpdatedBy { get; set; }
+}
\ No newline at end of file
diff --git a/src/X1.Application/Features/TestCaseSets/Queries/GetTestCaseSetById/GetTestCaseSetByIdQuery.cs b/src/X1.Application/Features/TestCaseSets/Queries/GetTestCaseSetById/GetTestCaseSetByIdQuery.cs
new file mode 100644
index 0000000..29512c3
--- /dev/null
+++ b/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;
+
+///
+/// 根据ID获取用例集查询
+///
+public class GetTestCaseSetByIdQuery : IRequest>
+{
+ ///
+ /// 用例集ID
+ ///
+ [Required(ErrorMessage = "用例集ID不能为空")]
+ [MaxLength(50, ErrorMessage = "用例集ID长度不能超过50个字符")]
+ public string Id { get; set; } = null!;
+}
\ No newline at end of file
diff --git a/src/X1.Application/Features/TestCaseSets/Queries/GetTestCaseSetById/GetTestCaseSetByIdQueryHandler.cs b/src/X1.Application/Features/TestCaseSets/Queries/GetTestCaseSetById/GetTestCaseSetByIdQueryHandler.cs
new file mode 100644
index 0000000..3fc3330
--- /dev/null
+++ b/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;
+
+///
+/// 根据ID获取用例集查询处理器
+///
+public class GetTestCaseSetByIdQueryHandler : IRequestHandler>
+{
+ private readonly ITestCaseSetRepository _testCaseSetRepository;
+ private readonly ILogger _logger;
+
+ ///
+ /// 初始化查询处理器
+ ///
+ public GetTestCaseSetByIdQueryHandler(
+ ITestCaseSetRepository testCaseSetRepository,
+ ILogger logger)
+ {
+ _testCaseSetRepository = testCaseSetRepository;
+ _logger = logger;
+ }
+
+ ///
+ /// 处理根据ID获取用例集查询
+ ///
+ public async Task> Handle(GetTestCaseSetByIdQuery request, CancellationToken cancellationToken)
+ {
+ try
+ {
+ // 验证请求参数
+ var validationContext = new ValidationContext(request);
+ var validationResults = new List();
+ if (!Validator.TryValidateObject(request, validationContext, validationResults, true))
+ {
+ var errorMessages = validationResults.Select(r => r.ErrorMessage).ToList();
+ _logger.LogWarning("请求参数无效: {Errors}", string.Join(", ", errorMessages));
+ return OperationResult.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.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.CreateSuccess(response);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "根据ID获取用例集时发生错误,ID: {Id}", request.Id);
+ return OperationResult.CreateFailure($"根据ID获取用例集时发生错误: {ex.Message}");
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/X1.Application/Features/TestCaseSets/Queries/GetTestCaseSetById/GetTestCaseSetByIdResponse.cs b/src/X1.Application/Features/TestCaseSets/Queries/GetTestCaseSetById/GetTestCaseSetByIdResponse.cs
new file mode 100644
index 0000000..f2386d8
--- /dev/null
+++ b/src/X1.Application/Features/TestCaseSets/Queries/GetTestCaseSetById/GetTestCaseSetByIdResponse.cs
@@ -0,0 +1,67 @@
+namespace CellularManagement.Application.Features.TestCaseSets.Queries.GetTestCaseSetById;
+
+///
+/// 根据ID获取用例集响应
+///
+public class GetTestCaseSetByIdResponse
+{
+ ///
+ /// 用例集ID
+ ///
+ public string TestCaseSetId { get; set; } = null!;
+
+ ///
+ /// 用例集编码
+ ///
+ public string Code { get; set; } = null!;
+
+ ///
+ /// 用例集名称
+ ///
+ public string Name { get; set; } = null!;
+
+ ///
+ /// 用例集说明
+ ///
+ public string? Description { get; set; }
+
+ ///
+ /// 用例集版本
+ ///
+ public string Version { get; set; } = null!;
+
+ ///
+ /// 版本更新信息
+ ///
+ public string? VersionUpdateInfo { get; set; }
+
+ ///
+ /// 是否禁用
+ ///
+ public bool IsDisabled { get; set; }
+
+ ///
+ /// 备注
+ ///
+ public string? Remarks { get; set; }
+
+ ///
+ /// 创建时间
+ ///
+ public DateTime CreatedAt { get; set; }
+
+ ///
+ /// 更新时间
+ ///
+ public DateTime? UpdatedAt { get; set; }
+
+ ///
+ /// 创建人
+ ///
+ public string CreatedBy { get; set; } = null!;
+
+ ///
+ /// 修改人
+ ///
+ public string? UpdatedBy { get; set; }
+}
\ No newline at end of file
diff --git a/src/X1.Application/Features/TestCaseSets/Queries/GetTestCaseSets/GetTestCaseSetsQuery.cs b/src/X1.Application/Features/TestCaseSets/Queries/GetTestCaseSets/GetTestCaseSetsQuery.cs
new file mode 100644
index 0000000..8a3d627
--- /dev/null
+++ b/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;
+
+///
+/// 获取用例集列表查询
+///
+public class GetTestCaseSetsQuery : IRequest>
+{
+ ///
+ /// 页码
+ ///
+ [Range(1, int.MaxValue, ErrorMessage = "页码必须大于0")]
+ public int PageNumber { get; set; } = 1;
+
+ ///
+ /// 每页数量
+ ///
+ [Range(1, 100, ErrorMessage = "每页数量必须在1-100之间")]
+ public int PageSize { get; set; } = 10;
+
+ ///
+ /// 搜索关键词
+ ///
+ [MaxLength(100)]
+ public string? SearchTerm { get; set; }
+
+ ///
+ /// 是否只获取启用的用例集
+ ///
+ public bool? IsEnabled { get; set; }
+
+ ///
+ /// 版本过滤
+ ///
+ [MaxLength(20)]
+ public string? Version { get; set; }
+}
\ No newline at end of file
diff --git a/src/X1.Application/Features/TestCaseSets/Queries/GetTestCaseSets/GetTestCaseSetsQueryHandler.cs b/src/X1.Application/Features/TestCaseSets/Queries/GetTestCaseSets/GetTestCaseSetsQueryHandler.cs
new file mode 100644
index 0000000..405a676
--- /dev/null
+++ b/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;
+
+///
+/// 获取用例集列表查询处理器
+///
+public class GetTestCaseSetsQueryHandler : IRequestHandler>
+{
+ private readonly ITestCaseSetRepository _testCaseSetRepository;
+ private readonly ILogger _logger;
+
+ ///
+ /// 初始化查询处理器
+ ///
+ public GetTestCaseSetsQueryHandler(
+ ITestCaseSetRepository testCaseSetRepository,
+ ILogger logger)
+ {
+ _testCaseSetRepository = testCaseSetRepository;
+ _logger = logger;
+ }
+
+ ///
+ /// 处理获取用例集列表查询
+ ///
+ public async Task> Handle(GetTestCaseSetsQuery request, CancellationToken cancellationToken)
+ {
+ try
+ {
+ // 验证请求参数
+ var validationContext = new ValidationContext(request);
+ var validationResults = new List();
+ if (!Validator.TryValidateObject(request, validationContext, validationResults, true))
+ {
+ var errorMessages = validationResults.Select(r => r.ErrorMessage).ToList();
+ _logger.LogWarning("请求参数无效: {Errors}", string.Join(", ", errorMessages));
+ return OperationResult.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.CreateSuccess(response);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "获取用例集列表时发生错误");
+ return OperationResult.CreateFailure($"获取用例集列表时发生错误: {ex.Message}");
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/X1.Application/Features/TestCaseSets/Queries/GetTestCaseSets/GetTestCaseSetsResponse.cs b/src/X1.Application/Features/TestCaseSets/Queries/GetTestCaseSets/GetTestCaseSetsResponse.cs
new file mode 100644
index 0000000..5c673ee
--- /dev/null
+++ b/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;
+
+///
+/// 获取用例集列表响应
+///
+public class GetTestCaseSetsResponse
+{
+ ///
+ /// 总数量
+ ///
+ public int TotalCount { get; set; }
+
+ ///
+ /// 当前页码
+ ///
+ public int PageNumber { get; set; }
+
+ ///
+ /// 每页数量
+ ///
+ public int PageSize { get; set; }
+
+ ///
+ /// 总页数
+ ///
+ public int TotalPages { get; set; }
+
+ ///
+ /// 是否有上一页
+ ///
+ public bool HasPreviousPage { get; set; }
+
+ ///
+ /// 是否有下一页
+ ///
+ public bool HasNextPage { get; set; }
+
+ ///
+ /// 用例集列表
+ ///
+ public List Items { get; set; } = new();
+}
\ No newline at end of file
diff --git a/src/X1.Domain/Entities/Device/TestCaseSet.cs b/src/X1.Domain/Entities/Device/TestCaseSet.cs
new file mode 100644
index 0000000..17f33ac
--- /dev/null
+++ b/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;
+
+///
+/// 用例集实体
+///
+public class TestCaseSet : AuditableEntity
+{
+ private TestCaseSet() { }
+
+ ///
+ /// 用例集编码
+ ///
+ [Required]
+ [MaxLength(50)]
+ public string Code { get; private set; } = null!;
+
+ ///
+ /// 用例集名称
+ ///
+ [Required]
+ [MaxLength(100)]
+ public string Name { get; private set; } = null!;
+
+ ///
+ /// 用例集说明
+ ///
+ [MaxLength(1000)]
+ public string? Description { get; private set; }
+
+ ///
+ /// 用例集版本
+ ///
+ [Required]
+ [MaxLength(20)]
+ public string Version { get; private set; } = null!;
+
+ ///
+ /// 版本更新信息
+ ///
+ [MaxLength(500)]
+ public string? VersionUpdateInfo { get; private set; }
+
+ ///
+ /// 是否禁用
+ ///
+ public bool IsDisabled { get; private set; } = false;
+
+ ///
+ /// 备注
+ ///
+ [MaxLength(1000)]
+ public string? Remarks { get; private set; }
+
+ ///
+ /// 创建用例集
+ ///
+ 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;
+ }
+
+ ///
+ /// 更新用例集
+ ///
+ 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;
+ }
+
+ ///
+ /// 启用用例集
+ ///
+ public void Enable()
+ {
+ IsDisabled = false;
+ UpdatedAt = DateTime.UtcNow;
+ }
+
+ ///
+ /// 禁用用例集
+ ///
+ public void Disable()
+ {
+ IsDisabled = true;
+ UpdatedAt = DateTime.UtcNow;
+ }
+
+ ///
+ /// 软删除用例集
+ ///
+ public void SoftDelete()
+ {
+ IsDeleted = true;
+ UpdatedAt = DateTime.UtcNow;
+ }
+
+ ///
+ /// 恢复用例集
+ ///
+ public void Restore()
+ {
+ IsDeleted = false;
+ UpdatedAt = DateTime.UtcNow;
+ }
+}
\ No newline at end of file
diff --git a/src/X1.Domain/Repositories/Device/ITestCaseSetRepository.cs b/src/X1.Domain/Repositories/Device/ITestCaseSetRepository.cs
new file mode 100644
index 0000000..de6e811
--- /dev/null
+++ b/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;
+
+///
+/// 用例集仓储接口
+///
+public interface ITestCaseSetRepository : IBaseRepository
+{
+ ///
+ /// 添加用例集
+ ///
+ Task AddTestCaseSetAsync(TestCaseSet testCaseSet, CancellationToken cancellationToken = default);
+
+ ///
+ /// 更新用例集
+ ///
+ void UpdateTestCaseSet(TestCaseSet testCaseSet);
+
+ ///
+ /// 删除用例集
+ ///
+ Task DeleteTestCaseSetAsync(string id, CancellationToken cancellationToken = default);
+
+ ///
+ /// 获取所有用例集
+ ///
+ Task> GetAllTestCaseSetsAsync(CancellationToken cancellationToken = default);
+
+ ///
+ /// 根据ID获取用例集
+ ///
+ Task GetTestCaseSetByIdAsync(string id, CancellationToken cancellationToken = default);
+
+ ///
+ /// 根据编码获取用例集
+ ///
+ Task GetTestCaseSetByCodeAsync(string code, CancellationToken cancellationToken = default);
+
+ ///
+ /// 根据版本获取用例集
+ ///
+ Task GetTestCaseSetByVersionAsync(string version, CancellationToken cancellationToken = default);
+
+ ///
+ /// 搜索用例集
+ ///
+ Task> SearchTestCaseSetsAsync(
+ string? keyword,
+ CancellationToken cancellationToken = default);
+
+ ///
+ /// 检查用例集是否存在
+ ///
+ Task ExistsAsync(string id, CancellationToken cancellationToken = default);
+
+ ///
+ /// 检查编码是否存在
+ ///
+ Task CodeExistsAsync(string code, CancellationToken cancellationToken = default);
+
+ ///
+ /// 检查版本是否存在
+ ///
+ Task VersionExistsAsync(string version, CancellationToken cancellationToken = default);
+
+ ///
+ /// 获取启用的用例集
+ ///
+ Task> GetEnabledTestCaseSetsAsync(CancellationToken cancellationToken = default);
+}
\ No newline at end of file
diff --git a/src/X1.Infrastructure/Configurations/Device/TestCaseSetConfiguration.cs b/src/X1.Infrastructure/Configurations/Device/TestCaseSetConfiguration.cs
new file mode 100644
index 0000000..ab88e74
--- /dev/null
+++ b/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
+{
+ public void Configure(EntityTypeBuilder 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("修改人");
+ }
+}
\ No newline at end of file
diff --git a/src/X1.Infrastructure/Context/AppDbContext.cs b/src/X1.Infrastructure/Context/AppDbContext.cs
index 0437a35..5481590 100644
--- a/src/X1.Infrastructure/Context/AppDbContext.cs
+++ b/src/X1.Infrastructure/Context/AppDbContext.cs
@@ -56,6 +56,11 @@ public class AppDbContext : IdentityDbContext
///
public DbSet Scenarios { get; set; } = null!;
+ ///
+ /// 用例集集合
+ ///
+ public DbSet TestCaseSets { get; set; } = null!;
+
///
/// 初始化数据库上下文
///
diff --git a/src/X1.Infrastructure/DependencyInjection.cs b/src/X1.Infrastructure/DependencyInjection.cs
index 9cbfe4b..0dccb9e 100644
--- a/src/X1.Infrastructure/DependencyInjection.cs
+++ b/src/X1.Infrastructure/DependencyInjection.cs
@@ -176,6 +176,7 @@ public static class DependencyInjection
services.AddScoped();
services.AddScoped();
services.AddScoped();
+ services.AddScoped();
return services;
}
diff --git a/src/X1.Infrastructure/Repositories/Device/TestCaseSetRepository.cs b/src/X1.Infrastructure/Repositories/Device/TestCaseSetRepository.cs
new file mode 100644
index 0000000..e7335c3
--- /dev/null
+++ b/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;
+
+///
+/// 用例集仓储实现类
+///
+public class TestCaseSetRepository : BaseRepository, ITestCaseSetRepository
+{
+ private readonly ILogger _logger;
+
+ ///
+ /// 初始化仓储
+ ///
+ public TestCaseSetRepository(
+ ICommandRepository commandRepository,
+ IQueryRepository queryRepository,
+ ILogger logger)
+ : base(commandRepository, queryRepository, logger)
+ {
+ _logger = logger;
+ }
+
+ ///
+ /// 添加用例集
+ ///
+ public async Task AddTestCaseSetAsync(TestCaseSet testCaseSet, CancellationToken cancellationToken = default)
+ {
+ var result = await CommandRepository.AddAsync(testCaseSet, cancellationToken);
+ return result;
+ }
+
+ ///
+ /// 更新用例集
+ ///
+ public void UpdateTestCaseSet(TestCaseSet testCaseSet)
+ {
+ CommandRepository.Update(testCaseSet);
+ }
+
+ ///
+ /// 删除用例集
+ ///
+ public async Task DeleteTestCaseSetAsync(string id, CancellationToken cancellationToken = default)
+ {
+ await CommandRepository.DeleteByIdAsync(id, cancellationToken);
+ }
+
+ ///
+ /// 获取所有用例集
+ ///
+ public async Task> GetAllTestCaseSetsAsync(CancellationToken cancellationToken = default)
+ {
+ var testCaseSets = await QueryRepository.GetAllAsync(cancellationToken: cancellationToken);
+ return testCaseSets.ToList();
+ }
+
+ ///
+ /// 根据ID获取用例集
+ ///
+ public async Task GetTestCaseSetByIdAsync(string id, CancellationToken cancellationToken = default)
+ {
+ return await QueryRepository.GetByIdAsync(id, cancellationToken: cancellationToken);
+ }
+
+ ///
+ /// 根据编码获取用例集
+ ///
+ public async Task GetTestCaseSetByCodeAsync(string code, CancellationToken cancellationToken = default)
+ {
+ return await QueryRepository.FirstOrDefaultAsync(tcs => tcs.Code == code, cancellationToken: cancellationToken);
+ }
+
+ ///
+ /// 根据版本获取用例集
+ ///
+ public async Task GetTestCaseSetByVersionAsync(string version, CancellationToken cancellationToken = default)
+ {
+ return await QueryRepository.FirstOrDefaultAsync(tcs => tcs.Version == version, cancellationToken: cancellationToken);
+ }
+
+ ///
+ /// 搜索用例集
+ ///
+ public async Task> 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();
+ }
+
+ ///
+ /// 检查用例集是否存在
+ ///
+ public async Task ExistsAsync(string id, CancellationToken cancellationToken = default)
+ {
+ return await QueryRepository.AnyAsync(tcs => tcs.Id == id, cancellationToken: cancellationToken);
+ }
+
+ ///
+ /// 检查编码是否存在
+ ///
+ public async Task CodeExistsAsync(string code, CancellationToken cancellationToken = default)
+ {
+ return await QueryRepository.AnyAsync(tcs => tcs.Code == code, cancellationToken: cancellationToken);
+ }
+
+ ///
+ /// 检查版本是否存在
+ ///
+ public async Task VersionExistsAsync(string version, CancellationToken cancellationToken = default)
+ {
+ return await QueryRepository.AnyAsync(tcs => tcs.Version == version, cancellationToken: cancellationToken);
+ }
+
+ ///
+ /// 获取启用的用例集
+ ///
+ public async Task> GetEnabledTestCaseSetsAsync(CancellationToken cancellationToken = default)
+ {
+ var testCaseSets = await QueryRepository.FindAsync(tcs => !tcs.IsDisabled, cancellationToken: cancellationToken);
+ return testCaseSets.ToList();
+ }
+}
\ No newline at end of file
diff --git a/src/X1.Presentation/Controllers/TestCaseSetsController.cs b/src/X1.Presentation/Controllers/TestCaseSetsController.cs
new file mode 100644
index 0000000..a0b873b
--- /dev/null
+++ b/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;
+
+///
+/// 用例集管理控制器
+///
+[Route("api/testcasesets")]
+[ApiController]
+[Authorize]
+public class TestCaseSetsController : ApiController
+{
+ private readonly ILogger _logger;
+
+ ///
+ /// 初始化用例集控制器
+ ///
+ public TestCaseSetsController(IMediator mediator, ILogger logger)
+ : base(mediator)
+ {
+ _logger = logger;
+ }
+
+ ///
+ /// 获取用例集列表
+ ///
+ [HttpGet]
+ public async Task> 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;
+ }
+
+ ///
+ /// 获取用例集详情
+ ///
+ [HttpGet("{id}")]
+ public async Task> 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;
+ }
+
+ ///
+ /// 创建用例集
+ ///
+ [HttpPost]
+ public async Task> 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;
+ }
+
+ ///
+ /// 更新用例集
+ ///
+ [HttpPut("{id}")]
+ public async Task> 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.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;
+ }
+
+ ///
+ /// 删除用例集
+ ///
+ [HttpDelete("{id}")]
+ public async Task> 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;
+ }
+
+ ///
+ /// 启用用例集
+ ///
+ [HttpPost("{id}/enable")]
+ public async Task> 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;
+ }
+
+ ///
+ /// 禁用用例集
+ ///
+ [HttpPost("{id}/disable")]
+ public async Task> 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;
+ }
+}
\ No newline at end of file