Browse Source

feat(scenario): 实现场景的增删改查及启用禁用等完整功能

feature/x1-owen-debug
test 4 weeks ago
parent
commit
491b9fa6da
  1. 43
      src/X1.Application/Features/Scenarios/Commands/CreateScenario/CreateScenarioCommand.cs
  2. 100
      src/X1.Application/Features/Scenarios/Commands/CreateScenario/CreateScenarioCommandHandler.cs
  3. 47
      src/X1.Application/Features/Scenarios/Commands/CreateScenario/CreateScenarioResponse.cs
  4. 18
      src/X1.Application/Features/Scenarios/Commands/DeleteScenario/DeleteScenarioCommand.cs
  5. 94
      src/X1.Application/Features/Scenarios/Commands/DeleteScenario/DeleteScenarioCommandHandler.cs
  6. 18
      src/X1.Application/Features/Scenarios/Commands/DisableScenario/DisableScenarioCommand.cs
  7. 101
      src/X1.Application/Features/Scenarios/Commands/DisableScenario/DisableScenarioCommandHandler.cs
  8. 18
      src/X1.Application/Features/Scenarios/Commands/EnableScenario/EnableScenarioCommand.cs
  9. 101
      src/X1.Application/Features/Scenarios/Commands/EnableScenario/EnableScenarioCommandHandler.cs
  10. 50
      src/X1.Application/Features/Scenarios/Commands/UpdateScenario/UpdateScenarioCommand.cs
  11. 109
      src/X1.Application/Features/Scenarios/Commands/UpdateScenario/UpdateScenarioCommandHandler.cs
  12. 47
      src/X1.Application/Features/Scenarios/Commands/UpdateScenario/UpdateScenarioResponse.cs
  13. 18
      src/X1.Application/Features/Scenarios/Queries/GetScenarioById/GetScenarioByIdQuery.cs
  14. 82
      src/X1.Application/Features/Scenarios/Queries/GetScenarioById/GetScenarioByIdQueryHandler.cs
  15. 57
      src/X1.Application/Features/Scenarios/Queries/GetScenarioById/GetScenarioByIdResponse.cs
  16. 40
      src/X1.Application/Features/Scenarios/Queries/GetScenarios/GetScenariosQuery.cs
  17. 109
      src/X1.Application/Features/Scenarios/Queries/GetScenarios/GetScenariosQueryHandler.cs
  18. 44
      src/X1.Application/Features/Scenarios/Queries/GetScenarios/GetScenariosResponse.cs
  19. 128
      src/X1.Domain/Entities/Device/Scenario.cs
  20. 68
      src/X1.Domain/Repositories/Device/IScenarioRepository.cs
  21. 30
      src/X1.Infrastructure/Configurations/Device/ScenarioConfiguration.cs
  22. 5
      src/X1.Infrastructure/Context/AppDbContext.cs
  23. 1
      src/X1.Infrastructure/DependencyInjection.cs
  24. 139
      src/X1.Infrastructure/Repositories/Device/ScenarioRepository.cs
  25. 175
      src/X1.Presentation/Controllers/ScenariosController.cs

43
src/X1.Application/Features/Scenarios/Commands/CreateScenario/CreateScenarioCommand.cs

@ -0,0 +1,43 @@
using CellularManagement.Domain.Common;
using MediatR;
using System.ComponentModel.DataAnnotations;
namespace CellularManagement.Application.Features.Scenarios.Commands.CreateScenario;
/// <summary>
/// 创建场景命令
/// </summary>
public class CreateScenarioCommand : IRequest<OperationResult<CreateScenarioResponse>>
{
/// <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>
/// 网络配置ID
/// </summary>
[Required(ErrorMessage = "网络配置ID不能为空")]
[MaxLength(50, ErrorMessage = "网络配置ID长度不能超过50个字符")]
public string NetworkConfigId { get; set; } = null!;
/// <summary>
/// 说明
/// </summary>
[MaxLength(1000, ErrorMessage = "说明长度不能超过1000个字符")]
public string? Description { get; set; }
/// <summary>
/// 是否禁用
/// </summary>
public bool IsDisabled { get; set; } = false;
}

100
src/X1.Application/Features/Scenarios/Commands/CreateScenario/CreateScenarioCommandHandler.cs

@ -0,0 +1,100 @@
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.Scenarios.Commands.CreateScenario;
/// <summary>
/// 创建场景命令处理器
/// </summary>
public class CreateScenarioCommandHandler : IRequestHandler<CreateScenarioCommand, OperationResult<CreateScenarioResponse>>
{
private readonly IScenarioRepository _scenarioRepository;
private readonly ILogger<CreateScenarioCommandHandler> _logger;
private readonly IUnitOfWork _unitOfWork;
private readonly ICurrentUserService _currentUserService;
/// <summary>
/// 初始化命令处理器
/// </summary>
public CreateScenarioCommandHandler(
IScenarioRepository scenarioRepository,
ILogger<CreateScenarioCommandHandler> logger,
IUnitOfWork unitOfWork,
ICurrentUserService currentUserService)
{
_scenarioRepository = scenarioRepository;
_logger = logger;
_unitOfWork = unitOfWork;
_currentUserService = currentUserService;
}
/// <summary>
/// 处理创建场景命令
/// </summary>
public async Task<OperationResult<CreateScenarioResponse>> Handle(CreateScenarioCommand request, CancellationToken cancellationToken)
{
try
{
_logger.LogInformation("开始创建场景,场景编码: {Code}, 场景名称: {Name}",
request.Code, request.Name);
// 检查场景编码是否已存在
if (await _scenarioRepository.CodeExistsAsync(request.Code, cancellationToken))
{
_logger.LogWarning("场景编码已存在: {Code}", request.Code);
return OperationResult<CreateScenarioResponse>.CreateFailure($"场景编码 {request.Code} 已存在");
}
// 获取当前用户ID
var currentUserId = _currentUserService.GetCurrentUserId();
if (string.IsNullOrEmpty(currentUserId))
{
_logger.LogError("无法获取当前用户ID,用户可能未认证");
return OperationResult<CreateScenarioResponse>.CreateFailure("用户未认证,无法创建场景");
}
// 创建场景实体
var scenario = Scenario.Create(
code: request.Code,
name: request.Name,
networkConfigId: request.NetworkConfigId,
createdBy: currentUserId,
description: request.Description,
isDisabled: request.IsDisabled);
// 保存场景
await _scenarioRepository.AddScenarioAsync(scenario, cancellationToken);
// 保存更改到数据库
await _unitOfWork.SaveChangesAsync(cancellationToken);
// 构建响应
var response = new CreateScenarioResponse
{
ScenarioId = scenario.Id,
Code = scenario.Code,
Name = scenario.Name,
NetworkConfigId = scenario.NetworkConfigId,
Description = scenario.Description,
IsDisabled = scenario.IsDisabled,
CreatedAt = scenario.CreatedAt,
CreatedBy = scenario.CreatedBy
};
_logger.LogInformation("场景创建成功,场景ID: {ScenarioId}, 场景编码: {Code}, 场景名称: {Name}",
scenario.Id, scenario.Code, scenario.Name);
return OperationResult<CreateScenarioResponse>.CreateSuccess(response);
}
catch (Exception ex)
{
_logger.LogError(ex, "创建场景时发生错误,场景编码: {Code}, 场景名称: {Name}",
request.Code, request.Name);
return OperationResult<CreateScenarioResponse>.CreateFailure($"创建场景时发生错误: {ex.Message}");
}
}
}

