Browse Source
- 添加NetworkConfig实体类,支持RAN、IMS、MME三种配置类型 - 实现网络配置的仓储接口和实现类 - 添加EF Core配置类,支持JSON字段存储和索引优化 - 实现完整的CQRS命令和查询处理器 - 创建NetworkConfigsController,提供RESTful API接口 - 添加详细的API文档和测试示例 - 优化现有仓储接口,移除未使用的方法 - 更新依赖注入配置 - 添加示例数据和README文档feature/x1-owen-debug
39 changed files with 2236 additions and 590 deletions
@ -0,0 +1,52 @@ |
|||
using CellularManagement.Domain.Common; |
|||
using MediatR; |
|||
using CellularManagement.Domain.Entities.Device; |
|||
using System.ComponentModel.DataAnnotations; |
|||
|
|||
namespace CellularManagement.Application.Features.NetworkConfigs.Commands.CreateNetworkConfig; |
|||
|
|||
/// <summary>
|
|||
/// 创建网络配置命令
|
|||
/// </summary>
|
|||
public class CreateNetworkConfigCommand : IRequest<OperationResult<CreateNetworkConfigResponse>> |
|||
{ |
|||
/// <summary>
|
|||
/// 配置类型
|
|||
/// </summary>
|
|||
public NetworkConfigType ConfigType { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 配置名称
|
|||
/// </summary>
|
|||
[Required] |
|||
[MaxLength(100)] |
|||
public string Name { get; set; } = null!; |
|||
|
|||
/// <summary>
|
|||
/// 配置索引(仅对IMS和MME类型有效)
|
|||
/// </summary>
|
|||
public int? ConfigIndex { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// PLMN字段(移动国家代码+移动网络代码)
|
|||
/// </summary>
|
|||
[MaxLength(10)] |
|||
public string? Plmn { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 配置内容(JSON格式)
|
|||
/// </summary>
|
|||
[Required] |
|||
public string ConfigContent { get; set; } = null!; |
|||
|
|||
/// <summary>
|
|||
/// 配置说明
|
|||
/// </summary>
|
|||
[MaxLength(500)] |
|||
public string? Description { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 是否禁用
|
|||
/// </summary>
|
|||
public bool IsDisabled { get; set; } = false; |
|||
} |
@ -0,0 +1,86 @@ |
|||
using CellularManagement.Domain.Common; |
|||
using MediatR; |
|||
using CellularManagement.Domain.Entities.Device; |
|||
using CellularManagement.Domain.Repositories.Device; |
|||
using CellularManagement.Domain.Services; |
|||
using Microsoft.Extensions.Logging; |
|||
|
|||
namespace CellularManagement.Application.Features.NetworkConfigs.Commands.CreateNetworkConfig; |
|||
|
|||
/// <summary>
|
|||
/// 创建网络配置命令处理器
|
|||
/// </summary>
|
|||
public class CreateNetworkConfigCommandHandler : IRequestHandler<CreateNetworkConfigCommand, OperationResult<CreateNetworkConfigResponse>> |
|||
{ |
|||
private readonly INetworkConfigRepository _networkConfigRepository; |
|||
private readonly ICurrentUserService _currentUserService; |
|||
|
|||
private readonly ILogger<CreateNetworkConfigCommandHandler> _logger; |
|||
|
|||
public CreateNetworkConfigCommandHandler( |
|||
INetworkConfigRepository networkConfigRepository, |
|||
ICurrentUserService currentUserService, |
|||
ILogger<CreateNetworkConfigCommandHandler> logger) |
|||
{ |
|||
_networkConfigRepository = networkConfigRepository; |
|||
_currentUserService = currentUserService; |
|||
_logger = logger; |
|||
} |
|||
|
|||
public async Task<OperationResult<CreateNetworkConfigResponse>> Handle(CreateNetworkConfigCommand request, CancellationToken cancellationToken) |
|||
{ |
|||
_logger.LogInformation("开始创建网络配置,配置名称: {Name}, 配置类型: {ConfigType}", request.Name, request.ConfigType); |
|||
|
|||
try |
|||
{ |
|||
// 检查配置名称是否已存在
|
|||
if (await _networkConfigRepository.NameExistsAsync(request.Name, cancellationToken)) |
|||
{ |
|||
_logger.LogWarning("配置名称已存在: {Name}", request.Name); |
|||
return OperationResult<CreateNetworkConfigResponse>.CreateFailure($"配置名称 '{request.Name}' 已存在"); |
|||
} |
|||
|
|||
// 获取当前用户
|
|||
var currentUser = _currentUserService.GetCurrentUserId(); |
|||
if (string.IsNullOrEmpty(currentUser)) |
|||
{ |
|||
_logger.LogWarning("用户未认证"); |
|||
return OperationResult<CreateNetworkConfigResponse>.CreateFailure("用户未认证"); |
|||
} |
|||
|
|||
// 创建网络配置
|
|||
var networkConfig = NetworkConfig.Create( |
|||
request.ConfigType, |
|||
request.Name, |
|||
request.ConfigContent, |
|||
currentUser, |
|||
request.ConfigIndex, |
|||
request.Plmn, |
|||
request.Description, |
|||
request.IsDisabled); |
|||
|
|||
// 保存到数据库
|
|||
await _networkConfigRepository.AddNetworkConfigAsync(networkConfig, cancellationToken); |
|||
|
|||
var response = new CreateNetworkConfigResponse |
|||
{ |
|||
NetworkConfigId = networkConfig.Id, |
|||
Name = networkConfig.Name, |
|||
ConfigType = (int)networkConfig.ConfigType |
|||
}; |
|||
|
|||
_logger.LogInformation("成功创建网络配置,配置ID: {NetworkConfigId}", response.NetworkConfigId); |
|||
return OperationResult<CreateNetworkConfigResponse>.CreateSuccess("网络配置创建成功", response); |
|||
} |
|||
catch (ArgumentException ex) |
|||
{ |
|||
_logger.LogWarning("创建网络配置参数错误: {Message}", ex.Message); |
|||
return OperationResult<CreateNetworkConfigResponse>.CreateFailure(ex.Message); |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
_logger.LogError(ex, "创建网络配置失败: {Message}", ex.Message); |
|||
return OperationResult<CreateNetworkConfigResponse>.CreateFailure($"创建网络配置失败: {ex.Message}"); |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,22 @@ |
|||
namespace CellularManagement.Application.Features.NetworkConfigs.Commands.CreateNetworkConfig; |
|||
|
|||
/// <summary>
|
|||
/// 创建网络配置响应
|
|||
/// </summary>
|
|||
public class CreateNetworkConfigResponse |
|||
{ |
|||
/// <summary>
|
|||
/// 配置ID
|
|||
/// </summary>
|
|||
public string NetworkConfigId { get; set; } = null!; |
|||
|
|||
/// <summary>
|
|||
/// 配置名称
|
|||
/// </summary>
|
|||
public string Name { get; set; } = null!; |
|||
|
|||
/// <summary>
|
|||
/// 配置类型
|
|||
/// </summary>
|
|||
public int ConfigType { get; set; } |
|||
} |
@ -0,0 +1,17 @@ |
|||
using CellularManagement.Domain.Common; |
|||
using MediatR; |
|||
using System.ComponentModel.DataAnnotations; |
|||
|
|||
namespace CellularManagement.Application.Features.NetworkConfigs.Commands.DeleteNetworkConfig; |
|||
|
|||
/// <summary>
|
|||
/// 删除网络配置命令
|
|||
/// </summary>
|
|||
public class DeleteNetworkConfigCommand : IRequest<OperationResult<bool>> |
|||
{ |
|||
/// <summary>
|
|||
/// 网络配置ID
|
|||
/// </summary>
|
|||
[Required] |
|||
public string NetworkConfigId { get; set; } = null!; |
|||
} |
@ -0,0 +1,50 @@ |
|||
using CellularManagement.Domain.Common; |
|||
using MediatR; |
|||
using CellularManagement.Domain.Repositories.Device; |
|||
using Microsoft.Extensions.Logging; |
|||
|
|||
namespace CellularManagement.Application.Features.NetworkConfigs.Commands.DeleteNetworkConfig; |
|||
|
|||
/// <summary>
|
|||
/// 删除网络配置命令处理器
|
|||
/// </summary>
|
|||
public class DeleteNetworkConfigCommandHandler : IRequestHandler<DeleteNetworkConfigCommand, OperationResult<bool>> |
|||
{ |
|||
private readonly INetworkConfigRepository _networkConfigRepository; |
|||
private readonly ILogger<DeleteNetworkConfigCommandHandler> _logger; |
|||
|
|||
public DeleteNetworkConfigCommandHandler( |
|||
INetworkConfigRepository networkConfigRepository, |
|||
ILogger<DeleteNetworkConfigCommandHandler> logger) |
|||
{ |
|||
_networkConfigRepository = networkConfigRepository; |
|||
_logger = logger; |
|||
} |
|||
|
|||
public async Task<OperationResult<bool>> Handle(DeleteNetworkConfigCommand request, CancellationToken cancellationToken) |
|||
{ |
|||
_logger.LogInformation("开始删除网络配置,配置ID: {NetworkConfigId}", request.NetworkConfigId); |
|||
|
|||
try |
|||
{ |
|||
// 检查配置是否存在
|
|||
var existingConfig = await _networkConfigRepository.GetNetworkConfigByIdAsync(request.NetworkConfigId, cancellationToken); |
|||
if (existingConfig == null) |
|||
{ |
|||
_logger.LogWarning("网络配置不存在,配置ID: {NetworkConfigId}", request.NetworkConfigId); |
|||
return OperationResult<bool>.CreateFailure("网络配置不存在"); |
|||
} |
|||
|
|||
// 删除网络配置
|
|||
await _networkConfigRepository.DeleteNetworkConfigAsync(request.NetworkConfigId, cancellationToken); |
|||
|
|||
_logger.LogInformation("成功删除网络配置,配置ID: {NetworkConfigId}", request.NetworkConfigId); |
|||
return OperationResult<bool>.CreateSuccess("网络配置删除成功", true); |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
_logger.LogError(ex, "删除网络配置失败,配置ID: {NetworkConfigId}, 错误: {Message}", request.NetworkConfigId, ex.Message); |
|||
return OperationResult<bool>.CreateFailure($"删除网络配置失败: {ex.Message}"); |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,53 @@ |
|||
using CellularManagement.Domain.Common; |
|||
using MediatR; |
|||
using CellularManagement.Domain.Entities.Device; |
|||
using System.ComponentModel.DataAnnotations; |
|||
|
|||
namespace CellularManagement.Application.Features.NetworkConfigs.Commands.UpdateNetworkConfig; |
|||
|
|||
/// <summary>
|
|||
/// 更新网络配置命令
|
|||
/// </summary>
|
|||
public class UpdateNetworkConfigCommand : IRequest<OperationResult<UpdateNetworkConfigResponse>> |
|||
{ |
|||
/// <summary>
|
|||
/// 网络配置ID
|
|||
/// </summary>
|
|||
[Required] |
|||
public string NetworkConfigId { get; set; } = null!; |
|||
|
|||
/// <summary>
|
|||
/// 配置名称
|
|||
/// </summary>
|
|||
[Required] |
|||
[MaxLength(100)] |
|||
public string Name { get; set; } = null!; |
|||
|
|||
/// <summary>
|
|||
/// 配置索引(仅对IMS和MME类型有效)
|
|||
/// </summary>
|
|||
public int? ConfigIndex { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// PLMN字段(移动国家代码+移动网络代码)
|
|||
/// </summary>
|
|||
[MaxLength(10)] |
|||
public string? Plmn { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 配置内容(JSON格式)
|
|||
/// </summary>
|
|||
[Required] |
|||
public string ConfigContent { get; set; } = null!; |
|||
|
|||
/// <summary>
|
|||
/// 配置说明
|
|||
/// </summary>
|
|||
[MaxLength(500)] |
|||
public string? Description { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 是否禁用
|
|||
/// </summary>
|
|||
public bool IsDisabled { get; set; } = false; |
|||
} |
@ -0,0 +1,92 @@ |
|||
using CellularManagement.Domain.Common; |
|||
using MediatR; |
|||
using CellularManagement.Domain.Entities.Device; |
|||
using CellularManagement.Domain.Repositories.Device; |
|||
using CellularManagement.Domain.Services; |
|||
using Microsoft.Extensions.Logging; |
|||
|
|||
namespace CellularManagement.Application.Features.NetworkConfigs.Commands.UpdateNetworkConfig; |
|||
|
|||
/// <summary>
|
|||
/// 更新网络配置命令处理器
|
|||
/// </summary>
|
|||
public class UpdateNetworkConfigCommandHandler : IRequestHandler<UpdateNetworkConfigCommand, OperationResult<UpdateNetworkConfigResponse>> |
|||
{ |
|||
private readonly INetworkConfigRepository _networkConfigRepository; |
|||
private readonly ICurrentUserService _currentUserService; |
|||
private readonly ILogger<UpdateNetworkConfigCommandHandler> _logger; |
|||
|
|||
public UpdateNetworkConfigCommandHandler( |
|||
INetworkConfigRepository networkConfigRepository, |
|||
ICurrentUserService currentUserService, |
|||
ILogger<UpdateNetworkConfigCommandHandler> logger) |
|||
{ |
|||
_networkConfigRepository = networkConfigRepository; |
|||
_currentUserService = currentUserService; |
|||
_logger = logger; |
|||
} |
|||
|
|||
public async Task<OperationResult<UpdateNetworkConfigResponse>> Handle(UpdateNetworkConfigCommand request, CancellationToken cancellationToken) |
|||
{ |
|||
_logger.LogInformation("开始更新网络配置,配置ID: {NetworkConfigId}", request.NetworkConfigId); |
|||
|
|||
try |
|||
{ |
|||
// 检查配置是否存在
|
|||
var existingConfig = await _networkConfigRepository.GetNetworkConfigByIdAsync(request.NetworkConfigId, cancellationToken); |
|||
if (existingConfig == null) |
|||
{ |
|||
_logger.LogWarning("网络配置不存在,配置ID: {NetworkConfigId}", request.NetworkConfigId); |
|||
return OperationResult<UpdateNetworkConfigResponse>.CreateFailure("网络配置不存在"); |
|||
} |
|||
|
|||
// 检查配置名称是否已存在(排除当前配置)
|
|||
if (await _networkConfigRepository.NameExistsAsync(request.Name, request.NetworkConfigId, cancellationToken)) |
|||
{ |
|||
_logger.LogWarning("配置名称已存在: {Name}", request.Name); |
|||
return OperationResult<UpdateNetworkConfigResponse>.CreateFailure($"配置名称 '{request.Name}' 已存在"); |
|||
} |
|||
|
|||
// 获取当前用户
|
|||
var currentUser = _currentUserService.GetCurrentUserId(); |
|||
if (string.IsNullOrEmpty(currentUser)) |
|||
{ |
|||
_logger.LogWarning("用户未认证"); |
|||
return OperationResult<UpdateNetworkConfigResponse>.CreateFailure("用户未认证"); |
|||
} |
|||
|
|||
// 更新网络配置
|
|||
existingConfig.Update( |
|||
request.Name, |
|||
request.ConfigContent, |
|||
currentUser, |
|||
request.ConfigIndex, |
|||
request.Plmn, |
|||
request.Description, |
|||
request.IsDisabled); |
|||
|
|||
// 保存到数据库
|
|||
_networkConfigRepository.UpdateNetworkConfig(existingConfig); |
|||
|
|||
var response = new UpdateNetworkConfigResponse |
|||
{ |
|||
NetworkConfigId = existingConfig.Id, |
|||
Name = existingConfig.Name, |
|||
ConfigType = (int)existingConfig.ConfigType |
|||
}; |
|||
|
|||
_logger.LogInformation("成功更新网络配置,配置ID: {NetworkConfigId}", response.NetworkConfigId); |
|||
return OperationResult<UpdateNetworkConfigResponse>.CreateSuccess("网络配置更新成功", response); |
|||
} |
|||
catch (ArgumentException ex) |
|||
{ |
|||
_logger.LogWarning("更新网络配置参数错误: {Message}", ex.Message); |
|||
return OperationResult<UpdateNetworkConfigResponse>.CreateFailure(ex.Message); |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
_logger.LogError(ex, "更新网络配置失败: {Message}", ex.Message); |
|||
return OperationResult<UpdateNetworkConfigResponse>.CreateFailure($"更新网络配置失败: {ex.Message}"); |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,22 @@ |
|||
namespace CellularManagement.Application.Features.NetworkConfigs.Commands.UpdateNetworkConfig; |
|||
|
|||
/// <summary>
|
|||
/// 更新网络配置响应
|
|||
/// </summary>
|
|||
public class UpdateNetworkConfigResponse |
|||
{ |
|||
/// <summary>
|
|||
/// 配置ID
|
|||
/// </summary>
|
|||
public string NetworkConfigId { get; set; } = null!; |
|||
|
|||
/// <summary>
|
|||
/// 配置名称
|
|||
/// </summary>
|
|||
public string Name { get; set; } = null!; |
|||
|
|||
/// <summary>
|
|||
/// 配置类型
|
|||
/// </summary>
|
|||
public int ConfigType { get; set; } |
|||
} |
@ -0,0 +1,17 @@ |
|||
using CellularManagement.Domain.Common; |
|||
using MediatR; |
|||
using System.ComponentModel.DataAnnotations; |
|||
|
|||
namespace CellularManagement.Application.Features.NetworkConfigs.Queries.GetNetworkConfigById; |
|||
|
|||
/// <summary>
|
|||
/// 根据ID获取网络配置查询
|
|||
/// </summary>
|
|||
public class GetNetworkConfigByIdQuery : IRequest<OperationResult<GetNetworkConfigByIdResponse>> |
|||
{ |
|||
/// <summary>
|
|||
/// 网络配置ID
|
|||
/// </summary>
|
|||
[Required] |
|||
public string NetworkConfigId { get; set; } = null!; |
|||
} |
@ -0,0 +1,64 @@ |
|||
using CellularManagement.Domain.Common; |
|||
using MediatR; |
|||
using CellularManagement.Domain.Entities.Device; |
|||
using CellularManagement.Domain.Repositories.Device; |
|||
using Microsoft.Extensions.Logging; |
|||
|
|||
namespace CellularManagement.Application.Features.NetworkConfigs.Queries.GetNetworkConfigById; |
|||
|
|||
/// <summary>
|
|||
/// 根据ID获取网络配置查询处理器
|
|||
/// </summary>
|
|||
public class GetNetworkConfigByIdQueryHandler : IRequestHandler<GetNetworkConfigByIdQuery, OperationResult<GetNetworkConfigByIdResponse>> |
|||
{ |
|||
private readonly INetworkConfigRepository _networkConfigRepository; |
|||
private readonly ILogger<GetNetworkConfigByIdQueryHandler> _logger; |
|||
|
|||
public GetNetworkConfigByIdQueryHandler( |
|||
INetworkConfigRepository networkConfigRepository, |
|||
ILogger<GetNetworkConfigByIdQueryHandler> logger) |
|||
{ |
|||
_networkConfigRepository = networkConfigRepository; |
|||
_logger = logger; |
|||
} |
|||
|
|||
public async Task<OperationResult<GetNetworkConfigByIdResponse>> Handle(GetNetworkConfigByIdQuery request, CancellationToken cancellationToken) |
|||
{ |
|||
_logger.LogInformation("开始获取网络配置详情,配置ID: {NetworkConfigId}", request.NetworkConfigId); |
|||
|
|||
try |
|||
{ |
|||
var networkConfig = await _networkConfigRepository.GetNetworkConfigByIdAsync(request.NetworkConfigId, cancellationToken); |
|||
|
|||
if (networkConfig == null) |
|||
{ |
|||
_logger.LogWarning("网络配置不存在,配置ID: {NetworkConfigId}", request.NetworkConfigId); |
|||
return OperationResult<GetNetworkConfigByIdResponse>.CreateFailure("网络配置不存在"); |
|||
} |
|||
|
|||
var response = new GetNetworkConfigByIdResponse |
|||
{ |
|||
Id = networkConfig.Id, |
|||
ConfigType = networkConfig.ConfigType, |
|||
Name = networkConfig.Name, |
|||
ConfigIndex = networkConfig.ConfigIndex, |
|||
Plmn = networkConfig.Plmn, |
|||
ConfigContent = networkConfig.ConfigContent, |
|||
Description = networkConfig.Description, |
|||
IsDisabled = networkConfig.IsDisabled, |
|||
CreatedAt = networkConfig.CreatedAt, |
|||
UpdatedAt = networkConfig.UpdatedAt, |
|||
CreatedBy = networkConfig.CreatedBy, |
|||
UpdatedBy = networkConfig.UpdatedBy |
|||
}; |
|||
|
|||
_logger.LogInformation("成功获取网络配置详情,配置ID: {NetworkConfigId}", request.NetworkConfigId); |
|||
return OperationResult<GetNetworkConfigByIdResponse>.CreateSuccess("获取网络配置详情成功", response); |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
_logger.LogError(ex, "获取网络配置详情失败,配置ID: {NetworkConfigId}, 错误: {Message}", request.NetworkConfigId, ex.Message); |
|||
return OperationResult<GetNetworkConfigByIdResponse>.CreateFailure($"获取网络配置详情失败: {ex.Message}"); |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,69 @@ |
|||
using CellularManagement.Domain.Entities.Device; |
|||
|
|||
namespace CellularManagement.Application.Features.NetworkConfigs.Queries.GetNetworkConfigById; |
|||
|
|||
/// <summary>
|
|||
/// 根据ID获取网络配置响应
|
|||
/// </summary>
|
|||
public class GetNetworkConfigByIdResponse |
|||
{ |
|||
/// <summary>
|
|||
/// 配置ID
|
|||
/// </summary>
|
|||
public string Id { get; set; } = null!; |
|||
|
|||
/// <summary>
|
|||
/// 配置类型
|
|||
/// </summary>
|
|||
public NetworkConfigType ConfigType { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 配置名称
|
|||
/// </summary>
|
|||
public string Name { get; set; } = null!; |
|||
|
|||
/// <summary>
|
|||
/// 配置索引
|
|||
/// </summary>
|
|||
public int? ConfigIndex { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// PLMN字段
|
|||
/// </summary>
|
|||
public string? Plmn { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 配置内容
|
|||
/// </summary>
|
|||
public string ConfigContent { 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; } = null!; |
|||
} |
@ -0,0 +1,46 @@ |
|||
using CellularManagement.Domain.Common; |
|||
using MediatR; |
|||
using CellularManagement.Domain.Entities.Device; |
|||
using System.ComponentModel.DataAnnotations; |
|||
|
|||
namespace CellularManagement.Application.Features.NetworkConfigs.Queries.GetNetworkConfigs; |
|||
|
|||
/// <summary>
|
|||
/// 获取网络配置列表查询
|
|||
/// </summary>
|
|||
public class GetNetworkConfigsQuery : IRequest<OperationResult<GetNetworkConfigsResponse>> |
|||
{ |
|||
/// <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>
|
|||
public NetworkConfigType? ConfigType { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// PLMN(可选)
|
|||
/// </summary>
|
|||
[MaxLength(10)] |
|||
public string? Plmn { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 是否只获取启用的配置
|
|||
/// </summary>
|
|||
public bool? OnlyEnabled { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 搜索关键词
|
|||
/// </summary>
|
|||
[MaxLength(100)] |
|||
public string? Keyword { get; set; } |
|||
} |
@ -0,0 +1,107 @@ |
|||
using CellularManagement.Domain.Common; |
|||
using MediatR; |
|||
using CellularManagement.Domain.Entities.Device; |
|||
using CellularManagement.Domain.Repositories.Device; |
|||
using Microsoft.Extensions.Logging; |
|||
|
|||
namespace CellularManagement.Application.Features.NetworkConfigs.Queries.GetNetworkConfigs; |
|||
|
|||
/// <summary>
|
|||
/// 获取网络配置列表查询处理器
|
|||
/// </summary>
|
|||
public class GetNetworkConfigsQueryHandler : IRequestHandler<GetNetworkConfigsQuery, OperationResult<GetNetworkConfigsResponse>> |
|||
{ |
|||
private readonly INetworkConfigRepository _networkConfigRepository; |
|||
|
|||
private readonly ILogger<GetNetworkConfigsQueryHandler> _logger; |
|||
|
|||
public GetNetworkConfigsQueryHandler( |
|||
INetworkConfigRepository networkConfigRepository, |
|||
ILogger<GetNetworkConfigsQueryHandler> logger) |
|||
{ |
|||
_networkConfigRepository = networkConfigRepository; |
|||
_logger = logger; |
|||
} |
|||
|
|||
public async Task<OperationResult<GetNetworkConfigsResponse>> Handle(GetNetworkConfigsQuery request, CancellationToken cancellationToken) |
|||
{ |
|||
_logger.LogInformation("开始获取网络配置列表,页码: {PageNumber}, 每页数量: {PageSize}, 搜索关键词: {Keyword}, 配置类型: {ConfigType}, PLMN: {Plmn}, 是否启用: {OnlyEnabled}", |
|||
request.PageNumber, request.PageSize, request.Keyword, request.ConfigType, request.Plmn, request.OnlyEnabled); |
|||
|
|||
try |
|||
{ |
|||
IList<NetworkConfig> networkConfigs; |
|||
|
|||
// 根据查询条件获取配置
|
|||
if (!string.IsNullOrWhiteSpace(request.Keyword)) |
|||
{ |
|||
// 使用搜索功能
|
|||
networkConfigs = await _networkConfigRepository.SearchNetworkConfigsAsync( |
|||
request.Keyword, request.ConfigType, request.Plmn, cancellationToken); |
|||
} |
|||
else if (request.OnlyEnabled == true) |
|||
{ |
|||
networkConfigs = await _networkConfigRepository.GetEnabledNetworkConfigsAsync(cancellationToken); |
|||
} |
|||
else if (request.ConfigType.HasValue && !string.IsNullOrEmpty(request.Plmn)) |
|||
{ |
|||
networkConfigs = await _networkConfigRepository.GetNetworkConfigsByTypeAndPlmnAsync( |
|||
request.ConfigType.Value, request.Plmn, cancellationToken); |
|||
} |
|||
else if (request.ConfigType.HasValue) |
|||
{ |
|||
networkConfigs = await _networkConfigRepository.GetNetworkConfigsByTypeAsync( |
|||
request.ConfigType.Value, cancellationToken); |
|||
} |
|||
else if (!string.IsNullOrEmpty(request.Plmn)) |
|||
{ |
|||
networkConfigs = await _networkConfigRepository.GetNetworkConfigsByPlmnAsync( |
|||
request.Plmn, cancellationToken); |
|||
} |
|||
else |
|||
{ |
|||
networkConfigs = await _networkConfigRepository.GetAllNetworkConfigsAsync(cancellationToken); |
|||
} |
|||
|
|||
// 转换为DTO
|
|||
var networkConfigDtos = networkConfigs.Select(config => new NetworkConfigDto |
|||
{ |
|||
Id = config.Id, |
|||
ConfigType = config.ConfigType, |
|||
Name = config.Name, |
|||
ConfigIndex = config.ConfigIndex, |
|||
Plmn = config.Plmn, |
|||
ConfigContent = config.ConfigContent, |
|||
Description = config.Description, |
|||
IsDisabled = config.IsDisabled, |
|||
CreatedAt = config.CreatedAt, |
|||
UpdatedAt = config.UpdatedAt, |
|||
CreatedBy = config.CreatedBy, |
|||
UpdatedBy = config.UpdatedBy |
|||
}).ToList(); |
|||
|
|||
// 计算分页信息
|
|||
var totalCount = networkConfigDtos.Count; |
|||
var totalPages = (int)Math.Ceiling((double)totalCount / request.PageSize); |
|||
var skip = (request.PageNumber - 1) * request.PageSize; |
|||
var pagedConfigs = networkConfigDtos.Skip(skip).Take(request.PageSize).ToList(); |
|||
|
|||
var response = new GetNetworkConfigsResponse |
|||
{ |
|||
NetworkConfigs = pagedConfigs, |
|||
TotalCount = totalCount, |
|||
PageNumber = request.PageNumber, |
|||
PageSize = request.PageSize, |
|||
TotalPages = totalPages |
|||
}; |
|||
|
|||
_logger.LogInformation("成功获取网络配置列表,共 {Count} 条记录", totalCount); |
|||
return OperationResult<GetNetworkConfigsResponse>.CreateSuccess("获取网络配置列表成功", response); |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
_logger.LogError(ex, "获取网络配置列表失败: {Message}", ex.Message); |
|||
return OperationResult<GetNetworkConfigsResponse>.CreateFailure($"获取网络配置列表失败: {ex.Message}"); |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,100 @@ |
|||
using CellularManagement.Domain.Entities.Device; |
|||
|
|||
namespace CellularManagement.Application.Features.NetworkConfigs.Queries.GetNetworkConfigs; |
|||
|
|||
/// <summary>
|
|||
/// 网络配置信息
|
|||
/// </summary>
|
|||
public class NetworkConfigDto |
|||
{ |
|||
/// <summary>
|
|||
/// 配置ID
|
|||
/// </summary>
|
|||
public string Id { get; set; } = null!; |
|||
|
|||
/// <summary>
|
|||
/// 配置类型
|
|||
/// </summary>
|
|||
public NetworkConfigType ConfigType { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 配置名称
|
|||
/// </summary>
|
|||
public string Name { get; set; } = null!; |
|||
|
|||
/// <summary>
|
|||
/// 配置索引
|
|||
/// </summary>
|
|||
public int? ConfigIndex { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// PLMN字段
|
|||
/// </summary>
|
|||
public string? Plmn { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 配置内容
|
|||
/// </summary>
|
|||
public string ConfigContent { 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; } = null!; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 获取网络配置列表响应
|
|||
/// </summary>
|
|||
public class GetNetworkConfigsResponse |
|||
{ |
|||
/// <summary>
|
|||
/// 网络配置列表
|
|||
/// </summary>
|
|||
public List<NetworkConfigDto> NetworkConfigs { get; set; } = new(); |
|||
|
|||
/// <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; } |
|||
} |
@ -0,0 +1,204 @@ |
|||
using System.ComponentModel.DataAnnotations; |
|||
using CellularManagement.Domain.Entities.Common; |
|||
|
|||
namespace CellularManagement.Domain.Entities.Device; |
|||
|
|||
/// <summary>
|
|||
/// 网络配置类型枚举
|
|||
/// </summary>
|
|||
public enum NetworkConfigType |
|||
{ |
|||
/// <summary>
|
|||
/// RAN配置
|
|||
/// </summary>
|
|||
RAN = 1, |
|||
|
|||
/// <summary>
|
|||
/// IMS配置
|
|||
/// </summary>
|
|||
IMS = 2, |
|||
|
|||
/// <summary>
|
|||
/// MME配置
|
|||
/// </summary>
|
|||
MME = 3 |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 网络配置实体
|
|||
/// </summary>
|
|||
public class NetworkConfig : AuditableEntity |
|||
{ |
|||
private NetworkConfig() { } |
|||
|
|||
/// <summary>
|
|||
/// 配置类型
|
|||
/// </summary>
|
|||
[Required] |
|||
public NetworkConfigType ConfigType { get; private set; } |
|||
|
|||
/// <summary>
|
|||
/// 配置名称
|
|||
/// </summary>
|
|||
[Required] |
|||
[MaxLength(100)] |
|||
public string Name { get; private set; } = null!; |
|||
|
|||
/// <summary>
|
|||
/// 配置索引(仅对IMS和MME类型有效)
|
|||
/// </summary>
|
|||
public int? ConfigIndex { get; private set; } |
|||
|
|||
/// <summary>
|
|||
/// PLMN字段(移动国家代码+移动网络代码)
|
|||
/// </summary>
|
|||
[MaxLength(10)] |
|||
public string? Plmn { get; private set; } |
|||
|
|||
/// <summary>
|
|||
/// 配置内容(JSON格式)
|
|||
/// </summary>
|
|||
[Required] |
|||
public string ConfigContent { get; private set; } = null!; |
|||
|
|||
/// <summary>
|
|||
/// 配置说明
|
|||
/// </summary>
|
|||
[MaxLength(500)] |
|||
public string? Description { get; private set; } |
|||
|
|||
/// <summary>
|
|||
/// 是否禁用
|
|||
/// </summary>
|
|||
public bool IsDisabled { get; private set; } = false; |
|||
|
|||
/// <summary>
|
|||
/// 创建网络配置
|
|||
/// </summary>
|
|||
public static NetworkConfig Create( |
|||
NetworkConfigType configType, |
|||
string name, |
|||
string configContent, |
|||
string createdBy, |
|||
int? configIndex = null, |
|||
string? plmn = null, |
|||
string? description = null, |
|||
bool isDisabled = false) |
|||
{ |
|||
// 验证业务规则
|
|||
ValidateCreateParameters(configType, configIndex, plmn); |
|||
|
|||
var networkConfig = new NetworkConfig |
|||
{ |
|||
Id = Guid.NewGuid().ToString(), |
|||
ConfigType = configType, |
|||
Name = name, |
|||
ConfigIndex = configIndex, |
|||
Plmn = plmn, |
|||
ConfigContent = configContent, |
|||
Description = description, |
|||
IsDisabled = isDisabled, |
|||
CreatedAt = DateTime.UtcNow, |
|||
UpdatedAt = DateTime.UtcNow, |
|||
CreatedBy = createdBy, |
|||
UpdatedBy = createdBy |
|||
}; |
|||
|
|||
return networkConfig; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 更新网络配置
|
|||
/// </summary>
|
|||
public void Update( |
|||
string name, |
|||
string configContent, |
|||
string updatedBy, |
|||
int? configIndex = null, |
|||
string? plmn = null, |
|||
string? description = null, |
|||
bool isDisabled = false) |
|||
{ |
|||
// 验证业务规则
|
|||
ValidateUpdateParameters(ConfigType, configIndex, plmn); |
|||
|
|||
Name = name; |
|||
ConfigIndex = configIndex; |
|||
Plmn = plmn; |
|||
ConfigContent = configContent; |
|||
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>
|
|||
private static void ValidateCreateParameters(NetworkConfigType configType, int? configIndex, string? plmn) |
|||
{ |
|||
// 验证PLMN字段的必填性
|
|||
if (configType == NetworkConfigType.IMS || configType == NetworkConfigType.MME) |
|||
{ |
|||
if (string.IsNullOrWhiteSpace(plmn)) |
|||
{ |
|||
throw new ArgumentException($"PLMN字段对于{configType}类型是必填的"); |
|||
} |
|||
} |
|||
|
|||
// 验证配置索引
|
|||
if (configType == NetworkConfigType.RAN && configIndex.HasValue) |
|||
{ |
|||
throw new ArgumentException("RAN类型不支持配置索引"); |
|||
} |
|||
|
|||
if ((configType == NetworkConfigType.IMS || configType == NetworkConfigType.MME) && !configIndex.HasValue) |
|||
{ |
|||
throw new ArgumentException($"{configType}类型必须提供配置索引"); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 验证更新参数
|
|||
/// </summary>
|
|||
private static void ValidateUpdateParameters(NetworkConfigType configType, int? configIndex, string? plmn) |
|||
{ |
|||
// 验证PLMN字段的必填性
|
|||
if (configType == NetworkConfigType.IMS || configType == NetworkConfigType.MME) |
|||
{ |
|||
if (string.IsNullOrWhiteSpace(plmn)) |
|||
{ |
|||
throw new ArgumentException($"PLMN字段对于{configType}类型是必填的"); |
|||
} |
|||
} |
|||
|
|||
// 验证配置索引
|
|||
if (configType == NetworkConfigType.RAN && configIndex.HasValue) |
|||
{ |
|||
throw new ArgumentException("RAN类型不支持配置索引"); |
|||
} |
|||
|
|||
if ((configType == NetworkConfigType.IMS || configType == NetworkConfigType.MME) && !configIndex.HasValue) |
|||
{ |
|||
throw new ArgumentException($"{configType}类型必须提供配置索引"); |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,78 @@ |
|||
using CellularManagement.Domain.Entities.Device; |
|||
|
|||
namespace CellularManagement.Domain.Repositories.Device; |
|||
|
|||
/// <summary>
|
|||
/// 网络配置仓储接口
|
|||
/// </summary>
|
|||
public interface INetworkConfigRepository |
|||
{ |
|||
/// <summary>
|
|||
/// 根据ID获取网络配置
|
|||
/// </summary>
|
|||
Task<NetworkConfig?> GetNetworkConfigByIdAsync(string id, CancellationToken cancellationToken = default); |
|||
|
|||
/// <summary>
|
|||
/// 根据配置类型获取网络配置列表
|
|||
/// </summary>
|
|||
Task<IList<NetworkConfig>> GetNetworkConfigsByTypeAsync(NetworkConfigType configType, CancellationToken cancellationToken = default); |
|||
|
|||
/// <summary>
|
|||
/// 根据PLMN获取网络配置列表
|
|||
/// </summary>
|
|||
Task<IList<NetworkConfig>> GetNetworkConfigsByPlmnAsync(string plmn, CancellationToken cancellationToken = default); |
|||
|
|||
/// <summary>
|
|||
/// 根据配置类型和PLMN获取网络配置列表
|
|||
/// </summary>
|
|||
Task<IList<NetworkConfig>> GetNetworkConfigsByTypeAndPlmnAsync(NetworkConfigType configType, string plmn, CancellationToken cancellationToken = default); |
|||
|
|||
/// <summary>
|
|||
/// 获取启用的网络配置
|
|||
/// </summary>
|
|||
Task<IList<NetworkConfig>> GetEnabledNetworkConfigsAsync(CancellationToken cancellationToken = default); |
|||
|
|||
/// <summary>
|
|||
/// 获取所有网络配置
|
|||
/// </summary>
|
|||
Task<IList<NetworkConfig>> GetAllNetworkConfigsAsync(CancellationToken cancellationToken = default); |
|||
|
|||
/// <summary>
|
|||
/// 添加网络配置
|
|||
/// </summary>
|
|||
Task<NetworkConfig> AddNetworkConfigAsync(NetworkConfig networkConfig, CancellationToken cancellationToken = default); |
|||
|
|||
/// <summary>
|
|||
/// 更新网络配置
|
|||
/// </summary>
|
|||
void UpdateNetworkConfig(NetworkConfig networkConfig); |
|||
|
|||
/// <summary>
|
|||
/// 删除网络配置
|
|||
/// </summary>
|
|||
Task DeleteNetworkConfigAsync(string id, CancellationToken cancellationToken = default); |
|||
|
|||
/// <summary>
|
|||
/// 搜索网络配置
|
|||
/// </summary>
|
|||
Task<IList<NetworkConfig>> SearchNetworkConfigsAsync( |
|||
string? keyword, |
|||
NetworkConfigType? configType = null, |
|||
string? plmn = null, |
|||
CancellationToken cancellationToken = default); |
|||
|
|||
/// <summary>
|
|||
/// 检查网络配置是否存在
|
|||
/// </summary>
|
|||
Task<bool> ExistsAsync(string id, CancellationToken cancellationToken = default); |
|||
|
|||
/// <summary>
|
|||
/// 检查配置名称是否存在
|
|||
/// </summary>
|
|||
Task<bool> NameExistsAsync(string name, CancellationToken cancellationToken = default); |
|||
|
|||
/// <summary>
|
|||
/// 检查配置名称是否存在(排除指定ID)
|
|||
/// </summary>
|
|||
Task<bool> NameExistsAsync(string name, string excludeId, CancellationToken cancellationToken = default); |
|||
} |
@ -0,0 +1,238 @@ |
|||
{ |
|||
"networkConfigs": [ |
|||
{ |
|||
"configType": "RAN", |
|||
"name": "RAN_Config_Default", |
|||
"configIndex": null, |
|||
"plmn": null, |
|||
"configContent": { |
|||
"frequencyBands": ["B1", "B3", "B5", "B8"], |
|||
"bandwidth": "20MHz", |
|||
"powerControl": { |
|||
"maxPower": 43, |
|||
"minPower": 23, |
|||
"powerStep": 1 |
|||
}, |
|||
"antennaConfig": { |
|||
"antennaCount": 4, |
|||
"mimoMode": "4x4", |
|||
"beamforming": true |
|||
}, |
|||
"scheduling": { |
|||
"schedulerType": "ProportionalFair", |
|||
"qosEnabled": true, |
|||
"priorityLevels": 8 |
|||
} |
|||
}, |
|||
"description": "默认RAN配置,支持多频段和4x4 MIMO", |
|||
"isDisabled": false |
|||
}, |
|||
{ |
|||
"configType": "IMS", |
|||
"name": "IMS_Config_ChinaMobile", |
|||
"configIndex": 0, |
|||
"plmn": "46000", |
|||
"configContent": { |
|||
"pCscfServers": [ |
|||
{ |
|||
"address": "10.1.1.100", |
|||
"port": 5060, |
|||
"transport": "UDP" |
|||
}, |
|||
{ |
|||
"address": "10.1.1.101", |
|||
"port": 5060, |
|||
"transport": "UDP" |
|||
} |
|||
], |
|||
"sCscfServers": [ |
|||
{ |
|||
"address": "10.2.1.100", |
|||
"port": 5060, |
|||
"transport": "UDP" |
|||
} |
|||
], |
|||
"iCscfServers": [ |
|||
{ |
|||
"address": "10.3.1.100", |
|||
"port": 5060, |
|||
"transport": "UDP" |
|||
} |
|||
], |
|||
"hssServers": [ |
|||
{ |
|||
"address": "10.4.1.100", |
|||
"port": 3868, |
|||
"transport": "SCTP" |
|||
} |
|||
], |
|||
"dnsServers": [ |
|||
"8.8.8.8", |
|||
"114.114.114.114" |
|||
], |
|||
"qosSettings": { |
|||
"qci": 5, |
|||
"arp": { |
|||
"priority": 1, |
|||
"preemptionCapability": false, |
|||
"preemptionVulnerability": false |
|||
} |
|||
} |
|||
}, |
|||
"description": "中国移动IMS配置,包含完整的IMS核心网服务器配置", |
|||
"isDisabled": false |
|||
}, |
|||
{ |
|||
"configType": "IMS", |
|||
"name": "IMS_Config_ChinaUnicom", |
|||
"configIndex": 1, |
|||
"plmn": "46001", |
|||
"configContent": { |
|||
"pCscfServers": [ |
|||
{ |
|||
"address": "10.1.2.100", |
|||
"port": 5060, |
|||
"transport": "UDP" |
|||
} |
|||
], |
|||
"sCscfServers": [ |
|||
{ |
|||
"address": "10.2.2.100", |
|||
"port": 5060, |
|||
"transport": "UDP" |
|||
} |
|||
], |
|||
"iCscfServers": [ |
|||
{ |
|||
"address": "10.3.2.100", |
|||
"port": 5060, |
|||
"transport": "UDP" |
|||
} |
|||
], |
|||
"hssServers": [ |
|||
{ |
|||
"address": "10.4.2.100", |
|||
"port": 3868, |
|||
"transport": "SCTP" |
|||
} |
|||
], |
|||
"dnsServers": [ |
|||
"8.8.8.8", |
|||
"223.5.5.5" |
|||
], |
|||
"qosSettings": { |
|||
"qci": 5, |
|||
"arp": { |
|||
"priority": 1, |
|||
"preemptionCapability": false, |
|||
"preemptionVulnerability": false |
|||
} |
|||
} |
|||
}, |
|||
"description": "中国联通IMS配置", |
|||
"isDisabled": false |
|||
}, |
|||
{ |
|||
"configType": "MME", |
|||
"name": "MME_Config_Primary", |
|||
"configIndex": 0, |
|||
"plmn": "46000", |
|||
"configContent": { |
|||
"mmeCode": "001", |
|||
"mmeGroupId": "001", |
|||
"tacList": ["0001", "0002", "0003"], |
|||
"servingGwList": [ |
|||
{ |
|||
"address": "10.5.1.100", |
|||
"weight": 100 |
|||
}, |
|||
{ |
|||
"address": "10.5.1.101", |
|||
"weight": 100 |
|||
} |
|||
], |
|||
"pdnGwList": [ |
|||
{ |
|||
"address": "10.6.1.100", |
|||
"weight": 100 |
|||
} |
|||
], |
|||
"hssServers": [ |
|||
{ |
|||
"address": "10.4.1.100", |
|||
"port": 3868, |
|||
"transport": "SCTP" |
|||
} |
|||
], |
|||
"sgsnServers": [ |
|||
{ |
|||
"address": "10.7.1.100", |
|||
"port": 2123, |
|||
"transport": "SCTP" |
|||
} |
|||
], |
|||
"securitySettings": { |
|||
"integrityAlgorithm": ["EIA1", "EIA2", "EIA3"], |
|||
"cipheringAlgorithm": ["EEA1", "EEA2", "EEA3"], |
|||
"authenticationAlgorithm": "MILENAGE" |
|||
}, |
|||
"loadBalancing": { |
|||
"enabled": true, |
|||
"algorithm": "RoundRobin", |
|||
"maxLoad": 80 |
|||
} |
|||
}, |
|||
"description": "主MME配置,支持负载均衡和多种安全算法", |
|||
"isDisabled": false |
|||
}, |
|||
{ |
|||
"configType": "MME", |
|||
"name": "MME_Config_Secondary", |
|||
"configIndex": 1, |
|||
"plmn": "46000", |
|||
"configContent": { |
|||
"mmeCode": "002", |
|||
"mmeGroupId": "001", |
|||
"tacList": ["0004", "0005", "0006"], |
|||
"servingGwList": [ |
|||
{ |
|||
"address": "10.5.2.100", |
|||
"weight": 100 |
|||
} |
|||
], |
|||
"pdnGwList": [ |
|||
{ |
|||
"address": "10.6.2.100", |
|||
"weight": 100 |
|||
} |
|||
], |
|||
"hssServers": [ |
|||
{ |
|||
"address": "10.4.1.100", |
|||
"port": 3868, |
|||
"transport": "SCTP" |
|||
} |
|||
], |
|||
"sgsnServers": [ |
|||
{ |
|||
"address": "10.7.2.100", |
|||
"port": 2123, |
|||
"transport": "SCTP" |
|||
} |
|||
], |
|||
"securitySettings": { |
|||
"integrityAlgorithm": ["EIA1", "EIA2", "EIA3"], |
|||
"cipheringAlgorithm": ["EEA1", "EEA2", "EEA3"], |
|||
"authenticationAlgorithm": "MILENAGE" |
|||
}, |
|||
"loadBalancing": { |
|||
"enabled": true, |
|||
"algorithm": "RoundRobin", |
|||
"maxLoad": 80 |
|||
} |
|||
}, |
|||
"description": "备用MME配置,与主MME形成冗余", |
|||
"isDisabled": false |
|||
} |
|||
] |
|||
} |
@ -0,0 +1,191 @@ |
|||
# 网络配置管理功能 |
|||
|
|||
## 概述 |
|||
|
|||
网络配置管理功能提供了对RAN、IMS、MME三种网络配置的统一管理,支持配置的创建、查询、更新和删除操作。 |
|||
|
|||
## 配置类型 |
|||
|
|||
### 1. RAN配置 (Radio Access Network) |
|||
- **用途**: 无线接入网络配置 |
|||
- **特点**: |
|||
- 不需要PLMN字段 |
|||
- 不需要配置索引 |
|||
- 包含频段、带宽、功率控制、天线配置等参数 |
|||
|
|||
### 2. IMS配置 (IP Multimedia Subsystem) |
|||
- **用途**: IP多媒体子系统配置 |
|||
- **特点**: |
|||
- 必须提供PLMN字段 |
|||
- 必须提供配置索引(可等于0) |
|||
- 包含P-CSCF、S-CSCF、I-CSCF、HSS等服务器配置 |
|||
|
|||
### 3. MME配置 (Mobility Management Entity) |
|||
- **用途**: 移动性管理实体配置 |
|||
- **特点**: |
|||
- 必须提供PLMN字段 |
|||
- 必须提供配置索引(可等于0) |
|||
- 包含MME代码、TAC列表、网关配置等参数 |
|||
|
|||
## 数据库设计 |
|||
|
|||
### 表结构 |
|||
```sql |
|||
CREATE TABLE "NetworkConfigs" ( |
|||
"Id" character varying(450) NOT NULL, |
|||
"ConfigType" integer NOT NULL, |
|||
"Name" character varying(100) NOT NULL, |
|||
"ConfigIndex" integer, |
|||
"Plmn" character varying(10), |
|||
"ConfigContent" jsonb NOT NULL, |
|||
"Description" character varying(500), |
|||
"IsDisabled" boolean NOT NULL DEFAULT false, |
|||
"CreatedAt" timestamp with time zone NOT NULL, |
|||
"UpdatedAt" timestamp with time zone NOT NULL, |
|||
"CreatedBy" character varying(450) NOT NULL, |
|||
"UpdatedBy" character varying(450) NOT NULL, |
|||
"IsDeleted" boolean NOT NULL DEFAULT false, |
|||
CONSTRAINT "PK_NetworkConfigs" PRIMARY KEY ("Id") |
|||
); |
|||
``` |
|||
|
|||
### 索引 |
|||
- `IX_NetworkConfigs_ConfigType` - 配置类型索引 |
|||
- `IX_NetworkConfigs_Name` - 名称唯一索引 |
|||
- `IX_NetworkConfigs_Plmn` - PLMN索引 |
|||
- `IX_NetworkConfigs_ConfigIndex` - 配置索引 |
|||
- `IX_NetworkConfigs_IsDisabled` - 禁用状态索引 |
|||
- `IX_NetworkConfigs_ConfigType_Plmn` - 配置类型和PLMN复合索引 |
|||
- `IX_NetworkConfigs_ConfigType_ConfigIndex` - 配置类型和索引复合索引 |
|||
|
|||
### 约束 |
|||
- `CK_NetworkConfigs_ConfigIndex_RAN` - RAN类型不能有配置索引 |
|||
- `CK_NetworkConfigs_ConfigIndex_IMS_MME` - IMS/MME类型必须有配置索引 |
|||
- `CK_NetworkConfigs_Plmn_IMS_MME` - IMS/MME类型必须有PLMN |
|||
|
|||
## API接口 |
|||
|
|||
### 1. 创建网络配置 |
|||
```http |
|||
POST /api/NetworkConfigs |
|||
Content-Type: application/json |
|||
|
|||
{ |
|||
"configType": 1, |
|||
"name": "RAN_Config_Default", |
|||
"configIndex": null, |
|||
"plmn": null, |
|||
"configContent": "{\"frequencyBands\":[\"B1\",\"B3\"]}", |
|||
"description": "默认RAN配置", |
|||
"isDisabled": false |
|||
} |
|||
``` |
|||
|
|||
### 2. 获取网络配置列表 |
|||
```http |
|||
GET /api/NetworkConfigs?configType=1&onlyEnabled=true |
|||
``` |
|||
|
|||
### 3. 根据类型获取配置 |
|||
```http |
|||
GET /api/NetworkConfigs/type/1 |
|||
``` |
|||
|
|||
### 4. 根据PLMN获取配置 |
|||
```http |
|||
GET /api/NetworkConfigs/plmn/46000 |
|||
``` |
|||
|
|||
### 5. 搜索网络配置 |
|||
```http |
|||
GET /api/NetworkConfigs/search?keyword=RAN&configType=1 |
|||
``` |
|||
|
|||
## 使用示例 |
|||
|
|||
### 创建RAN配置 |
|||
```csharp |
|||
var command = new CreateNetworkConfigCommand |
|||
{ |
|||
ConfigType = NetworkConfigType.RAN, |
|||
Name = "RAN_Config_Default", |
|||
ConfigContent = JsonSerializer.Serialize(new |
|||
{ |
|||
frequencyBands = new[] { "B1", "B3", "B5", "B8" }, |
|||
bandwidth = "20MHz", |
|||
powerControl = new |
|||
{ |
|||
maxPower = 43, |
|||
minPower = 23, |
|||
powerStep = 1 |
|||
} |
|||
}), |
|||
Description = "默认RAN配置" |
|||
}; |
|||
|
|||
var result = await mediator.Send(command); |
|||
``` |
|||
|
|||
### 创建IMS配置 |
|||
```csharp |
|||
var command = new CreateNetworkConfigCommand |
|||
{ |
|||
ConfigType = NetworkConfigType.IMS, |
|||
Name = "IMS_Config_ChinaMobile", |
|||
ConfigIndex = 0, |
|||
Plmn = "46000", |
|||
ConfigContent = JsonSerializer.Serialize(new |
|||
{ |
|||
pCscfServers = new[] |
|||
{ |
|||
new { address = "10.1.1.100", port = 5060, transport = "UDP" } |
|||
}, |
|||
sCscfServers = new[] |
|||
{ |
|||
new { address = "10.2.1.100", port = 5060, transport = "UDP" } |
|||
} |
|||
}), |
|||
Description = "中国移动IMS配置" |
|||
}; |
|||
|
|||
var result = await mediator.Send(command); |
|||
``` |
|||
|
|||
### 查询配置 |
|||
```csharp |
|||
// 获取所有启用的配置 |
|||
var query = new GetNetworkConfigsQuery { OnlyEnabled = true }; |
|||
var result = await mediator.Send(query); |
|||
|
|||
// 根据类型和PLMN查询 |
|||
var query = new GetNetworkConfigsQuery |
|||
{ |
|||
ConfigType = NetworkConfigType.IMS, |
|||
Plmn = "46000" |
|||
}; |
|||
var result = await mediator.Send(query); |
|||
``` |
|||
|
|||
## 业务规则 |
|||
|
|||
1. **配置名称唯一性**: 所有配置的名称必须唯一 |
|||
2. **RAN配置规则**: |
|||
- 不能有配置索引 |
|||
- 不能有PLMN字段 |
|||
3. **IMS/MME配置规则**: |
|||
- 必须有PLMN字段 |
|||
- 必须有配置索引(可等于0) |
|||
4. **配置内容**: 必须为有效的JSON格式 |
|||
5. **软删除**: 支持软删除,删除后数据仍保留但不可见 |
|||
|
|||
## 性能优化 |
|||
|
|||
1. **JSONB索引**: 对ConfigContent字段使用JSONB类型,支持高效的JSON查询 |
|||
2. **复合索引**: 针对常用查询场景创建复合索引 |
|||
3. **查询优化**: 使用仓储模式,支持灵活的查询条件组合 |
|||
|
|||
## 扩展性 |
|||
|
|||
1. **配置类型扩展**: 可以通过添加新的枚举值来支持更多配置类型 |
|||
2. **字段扩展**: 可以在ConfigContent中添加新的配置参数 |
|||
3. **验证规则扩展**: 可以为不同配置类型添加特定的验证规则 |
@ -0,0 +1,94 @@ |
|||
### 网络配置管理API测试 |
|||
|
|||
### 1. 创建RAN配置 |
|||
POST {{baseUrl}}/api/networkconfigs |
|||
Content-Type: application/json |
|||
Authorization: Bearer {{token}} |
|||
|
|||
{ |
|||
"configType": 1, |
|||
"name": "RAN_Config_Test", |
|||
"configIndex": null, |
|||
"plmn": null, |
|||
"configContent": "{\"frequencyBands\":[\"B1\",\"B3\"],\"bandwidth\":\"20MHz\",\"powerControl\":{\"maxPower\":43,\"minPower\":23}}", |
|||
"description": "测试RAN配置", |
|||
"isDisabled": false |
|||
} |
|||
|
|||
### 2. 创建IMS配置 |
|||
POST {{baseUrl}}/api/networkconfigs |
|||
Content-Type: application/json |
|||
Authorization: Bearer {{token}} |
|||
|
|||
{ |
|||
"configType": 2, |
|||
"name": "IMS_Config_Test", |
|||
"configIndex": 0, |
|||
"plmn": "46000", |
|||
"configContent": "{\"pCscfServers\":[{\"address\":\"10.1.1.100\",\"port\":5060,\"transport\":\"UDP\"}],\"sCscfServers\":[{\"address\":\"10.2.1.100\",\"port\":5060,\"transport\":\"UDP\"}]}", |
|||
"description": "测试IMS配置", |
|||
"isDisabled": false |
|||
} |
|||
|
|||
### 3. 创建MME配置 |
|||
POST {{baseUrl}}/api/networkconfigs |
|||
Content-Type: application/json |
|||
Authorization: Bearer {{token}} |
|||
|
|||
{ |
|||
"configType": 3, |
|||
"name": "MME_Config_Test", |
|||
"configIndex": 0, |
|||
"plmn": "46000", |
|||
"configContent": "{\"mmeCode\":\"001\",\"mmeGroupId\":\"001\",\"tacList\":[\"0001\",\"0002\"],\"servingGwList\":[{\"address\":\"10.5.1.100\",\"weight\":100}]}", |
|||
"description": "测试MME配置", |
|||
"isDisabled": false |
|||
} |
|||
|
|||
### 4. 获取网络配置列表 |
|||
GET {{baseUrl}}/api/networkconfigs?pageNumber=1&pageSize=10 |
|||
Authorization: Bearer {{token}} |
|||
|
|||
### 5. 根据配置类型获取 |
|||
GET {{baseUrl}}/api/networkconfigs?configType=1&pageNumber=1&pageSize=10 |
|||
Authorization: Bearer {{token}} |
|||
|
|||
### 6. 根据PLMN获取 |
|||
GET {{baseUrl}}/api/networkconfigs?plmn=46000&pageNumber=1&pageSize=10 |
|||
Authorization: Bearer {{token}} |
|||
|
|||
### 7. 搜索配置 |
|||
GET {{baseUrl}}/api/networkconfigs?keyword=Test&pageNumber=1&pageSize=10 |
|||
Authorization: Bearer {{token}} |
|||
|
|||
### 8. 获取启用的配置 |
|||
GET {{baseUrl}}/api/networkconfigs?onlyEnabled=true&pageNumber=1&pageSize=10 |
|||
Authorization: Bearer {{token}} |
|||
|
|||
### 9. 获取配置详情 |
|||
GET {{baseUrl}}/api/networkconfigs/{{networkConfigId}} |
|||
Authorization: Bearer {{token}} |
|||
|
|||
### 10. 更新配置 |
|||
PUT {{baseUrl}}/api/networkconfigs/{{networkConfigId}} |
|||
Content-Type: application/json |
|||
Authorization: Bearer {{token}} |
|||
|
|||
{ |
|||
"networkConfigId": "{{networkConfigId}}", |
|||
"name": "RAN_Config_Updated", |
|||
"configIndex": null, |
|||
"plmn": null, |
|||
"configContent": "{\"frequencyBands\":[\"B1\",\"B3\",\"B5\"],\"bandwidth\":\"40MHz\",\"powerControl\":{\"maxPower\":46,\"minPower\":20}}", |
|||
"description": "更新后的RAN配置", |
|||
"isDisabled": false |
|||
} |
|||
|
|||
### 11. 删除配置 |
|||
DELETE {{baseUrl}}/api/networkconfigs/{{networkConfigId}} |
|||
Authorization: Bearer {{token}} |
|||
|
|||
### 环境变量设置 |
|||
# baseUrl: http://localhost:5000 |
|||
# token: your_jwt_token_here |
|||
# networkConfigId: your_network_config_id_here |
@ -0,0 +1,103 @@ |
|||
using CellularManagement.Domain.Entities.Device; |
|||
using Microsoft.EntityFrameworkCore; |
|||
using Microsoft.EntityFrameworkCore.Metadata.Builders; |
|||
|
|||
namespace CellularManagement.Infrastructure.Configurations.Device; |
|||
|
|||
/// <summary>
|
|||
/// 网络配置实体配置
|
|||
/// </summary>
|
|||
public class NetworkConfigConfiguration : IEntityTypeConfiguration<NetworkConfig> |
|||
{ |
|||
public void Configure(EntityTypeBuilder<NetworkConfig> builder) |
|||
{ |
|||
// 表名
|
|||
builder.ToTable("NetworkConfigs"); |
|||
|
|||
// 主键
|
|||
builder.HasKey(x => x.Id); |
|||
|
|||
// 属性配置
|
|||
builder.Property(x => x.Id) |
|||
.HasMaxLength(450) |
|||
.IsRequired(); |
|||
|
|||
builder.Property(x => x.ConfigType) |
|||
.HasConversion<int>() |
|||
.IsRequired(); |
|||
|
|||
builder.Property(x => x.Name) |
|||
.HasMaxLength(100) |
|||
.IsRequired(); |
|||
|
|||
builder.Property(x => x.ConfigIndex) |
|||
.IsRequired(false); |
|||
|
|||
builder.Property(x => x.Plmn) |
|||
.HasMaxLength(10) |
|||
.IsRequired(false); |
|||
|
|||
builder.Property(x => x.ConfigContent) |
|||
.HasColumnType("jsonb") |
|||
.IsRequired(); |
|||
|
|||
builder.Property(x => x.Description) |
|||
.HasMaxLength(500) |
|||
.IsRequired(false); |
|||
|
|||
builder.Property(x => x.IsDisabled) |
|||
.HasDefaultValue(false); |
|||
|
|||
// 审计字段
|
|||
builder.Property(x => x.CreatedAt) |
|||
.IsRequired(); |
|||
|
|||
builder.Property(x => x.UpdatedAt) |
|||
.IsRequired(); |
|||
|
|||
builder.Property(x => x.CreatedBy) |
|||
.HasMaxLength(450) |
|||
.IsRequired(); |
|||
|
|||
builder.Property(x => x.UpdatedBy) |
|||
.HasMaxLength(450) |
|||
.IsRequired(); |
|||
|
|||
// 索引配置
|
|||
builder.HasIndex(x => x.ConfigType) |
|||
.HasDatabaseName("IX_NetworkConfigs_ConfigType"); |
|||
|
|||
builder.HasIndex(x => x.Name) |
|||
.HasDatabaseName("IX_NetworkConfigs_Name") |
|||
.IsUnique(); |
|||
|
|||
builder.HasIndex(x => x.Plmn) |
|||
.HasDatabaseName("IX_NetworkConfigs_Plmn"); |
|||
|
|||
builder.HasIndex(x => x.ConfigIndex) |
|||
.HasDatabaseName("IX_NetworkConfigs_ConfigIndex"); |
|||
|
|||
builder.HasIndex(x => x.IsDisabled) |
|||
.HasDatabaseName("IX_NetworkConfigs_IsDisabled"); |
|||
|
|||
// 复合索引
|
|||
builder.HasIndex(x => new { x.ConfigType, x.Plmn }) |
|||
.HasDatabaseName("IX_NetworkConfigs_ConfigType_Plmn"); |
|||
|
|||
builder.HasIndex(x => new { x.ConfigType, x.ConfigIndex }) |
|||
.HasDatabaseName("IX_NetworkConfigs_ConfigType_ConfigIndex"); |
|||
|
|||
// 约束配置
|
|||
builder.HasCheckConstraint("CK_NetworkConfigs_ConfigIndex_RAN", |
|||
"NOT (\"ConfigType\" = 1 AND \"ConfigIndex\" IS NOT NULL)"); |
|||
|
|||
builder.HasCheckConstraint("CK_NetworkConfigs_ConfigIndex_IMS_MME", |
|||
"NOT (\"ConfigType\" IN (2, 3) AND \"ConfigIndex\" IS NULL)"); |
|||
|
|||
builder.HasCheckConstraint("CK_NetworkConfigs_Plmn_IMS_MME", |
|||
"NOT (\"ConfigType\" IN (2, 3) AND \"Plmn\" IS NULL)"); |
|||
|
|||
// 软删除过滤器
|
|||
builder.HasQueryFilter(x => !x.IsDeleted); |
|||
} |
|||
} |
@ -0,0 +1,168 @@ |
|||
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 NetworkConfigRepository : BaseRepository<NetworkConfig>, INetworkConfigRepository |
|||
{ |
|||
private readonly ILogger<NetworkConfigRepository> _logger; |
|||
|
|||
/// <summary>
|
|||
/// 初始化仓储
|
|||
/// </summary>
|
|||
public NetworkConfigRepository( |
|||
ICommandRepository<NetworkConfig> commandRepository, |
|||
IQueryRepository<NetworkConfig> queryRepository, |
|||
ILogger<NetworkConfigRepository> logger) |
|||
: base(commandRepository, queryRepository, logger) |
|||
{ |
|||
_logger = logger; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 添加网络配置
|
|||
/// </summary>
|
|||
public async Task<NetworkConfig> AddNetworkConfigAsync(NetworkConfig networkConfig, CancellationToken cancellationToken = default) |
|||
{ |
|||
var result = await CommandRepository.AddAsync(networkConfig, cancellationToken); |
|||
return result; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 更新网络配置
|
|||
/// </summary>
|
|||
public void UpdateNetworkConfig(NetworkConfig networkConfig) |
|||
{ |
|||
CommandRepository.Update(networkConfig); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 删除网络配置
|
|||
/// </summary>
|
|||
public async Task DeleteNetworkConfigAsync(string id, CancellationToken cancellationToken = default) |
|||
{ |
|||
await CommandRepository.DeleteByIdAsync(id, cancellationToken); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 获取所有网络配置
|
|||
/// </summary>
|
|||
public async Task<IList<NetworkConfig>> GetAllNetworkConfigsAsync(CancellationToken cancellationToken = default) |
|||
{ |
|||
var networkConfigs = await QueryRepository.GetAllAsync(cancellationToken: cancellationToken); |
|||
return networkConfigs.OrderBy(x => x.ConfigType).ThenBy(x => x.Name).ToList(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 根据ID获取网络配置
|
|||
/// </summary>
|
|||
public async Task<NetworkConfig?> GetNetworkConfigByIdAsync(string id, CancellationToken cancellationToken = default) |
|||
{ |
|||
return await QueryRepository.GetByIdAsync(id, cancellationToken: cancellationToken); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 根据配置类型获取网络配置列表
|
|||
/// </summary>
|
|||
public async Task<IList<NetworkConfig>> GetNetworkConfigsByTypeAsync(NetworkConfigType configType, CancellationToken cancellationToken = default) |
|||
{ |
|||
var networkConfigs = await QueryRepository.FindAsync(x => x.ConfigType == configType, cancellationToken: cancellationToken); |
|||
return networkConfigs.OrderBy(x => x.Name).ToList(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 根据PLMN获取网络配置列表
|
|||
/// </summary>
|
|||
public async Task<IList<NetworkConfig>> GetNetworkConfigsByPlmnAsync(string plmn, CancellationToken cancellationToken = default) |
|||
{ |
|||
var networkConfigs = await QueryRepository.FindAsync(x => x.Plmn == plmn, cancellationToken: cancellationToken); |
|||
return networkConfigs.OrderBy(x => x.ConfigType).ThenBy(x => x.Name).ToList(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 根据配置类型和PLMN获取网络配置列表
|
|||
/// </summary>
|
|||
public async Task<IList<NetworkConfig>> GetNetworkConfigsByTypeAndPlmnAsync(NetworkConfigType configType, string plmn, CancellationToken cancellationToken = default) |
|||
{ |
|||
var networkConfigs = await QueryRepository.FindAsync(x => x.ConfigType == configType && x.Plmn == plmn, cancellationToken: cancellationToken); |
|||
return networkConfigs.OrderBy(x => x.ConfigIndex).ThenBy(x => x.Name).ToList(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 获取启用的网络配置
|
|||
/// </summary>
|
|||
public async Task<IList<NetworkConfig>> GetEnabledNetworkConfigsAsync(CancellationToken cancellationToken = default) |
|||
{ |
|||
var networkConfigs = await QueryRepository.FindAsync(x => !x.IsDisabled, cancellationToken: cancellationToken); |
|||
return networkConfigs.OrderBy(x => x.ConfigType).ThenBy(x => x.Name).ToList(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 搜索网络配置
|
|||
/// </summary>
|
|||
public async Task<IList<NetworkConfig>> SearchNetworkConfigsAsync( |
|||
string? keyword, |
|||
NetworkConfigType? configType = null, |
|||
string? plmn = null, |
|||
CancellationToken cancellationToken = default) |
|||
{ |
|||
var query = await QueryRepository.FindAsync(x => true, cancellationToken: cancellationToken); |
|||
|
|||
if (!string.IsNullOrWhiteSpace(keyword)) |
|||
{ |
|||
query = query.Where(x => |
|||
x.Name.Contains(keyword) || |
|||
x.Description.Contains(keyword) || |
|||
x.Plmn.Contains(keyword)); |
|||
} |
|||
|
|||
if (configType.HasValue) |
|||
{ |
|||
query = query.Where(x => x.ConfigType == configType.Value); |
|||
} |
|||
|
|||
if (!string.IsNullOrWhiteSpace(plmn)) |
|||
{ |
|||
query = query.Where(x => x.Plmn == plmn); |
|||
} |
|||
|
|||
return query.OrderBy(x => x.ConfigType).ThenBy(x => x.Name).ToList(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 检查网络配置是否存在
|
|||
/// </summary>
|
|||
public async Task<bool> ExistsAsync(string id, CancellationToken cancellationToken = default) |
|||
{ |
|||
return await QueryRepository.AnyAsync(x => x.Id == id, cancellationToken: cancellationToken); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 检查配置名称是否存在
|
|||
/// </summary>
|
|||
public async Task<bool> NameExistsAsync(string name, CancellationToken cancellationToken = default) |
|||
{ |
|||
return await QueryRepository.AnyAsync(x => x.Name == name, cancellationToken: cancellationToken); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 检查配置名称是否存在(排除指定ID)
|
|||
/// </summary>
|
|||
public async Task<bool> NameExistsAsync(string name, string excludeId, CancellationToken cancellationToken = default) |
|||
{ |
|||
return await QueryRepository.AnyAsync(x => x.Name == name && x.Id != excludeId, cancellationToken: cancellationToken); |
|||
} |
|||
} |
@ -1,151 +0,0 @@ |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Threading; |
|||
using System.Threading.Tasks; |
|||
using Microsoft.EntityFrameworkCore; |
|||
using Microsoft.Extensions.Logging; |
|||
using CellularManagement.Domain.Entities; |
|||
using CellularManagement.Domain.Repositories; |
|||
using CellularManagement.Infrastructure.Context; |
|||
using CellularManagement.Domain.Repositories.Identity; |
|||
|
|||
namespace CellularManagement.Infrastructure.Repositories; |
|||
|
|||
/// <summary>
|
|||
/// 用户角色服务仓储实现类
|
|||
/// </summary>
|
|||
public class UserRoleServiceRepository : IUserRoleServiceRepository |
|||
{ |
|||
private readonly AppDbContext _context; |
|||
private readonly ILogger<UserRoleServiceRepository> _logger; |
|||
private readonly IUserRoleRepository _userRoleRepository; |
|||
|
|||
/// <summary>
|
|||
/// 初始化仓储
|
|||
/// </summary>
|
|||
public UserRoleServiceRepository( |
|||
AppDbContext context, |
|||
IUserRoleRepository userRoleRepository, |
|||
ILogger<UserRoleServiceRepository> logger) |
|||
{ |
|||
_context = context; |
|||
_userRoleRepository = userRoleRepository; |
|||
_logger = logger; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 为用户分配角色
|
|||
/// </summary>
|
|||
public async Task AssignRolesToUserAsync(string userId, IEnumerable<string> roleIds, CancellationToken cancellationToken = default) |
|||
{ |
|||
// 先移除用户现有的角色
|
|||
await RemoveAllRolesFromUserAsync(userId, cancellationToken); |
|||
|
|||
// 创建新的用户角色关系
|
|||
var userRoles = roleIds.Select(roleId => new UserRole |
|||
{ |
|||
UserId = userId, |
|||
RoleId = roleId |
|||
}); |
|||
|
|||
// 批量添加新的用户角色关系
|
|||
await _userRoleRepository.AddUserRolesAsync(userRoles, cancellationToken); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 为角色分配用户
|
|||
/// </summary>
|
|||
public async Task AssignUsersToRoleAsync(string roleId, IEnumerable<string> userIds, CancellationToken cancellationToken = default) |
|||
{ |
|||
// 先移除角色现有的用户
|
|||
await RemoveAllUsersFromRoleAsync(roleId, cancellationToken); |
|||
|
|||
// 创建新的用户角色关系
|
|||
var userRoles = userIds.Select(userId => new UserRole |
|||
{ |
|||
UserId = userId, |
|||
RoleId = roleId |
|||
}); |
|||
|
|||
// 批量添加新的用户角色关系
|
|||
await _userRoleRepository.AddUserRolesAsync(userRoles, cancellationToken); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 移除用户的所有角色
|
|||
/// </summary>
|
|||
public async Task RemoveAllRolesFromUserAsync(string userId, CancellationToken cancellationToken = default) |
|||
{ |
|||
var userRoles = await _context.UserRoles |
|||
.Where(ur => ur.UserId == userId) |
|||
.ToListAsync(cancellationToken); |
|||
|
|||
if (userRoles.Any()) |
|||
{ |
|||
_context.UserRoles.RemoveRange(userRoles); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 移除角色的所有用户
|
|||
/// </summary>
|
|||
public async Task RemoveAllUsersFromRoleAsync(string roleId, CancellationToken cancellationToken = default) |
|||
{ |
|||
var userRoles = await _context.UserRoles |
|||
.Where(ur => ur.RoleId == roleId) |
|||
.ToListAsync(cancellationToken); |
|||
|
|||
if (userRoles.Any()) |
|||
{ |
|||
_context.UserRoles.RemoveRange(userRoles); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 获取用户的所有角色ID
|
|||
/// </summary>
|
|||
public async Task<IEnumerable<string>> GetUserRoleIdsAsync(string userId, CancellationToken cancellationToken = default) |
|||
{ |
|||
return await _context.UserRoles |
|||
.Where(ur => ur.UserId == userId) |
|||
.Select(ur => ur.RoleId) |
|||
.ToListAsync(cancellationToken); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 获取角色的所有用户ID
|
|||
/// </summary>
|
|||
public async Task<IEnumerable<string>> GetRoleUserIdsAsync(string roleId, CancellationToken cancellationToken = default) |
|||
{ |
|||
return await _context.UserRoles |
|||
.Where(ur => ur.RoleId == roleId) |
|||
.Select(ur => ur.UserId) |
|||
.ToListAsync(cancellationToken); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 检查用户是否拥有指定角色
|
|||
/// </summary>
|
|||
public async Task<bool> HasRoleAsync(string userId, string roleId, CancellationToken cancellationToken = default) |
|||
{ |
|||
return await _userRoleRepository.HasRoleAsync(userId, roleId, cancellationToken); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 检查用户是否拥有指定角色列表中的任意一个
|
|||
/// </summary>
|
|||
public async Task<bool> HasAnyRoleAsync(string userId, IEnumerable<string> roleIds, CancellationToken cancellationToken = default) |
|||
{ |
|||
return await _context.UserRoles |
|||
.AnyAsync(ur => ur.UserId == userId && roleIds.Contains(ur.RoleId), cancellationToken); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 检查用户是否拥有指定角色列表中的所有角色
|
|||
/// </summary>
|
|||
public async Task<bool> HasAllRolesAsync(string userId, IEnumerable<string> roleIds, CancellationToken cancellationToken = default) |
|||
{ |
|||
var userRoleIds = await GetUserRoleIdsAsync(userId, cancellationToken); |
|||
return roleIds.All(roleId => userRoleIds.Contains(roleId)); |
|||
} |
|||
} |
@ -0,0 +1,290 @@ |
|||
using Microsoft.AspNetCore.Authorization; |
|||
using Microsoft.AspNetCore.Mvc; |
|||
using MediatR; |
|||
using CellularManagement.Application.Features.NetworkConfigs.Commands.CreateNetworkConfig; |
|||
using CellularManagement.Application.Features.NetworkConfigs.Commands.DeleteNetworkConfig; |
|||
using CellularManagement.Application.Features.NetworkConfigs.Commands.UpdateNetworkConfig; |
|||
using CellularManagement.Application.Features.NetworkConfigs.Queries.GetNetworkConfigById; |
|||
using CellularManagement.Application.Features.NetworkConfigs.Queries.GetNetworkConfigs; |
|||
using CellularManagement.Application.Common; |
|||
using Microsoft.Extensions.Logging; |
|||
using Microsoft.AspNetCore.Http; |
|||
using CellularManagement.Presentation.Abstractions; |
|||
using CellularManagement.Domain.Common; |
|||
|
|||
namespace CellularManagement.Presentation.Controllers; |
|||
|
|||
/// <summary>
|
|||
/// 网络配置管理控制器
|
|||
/// 提供网络配置管理相关的 API 接口,包括创建、更新、删除和查询网络配置功能
|
|||
/// </summary>
|
|||
[Route("api/networkconfigs")] |
|||
[ApiController] |
|||
[Authorize(Roles = "Admin")] // 只有管理员可以访问
|
|||
public class NetworkConfigsController : ApiController |
|||
{ |
|||
private readonly ILogger<NetworkConfigsController> _logger; |
|||
|
|||
/// <summary>
|
|||
/// 初始化网络配置控制器
|
|||
/// </summary>
|
|||
/// <param name="mediator">MediatR 中介者,用于处理命令和查询</param>
|
|||
/// <param name="logger">日志记录器</param>
|
|||
public NetworkConfigsController( |
|||
IMediator mediator, |
|||
ILogger<NetworkConfigsController> logger) : base(mediator) |
|||
{ |
|||
_logger = logger; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 获取网络配置列表
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// 示例请求:
|
|||
///
|
|||
/// GET /api/networkconfigs?pageNumber=1&pageSize=10&configType=1&plmn=46000&onlyEnabled=true&keyword=RAN
|
|||
///
|
|||
/// </remarks>
|
|||
/// <param name="query">查询参数,包含分页、过滤和搜索条件</param>
|
|||
/// <returns>
|
|||
/// 查询结果,包含:
|
|||
/// - 成功:返回网络配置列表和分页信息
|
|||
/// - 失败:返回错误信息
|
|||
/// </returns>
|
|||
/// <response code="200">查询成功,返回网络配置列表</response>
|
|||
/// <response code="400">查询失败,返回错误信息</response>
|
|||
[HttpGet] |
|||
[ProducesResponseType(typeof(OperationResult<GetNetworkConfigsResponse>), StatusCodes.Status200OK)] |
|||
[ProducesResponseType(typeof(OperationResult<GetNetworkConfigsResponse>), StatusCodes.Status400BadRequest)] |
|||
public async Task<OperationResult<GetNetworkConfigsResponse>> GetNetworkConfigs([FromQuery] GetNetworkConfigsQuery query) |
|||
{ |
|||
try |
|||
{ |
|||
var result = await mediator.Send(query); |
|||
|
|||
if (result.IsSuccess) |
|||
{ |
|||
_logger.LogInformation("网络配置列表查询成功,共 {Count} 条记录", result.Data?.TotalCount ?? 0); |
|||
} |
|||
else |
|||
{ |
|||
_logger.LogWarning("网络配置列表查询失败: {Error}", |
|||
result.ErrorMessages?.FirstOrDefault()); |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
_logger.LogError(ex, "查询网络配置列表时发生异常"); |
|||
return OperationResult<GetNetworkConfigsResponse>.CreateFailure("系统错误,请稍后重试"); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 获取网络配置详情
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// 示例请求:
|
|||
///
|
|||
/// GET /api/networkconfigs/{id}
|
|||
///
|
|||
/// </remarks>
|
|||
/// <param name="id">网络配置ID</param>
|
|||
/// <returns>
|
|||
/// 查询结果,包含:
|
|||
/// - 成功:返回网络配置详情
|
|||
/// - 失败:返回错误信息
|
|||
/// </returns>
|
|||
/// <response code="200">查询成功,返回网络配置详情</response>
|
|||
/// <response code="400">查询失败,返回错误信息</response>
|
|||
[HttpGet("{id}")] |
|||
[ProducesResponseType(typeof(OperationResult<GetNetworkConfigByIdResponse>), StatusCodes.Status200OK)] |
|||
[ProducesResponseType(typeof(OperationResult<GetNetworkConfigByIdResponse>), StatusCodes.Status400BadRequest)] |
|||
public async Task<OperationResult<GetNetworkConfigByIdResponse>> GetNetworkConfigById(string id) |
|||
{ |
|||
try |
|||
{ |
|||
var result = await mediator.Send(new GetNetworkConfigByIdQuery { NetworkConfigId = id }); |
|||
|
|||
if (result.IsSuccess) |
|||
{ |
|||
_logger.LogInformation("网络配置 {ConfigId} 详情查询成功", id); |
|||
} |
|||
else |
|||
{ |
|||
_logger.LogWarning("网络配置 {ConfigId} 详情查询失败: {Error}", |
|||
id, |
|||
result.ErrorMessages?.FirstOrDefault()); |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
_logger.LogError(ex, "查询网络配置 {ConfigId} 详情时发生异常", id); |
|||
return OperationResult<GetNetworkConfigByIdResponse>.CreateFailure("系统错误,请稍后重试"); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 创建新网络配置
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// 示例请求:
|
|||
///
|
|||
/// POST /api/networkconfigs
|
|||
/// {
|
|||
/// "configType": 1,
|
|||
/// "name": "RAN_Config_Default",
|
|||
/// "configIndex": null,
|
|||
/// "plmn": null,
|
|||
/// "configContent": "{\"frequencyBands\":[\"B1\",\"B3\"]}",
|
|||
/// "description": "默认RAN配置",
|
|||
/// "isDisabled": false
|
|||
/// }
|
|||
///
|
|||
/// </remarks>
|
|||
/// <param name="command">创建网络配置命令,包含配置类型、名称、内容等信息</param>
|
|||
/// <returns>
|
|||
/// 创建结果,包含:
|
|||
/// - 成功:返回网络配置ID
|
|||
/// - 失败:返回错误信息
|
|||
/// </returns>
|
|||
/// <response code="200">创建成功,返回网络配置ID</response>
|
|||
/// <response code="400">创建失败,返回错误信息</response>
|
|||
[HttpPost] |
|||
[ProducesResponseType(typeof(OperationResult<CreateNetworkConfigResponse>), StatusCodes.Status200OK)] |
|||
[ProducesResponseType(typeof(OperationResult<CreateNetworkConfigResponse>), StatusCodes.Status400BadRequest)] |
|||
public async Task<OperationResult<CreateNetworkConfigResponse>> CreateNetworkConfig([FromBody] CreateNetworkConfigCommand command) |
|||
{ |
|||
try |
|||
{ |
|||
var result = await mediator.Send(command); |
|||
|
|||
if (result.IsSuccess) |
|||
{ |
|||
_logger.LogInformation("网络配置 {ConfigName} 创建成功", command.Name); |
|||
} |
|||
else |
|||
{ |
|||
_logger.LogWarning("网络配置 {ConfigName} 创建失败: {Error}", |
|||
command.Name, |
|||
result.ErrorMessages?.FirstOrDefault()); |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
_logger.LogError(ex, "创建网络配置 {ConfigName} 时发生异常", command.Name); |
|||
return OperationResult<CreateNetworkConfigResponse>.CreateFailure("系统错误,请稍后重试"); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 更新网络配置
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// 示例请求:
|
|||
///
|
|||
/// PUT /api/networkconfigs/{id}
|
|||
/// {
|
|||
/// "networkConfigId": "config-id",
|
|||
/// "name": "RAN_Config_Updated",
|
|||
/// "configContent": "{\"frequencyBands\":[\"B1\",\"B3\",\"B5\"]}",
|
|||
/// "description": "更新后的RAN配置"
|
|||
/// }
|
|||
///
|
|||
/// </remarks>
|
|||
/// <param name="id">网络配置ID</param>
|
|||
/// <param name="command">更新网络配置命令</param>
|
|||
/// <returns>
|
|||
/// 更新结果,包含:
|
|||
/// - 成功:返回更新后的网络配置信息
|
|||
/// - 失败:返回错误信息
|
|||
/// </returns>
|
|||
/// <response code="200">更新成功,返回网络配置信息</response>
|
|||
/// <response code="400">更新失败,返回错误信息</response>
|
|||
[HttpPut("{id}")] |
|||
[ProducesResponseType(typeof(OperationResult<UpdateNetworkConfigResponse>), StatusCodes.Status200OK)] |
|||
[ProducesResponseType(typeof(OperationResult<UpdateNetworkConfigResponse>), StatusCodes.Status400BadRequest)] |
|||
public async Task<OperationResult<UpdateNetworkConfigResponse>> UpdateNetworkConfig(string id, [FromBody] UpdateNetworkConfigCommand command) |
|||
{ |
|||
try |
|||
{ |
|||
if (id != command.NetworkConfigId) |
|||
{ |
|||
_logger.LogWarning("网络配置ID不匹配,路径ID: {PathId}, 命令ID: {CommandId}", id, command.NetworkConfigId); |
|||
return OperationResult<UpdateNetworkConfigResponse>.CreateFailure("网络配置ID不匹配"); |
|||
} |
|||
|
|||
var result = await mediator.Send(command); |
|||
|
|||
if (result.IsSuccess) |
|||
{ |
|||
_logger.LogInformation("网络配置 {ConfigId} 更新成功", id); |
|||
} |
|||
else |
|||
{ |
|||
_logger.LogWarning("网络配置 {ConfigId} 更新失败: {Error}", |
|||
id, |
|||
result.ErrorMessages?.FirstOrDefault()); |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
_logger.LogError(ex, "更新网络配置 {ConfigId} 时发生异常", id); |
|||
return OperationResult<UpdateNetworkConfigResponse>.CreateFailure("系统错误,请稍后重试"); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 删除网络配置
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// 示例请求:
|
|||
///
|
|||
/// DELETE /api/networkconfigs/{id}
|
|||
///
|
|||
/// </remarks>
|
|||
/// <param name="id">网络配置ID</param>
|
|||
/// <returns>
|
|||
/// 删除结果,包含:
|
|||
/// - 成功:返回删除成功标志
|
|||
/// - 失败:返回错误信息
|
|||
/// </returns>
|
|||
/// <response code="200">删除成功</response>
|
|||
/// <response code="400">删除失败,返回错误信息</response>
|
|||
[HttpDelete("{id}")] |
|||
[ProducesResponseType(typeof(OperationResult<bool>), StatusCodes.Status200OK)] |
|||
[ProducesResponseType(typeof(OperationResult<bool>), StatusCodes.Status400BadRequest)] |
|||
public async Task<OperationResult<bool>> DeleteNetworkConfig(string id) |
|||
{ |
|||
try |
|||
{ |
|||
var result = await mediator.Send(new DeleteNetworkConfigCommand { NetworkConfigId = id }); |
|||
|
|||
if (result.IsSuccess) |
|||
{ |
|||
_logger.LogInformation("网络配置 {ConfigId} 删除成功", id); |
|||
} |
|||
else |
|||
{ |
|||
_logger.LogWarning("网络配置 {ConfigId} 删除失败: {Error}", |
|||
id, |
|||
result.ErrorMessages?.FirstOrDefault()); |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
_logger.LogError(ex, "删除网络配置 {ConfigId} 时发生异常", id); |
|||
return OperationResult<bool>.CreateFailure("系统错误,请稍后重试"); |
|||
} |
|||
} |
|||
} |
Loading…
Reference in new issue