17 changed files with 1308 additions and 0 deletions
@ -0,0 +1,61 @@ |
|||||
|
using CellularManagement.Domain.Common; |
||||
|
using CellularManagement.Domain.Entities; |
||||
|
using MediatR; |
||||
|
using System.ComponentModel.DataAnnotations; |
||||
|
|
||||
|
namespace CellularManagement.Application.Features.Devices.Commands.CreateDevice; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 创建设备命令
|
||||
|
/// </summary>
|
||||
|
public class CreateDeviceCommand : IRequest<OperationResult<Device>> |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 设备名称
|
||||
|
/// </summary>
|
||||
|
[Required(ErrorMessage = "设备名称不能为空")] |
||||
|
[MaxLength(100, ErrorMessage = "设备名称不能超过100个字符")] |
||||
|
public string DeviceName { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 协议版本
|
||||
|
/// </summary>
|
||||
|
[MaxLength(50, ErrorMessage = "协议版本不能超过50个字符")] |
||||
|
public string ProtocolVersion { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 支持的频段
|
||||
|
/// </summary>
|
||||
|
[MaxLength(100, ErrorMessage = "支持的频段不能超过100个字符")] |
||||
|
public string SupportBands { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 硬件版本
|
||||
|
/// </summary>
|
||||
|
[MaxLength(50, ErrorMessage = "硬件版本不能超过50个字符")] |
||||
|
public string HardwareVersion { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 序列号
|
||||
|
/// </summary>
|
||||
|
[Required(ErrorMessage = "序列号不能为空")] |
||||
|
[MaxLength(100, ErrorMessage = "序列号不能超过100个字符")] |
||||
|
public string SerialNumber { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 备注
|
||||
|
/// </summary>
|
||||
|
[MaxLength(500, ErrorMessage = "备注不能超过500个字符")] |
||||
|
public string Comment { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// IP地址
|
||||
|
/// </summary>
|
||||
|
[MaxLength(50, ErrorMessage = "IP地址不能超过50个字符")] |
||||
|
public string IPAddress { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 是否禁用
|
||||
|
/// </summary>
|
||||
|
public bool IsDisabled { get; set; } |
||||
|
} |
@ -0,0 +1,72 @@ |
|||||
|
using MediatR; |
||||
|
using Microsoft.Extensions.Logging; |
||||
|
using CellularManagement.Domain.Common; |
||||
|
using CellularManagement.Domain.Entities; |
||||
|
using CellularManagement.Domain.Repositories; |
||||
|
|
||||
|
namespace CellularManagement.Application.Features.Devices.Commands.CreateDevice; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 创建设备命令处理器
|
||||
|
/// </summary>
|
||||
|
public class CreateDeviceCommandHandler : IRequestHandler<CreateDeviceCommand, OperationResult<Device>> |
||||
|
{ |
||||
|
private readonly IDeviceRepository _deviceRepository; |
||||
|
private readonly ILogger<CreateDeviceCommandHandler> _logger; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 初始化命令处理器
|
||||
|
/// </summary>
|
||||
|
public CreateDeviceCommandHandler( |
||||
|
IDeviceRepository deviceRepository, |
||||
|
ILogger<CreateDeviceCommandHandler> logger) |
||||
|
{ |
||||
|
_deviceRepository = deviceRepository; |
||||
|
_logger = logger; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 处理创建设备命令
|
||||
|
/// </summary>
|
||||
|
public async Task<OperationResult<Device>> Handle(CreateDeviceCommand request, CancellationToken cancellationToken) |
||||
|
{ |
||||
|
try |
||||
|
{ |
||||
|
_logger.LogInformation("Creating new device with serial number: {SerialNumber}", request.SerialNumber); |
||||
|
|
||||
|
// 检查序列号是否已存在
|
||||
|
if (await _deviceRepository.ExistsBySerialNumberAsync(request.SerialNumber, cancellationToken: cancellationToken)) |
||||
|
{ |
||||
|
_logger.LogWarning("Device with serial number {SerialNumber} already exists", request.SerialNumber); |
||||
|
return OperationResult<Device>.CreateFailure($"设备序列号 {request.SerialNumber} 已存在"); |
||||
|
} |
||||
|
|
||||
|
// 创建设备实体
|
||||
|
var device = new Device |
||||
|
{ |
||||
|
DeviceID = Guid.NewGuid().ToString(), |
||||
|
DeviceName = request.DeviceName, |
||||
|
ProtocolVersion = request.ProtocolVersion, |
||||
|
SupportBands = request.SupportBands, |
||||
|
HardwareVersion = request.HardwareVersion, |
||||
|
SerialNumber = request.SerialNumber, |
||||
|
Comment = request.Comment, |
||||
|
IPAddress = request.IPAddress, |
||||
|
IsDisabled = false, |
||||
|
CreatedAt = DateTime.UtcNow, |
||||
|
UpdatedAt = DateTime.UtcNow |
||||
|
}; |
||||
|
|
||||
|
// 保存设备
|
||||
|
await _deviceRepository.CreateAsync(device, cancellationToken); |
||||
|
|
||||
|
_logger.LogInformation("Successfully created device with ID: {DeviceId}", device.DeviceID); |
||||
|
return OperationResult<Device>.CreateSuccess("设备创建成功", device); |
||||
|
} |
||||
|
catch (Exception ex) |
||||
|
{ |
||||
|
_logger.LogError(ex, "Error creating device with serial number: {SerialNumber}", request.SerialNumber); |
||||
|
return OperationResult<Device>.CreateFailure($"创建设备时发生错误: {ex.Message}"); |
||||
|
} |
||||
|
} |
||||
|
} |
@ -0,0 +1,25 @@ |
|||||
|
using CellularManagement.Domain.Common; |
||||
|
using MediatR; |
||||
|
using System.ComponentModel.DataAnnotations; |
||||
|
|
||||
|
namespace CellularManagement.Application.Features.Devices.Commands.DeleteDevice; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 删除设备命令
|
||||
|
/// </summary>
|
||||
|
public class DeleteDeviceCommand : IRequest<OperationResult<bool>> |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 设备ID
|
||||
|
/// </summary>
|
||||
|
[Required(ErrorMessage = "设备ID不能为空")] |
||||
|
public string DeviceId { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 初始化删除设备命令
|
||||
|
/// </summary>
|
||||
|
public DeleteDeviceCommand(string deviceId) |
||||
|
{ |
||||
|
DeviceId = deviceId; |
||||
|
} |
||||
|
} |
@ -0,0 +1,55 @@ |
|||||
|
using MediatR; |
||||
|
using Microsoft.Extensions.Logging; |
||||
|
using CellularManagement.Domain.Common; |
||||
|
using CellularManagement.Domain.Repositories; |
||||
|
|
||||
|
namespace CellularManagement.Application.Features.Devices.Commands.DeleteDevice; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 删除设备命令处理器
|
||||
|
/// </summary>
|
||||
|
public class DeleteDeviceCommandHandler : IRequestHandler<DeleteDeviceCommand, OperationResult<bool>> |
||||
|
{ |
||||
|
private readonly IDeviceRepository _deviceRepository; |
||||
|
private readonly ILogger<DeleteDeviceCommandHandler> _logger; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 初始化删除设备命令处理器
|
||||
|
/// </summary>
|
||||
|
public DeleteDeviceCommandHandler( |
||||
|
IDeviceRepository deviceRepository, |
||||
|
ILogger<DeleteDeviceCommandHandler> logger) |
||||
|
{ |
||||
|
_deviceRepository = deviceRepository; |
||||
|
_logger = logger; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 处理删除设备命令
|
||||
|
/// </summary>
|
||||
|
public async Task<OperationResult<bool>> Handle(DeleteDeviceCommand request, CancellationToken cancellationToken) |
||||
|
{ |
||||
|
try |
||||
|
{ |
||||
|
_logger.LogInformation("开始处理删除设备命令,设备ID: {DeviceId}", request.DeviceId); |
||||
|
|
||||
|
var result = await _deviceRepository.DeleteByIdAsync(request.DeviceId, cancellationToken); |
||||
|
|
||||
|
if (result) |
||||
|
{ |
||||
|
_logger.LogInformation("设备删除成功,设备ID: {DeviceId}", request.DeviceId); |
||||
|
return OperationResult<bool>.CreateSuccess(true); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
_logger.LogWarning("设备删除失败,设备ID: {DeviceId}", request.DeviceId); |
||||
|
return OperationResult<bool>.CreateFailure("设备删除失败"); |
||||
|
} |
||||
|
} |
||||
|
catch (Exception ex) |
||||
|
{ |
||||
|
_logger.LogError(ex, "删除设备时发生错误,设备ID: {DeviceId}", request.DeviceId); |
||||
|
return OperationResult<bool>.CreateFailure($"删除设备时发生错误: {ex.Message}"); |
||||
|
} |
||||
|
} |
||||
|
} |
@ -0,0 +1,67 @@ |
|||||
|
using CellularManagement.Domain.Common; |
||||
|
using CellularManagement.Domain.Entities; |
||||
|
using MediatR; |
||||
|
using System.ComponentModel.DataAnnotations; |
||||
|
|
||||
|
namespace CellularManagement.Application.Features.Devices.Commands.UpdateDevice; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 更新设备命令
|
||||
|
/// </summary>
|
||||
|
public class UpdateDeviceCommand : IRequest<OperationResult<Device>> |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 设备ID
|
||||
|
/// </summary>
|
||||
|
[Required(ErrorMessage = "设备ID不能为空")] |
||||
|
public string DeviceID { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 设备名称
|
||||
|
/// </summary>
|
||||
|
[Required(ErrorMessage = "设备名称不能为空")] |
||||
|
[MaxLength(100, ErrorMessage = "设备名称不能超过100个字符")] |
||||
|
public string DeviceName { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 协议版本
|
||||
|
/// </summary>
|
||||
|
[MaxLength(50, ErrorMessage = "协议版本不能超过50个字符")] |
||||
|
public string ProtocolVersion { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 支持的频段
|
||||
|
/// </summary>
|
||||
|
[MaxLength(100, ErrorMessage = "支持的频段不能超过100个字符")] |
||||
|
public string SupportBands { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 硬件版本
|
||||
|
/// </summary>
|
||||
|
[MaxLength(50, ErrorMessage = "硬件版本不能超过50个字符")] |
||||
|
public string HardwareVersion { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 序列号
|
||||
|
/// </summary>
|
||||
|
[Required(ErrorMessage = "序列号不能为空")] |
||||
|
[MaxLength(100, ErrorMessage = "序列号不能超过100个字符")] |
||||
|
public string SerialNumber { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 备注
|
||||
|
/// </summary>
|
||||
|
[MaxLength(500, ErrorMessage = "备注不能超过500个字符")] |
||||
|
public string Comment { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// IP地址
|
||||
|
/// </summary>
|
||||
|
[MaxLength(50, ErrorMessage = "IP地址不能超过50个字符")] |
||||
|
public string IPAddress { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 是否禁用
|
||||
|
/// </summary>
|
||||
|
public bool IsDisabled { get; set; } |
||||
|
} |
@ -0,0 +1,83 @@ |
|||||
|
using MediatR; |
||||
|
using Microsoft.Extensions.Logging; |
||||
|
using CellularManagement.Domain.Common; |
||||
|
using CellularManagement.Domain.Entities; |
||||
|
using CellularManagement.Domain.Repositories; |
||||
|
|
||||
|
namespace CellularManagement.Application.Features.Devices.Commands.UpdateDevice; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 更新设备命令处理器
|
||||
|
/// </summary>
|
||||
|
public class UpdateDeviceCommandHandler : IRequestHandler<UpdateDeviceCommand, OperationResult<Device>> |
||||
|
{ |
||||
|
private readonly IDeviceRepository _deviceRepository; |
||||
|
private readonly ILogger<UpdateDeviceCommandHandler> _logger; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 初始化命令处理器
|
||||
|
/// </summary>
|
||||
|
public UpdateDeviceCommandHandler( |
||||
|
IDeviceRepository deviceRepository, |
||||
|
ILogger<UpdateDeviceCommandHandler> logger) |
||||
|
{ |
||||
|
_deviceRepository = deviceRepository; |
||||
|
_logger = logger; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 处理更新设备命令
|
||||
|
/// </summary>
|
||||
|
public async Task<OperationResult<Device>> Handle(UpdateDeviceCommand request, CancellationToken cancellationToken) |
||||
|
{ |
||||
|
try |
||||
|
{ |
||||
|
_logger.LogInformation("Updating device with ID: {DeviceId}", request.DeviceID); |
||||
|
|
||||
|
// 检查设备是否存在
|
||||
|
var existingDevice = await _deviceRepository.GetByIdAsync(request.DeviceID, cancellationToken); |
||||
|
if (existingDevice == null) |
||||
|
{ |
||||
|
_logger.LogWarning("Device not found with ID: {DeviceId}", request.DeviceID); |
||||
|
return OperationResult<Device>.CreateFailure($"未找到ID为 {request.DeviceID} 的设备"); |
||||
|
} |
||||
|
|
||||
|
// 如果序列号发生变化,检查新序列号是否已存在
|
||||
|
if (existingDevice.SerialNumber != request.SerialNumber) |
||||
|
{ |
||||
|
if (await _deviceRepository.ExistsBySerialNumberAsync(request.SerialNumber, request.DeviceID, cancellationToken)) |
||||
|
{ |
||||
|
_logger.LogWarning("Device with serial number {SerialNumber} already exists", request.SerialNumber); |
||||
|
return OperationResult<Device>.CreateFailure($"设备序列号 {request.SerialNumber} 已存在"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 更新设备属性
|
||||
|
existingDevice.DeviceName = request.DeviceName; |
||||
|
existingDevice.ProtocolVersion = request.ProtocolVersion; |
||||
|
existingDevice.SupportBands = request.SupportBands; |
||||
|
existingDevice.HardwareVersion = request.HardwareVersion; |
||||
|
existingDevice.SerialNumber = request.SerialNumber; |
||||
|
existingDevice.Comment = request.Comment; |
||||
|
existingDevice.IPAddress = request.IPAddress; |
||||
|
existingDevice.IsDisabled = request.IsDisabled; |
||||
|
existingDevice.UpdatedAt = DateTime.UtcNow; |
||||
|
|
||||
|
// 保存更新
|
||||
|
var result = await _deviceRepository.UpdateAsync(existingDevice, cancellationToken); |
||||
|
if (!result) |
||||
|
{ |
||||
|
_logger.LogWarning("Failed to update device with ID: {DeviceId}", request.DeviceID); |
||||
|
return OperationResult<Device>.CreateFailure("更新设备失败"); |
||||
|
} |
||||
|
|
||||
|
_logger.LogInformation("Successfully updated device with ID: {DeviceId}", request.DeviceID); |
||||
|
return OperationResult<Device>.CreateSuccess("设备更新成功", existingDevice); |
||||
|
} |
||||
|
catch (Exception ex) |
||||
|
{ |
||||
|
_logger.LogError(ex, "Error updating device with ID: {DeviceId}", request.DeviceID); |
||||
|
return OperationResult<Device>.CreateFailure($"更新设备时发生错误: {ex.Message}"); |
||||
|
} |
||||
|
} |
||||
|
} |
@ -0,0 +1,26 @@ |
|||||
|
using CellularManagement.Domain.Common; |
||||
|
using CellularManagement.Domain.Entities; |
||||
|
using MediatR; |
||||
|
using System.ComponentModel.DataAnnotations; |
||||
|
|
||||
|
namespace CellularManagement.Application.Features.Devices.Queries.GetDeviceById; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 根据ID获取设备查询
|
||||
|
/// </summary>
|
||||
|
public class GetDeviceByIdQuery : IRequest<OperationResult<Device>> |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 设备ID
|
||||
|
/// </summary>
|
||||
|
[Required(ErrorMessage = "设备ID不能为空")] |
||||
|
public string DeviceId { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 初始化查询
|
||||
|
/// </summary>
|
||||
|
public GetDeviceByIdQuery(string deviceId) |
||||
|
{ |
||||
|
DeviceId = deviceId; |
||||
|
} |
||||
|
} |
@ -0,0 +1,54 @@ |
|||||
|
using CellularManagement.Domain.Common; |
||||
|
using CellularManagement.Domain.Entities; |
||||
|
using CellularManagement.Domain.Repositories; |
||||
|
using MediatR; |
||||
|
using Microsoft.Extensions.Logging; |
||||
|
|
||||
|
namespace CellularManagement.Application.Features.Devices.Queries.GetDeviceById; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 根据ID获取设备查询处理器
|
||||
|
/// </summary>
|
||||
|
public class GetDeviceByIdQueryHandler : IRequestHandler<GetDeviceByIdQuery, OperationResult<Device>> |
||||
|
{ |
||||
|
private readonly IDeviceRepository _deviceRepository; |
||||
|
private readonly ILogger<GetDeviceByIdQueryHandler> _logger; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 初始化查询处理器
|
||||
|
/// </summary>
|
||||
|
public GetDeviceByIdQueryHandler( |
||||
|
IDeviceRepository deviceRepository, |
||||
|
ILogger<GetDeviceByIdQueryHandler> logger) |
||||
|
{ |
||||
|
_deviceRepository = deviceRepository; |
||||
|
_logger = logger; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 处理查询请求
|
||||
|
/// </summary>
|
||||
|
public async Task<OperationResult<Device>> Handle(GetDeviceByIdQuery request, CancellationToken cancellationToken) |
||||
|
{ |
||||
|
try |
||||
|
{ |
||||
|
_logger.LogInformation("开始查询设备,设备ID: {DeviceId}", request.DeviceId); |
||||
|
|
||||
|
var device = await _deviceRepository.GetByIdAsync(request.DeviceId, cancellationToken); |
||||
|
|
||||
|
if (device == null) |
||||
|
{ |
||||
|
_logger.LogWarning("未找到设备,设备ID: {DeviceId}", request.DeviceId); |
||||
|
return OperationResult<Device>.CreateFailure($"未找到ID为 {request.DeviceId} 的设备"); |
||||
|
} |
||||
|
|
||||
|
_logger.LogInformation("成功查询到设备,设备ID: {DeviceId}", request.DeviceId); |
||||
|
return OperationResult<Device>.CreateSuccess(device); |
||||
|
} |
||||
|
catch (Exception ex) |
||||
|
{ |
||||
|
_logger.LogError(ex, "查询设备时发生错误,设备ID: {DeviceId}", request.DeviceId); |
||||
|
return OperationResult<Device>.CreateFailure($"查询设备时发生错误: {ex.Message}"); |
||||
|
} |
||||
|
} |
||||
|
} |
@ -0,0 +1,64 @@ |
|||||
|
using System; |
||||
|
|
||||
|
namespace CellularManagement.Application.Features.Devices.Queries.GetDevices; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 设备数据传输对象
|
||||
|
/// </summary>
|
||||
|
public class DeviceDto |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 设备ID
|
||||
|
/// </summary>
|
||||
|
public string DeviceId { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 设备名称
|
||||
|
/// </summary>
|
||||
|
public string DeviceName { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 协议版本
|
||||
|
/// </summary>
|
||||
|
public string ProtocolVersion { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 支持的频段
|
||||
|
/// </summary>
|
||||
|
public string SupportBands { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 硬件版本
|
||||
|
/// </summary>
|
||||
|
public string HardwareVersion { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 序列号
|
||||
|
/// </summary>
|
||||
|
public string SerialNumber { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 备注
|
||||
|
/// </summary>
|
||||
|
public string Comment { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// IP地址
|
||||
|
/// </summary>
|
||||
|
public string IPAddress { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 是否禁用
|
||||
|
/// </summary>
|
||||
|
public bool IsDisabled { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 创建时间
|
||||
|
/// </summary>
|
||||
|
public DateTime CreatedAt { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 更新时间
|
||||
|
/// </summary>
|
||||
|
public DateTime UpdatedAt { get; set; } |
||||
|
} |
@ -0,0 +1,34 @@ |
|||||
|
using CellularManagement.Domain.Common; |
||||
|
using MediatR; |
||||
|
using System.ComponentModel.DataAnnotations; |
||||
|
|
||||
|
namespace CellularManagement.Application.Features.Devices.Queries.GetDevices; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 获取设备列表查询
|
||||
|
/// </summary>
|
||||
|
public class GetDevicesQuery : IRequest<OperationResult<GetDevicesResponse>> |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 页码,从1开始
|
||||
|
/// </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, ErrorMessage = "搜索关键词不能超过100个字符")] |
||||
|
public string? SearchTerm { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 是否禁用
|
||||
|
/// </summary>
|
||||
|
public bool? IsDisabled { get; set; } |
||||
|
} |
@ -0,0 +1,92 @@ |
|||||
|
using MediatR; |
||||
|
using Microsoft.Extensions.Logging; |
||||
|
using CellularManagement.Domain.Common; |
||||
|
using CellularManagement.Domain.Entities; |
||||
|
using CellularManagement.Domain.Repositories; |
||||
|
using System.ComponentModel.DataAnnotations; |
||||
|
using System.Linq; |
||||
|
|
||||
|
namespace CellularManagement.Application.Features.Devices.Queries.GetDevices; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 获取设备列表查询处理器
|
||||
|
/// </summary>
|
||||
|
public class GetDevicesQueryHandler : IRequestHandler<GetDevicesQuery, OperationResult<GetDevicesResponse>> |
||||
|
{ |
||||
|
private readonly IDeviceRepository _deviceRepository; |
||||
|
private readonly ILogger<GetDevicesQueryHandler> _logger; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 初始化查询处理器
|
||||
|
/// </summary>
|
||||
|
public GetDevicesQueryHandler( |
||||
|
IDeviceRepository deviceRepository, |
||||
|
ILogger<GetDevicesQueryHandler> logger) |
||||
|
{ |
||||
|
_deviceRepository = deviceRepository; |
||||
|
_logger = logger; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 处理获取设备列表查询
|
||||
|
/// </summary>
|
||||
|
public async Task<OperationResult<GetDevicesResponse>> Handle(GetDevicesQuery 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("Invalid request parameters: {Errors}", string.Join(", ", errorMessages)); |
||||
|
return OperationResult<GetDevicesResponse>.CreateFailure(errorMessages); |
||||
|
} |
||||
|
|
||||
|
_logger.LogInformation("Getting devices with page: {PageNumber}, size: {PageSize}, search: {SearchTerm}, isDisabled: {IsDisabled}", |
||||
|
request.PageNumber, request.PageSize, request.SearchTerm, request.IsDisabled); |
||||
|
|
||||
|
// 获取分页数据
|
||||
|
var (totalCount, items) = await _deviceRepository.GetPagedAsync( |
||||
|
request.PageNumber, |
||||
|
request.PageSize, |
||||
|
request.SearchTerm, |
||||
|
request.IsDisabled, |
||||
|
cancellationToken); |
||||
|
|
||||
|
// 构建响应
|
||||
|
var response = new GetDevicesResponse |
||||
|
{ |
||||
|
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(d => new DeviceDto |
||||
|
{ |
||||
|
DeviceId = d.DeviceID, |
||||
|
DeviceName = d.DeviceName, |
||||
|
ProtocolVersion = d.ProtocolVersion, |
||||
|
SupportBands = d.SupportBands, |
||||
|
HardwareVersion = d.HardwareVersion, |
||||
|
SerialNumber = d.SerialNumber, |
||||
|
Comment = d.Comment, |
||||
|
IPAddress = d.IPAddress, |
||||
|
IsDisabled = d.IsDisabled, |
||||
|
CreatedAt = d.CreatedAt, |
||||
|
UpdatedAt = d.UpdatedAt |
||||
|
}).ToList() |
||||
|
}; |
||||
|
|
||||
|
_logger.LogInformation("Successfully retrieved {Count} devices", items.Count()); |
||||
|
return OperationResult<GetDevicesResponse>.CreateSuccess(response); |
||||
|
} |
||||
|
catch (Exception ex) |
||||
|
{ |
||||
|
_logger.LogError(ex, "Error getting devices"); |
||||
|
return OperationResult<GetDevicesResponse>.CreateFailure($"获取设备列表时发生错误: {ex.Message}"); |
||||
|
} |
||||
|
} |
||||
|
} |
@ -0,0 +1,44 @@ |
|||||
|
using System.Collections.Generic; |
||||
|
|
||||
|
namespace CellularManagement.Application.Features.Devices.Queries.GetDevices; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 设备列表响应
|
||||
|
/// </summary>
|
||||
|
public class GetDevicesResponse |
||||
|
{ |
||||
|
/// <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<DeviceDto> Items { get; set; } = new(); |
||||
|
} |
@ -0,0 +1,19 @@ |
|||||
|
using System; |
||||
|
|
||||
|
namespace CellularManagement.Domain.Entities |
||||
|
{ |
||||
|
public class Device |
||||
|
{ |
||||
|
public string DeviceID { get; set; } |
||||
|
public string DeviceName { get; set; } |
||||
|
public string ProtocolVersion { get; set; } |
||||
|
public string SupportBands { get; set; } |
||||
|
public string HardwareVersion { get; set; } |
||||
|
public string SerialNumber { get; set; } |
||||
|
public string Comment { get; set; } |
||||
|
public DateTime CreatedAt { get; set; } |
||||
|
public DateTime UpdatedAt { get; set; } |
||||
|
public bool IsDisabled { get; set; } |
||||
|
public string IPAddress { get; set; } |
||||
|
} |
||||
|
} |
@ -0,0 +1,145 @@ |
|||||
|
using CellularManagement.Domain.Entities; |
||||
|
|
||||
|
namespace CellularManagement.Domain.Repositories; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 设备命令仓储接口
|
||||
|
/// 负责设备实体的写入操作
|
||||
|
/// </summary>
|
||||
|
public interface IDeviceCommandRepository : ICommandRepository<Device> |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 创建设备
|
||||
|
/// </summary>
|
||||
|
/// <param name="device">设备实体</param>
|
||||
|
/// <param name="cancellationToken">取消令牌</param>
|
||||
|
/// <returns>创建后的设备实体</returns>
|
||||
|
Task<Device> CreateAsync(Device device, CancellationToken cancellationToken = default); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 批量创建设备
|
||||
|
/// </summary>
|
||||
|
/// <param name="devices">设备实体集合</param>
|
||||
|
/// <param name="cancellationToken">取消令牌</param>
|
||||
|
/// <returns>创建后的设备实体集合</returns>
|
||||
|
Task<IEnumerable<Device>> CreateRangeAsync(IEnumerable<Device> devices, CancellationToken cancellationToken = default); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 更新设备
|
||||
|
/// </summary>
|
||||
|
/// <param name="device">设备实体</param>
|
||||
|
/// <param name="cancellationToken">取消令牌</param>
|
||||
|
/// <returns>是否更新成功</returns>
|
||||
|
Task<bool> UpdateAsync(Device device, CancellationToken cancellationToken = default); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 批量更新设备
|
||||
|
/// </summary>
|
||||
|
/// <param name="devices">设备实体集合</param>
|
||||
|
/// <param name="cancellationToken">取消令牌</param>
|
||||
|
/// <returns>是否更新成功</returns>
|
||||
|
Task<bool> UpdateRangeAsync(IEnumerable<Device> devices, CancellationToken cancellationToken = default); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 删除设备
|
||||
|
/// </summary>
|
||||
|
/// <param name="deviceId">设备ID</param>
|
||||
|
/// <param name="cancellationToken">取消令牌</param>
|
||||
|
/// <returns>是否删除成功</returns>
|
||||
|
Task<bool> DeleteAsync(string deviceId, CancellationToken cancellationToken = default); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 批量删除设备
|
||||
|
/// </summary>
|
||||
|
/// <param name="deviceIds">设备ID集合</param>
|
||||
|
/// <param name="cancellationToken">取消令牌</param>
|
||||
|
/// <returns>删除的设备数量</returns>
|
||||
|
Task<int> DeleteRangeAsync(IEnumerable<string> deviceIds, CancellationToken cancellationToken = default); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 启用设备
|
||||
|
/// </summary>
|
||||
|
/// <param name="deviceId">设备ID</param>
|
||||
|
/// <param name="cancellationToken">取消令牌</param>
|
||||
|
/// <returns>是否启用成功</returns>
|
||||
|
Task<bool> EnableAsync(string deviceId, CancellationToken cancellationToken = default); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 禁用设备
|
||||
|
/// </summary>
|
||||
|
/// <param name="deviceId">设备ID</param>
|
||||
|
/// <param name="cancellationToken">取消令牌</param>
|
||||
|
/// <returns>是否禁用成功</returns>
|
||||
|
Task<bool> DisableAsync(string deviceId, CancellationToken cancellationToken = default); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 批量启用设备
|
||||
|
/// </summary>
|
||||
|
/// <param name="deviceIds">设备ID集合</param>
|
||||
|
/// <param name="cancellationToken">取消令牌</param>
|
||||
|
/// <returns>启用的设备数量</returns>
|
||||
|
Task<int> EnableRangeAsync(IEnumerable<string> deviceIds, CancellationToken cancellationToken = default); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 批量禁用设备
|
||||
|
/// </summary>
|
||||
|
/// <param name="deviceIds">设备ID集合</param>
|
||||
|
/// <param name="cancellationToken">取消令牌</param>
|
||||
|
/// <returns>禁用的设备数量</returns>
|
||||
|
Task<int> DisableRangeAsync(IEnumerable<string> deviceIds, CancellationToken cancellationToken = default); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 设备查询仓储接口
|
||||
|
/// 负责设备实体的读取操作
|
||||
|
/// </summary>
|
||||
|
public interface IDeviceQueryRepository |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 根据序列号获取设备
|
||||
|
/// </summary>
|
||||
|
Task<Device?> GetBySerialNumberAsync(string serialNumber, CancellationToken cancellationToken = default); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 检查序列号是否存在
|
||||
|
/// </summary>
|
||||
|
Task<bool> ExistsBySerialNumberAsync(string serialNumber, string? excludeDeviceId = null, CancellationToken cancellationToken = default); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 分页查询设备列表
|
||||
|
/// </summary>
|
||||
|
Task<(int TotalCount, IEnumerable<Device> Items)> GetPagedAsync( |
||||
|
int pageNumber, |
||||
|
int pageSize, |
||||
|
string? searchTerm = null, |
||||
|
bool? isDisabled = null, |
||||
|
CancellationToken cancellationToken = default); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 获取所有启用的设备
|
||||
|
/// </summary>
|
||||
|
Task<IEnumerable<Device>> GetEnabledDevicesAsync(CancellationToken cancellationToken = default); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 获取所有禁用的设备
|
||||
|
/// </summary>
|
||||
|
Task<IEnumerable<Device>> GetDisabledDevicesAsync(CancellationToken cancellationToken = default); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 根据IP地址获取设备
|
||||
|
/// </summary>
|
||||
|
Task<Device?> GetByIPAddressAsync(string ipAddress, CancellationToken cancellationToken = default); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 根据IP地址获取设备
|
||||
|
/// </summary>
|
||||
|
Task<Device?> GetByIdAsync(string id, CancellationToken cancellationToken = default); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 设备仓储接口
|
||||
|
/// 组合命令和查询仓储接口
|
||||
|
/// </summary>
|
||||
|
public interface IDeviceRepository : IDeviceCommandRepository, IDeviceQueryRepository |
||||
|
{ |
||||
|
} |
@ -0,0 +1,370 @@ |
|||||
|
using CellularManagement.Domain.Entities; |
||||
|
using CellularManagement.Domain.Repositories; |
||||
|
using CellularManagement.Infrastructure.Context; |
||||
|
using Microsoft.EntityFrameworkCore; |
||||
|
using Microsoft.Extensions.Logging; |
||||
|
|
||||
|
namespace CellularManagement.Infrastructure.Repositories |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 设备仓储实现类
|
||||
|
/// </summary>
|
||||
|
public class DeviceRepository : CommandRepository<Device>, IDeviceRepository |
||||
|
{ |
||||
|
private readonly AppDbContext _context; |
||||
|
private readonly ILogger<DeviceRepository> _logger; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 初始化仓储
|
||||
|
/// </summary>
|
||||
|
public DeviceRepository( |
||||
|
AppDbContext context, |
||||
|
IUnitOfWork unitOfWork, |
||||
|
ILogger<DeviceRepository> logger) |
||||
|
: base(context, unitOfWork, logger) |
||||
|
{ |
||||
|
_context = context; |
||||
|
_logger = logger; |
||||
|
} |
||||
|
|
||||
|
#region IDeviceQueryRepository 实现
|
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 根据ID获取设备
|
||||
|
/// </summary>
|
||||
|
public async Task<Device?> GetByIdAsync(string id, CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
_logger.LogInformation("Getting device by ID: {DeviceId}", id); |
||||
|
return await _context.Devices |
||||
|
.AsNoTracking() // 使用 AsNoTracking 提高查询性能
|
||||
|
.FirstOrDefaultAsync(d => d.DeviceID == id, cancellationToken); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 根据序列号获取设备
|
||||
|
/// </summary>
|
||||
|
public async Task<Device?> GetBySerialNumberAsync(string serialNumber, CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
_logger.LogInformation("Getting device by serial number: {SerialNumber}", serialNumber); |
||||
|
return await _context.Devices |
||||
|
.AsNoTracking() |
||||
|
.FirstOrDefaultAsync(d => d.SerialNumber == serialNumber, cancellationToken); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 检查序列号是否存在
|
||||
|
/// </summary>
|
||||
|
public async Task<bool> ExistsBySerialNumberAsync(string serialNumber, string? excludeDeviceId = null, CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
_logger.LogInformation("Checking if device exists with serial number: {SerialNumber}", serialNumber); |
||||
|
|
||||
|
var query = _context.Devices.AsNoTracking().Where(d => d.SerialNumber == serialNumber); |
||||
|
|
||||
|
if (!string.IsNullOrEmpty(excludeDeviceId)) |
||||
|
{ |
||||
|
query = query.Where(d => d.DeviceID != excludeDeviceId); |
||||
|
} |
||||
|
|
||||
|
return await query.AnyAsync(cancellationToken); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 分页查询设备列表
|
||||
|
/// </summary>
|
||||
|
public async Task<(int TotalCount, IEnumerable<Device> Items)> GetPagedAsync( |
||||
|
int pageNumber, |
||||
|
int pageSize, |
||||
|
string? searchTerm = null, |
||||
|
bool? isDisabled = null, |
||||
|
CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
_logger.LogInformation("Getting paged devices. Page: {PageNumber}, Size: {PageSize}", pageNumber, pageSize); |
||||
|
|
||||
|
var query = _context.Devices.AsNoTracking().AsQueryable(); |
||||
|
|
||||
|
if (!string.IsNullOrEmpty(searchTerm)) |
||||
|
{ |
||||
|
query = query.Where(d => |
||||
|
d.DeviceName.Contains(searchTerm) || |
||||
|
d.SerialNumber.Contains(searchTerm) || |
||||
|
d.IPAddress.Contains(searchTerm)); |
||||
|
} |
||||
|
|
||||
|
if (isDisabled.HasValue) |
||||
|
{ |
||||
|
query = query.Where(d => d.IsDisabled == isDisabled.Value); |
||||
|
} |
||||
|
|
||||
|
var totalCount = await query.CountAsync(cancellationToken); |
||||
|
var items = await query |
||||
|
.Skip((pageNumber - 1) * pageSize) |
||||
|
.Take(pageSize) |
||||
|
.ToListAsync(cancellationToken); |
||||
|
|
||||
|
return (totalCount, items); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 获取所有启用的设备
|
||||
|
/// </summary>
|
||||
|
public async Task<IEnumerable<Device>> GetEnabledDevicesAsync(CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
_logger.LogInformation("Getting all enabled devices"); |
||||
|
return await _context.Devices |
||||
|
.AsNoTracking() |
||||
|
.Where(d => !d.IsDisabled) |
||||
|
.ToListAsync(cancellationToken); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 获取所有禁用的设备
|
||||
|
/// </summary>
|
||||
|
public async Task<IEnumerable<Device>> GetDisabledDevicesAsync(CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
_logger.LogInformation("Getting all disabled devices"); |
||||
|
return await _context.Devices |
||||
|
.AsNoTracking() |
||||
|
.Where(d => d.IsDisabled) |
||||
|
.ToListAsync(cancellationToken); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 根据IP地址获取设备
|
||||
|
/// </summary>
|
||||
|
public async Task<Device?> GetByIPAddressAsync(string ipAddress, CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
_logger.LogInformation("Getting device by IP address: {IPAddress}", ipAddress); |
||||
|
return await _context.Devices |
||||
|
.AsNoTracking() |
||||
|
.FirstOrDefaultAsync(d => d.IPAddress == ipAddress, cancellationToken); |
||||
|
} |
||||
|
#endregion
|
||||
|
|
||||
|
#region IDeviceCommandRepository 实现
|
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 创建设备
|
||||
|
/// </summary>
|
||||
|
public async Task<Device> CreateAsync(Device device, CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
_logger.LogInformation("Creating new device with serial number: {SerialNumber}", device.SerialNumber); |
||||
|
|
||||
|
// 确保实体有ID和时间戳
|
||||
|
if (string.IsNullOrEmpty(device.DeviceID)) |
||||
|
{ |
||||
|
device.DeviceID = Guid.NewGuid().ToString(); |
||||
|
} |
||||
|
device.CreatedAt = DateTime.UtcNow; |
||||
|
device.UpdatedAt = DateTime.UtcNow; |
||||
|
|
||||
|
return await AddAsync(device, cancellationToken); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 批量创建设备
|
||||
|
/// </summary>
|
||||
|
public async Task<IEnumerable<Device>> CreateRangeAsync(IEnumerable<Device> devices, CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
_logger.LogInformation("Creating {Count} devices in batch", devices.Count()); |
||||
|
|
||||
|
// 确保所有实体都有ID和时间戳
|
||||
|
foreach (var device in devices) |
||||
|
{ |
||||
|
if (string.IsNullOrEmpty(device.DeviceID)) |
||||
|
{ |
||||
|
device.DeviceID = Guid.NewGuid().ToString(); |
||||
|
} |
||||
|
device.CreatedAt = DateTime.UtcNow; |
||||
|
device.UpdatedAt = DateTime.UtcNow; |
||||
|
} |
||||
|
|
||||
|
return await AddRangeAsync(devices, cancellationToken); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 更新设备
|
||||
|
/// </summary>
|
||||
|
public async Task<bool> UpdateAsync(Device device, CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
_logger.LogInformation("Updating device with ID: {DeviceId}", device.DeviceID); |
||||
|
|
||||
|
var existingDevice = await _context.Devices.FindAsync(new object[] { device.DeviceID }, cancellationToken); |
||||
|
if (existingDevice == null) |
||||
|
{ |
||||
|
_logger.LogWarning("Device not found with ID: {DeviceId}", device.DeviceID); |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
// 更新实体属性
|
||||
|
existingDevice.DeviceName = device.DeviceName; |
||||
|
existingDevice.ProtocolVersion = device.ProtocolVersion; |
||||
|
existingDevice.SupportBands = device.SupportBands; |
||||
|
existingDevice.HardwareVersion = device.HardwareVersion; |
||||
|
existingDevice.SerialNumber = device.SerialNumber; |
||||
|
existingDevice.Comment = device.Comment; |
||||
|
existingDevice.IsDisabled = device.IsDisabled; |
||||
|
existingDevice.IPAddress = device.IPAddress; |
||||
|
existingDevice.UpdatedAt = DateTime.UtcNow; |
||||
|
|
||||
|
Update(existingDevice); |
||||
|
await _context.SaveChangesAsync(cancellationToken); |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 批量更新设备
|
||||
|
/// </summary>
|
||||
|
public async Task<bool> UpdateRangeAsync(IEnumerable<Device> devices, CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
_logger.LogInformation("Updating {Count} devices in batch", devices.Count()); |
||||
|
|
||||
|
var deviceIds = devices.Select(d => d.DeviceID).ToList(); |
||||
|
var existingDevices = await _context.Devices |
||||
|
.Where(d => deviceIds.Contains(d.DeviceID)) |
||||
|
.ToListAsync(cancellationToken); |
||||
|
|
||||
|
if (!existingDevices.Any()) |
||||
|
{ |
||||
|
_logger.LogWarning("No devices found for batch update"); |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
// 更新每个实体的属性
|
||||
|
foreach (var existingDevice in existingDevices) |
||||
|
{ |
||||
|
var updateInfo = devices.First(d => d.DeviceID == existingDevice.DeviceID); |
||||
|
existingDevice.DeviceName = updateInfo.DeviceName; |
||||
|
existingDevice.ProtocolVersion = updateInfo.ProtocolVersion; |
||||
|
existingDevice.SupportBands = updateInfo.SupportBands; |
||||
|
existingDevice.HardwareVersion = updateInfo.HardwareVersion; |
||||
|
existingDevice.SerialNumber = updateInfo.SerialNumber; |
||||
|
existingDevice.Comment = updateInfo.Comment; |
||||
|
existingDevice.IsDisabled = updateInfo.IsDisabled; |
||||
|
existingDevice.IPAddress = updateInfo.IPAddress; |
||||
|
existingDevice.UpdatedAt = DateTime.UtcNow; |
||||
|
} |
||||
|
|
||||
|
UpdateRange(existingDevices); |
||||
|
await _context.SaveChangesAsync(cancellationToken); |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 删除设备
|
||||
|
/// </summary>
|
||||
|
public async Task<bool> DeleteAsync(string deviceId, CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
_logger.LogInformation("Deleting device with ID: {DeviceId}", deviceId); |
||||
|
return await DeleteByIdAsync(deviceId, cancellationToken); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 批量删除设备
|
||||
|
/// </summary>
|
||||
|
public async Task<int> DeleteRangeAsync(IEnumerable<string> deviceIds, CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
_logger.LogInformation("Deleting {Count} devices in batch", deviceIds.Count()); |
||||
|
return await DeleteWhereAsync(d => deviceIds.Contains(d.DeviceID), cancellationToken); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 启用设备
|
||||
|
/// </summary>
|
||||
|
public async Task<bool> EnableAsync(string deviceId, CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
_logger.LogInformation("Enabling device with ID: {DeviceId}", deviceId); |
||||
|
|
||||
|
var device = await _context.Devices.FindAsync(new object[] { deviceId }, cancellationToken); |
||||
|
if (device == null) |
||||
|
{ |
||||
|
_logger.LogWarning("Device not found with ID: {DeviceId}", deviceId); |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
device.IsDisabled = false; |
||||
|
device.UpdatedAt = DateTime.UtcNow; |
||||
|
Update(device); |
||||
|
await _context.SaveChangesAsync(cancellationToken); |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 禁用设备
|
||||
|
/// </summary>
|
||||
|
public async Task<bool> DisableAsync(string deviceId, CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
_logger.LogInformation("Disabling device with ID: {DeviceId}", deviceId); |
||||
|
|
||||
|
var device = await _context.Devices.FindAsync(new object[] { deviceId }, cancellationToken); |
||||
|
if (device == null) |
||||
|
{ |
||||
|
_logger.LogWarning("Device not found with ID: {DeviceId}", deviceId); |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
device.IsDisabled = true; |
||||
|
device.UpdatedAt = DateTime.UtcNow; |
||||
|
Update(device); |
||||
|
await _context.SaveChangesAsync(cancellationToken); |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 批量启用设备
|
||||
|
/// </summary>
|
||||
|
public async Task<int> EnableRangeAsync(IEnumerable<string> deviceIds, CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
_logger.LogInformation("Enabling {Count} devices in batch", deviceIds.Count()); |
||||
|
|
||||
|
var devices = await _context.Devices |
||||
|
.Where(d => deviceIds.Contains(d.DeviceID)) |
||||
|
.ToListAsync(cancellationToken); |
||||
|
|
||||
|
if (!devices.Any()) |
||||
|
{ |
||||
|
_logger.LogWarning("No devices found for batch enable"); |
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
foreach (var device in devices) |
||||
|
{ |
||||
|
device.IsDisabled = false; |
||||
|
device.UpdatedAt = DateTime.UtcNow; |
||||
|
} |
||||
|
|
||||
|
UpdateRange(devices); |
||||
|
await _context.SaveChangesAsync(cancellationToken); |
||||
|
return devices.Count; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 批量禁用设备
|
||||
|
/// </summary>
|
||||
|
public async Task<int> DisableRangeAsync(IEnumerable<string> deviceIds, CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
_logger.LogInformation("Disabling {Count} devices in batch", deviceIds.Count()); |
||||
|
|
||||
|
var devices = await _context.Devices |
||||
|
.Where(d => deviceIds.Contains(d.DeviceID)) |
||||
|
.ToListAsync(cancellationToken); |
||||
|
|
||||
|
if (!devices.Any()) |
||||
|
{ |
||||
|
_logger.LogWarning("No devices found for batch disable"); |
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
foreach (var device in devices) |
||||
|
{ |
||||
|
device.IsDisabled = true; |
||||
|
device.UpdatedAt = DateTime.UtcNow; |
||||
|
} |
||||
|
|
||||
|
UpdateRange(devices); |
||||
|
await _context.SaveChangesAsync(cancellationToken); |
||||
|
return devices.Count; |
||||
|
} |
||||
|
|
||||
|
#endregion
|
||||
|
} |
||||
|
} |
@ -0,0 +1,75 @@ |
|||||
|
using CellularManagement.Application.Features.Devices.Commands; |
||||
|
using CellularManagement.Application.Features.Devices.Commands.CreateDevice; |
||||
|
using CellularManagement.Application.Features.Devices.Commands.DeleteDevice; |
||||
|
using CellularManagement.Application.Features.Devices.Commands.UpdateDevice; |
||||
|
using CellularManagement.Application.Features.Devices.Queries.GetDeviceById; |
||||
|
using CellularManagement.Application.Features.Devices.Queries.GetDevices; |
||||
|
using CellularManagement.Domain.Common; |
||||
|
using CellularManagement.Domain.Entities; |
||||
|
using CellularManagement.Presentation.Abstractions; |
||||
|
using MediatR; |
||||
|
using Microsoft.AspNetCore.Authorization; |
||||
|
using Microsoft.AspNetCore.Mvc; |
||||
|
|
||||
|
namespace CellularManagement.Presentation.Controllers |
||||
|
{ |
||||
|
[Route("api/devices")] |
||||
|
[ApiController] |
||||
|
[Authorize] |
||||
|
public class DevicesController : ApiController |
||||
|
{ |
||||
|
public DevicesController(IMediator mediator) : base(mediator) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
[HttpGet] |
||||
|
public async Task<ActionResult<OperationResult<(int TotalCount, IEnumerable<Device> Items)>>> GetAll([FromQuery] GetDevicesQuery query) |
||||
|
{ |
||||
|
var result = await mediator.Send(query); |
||||
|
return Ok(result); |
||||
|
} |
||||
|
|
||||
|
[HttpGet("{id}")] |
||||
|
public async Task<ActionResult<OperationResult<Device>>> GetById(string id) |
||||
|
{ |
||||
|
var device = await mediator.Send(new GetDeviceByIdQuery(id)); |
||||
|
if (device == null) |
||||
|
return NotFound(OperationResult<Device>.CreateFailure($"Device with ID {id} not found")); |
||||
|
|
||||
|
return Ok(device); |
||||
|
} |
||||
|
|
||||
|
[HttpPost] |
||||
|
public async Task<ActionResult<OperationResult<string>>> Create([FromBody] CreateDeviceCommand command) |
||||
|
{ |
||||
|
var deviceId = await mediator.Send(command); |
||||
|
return CreatedAtAction( |
||||
|
nameof(GetById), |
||||
|
new { id = deviceId }, |
||||
|
deviceId); |
||||
|
} |
||||
|
|
||||
|
[HttpPut("{id}")] |
||||
|
public async Task<ActionResult<OperationResult<bool>>> Update(string id, [FromBody] UpdateDeviceCommand command) |
||||
|
{ |
||||
|
if (id != command.DeviceID) |
||||
|
return BadRequest(OperationResult<bool>.CreateFailure("ID mismatch")); |
||||
|
|
||||
|
var result = await mediator.Send(command); |
||||
|
if (!result.IsSuccess) |
||||
|
return NotFound(OperationResult<bool>.CreateFailure($"Device with ID {id} not found")); |
||||
|
|
||||
|
return Ok(OperationResult<bool>.CreateSuccess("Device updated successfully", true)); |
||||
|
} |
||||
|
|
||||
|
[HttpDelete("{id}")] |
||||
|
public async Task<ActionResult<OperationResult<bool>>> Delete(string id) |
||||
|
{ |
||||
|
var result = await mediator.Send(new DeleteDeviceCommand(id)); |
||||
|
if (!result.IsSuccess) |
||||
|
return NotFound(OperationResult<bool>.CreateFailure($"Device with ID {id} not found")); |
||||
|
|
||||
|
return Ok(OperationResult<bool>.CreateSuccess("Device deleted successfully", true)); |
||||
|
} |
||||
|
} |
||||
|
} |
Loading…
Reference in new issue