47
src/X1.Application/Features/Scenarios/Commands/CreateScenario/CreateScenarioResponse.cs

@ -0,0 +1,47 @@
namespace CellularManagement.Application.Features.Scenarios.Commands.CreateScenario;
/// <summary>
/// 创建场景响应
/// </summary>
public class CreateScenarioResponse
{
/// <summary>
/// 场景ID
/// </summary>
public string ScenarioId { get; set; } = null!;
/// <summary>
/// 场景编码
/// </summary>
public string Code { get; set; } = null!;
/// <summary>
/// 场景名称
/// </summary>
public string Name { get; set; } = null!;
/// <summary>
/// 网络配置ID
/// </summary>
public string NetworkConfigId { get; set; } = null!;
/// <summary>
/// 说明
/// </summary>
public string? Description { get; set; }
/// <summary>
/// 是否禁用
/// </summary>
public bool IsDisabled { get; set; }
/// <summary>
/// 创建时间
/// </summary>
public DateTime CreatedAt { get; set; }
/// <summary>
/// 创建人
/// </summary>
public string CreatedBy { get; set; } = null!;
}

18
src/X1.Application/Features/Scenarios/Commands/DeleteScenario/DeleteScenarioCommand.cs

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

94
src/X1.Application/Features/Scenarios/Commands/DeleteScenario/DeleteScenarioCommandHandler.cs

@ -0,0 +1,94 @@
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.Scenarios.Commands.DeleteScenario;
/// <summary>
/// 删除场景命令处理器
/// </summary>
public class DeleteScenarioCommandHandler : IRequestHandler<DeleteScenarioCommand, OperationResult<bool>>
{
private readonly IScenarioRepository _scenarioRepository;
private readonly ILogger<DeleteScenarioCommandHandler> _logger;
private readonly IUnitOfWork _unitOfWork;
private readonly ICurrentUserService _currentUserService;
/// <summary>
/// 初始化命令处理器
/// </summary>
public DeleteScenarioCommandHandler(
IScenarioRepository scenarioRepository,
ILogger<DeleteScenarioCommandHandler> logger,
IUnitOfWork unitOfWork,
ICurrentUserService currentUserService)
{
_scenarioRepository = scenarioRepository;
_logger = logger;
_unitOfWork = unitOfWork;
_currentUserService = currentUserService;
}
/// <summary>
/// 处理删除场景命令
/// </summary>
public async Task<OperationResult<bool>> Handle(DeleteScenarioCommand request, CancellationToken cancellationToken)
{
try
{
_logger.LogInformation("开始删除场景,场景ID: {ScenarioId}", request.ScenarioId);
// 检查场景是否存在
var existingScenario = await _scenarioRepository.GetScenarioByIdAsync(request.ScenarioId, cancellationToken);
if (existingScenario == null)
{
_logger.LogWarning("场景不存在: {ScenarioId}", request.ScenarioId);
return OperationResult<bool>.CreateFailure($"场景ID {request.ScenarioId} 不存在");
}
// 检查场景是否已被软删除
if (existingScenario.IsDeleted)
{
_logger.LogWarning("场景已被删除: {ScenarioId}", request.ScenarioId);
return OperationResult<bool>.CreateFailure($"场景ID {request.ScenarioId} 已被删除");
}
// 获取当前用户ID
var currentUserId = _currentUserService.GetCurrentUserId();
if (string.IsNullOrEmpty(currentUserId))
{
_logger.LogError("无法获取当前用户ID,用户可能未认证");
return OperationResult<bool>.CreateFailure("用户未认证,无法删除场景");
}
// 软删除场景
existingScenario.SoftDelete();
existingScenario.Update(
code: existingScenario.Code,
name: existingScenario.Name,
networkConfigId: existingScenario.NetworkConfigId,
updatedBy: currentUserId,
description: existingScenario.Description,
isDisabled: existingScenario.IsDisabled);
// 保存更改
_scenarioRepository.UpdateScenario(existingScenario);
// 保存更改到数据库
await _unitOfWork.SaveChangesAsync(cancellationToken);
_logger.LogInformation("场景删除成功,场景ID: {ScenarioId}, 场景编码: {Code}, 场景名称: {Name}",
existingScenario.Id, existingScenario.Code, existingScenario.Name);
return OperationResult<bool>.CreateSuccess(true);
}
catch (Exception ex)
{
_logger.LogError(ex, "删除场景时发生错误,场景ID: {ScenarioId}", request.ScenarioId);
return OperationResult<bool>.CreateFailure($"删除场景时发生错误: {ex.Message}");
}
}
}

