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