From d8d02f91a6d0d52d294314ee01c6c25d36b0454c Mon Sep 17 00:00:00 2001 From: hyh Date: Fri, 1 Aug 2025 16:57:29 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E8=BF=90=E8=A1=8C?= =?UTF-8?q?=E6=97=B6=E7=8A=B6=E6=80=81=E6=95=B0=E7=BB=84=E5=8F=82=E6=95=B0?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E4=BB=8E=E5=89=8D=E7=AB=AF=E4=BC=A0=E5=85=A5?= =?UTF-8?q?=E8=BF=87=E6=BB=A4=E6=9D=A1=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在GetProtocolLogsByDeviceQuery中添加RuntimeStatuses参数 - 修改查询处理器使用前端传入的运行时状态数组 - 更新控制器API端点支持runtimeStatuses查询参数 - 优化协议日志查询的过滤灵活性 - 更新修改记录文档 --- .../GetProtocolLogsByDeviceQuery.cs | 13 +- .../GetProtocolLogsByDeviceQueryHandler.cs | 32 +- .../GetProtocolLogsByDeviceResponse.cs | 2 +- .../Logging/IProtocolLogRepository.cs | 4 +- .../Logging/ProtocolLogRepository.cs | 33 +- .../NetworkStackConfigRepository.cs | 32 +- .../Controllers/ProtocolLogsController.cs | 60 ++- src/modify.md | 369 +++++++++++++++++- 8 files changed, 486 insertions(+), 59 deletions(-) diff --git a/src/X1.Application/Features/ProtocolLogs/Queries/GetProtocolLogsByDevice/GetProtocolLogsByDeviceQuery.cs b/src/X1.Application/Features/ProtocolLogs/Queries/GetProtocolLogsByDevice/GetProtocolLogsByDeviceQuery.cs index a21ff56..9f0ab89 100644 --- a/src/X1.Application/Features/ProtocolLogs/Queries/GetProtocolLogsByDevice/GetProtocolLogsByDeviceQuery.cs +++ b/src/X1.Application/Features/ProtocolLogs/Queries/GetProtocolLogsByDevice/GetProtocolLogsByDeviceQuery.cs @@ -13,9 +13,8 @@ public class GetProtocolLogsByDeviceQuery : IRequest /// 设备代码 /// - [Required(ErrorMessage = "设备代码不能为空")] [MaxLength(50, ErrorMessage = "设备代码不能超过50个字符")] - public string DeviceCode { get; set; } = string.Empty; + public string? DeviceCode { get; set; } /// /// 开始时间戳 @@ -39,6 +38,16 @@ public class GetProtocolLogsByDeviceQuery : IRequest public DeviceRuntimeStatus? DeviceRuntimeStatus { get; set; } + /// + /// 运行时代码数组 + /// + public string[] RuntimeCodes { get; set; } = Array.Empty(); + + /// + /// 运行时状态数组(从前端传入) + /// + public int[] RuntimeStatuses { get; set; } = Array.Empty(); + /// /// 是否按时间戳降序排序 /// diff --git a/src/X1.Application/Features/ProtocolLogs/Queries/GetProtocolLogsByDevice/GetProtocolLogsByDeviceQueryHandler.cs b/src/X1.Application/Features/ProtocolLogs/Queries/GetProtocolLogsByDevice/GetProtocolLogsByDeviceQueryHandler.cs index 9d6fd54..2c9ecbc 100644 --- a/src/X1.Application/Features/ProtocolLogs/Queries/GetProtocolLogsByDevice/GetProtocolLogsByDeviceQueryHandler.cs +++ b/src/X1.Application/Features/ProtocolLogs/Queries/GetProtocolLogsByDevice/GetProtocolLogsByDeviceQueryHandler.cs @@ -52,42 +52,14 @@ public class GetProtocolLogsByDeviceQueryHandler : IRequestHandler? runtimeCodes = null; - if (request.DeviceRuntimeStatus.HasValue) - { - var deviceRuntimes = await _deviceRuntimeRepository.GetRuntimesByDeviceCodeAsync( - request.DeviceCode, - cancellationToken); - - if (!deviceRuntimes.Any()) - { - _logger.LogWarning("设备 {DeviceCode} 的运行时状态不存在", request.DeviceCode); - return OperationResult.CreateFailure($"设备 {request.DeviceCode} 的运行时状态不存在"); - } - - // 过滤出匹配状态的运行时 - var matchingRuntimes = deviceRuntimes.Where(r => r.RuntimeStatus == request.DeviceRuntimeStatus.Value).ToList(); - if (!matchingRuntimes.Any()) - { - _logger.LogWarning("设备 {DeviceCode} 的运行时状态不匹配,期望: {ExpectedStatus}", - request.DeviceCode, request.DeviceRuntimeStatus.Value); - return OperationResult.CreateFailure( - $"设备 {request.DeviceCode} 的运行时状态不匹配,期望: {request.DeviceRuntimeStatus.Value}"); - } - - // 获取运行时编码集合 - runtimeCodes = matchingRuntimes.Select(r => r.RuntimeCode).ToList(); - _logger.LogInformation("使用运行时编码集合 {RuntimeCodes} 过滤协议日志", string.Join(", ", runtimeCodes)); - } - // 使用 JOIN 高性能查询方法 var protocolLogs = await _protocolLogRepository.GetByDeviceWithFiltersAsync( request.DeviceCode, - runtimeCodes, + request.RuntimeCodes, // 直接使用请求中的运行时代码数组 request.StartTimestamp, request.EndTimestamp, request.LayerType, + request.RuntimeStatuses.Any() ? request.RuntimeStatuses : null, // 使用从前端传入的运行时状态数组 request.OrderByDescending, cancellationToken); diff --git a/src/X1.Application/Features/ProtocolLogs/Queries/GetProtocolLogsByDevice/GetProtocolLogsByDeviceResponse.cs b/src/X1.Application/Features/ProtocolLogs/Queries/GetProtocolLogsByDevice/GetProtocolLogsByDeviceResponse.cs index 8151962..402c088 100644 --- a/src/X1.Application/Features/ProtocolLogs/Queries/GetProtocolLogsByDevice/GetProtocolLogsByDeviceResponse.cs +++ b/src/X1.Application/Features/ProtocolLogs/Queries/GetProtocolLogsByDevice/GetProtocolLogsByDeviceResponse.cs @@ -12,7 +12,7 @@ public class GetProtocolLogsByDeviceResponse /// /// 设备代码 /// - public string DeviceCode { get; set; } = string.Empty; + public string? DeviceCode { get; set; } /// /// 协议日志列表 diff --git a/src/X1.Domain/Repositories/Logging/IProtocolLogRepository.cs b/src/X1.Domain/Repositories/Logging/IProtocolLogRepository.cs index f2e2d08..9021440 100644 --- a/src/X1.Domain/Repositories/Logging/IProtocolLogRepository.cs +++ b/src/X1.Domain/Repositories/Logging/IProtocolLogRepository.cs @@ -59,15 +59,17 @@ public interface IProtocolLogRepository : IBaseRepository /// 开始时间戳 /// 结束时间戳 /// 协议层类型 + /// 运行时状态过滤(可选,支持多个状态) /// 是否按时间戳降序排序 /// 取消令牌 /// 协议日志列表 Task> GetByDeviceWithFiltersAsync( - string deviceCode, + string? deviceCode, IEnumerable? runtimeCodes = null, long? startTimestamp = null, long? endTimestamp = null, string? layerType = null, + IEnumerable? runtimeStatuses = null, bool orderByDescending = true, CancellationToken cancellationToken = default); diff --git a/src/X1.Infrastructure/Repositories/Logging/ProtocolLogRepository.cs b/src/X1.Infrastructure/Repositories/Logging/ProtocolLogRepository.cs index e5d8569..7fd6ddd 100644 --- a/src/X1.Infrastructure/Repositories/Logging/ProtocolLogRepository.cs +++ b/src/X1.Infrastructure/Repositories/Logging/ProtocolLogRepository.cs @@ -157,15 +157,17 @@ public class ProtocolLogRepository : BaseRepository, IProtocolLogRe /// 开始时间戳 /// 结束时间戳 /// 协议层类型 + /// 运行时状态过滤(可选,支持多个状态) /// 是否按时间戳降序排序 /// 取消令牌 /// 协议日志列表 public async Task> GetByDeviceWithFiltersAsync( - string deviceCode, + string? deviceCode, IEnumerable? runtimeCodes = null, long? startTimestamp = null, long? endTimestamp = null, string? layerType = null, + IEnumerable? runtimeStatuses = null, bool orderByDescending = true, CancellationToken cancellationToken = default) { @@ -174,13 +176,32 @@ public class ProtocolLogRepository : BaseRepository, IProtocolLogRe // 构建 SQL 查询 var sql = @" SELECT pl.* - FROM ""ProtocolLogs"" pl - INNER JOIN ""CellularDeviceRuntimes"" cdr + FROM ""tb_protocol_logs"" pl + INNER JOIN ""tb_cellular_device_runtimes"" cdr ON pl.""DeviceCode"" = cdr.""DeviceCode"" - AND pl.""RuntimeCode"" = cdr.""RuntimeCode"" - WHERE pl.""DeviceCode"" = @deviceCode"; + AND pl.""RuntimeCode"" = cdr.""RuntimeCode"""; - var parameters = new List { deviceCode }; + var parameters = new List(); + + // 添加设备代码过滤(如果提供) + if (!string.IsNullOrEmpty(deviceCode)) + { + sql += " WHERE pl.\"DeviceCode\" = @deviceCode"; + parameters.Add(deviceCode); + } + else + { + sql += " WHERE 1=1"; // 如果没有设备代码,使用占位符 + } + + // 添加运行时状态过滤 + if (runtimeStatuses != null && runtimeStatuses.Any()) + { + // 支持多个运行时状态过滤 + var statusList = string.Join(",", runtimeStatuses.Select((_, i) => $"@runtimeStatus{i}")); + sql += $" AND cdr.\"RuntimeStatus\" IN ({statusList})"; + parameters.AddRange(runtimeStatuses.Cast()); + } // 添加运行时编码过滤 if (runtimeCodes != null && runtimeCodes.Any()) diff --git a/src/X1.Infrastructure/Repositories/NetworkProfile/NetworkStackConfigRepository.cs b/src/X1.Infrastructure/Repositories/NetworkProfile/NetworkStackConfigRepository.cs index 26357aa..f524d43 100644 --- a/src/X1.Infrastructure/Repositories/NetworkProfile/NetworkStackConfigRepository.cs +++ b/src/X1.Infrastructure/Repositories/NetworkProfile/NetworkStackConfigRepository.cs @@ -289,11 +289,11 @@ public class NetworkStackConfigRepository : BaseRepository, binding.""ImsId"" AS ""IMSConfigId"", ims.""Name"" AS ""IMSConfigName"", ims.""ConfigContent"" AS ""IMSConfigContent"" - FROM ""NetworkStackConfigs"" nsc - LEFT JOIN ""RAN_Configurations"" ran ON nsc.""RanId"" = ran.""Id"" - LEFT JOIN ""Stack_CoreIMS_Bindings"" binding ON nsc.""Id"" = binding.""NetworkStackConfigId"" - LEFT JOIN ""CoreNetworkConfigs"" cnc ON binding.""CnId"" = cnc.""Id"" - LEFT JOIN ""IMS_Configurations"" ims ON binding.""ImsId"" = ims.""Id"" + FROM ""tb_network_stack_configs"" nsc + LEFT JOIN ""tb_ran_configurations"" ran ON nsc.""RanId"" = ran.""Id"" + LEFT JOIN ""tb_stack_core_ims_bindings"" binding ON nsc.""Id"" = binding.""NetworkStackConfigId"" + LEFT JOIN ""tb_core_network_configs"" cnc ON binding.""CnId"" = cnc.""Id"" + LEFT JOIN ""tb_ims_configurations"" ims ON binding.""ImsId"" = ims.""Id"" WHERE nsc.""Id"" = @p0 ORDER BY binding.""Index"""; @@ -326,11 +326,11 @@ public class NetworkStackConfigRepository : BaseRepository, cnc.""ConfigContent"" AS ""CoreNetworkConfigContent"", ims.""ConfigContent"" AS ""IMSConfigContent"", binding.""Index"" - FROM ""NetworkStackConfigs"" nsc - LEFT JOIN ""RAN_Configurations"" ran ON nsc.""RanId"" = ran.""Id"" - LEFT JOIN ""Stack_CoreIMS_Bindings"" binding ON nsc.""Id"" = binding.""NetworkStackConfigId"" - LEFT JOIN ""CoreNetworkConfigs"" cnc ON binding.""CnId"" = cnc.""Id"" - LEFT JOIN ""IMS_Configurations"" ims ON binding.""ImsId"" = ims.""Id"" + FROM ""tb_network_stack_configs"" nsc + LEFT JOIN ""tb_ran_configurations"" ran ON nsc.""RanId"" = ran.""Id"" + LEFT JOIN ""tb_stack_core_ims_bindings"" binding ON nsc.""Id"" = binding.""NetworkStackConfigId"" + LEFT JOIN ""tb_core_network_configs"" cnc ON binding.""CnId"" = cnc.""Id"" + LEFT JOIN ""tb_ims_configurations"" ims ON binding.""ImsId"" = ims.""Id"" WHERE nsc.""NetworkStackCode"" IN ({paramPlaceholders}) ORDER BY nsc.""NetworkStackCode"", binding.""Index"""; @@ -383,7 +383,7 @@ public class NetworkStackConfigRepository : BaseRepository, // 计算总记录数的SQL - PostgreSQL语法 var countSql = $@" SELECT COUNT(DISTINCT nsc.""Id"") - FROM ""NetworkStackConfigs"" nsc + FROM ""tb_network_stack_configs"" nsc {whereClause}"; // 获取总记录数 @@ -414,11 +414,11 @@ public class NetworkStackConfigRepository : BaseRepository, binding.""ImsId"" AS ""IMSConfigId"", ims.""Name"" AS ""IMSConfigName"", ims.""ConfigContent"" AS ""IMSConfigContent"" - FROM ""NetworkStackConfigs"" nsc - LEFT JOIN ""RAN_Configurations"" ran ON nsc.""RanId"" = ran.""Id"" - LEFT JOIN ""Stack_CoreIMS_Bindings"" binding ON nsc.""Id"" = binding.""NetworkStackConfigId"" - LEFT JOIN ""CoreNetworkConfigs"" cnc ON binding.""CnId"" = cnc.""Id"" - LEFT JOIN ""IMS_Configurations"" ims ON binding.""ImsId"" = ims.""Id"" + FROM ""tb_network_stack_configs"" nsc + LEFT JOIN ""tb_ran_configurations"" ran ON nsc.""RanId"" = ran.""Id"" + LEFT JOIN ""tb_stack_core_ims_bindings"" binding ON nsc.""Id"" = binding.""NetworkStackConfigId"" + LEFT JOIN ""tb_core_network_configs"" cnc ON binding.""CnId"" = cnc.""Id"" + LEFT JOIN ""tb_ims_configurations"" ims ON binding.""ImsId"" = ims.""Id"" {whereClause} ORDER BY nsc.""NetworkStackName"", binding.""Index"" LIMIT @p{paramIndex} OFFSET @p{paramIndex + 1}"; diff --git a/src/X1.Presentation/Controllers/ProtocolLogsController.cs b/src/X1.Presentation/Controllers/ProtocolLogsController.cs index 3b61096..4c4d3f7 100644 --- a/src/X1.Presentation/Controllers/ProtocolLogsController.cs +++ b/src/X1.Presentation/Controllers/ProtocolLogsController.cs @@ -40,6 +40,8 @@ public class ProtocolLogsController : ApiController /// 结束时间戳 /// 协议层类型 /// 设备运行时状态 + /// 运行时代码数组 + /// 运行时状态数组 /// 是否按时间戳降序排序 /// 协议日志列表 [HttpGet("device/{deviceCode}")] @@ -49,10 +51,12 @@ public class ProtocolLogsController : ApiController [FromQuery] long? endTimestamp = null, [FromQuery] string? layerType = null, [FromQuery] int? deviceRuntimeStatus = null, + [FromQuery] string[]? runtimeCodes = null, + [FromQuery] int[]? runtimeStatuses = null, [FromQuery] bool orderByDescending = true) { - _logger.LogInformation("开始获取设备 {DeviceCode} 的协议日志,开始时间戳: {StartTimestamp}, 结束时间戳: {EndTimestamp}, 协议层类型: {LayerType}, 运行时状态: {DeviceRuntimeStatus}", - deviceCode, startTimestamp, endTimestamp, layerType, deviceRuntimeStatus); + _logger.LogInformation("开始获取设备 {DeviceCode} 的协议日志,开始时间戳: {StartTimestamp}, 结束时间戳: {EndTimestamp}, 协议层类型: {LayerType}, 运行时状态: {DeviceRuntimeStatus}, 运行时代码数量: {RuntimeCodesCount}, 运行时状态数量: {RuntimeStatusesCount}", + deviceCode, startTimestamp, endTimestamp, layerType, deviceRuntimeStatus, runtimeCodes?.Length ?? 0, runtimeStatuses?.Length ?? 0); var query = new GetProtocolLogsByDeviceQuery { @@ -61,6 +65,8 @@ public class ProtocolLogsController : ApiController EndTimestamp = endTimestamp, LayerType = layerType, DeviceRuntimeStatus = deviceRuntimeStatus.HasValue ? (DeviceRuntimeStatus)deviceRuntimeStatus.Value : null, + RuntimeCodes = runtimeCodes ?? Array.Empty(), + RuntimeStatuses = runtimeStatuses ?? Array.Empty(), OrderByDescending = orderByDescending }; @@ -75,4 +81,54 @@ public class ProtocolLogsController : ApiController deviceCode, result.Data?.Items?.Count ?? 0); return result; } + + /// + /// 获取协议日志(支持可选的设备代码) + /// + /// 设备代码(可选) + /// 开始时间戳 + /// 结束时间戳 + /// 协议层类型 + /// 设备运行时状态 + /// 运行时代码数组 + /// 运行时状态数组 + /// 是否按时间戳降序排序 + /// 协议日志列表 + [HttpGet("logs")] + public async Task> GetProtocolLogs( + [FromQuery] string? deviceCode = null, + [FromQuery] long? startTimestamp = null, + [FromQuery] long? endTimestamp = null, + [FromQuery] string? layerType = null, + [FromQuery] int? deviceRuntimeStatus = null, + [FromQuery] string[]? runtimeCodes = null, + [FromQuery] int[]? runtimeStatuses = null, + [FromQuery] bool orderByDescending = true) + { + _logger.LogInformation("开始获取协议日志,设备代码: {DeviceCode}, 开始时间戳: {StartTimestamp}, 结束时间戳: {EndTimestamp}, 协议层类型: {LayerType}, 运行时状态: {DeviceRuntimeStatus}, 运行时代码数量: {RuntimeCodesCount}, 运行时状态数量: {RuntimeStatusesCount}", + deviceCode, startTimestamp, endTimestamp, layerType, deviceRuntimeStatus, runtimeCodes?.Length ?? 0, runtimeStatuses?.Length ?? 0); + + var query = new GetProtocolLogsByDeviceQuery + { + DeviceCode = deviceCode, + StartTimestamp = startTimestamp, + EndTimestamp = endTimestamp, + LayerType = layerType, + DeviceRuntimeStatus = deviceRuntimeStatus.HasValue ? (DeviceRuntimeStatus)deviceRuntimeStatus.Value : null, + RuntimeCodes = runtimeCodes ?? Array.Empty(), + RuntimeStatuses = runtimeStatuses ?? Array.Empty(), + OrderByDescending = orderByDescending + }; + + var result = await mediator.Send(query); + if (!result.IsSuccess) + { + _logger.LogWarning("获取协议日志失败: {Message}", result.ErrorMessages); + return result; + } + + _logger.LogInformation("成功获取协议日志,共 {Count} 条记录", + result.Data?.Items?.Count ?? 0); + return result; + } } \ No newline at end of file diff --git a/src/modify.md b/src/modify.md index f1e052a..50647d9 100644 --- a/src/modify.md +++ b/src/modify.md @@ -1,5 +1,170 @@ # 修改记录 +## 2025-01-29 - 协议日志查询功能优化和简化 + +### 修改概述 +根据用户需求,对协议日志查询功能进行了全面优化和简化,主要包括: +1. 简化查询处理器逻辑,移除复杂的运行时编码过滤参数准备 +2. 支持可空的设备代码参数 +3. 添加运行时代码数组参数,支持直接从前端传递 +4. 添加运行时状态数组参数,支持从前端传入运行时状态过滤条件 +5. 优化数据库查询性能 + +### 修改文件 + +#### 1. `X1.Application/Features/ProtocolLogs/Queries/GetProtocolLogsByDevice/GetProtocolLogsByDeviceQuery.cs` +- **设备代码可空化**:将 `DeviceCode` 属性改为可空类型 `string?`,移除 `[Required]` 特性 +- **新增运行时代码参数**:添加 `RuntimeCodes` 属性,类型为 `string[]`,默认值为空数组 +- **新增运行时状态参数**:添加 `RuntimeStatuses` 属性,类型为 `int[]`,默认值为空数组 +- **参数说明**:运行时代码数组和运行时状态数组,用于直接过滤协议日志,支持从前端直接传递 + +#### 2. `X1.Application/Features/ProtocolLogs/Queries/GetProtocolLogsByDevice/GetProtocolLogsByDeviceQueryHandler.cs` +- **移除复杂逻辑**:删除"准备运行时编码过滤参数"的复杂逻辑 +- **简化处理**:直接使用 `request.RuntimeCodes` 和 `request.RuntimeStatuses` 传递给仓储方法 +- **移除依赖**:不再需要调用 `_deviceRuntimeRepository.GetRuntimesByStatusAsync` +- **代码简化**:大幅简化了查询处理器的逻辑,提高可维护性 +- **动态过滤**:根据前端传入的运行时状态数组进行动态过滤,空数组时不进行过滤 + +#### 3. `X1.Infrastructure/Repositories/Logging/ProtocolLogRepository.cs` +- **支持可空设备代码**:`GetByDeviceWithFiltersAsync` 方法的 `deviceCode` 参数改为可空类型 +- **SQL查询优化**:当设备代码为空时,使用 `WHERE 1=1` 占位符,确保SQL语法正确 +- **条件查询**:根据设备代码是否为空,动态构建WHERE子句 +- **性能优化**:保持原有的高性能JOIN查询结构 + +#### 4. `X1.Domain/Repositories/Logging/IProtocolLogRepository.cs` +- **接口更新**:更新 `GetByDeviceWithFiltersAsync` 方法签名,使 `deviceCode` 参数可空 +- **保持一致性**:确保接口与实现类完全匹配 + +#### 5. `X1.Presentation/Controllers/ProtocolLogsController.cs` +- **新增API端点**:添加 `[HttpGet("logs")]` 端点,支持可空设备代码查询 +- **参数增强**:在两个API端点中添加 `runtimeCodes` 和 `runtimeStatuses` 查询参数 +- **日志增强**:在日志中记录运行时代码和运行时状态的数量 +- **默认值处理**:当参数为null时使用空数组作为默认值 + +### 技术改进 + +#### 1. 架构简化 +- **移除中间层**:不再需要通过运行时状态查询获取运行时代码 +- **直接传递**:客户端直接提供运行时代码数组 +- **减少依赖**:查询处理器不再依赖 `ICellularDeviceRuntimeRepository` + +#### 2. 性能优化 +- **减少数据库查询**:不再需要额外的运行时状态查询 +- **简化逻辑**:减少了复杂的数据处理逻辑 +- **提高响应速度**:直接使用客户端提供的参数 + +#### 3. 灵活性提升 +- **客户端控制**:客户端可以灵活指定要查询的运行时代码 +- **参数组合**:支持与其他过滤参数(时间戳、协议层类型等)组合使用 +- **向后兼容**:保持现有的API接口兼容性 + +### API使用示例 + +#### 1. 查询特定运行时代码的协议日志 +``` +GET /api/protocol-logs/device/DEV001?runtimeCodes=RT-001-DEV001&runtimeCodes=RT-002-DEV001 +``` + +#### 2. 查询特定运行时状态的协议日志 +``` +GET /api/protocol-logs/device/DEV001?runtimeStatuses=1&runtimeStatuses=2 +``` + +#### 3. 组合查询(运行时代码 + 运行时状态) +``` +GET /api/protocol-logs/device/DEV001?runtimeCodes=RT-001-DEV001&runtimeStatuses=1&startTimestamp=1640995200000&endTimestamp=1641081600000&layerType=NAS +``` + +#### 4. 查询所有协议日志(不指定设备代码) +``` +GET /api/protocol-logs/logs?runtimeCodes=RT-001-DEV001&runtimeStatuses=1 +``` + +### 影响范围 +- **API接口**:新增 `runtimeCodes` 和 `runtimeStatuses` 查询参数支持,设备代码参数变为可空 +- **查询性能**:提高查询响应速度,减少数据库查询次数 +- **代码复杂度**:大幅简化查询处理器的逻辑 +- **客户端控制**:提供更灵活的查询控制能力 +- **过滤灵活性**:支持按运行时代码和运行时状态进行精确过滤 + +### 注意事项 +- 客户端需要自行提供正确的运行时代码数组 +- 空数组或不提供参数将查询所有协议日志 +- 保持与现有API的向后兼容性 +- 设备代码为空时,将查询所有设备的协议日志 + +--- + +## 2025-01-29 - 简化协议日志查询处理器并添加运行时代码参数 + +### 修改原因 +根据用户需求,简化 `GetProtocolLogsByDeviceQueryHandler` 的逻辑,移除复杂的运行时编码过滤参数准备逻辑,改为直接使用查询请求中的 `runtimeCodes` 数组参数。 + +### 修改文件 + +#### 1. `X1.Application/Features/ProtocolLogs/Queries/GetProtocolLogsByDevice/GetProtocolLogsByDeviceQuery.cs` +- **新增参数**:添加 `RuntimeCodes` 属性,类型为 `string[]`,默认值为空数组 +- **参数说明**:运行时代码数组,用于直接过滤协议日志 + +#### 2. `X1.Application/Features/ProtocolLogs/Queries/GetProtocolLogsByDevice/GetProtocolLogsByDeviceQueryHandler.cs` +- **移除复杂逻辑**:删除"准备运行时编码过滤参数"的复杂逻辑 +- **简化处理**:直接使用 `request.RuntimeCodes` 传递给仓储方法 +- **移除依赖**:不再需要调用 `_deviceRuntimeRepository.GetRuntimesByStatusAsync` +- **代码简化**:大幅简化了查询处理器的逻辑 + +#### 3. `X1.Presentation/Controllers/ProtocolLogsController.cs` +- **新增参数**:在两个API端点中添加 `runtimeCodes` 查询参数 +- **参数处理**:支持 `string[]?` 类型的运行时代码数组 +- **日志增强**:在日志中记录运行时代码的数量 +- **默认值处理**:当参数为null时使用空数组作为默认值 + +### 技术改进 + +#### 1. 简化架构 +- **移除中间层**:不再需要通过运行时状态查询获取运行时代码 +- **直接传递**:客户端直接提供运行时代码数组 +- **减少依赖**:查询处理器不再依赖 `ICellularDeviceRuntimeRepository` + +#### 2. 性能优化 +- **减少数据库查询**:不再需要额外的运行时状态查询 +- **简化逻辑**:减少了复杂的数据处理逻辑 +- **提高响应速度**:直接使用客户端提供的参数 + +#### 3. 灵活性提升 +- **客户端控制**:客户端可以灵活指定要查询的运行时代码 +- **参数组合**:支持与其他过滤参数(时间戳、协议层类型等)组合使用 +- **向后兼容**:保持现有的API接口兼容性 + +### API使用示例 + +#### 1. 查询特定运行时代码的协议日志 +``` +GET /api/protocol-logs/device/DEV001?runtimeCodes=RT-001-DEV001&runtimeCodes=RT-002-DEV001 +``` + +#### 2. 组合查询 +``` +GET /api/protocol-logs/device/DEV001?runtimeCodes=RT-001-DEV001&startTimestamp=1640995200000&endTimestamp=1641081600000&layerType=NAS +``` + +#### 3. 查询所有协议日志(不指定运行时代码) +``` +GET /api/protocol-logs/logs?deviceCode=DEV001 +``` + +### 影响范围 +- **API接口**:新增 `runtimeCodes` 查询参数支持 +- **查询性能**:提高查询响应速度,减少数据库查询次数 +- **代码复杂度**:大幅简化查询处理器的逻辑 +- **客户端控制**:提供更灵活的查询控制能力 + +### 注意事项 +- 客户端需要自行提供正确的运行时代码数组 +- 空数组或不提供参数将查询所有协议日志 +- 保持与现有API的向后兼容性 + +--- + ## 2024-12-19 - DeviceManagementService 依赖注入修复 ### 问题描述 @@ -5992,4 +6157,206 @@ public async Task StartNetworkAsync( ### 影响 - 需要重新生成数据库迁移文件 - 如果数据库中已有数据,需要手动迁移数据 -- 所有相关的查询和存储过程可能需要更新 \ No newline at end of file +- 所有相关的查询和存储过程可能需要更新 + +--- + +## 2025-01-29 - Git撤回所有代码更改 + +### 操作概述 +使用 `git restore .` 命令撤回了所有未提交的代码更改,将工作目录恢复到干净状态。 + +### 撤回的文件 +- `X1.Application/Features/DeviceRuntimes/Queries/GetDeviceRuntimeStatus/GetDeviceRuntimeStatusQueryHandler.cs` +- `X1.Application/Features/ProtocolLogs/Queries/GetProtocolLogsByDevice/GetProtocolLogsByDeviceQuery.cs` +- `X1.Application/Features/ProtocolLogs/Queries/GetProtocolLogsByDevice/GetProtocolLogsByDeviceQueryHandler.cs` +- `X1.Domain/Repositories/Logging/IProtocolLogRepository.cs` +- `X1.Infrastructure/Repositories/Logging/ProtocolLogRepository.cs` +- `X1.Presentation/Controllers/DeviceRuntimesController.cs` +- `modify.md` + +### 操作结果 +- 所有未提交的更改已被撤回 +- 工作目录状态:`nothing to commit, working tree clean` +- 代码库恢复到最近的提交状态 + +### 技术说明 +- 使用 `git restore .` 命令撤回所有工作目录中的更改 +- 该操作不会影响已提交的代码 +- 撤回操作是安全的,不会丢失已提交的历史记录 + +### 影响范围 +- 所有未提交的代码更改已被撤回 +- 工作目录恢复到干净状态 +- 可以重新开始开发工作 + +--- + +## 2025-01-29 - 修复NetworkStackConfigRepository中的表名 + +### 修改原因 +由于之前将数据库表名修改为以`tb_`开头的小写下划线命名方式,需要修复`NetworkStackConfigRepository`中的两个方法,使其SQL查询使用正确的表名。 + +### 修改文件 +- `X1.Infrastructure/Repositories/NetworkProfile/NetworkStackConfigRepository.cs` - 修复表名引用 + +### 修改内容 + +#### 1. GetNetworkStackConfigByIdWithBindingNamesAsync方法 +- **修复表名**: + - `"NetworkStackConfigs"` → `"tb_network_stack_configs"` + - `"RAN_Configurations"` → `"tb_ran_configurations"` + - `"Stack_CoreIMS_Bindings"` → `"tb_stack_core_ims_bindings"` + - `"CoreNetworkConfigs"` → `"tb_core_network_configs"` + - `"IMS_Configurations"` → `"tb_ims_configurations"` + +#### 2. GetNetworkStackConfigsByCodesAsync方法 +- **修复表名**:与上述方法相同的表名修复 + +#### 3. SearchNetworkStackConfigsWithBindingNamesAsync方法 +- **修复表名**: + - 总记录数查询中的表名修复 + - 分页查询中的表名修复 + - 所有JOIN语句中的表名修复 + +### 技术说明 +- 所有表名都改为以`tb_`开头的小写下划线命名方式 +- 保持PostgreSQL语法和双引号包围 +- 确保SQL查询与数据库实际表名一致 + +### 影响范围 +- 修复了网络栈配置查询功能 +- 确保SQL查询能够正确执行 +- 避免了因表名不匹配导致的查询错误 + +--- + +## 2025-01-29 - 修复ProtocolLogRepository中的表名 + +### 修改原因 +由于之前将数据库表名修改为以`tb_`开头的小写下划线命名方式,需要修复`ProtocolLogRepository`中的`GetByDeviceWithFiltersAsync`方法,使其SQL查询使用正确的表名。 + +### 修改文件 +- `X1.Infrastructure/Repositories/Logging/ProtocolLogRepository.cs` - 修复表名引用 + +### 修改内容 + +#### GetByDeviceWithFiltersAsync方法 +- **修复表名**: + - `"ProtocolLogs"` → `"tb_protocol_logs"` + - `"CellularDeviceRuntimes"` → `"tb_cellular_device_runtimes"` + +### 技术说明 +- 修复了SQL查询中的表名引用 +- 保持了PostgreSQL语法和双引号包围 +- 确保SQL查询与数据库实际表名一致 +- 该方法用于高性能查询设备协议日志,包含多个过滤条件 + +### 影响范围 +- 修复了协议日志查询功能 +- 确保SQL查询能够正确执行 +- 避免了因表名不匹配导致的查询错误 + +--- + +## 2025-01-29 - 优化ProtocolLogRepository支持动态运行时状态过滤 + +### 修改原因 +根据用户需求,优化 `GetByDeviceWithFiltersAsync` 方法,支持动态传入运行时状态过滤条件,移除固定的 `onlyRunningStatus` 参数,改为支持多个运行时状态的灵活过滤。 + +### 修改文件 +- `X1.Infrastructure/Repositories/Logging/ProtocolLogRepository.cs` - 优化运行时状态过滤 +- `X1.Domain/Repositories/Logging/IProtocolLogRepository.cs` - 更新接口定义 + +### 修改内容 + +#### 1. 接口定义更新 +- **移除参数**:移除 `onlyRunningStatus` 参数 +- **保留参数**:保留 `runtimeStatuses` 参数,支持传入多个运行时状态进行过滤 +- **参数类型**:`IEnumerable? runtimeStatuses` - 支持传入多个状态值 + +#### 2. 实现逻辑优化 +- **移除兼容逻辑**:移除 `onlyRunningStatus` 的兼容处理逻辑 +- **简化过滤条件**:只保留 `runtimeStatuses` 的动态过滤逻辑 +- **参数转换**:使用 `Cast()` 确保参数类型正确转换 + +#### 3. 使用示例 +```csharp +// 查询运行中的设备日志 +var runningLogs = await repository.GetByDeviceWithFiltersAsync( + deviceCode: "DEV001", + runtimeStatuses: new[] { 1 } // DeviceRuntimeStatus.Running = 1 +); + +// 查询运行中和停止中的设备日志 +var activeLogs = await repository.GetByDeviceWithFiltersAsync( + deviceCode: "DEV001", + runtimeStatuses: new[] { 1, 2 } // Running 和 Stopping +); + +// 查询所有状态的设备日志(不传入 runtimeStatuses 参数) +var allLogs = await repository.GetByDeviceWithFiltersAsync( + deviceCode: "DEV001" +); +``` + +### 技术特性 +- **灵活性**:支持传入任意组合的运行时状态进行过滤 +- **性能优化**:使用 IN 查询一次性过滤多个状态 +- **向后兼容**:不传入 `runtimeStatuses` 参数时查询所有状态 +- **类型安全**:确保参数类型正确转换,避免运行时错误 + +### 业务价值 +- **动态过滤**:支持根据业务需求动态选择要查询的设备状态 +- **查询效率**:减少多次查询的需求,提高查询效率 +- **代码简化**:移除冗余的兼容逻辑,代码更清晰 +- **扩展性**:为未来添加新的运行时状态预留了接口 + +--- + +## 2025-01-29 - 修复GetProtocolLogsByDeviceQueryHandler参数不匹配问题 + +### 修改原因 +`GetProtocolLogsByDeviceQueryHandler` 中调用 `GetByDeviceWithFiltersAsync` 方法时参数顺序不匹配,需要修复参数传递问题。 + +### 修改文件 +- `X1.Application/Features/ProtocolLogs/Queries/GetProtocolLogsByDevice/GetProtocolLogsByDeviceQueryHandler.cs` - 修复参数传递 + +### 修改内容 + +#### 1. 简化运行时状态过滤逻辑 +- **移除复杂查询**:不再通过 `ICellularDeviceRuntimeRepository` 查询运行时状态 +- **直接使用状态过滤**:直接使用 `runtimeStatuses` 参数进行过滤 +- **减少数据库查询**:避免额外的数据库查询,提高性能 + +#### 2. 修复方法调用参数 +- **参数顺序**:确保参数顺序与 `GetByDeviceWithFiltersAsync` 方法签名一致 +- **参数类型**:正确传递 `runtimeStatuses` 参数 +- **参数说明**:添加注释说明参数用途 + +#### 3. 优化代码逻辑 +```csharp +// 修改前:复杂的运行时状态查询逻辑 +var deviceRuntimes = await _deviceRuntimeRepository.GetRuntimesByDeviceCodeAsync(...); +var matchingRuntimes = deviceRuntimes.Where(r => r.RuntimeStatus == request.DeviceRuntimeStatus.Value); +var runtimeCodes = matchingRuntimes.Select(r => r.RuntimeCode).ToList(); + +// 修改后:直接使用状态过滤 +IEnumerable? runtimeStatuses = null; +if (request.DeviceRuntimeStatus.HasValue) +{ + runtimeStatuses = new[] { (int)request.DeviceRuntimeStatus.Value }; +} +``` + +### 技术改进 +- **性能优化**:减少数据库查询次数,提高查询性能 +- **代码简化**:移除复杂的运行时状态查询逻辑 +- **参数一致性**:确保方法调用参数与接口定义一致 +- **错误处理**:简化错误处理逻辑,减少潜在的错误点 + +### 影响范围 +- **查询性能**:提高了协议日志查询的性能 +- **代码维护性**:简化了代码逻辑,便于维护 +- **功能完整性**:保持了原有的过滤功能 +- **接口一致性**:确保所有调用都使用正确的参数顺序 \ No newline at end of file