18
src/X1.Application/Features/Scenarios/Commands/DisableScenario/DisableScenarioCommand.cs

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

101
src/X1.Application/Features/Scenarios/Commands/DisableScenario/DisableScenarioCommandHandler.cs

@ -0,0 +1,101 @@
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.Scenarios.Commands.DisableScenario;
/// <summary>
/// 禁用场景命令处理器
/// </summary>
public class DisableScenarioCommandHandler : IRequestHandler<DisableScenarioCommand, OperationResult<bool>>
{
private readonly IScenarioRepository _scenarioRepository;
private readonly ILogger<DisableScenarioCommandHandler> _logger;
private readonly IUnitOfWork _unitOfWork;
private readonly ICurrentUserService _currentUserService;
/// <summary>
/// 初始化命令处理器
/// </summary>
public DisableScenarioCommandHandler(
IScenarioRepository scenarioRepository,
ILogger<DisableScenarioCommandHandler> logger,
IUnitOfWork unitOfWork,
ICurrentUserService currentUserService)
{
_scenarioRepository = scenarioRepository;
_logger = logger;
_unitOfWork = unitOfWork;
_currentUserService = currentUserService;
}
/// <summary>
/// 处理禁用场景命令
/// </summary>
public async Task<OperationResult<bool>> Handle(DisableScenarioCommand request, CancellationToken cancellationToken)
{
try
{
_logger.LogInformation("开始禁用场景,场景ID: {ScenarioId}", request.ScenarioId);
// 检查场景是否存在
var existingScenario = await _scenarioRepository.GetScenarioByIdAsync(request.ScenarioId, cancellationToken);
if (existingScenario == null)
{
_logger.LogWarning("场景不存在: {ScenarioId}", request.ScenarioId);
return OperationResult<bool>.CreateFailure($"场景ID {request.ScenarioId} 不存在");
}
// 检查场景是否已被软删除
if (existingScenario.IsDeleted)
{
_logger.LogWarning("场景已被删除: {ScenarioId}", request.ScenarioId);
return OperationResult<bool>.CreateFailure($"场景ID {request.ScenarioId} 已被删除");
}
// 检查场景是否已经禁用
if (existingScenario.IsDisabled)
{
_logger.LogWarning("场景已经禁用: {ScenarioId}", request.ScenarioId);
return OperationResult<bool>.CreateFailure($"场景ID {request.ScenarioId} 已经禁用");
}
// 获取当前用户ID
var currentUserId = _currentUserService.GetCurrentUserId();
if (string.IsNullOrEmpty(currentUserId))
{
_logger.LogError("无法获取当前用户ID,用户可能未认证");
return OperationResult<bool>.CreateFailure("用户未认证,无法禁用场景");
}
// 禁用场景
existingScenario.Disable();
existingScenario.Update(
code: existingScenario.Code,
name: existingScenario.Name,
networkConfigId: existingScenario.NetworkConfigId,
updatedBy: currentUserId,
description: existingScenario.Description,
isDisabled: true);
// 保存更改
_scenarioRepository.UpdateScenario(existingScenario);
// 保存更改到数据库
await _unitOfWork.SaveChangesAsync(cancellationToken);
_logger.LogInformation("场景禁用成功,场景ID: {ScenarioId}, 场景编码: {Code}, 场景名称: {Name}",
existingScenario.Id, existingScenario.Code, existingScenario.Name);
return OperationResult<bool>.CreateSuccess(true);
}
catch (Exception ex)
{
_logger.LogError(ex, "禁用场景时发生错误,场景ID: {ScenarioId}", request.ScenarioId);
return OperationResult<bool>.CreateFailure($"禁用场景时发生错误: {ex.Message}");
}
}
}

18
src/X1.Application/Features/Scenarios/Commands/EnableScenario/EnableScenarioCommand.cs

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

101
src/X1.Application/Features/Scenarios/Commands/EnableScenario/EnableScenarioCommandHandler.cs

@ -0,0 +1,101 @@
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.Scenarios.Commands.EnableScenario;
/// <summary>
/// 启用场景命令处理器
/// </summary>
public class EnableScenarioCommandHandler : IRequestHandler<EnableScenarioCommand, OperationResult<bool>>
{
private readonly IScenarioRepository _scenarioRepository;
private readonly ILogger<EnableScenarioCommandHandler> _logger;
private readonly IUnitOfWork _unitOfWork;
private readonly ICurrentUserService _currentUserService;
/// <summary>
/// 初始化命令处理器
/// </summary>
public EnableScenarioCommandHandler(
IScenarioRepository scenarioRepository,
ILogger<EnableScenarioCommandHandler> logger,
IUnitOfWork unitOfWork,
ICurrentUserService currentUserService)
{
_scenarioRepository = scenarioRepository;
_logger = logger;
_unitOfWork = unitOfWork;
_currentUserService = currentUserService;
}
/// <summary>
/// 处理启用场景命令
/// </summary>
public async Task<OperationResult<bool>> Handle(EnableScenarioCommand request, CancellationToken cancellationToken)
{
try
{
_logger.LogInformation("开始启用场景,场景ID: {ScenarioId}", request.ScenarioId);
// 检查场景是否存在
var existingScenario = await _scenarioRepository.GetScenarioByIdAsync(request.ScenarioId, cancellationToken);
if (existingScenario == null)
{
_logger.LogWarning("场景不存在: {ScenarioId}", request.ScenarioId);
return OperationResult<bool>.CreateFailure($"场景ID {request.ScenarioId} 不存在");
}
// 检查场景是否已被软删除
if (existingScenario.IsDeleted)
{
_logger.LogWarning("场景已被删除: {ScenarioId}", request.ScenarioId);
return OperationResult<bool>.CreateFailure($"场景ID {request.ScenarioId} 已被删除");
}
// 检查场景是否已经启用
if (!existingScenario.IsDisabled)
{
_logger.LogWarning("场景已经启用: {ScenarioId}", request.ScenarioId);
return OperationResult<bool>.CreateFailure($"场景ID {request.ScenarioId} 已经启用");
}
// 获取当前用户ID
var currentUserId = _currentUserService.GetCurrentUserId();
if (string.IsNullOrEmpty(currentUserId))
{
_logger.LogError("无法获取当前用户ID,用户可能未认证");
return OperationResult<bool>.CreateFailure("用户未认证,无法启用场景");
}
// 启用场景
existingScenario.Enable();
existingScenario.Update(
code: existingScenario.Code,
name: existingScenario.Name,
networkConfigId: existingScenario.NetworkConfigId,
updatedBy: currentUserId,
description: existingScenario.Description,
isDisabled: false);
// 保存更改
_scenarioRepository.UpdateScenario(existingScenario);
// 保存更改到数据库
await _unitOfWork.SaveChangesAsync(cancellationToken);
_logger.LogInformation("场景启用成功,场景ID: {ScenarioId}, 场景编码: {Code}, 场景名称: {Name}",
existingScenario.Id, existingScenario.Code, existingScenario.Name);
return OperationResult<bool>.CreateSuccess(true);
}
catch (Exception ex)
{
_logger.LogError(ex, "启用场景时发生错误,场景ID: {ScenarioId}", request.ScenarioId);
return OperationResult<bool>.CreateFailure($"启用场景时发生错误: {ex.Message}");
}
}
}

50
src/X1.Application/Features/Scenarios/Commands/UpdateScenario/UpdateScenarioCommand.cs

@ -0,0 +1,50 @@
using CellularManagement.Domain.Common;
using MediatR;
using System.ComponentModel.DataAnnotations;
namespace CellularManagement.Application.Features.Scenarios.Commands.UpdateScenario;
/// <summary>
/// 更新场景命令
/// </summary>
public class UpdateScenarioCommand : IRequest<OperationResult<UpdateScenarioResponse>>
{
/// <summary>
/// 场景ID
/// </summary>
[Required(ErrorMessage = "场景ID不能为空")]
[MaxLength(50, ErrorMessage = "场景ID长度不能超过50个字符")]
public string ScenarioId { 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>
/// 网络配置ID
/// </summary>
[Required(ErrorMessage = "网络配置ID不能为空")]
[MaxLength(50, ErrorMessage = "网络配置ID长度不能超过50个字符")]
public string NetworkConfigId { get; set; } = null!;
/// <summary>
/// 说明
/// </summary>
[MaxLength(1000, ErrorMessage = "说明长度不能超过1000个字符")]
public string? Description { get; set; }
/// <summary>
/// 是否禁用
/// </summary>
public bool IsDisabled { get; set; } = false;
}

109
src/X1.Application/Features/Scenarios/Commands/UpdateScenario/UpdateScenarioCommandHandler.cs

@ -0,0 +1,109 @@
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.Scenarios.Commands.UpdateScenario;
/// <summary>
/// 更新场景命令处理器
/// </summary>
public class UpdateScenarioCommandHandler : IRequestHandler<UpdateScenarioCommand, OperationResult<UpdateScenarioResponse>>
{
private readonly IScenarioRepository _scenarioRepository;
private readonly ILogger<UpdateScenarioCommandHandler> _logger;
private readonly IUnitOfWork _unitOfWork;
private readonly ICurrentUserService _currentUserService;
/// <summary>
/// 初始化命令处理器
/// </summary>
public UpdateScenarioCommandHandler(
IScenarioRepository scenarioRepository,
ILogger<UpdateScenarioCommandHandler> logger,
IUnitOfWork unitOfWork,
ICurrentUserService currentUserService)
{
_scenarioRepository = scenarioRepository;
_logger = logger;
_unitOfWork = unitOfWork;
_currentUserService = currentUserService;
}
/// <summary>
/// 处理更新场景命令
/// </summary>
public async Task<OperationResult<UpdateScenarioResponse>> Handle(UpdateScenarioCommand request, CancellationToken cancellationToken)
{
try
{
_logger.LogInformation("开始更新场景,场景ID: {ScenarioId}, 场景编码: {Code}, 场景名称: {Name}",
request.ScenarioId, request.Code, request.Name);
// 检查场景是否存在
var existingScenario = await _scenarioRepository.GetScenarioByIdAsync(request.ScenarioId, cancellationToken);
if (existingScenario == null)
{
_logger.LogWarning("场景不存在: {ScenarioId}", request.ScenarioId);
return OperationResult<UpdateScenarioResponse>.CreateFailure($"场景ID {request.ScenarioId} 不存在");
}
// 检查场景编码是否已被其他场景使用
var scenarioWithSameCode = await _scenarioRepository.GetScenarioByCodeAsync(request.Code, cancellationToken);
if (scenarioWithSameCode != null && scenarioWithSameCode.Id != request.ScenarioId)
{
_logger.LogWarning("场景编码已被其他场景使用: {Code}", request.Code);
return OperationResult<UpdateScenarioResponse>.CreateFailure($"场景编码 {request.Code} 已被其他场景使用");
}
// 获取当前用户ID
var currentUserId = _currentUserService.GetCurrentUserId();
if (string.IsNullOrEmpty(currentUserId))
{
_logger.LogError("无法获取当前用户ID,用户可能未认证");
return OperationResult<UpdateScenarioResponse>.CreateFailure("用户未认证,无法更新场景");
}
// 更新场景
existingScenario.Update(
code: request.Code,
name: request.Name,
networkConfigId: request.NetworkConfigId,
updatedBy: currentUserId,
description: request.Description,
isDisabled: request.IsDisabled);
// 保存更改
_scenarioRepository.UpdateScenario(existingScenario);
// 保存更改到数据库
await _unitOfWork.SaveChangesAsync(cancellationToken);
// 构建响应
var response = new UpdateScenarioResponse
{
ScenarioId = existingScenario.Id,
Code = existingScenario.Code,
Name = existingScenario.Name,
NetworkConfigId = existingScenario.NetworkConfigId,
Description = existingScenario.Description,
IsDisabled = existingScenario.IsDisabled,
UpdatedAt = existingScenario.UpdatedAt,
UpdatedBy = existingScenario.UpdatedBy
};
_logger.LogInformation("场景更新成功,场景ID: {ScenarioId}, 场景编码: {Code}, 场景名称: {Name}",
existingScenario.Id, existingScenario.Code, existingScenario.Name);
return OperationResult<UpdateScenarioResponse>.CreateSuccess(response);
}
catch (Exception ex)
{
_logger.LogError(ex, "更新场景时发生错误,场景ID: {ScenarioId}, 场景编码: {Code}, 场景名称: {Name}",
request.ScenarioId, request.Code, request.Name);
return OperationResult<UpdateScenarioResponse>.CreateFailure($"更新场景时发生错误: {ex.Message}");
}
}
}

47
src/X1.Application/Features/Scenarios/Commands/UpdateScenario/UpdateScenarioResponse.cs

@ -0,0 +1,47 @@
namespace CellularManagement.Application.Features.Scenarios.Commands.UpdateScenario;
/// <summary>
/// 更新场景响应
/// </summary>
public class UpdateScenarioResponse
{
/// <summary>
/// 场景ID
/// </summary>
public string ScenarioId { get; set; } = null!;
/// <summary>
/// 场景编码
/// </summary>
public string Code { get; set; } = null!;
/// <summary>
/// 场景名称
/// </summary>
public string Name { get; set; } = null!;
/// <summary>
/// 网络配置ID
/// </summary>
public string NetworkConfigId { get; set; } = null!;
/// <summary>
/// 说明
/// </summary>
public string? Description { get; set; }
/// <summary>
/// 是否禁用
/// </summary>
public bool IsDisabled { get; set; }
/// <summary>
/// 更新时间
/// </summary>
public DateTime? UpdatedAt { get; set; }
/// <summary>
/// 修改人
/// </summary>
public string? UpdatedBy { get; set; }
}

18
src/X1.Application/Features/Scenarios/Queries/GetScenarioById/GetScenarioByIdQuery.cs

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

82
src/X1.Application/Features/Scenarios/Queries/GetScenarioById/GetScenarioByIdQueryHandler.cs

@ -0,0 +1,82 @@
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.Scenarios.Queries.GetScenarioById;
/// <summary>
/// 根据ID获取场景查询处理器
/// </summary>
public class GetScenarioByIdQueryHandler : IRequestHandler<GetScenarioByIdQuery, OperationResult<GetScenarioByIdResponse>>
{
private readonly IScenarioRepository _scenarioRepository;
private readonly ILogger<GetScenarioByIdQueryHandler> _logger;
/// <summary>
/// 初始化查询处理器
/// </summary>
public GetScenarioByIdQueryHandler(
IScenarioRepository scenarioRepository,
ILogger<GetScenarioByIdQueryHandler> logger)
{
_scenarioRepository = scenarioRepository;
_logger = logger;
}
/// <summary>
/// 处理根据ID获取场景查询
/// </summary>
public async Task<OperationResult<GetScenarioByIdResponse>> Handle(GetScenarioByIdQuery 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<GetScenarioByIdResponse>.CreateFailure(errorMessages);
}
_logger.LogInformation("开始根据ID获取场景,ID: {Id}", request.Id);
// 获取场景数据
var scenario = await _scenarioRepository.GetScenarioByIdAsync(request.Id, cancellationToken);
if (scenario == null)
{
_logger.LogWarning("未找到指定的场景,ID: {Id}", request.Id);
return OperationResult<GetScenarioByIdResponse>.CreateFailure($"未找到ID为 {request.Id} 的场景");
}
// 构建响应
var response = new GetScenarioByIdResponse
{
ScenarioId = scenario.Id,
Code = scenario.Code,
Name = scenario.Name,
NetworkConfigId = scenario.NetworkConfigId,
Description = scenario.Description,
IsDisabled = scenario.IsDisabled,
CreatedAt = scenario.CreatedAt,
UpdatedAt = scenario.UpdatedAt,
CreatedBy = scenario.CreatedBy,
UpdatedBy = scenario.UpdatedBy
};
_logger.LogInformation("成功获取场景信息,ID: {Id}", request.Id);
return OperationResult<GetScenarioByIdResponse>.CreateSuccess(response);
}
catch (Exception ex)
{
_logger.LogError(ex, "根据ID获取场景时发生错误,ID: {Id}", request.Id);
return OperationResult<GetScenarioByIdResponse>.CreateFailure($"根据ID获取场景时发生错误: {ex.Message}");
}
}
}

57
src/X1.Application/Features/Scenarios/Queries/GetScenarioById/GetScenarioByIdResponse.cs

@ -0,0 +1,57 @@
namespace CellularManagement.Application.Features.Scenarios.Queries.GetScenarioById;
/// <summary>
/// 根据ID获取场景响应
/// </summary>
public class GetScenarioByIdResponse
{
/// <summary>
/// 场景ID
/// </summary>
public string ScenarioId { get; set; } = null!;
/// <summary>
/// 场景编码
/// </summary>
public string Code { get; set; } = null!;
/// <summary>
/// 场景名称
/// </summary>
public string Name { get; set; } = null!;
/// <summary>
/// 网络配置ID
/// </summary>
public string NetworkConfigId { get; set; } = null!;
/// <summary>
/// 说明
/// </summary>
public string? Description { get; set; }
/// <summary>
/// 是否禁用
/// </summary>
public bool IsDisabled { 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/Scenarios/Queries/GetScenarios/GetScenariosQuery.cs

@ -0,0 +1,40 @@
using CellularManagement.Domain.Common;
using MediatR;
using System.ComponentModel.DataAnnotations;
namespace CellularManagement.Application.Features.Scenarios.Queries.GetScenarios;
/// <summary>
/// 获取场景列表查询
/// </summary>
public class GetScenariosQuery : IRequest<OperationResult<GetScenariosResponse>>
{
/// <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>
/// 网络配置ID过滤
/// </summary>
[MaxLength(50)]
public string? NetworkConfigId { get; set; }
}

109
src/X1.Application/Features/Scenarios/Queries/GetScenarios/GetScenariosQueryHandler.cs

@ -0,0 +1,109 @@
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.Scenarios.Queries.GetScenarioById;
using CellularManagement.Domain.Repositories.Device;
namespace CellularManagement.Application.Features.Scenarios.Queries.GetScenarios;
/// <summary>
/// 获取场景列表查询处理器
/// </summary>
public class GetScenariosQueryHandler : IRequestHandler<GetScenariosQuery, OperationResult<GetScenariosResponse>>
{
private readonly IScenarioRepository _scenarioRepository;
private readonly ILogger<GetScenariosQueryHandler> _logger;
/// <summary>
/// 初始化查询处理器
/// </summary>
public GetScenariosQueryHandler(
IScenarioRepository scenarioRepository,
ILogger<GetScenariosQueryHandler> logger)
{
_scenarioRepository = scenarioRepository;
_logger = logger;
}
/// <summary>
/// 处理获取场景列表查询
/// </summary>
public async Task<OperationResult<GetScenariosResponse>> Handle(GetScenariosQuery 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<GetScenariosResponse>.CreateFailure(errorMessages);
}
_logger.LogInformation("开始获取场景列表,页码: {PageNumber}, 每页数量: {PageSize}, 搜索关键词: {SearchTerm}, 是否启用: {IsEnabled}, 网络配置ID: {NetworkConfigId}",
request.PageNumber, request.PageSize, request.SearchTerm, request.IsEnabled, request.NetworkConfigId);
// 获取场景数据
var scenarios = await _scenarioRepository.SearchScenariosAsync(
request.SearchTerm,
cancellationToken);
// 如果指定了启用状态过滤
if (request.IsEnabled.HasValue)
{
scenarios = scenarios.Where(s => !s.IsDisabled == request.IsEnabled.Value).ToList();
}
// 如果指定了网络配置ID过滤
if (!string.IsNullOrEmpty(request.NetworkConfigId))
{
scenarios = scenarios.Where(s => s.NetworkConfigId == request.NetworkConfigId).ToList();
}
// 计算分页
int totalCount = scenarios.Count();
var items = scenarios
.Skip((request.PageNumber - 1) * request.PageSize)
.Take(request.PageSize)
.ToList();
// 构建响应
var response = new GetScenariosResponse
{
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(s => new GetScenarioByIdResponse
{
ScenarioId = s.Id,
Code = s.Code,
Name = s.Name,
NetworkConfigId = s.NetworkConfigId,
Description = s.Description,
IsDisabled = s.IsDisabled,
CreatedAt = s.CreatedAt,
UpdatedAt = s.UpdatedAt,
CreatedBy = s.CreatedBy,
UpdatedBy = s.UpdatedBy
}).ToList()
};
_logger.LogInformation("成功获取场景列表,共 {Count} 条记录", items.Count);
return OperationResult<GetScenariosResponse>.CreateSuccess(response);
}
catch (Exception ex)
{
_logger.LogError(ex, "获取场景列表时发生错误");
return OperationResult<GetScenariosResponse>.CreateFailure($"获取场景列表时发生错误: {ex.Message}");
}
}
}

44
src/X1.Application/Features/Scenarios/Queries/GetScenarios/GetScenariosResponse.cs

@ -0,0 +1,44 @@
using CellularManagement.Application.Features.Scenarios.Queries.GetScenarioById;
namespace CellularManagement.Application.Features.Scenarios.Queries.GetScenarios;
/// <summary>
/// 获取场景列表响应
/// </summary>
public class GetScenariosResponse
{
/// <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<GetScenarioByIdResponse> Items { get; set; } = new();
}

128
src/X1.Domain/Entities/Device/Scenario.cs

@ -0,0 +1,128 @@
using System.ComponentModel.DataAnnotations;
using CellularManagement.Domain.Entities.Common;
namespace CellularManagement.Domain.Entities.Device;
/// <summary>
/// 场景实体
/// </summary>
public class Scenario : AuditableEntity
{
private Scenario() { }
/// <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>
/// 网络配置ID
/// </summary>
[Required]
[MaxLength(50)]
public string NetworkConfigId { get; private set; } = null!;
/// <summary>
/// 说明
/// </summary>
[MaxLength(1000)]
public string? Description { get; private set; }
/// <summary>
/// 是否禁用
/// </summary>
public bool IsDisabled { get; private set; } = false;
/// <summary>
/// 创建场景
/// </summary>
public static Scenario Create(
string code,
string name,
string networkConfigId,
string createdBy,
string? description = null,
bool isDisabled = false)
{
var scenario = new Scenario
{
Id = Guid.NewGuid().ToString(),
Code = code,
Name = name,
NetworkConfigId = networkConfigId,
Description = description,
IsDisabled = isDisabled,
CreatedAt = DateTime.UtcNow,
UpdatedAt = DateTime.UtcNow,
CreatedBy = createdBy,
UpdatedBy = createdBy
};
return scenario;
}
/// <summary>
/// 更新场景
/// </summary>
public void Update(
string code,
string name,
string networkConfigId,
string updatedBy,
string? description = null,
bool isDisabled = false)
{
Code = code;
Name = name;
NetworkConfigId = networkConfigId;
Description = description;
IsDisabled = isDisabled;
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;
}
}

68
src/X1.Domain/Repositories/Device/IScenarioRepository.cs

@ -0,0 +1,68 @@
using CellularManagement.Domain.Entities;
using CellularManagement.Domain.Entities.Device;
using CellularManagement.Domain.Repositories.Base;
namespace CellularManagement.Domain.Repositories.Device;
/// <summary>
/// 场景仓储接口
/// </summary>
public interface IScenarioRepository : IBaseRepository<Scenario>
{
/// <summary>
/// 添加场景
/// </summary>
Task<Scenario> AddScenarioAsync(Scenario scenario, CancellationToken cancellationToken = default);
/// <summary>
/// 更新场景
/// </summary>
void UpdateScenario(Scenario scenario);
/// <summary>
/// 删除场景
/// </summary>
Task DeleteScenarioAsync(string id, CancellationToken cancellationToken = default);
/// <summary>
/// 获取所有场景
/// </summary>
Task<IList<Scenario>> GetAllScenariosAsync(CancellationToken cancellationToken = default);
/// <summary>
/// 根据ID获取场景
/// </summary>
Task<Scenario?> GetScenarioByIdAsync(string id, CancellationToken cancellationToken = default);
/// <summary>
/// 根据编码获取场景
/// </summary>
Task<Scenario?> GetScenarioByCodeAsync(string code, CancellationToken cancellationToken = default);
/// <summary>
/// 搜索场景
/// </summary>
Task<IList<Scenario>> SearchScenariosAsync(
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<IList<Scenario>> GetEnabledScenariosAsync(CancellationToken cancellationToken = default);
/// <summary>
/// 根据网络配置ID获取场景
/// </summary>
Task<IList<Scenario>> GetScenariosByNetworkConfigIdAsync(string networkConfigId, CancellationToken cancellationToken = default);
}

30
src/X1.Infrastructure/Configurations/Device/ScenarioConfiguration.cs

@ -0,0 +1,30 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using CellularManagement.Domain.Entities.Device;
namespace CellularManagement.Infrastructure.Configurations.Device;
public class ScenarioConfiguration : IEntityTypeConfiguration<Scenario>
{
public void Configure(EntityTypeBuilder<Scenario> builder)
{
builder.ToTable("Scenarios", t => t.HasComment("场景表"));
builder.HasKey(s => s.Id);
// 配置索引
builder.HasIndex(s => s.Code).IsUnique().HasDatabaseName("IX_Scenarios_Code");
builder.HasIndex(s => s.NetworkConfigId).HasDatabaseName("IX_Scenarios_NetworkConfigId");
// 配置属性
builder.Property(s => s.Id).HasComment("场景ID");
builder.Property(s => s.Code).IsRequired().HasMaxLength(50).HasComment("场景编码");
builder.Property(s => s.Name).IsRequired().HasMaxLength(100).HasComment("场景名称");
builder.Property(s => s.NetworkConfigId).IsRequired().HasMaxLength(50).HasComment("网络配置ID");
builder.Property(s => s.Description).HasMaxLength(1000).HasComment("说明");
builder.Property(s => s.IsDisabled).IsRequired().HasComment("是否禁用");
builder.Property(s => s.CreatedAt).IsRequired().HasColumnType("timestamp with time zone").HasComment("创建时间");
builder.Property(s => s.UpdatedAt).HasColumnType("timestamp with time zone").HasComment("更新时间");
builder.Property(s => s.CreatedBy).IsRequired().HasMaxLength(50).HasComment("创建人");
builder.Property(s => s.UpdatedBy).HasMaxLength(50).HasComment("修改人");
}
}

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

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

1
src/X1.Infrastructure/DependencyInjection.cs

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

139
src/X1.Infrastructure/Repositories/Device/ScenarioRepository.cs

@ -0,0 +1,139 @@
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 ScenarioRepository : BaseRepository<Scenario>, IScenarioRepository
{
private readonly ILogger<ScenarioRepository> _logger;
/// <summary>
/// 初始化仓储
/// </summary>
public ScenarioRepository(
ICommandRepository<Scenario> commandRepository,
IQueryRepository<Scenario> queryRepository,
ILogger<ScenarioRepository> logger)
: base(commandRepository, queryRepository, logger)
{
_logger = logger;
}
/// <summary>
/// 添加场景
/// </summary>
public async Task<Scenario> AddScenarioAsync(Scenario scenario, CancellationToken cancellationToken = default)
{
var result = await CommandRepository.AddAsync(scenario, cancellationToken);
return result;
}
/// <summary>
/// 更新场景
/// </summary>
public void UpdateScenario(Scenario scenario)
{
CommandRepository.Update(scenario);
}
/// <summary>
/// 删除场景
/// </summary>
public async Task DeleteScenarioAsync(string id, CancellationToken cancellationToken = default)
{
await CommandRepository.DeleteByIdAsync(id, cancellationToken);
}
/// <summary>
/// 获取所有场景
/// </summary>
public async Task<IList<Scenario>> GetAllScenariosAsync(CancellationToken cancellationToken = default)
{
var scenarios = await QueryRepository.GetAllAsync(cancellationToken: cancellationToken);
return scenarios.ToList();
}
/// <summary>
/// 根据ID获取场景
/// </summary>
public async Task<Scenario?> GetScenarioByIdAsync(string id, CancellationToken cancellationToken = default)
{
return await QueryRepository.GetByIdAsync(id, cancellationToken: cancellationToken);
}
/// <summary>
/// 根据编码获取场景
/// </summary>
public async Task<Scenario?> GetScenarioByCodeAsync(string code, CancellationToken cancellationToken = default)
{
return await QueryRepository.FirstOrDefaultAsync(s => s.Code == code, cancellationToken: cancellationToken);
}
/// <summary>
/// 搜索场景
/// </summary>
public async Task<IList<Scenario>> SearchScenariosAsync(
string? keyword,
CancellationToken cancellationToken = default)
{
var query = await QueryRepository.FindAsync(s => true, cancellationToken: cancellationToken);
if (!string.IsNullOrWhiteSpace(keyword))
{
query = query.Where(s =>
s.Name.Contains(keyword) ||
s.Code.Contains(keyword) ||
(s.Description != null && s.Description.Contains(keyword)));
}
var scenarios = query;
return scenarios.ToList();
}
/// <summary>
/// 检查场景是否存在
/// </summary>
public async Task<bool> ExistsAsync(string id, CancellationToken cancellationToken = default)
{
return await QueryRepository.AnyAsync(s => s.Id == id, cancellationToken: cancellationToken);
}
/// <summary>
/// 检查编码是否存在
/// </summary>
public async Task<bool> CodeExistsAsync(string code, CancellationToken cancellationToken = default)
{
return await QueryRepository.AnyAsync(s => s.Code == code, cancellationToken: cancellationToken);
}
/// <summary>
/// 获取启用的场景
/// </summary>
public async Task<IList<Scenario>> GetEnabledScenariosAsync(CancellationToken cancellationToken = default)
{
var scenarios = await QueryRepository.FindAsync(s => !s.IsDisabled, cancellationToken: cancellationToken);
return scenarios.ToList();
}
/// <summary>
/// 根据网络配置ID获取场景
/// </summary>
public async Task<IList<Scenario>> GetScenariosByNetworkConfigIdAsync(string networkConfigId, CancellationToken cancellationToken = default)
{
var scenarios = await QueryRepository.FindAsync(s => s.NetworkConfigId == networkConfigId, cancellationToken: cancellationToken);
return scenarios.ToList();
}
}

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

@ -0,0 +1,175 @@
using CellularManagement.Application.Features.Scenarios.Commands.CreateScenario;
using CellularManagement.Application.Features.Scenarios.Commands.DeleteScenario;
using CellularManagement.Application.Features.Scenarios.Commands.DisableScenario;
using CellularManagement.Application.Features.Scenarios.Commands.EnableScenario;
using CellularManagement.Application.Features.Scenarios.Commands.UpdateScenario;
using CellularManagement.Application.Features.Scenarios.Queries.GetScenarioById;
using CellularManagement.Application.Features.Scenarios.Queries.GetScenarios;
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/scenarios")]
[ApiController]
[Authorize]
public class ScenariosController : ApiController
{
private readonly ILogger<ScenariosController> _logger;
/// <summary>
/// 初始化场景控制器
/// </summary>
public ScenariosController(IMediator mediator, ILogger<ScenariosController> logger)
: base(mediator)
{
_logger = logger;
}
/// <summary>
/// 获取场景列表
/// </summary>
[HttpGet]
public async Task<OperationResult<GetScenariosResponse>> GetAll([FromQuery] GetScenariosQuery query)
{
_logger.LogInformation("开始获取场景列表,页码: {PageNumber}, 每页数量: {PageSize}, 搜索关键词: {SearchTerm}, 是否启用: {IsEnabled}, 网络配置ID: {NetworkConfigId}",
query.PageNumber, query.PageSize, query.SearchTerm, query.IsEnabled, query.NetworkConfigId);
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<GetScenarioByIdResponse>> GetById(string id)
{
_logger.LogInformation("开始获取场景详情,场景ID: {ScenarioId}", id);
var result = await mediator.Send(new GetScenarioByIdQuery { Id = id });
if (!result.IsSuccess)
{
_logger.LogWarning("获取场景详情失败: {Message}", result.ErrorMessages);
return result;
}
_logger.LogInformation("成功获取场景详情,场景ID: {ScenarioId}", id);
return result;
}
/// <summary>
/// 创建场景
/// </summary>
[HttpPost]
public async Task<OperationResult<CreateScenarioResponse>> Create([FromBody] CreateScenarioCommand command)
{
_logger.LogInformation("开始创建场景,场景编码: {Code}, 场景名称: {Name}", command.Code, command.Name);
var result = await mediator.Send(command);
if (!result.IsSuccess)
{
_logger.LogWarning("创建场景失败: {Message}", result.ErrorMessages);
return result;
}
_logger.LogInformation("成功创建场景,场景ID: {ScenarioId}", result.Data?.ScenarioId);
return result;
}
/// <summary>
/// 更新场景
/// </summary>
[HttpPut("{id}")]
public async Task<OperationResult<UpdateScenarioResponse>> Update(string id, [FromBody] UpdateScenarioCommand command)
{
_logger.LogInformation("开始更新场景,场景ID: {ScenarioId}", id);
if (id != command.ScenarioId)
{
_logger.LogWarning("场景ID不匹配,路径ID: {PathId}, 命令ID: {CommandId}", id, command.ScenarioId);
return OperationResult<UpdateScenarioResponse>.CreateFailure("场景ID不匹配");
}
var result = await mediator.Send(command);
if (!result.IsSuccess)
{
_logger.LogWarning("更新场景失败: {Message}", result.ErrorMessages);
return result;
}
_logger.LogInformation("成功更新场景,场景ID: {ScenarioId}", id);
return result;
}
/// <summary>
/// 删除场景
/// </summary>
[HttpDelete("{id}")]
public async Task<OperationResult<bool>> Delete(string id)
{
_logger.LogInformation("开始删除场景,场景ID: {ScenarioId}", id);
var result = await mediator.Send(new DeleteScenarioCommand { ScenarioId = id });
if (!result.IsSuccess)
{
_logger.LogWarning("删除场景失败: {Message}", result.ErrorMessages);
return result;
}
_logger.LogInformation("成功删除场景,场景ID: {ScenarioId}", id);
return result;
}
/// <summary>
/// 启用场景
/// </summary>
[HttpPost("{id}/enable")]
public async Task<OperationResult<bool>> Enable(string id)
{
_logger.LogInformation("开始启用场景,场景ID: {ScenarioId}", id);
var result = await mediator.Send(new EnableScenarioCommand { ScenarioId = id });
if (!result.IsSuccess)
{
_logger.LogWarning("启用场景失败: {Message}", result.ErrorMessages);
return result;
}
_logger.LogInformation("成功启用场景,场景ID: {ScenarioId}", id);
return result;
}
/// <summary>
/// 禁用场景
/// </summary>
[HttpPost("{id}/disable")]
public async Task<OperationResult<bool>> Disable(string id)
{
_logger.LogInformation("开始禁用场景,场景ID: {ScenarioId}", id);
var result = await mediator.Send(new DisableScenarioCommand { ScenarioId = id });
if (!result.IsSuccess)
{
_logger.LogWarning("禁用场景失败: {Message}", result.ErrorMessages);
return result;
}
_logger.LogInformation("成功禁用场景,场景ID: {ScenarioId}", id);
return result;
}
}
Loading…
Cancel
Save