From 56890fb32657c8e66ed9439966d902eb0a0ac55d Mon Sep 17 00:00:00 2001 From: hyh Date: Mon, 4 Aug 2025 12:00:35 +0800 Subject: [PATCH] =?UTF-8?q?GetProtocolLogsNotInActiveRuntimesAsync=20?= =?UTF-8?q?=E5=8E=BB=E9=99=A4=E5=A4=9A=E8=A1=A8=E5=85=B3=E8=81=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../GetProtocolLogsByDeviceQueryHandler.cs | 2 +- .../Logging/IProtocolLogRepository.cs | 22 + .../Logging/ProtocolLogRepository.cs | 136 + src/modify.md | 7292 +---------------- 4 files changed, 254 insertions(+), 7198 deletions(-) diff --git a/src/X1.Application/Features/ProtocolLogs/Queries/GetProtocolLogsByDevice/GetProtocolLogsByDeviceQueryHandler.cs b/src/X1.Application/Features/ProtocolLogs/Queries/GetProtocolLogsByDevice/GetProtocolLogsByDeviceQueryHandler.cs index af8fb09..982edb0 100644 --- a/src/X1.Application/Features/ProtocolLogs/Queries/GetProtocolLogsByDevice/GetProtocolLogsByDeviceQueryHandler.cs +++ b/src/X1.Application/Features/ProtocolLogs/Queries/GetProtocolLogsByDevice/GetProtocolLogsByDeviceQueryHandler.cs @@ -54,7 +54,7 @@ public class GetProtocolLogsByDeviceQueryHandler : IRequestHandler /// RuntimeCode和DeviceCode列表 Task> GetRuntimeDeviceCodesNotInActiveRuntimesAsync(CancellationToken cancellationToken = default); + /// + /// 获取不在活跃运行时状态中的协议日志(高性能查询,不包含MessageDetailJson) + /// + /// 设备代码 + /// 运行时代码集合 + /// 开始时间戳 + /// 结束时间戳 + /// 协议层类型数组 + /// 运行时状态过滤(可选,支持多个状态) + /// 是否按时间戳降序排序 + /// 取消令牌 + /// 协议日志列表DTO + Task> GetProtocolLogsNotInActiveRuntimesAsync( + string? deviceCode, + IEnumerable? runtimeCodes = null, + long? startTimestamp = null, + long? endTimestamp = null, + IEnumerable? layerTypes = null, + IEnumerable? runtimeStatuses = null, + bool orderByDescending = true, + CancellationToken cancellationToken = default); + } \ No newline at end of file diff --git a/src/X1.Infrastructure/Repositories/Logging/ProtocolLogRepository.cs b/src/X1.Infrastructure/Repositories/Logging/ProtocolLogRepository.cs index 4ef2015..32d91e6 100644 --- a/src/X1.Infrastructure/Repositories/Logging/ProtocolLogRepository.cs +++ b/src/X1.Infrastructure/Repositories/Logging/ProtocolLogRepository.cs @@ -356,4 +356,140 @@ public class ProtocolLogRepository : BaseRepository, IProtocolLogRe throw; } } + + /// + /// 获取不在活跃运行时状态中的协议日志(高性能查询,不包含MessageDetailJson) + /// + /// 设备代码 + /// 运行时代码集合 + /// 开始时间戳 + /// 结束时间戳 + /// 协议层类型数组 + /// 运行时状态过滤(可选,支持多个状态) + /// 是否按时间戳降序排序 + /// 取消令牌 + /// 协议日志列表DTO + public async Task> GetProtocolLogsNotInActiveRuntimesAsync( + string? deviceCode, + IEnumerable? runtimeCodes = null, + long? startTimestamp = null, + long? endTimestamp = null, + IEnumerable? layerTypes = null, + IEnumerable? runtimeStatuses = null, + bool orderByDescending = false, + CancellationToken cancellationToken = default) + { + try + { + // 构建 SQL 查询 - 基于您提供的SQL,但添加了与GetByDeviceWithFiltersAsync相同的过滤条件 + var sql = @" + SELECT + pl.""Id"", + pl.""MessageId"", + pl.""LayerType"", + pl.""CellID"", + pl.""IMSI"", + pl.""Direction"", + pl.""UEID"", + pl.""PLMN"", + pl.""TimeMs"", + pl.""Timestamp"", + pl.""Info"", + pl.""Message"", + pl.""DeviceCode"", + pl.""RuntimeCode"" + FROM ""tb_protocol_logs"" pl + WHERE "; + + // 根据 runtimeStatuses 参数动态决定使用 EXISTS 还是 NOT EXISTS + bool containsActiveStatus = runtimeStatuses != null && runtimeStatuses.Contains(1); + if (containsActiveStatus) + { + sql += @"EXISTS ( + SELECT 1 + FROM ""tb_cellular_device_runtimes"" t + WHERE t.""RuntimeStatus"" = 1 + AND t.""RuntimeCode"" = pl.""RuntimeCode"" + )"; + } + else + { + sql += @"NOT EXISTS ( + SELECT 1 + FROM ""tb_cellular_device_runtimes"" t + WHERE t.""RuntimeStatus"" = 1 + AND t.""RuntimeCode"" = pl.""RuntimeCode"" + )"; + } + + var parameters = new List(); + var paramIndex = 0; + + // 添加设备代码过滤 + if (!string.IsNullOrEmpty(deviceCode)) + { + sql += $" AND pl.\"DeviceCode\" = {{{paramIndex}}}"; + parameters.Add(deviceCode); + paramIndex++; + } + + // 添加时间范围过滤 + if (startTimestamp.HasValue) + { + sql += $" AND pl.\"Timestamp\" >= {{{paramIndex}}}"; + parameters.Add(startTimestamp.Value); + paramIndex++; + } + + if (endTimestamp.HasValue) + { + sql += $" AND pl.\"Timestamp\" <= {{{paramIndex}}}"; + parameters.Add(endTimestamp.Value); + paramIndex++; + } + + // 添加协议层类型过滤 + if (layerTypes != null && layerTypes.Any()) + { + var layerTypeList = string.Join(",", layerTypes.Select((_, i) => $"{{{paramIndex + i}}}")); + sql += $" AND pl.\"LayerType\" IN ({layerTypeList})"; + foreach (var layerType in layerTypes) + { + parameters.Add(layerType); + } + paramIndex += layerTypes.Count(); + } + + // 添加运行时代码过滤 + if (runtimeCodes != null && runtimeCodes.Any()) + { + var runtimeCodeList = string.Join(",", runtimeCodes.Select((_, i) => $"{{{paramIndex + i}}}")); + sql += $" AND pl.\"RuntimeCode\" IN ({runtimeCodeList})"; + parameters.AddRange(runtimeCodes); + paramIndex += runtimeCodes.Count(); + } + + // 添加排序 + if (orderByDescending) + { + sql += " ORDER BY pl.\"Timestamp\" DESC"; + } + else + { + sql += " ORDER BY pl.\"Timestamp\" ASC"; + } + + // 执行SQL查询,直接映射到ProtocolLogListDto + var result = await QueryRepository.ExecuteSqlQueryAsync(sql, parameters.ToArray(), cancellationToken); + + _logger.LogDebug("获取不在活跃运行时状态中的协议日志,结果数量:{Count}", result.Count()); + + return result; + } + catch (Exception ex) + { + _logger.LogError(ex, "获取不在活跃运行时状态中的协议日志时发生错误"); + throw; + } + } } \ No newline at end of file diff --git a/src/modify.md b/src/modify.md index 60c8f49..5528a1c 100644 --- a/src/modify.md +++ b/src/modify.md @@ -1,7202 +1,100 @@ # 修改记录 -## 2025-01-29 - DeviceManagementService 事务管理优化 - -### 修改概述 -根据用户需求,将 `DeviceManagementService` 中的手动事务管理代码替换为使用 `unitOfWork.ExecuteTransactionAsync` 方法,简化事务处理逻辑,提高代码可读性和维护性。 - -### 修改文件 -- `X1.Application/BackendServiceManager/DeviceManagementService.cs` - 优化事务管理代码 - -### 修改内容 - -#### 1. 批量插入协议日志事务优化 -- **原实现**:使用手动的事务管理,包括 `BeginTransactionAsync`、`CommitTransactionAsync`、`RollbackTransactionAsync` -- **新实现**:使用 `ExecuteTransactionAsync` 方法,自动处理事务的提交和回滚 -- **代码简化**:移除了复杂的 try-catch 块和手动事务管理代码 -- **错误处理**:`ExecuteTransactionAsync` 内部自动处理异常和回滚 - -#### 2. 逐个插入协议日志事务优化 -- **原实现**:在循环中手动管理每个批次的事务 -- **新实现**:使用 `ExecuteTransactionAsync` 包装每个批次的处理逻辑 -- **性能保持**:保持原有的分批处理逻辑,避免内存问题 -- **事务安全**:每个批次在独立的事务中处理,确保数据一致性 - -### 技术特性 - -#### 1. ExecuteTransactionAsync 方法优势 -- **自动事务管理**:自动处理事务的开始、提交和回滚 -- **异常处理**:内置异常处理机制,异常时自动回滚 -- **资源管理**:自动释放事务资源,避免资源泄漏 -- **执行策略**:使用 Entity Framework 的执行策略,提高可靠性 - -#### 2. 代码简化效果 -- **减少代码量**:大幅减少事务管理相关的代码 -- **提高可读性**:事务逻辑更加清晰,易于理解 -- **降低复杂度**:移除了手动事务管理的复杂性 -- **减少错误**:避免手动事务管理可能出现的错误 - -#### 3. 性能影响 -- **保持性能**:事务处理性能基本保持不变 -- **资源优化**:更好的资源管理和释放 -- **并发安全**:使用执行策略提高并发处理的安全性 - -### 业务价值 -- **代码质量**:提高代码的可读性和可维护性 -- **开发效率**:减少事务管理相关的开发工作 -- **系统稳定性**:降低手动事务管理可能导致的错误 -- **维护便利**:简化的事务逻辑便于后续维护和调试 - -### 影响范围 -- **事务处理**:所有协议日志处理的事务管理方式 -- **错误处理**:异常处理逻辑更加统一和可靠 -- **代码结构**:简化了事务相关的代码结构 -- **开发体验**:减少了事务管理的复杂性 - -### 注意事项 -- 保持了原有的业务逻辑不变 -- 保持了原有的性能特性 -- 保持了原有的错误处理机制 -- 事务的原子性得到更好的保证 - ---- - -## 2025-01-29 - ProtocolLogsController 修复 GetProtocolLogsByDevice 和 GetProtocolLogs 改为 POST 方式并合并 - -### 修改概述 -根据用户需求,将 ProtocolLogsController 中的 `GetProtocolLogsByDevice` 和 `GetProtocolLogs` 方法从 GET 方式改为 POST 方式,直接使用现有的 `GetProtocolLogsByDeviceQuery` 作为请求模型,并将两个方法合并为一个统一的接口,简化代码结构。 - -### 修改文件 -- `X1.Presentation/Controllers/ProtocolLogsController.cs` - 修改协议日志控制器 - -### 修改内容 - -#### 1. 简化请求模型 -- **移除 ProtocolLogsQueryRequest 类**:直接使用现有的 `GetProtocolLogsByDeviceQuery` 作为请求模型 -- **代码复用**:避免重复定义相同的属性,减少代码冗余 -- **类型一致性**:确保请求模型与查询模型完全一致 - -#### 2. 方法合并 -- **合并为单一方法**:将 `GetProtocolLogsByDevice` 和 `GetProtocolLogs` 合并为 `GetProtocolLogs` -- **统一路由**:使用 `[HttpPost("logs")]` 作为统一入口 -- **参数统一**:所有参数(包括设备代码)都从请求体获取 -- **简化逻辑**:移除设备代码的特殊处理逻辑 - -#### 3. 业务逻辑更新 -- **参数处理**:直接从 `query` 对象中获取所有查询参数 -- **设备代码处理**:设备代码作为可选参数,在请求体中传递 -- **日志记录**:更新日志记录,使用查询对象中的参数 -- **查询执行**:直接使用查询对象执行,无需额外的对象转换 -- **代码简化**:移除重复代码,统一处理逻辑 - -### 技术特性 - -#### 1. POST 方式优势 -- **参数复杂性**:支持复杂的查询参数,包括数组类型 -- **安全性**:敏感参数不会出现在 URL 中 -- **数据大小**:支持更大的查询参数 -- **一致性**:与其他复杂查询接口保持一致 - -#### 2. 请求模型设计 -- **类型安全**:使用强类型的请求模型 -- **可选参数**:大部分参数都是可选的,提供灵活性 -- **默认值**:为常用参数提供合理的默认值 -- **文档完整**:为所有属性添加 XML 文档注释 - -#### 3. 向后兼容性 -- **API 路径**:保持原有的 API 路径不变 -- **响应格式**:保持原有的响应格式不变 -- **业务逻辑**:保持原有的查询逻辑不变 - -### API 使用示例 - -#### 1. 根据设备代码获取协议日志 -```http -POST /api/protocol-logs/logs -Content-Type: application/json - -{ - "deviceCode": "DEV001", - "startTimestamp": 1640995200000, - "endTimestamp": 1641081600000, - "layerType": "NAS", - "deviceRuntimeStatus": 1, - "runtimeCodes": ["RT-001-DEV001", "RT-002-DEV001"], - "runtimeStatuses": [1, 2], - "orderByDescending": true -} -``` - -#### 2. 获取所有协议日志(不指定设备代码) -```http -POST /api/protocol-logs/logs -Content-Type: application/json - -{ - "startTimestamp": 1640995200000, - "endTimestamp": 1641081600000, - "layerType": "RRC", - "runtimeStatuses": [1] -} -``` - -### 影响范围 -- **API 接口**:从 GET 改为 POST 方式,需要更新客户端调用 -- **API 路径**:统一使用 `/api/protocol-logs/logs` 路径 -- **参数传递**:从 URL 查询参数改为请求体 JSON 参数 -- **客户端适配**:前端需要更新调用方式和路径 -- **文档更新**:需要更新 API 文档 - -### 注意事项 -- 客户端需要将原来的 GET 请求改为 POST 请求 -- 查询参数需要从 URL 移到请求体中 -- 原来使用 `/api/protocol-logs/device/{deviceCode}` 的客户端需要改为使用 `/api/protocol-logs/logs` 并在请求体中包含 `deviceCode` -- 设备代码现在是可选参数,可以在请求体中指定或省略 -- 需要设置正确的 Content-Type 头 -- 保持原有的业务逻辑和响应格式不变 - ---- - -## 2025-01-29 - StopDeviceRuntimeCommandHandler重构优化 - -### 修改概述 -根据用户需求,对StopDeviceRuntimeCommandHandler进行了全面重构,主要改进包括: -1. 将Handle方法重构为多个私有方法,提高代码可读性 -2. 修复StopNetworkAsync的并行执行问题 -3. 提取方法以提高代码的可维护性 -4. 修复代码中的错误和逻辑问题 - -### 修改文件 - -#### 1. `X1.Application/Features/DeviceRuntimes/Commands/StopDeviceRuntime/StopDeviceRuntimeCommandHandler.cs` -- **方法重构**:将Handle方法拆分为多个职责明确的私有方法 -- **并行执行优化**:修复StopNetworkAsync的并行执行,确保所有网络停止操作同时进行 -- **代码可读性提升**:提取以下私有方法: - - `ValidateRequest()` - 验证请求参数 - - `GetCurrentUser()` - 获取当前用户 - - `GetDeviceRuntimesAsync()` - 获取设备运行时状态 - - `ProcessDeviceStop()` - 处理设备停止(同步方法) - - `ProcessSingleDevice()` - 处理单个设备停止(同步方法) - - `StopNetworkConnectionsAsync()` - 并行停止网络连接 - - `BuildResults()` - 构建结果 - - `SaveDataAsync()` - 保存数据 -- **错误修复**: - - 修复StopNetworkAsync中的参数错误(Key字段赋值错误) - - 修复并行执行中的变量引用问题 - - 优化网络停止结果的处理逻辑 -- **性能优化**: - - 使用Task.WhenAll实现真正的并行执行 - - 优化结果收集和处理逻辑 - - 改进错误处理和日志记录 - -#### 2. 新增内部类 -- **DeviceProcessingResult类**:用于封装设备处理结果,包含设备编号、成功状态、运行时对象、详情对象和错误信息 - -### 技术改进 - -#### 1. 代码结构优化 -- **单一职责原则**:每个方法只负责一个特定的功能 -- **方法提取**:将复杂的逻辑拆分为可读性更高的方法 -- **参数传递**:通过方法参数传递数据,减少对成员变量的依赖 - -#### 2. 并行执行修复 -- **Task.WhenAll**:使用Task.WhenAll确保所有网络停止操作真正并行执行 -- **结果收集**:正确收集并行操作的结果并处理 -- **错误处理**:每个并行操作都有独立的错误处理 - -#### 3. 错误处理增强 -- **分层处理**:不同层级的错误有不同的处理策略 -- **详细日志**:提供更详细的错误信息和上下文 -- **异常传播**:合理处理异常传播,避免不必要的异常捕获 - -#### 4. 性能优化 -- **批量操作**:保持原有的批量操作性能优势 -- **并行处理**:网络停止操作真正并行执行 -- **内存优化**:减少不必要的对象创建 -- **同步优化**:避免为了异步而异步,将没有异步操作的方法改为同步方法 -- **异常处理优化**:移除不必要的try-catch包装,简化代码逻辑 -- **空值检查优化**:添加对RuntimeCode和NetworkStackCode的空值检查,避免运行时异常 -- **跟踪日志增强**:为StopNetworkConnectionsAsync方法添加详细的跟踪日志,包括处理进度、统计信息和错误详情 -- **Handle方法跟踪日志**:为Handle方法添加完整的跟踪日志,包括请求ID、各阶段执行状态、性能统计和错误追踪 - -### 业务价值 -- **代码可读性**:重构后的代码更容易理解和维护 -- **性能提升**:网络停止操作真正并行执行,提高批量操作效率 -- **错误处理**:更精确的错误处理和用户反馈 -- **可维护性**:模块化的代码结构便于后续维护和扩展 - -### 影响范围 -- **代码质量**:显著提高代码的可读性和可维护性 -- **性能表现**:网络停止操作的并行执行提高批量操作效率 -- **错误处理**:更准确的错误信息和处理策略 -- **开发体验**:清晰的代码结构便于后续开发和调试 - -### 注意事项 -- 保持了原有的API接口和响应格式 -- 保持了原有的业务逻辑和验证规则 -- 保持了原有的日志记录和错误处理机制 -- 重构后的代码更容易进行单元测试 - ---- - -## 2025-01-29 - StopDeviceRuntime批量操作性能优化 - -### 修改概述 -根据用户需求,对StopDeviceRuntime命令进行了批量操作性能优化,主要包括: -1. 修改StopDeviceRuntimeCommand支持批量操作,参考StartDeviceRuntimeCommand结构 -2. 更新StopDeviceRuntimeResponse支持批量操作响应 -3. 重构StopDeviceRuntimeCommandHandler使用批量数据库操作 -4. 添加仓储批量操作方法,提高数据库操作性能 -5. 更新控制器支持批量停止操作,保持向后兼容性 - -### 修改文件 - -#### 1. `X1.Application/Features/DeviceRuntimes/Commands/StopDeviceRuntime/StopDeviceRuntimeCommand.cs` -- **批量操作支持**:将单个设备编号改为设备停止请求列表 -- **新增DeviceStopRequest类**:定义设备停止请求结构,包含DeviceCode和NetworkStackCode -- **参数验证**:添加IsValid方法验证请求参数 -- **向后兼容**:保持与StartDeviceRuntimeCommand相同的结构 -- **字段一致性**:DeviceStopRequest包含与DeviceStartRequest相同的字段 - -#### 2. `X1.Application/Features/DeviceRuntimes/Commands/StopDeviceRuntime/StopDeviceRuntimeResponse.cs` -- **批量响应支持**:添加DeviceResults和Summary属性 -- **新增DeviceStopResult类**:定义单个设备停止结果 -- **新增BatchOperationSummary类**:定义批量操作统计信息 -- **向后兼容**:保持单个设备操作的响应结构 - -#### 3. `X1.Application/Features/DeviceRuntimes/Commands/StopDeviceRuntime/StopDeviceRuntimeCommandHandler.cs` -- **批量查询优化**:使用GetRuntimesByDeviceCodesAsync一次性获取所有设备状态 -- **内存映射优化**:使用Dictionary提高设备状态查找性能 -- **批量更新优化**:收集所有需要更新的实体,一次性批量更新 -- **性能提升**:从N次数据库查询优化为1次批量查询+1次批量更新 -- **检查逻辑优化**:将设备运行时状态存在性检查和设备运行状态检查改为只记录日志并跳过,不再记录失败结果 - -#### 4. `X1.Domain/Repositories/Device/ICellularDeviceRuntimeRepository.cs` -- **新增批量查询方法**:GetRuntimesByDeviceCodesAsync -- **新增批量更新方法**:UpdateRuntimesAsync -- **接口扩展**:支持高效的批量操作 - -#### 5. `X1.Infrastructure/Repositories/Device/CellularDeviceRuntimeRepository.cs` -- **实现批量查询**:根据设备编号列表一次性查询所有运行时状态 -- **实现批量更新**:批量标记实体为已修改状态 -- **性能优化**:减少数据库往返次数 -- **优化GetRuntimesByDeviceCodesAsync**:使用ExecuteSqlQueryAsync方法和PostgreSQL的DISTINCT ON语法在数据库层面确保每个设备编码只返回一条最新记录,支持状态过滤,提高查询性能 - - **修复异常处理**:移除不合理的try-catch异常处理逻辑,简化代码结构,让异常正常向上传播 - - **方法简化**:合并两个重载方法为一个,支持可选的运行时状态过滤参数 - - **UpdateRuntimesAsync优化**:移除不必要的async/await,改为同步方法UpdateRuntimes,避免为了异步而异步的问题 - - **UpdateRuntimes方法优化**:使用基类的UpdateRange方法替代手动foreach循环,提高代码复用性和性能 - - **GetRuntimesByDeviceCodesAsync支持多种状态过滤**:将单个DeviceRuntimeStatus?参数改为IEnumerable?,支持传入多个运行时状态进行过滤,使用PostgreSQL的ANY操作符实现高效的批量状态过滤 - - **StopDeviceRuntimeCommandHandler查询优化**:只获取运行状态的设备进行停止操作,避免获取所有状态的设备,提高查询效率并简化后续的状态检查逻辑 - - **DeviceStopRequest添加RuntimeCode字段**:在设备停止请求中添加运行时代码字段,设为必填字段,确保停止操作时能准确识别要停止的运行时实例 - - **StopDeviceRuntimeCommand简化**:将复杂的DeviceStopRequest类简化为简单的DeviceCodes数组,移除NetworkStackCode和RuntimeCode字段,简化API接口,提高易用性 - - **StopDeviceRuntimeCommandHandler优化**:使用LINQ优化批量处理逻辑,将处理逻辑与结果收集分离,提高代码可读性和性能,减少重复代码 - - **InstrumentProtocolClient.StopNetworkAsync修复**:修复方法返回值问题,添加完整的错误处理和响应验证逻辑,参考StartNetworkAsync的实现模式,确保所有代码路径都有返回值 - - **StopDeviceRuntimeCommandHandler协议调用优化**:添加并行调用协议客户端停止网络连接的功能,使用Task.WhenAll实现并发处理,提高批量停止操作的性能 - -#### 6. `X1.Presentation/Controllers/DeviceRuntimesController.cs` -- **新增批量停止端点**:POST /api/device-runtimes/stop -- **保持向后兼容**:单个设备停止端点继续支持 -- **统一响应格式**:批量操作和单个操作使用相同的响应结构 - -### 技术改进 - -#### 1. 性能优化 -- **数据库查询优化**:从N次查询优化为1次批量查询 -- **数据库更新优化**:从N次更新优化为1次批量更新 -- **内存操作优化**:使用Dictionary提高查找效率 -- **事务优化**:所有更新在同一个事务中完成 - -#### 2. 架构改进 -- **批量操作模式**:统一批量操作的设计模式 -- **仓储层扩展**:添加批量操作的基础设施 -- **响应格式统一**:批量操作和单个操作响应格式一致 -- **错误处理优化**:每个设备的错误独立处理,不影响其他设备 - -#### 3. 用户体验 -- **操作效率**:批量操作大幅提高处理速度 -- **错误反馈**:详细的每个设备操作结果 -- **统计信息**:提供成功/失败统计和成功率 -- **向后兼容**:现有API继续正常工作 - -### API使用示例 - -#### 1. 批量停止设备 -```http -POST /api/device-runtimes/stop -Content-Type: application/json - -{ - "deviceRequests": [ - { "deviceCode": "DEV001", "networkStackCode": "STACK001" }, - { "deviceCode": "DEV002", "networkStackCode": "STACK002" }, - { "deviceCode": "DEV003", "networkStackCode": "STACK003" } - ] -} -``` - -#### 2. 单个设备停止(向后兼容) -```http -POST /api/device-runtimes/DEV001/stop -``` - -### 性能对比 - -#### 修改前(逐个处理) -- 数据库查询:N次(每个设备1次) -- 数据库更新:N次(每个设备1次) -- 事务数量:N个(每个设备1个) -- 总耗时:O(N) - -#### 修改后(批量处理) -- 数据库查询:1次(批量查询所有设备) -- 数据库更新:1次(批量更新所有设备) -- 事务数量:1个(所有设备在同一个事务中) -- 总耗时:O(1) - -### 影响范围 -- **性能提升**:批量操作性能提升显著,特别是设备数量较多时 -- **数据库负载**:减少数据库连接和查询次数 -- **响应时间**:大幅减少API响应时间 -- **系统稳定性**:减少数据库连接池压力 -- **代码一致性**:与StartDeviceRuntime保持相同的设计模式 - -### 注意事项 -- 批量操作在单个事务中完成,确保数据一致性 -- 每个设备的错误独立处理,不会影响其他设备的操作 -- 保持向后兼容性,现有代码无需修改 -- 建议在生产环境中监控批量操作的性能表现 - ---- - -## 2025-01-29 - 协议日志查询功能优化和简化 - -### 修改文件 - -#### 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 依赖注入修复 - -### 问题描述 -DeviceManagementService 作为 BackgroundService(单例服务)试图注入作用域服务(ICellularDeviceRepository、IProtocolLogRepository、IUnitOfWork),导致依赖注入错误: -``` -Error while validating the service descriptor 'ServiceType: Microsoft.Extensions.Hosting.IHostedService Lifetime: Singleton ImplementationType: X1.Application.BackendServiceManager.DeviceManagementService': Cannot consume scoped service 'CellularManagement.Domain.Repositories.Device.ICellularDeviceRepository' from singleton 'Microsoft.Extensions.Hosting.IHostedService'. -``` - -### 解决方案 -1. **使用 IServiceScopeFactory**:将直接注入的作用域服务改为注入 IServiceScopeFactory -2. **创建安全的作用域执行方法**: - - `ExecuteInScopeAsync()` - 用于有返回值的操作 - - `ExecuteInScopeAsync()` - 用于无返回值的操作 -3. **统一错误处理**:在作用域执行方法中统一处理异常和资源释放 - -### 修改的文件 -- `X1.Application/BackendServiceManager/DeviceManagementService.cs` - -### 修改内容 -1. 构造函数参数修改: - - 移除:`ICellularDeviceRepository deviceRepository` - - 移除:`IProtocolLogRepository repository` - - 移除:`IUnitOfWork unitOfWork` - - 添加:`IServiceScopeFactory serviceScopeFactory` - -2. 添加安全的作用域执行方法: - ```csharp - private async Task ExecuteInScopeAsync(Func> operation, CancellationToken cancellationToken = default) - private async Task ExecuteInScopeAsync(Func operation, CancellationToken cancellationToken = default) +## 2024年修改记录 + +### 协议日志仓储修改 + +#### 修改文件: +1. `X1.Domain/Repositories/Logging/IProtocolLogRepository.cs` +2. `X1.Infrastructure/Repositories/Logging/ProtocolLogRepository.cs` + +#### 修改内容: + +1. **保留现有方法**: + - 保留了 `GetByDeviceWithFiltersAsync` 方法,该方法用于根据设备代码和运行时状态获取协议日志 + +2. **新增方法**: + - 在接口 `IProtocolLogRepository` 中添加了 `GetProtocolLogsNotInActiveRuntimesAsync` 方法 + - 在实现类 `ProtocolLogRepository` 中实现了该方法 + +3. **新方法特性**: + - 方法名:`GetProtocolLogsNotInActiveRuntimesAsync` + - 功能:获取不在活跃运行时状态中的协议日志 + - 参数:与 `GetByDeviceWithFiltersAsync` 保持一致 + - `deviceCode`:设备代码 + - `runtimeCodes`:运行时代码集合 + - `startTimestamp`:开始时间戳 + - `endTimestamp`:结束时间戳 + - `layerTypes`:协议层类型数组 + - `runtimeStatuses`:运行时状态过滤 + - `orderByDescending`:是否按时间戳降序排序 + - `cancellationToken`:取消令牌 + - 返回类型:`IEnumerable` + +4. **SQL查询逻辑**: + - 基于用户提供的SQL查询 + - **动态查询逻辑**:根据 `runtimeStatuses` 参数动态决定使用 `EXISTS` 还是 `NOT EXISTS` + - 当 `runtimeStatuses` 包含值 1 时,使用 `EXISTS` 包含活跃运行时状态(`RuntimeStatus = 1`)的记录 + - 当 `runtimeStatuses` 不包含值 1 时,使用 `NOT EXISTS` 排除活跃运行时状态(`RuntimeStatus = 1`)的记录 + - 支持所有与 `GetByDeviceWithFiltersAsync` 相同的过滤条件 + - 高性能查询,不包含 `MessageDetailJson` 字段 + +5. **动态查询逻辑示例**: + + **当 runtimeStatuses 包含值 1 时(使用 EXISTS)**: + ```sql + SELECT + pl."Id", + pl."MessageId", + pl."LayerType", + pl."CellID", + pl."IMSI", + pl."Direction", + pl."UEID", + pl."PLMN", + pl."TimeMs", + pl."Timestamp", + pl."Info", + pl."Message", + pl."DeviceCode", + pl."RuntimeCode" + FROM "tb_protocol_logs" pl + WHERE EXISTS ( + SELECT 1 + FROM "tb_cellular_device_runtimes" t + WHERE t."RuntimeStatus" = 1 + AND t."RuntimeCode" = pl."RuntimeCode" + ) + ``` + + **当 runtimeStatuses 不包含值 1 时(使用 NOT EXISTS)**: + ```sql + SELECT + pl."Id", + pl."MessageId", + pl."LayerType", + pl."CellID", + pl."IMSI", + pl."Direction", + pl."UEID", + pl."PLMN", + pl."TimeMs", + pl."Timestamp", + pl."Info", + pl."Message", + pl."DeviceCode", + pl."RuntimeCode" + FROM "tb_protocol_logs" pl + WHERE NOT EXISTS ( + SELECT 1 + FROM "tb_cellular_device_runtimes" t + WHERE t."RuntimeStatus" = 1 + AND t."RuntimeCode" = pl."RuntimeCode" + ) ``` -3. 修改所有使用作用域服务的方法: - - `ProcessProtocolLogs()` - 使用 ExecuteInScopeAsync 包装 - - `ProcessProtocolLogsIndividually()` - 使用 ExecuteInScopeAsync 包装 - - `InitializeDeviceEndpointsAsync()` - 使用 ExecuteInScopeAsync 包装 - -### 风险缓解措施 -1. **内存泄漏防护**:使用 using 语句确保作用域正确释放 -2. **异常处理**:统一的作用域异常处理和日志记录 -3. **资源管理**:自动的作用域生命周期管理 -4. **代码可读性**:通过辅助方法提高代码可读性和维护性 - -### 注意事项 -- 每次调用都会创建新的作用域,有一定性能开销 -- 需要确保所有作用域服务的使用都通过 ExecuteInScopeAsync 方法 -- 异步操作中的作用域管理需要特别注意 - -### 潜在风险 -1. **内存泄漏风险**:如果忘记使用 using 语句,会导致作用域无法正确释放 -2. **性能开销**:每次调用都需要创建新的作用域,作用域创建和销毁有性能成本 -3. **资源管理复杂性**:需要手动管理作用域的生命周期,错误处理时需要确保作用域正确释放 -4. **依赖关系不明确**:从构造函数中无法直接看出服务依赖了哪些作用域服务 - -### 更好的解决方案 -1. **服务工厂模式**:使用安全的作用域执行方法,统一管理作用域生命周期 -2. **错误处理增强**:在作用域执行方法中统一处理异常和资源释放 -3. **代码可读性**:通过辅助方法提高代码可读性和维护性 -4. **性能优化**:避免频繁创建作用域,考虑缓存常用服务 - -### 错误处理优化 -- **记录错误但不抛出**:在作用域执行方法中记录错误日志,但不重新抛出异常 -- **返回默认值**:对于有返回值的方法,在异常时返回默认值 -- **静默处理**:对于无返回值的方法,在异常时静默处理,避免异常传播 -- **日志记录**:保持详细的错误日志记录,便于问题排查 - -### 代码健壮性增强 -- **参数验证**:添加操作委托和服务作用域工厂的空值检查 -- **取消令牌支持**:在执行操作前检查取消令牌状态 -- **返回值验证**:对于引用类型,检查返回值是否为null并记录警告 -- **异常分类处理**: - - `OperationCanceledException`:操作被取消,记录信息日志 - - `ObjectDisposedException`:服务作用域已被释放,记录错误日志 - - `InvalidOperationException`:作用域操作无效,记录错误日志 - - `Exception`:其他未预期的错误,记录详细错误信息 -- **详细错误信息**:在日志中包含具体的错误消息,便于问题排查 -- **代码简化**:移除冗余的 `ExecuteInScopeAsync` 方法,统一使用 `ExecuteInScopeWithResultAsync` - -### 通用化重构 -- **提取通用接口**:创建 `IServiceScopeExecutor` 接口,定义作用域服务执行的标准方法 -- **创建通用实现**:创建 `ServiceScopeExecutor` 类,实现 `IServiceScopeExecutor` 接口 -- **重命名结果类**:将 `OperationResult` 重命名为 `ScopeOperationResult`,使其更加具体和明确 -- **添加无返回值结果类**:创建 `ScopeOperationResult` 类,用于无返回值的操作 -- **接口设计**: - - `ExecuteWithResultAsync()` - 用于有返回值的操作 - - `ExecuteAsync()` - 用于无返回值的操作 -- **重构DeviceManagementService**:移除私有方法,改为注入和使用 `IServiceScopeExecutor` -- **可复用性**:其他需要作用域服务的类可以直接注入 `IServiceScopeExecutor` -- **依赖注入**:需要在DI容器中注册 `ServiceScopeExecutor` 为 `IServiceScopeExecutor` - -### BackgroundService 优化 -- **移除多余的 Task.Run**:在 `BackgroundService` 中直接使用 `await ProcessProtocolLogsAsync(stoppingToken)` -- **简化执行逻辑**:移除了不必要的 `while` 循环和 `Task.Delay` -- **正确的异步模式**:`BackgroundService` 应该直接等待主要任务完成,而不是使用 `Task.Run` -- **更好的取消支持**:直接传递 `stoppingToken` 给子任务,确保正确的取消传播 - -### 性能优化 -- **减少轮询延迟**:将 `Task.Delay(100)` 改为 `Task.Delay(10)`,提高响应性 -- **性能对比分析**: - - **轮询模式**:固定延迟,响应延迟可控,但CPU使用率较高 - - **事件驱动**:零延迟响应,CPU使用率低,但需要支持事件机制 - - **定时器模式**:固定间隔处理,适合批量处理,但响应延迟固定 -- **当前选择**:使用短延迟轮询,平衡响应性和资源使用 -- **未来优化方向**:如果 `IProtocolChannelManager` 支持事件机制,可改为事件驱动模式 - -### 服务生命周期管理 -- **构造函数限制**:不能在构造函数中直接注入作用域服务(如 `IProtocolLogRepository`) -- **生命周期冲突**:单例服务(BackgroundService)不能持有作用域服务的引用 -- **内存泄漏风险**:作用域服务被单例持有会导致内存泄漏 -- **数据库连接问题**:作用域服务通常包含数据库连接,被单例持有会导致连接管理问题 -- **正确做法**:使用 `IServiceScopeFactory` 在需要时创建作用域并获取服务 -- **参数验证**:添加操作委托和服务作用域工厂的空值检查 -- **取消令牌支持**:在执行操作前检查取消令牌状态 -- **返回值验证**:对于引用类型,检查返回值是否为null并记录警告 -- **异常分类处理**: - - `OperationCanceledException`:操作被取消,记录信息日志 - - `ObjectDisposedException`:服务作用域已被释放,记录错误日志 - - `InvalidOperationException`:作用域操作无效,记录错误日志 - - `Exception`:其他未预期的错误,记录详细错误信息 -- **详细错误信息**:在日志中包含具体的错误消息,便于问题排查 - ---- - -## 2025-01-29 - 创建CellularDeviceRuntimeDetailRepository实现类 - -### 修改原因 -`ICellularDeviceRuntimeDetailRepository` 接口在 `DependencyInjection.cs` 中已注册,但缺少对应的实现类,导致依赖注入失败。 - -### 修改文件 -- `X1.Infrastructure/Repositories/Device/CellularDeviceRuntimeDetailRepository.cs` - 创建运行时明细仓储实现类 - -### 修改内容 - -#### 1. 实现类结构 -- **继承关系**:继承 `BaseRepository` 基类 -- **接口实现**:实现 `ICellularDeviceRuntimeDetailRepository` 接口的所有方法 -- **依赖注入**:通过构造函数注入 `ICommandRepository`、`IQueryRepository` 和 `ILogger` - -#### 2. 核心方法实现 -- **GetDetailsByRuntimeCodeAsync**:根据运行编码查询明细列表 -- **GetDetailsByCreatedByAsync**:根据创建人查询明细列表(按创建时间倒序) -- **GetDetailsByRuntimeStatusAsync**:根据运行时状态查询明细列表(按创建时间倒序) -- **SearchDetailsAsync**:支持多条件分页查询(运行编码、创建人、状态、时间范围) -- **GetDetailCountAsync**:获取明细记录总数 -- **AddDetailsRangeAsync**:批量添加明细记录 - -#### 3. 查询优化 -- **条件组合**:支持多个查询条件的组合查询 -- **分页支持**:提供标准的分页查询功能 -- **排序优化**:查询结果按创建时间倒序排列 -- **性能考虑**:利用数据库索引提升查询性能 - -#### 4. 错误处理 -- **空值处理**:正确处理可选的查询参数 -- **异常传播**:将底层仓储的异常向上传播 -- **日志记录**:通过注入的Logger记录操作日志 - -### 技术特性 -- **CQRS模式**:使用命令和查询分离的仓储模式 -- **异步操作**:所有方法都支持异步操作和取消令牌 -- **类型安全**:使用强类型的查询表达式 -- **可扩展性**:基于基类设计,便于扩展和维护 - -### 业务价值 -- **数据查询**:提供完整的运行时明细数据查询功能 -- **历史追踪**:支持按时间、状态、用户等维度追踪设备运行历史 -- **统计分析**:支持明细数据的统计和分页查询 -- **批量操作**:支持批量添加明细记录,提高数据录入效率 - -### 影响范围 -- **依赖注入**:修复了 `ICellularDeviceRuntimeDetailRepository` 的依赖注入问题 -- **应用层**:`StartDeviceRuntimeCommandHandler` 现在可以正常使用明细仓储 -- **数据访问**:提供了完整的运行时明细数据访问能力 - ---- - -## 2025-01-29 - 修复StartDeviceRuntimeCommandHandler中网络启动返回值记录问题 - -### 修改原因 -`IInstrumentProtocolClient.StartNetworkAsync` 方法返回 `Task` 表示网络启动是否成功,但原代码没有记录这个返回值,导致无法准确判断网络启动的实际结果。 - -### 修改文件 -- `X1.Application/Features/DeviceRuntimes/Commands/StartDeviceRuntime/StartDeviceRuntimeCommandHandler.cs` - 修复网络启动返回值记录 - -### 修改内容 - -#### 1. 记录网络启动返回值 -- **获取返回值**:将 `await _protocolClient.StartNetworkAsync(networkRequest)` 的返回值保存到 `startResult` 变量 -- **记录启动结果**:添加日志记录网络启动的实际结果(成功/失败) -- **条件处理**:根据返回值决定是否将设备标记为成功启动 - -#### 2. 具体修改 -```csharp -// 修改前 -await _protocolClient.StartNetworkAsync(networkRequest); -_logger.LogDebug("网络启动成功,设备代码: {DeviceCode}", networkRequest.DeviceCode); -networkResults.Add((true, networkRequest.DeviceCode, string.Empty)); - -// 修改后 -var startResult = await _protocolClient.StartNetworkAsync(networkRequest); -_logger.LogDebug("网络启动结果,设备代码: {DeviceCode}, 启动成功: {StartResult}", - networkRequest.DeviceCode, startResult); - -if (startResult) -{ - _logger.LogDebug("网络启动成功,设备代码: {DeviceCode}", networkRequest.DeviceCode); - networkResults.Add((true, networkRequest.DeviceCode, string.Empty)); -} -else -{ - var errorMessage = "网络启动返回失败状态"; - _logger.LogWarning("网络启动返回失败状态,设备代码: {DeviceCode}", networkRequest.DeviceCode); - networkResults.Add((false, networkRequest.DeviceCode, errorMessage)); -} -``` - -#### 3. 错误处理增强 -- **返回值验证**:检查 `StartNetworkAsync` 的返回值,只有返回 `true` 才认为启动成功 -- **失败状态记录**:当返回 `false` 时,记录警告日志并将设备标记为失败 -- **异常处理保持**:保持原有的异常处理逻辑不变 - -### 技术特性 -- **返回值处理**:正确处理异步方法的返回值 -- **条件判断**:根据返回值进行条件分支处理 -- **日志记录**:详细记录网络启动的实际结果 -- **错误分类**:区分网络启动失败和异常情况 - -### 业务价值 -- **准确性**:准确反映网络启动的实际结果 -- **可追踪性**:通过日志可以追踪每个设备的网络启动状态 -- **错误诊断**:能够区分网络启动失败和异常情况,便于问题诊断 - -### 影响范围 -- **日志记录**:增加了网络启动结果的详细日志 -- **成功统计**:更准确地统计成功启动的设备数量 -- **错误处理**:更精确地处理网络启动失败的情况 - ---- - -## 2025-01-29 - 重构StartDeviceRuntimeCommandHandler,提取网络配置请求构建逻辑 - -### 修改原因 -将按DeviceCode分组处理网络配置请求的逻辑提取为独立方法,提高代码的可读性和可维护性。 - -### 修改文件 -- `X1.Application/Features/DeviceRuntimes/Commands/StartDeviceRuntime/StartDeviceRuntimeCommandHandler.cs` - 重构网络配置请求构建逻辑 - -### 修改内容 - -#### 1. 提取独立方法 -- **新增方法**:`BuildNetworkConfigurationRequests` - 专门负责构建网络配置请求 -- **方法职责**: - - 按DeviceCode分组处理设备请求 - - 匹配对应的网络配置 - - 去重处理设备-网络堆栈组合 - - 构建CellularNetworkConfiguration对象 - -#### 2. 方法签名设计 -```csharp -private List BuildNetworkConfigurationRequests( - StartDeviceRuntimeCommand request, - IEnumerable networkConfigs, - string runtimeCode) -``` - -#### 3. 核心逻辑 -- **按DeviceCode分组**:遍历request.DeviceRequests,确保每个设备都能正确匹配到对应的网络配置 -- **网络配置匹配**:通过NetworkStackCode查找对应的所有网络配置(可能有多条绑定关系) -- **多绑定关系处理**:为每个设备收集所有相关的绑定关系,组合成一条完整的网络配置 -- **数据验证**:验证RAN配置和IMS/核心网配置的有效性,确保至少有一种配置类型有效 -- **去重处理**:使用HashSet跟踪已处理的设备-网络堆栈组合,避免重复处理 -- **配置构建**:创建CellularNetworkConfiguration对象,包含运行时编码、设备编码、网络配置等 - -#### 4. 错误处理 -- **网络配置缺失**:当找不到对应的网络配置时记录警告并跳过 -- **重复组合**:当设备-网络堆栈组合已存在时记录警告并跳过 -- **配置内容验证**:当RAN配置和IMS/核心网配置都为空时记录警告并跳过 -- **多绑定关系验证**:确保每个设备的所有绑定关系都被正确处理 -- **空请求检查**:在并行启动网络前检查是否有有效的网络配置请求,避免不必要的操作 -- **空值安全处理**:使用null检查和空合并运算符安全处理networkRequests,防止空引用异常 -- **业务逻辑验证**:当没有有效的网络配置请求时直接返回失败,避免无效的后续操作 -- **网络启动结果收集**:收集每个设备的网络启动结果,只对成功启动的设备进行后续处理 -- **精确的成功/失败统计**:根据实际网络启动结果统计成功和失败数量,提供准确的业务反馈 -- **详细日志**:记录每个步骤的详细信息,包括绑定关系数量,便于调试 - -#### 5. 代码优化 -- **参数名修复**:修复Parallel.ForEachAsync中参数名冲突问题(request → networkRequest) -- **类型引用**:添加X1.Domain.Models命名空间引用 -- **方法简化**:主方法Handle现在更加简洁,职责更清晰 -- **多绑定关系处理**:正确处理一个设备对应多个网络配置绑定关系的情况 -- **可空字段处理**:修复Index字段的可空性,使用空合并运算符提供默认值 -- **数据验证增强**:使用string.IsNullOrEmpty进行更严格的空值检查,避免空引用异常 -- **配置验证逻辑**:确保RadioAccessNetworkConfiguration和CoreNetworkImsConfigurations至少有一个有值 -- **空值安全处理**:使用空合并运算符安全处理RAN配置的null值,避免运行时异常 -- **代码简化**:移除不必要的null检查,使用null-forgiving操作符明确表示已验证的非空值 -- **命名规范**:修复方法命名,使用同步方法命名规范(移除Async后缀和CancellationToken参数) -- **性能优化**:使用LINQ函数式编程风格,提高代码可读性和性能 -- **空值过滤**:在分组前过滤掉NetworkStackCode为空的配置,避免字典键为null的警告 -- **条件检查**:在并行操作前检查集合是否为空,提高代码的健壮性 -- **防御性编程**:使用null检查和空合并运算符确保代码在各种情况下都能安全运行 -- **重复验证移除**:移除与request.IsValid()重复的输入参数验证,避免冗余检查 -- **运行时编码验证**:添加对生成的运行时编码的空值检查,确保编码生成成功 -- **批量操作优化**:使用批量保存和更新操作,提高数据库操作效率 - -### 技术特性 -- **单一职责**:每个方法职责明确,便于理解和维护 -- **类型安全**:使用正确的NetworkStackConfigBasicDto类型,处理可空字段 -- **同步方法**:使用同步方法命名规范,因为内部没有异步操作 -- **详细注释**:为方法添加完整的XML文档注释 -- **空值处理**:正确处理Index字段的可空性,使用默认值0 -- **防御性编程**:使用空合并运算符和null检查,确保代码的健壮性 -- **代码优化**:使用null-forgiving操作符明确表示已验证的非空值,提高代码可读性 -- **函数式编程**:使用LINQ函数式编程风格,提高代码可读性和维护性 - -### 业务价值 -- **代码可读性**:主方法逻辑更清晰,易于理解 -- **可维护性**:网络配置请求构建逻辑独立,便于修改和测试 -- **可复用性**:提取的方法可以在其他地方复用 -- **调试便利**:独立的日志记录,便于问题排查 - -### 影响范围 -- **代码结构**:改善了代码组织结构,提高了可读性 -- **维护性**:网络配置请求构建逻辑独立,便于后续维护 -- **性能**:保持了原有的性能特性,没有引入额外的开销 - -### 后续工作建议 -1. **单元测试**:为BuildNetworkConfigurationRequestsAsync方法添加单元测试 -2. **性能监控**:监控网络配置请求构建的性能表现 -3. **错误处理**:进一步完善错误处理机制 -4. **文档更新**:更新相关技术文档 - ---- - -## 2024-12-19 - Device Runtimes 页面重构 - -### 修改概述 -按照 instruments 页面的结构重构了 device-runtimes 页面,移除了 Form 组件,将网络栈配置改为下拉框选择,并简化了页面结构。同时修复了设备列表页面的主题兼容性问题。 - -### 修改的文件 - -#### 1. `X1.WebUI/src/pages/device-runtimes/DeviceRuntimesView.tsx` -- **页面结构重构**:按照 instruments 页面的布局结构重新组织页面 -- **移除 Form 组件**:不再使用独立的 Form 组件,改为内联表单 -- **移除统计卡片**:移除了总设备数、运行中、已停止、错误状态的统计卡片 -- **移除展开功能**:移除了搜索条件的高级展开/收起功能 -- **移除页面标题**:移除了"设备运行时管理"标题和描述文本 -- **恢复搜索工具栏**:恢复了搜索关键词和运行时状态的搜索表单,但移除了每页数量选择框 -- **网络栈配置下拉框**:将网络栈配置输入框改为下拉选择框,从网络栈配置服务获取选项 -- **组件接口修复**:修复了 TableToolbar 和 PaginationBar 组件的接口问题 -- **批量启动对话框优化**:使用 Select 组件替代 Input 组件选择网络栈配置 -- **移除错误状态选项**:从运行时状态下拉框中移除了"错误"选项 -- **主题兼容性修复**:修复了搜索工具栏在黑色主题下的显示问题 - -#### 2. `X1.WebUI/src/pages/instruments/DevicesView.tsx` -- **移除展开功能**:移除了搜索条件的高级展开/收起功能 -- **简化搜索工具栏**:将搜索表单简化为单行布局,包含搜索关键词和状态筛选 -- **主题兼容性修复**:修复了搜索工具栏在黑色主题下的显示问题 -- **按钮样式统一**:使用 Button 组件替代硬编码样式,保持与系统其他页面一致 -- **移除每页数量选择**:从搜索工具栏中移除了每页数量选择框 - -#### 3. `X1.WebUI/src/pages/protocols/ProtocolsView.tsx` -- **移除展开功能**:移除了搜索条件的高级展开/收起功能 -- **简化搜索工具栏**:将搜索表单简化为单行布局,包含搜索关键词和状态筛选 -- **主题兼容性修复**:修复了搜索工具栏在黑色主题下的显示问题 -- **按钮样式统一**:使用 Button 组件替代硬编码样式,保持与系统其他页面一致 -- **移除每页数量选择**:从搜索工具栏中移除了每页数量选择框 -- **接口修复**:修复了 ProtocolVersion 接口属性名称问题 - -#### 4. `X1.WebUI/src/pages/ran-configurations/RANConfigurationsView.tsx` -- **简化搜索工具栏**:将搜索表单简化为单行布局,包含搜索关键词和状态筛选 -- **主题兼容性修复**:修复了搜索工具栏在黑色主题下的显示问题 -- **按钮样式统一**:使用 Button 组件替代硬编码样式,保持与系统其他页面一致 -- **布局优化**:使用 flex 布局替代 grid 布局,提升响应式效果 -- **代码清理**:移除了不必要的类型定义和变量 - -#### 5. `X1.WebUI/src/pages/ims-configurations/IMSConfigurationsView.tsx` -- **移除展开功能**:移除了搜索条件的高级展开/收起功能 -- **简化搜索工具栏**:将搜索表单简化为单行布局,包含搜索关键词和状态筛选 -- **主题兼容性修复**:修复了搜索工具栏在黑色主题下的显示问题 -- **按钮样式统一**:使用 Button 组件替代硬编码样式,保持与系统其他页面一致 -- **布局优化**:使用 flex 布局替代 grid 布局,提升响应式效果 -- **代码清理**:移除了不必要的类型定义和变量 -- **接口修复**:修复了 IMSConfiguration 接口属性名称问题 - -#### 6. `X1.WebUI/src/pages/network-stack-configs/NetworkStackConfigsView.tsx` -- **移除展开功能**:移除了搜索条件的高级展开/收起功能 -- **简化搜索工具栏**:将搜索表单简化为单行布局,包含网络栈名称和状态筛选 -- **主题兼容性修复**:修复了搜索工具栏在黑色主题下的显示问题 -- **按钮样式统一**:使用 Button 组件替代硬编码样式,保持与系统其他页面一致 -- **布局优化**:使用 flex 布局替代 grid 布局,提升响应式效果 -- **代码清理**:移除了不必要的类型定义和变量 - -#### 7. `X1.WebUI/src/pages/core-network-configs/CoreNetworkConfigsView.tsx` -- **移除展开功能**:移除了搜索条件的高级展开/收起功能 -- **简化搜索工具栏**:将搜索表单简化为单行布局,包含搜索关键词和状态筛选 -- **主题兼容性修复**:修复了搜索工具栏在黑色主题下的显示问题 -- **按钮样式统一**:使用 Button 组件替代硬编码样式,保持与系统其他页面一致 -- **布局优化**:使用 flex 布局替代 grid 布局,提升响应式效果 -- **代码清理**:移除了不必要的类型定义和变量 - -### 修改的文件 - -#### 1. `X1.WebUI/src/pages/device-runtimes/DeviceRuntimesView.tsx` -- **页面结构重构**:按照 instruments 页面的布局结构重新组织页面 -- **移除 Form 组件**:不再使用独立的 Form 组件,改为内联表单 -- **移除统计卡片**:移除了总设备数、运行中、已停止、错误状态的统计卡片 -- **移除展开功能**:移除了搜索条件的高级展开/收起功能 -- **移除页面标题**:移除了"设备运行时管理"标题和描述文本 -- **恢复搜索工具栏**:恢复了搜索关键词和运行时状态的搜索表单,但移除了每页数量选择框 -- **网络栈配置下拉框**:将网络栈配置输入框改为下拉选择框,从网络栈配置服务获取选项 -- **组件接口修复**:修复了 TableToolbar 和 PaginationBar 组件的接口问题 -- **批量启动对话框优化**:使用 Select 组件替代 Input 组件选择网络栈配置 -- **移除错误状态选项**:从运行时状态下拉框中移除了"错误"选项 - -#### 8. `X1.WebUI/src/pages/device-runtimes/DeviceRuntimesTable.tsx` -- **类型修复**:修复了 density 类型定义,使用 DensityType 替代硬编码类型 -- **样式映射更新**:添加了 'relaxed' 密度选项的样式映射 - -### 功能特性 - -#### 1. 页面布局 -- **统一布局**:采用与 instruments 页面一致的布局结构 -- **响应式设计**:保持响应式布局特性 -- **卡片式布局**:使用卡片组件组织内容区域 - -#### 2. 搜索功能 -- **内联表单**:搜索条件直接嵌入页面,无需独立表单组件 -- **高级搜索**:支持展开/收起高级搜索选项 -- **实时查询**:支持实时搜索和重置功能 - -#### 3. 网络栈配置选择 -- **下拉选择**:从网络栈配置服务获取激活的配置列表 -- **用户友好**:显示配置名称和编码,便于用户选择 -- **数据驱动**:动态加载配置选项,无需硬编码 - -#### 4. 批量操作 -- **批量启动**:支持选择多个设备进行批量启动 -- **网络栈配置**:批量启动时统一选择网络栈配置 -- **操作反馈**:提供详细的操作结果反馈 - -### 技术改进 - -#### 1. 组件接口统一 -- **TableToolbar**:使用正确的接口参数 -- **PaginationBar**:修复分页组件参数 -- **DeviceRuntimesTable**:统一密度类型定义 - -#### 2. 服务集成 -- **网络栈配置服务**:集成 networkStackConfigService 获取配置列表 -- **数据获取**:在页面初始化时获取网络栈配置数据 - -#### 3. 类型安全 -- **TypeScript 类型**:完善类型定义,提高代码安全性 -- **接口一致性**:确保组件接口的一致性 - -### 用户体验改进 - -#### 1. 操作简化 -- **一键选择**:网络栈配置通过下拉框快速选择 -- **批量操作**:支持多选设备进行批量操作 -- **状态反馈**:实时显示操作状态和结果 - -#### 2. 界面优化 -- **布局统一**:与系统其他页面保持一致的布局风格 -- **视觉层次**:清晰的信息层次和视觉引导 -- **交互反馈**:及时的操作反馈和状态提示 - -### 影响范围 -- **前端页面**:device-runtimes 页面的完整重构 -- **用户体验**:提升设备运行时管理的操作便利性 -- **代码维护**:统一代码结构,便于后续维护和扩展 - ---- - -## 2025-01-29 根据DeviceRuntimesController实现X1.WebUI.src.services - -### 修改原因 -根据后端 `DeviceRuntimesController` 的实现,为前端 `X1.WebUI/src/services` 目录创建对应的服务,实现设备运行时状态管理的完整功能。 - -### 新增文件 - -#### 1. 设备运行时服务 -- `X1.WebUI/src/services/deviceRuntimeService.ts` - 设备运行时状态管理服务 - -#### 2. 设备管理服务 -- `X1.WebUI/src/services/deviceService.ts` - 设备管理服务 - -#### 3. 权限管理服务 -- `X1.WebUI/src/services/permissionService.ts` - 权限管理服务 - -#### 4. 角色权限管理服务 -- `X1.WebUI/src/services/rolePermissionService.ts` - 角色权限管理服务 - -### 修改文件 - -#### 1. API常量配置 -- `X1.WebUI/src/constants/api.ts` - 添加设备运行时、设备、权限、角色权限相关的API路径 - -### 功能特性 - -#### 1. 设备运行时服务 (deviceRuntimeService.ts) -- **设备运行时状态枚举**:`DeviceRuntimeStatus`(Running、Stopped、Error、Unknown) -- **核心功能**: - - `getDeviceRuntimes()` - 获取设备运行时状态列表(支持分页、搜索、状态过滤) - - `getDeviceRuntimeStatus()` - 根据设备编号获取设备运行时状态 - - `startDevices()` - 批量启动设备 - - `stopDevice()` - 停止单个设备 -- **辅助功能**: - - `getRuntimeStatusDescription()` - 获取状态的可读描述 - - `getRuntimeStatusColor()` - 获取状态对应的颜色 - -#### 2. 设备管理服务 (deviceService.ts) -- **核心功能**: - - `getDevices()` - 获取设备列表(支持分页、搜索、类型过滤、状态过滤) - - `getDeviceById()` - 根据ID获取设备详情 - - `createDevice()` - 创建设备 - - `updateDevice()` - 更新设备 - - `deleteDevice()` - 删除设备 -- **辅助功能**: - - `getDeviceStatusDescription()` - 获取设备状态描述 - - `getDeviceStatusColor()` - 获取设备状态颜色 - -#### 3. 权限管理服务 (permissionService.ts) -- **核心功能**: - - `createPermission()` - 创建权限 - - `getPermissions()` - 获取权限列表 - - `getPermissionById()` - 根据ID获取权限详情 - - `deletePermission()` - 删除权限 - -#### 4. 角色权限管理服务 (rolePermissionService.ts) -- **核心功能**: - - `getRolePermissions()` - 获取角色权限 - - `addRolePermissions()` - 添加角色权限 - - `deleteRolePermissions()` - 删除角色权限 - - `batchAddPermissions()` - 批量添加权限到角色 - - `batchRemovePermissions()` - 批量从角色删除权限 -- **辅助功能**: - - `getRolePermissionStats()` - 获取角色权限统计信息 - -### 技术特性 - -#### 1. 类型安全 -- 完整的 TypeScript 接口定义 -- 与后端 API 响应格式完全匹配 -- 提供良好的开发体验和代码提示 - -#### 2. 错误处理 -- 统一的错误处理机制 -- 使用 `OperationResult` 包装响应 -- 详细的错误信息记录 - -#### 3. HTTP 客户端集成 -- 使用 `httpClient` 进行 API 调用 -- 支持 GET、POST、PUT、DELETE 方法 -- 自动处理查询参数构建 - -#### 4. 查询参数支持 -- 分页参数:`pageNumber`、`pageSize` -- 搜索参数:`searchTerm` -- 过滤参数:状态、类型等 -- 排序参数:按时间、名称等排序 - -### API 路径配置 - -#### 1. 新增的 API 路径 -``` -export const API_PATHS = { - // 设备相关 - DEVICES: '/devices', - DEVICE_RUNTIMES: '/api/device-runtimes', - - // 权限相关 - PERMISSIONS: '/api/permissions', - ROLE_PERMISSIONS: '/api/role-permissions', - - // ... 其他现有路径 -} -``` - -### 使用示例 - -#### 1. 设备运行时管理 -``` -// 获取设备运行时状态列表 -const result = await deviceRuntimeService.getDeviceRuntimes({ - pageNumber: 1, - pageSize: 10, - searchTerm: 'DEV001', - runtimeStatus: 1 // 对应 Running 状态 -}); - -// 启动设备 -const startResult = await deviceRuntimeService.startDevices([ - { deviceCode: 'DEV001', networkStackCode: 'STACK001' }, - { deviceCode: 'DEV002', networkStackCode: 'STACK002' } -]); - -// 停止设备 -const stopResult = await deviceRuntimeService.stopDevice('DEV001'); -``` - -#### 2. 设备管理 -``` -// 获取设备列表 -const result = await deviceService.getDevices({ - pageNumber: 1, - pageSize: 10, - searchTerm: 'LTE', - deviceType: 'Cellular', - isActive: true -}); - -// 创建设备 -const createResult = await deviceService.createDevice({ - deviceName: '新设备', - deviceCode: 'DEV003', - deviceType: 'Cellular', - description: '测试设备' -}); -``` - -#### 3. 权限管理 -``` -// 创建权限 -const result = await permissionService.createPermission({ - name: 'CreateUser', - description: '创建用户的权限' -}); -``` - -#### 4. 角色权限管理 -``` -// 获取角色权限 -const result = await rolePermissionService.getRolePermissions('roleId', true); - -// 添加角色权限 -const addResult = await rolePermissionService.addRolePermissions({ - roleId: 'roleId', - permissionIds: ['perm1', 'perm2'] -}); -``` - -### 影响范围 -- **前端服务**:提供了完整的设备运行时、设备、权限、角色权限管理前端服务 -- **API 集成**:与后端控制器完全对应 -- **类型安全**:提供了完整的 TypeScript 类型定义 -- **开发体验**:统一的服务接口,便于前端开发使用 - -### 后续工作建议 -1. **前端页面开发**:基于这些服务开发对应的前端页面 -2. **组件开发**:开发设备运行时状态显示组件 -3. **状态管理**:集成到前端状态管理系统中 -4. **错误处理**:完善错误处理和用户提示 -5. **测试验证**:为所有服务方法添加单元测试 - -## 2025-01-29 更新instrumentService.ts和DevicesView.tsx以匹配后端API - -### 修改原因 -根据后端API的响应结构,需要更新前端的接口定义和组件,确保前后端数据格式一致。主要变化包括: -1. 添加 `runtimeStatus` 字段到设备接口 -2. 移除 `isRunning` 字段(后端没有这个字段) -3. 更新表格显示以包含运行时状态 - -### 修改文件 - -#### 1. 前端服务接口更新 -- `X1.WebUI/src/services/instrumentService.ts` - 更新设备接口定义 - -#### 2. 前端组件更新 -- `X1.WebUI/src/pages/instruments/DevicesView.tsx` - 更新设备管理页面 -- `X1.WebUI/src/pages/instruments/DevicesTable.tsx` - 更新设备表格组件 -- `X1.WebUI/src/pages/instruments/DeviceForm.tsx` - 更新设备表单组件 - -### 修改内容 - -#### 1. 设备接口定义更新 -- **Device接口**: - - 添加 `runtimeStatus: number` 字段(运行时状态,-1表示未知状态) - - 移除 `isRunning: boolean` 字段(后端没有此字段) - - 保持其他字段不变 - -- **CreateDeviceRequest接口**: - - 移除 `isRunning?: boolean` 字段 - - 保持其他字段不变 - -- **UpdateDeviceRequest接口**: - - 移除 `isRunning?: boolean` 字段 - - 保持其他字段不变 - -- **响应接口**: - - 所有响应接口都移除 `isRunning` 字段 - - 保持其他字段不变 - -#### 2. 设备管理页面更新 -- **DevicesView.tsx**: - - 添加运行时状态映射函数:`getRuntimeStatusText` 和 `getRuntimeStatusColor` - - 更新默认列配置,添加运行时状态列 - - 更新注释说明新的字段结构 - - 移除对 `isRunning` 字段的引用 - -#### 3. 设备表格组件更新 -- **DevicesTable.tsx**: - - 添加 `RuntimeStatusBadge` 组件,用于显示运行时状态 - - 更新 `renderCell` 函数,添加对 `runtimeStatus` 字段的处理 - - 更新注释说明新的字段结构 - - 运行时状态显示为徽章形式,不同状态使用不同颜色 - -#### 4. 设备表单组件更新 -- **DeviceForm.tsx**: - - 移除 `isRunning` 字段的初始化和处理 - - 更新表单状态管理,移除对 `isRunning` 的引用 - - 修复表单提交逻辑,移除对 `isRunning` 字段的处理 - -### 技术特性 - -#### 1. 运行时状态映射 -- **状态值**: - - -1: 未知状态 - - 0: 初始化 - - 1: 运行中 - - 2: 停止中 - -- **颜色映射**: - - 未知: 灰色轮廓 - - 初始化: 黄色 - - 运行中: 绿色 - - 停止中: 橙色 - -#### 2. 表格列配置 -- **新增列**:运行时状态列,显示在启用状态列之后 -- **列标题**:启用状态列标题改为"启用状态",新增"运行时状态"列 -- **列顺序**:设备ID、设备名称、设备编码、描述、Agent端口、启用状态、运行时状态、创建时间、操作 - -#### 3. 类型安全 -- 确保所有接口定义与后端API完全匹配 -- 移除不存在的字段引用 -- 添加必要的类型检查和验证 - -### 业务价值 -- **数据一致性**:确保前后端数据格式完全一致 -- **状态可见性**:用户可以在设备列表中看到设备的实时运行状态 -- **用户体验**:通过颜色编码直观显示设备状态 -- **系统稳定性**:避免因字段不匹配导致的错误 - -### 影响范围 -- **API集成**:前端接口定义与后端API完全匹配 -- **用户界面**:设备列表显示运行时状态信息 -- **数据完整性**:确保所有设备数据都能正确显示 -- **开发体验**:提供完整的类型安全和代码提示 - -### 测试建议 -1. 测试设备列表的显示,确认运行时状态正确显示 -2. 验证不同状态的颜色编码是否正确 -3. 测试设备创建和编辑功能,确认表单正常工作 -4. 检查表格列配置,确认列显示顺序正确 -5. 验证搜索和过滤功能是否正常工作 - -## 2025-01-29 修复SearchRuntimesAsync方法,添加设备信息关联查询 - -### 修改原因 -`SearchRuntimesAsync` 方法在查询 `CellularDeviceRuntime` 时没有包含 `Device` 导航属性,导致在 `MapToDto` 方法中访问 `runtime.Device?.Name` 时返回 null。需要修复查询方法,确保能够正确获取设备名称信息。 - -### 修改文件 -- `X1.Infrastructure/Repositories/Device/CellularDeviceRuntimeRepository.cs` - 修复 SearchRuntimesAsync 方法 - -### 修改内容 - -#### 1. 分页查询方法修复 -**SearchRuntimesAsync(分页版本)**: -- 添加 `include: q => q.Include(r => r.Device)` 参数 -- 确保查询结果包含设备信息,支持通过 `DeviceCode` 关联获取 `CellularDevice.Name` - -#### 2. 非分页查询方法修复 -**SearchRuntimesAsync(非分页版本)**: -- 添加 `include: q => q.Include(r => r.Device)` 参数 -- 确保所有搜索查询都能正确获取设备信息 - -### 技术实现 - -#### 1. Entity Framework Include -```csharp -// 修改前 -var result = await QueryRepository.GetPagedAsync(predicate, pageNumber, pageSize, null, cancellationToken); - -// 修改后 -var result = await QueryRepository.GetPagedAsync( - predicate, - pageNumber, - pageSize, - include: q => q.Include(r => r.Device), - cancellationToken); -``` - -#### 2. 导航属性查询 -- 通过 `DeviceCode` 外键关联 `CellularDeviceRuntime` 和 `CellularDevice` -- 使用 `Include(r => r.Device)` 预加载设备信息 -- 确保 `MapToDto` 方法中的 `runtime.Device?.Name` 能够正确获取设备名称 - -### 影响范围 -- **API 响应**:设备运行时状态列表现在能够正确显示设备名称 -- **数据完整性**:确保运行时状态查询结果包含完整的设备信息 -- **用户体验**:前端能够显示设备名称,提供更好的用户界面 - -### 业务价值 -- **信息完整性**:运行时状态列表显示设备名称,便于用户识别 -- **数据关联**:正确建立 `CellularDeviceRuntime` 和 `CellularDevice` 的关联关系 -- **查询性能**:通过 Include 预加载避免 N+1 查询问题 - -## 2025-01-29 修改DeleteDeviceCommandHandler实现软删除CellularDeviceRuntime - -### 修改原因 -根据用户需求,在删除设备时需要同时软删除相关的 `CellularDeviceRuntime` 记录,确保数据的一致性和完整性。 - -### 修改文件 -- `X1.Application/Features/Devices/Commands/DeleteDevice/DeleteDeviceCommandHandler.cs` - 修改删除设备命令处理器 -- `X1.Domain/Entities/Common/BaseEntity.cs` - 让BaseEntity实现ISoftDelete接口 - -### 修改内容 - -#### 1. 依赖注入修改 -- **新增依赖**:添加 `ICellularDeviceRuntimeRepository` 依赖注入 -- **构造函数更新**:在构造函数中注入运行时仓储服务 - -#### 2. 删除逻辑增强 -- **软删除运行时记录**:在删除设备前,先软删除相关的设备运行时状态记录 -- **使用设备编号**:通过 `device.DeviceCode` 查找并删除相关的运行时记录 -- **日志记录**:添加详细的日志记录,便于追踪删除过程 - -#### 3. 执行顺序 -1. 检查设备是否存在 -2. 软删除相关的设备运行时状态记录 -3. 删除设备本身 -4. 保存所有更改到数据库 - -#### 4. 软删除基础设施 -- **BaseEntity接口实现**:让 `BaseEntity` 实现 `ISoftDelete` 接口 -- **软删除机制**:利用 `UnitOfWork` 中的软删除逻辑,自动将删除操作转换为软删除 -- **查询过滤**:通过 Entity Framework 的查询过滤器自动过滤已删除的记录 -- **删除流程**:`DeleteRuntimeByDeviceCodeAsync` → `CommandRepository.DeleteWhereAsync` → `UnitOfWork.SaveChangesAsync` → 自动软删除 - -### 技术特性 -- **数据一致性**:确保设备删除时相关的运行时记录也被正确处理 -- **软删除机制**:利用 `BaseEntity` 的 `IsDeleted` 字段实现软删除 -- **事务安全**:在同一个事务中执行所有删除操作 -- **错误处理**:保持原有的异常处理机制 - -### 业务价值 -- **数据完整性**:避免孤立的运行时记录 -- **审计追踪**:软删除保留历史数据,便于审计 -- **系统稳定性**:确保删除操作的原子性和一致性 - -### 影响范围 -- **删除操作**:设备删除时会同时处理运行时记录 -- **数据存储**:运行时记录被标记为已删除而非物理删除 -- **查询结果**:软删除的记录不会出现在正常查询结果中 - ---- - -## 2025-01-29 更新ProtocolLogRepository使用DISTINCT ON查询 - -### 修改原因 -根据用户需求,将 `GetRuntimeDeviceCodesNotInActiveRuntimesAsync` 方法中的SQL查询更新为使用 `DISTINCT ON` 语法,提高查询性能和结果准确性。 - -### 修改文件 -- `X1.Domain/Models/ProtocolLogRuntimeDeviceDto.cs` - 添加Timestamp属性 -- `X1.Infrastructure/Repositories/Logging/ProtocolLogRepository.cs` - 更新SQL查询 - -### 修改内容 - -#### 1. DTO模型更新 -- **新增Timestamp属性**:在 `ProtocolLogRuntimeDeviceDto` 中添加 `Timestamp` 属性 -- **类型定义**:`public long Timestamp { get; set; }` -- **用途说明**:用于返回协议日志的时间戳信息 - -#### 2. SQL查询优化 -- **查询语法更新**:从 `NOT IN` 子查询改为 `NOT EXISTS` 子查询 -- **DISTINCT ON语法**:使用 `SELECT DISTINCT ON (tpl."DeviceCode", tpl."RuntimeCode")` 确保每个设备-运行时组合只返回一条记录 -- **排序优化**:按 `tpl."DeviceCode"`, `tpl."RuntimeCode"`, `tpl."Timestamp" DESC` 排序,确保返回最新的记录 -- **性能提升**:`NOT EXISTS` 通常比 `NOT IN` 性能更好,特别是在大数据集上 - -#### 3. 具体SQL变更 -```sql --- 修改前 -SELECT tpl."RuntimeCode", tpl."DeviceCode" -FROM "tb_protocol_logs" tpl -WHERE tpl."RuntimeCode" NOT IN ( - SELECT "RuntimeCode" - FROM "tb_cellular_device_runtimes" - WHERE "RuntimeStatus" = 1 -) -GROUP BY tpl."DeviceCode", tpl."RuntimeCode" -ORDER BY tpl."Timestamp" DESC - --- 修改后 -SELECT DISTINCT ON (tpl."DeviceCode", tpl."RuntimeCode") - tpl."RuntimeCode", tpl."DeviceCode", tpl."Timestamp" -FROM "tb_protocol_logs" tpl -WHERE NOT EXISTS ( - SELECT 1 - FROM "tb_cellular_device_runtimes" t - WHERE t."RuntimeStatus" = 1 - AND t."RuntimeCode" = tpl."RuntimeCode" -) -ORDER BY tpl."DeviceCode", tpl."RuntimeCode", tpl."Timestamp" DESC -``` - -### 技术特性 -- **DISTINCT ON语法**:PostgreSQL特有的语法,确保每个分组只返回一条记录 -- **NOT EXISTS优化**:比NOT IN性能更好,特别是在大数据集上 -- **时间戳排序**:确保返回每个设备-运行时组合的最新记录 -- **数据完整性**:返回完整的协议日志信息,包括时间戳 - -### 业务价值 -- **查询性能**:提高大数据表的查询性能 -- **结果准确性**:确保返回每个设备-运行时组合的最新记录 -- **数据完整性**:提供更完整的协议日志信息 -- **系统稳定性**:优化查询减少数据库负载 - -### 影响范围 -- **API响应**:响应数据现在包含时间戳信息 -- **查询性能**:提高大数据表的查询效率 -- **数据准确性**:确保返回最新记录而非任意记录 -- **DTO结构**:扩展了返回数据结构 - ---- - -## 2025-01-29 优化GetRuntimeDeviceCodesNotInActiveRuntimesQueryHandler支持树形结构 - -### 修改原因 -根据用户需求,当 `DeviceCode` 和 `RuntimeCode` 数据较多时,界面需要渲染为树形结构。需要将平面数据按设备分组,每个设备下包含其对应的运行时列表,便于前端渲染树形界面。 - -### 修改文件 -- `X1.Domain/Models/ProtocolLogRuntimeDeviceTreeDto.cs` - 新增树形结构DTO -- `X1.Application/Features/ProtocolLogs/Queries/GetRuntimeDeviceCodesNotInActiveRuntimes/GetRuntimeDeviceCodesNotInActiveRuntimesResponse.cs` - 更新响应类 -- `X1.Application/Features/ProtocolLogs/Queries/GetRuntimeDeviceCodesNotInActiveRuntimes/GetRuntimeDeviceCodesNotInActiveRuntimesQueryHandler.cs` - 更新查询处理器 - -### 修改内容 - -#### 1. 新增树形结构DTO -- **ProtocolLogRuntimeDeviceTreeDto**:表示按设备分组的树形结构 - - `DeviceCode`:设备代码 - - `DeviceName`:设备名称(可选,用于显示) - - `Runtimes`:该设备下的运行时列表 - - `RuntimeCount`:该设备下的运行时数量 - -- **ProtocolLogRuntimeInfo**:运行时信息 - - `RuntimeCode`:运行时代码 - - `Timestamp`:时间戳 - - `FormattedTime`:格式化后的时间显示 - -#### 2. 更新响应类 -- **新增TreeItems属性**:包含树形结构数据 -- **新增DeviceCount属性**:设备数量统计 -- **简化数据结构**:移除平面结构的Items属性,只保留树形结构 - -#### 3. 更新查询处理器 -- **新增BuildTreeStructure方法**:将平面数据转换为树形结构 -- **数据分组逻辑**:按DeviceCode分组,每个设备下包含其RuntimeCode列表 -- **排序优化**:按设备代码排序,便于前端显示 -- **统计信息**:提供设备数量和总记录数的统计 - -#### 4. 数据结构示例 -```json -{ - "treeItems": [ - { - "deviceCode": "DEV001", - "deviceName": "DEV001", - "runtimeCount": 2, - "runtimes": [ - {"runtimeCode": "RT-001-DEV001", "timestamp": 1640995200000, "formattedTime": "2022-01-01 12:00:00.000"}, - {"runtimeCode": "RT-002-DEV001", "timestamp": 1640995300000, "formattedTime": "2022-01-01 12:01:40.000"} - ] - }, - { - "deviceCode": "DEV002", - "deviceName": "DEV002", - "runtimeCount": 1, - "runtimes": [ - {"runtimeCode": "RT-001-DEV002", "timestamp": 1640995400000, "formattedTime": "2022-01-01 12:03:20.000"} - ] - } - ], - "totalCount": 3, - "deviceCount": 2 -} -``` - -### 技术特性 -- **数据分组**:按设备代码自动分组,便于树形显示 -- **时间格式化**:提供格式化后的时间显示,便于用户阅读 -- **简化结构**:移除平面数据结构,专注于树形结构支持 -- **性能优化**:在应用层进行数据分组,减少数据库查询压力 -- **统计信息**:提供设备数量和总记录数的统计信息 - -### 业务价值 -- **界面友好**:支持树形结构显示,提高用户体验 -- **数据组织**:按设备分组,便于数据管理和查看 -- **扩展性**:为未来添加设备名称等扩展信息预留接口 -- **结构简化**:专注于树形结构,减少数据冗余 - -### 影响范围 -- **API响应**:专注于树形结构数据,简化响应格式 -- **前端渲染**:支持树形结构显示,提高数据展示效果 -- **数据组织**:按设备分组,便于数据管理和查看 -- **统计信息**:提供更详细的统计信息,便于数据分析 - -## 2025-01-29 修复DeviceRuntimes相关代码 - -### 修改原因 -在移除 `CellularDeviceRuntime` 实体中的 `StartedBy`、`StartedAt`、`StoppedBy`、`StoppedAt` 字段后,需要修复相关的 Application 层代码,确保所有引用都已正确更新。 - -### 修改文件 -- `X1.Application/Features/DeviceRuntimes/Commands/StartDeviceRuntime/StartDeviceRuntimeCommandHandler.cs` - 修复启动设备命令处理器 -- `X1.Application/Features/DeviceRuntimes/Commands/StartDeviceRuntime/StartDeviceRuntimeResponse.cs` - 修复启动设备响应类 -- `X1.Application/Features/DeviceRuntimes/Commands/StopDeviceRuntime/StopDeviceRuntimeCommandHandler.cs` - 修复停止设备命令处理器 -- `X1.Application/Features/DeviceRuntimes/Commands/StopDeviceRuntime/StopDeviceRuntimeResponse.cs` - 修复停止设备响应类 -- `X1.Application/Features/DeviceRuntimes/Queries/GetDeviceRuntimes/GetDeviceRuntimesQueryHandler.cs` - 修复查询处理器 -- `X1.Application/Features/DeviceRuntimes/Queries/GetDeviceRuntimes/GetDeviceRuntimesResponse.cs` - 修复查询响应类 -- `X1.Domain/Repositories/Device/ICellularDeviceRuntimeDetailRepository.cs` - 修复仓储接口警告 - -### 修改内容 - -#### 1. 命令处理器修复 -- **StartDeviceRuntimeCommandHandler**: - - 移除对 `StartedBy` 和 `StartedAt` 字段的引用 - - 更新 `deviceRuntime.Start()` 方法调用,移除 `currentUser` 参数 - - 更新响应构建,移除已删除字段的映射 - -- **StopDeviceRuntimeCommandHandler**: - - 移除对 `StoppedBy` 和 `StoppedAt` 字段的引用 - - 更新 `deviceRuntime.Stop()` 方法调用,移除 `currentUser` 参数 - - 更新响应构建,移除已删除字段的映射 - -#### 2. 响应类修复 -- **StartDeviceRuntimeResponse**: - - 移除 `StartedBy` 和 `StartedAt` 属性 - - 更新 `DeviceStartResult` 类,移除相关字段 - -- **StopDeviceRuntimeResponse**: - - 移除 `StoppedBy` 和 `StoppedAt` 属性 - -- **GetDeviceRuntimesResponse**: - - 移除 `StartedBy`、`StoppedBy`、`StartedAt`、`StoppedAt` 属性 - - 更新 `DeviceRuntimeDto` 类,移除相关字段 - -#### 3. 查询处理器修复 -- **GetDeviceRuntimesQueryHandler**: - - 更新 `MapToDto` 方法,移除对已删除字段的映射 - -#### 4. 仓储接口修复 -- **ICellularDeviceRuntimeDetailRepository**: - - 添加 `new` 关键字修复方法隐藏警告 - -### 技术特性 -- **代码一致性**:确保所有代码都与更新后的实体结构一致 -- **编译通过**:修复所有编译错误和警告 -- **向后兼容**:保持API接口的稳定性 -- **数据完整性**:移除对不存在字段的引用 - -### 业务价值 -- **系统稳定性**:确保系统能够正常编译和运行 -- **代码质量**:消除编译警告,提高代码质量 -- **维护便利**:统一的代码结构便于后续维护 - -### 影响范围 -- **API响应**:响应中不再包含已删除的字段 -- **业务逻辑**:启动和停止操作不再记录操作人信息 -- **数据查询**:查询结果中移除相关字段 - -## 2025-01-29 创建CellularDeviceRuntimeDetail明细表实体 - -### 修改原因 -根据用户需求,创建一个设备运行时明细表,用于记录运行编码、创建时间、创建人和状态等信息,便于追踪设备运行历史。 - -### 修改文件 -- `X1.Domain/Entities/Device/CellularDeviceRuntimeDetail.cs` - 创建设备运行时明细表实体 -- `X1.Domain/Repositories/Device/ICellularDeviceRuntimeDetailRepository.cs` - 创建明细表仓储接口 -- `X1.Infrastructure/Configurations/Device/CellularDeviceRuntimeDetailConfiguration.cs` - 创建数据库配置 - -### 修改内容 - -#### 1. 实体设计 -- **继承关系**:继承 `Entity` 基类 -- **核心字段**: - - `RuntimeCode`:运行编码(必填,最大50字符) - - `RuntimeStatus`:运行时状态(bool类型,true=运行中,false=已停止) - - `CreatedBy`:创建人ID(最大450字符) - - `CreatedAt`:创建时间 - - `Id`:主键(继承自Entity) - -#### 2. 实体特性 -- **只读设计**:所有属性都是私有setter,确保数据不可变性 -- **工厂方法**:提供静态 `Create` 方法创建实例 -- **无更新方法**:只用于添加记录,不提供更新功能 -- **简化状态**:使用bool类型表示运行/停止两种状态 - -#### 3. 仓储接口设计 -- **基础查询**:根据运行编码、创建人、运行时状态查询 -- **分页查询**:支持多条件分页查询 -- **批量操作**:支持批量添加明细记录 -- **统计功能**:获取明细记录总数 - -#### 4. 数据库配置 -- **表名**:`CellularDeviceRuntimeDetails` -- **索引优化**: - - 运行编码索引 - - 创建人索引 - - 运行时状态索引 - - 创建时间索引 -- **字段配置**:合理的字段长度和约束设置 - -### 技术特性 -- **不可变设计**:创建后不可修改,确保数据完整性 -- **简化状态管理**:使用bool类型简化状态表示 -- **高效查询**:通过索引优化查询性能 -- **批量支持**:支持批量添加操作 - -### 业务价值 -- **历史追踪**:记录设备运行历史,便于审计和问题排查 -- **状态监控**:通过明细表监控设备运行状态变化 -- **操作记录**:记录每次操作的创建人和时间 -- **数据完整性**:不可变设计确保数据不被意外修改 - -### 使用场景 -- **设备启动记录**:记录设备启动时的运行编码和状态 -- **设备停止记录**:记录设备停止时的状态变化 -- **历史查询**:查询特定设备的运行历史 -- **统计分析**:统计设备运行状态和操作频率 - -## 2025-01-29 优化GenerateRuntimeCodeAsync方法,移除时间戳以缩短运行编码长度 - -## 2025-01-29 优化GenerateRuntimeCodeAsync方法,移除时间戳以缩短运行编码长度 - -### 修改原因 -用户反馈运行编码太长,需要移除时间戳部分以缩短编码长度,提高可读性和使用便利性。 - -### 修改文件 -- `X1.Application/Features/DeviceRuntimes/Commands/StartDeviceRuntime/StartDeviceRuntimeCommandHandler.cs` - 优化运行编码生成方法 - -### 修改内容 - -#### 1. 运行编码格式简化 -- **原格式**:`RT-YYYYMMDD-HHMMSS-FFF-000-DEVCODE`(包含时间戳) -- **新格式**:`RT-000-DEVCODE`(移除时间戳,保留序号和设备编号) - -#### 2. 代码优化 -- **移除时间戳生成**:删除 `currentTime` 和 `timeStamp` 相关代码 -- **简化编码格式**:直接使用序号和设备编号生成编码 -- **更新日志记录**:移除时间戳相关的日志参数 - -#### 3. 具体修改 -```csharp -// 修改前 -var currentTime = DateTime.UtcNow; -var timeStamp = currentTime.ToString("yyyyMMdd-HHmmss-fff"); -var runtimeCode = $"RT-{timeStamp}-{formattedNumber}-{deviceCode}"; - -// 修改后 -var runtimeCode = $"RT-{formattedNumber}-{deviceCode}"; -``` - -#### 4. 日志优化 -- **移除时间戳参数**:从日志记录中移除 `timeStamp` 参数 -- **保持关键信息**:保留运行编码、运行时总数、位数等关键信息 - -### 技术特性 -- **编码简化**:大幅缩短运行编码长度,提高可读性 -- **保持唯一性**:通过序号确保编码的唯一性 -- **性能优化**:减少时间戳生成的开销 -- **向后兼容**:不影响现有的业务逻辑 - -### 业务价值 -- **用户体验**:更短的编码便于用户输入和识别 -- **系统性能**:减少字符串处理开销 -- **维护便利**:简化的编码格式便于系统维护 - -### 影响范围 -- **运行编码长度**:从约30个字符缩短到约15个字符 -- **编码格式**:从 `RT-20250129-143022-123-001-DEV001` 变为 `RT-001-DEV001` -- **日志记录**:减少日志中的时间戳信息 - -### 示例对比 -- **修改前**:`RT-20250129-143022-123-001-DEV001` -- **修改后**:`RT-001-DEV001` - -## 2025-01-29 在CreateDeviceCommandHandler中添加CellularDeviceRuntime创建逻辑(原子性操作) - -## 2025-01-29 在CreateDeviceCommandHandler中添加CellularDeviceRuntime创建逻辑(原子性操作) - -### 修改原因 -根据用户需求,在创建设备时需要同时创建一条 `CellularDeviceRuntime` 数据,用于管理设备的运行时状态。为了确保数据保存的原子性,将两个操作合并到一个事务中。 - -### 修改文件 -- `X1.Application/Features/Devices/Commands/CreateDevice/CreateDeviceCommandHandler.cs` - 添加设备运行时状态创建逻辑(原子性操作) - -### 修改内容 - -#### 1. 依赖注入更新 -- **新增依赖**:添加 `ICellularDeviceRuntimeRepository` 依赖注入 -- **构造函数更新**:在构造函数中添加 `deviceRuntimeRepository` 参数 -- **字段声明**:添加 `_deviceRuntimeRepository` 私有字段 - -#### 2. 业务逻辑重构 -- **原子性操作**:将设备创建和运行时状态创建合并到一个方法中 -- **事务管理**:通过 `IUnitOfWork.SaveChangesAsync()` 确保原子性保存 -- **错误处理**:如果任一操作失败,整个事务回滚,确保数据一致性 - -#### 3. 方法重构 -- **删除方法**: - - `CreateAndSaveDeviceAsync` - 原设备创建方法 - - `CreateAndSaveDeviceRuntimeAsync` - 原运行时状态创建方法 -- **新增方法**: - - `CreateAndSaveDeviceWithRuntimeAsync` - 合并的设备创建和运行时状态创建方法 - -#### 4. 原子性操作流程 -1. **创建设备实体**:使用 `CellularDevice.Create()` 创建设备 -2. **创建运行时状态实体**:使用 `CellularDeviceRuntime.Create()` 创建运行时状态 -3. **添加到仓储**:将两个实体分别添加到对应的仓储 -4. **原子性保存**:调用 `_unitOfWork.SaveChangesAsync()` 一次性保存所有更改 -5. **错误处理**:如果保存失败,整个事务回滚 - -#### 5. 运行时状态配置 -- **初始状态**:新创建的设备运行时状态设置为 `DeviceRuntimeStatus.Initializing` -- **网络栈配置**:初始时 `NetworkStackCode` 为 `null` -- **创建者信息**:记录创建运行时状态的用户ID -- **时间戳**:自动设置创建和更新时间 - -### 技术特性 -- **事务安全**:通过工作单元模式确保数据一致性 -- **原子性操作**:设备和运行时状态创建要么全部成功,要么全部失败 -- **错误回滚**:任一操作失败时自动回滚整个事务 -- **日志记录**:完整的操作日志,便于问题排查 -- **状态管理**:统一的设备运行时状态管理 - -### 业务价值 -- **数据一致性**:确保设备和运行时状态的数据一致性 -- **状态跟踪**:为每个设备提供运行时状态跟踪 -- **监控能力**:支持设备运行状态的实时监控 -- **系统稳定性**:通过原子性操作提高系统稳定性 - -### 影响范围 -- **设备创建流程**:设备创建时会同时创建运行时状态(原子性操作) -- **数据库操作**:增加运行时状态表的插入操作,但保证原子性 -- **错误处理**:统一的错误处理,确保数据一致性 -- **日志记录**:增加运行时状态创建相关的日志 - -### 原子性保证 -- **事务边界**:整个创建过程在一个事务中完成 -- **回滚机制**:如果运行时状态创建失败,设备创建也会回滚 -- **数据完整性**:确保不会出现只有设备没有运行时状态的情况 -- **一致性保证**:通过数据库事务确保ACID特性 - -### 后续工作建议 -1. **测试验证**:测试设备创建和运行时状态创建的完整流程 -2. **事务测试**:测试事务回滚机制是否正常工作 -3. **性能监控**:监控原子性操作对性能的影响 -4. **错误处理验证**:验证各种错误情况下的回滚机制 - -## 2025-01-29 实现CellularDeviceRuntime的Application层功能 - -### 修改原因 -根据用户需求,为CellularDeviceRuntime实现Application层的修改和查询功能,主要包括Start和Stop操作,以及相关的查询功能。 - -### 修改文件 - -#### 1. 命令功能 -- `X1.Application/Features/DeviceRuntimes/Commands/StartDeviceRuntime/StartDeviceRuntimeCommand.cs` - 启动设备命令 -- `X1.Application/Features/DeviceRuntimes/Commands/StartDeviceRuntime/StartDeviceRuntimeResponse.cs` - 启动设备响应 -- `X1.Application/Features/DeviceRuntimes/Commands/StartDeviceRuntime/StartDeviceRuntimeCommandHandler.cs` - 启动设备命令处理器 -- `X1.Application/Features/DeviceRuntimes/Commands/StopDeviceRuntime/StopDeviceRuntimeCommand.cs` - 停止设备命令 -- `X1.Application/Features/DeviceRuntimes/Commands/StopDeviceRuntime/StopDeviceRuntimeResponse.cs` - 停止设备响应 -- `X1.Application/Features/DeviceRuntimes/Commands/StopDeviceRuntime/StopDeviceRuntimeCommandHandler.cs` - 停止设备命令处理器 - -#### 2. 查询功能 -- `X1.Application/Features/DeviceRuntimes/Queries/GetDeviceRuntimes/GetDeviceRuntimesQuery.cs` - 获取设备运行时状态列表查询 -- `X1.Application/Features/DeviceRuntimes/Queries/GetDeviceRuntimes/GetDeviceRuntimesResponse.cs` - 获取设备运行时状态列表响应 -- `X1.Application/Features/DeviceRuntimes/Queries/GetDeviceRuntimes/GetDeviceRuntimesQueryHandler.cs` - 获取设备运行时状态列表查询处理器 -- `X1.Application/Features/DeviceRuntimes/Queries/GetDeviceRuntimeStatus/GetDeviceRuntimeStatusQuery.cs` - 获取设备运行时状态查询 -- `X1.Application/Features/DeviceRuntimes/Queries/GetDeviceRuntimeStatus/GetDeviceRuntimeStatusResponse.cs` - 获取设备运行时状态响应 -- `X1.Application/Features/DeviceRuntimes/Queries/GetDeviceRuntimeStatus/GetDeviceRuntimeStatusQueryHandler.cs` - 获取设备运行时状态查询处理器 - -#### 3. 控制器 -- `X1.Presentation/Controllers/DeviceRuntimesController.cs` - 设备运行时状态管理控制器 - -### 修改内容 - -#### 1. 启动设备功能 (StartDeviceRuntime) -- **命令参数**: - - `DeviceCode`:设备编号(必填) - - `NetworkStackCode`:网络栈配置编号(必填) - - `RuntimeCode`:运行编码(必填) - -- **业务逻辑**: - - 验证设备运行时状态是否存在 - - 检查设备是否已经在运行中 - - 验证用户身份 - - 调用实体的Start方法更新状态 - - 保存更改到数据库 - -- **响应数据**: - - 运行时状态ID、设备编号、运行时状态 - - 运行编码、网络栈配置编号 - - 运行人ID、开始时间、更新时间 - -#### 2. 停止设备功能 (StopDeviceRuntime) -- **命令参数**: - - `DeviceCode`:设备编号(必填) - -- **业务逻辑**: - - 验证设备运行时状态是否存在 - - 检查设备是否在运行中 - - 验证用户身份 - - 调用实体的Stop方法更新状态 - - 保存更改到数据库 - -- **响应数据**: - - 运行时状态ID、设备编号、运行时状态 - - 停止人ID、停止时间、更新时间 - -#### 3. 查询功能 -- **列表查询**: - - 支持分页查询(页码、每页数量) - - 支持关键词搜索(设备编号、运行编码、网络栈配置编号) - - 支持运行时状态过滤 - - 支持网络栈配置编号过滤 - - 返回包含设备信息的完整数据 - -- **详情查询**: - - 根据设备编号查询单个设备运行时状态 - - 返回包含设备信息的完整数据 - -#### 4. API接口设计 -- **GET /api/device-runtimes**:获取设备运行时状态列表 -- **GET /api/device-runtimes/{deviceCode}**:根据设备编号获取设备运行时状态 -- **POST /api/device-runtimes/{deviceCode}/start**:启动设备 -- **POST /api/device-runtimes/{deviceCode}/stop**:停止设备 - -### 技术特性 -- **CQRS模式**:命令和查询职责分离 -- **MediatR**:使用中介者模式处理命令和查询 -- **依赖注入**:通过构造函数注入依赖服务 -- **日志记录**:完整的操作日志记录 -- **错误处理**:统一的错误处理和响应格式 -- **数据验证**:输入参数验证和业务规则验证 - -### 业务价值 -- **设备管理**:提供完整的设备启动/停止管理功能 -- **状态跟踪**:实时跟踪设备运行时状态 -- **操作审计**:记录设备操作的操作人和操作时间 -- **数据查询**:支持灵活的设备运行时状态查询 - -### 安全特性 -- **身份验证**:所有接口都需要用户身份验证 -- **权限控制**:通过Authorize特性控制访问权限 -- **参数验证**:输入参数验证防止恶意输入 -- **业务规则**:状态检查防止非法操作 - -### 影响范围 -- **API接口**:新增设备运行时状态管理相关的API接口 -- **业务逻辑**:新增设备启动/停止的业务逻辑 -- **数据访问**:通过仓储层访问设备运行时状态数据 -- **前端集成**:为前端提供设备运行时状态管理接口 - -### 后续工作建议 -1. **单元测试**:为所有命令和查询处理器编写单元测试 -2. **集成测试**:测试API接口的完整功能 -3. **前端开发**:开发设备运行时状态管理的前端界面 -4. **文档编写**:编写API接口文档和使用说明 -5. **性能优化**:根据实际使用情况优化查询性能 - -## 2025-01-29 优化GetRuntimeByDeviceCodeAsync方法返回最新记录 - -### 修改原因 -根据用户需求,`GetRuntimeByDeviceCodeAsync`方法需要返回按创建时间排序的最新一条记录,而不是任意一条记录。 - -### 修改文件 -- `X1.Infrastructure/Repositories/Device/CellularDeviceRuntimeRepository.cs` - 优化GetRuntimeByDeviceCodeAsync方法 - -### 修改内容 - -#### 1. 方法实现优化 -- **原实现**:使用`FirstOrDefaultAsync`直接查询,返回任意一条匹配记录 -- **新实现**:使用`FindAsync`查询所有匹配记录,然后按`CreatedAt`降序排序,返回第一条记录 - -#### 2. 查询逻辑 -```csharp -var runtimes = await QueryRepository.FindAsync(r => r.DeviceCode == deviceCode, cancellationToken: cancellationToken); -return runtimes.OrderByDescending(r => r.CreatedAt).FirstOrDefault(); -``` - -#### 3. 性能考虑 -- **内存排序**:在应用层进行排序,适用于记录数量较少的情况 -- **数据库排序**:如果记录数量较多,建议在数据库层进行排序优化 - -### 技术特性 -- **数据准确性**:确保返回的是最新创建的运行时状态记录 -- **向后兼容**:方法签名保持不变,不影响现有调用 -- **错误处理**:保持原有的空值处理逻辑 - -### 业务价值 -- **状态准确性**:获取设备的最新运行时状态,而不是历史状态 -- **数据一致性**:确保查询结果的一致性,避免返回过时的状态信息 -- **用户体验**:提供更准确的设备状态信息 - -### 影响范围 -- **查询结果**:现在返回的是按创建时间排序的最新记录 -- **性能影响**:对于有多个运行时状态记录的设备,会有轻微的性能影响 -- **API行为**:API返回的数据更加准确和有意义 - -### 后续工作建议 -1. **性能监控**:监控查询性能,特别是对于有大量历史记录的设备 -2. **索引优化**:考虑在数据库层面添加`(DeviceCode, CreatedAt)`的复合索引 -3. **数据清理**:考虑清理过时的运行时状态记录,减少数据量 - -## 2024-12-19 仪器客户端接口规范化重构 - -### 修改文件 -- `X1.DynamicClientCore/Features/IBaseInstrumentClient.cs` - 规范化基础仪器客户端接口 -- `X1.DynamicClientCore/Features/IInstrumentProtocolClient.cs` - 规范化仪器协议客户端接口 -- `X1.DynamicClientCore/Features/IInstrumentHttpClient.cs` - 创建仪器HTTP客户端接口 -- `X1.DynamicClientCore/Features/Service/InstrumentProtocolClient.cs` - 更新实现类方法名 - -### 修改内容 - -#### 1. IBaseInstrumentClient 接口规范化 -- **添加完整注释**:为接口和方法添加详细的XML文档注释 -- **方法命名规范化**:`GetDeviceSerialNumber` → `GetDeviceSerialNumberAsync` -- **参数文档**:为所有参数添加详细的说明文档 -- **异常文档**:添加可能抛出的异常类型说明 -- **接口说明**:添加接口用途和设计理念的说明 - -#### 2. IInstrumentProtocolClient 接口规范化 -- **添加完整注释**:为接口和所有方法添加详细的XML文档注释 -- **方法命名规范化**: - - `StartNetwork` → `StartNetworkAsync` - - `StopNetwork` → `StopNetworkAsync` -- **参数命名规范化**:`InstrumentNumber` → `instrumentNumber`(遵循C#命名规范) -- **参数文档**:为所有参数添加详细的说明文档 -- **异常文档**:添加可能抛出的异常类型说明 -- **接口说明**:添加接口用途和设计理念的说明 - -#### 3. IInstrumentHttpClient 接口创建 -- **接口设计**:创建组合接口,继承自 `IBaseInstrumentClient` 和 `IInstrumentProtocolClient` -- **功能组合**:提供完整的仪器设备通信服务 -- **接口说明**:添加详细的接口用途和设计理念说明 -- **方法继承**:明确说明继承的方法和功能 - -#### 4. InstrumentProtocolClient 实现类更新 -- **方法名更新**:更新所有方法名以匹配接口定义 -- **接口实现**:改为实现 `IInstrumentHttpClient` 接口 -- **方法签名**:确保方法签名与接口定义完全一致 - -### 技术特性 -- **命名规范**:遵循C#异步方法命名规范(Async后缀) -- **接口设计**:使用接口组合模式,提供灵活的功能组合 -- **文档完整**:为所有接口和方法提供完整的XML文档注释 -- **类型安全**:确保接口定义和实现的一致性 -- **异常处理**:明确定义可能抛出的异常类型 - -### 设计理念 -- **职责分离**:基础功能、协议功能、HTTP功能分别定义 -- **接口组合**:通过接口继承实现功能组合 -- **命名一致性**:统一的命名规范和异步方法约定 -- **文档驱动**:完整的文档注释,便于理解和使用 - -### 用户体验改进 -- **代码可读性**:清晰的接口定义和方法命名 -- **开发体验**:完整的IntelliSense支持和文档提示 -- **维护性**:清晰的接口层次和职责划分 -- **扩展性**:灵活的接口组合,便于功能扩展 - -## 2024-12-19 InstrumentProtocolClient 规范化重构 - -### 修改文件 -- `X1.DynamicClientCore/Features/Service/InstrumentProtocolClient.cs` - 规范化仪器协议客户端实现 - -### 修改内容 - -#### 1. 代码结构优化 -- **构造函数规范化**:修复参数命名不一致问题,使用统一的命名规范 -- **字段重命名**:`_dynamicHttp` → `_dynamicHttpClient`,`_endpointManager` → `_serviceEndpointManager` -- **参数验证**:添加空值检查和异常抛出,确保依赖注入的正确性 -- **代码格式**:统一代码格式和缩进,提高可读性 - -#### 2. 方法规范化 -- **GetDeviceSerialNumber方法**: - - 添加完整的XML文档注释 - - 改进错误处理逻辑,区分不同类型的错误 - - 优化日志记录,使用结构化日志 - - 修复ApiActionResult字段访问错误(ErrorMessage → Message) - - 添加参数验证和异常处理 - -- **StartNetwork方法**: - - 添加完整的XML文档注释 - - 添加参数验证(仪器编号不能为空) - - 添加异常处理和日志记录 - - 添加TODO注释,说明需要实现的业务逻辑 - -- **StopNetwork方法**: - - 添加完整的XML文档注释 - - 添加参数验证(仪器编号不能为空) - - 添加异常处理和日志记录 - - 添加TODO注释,说明需要实现的业务逻辑 - -#### 3. 错误处理改进 -- **分层异常处理**:区分WebSocket异常和其他异常 -- **详细错误日志**:提供更详细的错误信息和上下文 -- **参数验证**:添加输入参数的空值检查和验证 -- **异常传播**:合理处理异常传播,避免不必要的异常捕获 - -#### 4. 日志记录优化 -- **结构化日志**:使用结构化日志记录,提高日志可读性 -- **日志级别**:合理使用Debug、Info、Warning、Error级别 -- **上下文信息**:添加连接ID、端点名称等上下文信息 -- **性能监控**:添加关键操作的性能监控日志 - -#### 5. 代码质量提升 -- **XML文档注释**:为类、方法、参数添加完整的XML文档注释 -- **命名规范**:统一变量和方法命名规范 -- **代码组织**:优化代码结构,提高可维护性 -- **类型安全**:确保类型安全和空值处理 - -### 技术特性 -- **依赖注入**:正确使用依赖注入模式 -- **异步编程**:使用async/await模式,支持取消令牌 -- **错误处理**:完整的异常处理和错误恢复机制 -- **日志记录**:结构化日志记录,便于监控和调试 -- **参数验证**:输入参数验证,确保数据完整性 - -### 用户体验改进 -- **错误提示**:提供更清晰的错误信息和处理建议 -- **性能监控**:通过日志监控系统性能和响应时间 -- **调试支持**:详细的调试日志,便于问题排查 -- **代码可读性**:清晰的代码结构和注释,便于维护 - -### 后续开发建议 -- **业务逻辑实现**:根据具体需求实现StartNetwork和StopNetwork方法 -- **单元测试**:为重构后的方法添加单元测试 -- **集成测试**:测试与其他组件的集成 -- **性能优化**:根据实际使用情况优化性能 - -## 2024-12-19 RAN配置列表状态开关优化 - -### 修改文件 -- `X1.WebUI/src/pages/ran-configurations/RANConfigurationsTable.tsx` - 将状态徽章改为状态开关,支持直接修改状态 -- `X1.WebUI/src/pages/ran-configurations/RANConfigurationsView.tsx` - 添加状态切换处理逻辑 - -### 修改内容 -- **状态显示优化**:将状态列从徽章显示改为状态开关显示 -- **直接状态修改**:用户可以直接在列表中点击状态开关来启用/禁用配置 -- **实时状态更新**:状态修改后立即更新列表显示 -- **操作反馈**:提供状态修改成功/失败的提示信息 -- **防重复提交**:在状态修改过程中禁用开关,防止重复操作 - -### 技术特性 -- **状态开关组件**:使用StatusSwitch组件,提供直观的开关界面 -- **异步状态更新**:通过API调用更新配置状态 -- **错误处理**:完整的错误处理和用户提示 -- **加载状态**:在操作过程中显示加载状态 -- **数据同步**:状态修改后自动刷新列表数据 - -### 用户体验改进 -- **直观的状态显示**:状态开关比徽章更直观地显示当前状态 -- **便捷的状态修改**:无需打开编辑界面,直接在列表中修改状态 -- **即时反馈**:状态修改后立即看到结果 -- **操作简化**:减少了打开编辑界面的步骤 -- **视觉一致性**:与其他配置管理页面保持一致的交互方式 - -## 2024-12-19 修复RAN配置抽屉保存按钮显示问题 - -### 修改文件 -- `X1.WebUI/src/components/ui/drawer.tsx` - 修复抽屉组件布局问题 -- `X1.WebUI/src/pages/ran-configurations/RANConfigurationDrawer.tsx` - 优化抽屉表单布局 -- `X1.WebUI/src/pages/ran-configurations/RANConfigurationForm.tsx` - 删除已废弃的表单组件 - -### 修改内容 -- **修复布局问题**:为DrawerContent添加overflow-y-auto,确保内容可滚动 -- **优化表单布局**:调整抽屉表单的flex布局,确保保存按钮正确显示 -- **滚动优化**:DrawerContent支持垂直滚动,避免内容溢出 -- **移除状态开关**:从抽屉表单中移除状态开关,因为状态修改已在列表中实现 -- **修复标签重复**:移除抽屉中的重复标签,使用ConfigContentEditor内部的标签 -- **布局简化**:简化配置内容区域的布局结构,确保保存按钮正确显示 -- **空间分配**:正确分配flex空间,确保保存按钮始终可见 -- **布局重构**:重新设计抽屉的整体布局结构,确保保存按钮正确显示 -- **清理废弃文件**:删除已不再使用的RANConfigurationForm.tsx文件 - -### 技术特性 -- **正确的flex布局**:确保表单内容、配置编辑器和保存按钮都能正确显示 -- **滚动支持**:当内容超出抽屉高度时,支持垂直滚动 -- **布局稳定性**:修复了保存按钮被隐藏的问题 -- **功能分离**:状态修改在列表中,配置内容编辑在抽屉中 -- **标签优化**:避免标签重复,使用组件内部的标签显示 -- **空间管理**:合理分配垂直空间,确保所有元素都能正确显示 -- **布局层次**:正确的HTML结构层次,确保CSS布局正常工作 - -### 用户体验改进 -- **保存按钮可见**:修复了保存按钮看不到的问题 -- **布局稳定**:抽屉内容布局更加稳定和可预测 -- **滚动体验**:支持内容滚动,适应不同屏幕高度 -- **功能清晰**:状态修改和内容编辑功能分离,避免重复 -- **界面简洁**:移除重复标签,界面更加简洁 -- **操作便利**:保存按钮始终可见,用户可以方便地保存配置 -- **代码清理**:删除废弃的RANConfigurationForm.tsx,保持代码库整洁 - -## 2024-12-19 IMS配置改用抽屉组件 - -### 修改文件 -- `X1.WebUI/src/pages/ims-configurations/IMSConfigurationDrawer.tsx` - 创建IMS配置抽屉组件 -- `X1.WebUI/src/pages/ims-configurations/IMSConfigurationsTable.tsx` - 添加状态开关功能 -- `X1.WebUI/src/pages/ims-configurations/IMSConfigurationsView.tsx` - 使用抽屉组件替代对话框 -- `X1.WebUI/src/pages/ims-configurations/IMSConfigurationForm.tsx` - 删除已废弃的表单组件 - -### 修改内容 -- **创建抽屉组件**:参考RAN配置实现,创建IMS配置的抽屉组件 -- **状态开关集成**:在表格中添加状态开关,支持直接修改IMS配置状态 -- **抽屉布局**:使用与RAN配置相同的抽屉布局,确保保存按钮正确显示 -- **功能分离**:状态修改在列表中,配置内容编辑在抽屉中 -- **代码清理**:删除废弃的IMSConfigurationForm.tsx文件 - -### 技术特性 -- **抽屉布局**:右侧滑出的抽屉,提供更大的编辑空间 -- **状态管理**:表格中的状态开关,支持直接切换启用/禁用状态 -- **配置编辑器**:使用ConfigContentEditor组件,支持大文本编辑 -- **响应式设计**:抽屉支持滚动,适应不同屏幕高度 -- **统一体验**:与RAN配置保持一致的交互体验 - -### 用户体验改进 -- **更大编辑空间**:抽屉提供比对话框更大的编辑区域 -- **直接状态修改**:在列表中直接切换状态,无需进入编辑模式 -- **一致的操作体验**:与RAN配置保持相同的操作方式 -- **更好的视觉反馈**:状态开关提供直观的启用/禁用状态显示 - -## 2024-12-19 Core Network配置改用抽屉组件 - -### 修改文件 -- `X1.WebUI/src/pages/core-network-configs/CoreNetworkConfigDrawer.tsx` - 创建Core Network配置抽屉组件 -- `X1.WebUI/src/pages/core-network-configs/CoreNetworkConfigsTable.tsx` - 添加状态开关功能 -- `X1.WebUI/src/pages/core-network-configs/CoreNetworkConfigsView.tsx` - 使用抽屉组件替代对话框 -- `X1.WebUI/src/pages/core-network-configs/CoreNetworkConfigForm.tsx` - 删除已废弃的表单组件 - -### 修改内容 -- **创建抽屉组件**:参考RAN配置实现,创建Core Network配置的抽屉组件 -- **状态开关集成**:在表格中添加状态开关,支持直接修改Core Network配置状态 -- **抽屉布局**:使用与RAN配置相同的抽屉布局,确保保存按钮正确显示 -- **功能分离**:状态修改在列表中,配置内容编辑在抽屉中 -- **代码清理**:删除废弃的CoreNetworkConfigForm.tsx文件 - -### 技术特性 -- **抽屉布局**:右侧滑出的抽屉,提供更大的编辑空间 -- **状态管理**:表格中的状态开关,支持直接切换启用/禁用状态 -- **配置编辑器**:使用ConfigContentEditor组件,支持大文本编辑 -- **响应式设计**:抽屉支持滚动,适应不同屏幕高度 -- **统一体验**:与RAN配置和IMS配置保持一致的交互体验 - -### 用户体验改进 -- **更大编辑空间**:抽屉提供比对话框更大的编辑区域 -- **直接状态修改**:在列表中直接切换状态,无需进入编辑模式 -- **一致的操作体验**:与RAN配置和IMS配置保持相同的操作方式 -- **更好的视觉反馈**:状态开关提供直观的启用/禁用状态显示 - -## 2024-12-19 RAN配置创建改用抽屉组件 - -### 修改文件 -- `X1.WebUI/src/components/ui/drawer.tsx` - 新增抽屉组件 -- `X1.WebUI/src/pages/ran-configurations/RANConfigurationDrawer.tsx` - 新增RAN配置抽屉表单组件 -- `X1.WebUI/src/pages/ran-configurations/RANConfigurationsView.tsx` - 修改为使用抽屉组件 -- `X1.WebUI/src/components/ui/ConfigContentEditor.tsx` - 优化配置内容编辑器,支持高度自适应 - -### 修改内容 -- **创建抽屉组件**:实现右侧滑出的抽屉组件,提供更大的编辑空间 -- **RAN配置抽屉表单**:专门为RAN配置设计的抽屉表单,支持配置内容的编辑 -- **替换对话框**:将原有的对话框创建/编辑方式改为抽屉方式 -- **优化编辑体验**:为配置内容提供更大的编辑区域,支持自适应高度 -- **修复定位问题**:修复抽屉组件显示位置错误的问题,确保从右侧正确滑出 -- **配置内容自适应**:配置内容编辑器现在能够占满抽屉中的剩余空间 - -### 技术特性 -- **抽屉组件**:600px宽度,支持动画效果,右侧滑出 -- **配置内容编辑器**:使用ConfigContentEditor组件,支持搜索高亮功能和高度自适应 -- **状态开关**:使用StatusSwitch组件,提供更好的视觉反馈 -- **表单验证**:保持原有的表单验证逻辑 -- **响应式设计**:支持90%视口宽度的最大限制 -- **正确定位**:使用fixed定位和transform动画,确保抽屉从右侧正确滑出 -- **弹性布局**:使用flex布局,配置内容编辑器自动占满剩余空间 - -### 用户体验改进 -- **更大的编辑空间**:抽屉提供比对话框更大的编辑区域 -- **更好的配置内容编辑**:配置内容编辑器自动占满剩余空间,提供最大编辑区域 -- **保持上下文**:抽屉不会完全遮挡主界面,用户可以看到背景内容 -- **流畅的动画**:右侧滑入滑出动画提供良好的交互体验 -- **正确的显示位置**:抽屉从右侧正确滑出,不会显示在错误位置 -- **自适应高度**:配置内容编辑器根据抽屉高度自动调整,充分利用可用空间 - -## 2024-12-19 网络栈配置菜单图标修改 - -### 修改文件 -- `X1.WebUI/src/constants/menuConfig.ts` - 修改网络栈配置菜单项的图标 - -### 修改内容 -- 导入 `Network` 图标:在 lucide-react 导入中添加 `Network` -- 修改网络栈配置菜单项图标:将 `icon: Gauge` 改为 `icon: Network` -- 使网络栈配置菜单项与仪表管理菜单项使用不同的图标,提高视觉区分度 - -### 技术说明 -- 仪表管理菜单项继续使用 `Gauge` 图标 -- 网络栈配置菜单项使用 `Network` 图标,更符合网络配置的功能定位 -- 提高了菜单的视觉层次和用户体验 - -## 2024-12-19 配置表格Key属性统一修复 - -### 修改文件 -- `X1.WebUI/src/pages/ran-configurations/RANConfigurationsTable.tsx` - 修复React Key属性警告 -- `X1.WebUI/src/pages/ims-configurations/IMSConfigurationsTable.tsx` - 修复React Key属性警告 -- `X1.WebUI/src/pages/core-network-configs/CoreNetworkConfigsTable.tsx` - 修复React Key属性警告 - -### 问题修复 -- **Key属性警告**:修复了所有配置表格中缺少唯一key属性的React警告 -- **唯一标识**:为每个TableCell添加了基于配置ID和列键的唯一key -- **操作按钮Key**:重构操作列中的按钮渲染,使用map方法确保每个按钮都有唯一key -- **容器Key清理**:移除了TableHeader和TableBody上不必要的key属性 -- **性能优化**:确保React能够正确识别和更新列表项 - -### 技术细节 -- 将 `key={column.key}` 修改为 `key={`${configuration.raN_ConfigurationId}-${column.key}`}`、`key={`${configuration.ims_ConfigurationId}-${column.key}`}` 和 `key={`${config.CoreNetworkConfigId}-${column.key}`}` -- 重构操作列按钮渲染:使用数组map渲染,确保每个按钮都有唯一key -- 使用动态key:将TableHeader和TableBody的key改为 `key={`header-${Date.now()}`}` 和 `key={`body-${Date.now()}`}` -- 确保每个表格单元格和子元素都有唯一的key属性 -- 避免React渲染时的key冲突问题 -- 修复actions列中span元素的key:使用 `key={`${configuration.id}-${item.key}`}` 格式 -- 修复TableHead的key:使用 `key={`header-${col.key}-${index}`}` 格式,包含索引确保唯一性 -- 修复TableRow的key:使用 `key={`${configuration.id}-${index}`}` 格式,包含索引确保唯一性 - -### 重构说明 -- 将操作列中的两个静态span元素改为数组map渲染 -- 每个按钮对象包含key、className、onClick和text属性 -- 通过map方法确保每个渲染的元素都有唯一的key属性 -- 使用动态时间戳作为容器元素的key,避免写死的key值 -- 为actions列中的span元素添加更唯一的key,包含配置ID和操作类型 -- 为TableHead添加更唯一的key,包含列key和索引,避免重复key冲突 -- 为TableRow添加更唯一的key,包含配置ID和索引,确保每行都有唯一标识 - -## 2024-12-19 修复Dialog可访问性警告 - -### 问题描述 -- Radix UI Dialog组件要求 `DialogContent` 必须包含 `DialogTitle` 以确保屏幕阅读器可访问性 -- 项目中多个Dialog组件缺少 `DialogTitle`,导致可访问性警告 - -### 修复内容 -1. **Dialog组件导出**: - - 在 `dialog.tsx` 中添加 `DialogTitle` 和 `DialogDescription` 的导出 - -2. **RAN配置视图**: - - 添加 `DialogTitle` 导入 - - 为创建和编辑对话框添加标题:"创建RAN配置" 和 "编辑RAN配置" - -3. **IMS配置视图**: - - 添加 `DialogTitle` 导入 - - 为创建和编辑对话框添加标题:"创建IMS配置" 和 "编辑IMS配置" - -4. **核心网络配置视图**: - - 添加 `DialogTitle` 导入 - - 为创建和编辑对话框添加标题:"创建核心网络配置" 和 "编辑核心网络配置" - -### 技术说明 -- 确保所有Dialog组件都符合Radix UI的可访问性要求 -- 为屏幕阅读器用户提供更好的体验 -- 添加语义化的对话框标题,提高用户体验 -- 使用一致的样式:`text-lg font-semibold mb-4` - -## 2024-12-19 修复配置字段名不匹配问题 - -### 问题描述 -- 前端接口定义与后端API返回的数据字段名不匹配 -- 导致前端访问配置ID时出现 undefined 错误 - -### RAN配置修复内容 -1. **修复前端接口定义**: - - `RANConfiguration` 接口:`id` → `raN_ConfigurationId` - - `CreateRANConfigurationResponse` 接口:`id` → `raN_ConfigurationId` - - `UpdateRANConfigurationRequest` 接口:`id` → `raN_ConfigurationId` - - `UpdateRANConfigurationResponse` 接口:`id` → `raN_ConfigurationId` - -2. **修复表格组件**: - - `RANConfigurationsTable.tsx`:`configuration.id` → `configuration.raN_ConfigurationId` - - 表格行key:`key={configuration.id}` → `key={configuration.raN_ConfigurationId}` - - 表格单元格key:`key={`${configuration.id}-${column.key}`}` → `key={`${configuration.raN_ConfigurationId}-${column.key}`}` - -3. **修复视图组件**: - - `RANConfigurationsView.tsx`:删除和更新操作中的字段引用 - - `configuration.id` → `configuration.raN_ConfigurationId` - - `selectedConfiguration.id` → `selectedConfiguration.raN_ConfigurationId` - -### IMS配置修复内容 -1. **修复前端接口定义**: - - `IMSConfiguration` 接口:`imsConfigurationId` → `ims_ConfigurationId` - - `CreateIMSConfigurationResponse` 接口:`imsConfigurationId` → `ims_ConfigurationId` - - `UpdateIMSConfigurationRequest` 接口:`imsConfigurationId` → `ims_ConfigurationId` - - `UpdateIMSConfigurationResponse` 接口:`imsConfigurationId` → `ims_ConfigurationId` - -2. **修复表格组件**: - - `IMSConfigurationsTable.tsx`:`configuration.imsConfigurationId` → `configuration.ims_ConfigurationId` - - 表格行key:`key={configuration.imsConfigurationId}` → `key={configuration.ims_ConfigurationId}` - - 表格单元格key:`key={`${configuration.imsConfigurationId}-${column.key}`}` → `key={`${configuration.ims_ConfigurationId}-${column.key}`}` - -3. **修复视图组件**: - - `IMSConfigurationsView.tsx`:删除和更新操作中的字段引用 - - `configuration.imsConfigurationId` → `configuration.ims_ConfigurationId` - - `selectedConfiguration.imsConfigurationId` → `selectedConfiguration.ims_ConfigurationId` - -### 核心网络配置修复内容 -1. **修复前端接口定义**: - - `CoreNetworkConfig` 接口:`coreNetworkConfigId` → `CoreNetworkConfigId` - - `CreateCoreNetworkConfigResponse` 接口:`coreNetworkConfigId` → `CoreNetworkConfigId` - - `UpdateCoreNetworkConfigRequest` 接口:`coreNetworkConfigId` → `CoreNetworkConfigId` - - `UpdateCoreNetworkConfigResponse` 接口:`coreNetworkConfigId` → `CoreNetworkConfigId` - -2. **修复表格组件**: - - `CoreNetworkConfigsTable.tsx`:`config.coreNetworkConfigId` → `config.CoreNetworkConfigId` - - 表格行key:`key={config.coreNetworkConfigId}` → `key={config.CoreNetworkConfigId}` - - 表格单元格key:`key={`${config.coreNetworkConfigId}-${column.key}`}` → `key={`${config.CoreNetworkConfigId}-${column.key}`}` - -3. **修复视图组件**: - - `CoreNetworkConfigsView.tsx`:删除和更新操作中的字段引用 - - `config.coreNetworkConfigId` → `config.CoreNetworkConfigId` - - `selectedConfig.coreNetworkConfigId` → `selectedConfig.CoreNetworkConfigId` - -### 技术说明 -- 统一前后端字段命名规范 -- 确保前端接口定义与后端API返回数据格式一致 -- 修复所有相关的字段引用 -- 避免运行时出现 undefined 错误 -- 注意后端返回的字段名大小写: - - RAN配置:`raN_ConfigurationId` - - IMS配置:`ims_ConfigurationId` - - 核心网络配置:`CoreNetworkConfigId` - -## 2024-12-19 配置表单统一集成配置内容编辑器 - -### 修改文件 -- `X1.WebUI/src/pages/ims-configurations/IMSConfigurationForm.tsx` - 集成配置内容编辑器 -- `X1.WebUI/src/pages/core-network-configs/CoreNetworkConfigForm.tsx` - 集成配置内容编辑器 - -### 功能统一 -- **IMS配置表单**:使用新的配置内容编辑器替换原有的Textarea -- **核心网络配置表单**:使用新的配置内容编辑器替换原有的Textarea -- **功能一致性**:所有配置表单现在都支持搜索高亮功能 - -### 技术实现 -- 导入 `ConfigContentEditor` 组件 -- 替换原有的配置内容输入区域 -- 移除JSON格式限制的提示文本 -- 保持表单的其他功能不变 - -### 用户体验 -- **统一体验**:所有配置表单现在都有相同的编辑体验 -- **搜索功能**:支持在配置内容中搜索和高亮显示匹配项 -- **格式灵活**:不再强制要求JSON格式,支持任意格式的配置内容 - -## 2024-12-19 RAN配置表格Key属性修复 - -### 修改文件 -- `X1.WebUI/src/pages/ran-configurations/RANConfigurationsTable.tsx` - 修复React Key属性警告 - -### 问题修复 -- **Key属性警告**:修复了表格单元格缺少唯一key属性的React警告 -- **唯一标识**:为每个TableCell添加了基于配置ID和列键的唯一key -- **操作按钮Key**:重构操作列中的按钮渲染,使用map方法确保每个按钮都有唯一key -- **性能优化**:确保React能够正确识别和更新列表项 - -### 技术细节 -- 将 `key={column.key}` 修改为 `key={`${configuration.ranConfigurationId}-${column.key}`}` -- 重构操作列按钮渲染:使用数组map方法替代静态JSX,确保每个按钮都有唯一key -- 确保每个表格单元格和子元素都有唯一的key属性 -- 避免React渲染时的key冲突问题 - -### 重构说明 -- 将操作列中的两个静态span元素改为数组map渲染 -- 每个按钮对象包含key、className、onClick和text属性 -- 通过map方法确保每个渲染的元素都有唯一的key属性 - -## 2024-12-19 配置内容编辑器组件简化 - -### 修改文件 -- `X1.WebUI/src/components/ui/ConfigContentEditor.tsx` - 简化配置内容编辑器组件 - -### 功能调整 - -#### 1. 移除的功能 -- **复制功能**:移除了复制到剪贴板的功能 -- **导出功能**:移除了导出为文件的功能 -- **导入功能**:移除了从文件导入的功能 -- **模板管理**:移除了模板注册、查询、修改、删除功能 - -#### 2. 新增的功能 -- **搜索高亮**:支持在配置内容中搜索并高亮显示匹配项 -- **实时搜索**:输入搜索关键词时实时高亮所有匹配项 -- **导航功能**:支持上一个/下一个匹配项的快速导航 -- **匹配计数**:显示当前搜索关键词的匹配数量 - -#### 3. 搜索功能特性 -- **高亮显示**:使用黄色背景高亮所有匹配的文本 -- **大小写不敏感**:搜索时忽略大小写 -- **正则表达式转义**:自动转义特殊字符,支持普通文本搜索 -- **循环搜索**:到达末尾时自动从头开始,到达开头时自动从末尾开始 - -#### 4. 用户体验 -- **简洁界面**:只保留搜索按钮,界面更加简洁 -- **快速访问**:点击搜索按钮即可打开搜索栏 -- **键盘友好**:搜索栏自动获得焦点,支持回车键操作 -- **视觉反馈**:匹配项数量实时显示 - -### 技术实现 -- **高亮层**:使用绝对定位的透明层显示高亮效果 -- **正则匹配**:使用正则表达式进行大小写不敏感的匹配 -- **选择导航**:通过 setSelectionRange 实现光标定位 -- **状态管理**:使用 useState 管理搜索状态和高亮内容 - -### 使用方式 -```tsx - -``` - -### 界面布局 -- **工具栏**:只包含搜索按钮 -- **搜索栏**:可展开的搜索输入框和导航按钮 -- **编辑器**:主要的文本编辑区域,支持高亮显示 -- **高亮层**:覆盖在编辑器上的透明高亮层 - -## 2024-12-19 RAN配置页面展开按钮移除 - -### 修改文件 -- `X1.WebUI/src/pages/ran-configurations/RANConfigurationsView.tsx` - -### 修改内容 - -#### 1. 移除展开/收起功能 -- 删除了 `ChevronDownIcon` 和 `ChevronUpIcon` 的导入 -- 移除了 `showAdvanced` 状态变量 -- 删除了 `advancedFields` 高级字段配置 -- 将 `firstRowFields` 重命名为 `searchFields` - -#### 2. 简化搜索栏结构 -- 移除了展开/收起按钮 -- 只保留基本的搜索字段:搜索关键词和状态 -- 简化了表单布局,固定为3列网格布局 -- 移除了每页数量选择功能(该功能已移至分页组件) - -#### 3. 优化代码结构 -- 移除了条件渲染逻辑 -- 简化了字段映射和事件处理 -- 保持了类型安全和错误处理 - -### 功能影响 -- **用户体验**:搜索界面更简洁,减少了用户操作复杂度 -- **界面布局**:搜索栏高度固定,布局更稳定 -- **功能完整性**:核心搜索功能保持不变,分页大小调整功能移至分页组件 - -### 技术细节 -- 保持了所有必要的搜索功能 -- 维持了类型安全和错误处理机制 -- 简化了组件状态管理 -- 提高了代码可读性和维护性 - -## 2024-12-19 网络栈配置管理页面实现 - -### 新增文件 -- `X1.WebUI/src/pages/network-stack-configs/NetworkStackConfigsView.tsx` - 网络栈配置页面视图组件 -- `X1.WebUI/src/pages/network-stack-configs/NetworkStackConfigsTable.tsx` - 网络栈配置表格组件 -- `X1.WebUI/src/pages/network-stack-configs/NetworkStackConfigForm.tsx` - 网络栈配置表单组件 - -### 修改文件 -- `X1.WebUI/src/routes/AppRouter.tsx` - 添加网络栈配置页面路由,将网络栈配置相关页面从仪表管理中分离 -- `X1.WebUI/src/constants/menuConfig.ts` - 添加网络栈配置权限和菜单项,将网络栈配置作为独立菜单项 -- `X1.WebUI/src/contexts/AuthContext.tsx` - 在 getDefaultPermissions 函数中添加网络栈配置相关权限 - -### 功能特性 - -#### 1. 页面组件结构 -- **NetworkStackConfigsView**: 主页面视图,包含搜索、表格、分页等功能 -- **NetworkStackConfigsTable**: 数据表格组件,支持列显示控制、密度调整 -- **NetworkStackConfigForm**: 创建/编辑表单组件,支持栈ID、RAN ID等字段编辑 - -#### 2. 搜索功能 -- 支持按栈ID和描述搜索 -- 支持按激活/非激活状态过滤 -- 支持分页大小调整 -- 提供展开/收起高级搜索选项 - -#### 3. 表格功能 -- 支持列显示控制(栈ID、RAN ID、描述、状态、创建时间、操作) -- 支持表格密度调整(宽松、默认、紧凑) -- 栈ID使用等宽字体显示,便于识别 -- 状态徽章显示(激活/非激活) -- 日期格式化显示 - -#### 4. 表单功能 -- 栈ID输入(必填,编辑时不允许修改) -- RAN ID输入(可选) -- 描述信息输入(可选) -- 激活/非激活状态切换 -- 表单验证和提交状态管理 - -#### 5. 权限控制 -- 添加 `networkstackconfigs.view` 和 `networkstackconfigs.manage` 权限 -- 路由级别的权限保护 -- 菜单项权限控制 - -#### 6. 用户体验 -- 加载状态显示 -- 操作成功/失败提示 -- 删除确认对话框 -- 防重复提交保护 -- 响应式设计 -- 编辑时栈ID字段禁用,防止误操作 - -### 技术实现 - -#### 1. 组件设计 -- 参考协议管理页面的设计模式 -- 使用TypeScript确保类型安全 -- 采用React Hooks管理状态 -- 使用shadcn/ui组件库 - -#### 2. 数据管理 -- 使用网络栈配置服务进行API调用 -- 支持分页、搜索、过滤功能 -- 完整的CRUD操作支持 - -#### 3. 路由配置 -- 懒加载组件提高性能 -- 权限保护路由 -- 动画容器包装 - -#### 4. 样式设计 -- 统一的UI风格 -- 响应式布局 -- 美观的表格和表单设计 -- 栈ID使用等宽字体,提高可读性 - -### 使用方式 -1. 通过菜单 "网络栈配置" 访问页面 -2. 支持创建、编辑、删除网络栈配置 -3. 支持按栈ID、描述搜索配置 -4. 支持按激活状态过滤配置 -5. 支持调整表格显示密度和列显示 -6. 编辑时栈ID字段自动禁用,防止误操作 - -### 路由结构调整 -- 将网络栈配置相关页面从 `/dashboard/instruments` 下分离出来 -- 创建独立的 `/dashboard/network-stack-configs` 路由组 -- 包含以下子路由: - - `/dashboard/network-stack-configs/ran-configurations` - RAN配置管理 - - `/dashboard/network-stack-configs/ims-configurations` - IMS配置管理 - - `/dashboard/network-stack-configs/core-network-configs` - 核心网络配置管理 - - `/dashboard/network-stack-configs/network-stack-configs` - 网络栈配置管理 - -### 菜单结构调整 -- 将网络栈配置从仪表管理菜单中分离出来 -- 创建独立的"网络栈配置"顶级菜单项 -- 包含四个子菜单项:RAN配置、IMS配置、核心网络配置、网络栈配置 -- 使用 `ranconfigurations.view` 权限作为主菜单权限 - -### 权限配置 -- 在 `AuthContext.tsx` 的 `getDefaultPermissions` 函数中添加了网络栈配置相关权限: - - `ranconfigurations.view` 和 `ranconfigurations.manage` - - `imsconfigurations.view` 和 `imsconfigurations.manage` - - `corenetworkconfigs.view` 和 `corenetworkconfigs.manage` - - `networkstackconfigs.view` 和 `networkstackconfigs.manage` -- 确保用户登录后能够正确获取网络栈配置相关权限 - -## 2024-12-19 核心网络配置管理页面实现 - -### 新增文件 -- `X1.WebUI/src/pages/core-network-configs/CoreNetworkConfigsView.tsx` - 核心网络配置页面视图组件 -- `X1.WebUI/src/pages/core-network-configs/CoreNetworkConfigsTable.tsx` - 核心网络配置表格组件 -- `X1.WebUI/src/pages/core-network-configs/CoreNetworkConfigForm.tsx` - 核心网络配置表单组件 - -### 修改文件 -- `X1.WebUI/src/routes/AppRouter.tsx` - 添加核心网络配置页面路由 -- `X1.WebUI/src/constants/menuConfig.ts` - 添加核心网络配置权限和菜单项 - -### 功能特性 - -#### 1. 页面组件结构 -- **CoreNetworkConfigsView**: 主页面视图,包含搜索、表格、分页等功能 -- **CoreNetworkConfigsTable**: 数据表格组件,支持列显示控制、密度调整 -- **CoreNetworkConfigForm**: 创建/编辑表单组件,支持JSON配置内容编辑 - -#### 2. 搜索功能 -- 支持按配置名称和描述搜索 -- 支持按启用/禁用状态过滤 -- 支持分页大小调整 -- 提供展开/收起高级搜索选项 - -#### 3. 表格功能 -- 支持列显示控制(配置名称、描述、状态、创建时间、操作) -- 支持表格密度调整(宽松、默认、紧凑) -- 配置内容预览(截断显示,鼠标悬停显示完整内容) -- 状态徽章显示(启用/禁用) -- 日期格式化显示 - -#### 4. 表单功能 -- 配置名称输入(必填) -- JSON格式配置内容编辑(必填,支持多行编辑) -- 描述信息输入(可选) -- 启用/禁用状态切换 -- 表单验证和提交状态管理 - -#### 5. 权限控制 -- 添加 `corenetworkconfigs.view` 和 `corenetworkconfigs.manage` 权限 -- 路由级别的权限保护 -- 菜单项权限控制 - -#### 6. 用户体验 -- 加载状态显示 -- 操作成功/失败提示 -- 删除确认对话框 -- 防重复提交保护 -- 响应式设计 - -### 技术实现 - -#### 1. 组件设计 -- 参考协议管理页面的设计模式 -- 使用TypeScript确保类型安全 -- 采用React Hooks管理状态 -- 使用shadcn/ui组件库 - -#### 2. 数据管理 -- 使用核心网络配置服务进行API调用 -- 支持分页、搜索、过滤功能 -- 完整的CRUD操作支持 - -#### 3. 路由配置 -- 懒加载组件提高性能 -- 权限保护路由 -- 动画容器包装 - -#### 4. 样式设计 -- 统一的UI风格 -- 响应式布局 -- 美观的表格和表单设计 - -### 使用方式 -1. 通过菜单 "仪表管理" -> "核心网络配置" 访问页面 -2. 支持创建、编辑、删除核心网络配置 -3. 支持按名称、描述搜索配置 -4. 支持按启用状态过滤配置 -5. 支持调整表格显示密度和列显示 - -## 2024-12-19 IMS配置管理页面实现 - -### 新增文件 -- `X1.WebUI/src/pages/ims-configurations/IMSConfigurationsView.tsx` - IMS配置页面视图组件 -- `X1.WebUI/src/pages/ims-configurations/IMSConfigurationsTable.tsx` - IMS配置表格组件 -- `X1.WebUI/src/pages/ims-configurations/IMSConfigurationForm.tsx` - IMS配置表单组件 - -### 修改文件 -- `X1.WebUI/src/routes/AppRouter.tsx` - 添加IMS配置页面路由 -- `X1.WebUI/src/constants/menuConfig.ts` - 添加IMS配置权限和菜单项 - -### 功能特性 - -#### 1. 页面组件结构 -- **IMSConfigurationsView**: 主页面视图,包含搜索、表格、分页等功能 -- **IMSConfigurationsTable**: 数据表格组件,支持列显示控制、密度调整 -- **IMSConfigurationForm**: 创建/编辑表单组件,支持JSON配置内容编辑 - -#### 2. 搜索功能 -- 支持按配置名称和描述搜索 -- 支持按启用/禁用状态过滤 -- 支持分页大小调整 -- 提供展开/收起高级搜索选项 - -#### 3. 表格功能 -- 支持列显示控制(配置名称、描述、状态、创建时间、操作) -- 支持表格密度调整(宽松、默认、紧凑) -- 配置内容预览(截断显示,鼠标悬停显示完整内容) -- 状态徽章显示(启用/禁用) -- 日期格式化显示 - -#### 4. 表单功能 -- 配置名称输入(必填) -- JSON格式配置内容编辑(必填,支持多行编辑) -- 描述信息输入(可选) -- 启用/禁用状态切换 -- 表单验证和提交状态管理 - -#### 5. 权限控制 -- 添加 `imsconfigurations.view` 和 `imsconfigurations.manage` 权限 -- 路由级别的权限保护 -- 菜单项权限控制 - -#### 6. 用户体验 -- 加载状态显示 -- 操作成功/失败提示 -- 删除确认对话框 -- 防重复提交保护 -- 响应式设计 - -### 技术实现 - -#### 1. 组件设计 -- 参考协议管理页面的设计模式 -- 使用TypeScript确保类型安全 -- 采用React Hooks管理状态 -- 使用shadcn/ui组件库 - -#### 2. 数据管理 -- 使用IMS配置服务进行API调用 -- 支持分页、搜索、过滤功能 -- 完整的CRUD操作支持 - -#### 3. 路由配置 -- 懒加载组件提高性能 -- 权限保护路由 -- 动画容器包装 - -#### 4. 样式设计 -- 统一的UI风格 -- 响应式布局 -- 美观的表格和表单设计 - -### 使用方式 -1. 通过菜单 "仪表管理" -> "IMS配置" 访问页面 -2. 支持创建、编辑、删除IMS配置 -3. 支持按名称、描述搜索配置 -4. 支持按启用状态过滤配置 -5. 支持调整表格显示密度和列显示 - -## 2024-12-19 RAN配置管理页面实现 - -### 新增文件 -- `X1.WebUI/src/pages/ran-configurations/RANConfigurationsView.tsx` - RAN配置页面视图组件 -- `X1.WebUI/src/pages/ran-configurations/RANConfigurationsTable.tsx` - RAN配置表格组件 -- `X1.WebUI/src/pages/ran-configurations/RANConfigurationForm.tsx` - RAN配置表单组件 - -### 修改文件 -- `X1.WebUI/src/routes/AppRouter.tsx` - 添加RAN配置页面路由 -- `X1.WebUI/src/constants/menuConfig.ts` - 添加RAN配置权限和菜单项 - -### 功能特性 - -#### 1. 页面组件结构 -- **RANConfigurationsView**: 主页面视图,包含搜索、表格、分页等功能 -- **RANConfigurationsTable**: 数据表格组件,支持列显示控制、密度调整 -- **RANConfigurationForm**: 创建/编辑表单组件,支持JSON配置内容编辑 - -#### 2. 搜索功能 -- 支持按配置名称和描述搜索 -- 支持按启用/禁用状态过滤 -- 支持分页大小调整 -- 提供展开/收起高级搜索选项 - -#### 3. 表格功能 -- 支持列显示控制(配置名称、描述、状态、创建时间、操作) -- 支持表格密度调整(宽松、默认、紧凑) -- 配置内容预览(截断显示,鼠标悬停显示完整内容) -- 状态徽章显示(启用/禁用) -- 日期格式化显示 - -#### 4. 表单功能 -- 配置名称输入(必填) -- JSON格式配置内容编辑(必填,支持多行编辑) -- 描述信息输入(可选) -- 启用/禁用状态切换 -- 表单验证和提交状态管理 - -#### 5. 权限控制 -- 添加 `ranconfigurations.view` 和 `ranconfigurations.manage` 权限 -- 路由级别的权限保护 -- 菜单项权限控制 - -#### 6. 用户体验 -- 加载状态显示 -- 操作成功/失败提示 -- 删除确认对话框 -- 防重复提交保护 -- 响应式设计 - -### 技术实现 - -#### 1. 组件设计 -- 参考协议管理页面的设计模式 -- 使用TypeScript确保类型安全 -- 采用React Hooks管理状态 -- 使用shadcn/ui组件库 - -#### 2. 数据管理 -- 使用RAN配置服务进行API调用 -- 支持分页、搜索、过滤功能 -- 完整的CRUD操作支持 - -#### 3. 路由配置 -- 懒加载组件提高性能 -- 权限保护路由 -- 动画容器包装 - -#### 4. 样式设计 -- 统一的UI风格 -- 响应式布局 -- 美观的表格和表单设计 - -### 使用方式 -1. 通过菜单 "仪表管理" -> "RAN配置" 访问页面 -2. 支持创建、编辑、删除RAN配置 -3. 支持按名称、描述搜索配置 -4. 支持按启用状态过滤配置 -5. 支持调整表格显示密度和列显示 - -## 2024-12-19 ProtocolMessageHandler 优化 - -## 2024-12-19 ProtocolMessageHandler 优化 - -### 修改文件 -- `X1.WebSocket/Handlers/ProtocolMessageHandler.cs` - -### 主要改进 - -#### 1. 方法重命名 -- `ProtocolMessageOutput` → `ProcessProtocolMessageAsync` -- 更符合方法命名规范,清晰表达方法功能 - -#### 2. 代码结构优化 -- 将原来的单一方法拆分为多个职责明确的方法: - - `ProcessProtocolMessageAsync`: 处理协议消息的主要逻辑 - - `ProcessProtocolLogs`: 处理协议日志数组 - - `ProcessSingleProtocolLog`: 处理单个协议日志 - -#### 3. 错误处理改进 -- 在 `ProcessProtocolMessageAsync` 方法中添加了完整的异常处理机制 -- 区分 JSON 反序列化错误和其他异常 -- 提供更详细的错误日志信息 -- 移除了 `HandleAsync` 方法中不必要的 try-catch,让异常向上传播 -- 优化异常处理策略:记录错误日志后不再抛出异常,避免异常传播 - -#### 4. 日志记录优化 -- 使用结构化日志记录,提高日志可读性 -- 添加处理进度和统计信息的日志 -- 改进日志级别使用,Debug/Info/Warning/Error 合理分配 -- 美化协议日志输出格式,使用【】括号突出字段名称,提高可读性 -- 添加空值处理,使用 "N/A" 标识空值 -- 时间格式化为易读的时分秒毫秒格式 - -#### 5. 性能优化 -- 添加 JsonSerializerOptions 配置,提高序列化性能 -- 移除不必要的异步操作(ProcessProtocolMessage、ProcessProtocolLogs 和 ProcessSingleProtocolLog) -- 避免为了异步而异步的代码模式,只在实际需要异步的地方使用 async/await - -#### 6. 代码质量提升 -- 添加详细的 XML 文档注释 -- 改进变量命名(MsgData → messageData) -- 使用 null 检查和空值验证 -- 添加输入参数验证 - -#### 7. 可维护性改进 -- 方法职责单一,便于测试和维护 -- 代码结构清晰,易于理解和扩展 -- 为未来业务逻辑扩展预留了接口 - -### 技术细节 -- 使用 JsonSerializerOptions 配置大小写不敏感和驼峰命名 -- 添加了消息数量统计和错误计数 -- 改进了异常处理的分层结构 -- 优化了日志输出的格式和内容 - -## 2024-12-19 WebSocketMiddleware ProcessWebSocketMessages 修复 - -### 修改文件 -- `X1.WebSocket/Middleware/WebSocketMiddleware.cs` - -### 主要问题修复 - -#### 1. 消息缓冲区共享问题 -- **问题**:`_messageBuffer` 是类的成员变量,被所有连接共享,导致数据混乱 -- **修复**:为每个连接创建独立的 `WebSocketMessageBuffer` 实例 -- **影响**:避免多连接间的数据干扰,提高并发安全性 - -#### 2. 消息超时逻辑错误 -- **问题**:`messageStartTime` 在循环中被重置,超时检查逻辑有问题 -- **修复**:基于最后接收消息的时间进行超时检查 -- **影响**:确保超时机制正确工作,及时检测到超时连接 - -#### 3. 缓冲区重置时机不当 -- **问题**:只有在 `EndOfMessage` 为 true 时才重置缓冲区 -- **修复**:在消息完整处理后立即重置缓冲区 -- **影响**:避免缓冲区累积过多数据,提高内存使用效率 - -#### 4. 异常处理不完善 -- **问题**:缺少对 WebSocket 连接状态的检查,没有处理连接意外断开的情况 -- **修复**:添加连接状态检查和详细的异常处理机制 -- **影响**:提高系统稳定性,避免因连接异常导致的崩溃 - -#### 5. 资源泄漏风险 -- **问题**:缓冲区没有正确释放,异常情况下可能导致资源泄漏 -- **修复**:使用 `using` 语句确保缓冲区正确释放 -- **影响**:防止内存泄漏,提高资源管理效率 - -### 技术改进 - -#### 1. 连接状态验证 -- 在处理消息前检查 WebSocket 连接状态 -- 及时发现并处理异常连接状态 - -#### 2. 消息大小验证 -- 在处理消息前验证消息大小是否超过限制 -- 防止过大消息导致的内存问题 - -#### 3. 通道状态检查 -- 在写入消息前检查通道是否已关闭 -- 避免向已关闭的通道写入数据 - -#### 4. 增强的日志记录 -- 添加更详细的调试和错误日志 -- 便于问题排查和性能监控 - -#### 5. 资源管理优化 -- 使用 `using` 语句自动管理缓冲区生命周期 -- 确保异常情况下资源也能正确释放 - -### 性能影响 -- 提高并发处理能力,避免连接间的数据竞争 -- 减少内存泄漏风险,提高系统稳定性 -- 优化超时检测机制,及时释放无效连接 -- 改进异常处理,减少系统崩溃概率 - -## 2024-12-19 WebSocket 缓冲区管理问题修复 - -### 修改文件 -- `X1.WebSocket/Middleware/WebSocketMiddleware.cs` - -### 问题描述 -从日志中发现缓冲区溢出错误: -``` -[17:19:07 WRN] 消息缓冲区已满,连接ID:ff70aebb-c0a2-40a3-b478-8aaa00daf50f,缓冲区大小:1048576,消息大小:4096 -[17:19:07 WRN] 操作失败,重试 1/3 -System.Net.WebSockets.WebSocketException (0x80004005): 消息缓冲区溢出 -``` - -### 根本原因分析 - -#### 1. 缓冲区大小设置错误 -- **问题**:缓冲区大小设置为 `_options.MaxMessageSize`(1MB),但这是用来累积分片消息的 -- **影响**:当消息分片传输时,缓冲区会累积所有分片直到达到最大大小,导致溢出 - -#### 2. 分片消息处理逻辑缺失 -- **问题**:没有正确处理大型消息的分片传输 -- **影响**:分片消息无法正确累积和重组 - -#### 3. 缓冲区管理逻辑错误 -- **问题**:在写入数据前没有检查总大小是否会超过限制 -- **影响**:可能导致缓冲区溢出 - -### 修复方案 - -#### 1. 优化缓冲区大小设置 -- **修复**:将缓冲区大小设置为 `MaxMessageSize` 的 1.5 倍 -- **原因**:确保有足够空间处理分片消息,避免溢出 -- **代码**: -```csharp -var bufferSize = (int)(_options.MaxMessageSize * 1.5); -using var messageBuffer = new WebSocketMessageBuffer(bufferSize); -``` - -#### 2. 改进缓冲区写入逻辑 -- **修复**:在写入前检查总大小是否会超过限制 -- **原因**:提前检测溢出风险,避免不必要的写入操作 -- **代码**: -```csharp -var totalSize = messageBuffer.Size + receiveResult.Count; -if (totalSize > _options.MaxMessageSize) -{ - throw new WebSocketException("消息大小超过限制"); -} -``` - -#### 3. 增强分片消息处理 -- **修复**:添加分片消息的详细日志记录 -- **原因**:便于调试和监控分片消息的处理过程 -- **代码**: -```csharp -_logger.LogDebug("消息分片已累积,连接ID:{ConnectionId},当前缓冲区大小:{BufferSize}字节", - connectionId, messageBuffer.Size); -``` - -#### 4. 改进错误处理和日志 -- **修复**:提供更详细的错误信息和调试日志 -- **原因**:便于问题排查和性能监控 -- **改进**: - - 区分"消息大小超过限制"和"缓冲区写入失败" - - 添加缓冲区状态和分片处理过程的详细日志 - - 在关键操作点添加调试日志 - -### 技术细节 - -#### 1. 缓冲区大小计算 -- 原始大小:`_options.MaxMessageSize`(1MB) -- 新大小:`_options.MaxMessageSize * 1.5`(1.5MB) -- 原因:为分片消息提供足够的缓冲空间 - -#### 2. 大小检查策略 -- 写入前检查:`totalSize = currentSize + newDataSize` -- 最终验证:`messageData.Length > _options.MaxMessageSize` -- 双重保护:确保消息大小在合理范围内 - -#### 3. 分片处理流程 -- 累积分片:`messageBuffer.TryWrite(buffer, 0, receiveResult.Count)` -- 检查完整性:`receiveResult.EndOfMessage` -- 重组消息:`messageBuffer.GetMessage()` -- 重置缓冲区:`messageBuffer.Reset()` - -### 性能影响 -- **内存使用**:缓冲区大小增加 50%,但避免了溢出错误 -- **处理效率**:提前检测大小限制,避免无效的写入操作 -- **稳定性**:正确处理分片消息,提高系统稳定性 -- **可维护性**:详细的日志记录,便于问题排查 - -### 测试建议 -1. 测试大型消息的分片传输 -2. 验证缓冲区大小限制的正确性 -3. 检查分片消息的完整重组 -4. 监控内存使用情况 -5. 验证错误处理的正确性 - -## 2024-12-19 WebSocket 错误处理优化 - -### 修改文件 -- `X1.WebSocket/Middleware/WebSocketMiddleware.cs` - -### 问题描述 -从日志中发现重试机制在缓冲区满的情况下无效: -``` -[17:19:07 WRN] 消息缓冲区已满,连接ID:ff70aebb-c0a2-40a3-b478-8aaa00daf50f,缓冲区大小:1048576,消息大小:4096 -[17:19:07 WRN] 操作失败,重试 1/3 -[17:19:08 WRN] 操作失败,重试 2/3 -[17:19:09 WRN] 操作失败,重试 3/3 -[17:19:09 ERR] 消息处理失败,连接ID:ff70aebb-c0a2-40a3-b478-8aaa00daf50f,关闭连接 -``` - -### 根本原因分析 - -#### 1. 重试机制设计缺陷 -- **问题**:对于缓冲区满等状态性问题,重试机制没有意义 -- **影响**:浪费系统资源,延迟错误处理 - -#### 2. 异常类型区分不足 -- **问题**:没有区分不同类型的异常,所有异常都进行重试 -- **影响**:对不可恢复的错误进行无效重试 - -#### 3. 资源清理不完整 -- **问题**:存在未使用的成员变量 `_messageBuffer` -- **影响**:代码冗余,可能造成混淆 - -### 修复方案 - -#### 1. 优化异常处理策略 -- **修复**:区分 WebSocket 异常和其他异常 -- **原因**:WebSocket 异常通常不可恢复,不需要重试 -- **代码**: -```csharp -catch (WebSocketException ex) -{ - // 对于 WebSocket 异常,直接抛出,不进行重试 - _logger.LogError(ex, "WebSocket 消息处理异常,连接ID:{ConnectionId},错误:{Error}", - connectionId, ex.Message); - throw; -} -catch (Exception ex) -{ - // 对于其他异常,使用重试机制 - // ... -} -``` - -#### 2. 移除未使用的成员变量 -- **修复**:移除 `_messageBuffer` 成员变量和初始化代码 -- **原因**:清理代码冗余,避免混淆 -- **改进**: - - 移除成员变量声明:`private readonly WebSocketMessageBuffer _messageBuffer;` - - 移除初始化代码:`_messageBuffer = new WebSocketMessageBuffer(_options.MaxMessageSize);` - -#### 3. 改进错误日志记录 -- **修复**:提供更详细的错误分类和日志信息 -- **原因**:便于问题排查和性能监控 -- **改进**: - - 区分 WebSocket 异常和其他异常 - - 提供更具体的错误描述 - - 减少无效的重试日志 - -### 技术细节 - -#### 1. 异常分类策略 -- **WebSocket 异常**:直接抛出,不重试 - - 缓冲区溢出 - - 消息大小超限 - - 连接状态异常 -- **其他异常**:使用重试机制 - - 网络临时错误 - - 系统资源临时不足 - -#### 2. 重试逻辑优化 -- **适用场景**:临时性、可恢复的错误 -- **不适用场景**:状态性、不可恢复的错误 -- **重试策略**:指数退避,避免系统过载 - -#### 3. 资源管理改进 -- **成员变量清理**:移除未使用的 `_messageBuffer` -- **内存优化**:减少不必要的对象创建 -- **代码简化**:提高代码可读性和维护性 - -### 性能影响 -- **响应速度**:减少无效重试,提高错误响应速度 -- **资源使用**:减少系统资源浪费 -- **稳定性**:更准确的错误处理,提高系统稳定性 -- **可维护性**:代码更清晰,便于维护和调试 - -### 测试建议 -1. 测试缓冲区满时的错误处理 -2. 验证不同类型异常的处理策略 -3. 检查重试机制的正确性 -4. 监控系统资源使用情况 -5. 验证错误日志的准确性 - -## 2024-12-19 HandleWebSocketConnection 缓冲区大小修复 - -### 修改文件 -- `X1.WebSocket/Middleware/WebSocketMiddleware.cs` - -### 问题描述 -- 原实现中 buffer 大小为 4KB(`1024 * 4`),与 WebSocketOptions.MaxMessageSize(如 1MB)不匹配。 -- 当接收大消息时,分片次数多,增加缓冲区溢出和性能问题风险。 - -### 修复方案 -- 将 buffer 大小调整为 `_options.MaxMessageSize`,与最大消息大小保持一致。 -- 这样可减少分片次数,提高性能,降低溢出风险。 - -### 代码片段 -```csharp -// 修复前 -var buffer = ArrayPool.Shared.Rent(1024 * 4); -// 修复后 -var buffer = ArrayPool.Shared.Rent(_options.MaxMessageSize); -``` - -### 影响 -- 提高了大消息处理的效率和健壮性。 -- 降低了分片累积导致的缓冲区溢出风险。 -- 代码更符合最佳实践。 - -## 2024-12-19 ProcessMessage 检查逻辑优化 - -### 修改文件 -- `X1.WebSocket/Middleware/WebSocketMiddleware.cs` - -### 问题描述 -- `ProcessMessage` 方法中存在冗余的大小检查逻辑 -- 在已经提前检查 `totalSize` 的情况下,后续的检查理论上不应该失败 -- 日志级别使用不当,某些错误情况应该使用 Error 级别 - -### 优化方案 - -#### 1. 优化检查逻辑 -- 保留提前的 `totalSize` 检查作为主要验证 -- 将后续检查作为安全验证,并调整日志级别为 Error -- 添加注释说明检查的层次和目的 - -#### 2. 改进日志记录 -- 将不应该发生的错误情况日志级别调整为 Error -- 添加更明确的错误描述,便于问题排查 - -### 代码改进 -```csharp -// 主要检查:提前验证大小 -var totalSize = messageBuffer.Size + receiveResult.Count; -if (totalSize > _options.MaxMessageSize) -{ - // 正常的大小超限情况,使用 Warning 级别 - _logger.LogWarning("消息大小将超过限制..."); -} - -// 安全验证:理论上不应该失败 -if (!messageBuffer.TryWrite(buffer, 0, receiveResult.Count)) -{ - // 不应该发生的情况,使用 Error 级别 - _logger.LogError("消息缓冲区写入失败,这不应该发生"); -} - -// 最终验证:双重保护 -if (messageData.Length > _options.MaxMessageSize) -{ - // 不应该发生的情况,使用 Error 级别 - _logger.LogError("最终消息大小超过限制,这不应该发生"); -} -``` - -### 影响 -- 提高了代码的可读性和维护性 -- 更准确的日志级别分类 -- 保持了安全检查的完整性 -- 便于问题排查和调试 - -## 2024-12-19 移除无意义的重试逻辑 - -### 修改文件 -- `X1.WebSocket/Middleware/WebSocketMiddleware.cs` - -### 问题描述 -- `ProcessMessage` 方法中的重试逻辑没有实际意义 -- 对于 WebSocketException,已经单独 catch 并直接抛出 -- 对于其他异常,重试逻辑只是简单地 `throw ex`,没有实际重试操作 -- `HandleMessageProcessingFailure` 只会在所有重试都失败后调用,但由于每次都直接抛出异常,实际上不会有任何重试 - -### 优化方案 -- 移除无意义的重试逻辑 -- 简化异常处理流程 -- 直接调用 `HandleMessageProcessingFailure` - -### 代码改进 -```csharp -// 优化前 -catch (Exception ex) -{ - _logger.LogError(ex, "消息处理发生未知异常,连接ID:{ConnectionId},错误:{Error}", - connectionId, ex.Message); - - var success = await _errorHandler.HandleWithRetryAsync(async () => - { - // 这里可以添加重试逻辑,但对于缓冲区问题,重试通常无效 - throw ex; // 重新抛出异常 - }); - - if (!success) - { - await HandleMessageProcessingFailure(webSocket, connectionId, cancellationToken); - } -} - -// 优化后 -catch (Exception ex) -{ - _logger.LogError(ex, "WebSocket 消息处理发生未知异常,连接ID:{ConnectionId},错误:{Error}", - connectionId, ex.Message); - await HandleMessageProcessingFailure(webSocket, connectionId, cancellationToken); -} -``` - -### 影响 -- 简化了代码逻辑,提高了可读性 -- 减少了不必要的重试开销 -- 保持了错误处理的完整性 -- 提高了代码执行效率 - -## 2024-12-19 WebSocket 缓冲区大小修复 - -### 修改文件 -- `X1.WebSocket/Models/WebSocketOptions.cs` -- `X1.WebSocket/Buffer/WebSocketMessageBuffer.cs` -- `X1.WebSocket/Middleware/WebSocketMiddleware.cs` -- `X1.WebAPI/Program.cs` - -### 问题描述 -原始实现中存在严重的设计问题: -```csharp -// 问题代码 -using var messageBuffer = new WebSocketMessageBuffer(_options.MaxMessageSize); -``` - -**问题所在:** -1. **`_options.MaxMessageSize` 是服务器端的业务限制**(默认 1MB) -2. **客户端发送的数据大小无法预知**,可能超过服务器限制 -3. **缓冲区大小被硬编码为业务限制**,无法处理更大的消息 -4. **混淆了"缓冲区容量"和"业务限制"的概念** - -### 根本原因分析 - -#### 1. 概念混淆 -- **业务限制**:`MaxMessageSize` 是业务层面的限制,用于防止过大的消息影响系统性能 -- **缓冲区容量**:应该为客户端数据提供足够的空间,通常大于业务限制 - -#### 2. 实际场景问题 -```csharp -// 配置中的限制 -options.MaxMessageSize = 1024 * 1024; // 1MB - -// 但客户端可能发送: -// - 2MB 的文件 -// - 5MB 的图片 -// - 10MB 的视频片段 -// - 等等... -``` - -### 修复方案 - -#### 1. 改进 WebSocketOptions 配置 -```csharp -public class WebSocketOptions -{ - /// - /// 最大消息大小(业务限制) - /// 超过此大小的消息会被记录警告,但不会导致连接关闭 - /// - public int MaxMessageSize { get; set; } = 1024 * 1024; // 1MB - - /// - /// 消息缓冲区大小倍数 - /// 用于计算实际缓冲区大小:MaxMessageSize * MessageBufferMultiplier - /// - public int MessageBufferMultiplier { get; set; } = 5; // 5倍 - - /// - /// 计算实际缓冲区大小 - /// - public int GetActualBufferSize() => MaxMessageSize * MessageBufferMultiplier; -} -``` - -#### 2. 增强 WebSocketMessageBuffer -```csharp -public sealed class WebSocketMessageBuffer : IDisposable -{ - // 添加公共属性访问最大缓冲区大小 - public int MaxSize => _maxSize; -} -``` - -#### 3. 修改 ProcessWebSocketMessages 方法 -```csharp -private async Task ProcessWebSocketMessages(...) -{ - // 使用动态缓冲区大小,为客户端数据提供足够空间 - var bufferSize = _options.GetActualBufferSize(); // 5MB - using var messageBuffer = new WebSocketMessageBuffer(bufferSize); - - _logger.LogDebug("创建消息缓冲区,缓冲区大小:{BufferSize}字节,业务限制:{MaxMessageSize}字节", - bufferSize, _options.MaxMessageSize); -} -``` - -#### 4. 改进 AccumulateMessageFragment 验证逻辑 -```csharp -// 检查累积后的大小是否会超过缓冲区容量 -// 这是技术层面的检查,防止缓冲区溢出 -var totalSize = messageBuffer.Size + receiveResult.Count; -if (totalSize > messageBuffer.MaxSize) -{ - throw new WebSocketException($"消息大小将超过缓冲区容量:{totalSize} > {messageBuffer.MaxSize}字节"); -} - -// 最终验证消息大小是否符合业务限制 -// 这是业务层面的检查,超过限制会记录警告但继续处理 -if (messageData.Length > _options.MaxMessageSize) -{ - _logger.LogWarning("消息大小超过业务限制,但已完整接收"); - // 记录警告但继续处理,确保数据完整性 -} -``` - -#### 5. 更新配置示例 -```csharp -builder.Services.AddWebSocketServices(options => -{ - options.MaxConcurrentConnections = 2000; - options.MaxMessageSize = 1024 * 1024; // 业务限制:1MB - options.MessageBufferMultiplier = 5; // 缓冲区:5MB - options.ConnectionTimeout = TimeSpan.FromMinutes(2); - options.HeartbeatInterval = TimeSpan.FromSeconds(30); -}); -``` - -### 技术细节 - -#### 1. 分层验证策略 -- **缓冲区容量检查**:防止技术层面的溢出 -- **业务限制检查**:防止业务层面的过大消息 -- **分离关注点**:技术问题 vs 业务问题 - -#### 2. 动态缓冲区大小 -- **计算公式**:`MaxMessageSize * MessageBufferMultiplier` -- **默认配置**:1MB * 5 = 5MB 缓冲区 -- **可配置性**:根据实际需求调整倍数 - -#### 3. 错误处理策略 -- **缓冲区溢出**:抛出异常,关闭连接 -- **业务限制超限**:记录警告,继续处理 -- **数据完整性**:优先保证数据完整性 - -### 性能影响 -- **内存使用**:缓冲区大小增加,但避免了数据丢失 -- **处理能力**:能够处理更大的客户端数据 -- **稳定性**:提高了系统的健壮性 -- **可维护性**:清晰的概念分离,便于理解和维护 - -### 测试建议 -1. 测试不同大小的消息传输 -2. 验证缓冲区容量检查的正确性 -3. 验证业务限制检查的正确性 -4. 测试分片消息的完整重组 -5. 监控内存使用情况 - -### 总结 -这次修复解决了 WebSocket 中间件中缓冲区大小设计的根本问题: -- **分离了技术限制和业务限制** -- **提供了足够的缓冲区空间处理客户端数据** -- **保持了数据完整性** -- **提高了系统的健壮性和可维护性** - -## 2024-12-19 WebSocketMessageHandlerAdapter 验证逻辑修复 - -### 修改文件 -- `X1.WebSocket/Handlers/WebSocketMessageHandlerAdapter.cs` - -### 问题描述 -在 `ValidateMessage` 方法中存在验证逻辑不一致的问题: -```csharp -// 问题代码 -if (message.Data.Length > _options.MaxMessageSize) -{ - _logger.LogWarning("消息大小超过限制..."); - return false; // 拒绝处理消息 -} -``` - -**问题所在:** -1. **与缓冲区大小修复不一致**:我们刚刚修复了缓冲区大小问题,允许处理超过业务限制的消息 -2. **数据完整性冲突**:拒绝处理大消息会导致数据丢失 -3. **业务逻辑混乱**:业务限制应该是警告而非拒绝处理的理由 - -### 根本原因分析 - -#### 1. 设计理念不一致 -- **缓冲区修复**:允许接收大消息,记录警告但继续处理 -- **验证逻辑**:拒绝处理大消息,导致数据丢失 -- **结果**:修复了接收问题,但处理时仍然拒绝 - -#### 2. 业务限制的定位错误 -- **业务限制**:应该是性能监控和资源管理的参考 -- **当前实现**:被当作拒绝处理的硬性条件 -- **影响**:无法处理客户端发送的大数据 - -### 修复方案 - -#### 1. 修改验证逻辑 -```csharp -// 检查消息大小是否超过缓冲区容量 -// 这是技术层面的检查,防止缓冲区溢出 -var actualBufferSize = _options.GetActualBufferSize(); -if (message.Data.Length > actualBufferSize) -{ - _logger.LogError("消息大小超过缓冲区容量,处理器:{HandlerName},连接ID:{ConnectionId},大小:{Size}字节,缓冲区容量:{BufferSize}字节", - Name, message.ConnectionId, message.Data.Length, actualBufferSize); - return false; // 超过缓冲区容量时拒绝处理 -} - -// 注意:不检查 MaxMessageSize,因为: -// 1. message.Data 已经是完整接收的消息数据 -// 2. 在接收阶段已经通过缓冲区容量检查 -// 3. 业务限制检查在接收阶段已经完成并记录警告 -``` - -#### 2. 保持数据完整性 -- **移除拒绝逻辑**:不再因为大小超限而拒绝处理 -- **保留警告记录**:继续记录业务层面的警告信息 -- **确保处理**:保证所有消息都能被正确处理 - -### 技术细节 - -#### 1. 验证策略调整 -- **必需验证**:消息为空、连接ID为空、数据为空 -- **技术验证**:消息大小超过缓冲区容量(拒绝处理) -- **处理策略**:技术验证失败时拒绝,其他情况继续处理 - -#### 2. 日志级别优化 -- **Error 级别**:用于缓冲区容量超限等严重错误 -- **Warning 级别**:用于其他验证失败的警告 -- **Debug 级别**:用于正常处理的调试信息 - -#### 3. 业务逻辑一致性 -- **接收层**:负责缓冲区容量检查和业务限制检查 -- **处理层**:只负责缓冲区容量检查,业务限制已在接收层处理 -- **整体策略**:职责分离,避免重复验证 - -### 性能影响 -- **处理效率**:避免重复验证,提高处理性能 -- **职责清晰**:接收层和处理层职责分离 -- **稳定性**:保持必要的技术验证,确保系统稳定 -- **一致性**:与缓冲区大小修复保持一致 - -### 测试建议 -1. 测试不同大小消息的处理 -2. 验证缓冲区容量检查的正确性 -3. 确认消息处理的完整性 -4. 检查日志记录的准确性 - -### 总结 -这次修复确保了 WebSocket 消息处理的职责分离: -- **接收层负责完整验证**:缓冲区容量 + 业务限制 -- **处理层负责必要验证**:只检查缓冲区容量 -- **避免重复验证**:提高性能和代码清晰度 -- **保持数据完整性**:确保系统稳定性和一致性 - -## 2024-12-19 移除配置管理相关功能 - -### 修改概述 -根据用户要求,移除了与配置管理相关的所有功能,包括服务、页面组件和路由配置。 - -### 删除的文件 -- `X1.WebUI/src/services/configService.ts` - 配置管理服务 -- `X1.WebUI/src/pages/configs/ConfigsView.tsx` - 配置管理页面组件 -- `X1.WebUI/src/pages/configs/ConfigsTable.tsx` - 配置表格组件 - -### 修改的文件 - -#### 1. `X1.WebUI/src/routes/AppRouter.tsx` -- 移除了 `ConfigsView` 的 lazy 导入 -- 删除了 `/dashboard/instruments/configs` 路由配置 - -#### 2. `X1.WebUI/src/services/instrumentService.ts` -- 移除了对 `configService` 的导出语句 -- 保持其他服务的导出不变 - -#### 3. `X1.WebUI/src/constants/api.ts` -- 移除了 `CONFIGS: '/instruments/configs'` API 路径配置 - -#### 4. `X1.WebUI/src/constants/menuConfig.ts` -- 移除了 `configs.view` 和 `configs.manage` 权限类型定义 -- 删除了菜单配置中的"配置列表"菜单项 - -#### 5. `X1.WebUI/src/contexts/AuthContext.tsx` -- 移除了默认权限中的 `configs.view` 和 `configs.manage` 权限 - -### 影响范围 -- **功能影响**:用户无法再访问配置管理功能 -- **路由影响**:`/dashboard/instruments/configs` 路径不再可用 -- **权限影响**:配置相关的权限检查被移除 -- **菜单影响**:仪表管理菜单中不再显示配置列表选项 - -### 技术细节 -- 所有相关的 TypeScript 类型定义已被移除 -- 路由配置已更新,移除了配置相关的路由 -- 权限系统已更新,移除了配置相关的权限检查 -- 菜单系统已更新,移除了配置相关的菜单项 - -### 注意事项 -- 如果后端 API 仍然存在配置相关的端点,前端将无法访问 -- 建议同时清理后端相关的配置管理功能 -- 确保没有其他地方引用已删除的组件或服务 - -## 2024-12-19 创建 RAN 配置前端服务 - -### 修改概述 -参考 `protocolService` 的实现模式,为 `RANConfigurationController` 创建对应的前端服务。 - -### 新增文件 -- `X1.WebUI/src/services/ranConfigurationService.ts` - RAN 配置管理服务 - -### 修改的文件 - -#### 1. `X1.WebUI/src/constants/api.ts` -- 添加了 `RAN_CONFIGURATIONS: '/ranconfigurations'` API 路径配置 - -#### 2. `X1.WebUI/src/services/ranConfigurationService.ts`(新增) -- 实现了完整的 RAN 配置管理服务 -- 包含所有 CRUD 操作的接口定义和方法实现 -- 参考 `protocolService` 的设计模式和代码结构 - -### 功能特性 - -#### 1. 接口定义 -- `RANConfiguration` - RAN 配置实体接口 -- `GetRANConfigurationsRequest` - 获取列表请求接口 -- `GetRANConfigurationsResponse` - 获取列表响应接口 -- `CreateRANConfigurationRequest` - 创建请求接口 -- `CreateRANConfigurationResponse` - 创建响应接口 -- `UpdateRANConfigurationRequest` - 更新请求接口 -- `UpdateRANConfigurationResponse` - 更新响应接口 - -#### 2. 服务方法 -- `getRANConfigurations()` - 获取 RAN 配置列表(支持分页和搜索) -- `getRANConfigurationById()` - 根据 ID 获取配置详情 -- `createRANConfiguration()` - 创建新的 RAN 配置 -- `updateRANConfiguration()` - 更新现有 RAN 配置 -- `deleteRANConfiguration()` - 删除 RAN 配置 - -#### 3. 查询参数支持 -- 分页参数:`pageNumber`、`pageSize` -- 搜索参数:`searchTerm` -- 过滤参数:`isDisabled` - -### 技术实现 - -#### 1. 设计模式 -- 采用与 `protocolService` 相同的设计模式 -- 使用 TypeScript 接口定义数据结构 -- 统一的错误处理和响应格式 - -#### 2. HTTP 客户端集成 -- 使用 `httpClient` 进行 API 调用 -- 支持 GET、POST、PUT、DELETE 方法 -- 自动处理查询参数构建 - -#### 3. 类型安全 -- 完整的 TypeScript 类型定义 -- 与后端 API 响应格式完全匹配 -- 提供良好的开发体验和代码提示 - -### 使用示例 -``` -// 获取 RAN 配置列表 -const result = await ranConfigurationService.getRANConfigurations({ - pageNumber: 1, - pageSize: 10, - searchTerm: 'LTE' -}); - -// 创建新的 RAN 配置 -const createResult = await ranConfigurationService.createRANConfiguration({ - name: 'LTE Configuration', - configContent: JSON.stringify(configData), - description: 'LTE 网络配置' -}); -``` - -### 影响范围 -- **前端服务**:提供了完整的 RAN 配置管理前端服务 -- **API 集成**:与后端 `RANConfigurationController` 完全对应 -- **类型安全**:提供了完整的 TypeScript 类型定义 -- **开发体验**:统一的服务接口,便于前端开发使用 - -## 2024-12-19 创建 IMS 配置前端服务 - -### 修改概述 -参考 `protocolService` 和 `ranConfigurationService` 的实现模式,为 `IMSConfigurationController` 创建对应的前端服务。 - -### 新增文件 -- `X1.WebUI/src/services/imsConfigurationService.ts` - IMS 配置管理服务 - -### 修改的文件 - -#### 1. `X1.WebUI/src/constants/api.ts` -- 添加了 `IMS_CONFIGURATIONS: '/imsconfigurations'` API 路径配置 - -#### 2. `X1.WebUI/src/services/imsConfigurationService.ts`(新增) -- 实现了完整的 IMS 配置管理服务 -- 包含所有 CRUD 操作的接口定义和方法实现 -- 参考 `protocolService` 和 `ranConfigurationService` 的设计模式和代码结构 - -### 功能特性 - -#### 1. 接口定义 -- `IMSConfiguration` - IMS 配置实体接口 -- `GetIMSConfigurationsRequest` - 获取列表请求接口 -- `GetIMSConfigurationsResponse` - 获取列表响应接口 -- `CreateIMSConfigurationRequest` - 创建请求接口 -- `CreateIMSConfigurationResponse` - 创建响应接口 -- `UpdateIMSConfigurationRequest` - 更新请求接口 -- `UpdateIMSConfigurationResponse` - 更新响应接口 - -#### 2. 服务方法 -- `getIMSConfigurations()` - 获取 IMS 配置列表(支持分页和搜索) -- `getIMSConfigurationById()` - 根据 ID 获取配置详情 -- `createIMSConfiguration()` - 创建新的 IMS 配置 -- `updateIMSConfiguration()` - 更新现有 IMS 配置 -- `deleteIMSConfiguration()` - 删除 IMS 配置 - -#### 3. 查询参数支持 -- 分页参数:`pageNumber`、`pageSize` -- 搜索参数:`searchTerm` -- 过滤参数:`isDisabled` - -### 技术实现 - -#### 1. 设计模式 -- 采用与 `protocolService` 和 `ranConfigurationService` 相同的设计模式 -- 使用 TypeScript 接口定义数据结构 -- 统一的错误处理和响应格式 - -#### 2. HTTP 客户端集成 -- 使用 `httpClient` 进行 API 调用 -- 支持 GET、POST、PUT、DELETE 方法 -- 自动处理查询参数构建 - -#### 3. 类型安全 -- 完整的 TypeScript 类型定义 -- 与后端 API 响应格式完全匹配 -- 提供良好的开发体验和代码提示 - -### 使用示例 -``` -// 获取 IMS 配置列表 -const result = await imsConfigurationService.getIMSConfigurations({ - pageNumber: 1, - pageSize: 10, - searchTerm: 'VoIP' -}); - -// 创建新的 IMS 配置 -const createResult = await imsConfigurationService.createIMSConfiguration({ - name: 'VoIP Configuration', - configContent: JSON.stringify(configData), - description: 'VoIP 服务配置' -}); -``` - -### 影响范围 -- **前端服务**:提供了完整的 IMS 配置管理前端服务 -- **API 集成**:与后端 `IMSConfigurationController` 完全对应 -- **类型安全**:提供了完整的 TypeScript 类型定义 -- **开发体验**:统一的服务接口,便于前端开发使用 - -## 2024-12-19 创建核心网络配置前端服务 - -### 修改概述 -参考其他配置服务的实现模式,为 `CoreNetworkConfigsController` 创建对应的前端服务。 - -### 新增文件 -- `X1.WebUI/src/services/coreNetworkConfigService.ts` - 核心网络配置管理服务 - -### 修改的文件 - -#### 1. `X1.WebUI/src/constants/api.ts` -- 添加了 `CORE_NETWORK_CONFIGS: '/corenetworkconfigs'` API 路径配置 - -#### 2. `X1.WebUI/src/services/coreNetworkConfigService.ts`(新增) -- 实现了完整的核心网络配置管理服务 -- 包含所有 CRUD 操作的接口定义和方法实现 -- 参考其他配置服务的设计模式和代码结构 - -### 功能特性 - -#### 1. 接口定义 -- `CoreNetworkConfig` - 核心网络配置实体接口 -- `GetCoreNetworkConfigsRequest` - 获取列表请求接口 -- `GetCoreNetworkConfigsResponse` - 获取列表响应接口 -- `CreateCoreNetworkConfigRequest` - 创建请求接口 -- `CreateCoreNetworkConfigResponse` - 创建响应接口 -- `UpdateCoreNetworkConfigRequest` - 更新请求接口 -- `UpdateCoreNetworkConfigResponse` - 更新响应接口 - -#### 2. 服务方法 -- `getCoreNetworkConfigs()` - 获取核心网络配置列表(支持分页和搜索) -- `getCoreNetworkConfigById()` - 根据 ID 获取配置详情 -- `createCoreNetworkConfig()` - 创建新的核心网络配置 -- `updateCoreNetworkConfig()` - 更新现有核心网络配置 -- `deleteCoreNetworkConfig()` - 删除核心网络配置 - -#### 3. 查询参数支持 -- 分页参数:`pageNumber`、`pageSize` -- 搜索参数:`searchTerm` -- 过滤参数:`isDisabled` - -### 技术实现 - -#### 1. 设计模式 -- 采用与其他配置服务相同的设计模式 -- 使用 TypeScript 接口定义数据结构 -- 统一的错误处理和响应格式 - -#### 2. HTTP 客户端集成 -- 使用 `httpClient` 进行 API 调用 -- 支持 GET、POST、PUT、DELETE 方法 -- 自动处理查询参数构建 - -#### 3. 类型安全 -- 完整的 TypeScript 类型定义 -- 与后端 API 响应格式完全匹配 -- 提供良好的开发体验和代码提示 - -### 使用示例 -``` -// 获取核心网络配置列表 -const result = await coreNetworkConfigService.getCoreNetworkConfigs({ - pageNumber: 1, - pageSize: 10, - searchTerm: 'EPC' -}); - -// 创建新的核心网络配置 -const createResult = await coreNetworkConfigService.createCoreNetworkConfig({ - name: 'EPC Configuration', - configContent: JSON.stringify(configData), - description: '演进分组核心网配置' -}); -``` - -### 影响范围 -- **前端服务**:提供了完整的核心网络配置管理前端服务 -- **API 集成**:与后端 `CoreNetworkConfigsController` 完全对应 -- **类型安全**:提供了完整的 TypeScript 类型定义 -- **开发体验**:统一的服务接口,便于前端开发使用 - -## 2024-12-19 创建栈核心网IMS绑定前端服务 - -### 修改概述 -参考其他配置服务的实现模式,为 `StackCoreIMSBindingsController` 创建对应的前端服务。 - -### 新增文件 -- `X1.WebUI/src/services/stackCoreIMSBindingService.ts` - 栈核心网IMS绑定管理服务 - -### 修改的文件 - -#### 1. `X1.WebUI/src/constants/api.ts` -- 添加了 `STACK_CORE_IMS_BINDINGS: '/stackcoreimsbindings'` API 路径配置 - -#### 2. `X1.WebUI/src/services/stackCoreIMSBindingService.ts`(新增) -- 实现了完整的栈核心网IMS绑定管理服务 -- 包含所有 CRUD 操作的接口定义和方法实现 -- 参考其他配置服务的设计模式和代码结构 - -### 功能特性 - -#### 1. 接口定义 -- `StackCoreIMSBinding` - 栈核心网IMS绑定实体接口 -- `GetStackCoreIMSBindingsRequest` - 获取列表请求接口 -- `GetStackCoreIMSBindingsResponse` - 获取列表响应接口 -- `CreateStackCoreIMSBindingRequest` - 创建请求接口 -- `CreateStackCoreIMSBindingResponse` - 创建响应接口 -- `UpdateStackCoreIMSBindingRequest` - 更新请求接口 -- `UpdateStackCoreIMSBindingResponse` - 更新响应接口 - -#### 2. 服务方法 -- `getStackCoreIMSBindings()` - 获取列表(支持分页、按栈ID/核心网ID/IMS ID过滤) -- `getStackCoreIMSBindingById()` - 获取详情 -- `createStackCoreIMSBinding()` - 创建绑定关系 -- `updateStackCoreIMSBinding()` - 更新绑定关系 -- `deleteStackCoreIMSBinding()` - 删除绑定关系 - -#### 3. 特殊功能 -- **复合键支持**:支持栈ID和索引的复合唯一键 -- **多维度过滤**:支持按栈ID、核心网配置ID、IMS配置ID进行过滤 -- **关系管理**:管理网络栈与核心网/IMS配置之间的绑定关系 - -### 技术特点 -- **类型安全**:完整的 TypeScript 类型定义 -- **错误处理**:统一的错误处理机制 -- **查询参数**:支持灵活的查询参数组合 -- **RESTful API**:遵循 RESTful API 设计规范 - -### 影响范围 -- **前端服务**:提供了完整的栈核心网IMS绑定管理前端服务 -- **API 集成**:与后端 `StackCoreIMSBindingsController` 完全对应 -- **类型安全**:提供了完整的 TypeScript 类型定义 -- **开发体验**:统一的服务接口,便于前端开发使用 - -## 2024-12-19 创建网络栈配置前端服务 - -### 修改概述 -参考其他配置服务的实现模式,为 `NetworkStackConfigsController` 创建对应的前端服务。 - -### 新增文件 -- `X1.WebUI/src/services/networkStackConfigService.ts` - 网络栈配置管理服务 - -### 修改的文件 - -#### 1. `X1.WebUI/src/constants/api.ts` -- 添加了 `NETWORK_STACK_CONFIGS: '/networkstackconfigs'` API 路径配置 - -#### 2. `X1.WebUI/src/services/networkStackConfigService.ts`(新增) -- 实现了完整的网络栈配置管理服务 -- 包含所有 CRUD 操作的接口定义和方法实现 -- 参考其他配置服务的设计模式和代码结构 - -### 功能特性 - -#### 1. 接口定义 -- `NetworkStackConfig` - 网络栈配置实体接口 -- `GetNetworkStackConfigsRequest` - 获取列表请求接口 -- `GetNetworkStackConfigsResponse` - 获取列表响应接口 -- `CreateNetworkStackConfigRequest` - 创建请求接口 -- `CreateNetworkStackConfigResponse` - 创建响应接口 -- `UpdateNetworkStackConfigRequest` - 更新请求接口 -- `UpdateNetworkStackConfigResponse` - 更新响应接口 - -#### 2. 服务方法 -- `getNetworkStackConfigs()` - 获取列表(支持分页、搜索、按激活状态和RAN ID过滤) -- `getNetworkStackConfigById()` - 获取详情 -- `createNetworkStackConfig()` - 创建配置 -- `updateNetworkStackConfig()` - 更新配置 -- `deleteNetworkStackConfig()` - 删除配置 - -#### 3. 特殊功能 -- **栈ID唯一性**:栈ID作为唯一标识符 -- **RAN关联**:支持与RAN配置的关联关系 -- **激活状态管理**:支持配置的激活/停用状态管理 -- **多维度过滤**:支持按激活状态、RAN ID、搜索关键词进行过滤 - -### 技术特点 -- **类型安全**:完整的 TypeScript 类型定义 -- **错误处理**:统一的错误处理机制 -- **查询参数**:支持灵活的查询参数组合 -- **RESTful API**:遵循 RESTful API 设计规范 - -### 影响范围 -- **前端服务**:提供了完整的网络栈配置管理前端服务 -- **API 集成**:与后端 `NetworkStackConfigsController` 完全对应 -- **类型安全**:提供了完整的 TypeScript 类型定义 -- **开发体验**:统一的服务接口,便于前端开发使用 - -## 2024-12-19 数据库重新迁移 - -### 修改概述 -根据用户要求,重新迁移数据库,删除所有现有迁移文件并创建新的初始迁移。 - -### 执行步骤 - -#### 1. 检查现有迁移 -- 使用 `dotnet ef migrations list` 命令检查现有迁移 -- 发现存在3个迁移文件: - - `20250705165102_InitialCreate` - - `20250705173130_InitProtocolVersionAndDevice` - - `20250705174217_UpdateProtocolVersionAndCellularDevice` - -#### 2. 回滚数据库 -- 使用 `dotnet ef database update 0` 命令将数据库回滚到初始状态 -- 成功删除了所有表结构和迁移历史记录 - -#### 3. 删除迁移文件 -- 删除了所有现有的迁移文件: - - `20250705174217_UpdateProtocolVersionAndCellularDevice.cs` - - `20250705174217_UpdateProtocolVersionAndCellularDevice.Designer.cs` - - `20250705173130_InitProtocolVersionAndDevice.cs` - - `20250705173130_InitProtocolVersionAndDevice.Designer.cs` - - `20250705165102_InitialCreate.cs` - - `20250705165102_InitialCreate.Designer.cs` - - `AppDbContextModelSnapshot.cs` - -#### 4. 创建新迁移 -- 使用 `dotnet ef migrations add InitialCreate` 命令创建新的初始迁移 -- 生成了新的迁移文件: - - `20250728081332_InitialCreate.cs` - - `20250728081332_InitialCreate.Designer.cs` - - `AppDbContextModelSnapshot.cs` - -#### 5. 应用新迁移 -- 使用 `dotnet ef database update` 命令将新迁移应用到数据库 -- 成功创建了所有表结构和初始数据 - -### 技术细节 - -#### 1. 迁移文件管理 -- 完全清理了旧的迁移历史 -- 创建了全新的初始迁移 -- 确保数据库结构与当前代码模型完全一致 - -#### 2. 数据库状态 -- 数据库已回滚到初始状态 -- 所有表结构已重新创建 -- 迁移历史记录已重置 - -#### 3. 实体模型 -- 包含所有当前定义的实体: - - 用户和角色管理(AppUser、AppRole、UserRole、Permission、RolePermission) - - 设备管理(CellularDevice、ProtocolVersion) - - 网络配置(RAN_Configuration、CoreNetworkConfig、IMS_Configuration、NetworkStackConfig、Stack_CoreIMS_Binding) - - 日志记录(LoginLog) - -### 影响范围 -- **数据库结构**:所有表结构已重新创建 -- **数据丢失**:所有现有数据已清除 -- **迁移历史**:迁移历史记录已重置 -- **开发环境**:开发环境数据库已重置为初始状态 - -### 注意事项 -- 这是一个破坏性操作,所有现有数据已丢失 -- 需要重新初始化测试数据 -- 生产环境请谨慎执行此操作 -- 建议在执行前备份重要数据 - -### 后续操作建议 -1. 重新初始化测试数据 -2. 验证所有实体关系是否正确 -3. 测试所有CRUD操作功能 -4. 确认数据库约束和索引设置正确 - -## 2024-12-19 修复IMS配置字段名称 - -### 修复内容 -- 将 `ims_ConfigurationId` 改为 `imS_ConfigurationId` 以匹配后端API返回的数据格式 -- 修改 `X1.WebUI/src/services/imsConfigurationService.ts` 中的所有接口定义 -- 修改 `X1.WebUI/src/pages/ims-configurations/IMSConfigurationsTable.tsx` - ---- - -## 2025-01-29 为GetRuntimeDeviceCodesNotInActiveRuntimesAsync方法添加ORDER BY子句 - -### 修改概述 -根据用户需求,为 `GetRuntimeDeviceCodesNotInActiveRuntimesAsync` 方法添加 `ORDER BY tpl."Timestamp" DESC` 子句,确保查询结果按时间戳降序排列。 - -### 修改文件 -- `X1.Infrastructure/Repositories/Logging/ProtocolLogRepository.cs` - 修改SQL查询语句 - -### 修改内容 - -#### 1. SQL查询优化 -- **原查询**: -```sql -SELECT tpl."RuntimeCode", tpl."DeviceCode" -FROM "tb_protocol_logs" tpl -WHERE tpl."RuntimeCode" NOT IN ( - SELECT "RuntimeCode" - FROM "tb_cellular_device_runtimes" - WHERE "RuntimeStatus" = 1 -) -GROUP BY tpl."DeviceCode", tpl."RuntimeCode" -``` - -- **新查询**: -```sql -SELECT tpl."RuntimeCode", tpl."DeviceCode" -FROM "tb_protocol_logs" tpl -WHERE tpl."RuntimeCode" NOT IN ( - SELECT "RuntimeCode" - FROM "tb_cellular_device_runtimes" - WHERE "RuntimeStatus" = 1 -) -GROUP BY tpl."DeviceCode", tpl."RuntimeCode" -ORDER BY tpl."Timestamp" DESC -``` - -#### 2. 排序逻辑 -- **排序字段**:使用 `tpl."Timestamp"` 字段进行排序 -- **排序方向**:降序排列(DESC),最新的记录排在前面 -- **排序位置**:在 GROUP BY 子句之后添加 ORDER BY 子句 - -### 技术特性 -- **性能优化**:利用数据库索引进行排序,提高查询效率 -- **数据一致性**:确保查询结果按时间戳降序排列,便于用户查看最新数据 -- **向后兼容**:方法签名和返回类型保持不变,不影响现有调用 - -### 业务价值 -- **用户体验**:查询结果按时间顺序排列,便于用户快速找到最新记录 -- **数据展示**:在应用层和前端显示时,最新数据自动排在前面 -- **分析便利**:便于进行时间序列分析和趋势观察 - -### 影响范围 -- **查询结果**:现在返回的结果按时间戳降序排列 -- **性能影响**:轻微的排序开销,但提高了数据的有序性 -- **API行为**:API返回的数据更加有序和有意义 - ---- - -## 2025-01-29 修复消息详情抽屉滚动条问题 - -### 修改概述 -根据用户反馈,修复了消息详情抽屉中滚动条位置不正确的问题。通过对比 `RANConfigurationDrawer.tsx` 的实现,发现 `ProtocolLogsTable.tsx` 中的抽屉结构存在问题。 - -### 修改文件 -- `X1.WebUI/src/components/protocol-logs/ProtocolLogsTable.tsx` - 修复抽屉布局结构 - -### 修改内容 - -#### 1. 抽屉结构重构 -- **原结构问题**:`DrawerContent` 没有正确的 className,内容区域使用了错误的布局 -- **新结构**:参考 `RANConfigurationDrawer.tsx` 的实现,使用正确的 flex 布局结构 - -#### 2. 具体修改 -```tsx -// 修改前 - - - - {/* 头部内容 */} - - -
- -
-
-
- -// 修改后 - -
- - {/* 头部内容 */} - - - -
- -
-
-
-
-``` - -#### 3. 布局优化 -- **外层容器**:添加 `div` 包装器,使用 `flex flex-col h-full` 布局 -- **DrawerContent**:添加 `flex flex-col flex-1 overflow-y-auto` className -- **内容区域**:使用 `flex flex-col flex-1 min-h-0 p-4` 布局 -- **ConfigContentViewer**:使用 `flex-1` className 占满剩余空间 - -### 技术特性 -- **正确的 flex 布局**:确保抽屉内容能够正确滚动 -- **高度管理**:使用 `min-h-0` 确保 flex 子元素能够正确收缩 -- **滚动控制**:滚动条出现在内容区域内部,而不是外层容器 -- **空间分配**:正确分配垂直空间,确保所有元素都能正确显示 - -### 用户体验改进 -- **滚动条位置**:滚动条现在出现在内容区域内部,符合用户期望 -- **内容可见性**:底部内容现在能够正确显示和滚动 -- **布局稳定性**:抽屉布局更加稳定和可预测 -- **操作便利性**:用户可以在内容区域内部滚动查看完整内容 - -### 影响范围 -- **消息详情抽屉**:修复了滚动条位置和内容显示问题 -- **用户体验**:提供了更好的内容查看体验 -- **布局一致性**:与 `RANConfigurationDrawer.tsx` 保持一致的布局结构 - ---- - -## 2025-01-29 移除消息详情抽屉的保存和下载功能 - -### 修改概述 -根据用户需求,移除了消息详情抽屉中的保存和下载功能,使 `ConfigContentViewer` 变为只读模式。 - -### 修改文件 -- `X1.WebUI/src/components/protocol-logs/ProtocolLogsTable.tsx` - 移除保存和下载功能 - -### 修改内容 - -#### 1. 移除功能按钮 -- **移除复制功能**:不再传递 `onCopy` 属性给 `ConfigContentViewer` -- **移除下载功能**:不再传递 `onDownload` 属性给 `ConfigContentViewer` -- **保留搜索功能**:搜索功能仍然可用,便于用户查找特定内容 - -#### 2. 具体修改 -```tsx -// 修改前 - - -// 修改后 - -``` - -### 技术特性 -- **只读模式**:消息详情现在为只读,用户无法修改内容 -- **简化界面**:移除了不必要的操作按钮,界面更加简洁 -- **保留搜索**:搜索功能仍然可用,便于用户查找特定内容 -- **功能隔离**:通过不传递回调函数来控制按钮的显示 - -### 用户体验改进 -- **界面简化**:移除了复制和下载按钮,界面更加简洁 -- **功能明确**:明确表示这是一个只读的查看界面 -- **操作专注**:用户可以专注于查看和搜索内容,不会被其他操作干扰 - ---- - -## 2025-01-29 修复ConfigContentViewer主题适配问题 - -### 修改概述 -根据用户反馈,修复了 `ConfigContentViewer` 组件不会随着主题改变的问题,参考 `ConfigContentEditor` 的实现,使用 Tailwind 主题变量替换硬编码的颜色类名。 - -### 修改文件 -- `X1.WebUI/src/components/ui/ConfigContentViewer.tsx` - 修复主题适配问题 - -### 修改内容 - -#### 1. 颜色类名替换 -- **搜索图标颜色**:将 `text-gray-400` 替换为 `text-muted-foreground` -- **搜索状态文本**:将 `text-gray-500` 替换为 `text-muted-foreground` -- **内容区域背景**:将 `bg-gray-50` 替换为 `bg-muted/50` - -#### 2. 具体修改 -```tsx -// 修改前 - - -
- -// 修改后 - - -
-``` - -### 技术特性 -- **主题适配**:使用 Tailwind 主题变量,支持明暗主题切换 -- **颜色一致性**:与 `ConfigContentEditor` 保持一致的色彩方案 -- **响应式设计**:颜色会根据当前主题自动调整 -- **可维护性**:使用语义化的颜色类名,便于维护和扩展 - -### 用户体验改进 -- **主题一致性**:组件现在会随着主题切换而改变颜色 -- **视觉统一**:与 `ConfigContentEditor` 保持一致的视觉效果 -- **更好的可读性**:在不同主题下都有良好的对比度和可读性 - ---- - -## 2025-01-29 修复RANConfigurationViewDialog主题适配问题 - -### 修改概述 -根据用户需求,修复了 `RANConfigurationViewDialog.tsx` 组件不会随着主题改变的问题,将硬编码的颜色类名替换为 Tailwind 主题变量,但保留 `ConfigContentViewer` 的修改。 - -### 修改文件 -- `X1.WebUI/src/pages/ran-configurations/RANConfigurationViewDialog.tsx` - 修复主题适配问题 - -### 修改内容 - -#### 1. 标签文本颜色 -- **配置名称标签**:将 `text-gray-600` 替换为 `text-muted-foreground` -- **状态标签**:将 `text-gray-600` 替换为 `text-muted-foreground` -- **描述标签**:将 `text-gray-600` 替换为 `text-muted-foreground` -- **配置内容标签**:将 `text-gray-600` 替换为 `text-muted-foreground` - -#### 2. 内容文本颜色 -- **配置名称内容**:将 `text-gray-900` 替换为 `text-foreground` -- **描述内容**:将 `text-gray-900` 替换为 `text-foreground` - -#### 3. 状态标签颜色 -- **禁用状态**:将 `bg-red-100 text-red-800` 替换为 `bg-destructive/10 text-destructive` -- **启用状态**:将 `bg-green-100 text-green-800` 替换为 `bg-green-500/10 text-green-600 dark:text-green-400` - -#### 4. 标题颜色 -- **对话框标题**:为 `DialogTitle` 添加 `text-foreground` 类名以确保正确的主题适配 - -#### 5. 对话框容器 -- **DialogContent**:为 `DialogContent` 添加 `bg-background text-foreground` 类名以确保整个对话框的主题适配 - -#### 6. 具体修改 -```tsx -// 修改前 - - - - 查看配置内容 - {configuration.name} - - -
{configuration.name}
- - -// 修改后 - - - - 查看配置内容 - {configuration.name} - - -
{configuration.name}
- -``` - -### 技术特性 -- **主题适配**:使用 Tailwind 主题变量,支持明暗主题切换 -- **语义化颜色**:使用 `text-foreground`、`text-muted-foreground` 等语义化颜色类名 -- **状态颜色优化**:使用 `destructive` 主题色表示禁用状态,绿色表示启用状态 -- **暗色主题支持**:为启用状态添加了 `dark:text-green-400` 以在暗色主题下保持良好的可读性 - -### 用户体验改进 -- **主题一致性**:对话框现在会随着主题切换而改变颜色 -- **视觉统一**:与整个应用保持一致的色彩方案 -- **更好的可读性**:在不同主题下都有良好的对比度和可读性 -- **状态清晰**:禁用和启用状态的颜色更加语义化和直观 - ---- - -## 2025-01-29 修复IMSConfigurationViewDialog主题适配问题 - -### 修改概述 -根据用户需求,修复了 `IMSConfigurationViewDialog.tsx` 组件不会随着主题改变的问题,应用与 `RANConfigurationViewDialog.tsx` 相同的主题适配修复。 - -### 修改文件 -- `X1.WebUI/src/pages/ims-configurations/IMSConfigurationViewDialog.tsx` - 修复主题适配问题 - -### 修改内容 - -#### 1. 对话框容器 -- **DialogContent**:添加 `bg-background text-foreground` 类名以确保整个对话框的主题适配 - -#### 2. 标题颜色 -- **对话框标题**:为 `DialogTitle` 添加 `text-foreground` 类名以确保正确的主题适配 - -#### 3. 标签文本颜色 -- **配置名称标签**:将 `text-gray-600` 替换为 `text-muted-foreground` -- **状态标签**:将 `text-gray-600` 替换为 `text-muted-foreground` -- **描述标签**:将 `text-gray-600` 替换为 `text-muted-foreground` -- **配置内容标签**:将 `text-gray-600` 替换为 `text-muted-foreground` - -#### 4. 内容文本颜色 -- **配置名称内容**:将 `text-gray-900` 替换为 `text-foreground` -- **描述内容**:将 `text-gray-900` 替换为 `text-foreground` - -#### 5. 状态标签颜色 -- **禁用状态**:将 `bg-red-100 text-red-800` 替换为 `bg-destructive/10 text-destructive` -- **启用状态**:将 `bg-green-100 text-green-800` 替换为 `bg-green-500/10 text-green-600 dark:text-green-400` - -#### 6. 具体修改 -```tsx -// 修改前 - - - -
{configuration.name}
- - -// 修改后 - - - -
{configuration.name}
- -``` - -### 技术特性 -- **主题适配**:使用 Tailwind 主题变量,支持明暗主题切换 -- **语义化颜色**:使用 `text-foreground`、`text-muted-foreground` 等语义化颜色类名 -- **状态颜色优化**:使用 `destructive` 主题色表示禁用状态,绿色表示启用状态 -- **暗色主题支持**:为启用状态添加了 `dark:text-green-400` 以在暗色主题下保持良好的可读性 - -### 用户体验改进 -- **主题一致性**:对话框现在会随着主题切换而改变颜色 -- **视觉统一**:与整个应用保持一致的色彩方案 -- **更好的可读性**:在不同主题下都有良好的对比度和可读性 -- **状态清晰**:禁用和启用状态的颜色更加语义化和直观 - ---- - -## 2025-01-29 修复CoreNetworkConfigViewDialog主题适配问题 - -### 修改概述 -根据用户需求,修复了 `CoreNetworkConfigViewDialog.tsx` 组件不会随着主题改变的问题,应用与其他配置查看对话框相同的主题适配修复。 - -### 修改文件 -- `X1.WebUI/src/pages/core-network-configs/CoreNetworkConfigViewDialog.tsx` - 修复主题适配问题 - -### 修改内容 - -#### 1. 对话框容器 -- **DialogContent**:添加 `bg-background text-foreground` 类名以确保整个对话框的主题适配 - -#### 2. 标题颜色 -- **对话框标题**:为 `DialogTitle` 添加 `text-foreground` 类名以确保正确的主题适配 - -#### 3. 标签文本颜色 -- **配置名称标签**:将 `text-gray-600` 替换为 `text-muted-foreground` -- **状态标签**:将 `text-gray-600` 替换为 `text-muted-foreground` -- **描述标签**:将 `text-gray-600` 替换为 `text-muted-foreground` -- **配置内容标签**:将 `text-gray-600` 替换为 `text-muted-foreground` - -#### 4. 内容文本颜色 -- **配置名称内容**:将 `text-gray-900` 替换为 `text-foreground` -- **描述内容**:将 `text-gray-900` 替换为 `text-foreground` - -#### 5. 状态标签颜色 -- **禁用状态**:将 `bg-red-100 text-red-800` 替换为 `bg-destructive/10 text-destructive` -- **启用状态**:将 `bg-green-100 text-green-800` 替换为 `bg-green-500/10 text-green-600 dark:text-green-400` - -#### 6. 具体修改 -```tsx -// 修改前 - - - -
{config.name}
- - -// 修改后 - - - -
{config.name}
- -``` - -### 技术特性 -- **主题适配**:使用 Tailwind 主题变量,支持明暗主题切换 -- **语义化颜色**:使用 `text-foreground`、`text-muted-foreground` 等语义化颜色类名 -- **状态颜色优化**:使用 `destructive` 主题色表示禁用状态,绿色表示启用状态 -- **暗色主题支持**:为启用状态添加了 `dark:text-green-400` 以在暗色主题下保持良好的可读性 - -### 用户体验改进 -- **主题一致性**:对话框现在会随着主题切换而改变颜色 -- **视觉统一**:与整个应用保持一致的色彩方案 -- **更好的可读性**:在不同主题下都有良好的对比度和可读性 -- **状态清晰**:禁用和启用状态的颜色更加语义化和直观 - ---- - -## 2025-01-29 修复消息详情抽屉滚动条问题 - -### 修改概述 -根据用户需求,修复消息详情抽屉的滚动条问题,将滚动条从最外层移到内容区域内部,提供更好的用户体验。 - -### 修改文件 -- `X1.WebUI/src/components/protocol-logs/ProtocolLogsTable.tsx` - 修复消息详情抽屉布局 - -### 修改内容 - -#### 1. 抽屉结构重构 -- **原结构问题**:`DrawerContent` 被错误地嵌套在 `DrawerHeader` 内部,导致布局混乱 -- **新结构**:将 `DrawerContent` 移到正确的位置,作为 `Drawer` 的直接子元素 - -#### 2. 滚动条位置修复 -- **原实现**:滚动条在最外层,影响整体布局 -- **新实现**:滚动条在内容区域内部,只对消息详情内容进行滚动 -- **布局优化**:使用 `overflow-auto` 类在内容区域实现滚动 - -#### 3. Flex布局高度修复 -- **问题**:flex容器中的子元素没有正确的高度约束 -- **解决方案**:添加 `min-h-0` 类确保flex子元素能够正确收缩 -- **影响**:修复了内容区域无法正确滚动的问题 - -#### 4. 具体修改 -```tsx -// 修改前 - -
- - {/* 标题和关闭按钮 */} - - - -
- -
-
-
-
- -// 修改后 - - - - {/* 标题和关闭按钮 */} - - -
- -
-
-
-``` - -#### 5. ConfigContentViewer组件修复 -- **问题**:组件内部的高度约束不正确 -- **解决方案**: - - 为内容容器添加 `min-h-0` 类 - - 移除内联样式中的 `height: '100%'`,避免冲突 - - 确保flex布局正确工作 - -#### 6. DrawerContent组件修复 -- **问题**:`DrawerContent` 组件本身有 `overflow-y-auto` 类,导致双重滚动 -- **解决方案**: - - 移除 `DrawerContent` 中的 `overflow-y-auto` 和 `p-6` 类 - - 改为使用 `flex flex-col` 布局 - - 让具体的滚动控制由子组件决定 - -#### 7. DrawerContent高度约束修复 -- **问题**:`DrawerContent` 缺少 `min-h-0` 类,导致无法正确收缩 -- **解决方案**: - - 为 `DrawerContent` 添加 `min-h-0` 类 - - 确保flex子元素能够正确收缩到比内容更小的高度 - - 这是解决滚动问题的关键修复 - -### 技术特性 - -#### 1. 布局结构优化 -- **正确的HTML层次**:`Drawer` → `DrawerContent` → `DrawerHeader` + 内容区域 -- **Flex布局**:使用flex布局确保内容区域占满剩余空间 -- **滚动区域**:只在内容区域实现滚动,不影响标题栏 - -#### 2. 用户体验改进 -- **固定标题**:标题栏始终可见,不会随内容滚动 -- **内容滚动**:只有消息详情内容可以滚动 -- **布局稳定**:抽屉整体布局更加稳定和可预测 - -#### 3. 响应式设计 -- **自适应高度**:内容区域自动适应抽屉高度 -- **滚动支持**:当内容超出可视区域时自动显示滚动条 -- **空间利用**:充分利用抽屉的可用空间 - -### 影响范围 -- **用户界面**:消息详情抽屉的滚动行为更加合理 -- **布局稳定性**:抽屉布局更加稳定,不会出现布局混乱 -- **用户体验**:提供更好的内容浏览体验 - -### 注意事项 -- 保持了原有的功能不变 -- 滚动条现在只在内容区域显示 -- 标题栏始终固定在顶部 -- 内容区域可以独立滚动 中的字段引用 -- 修改 `X1.WebUI/src/pages/ims-configurations/IMSConfigurationsView.tsx` 中的字段引用 - -### 技术说明 -- 确保前端接口定义与后端API返回的JSON数据格式完全一致 -- 修复字段名称大小写问题,从 `CoreNetworkConfigId` 改为 `coreNetworkConfigId` -- 保持与后端数据结构的同步 - -## 2024-12-19 修复核心网络配置字段名称 - -### 修复内容 -- 将 `CoreNetworkConfigId` 改为 `coreNetworkConfigId` 以匹配后端API返回的数据格式 -- 修改 `X1.WebUI/src/services/coreNetworkConfigService.ts` 中的所有接口定义 -- 修改 `X1.WebUI/src/pages/core-network-configs/CoreNetworkConfigsTable.tsx` 中的字段引用 -- 修改 `X1.WebUI/src/pages/core-network-configs/CoreNetworkConfigsView.tsx` 中的字段引用 - -### 技术说明 -- 确保前端接口定义与后端API返回的JSON数据格式完全一致 -- 修复字段名称大小写问题,从 `CoreNetworkConfigId` 改为 `coreNetworkConfigId` -- 保持与后端数据结构的同步 - -## 2025-07-28 重构网络栈配置表单 - -### 重构内容 -- **类型安全改进**:修复了表单类型不匹配问题,支持创建和编辑模式的不同类型 -- **绑定关系管理**:添加了栈与核心网/IMS绑定关系的完整管理功能 -- **表单验证**:添加了基本的表单验证,确保必填字段不为空 -- **用户体验优化**:使用卡片布局,改进表单结构和交互体验 -- **功能完整性**:支持添加、删除、编辑绑定关系 - -### 技术改进 -- **类型系统**:使用联合类型 `CreateNetworkStackConfigRequest | UpdateNetworkStackConfigRequest` -- **状态管理**:使用 `useEffect` 处理初始数据变化 -- **表单验证**:添加网络栈名称的必填验证 -- **绑定管理**:实现完整的绑定关系CRUD操作 -- **响应式设计**:使用网格布局适配不同屏幕尺寸 - -### 新增功能 -- **绑定关系管理**: - - 添加绑定关系 - - 删除绑定关系 - - 编辑绑定关系(索引、核心网配置ID、IMS配置ID) -- **表单验证**:网络栈名称必填验证 -- **用户体验**: - - 卡片式布局 - - 绑定关系可视化 - - 空状态提示 - -### 界面改进 -- **基本信息卡片**:包含网络栈名称、RAN配置下拉框、描述、激活状态 -- **绑定关系卡片**:包含绑定关系列表和添加按钮 -- **绑定项**:每个绑定关系显示为独立的卡片项 -- **操作按钮**:添加和删除绑定关系的按钮 - -### 2025-07-28 改进RAN配置选择 -- **下拉框选择**:将RAN ID输入框改为下拉框,从ranConfigurationService获取数据 -- **数据加载**:自动加载所有可用的RAN配置(未禁用的) -- **用户体验**:提供更直观的RAN配置选择方式 -- **数据一致性**:确保选择的RAN配置ID与现有配置一致 -- **错误修复**:修复Radix UI Select组件空值错误,使用"none"作为"无"选项的值 -- **界面简化**:移除"激活此配置"复选框,默认激活状态 -- **服务调用修复**:使用ranConfigurationService.getRANConfigurations()方法替代直接fetch调用 -- **搜索功能增强**:为RAN配置下拉框添加搜索功能,支持按名称过滤配置 -- **抽屉式界面**:创建NetworkStackConfigDrawer组件,采用抽屉形式替代对话框表单 -- **清理冗余文件**:删除不再使用的NetworkStackConfigForm.tsx文件 -- **RAN配置显示优化**:下拉框显示格式改为"名称 | 描述"的组合形式,提升用户识别度 -- **搜索功能增强**:RAN配置搜索同时匹配名称和描述字段,提供更灵活的搜索体验 -- **绑定关系索引优化**:索引自动从1开始递增,删除后自动重新排序,提升用户体验 -- **绑定关系配置选择**:核心网配置ID和IMS配置ID改为下拉框,分别从coreNetworkConfigService和imsConfigurationService获取数据,支持搜索功能 -- **布局优化**:栈与核心网/IMS绑定关系区域铺满剩余空白,内容支持纵向滚动 -- **布局修复**:调整抽屉内容结构,确保绑定关系区域正确占据剩余空间并显示滚动条 -- **列表化设计**:将栈与核心网/IMS绑定关系改为列表形式,更紧凑和直观 -- **下拉框状态修复**:修复多个绑定项共享下拉框状态的问题,每个绑定项现在有独立的下拉框控制 -- **下拉框互斥控制**:确保同时只有一个下拉框打开,点击任何下拉框都会关闭其他所有下拉框 -- **自动关闭机制**:当鼠标离开下拉框区域时自动关闭所有下拉框,提升用户体验 -- **悬停显示下拉框**:改为鼠标悬停显示下拉框,鼠标离开时自动关闭,提供更直观的交互体验 -- **回退到点击交互**:由于悬停交互不够稳定,改回点击交互方式,优化点击外部关闭逻辑 -- **滚动条优化**:修复绑定关系区域的滚动条显示问题,确保内容超出时正确显示滚动条 -- **强制滚动高度**:为绑定关系区域设置明确的最大高度,确保滚动条正确显示 -- **标签右对齐**:将核心网和IMS标签设置为右对齐,提升界面美观度 -- **下拉框定位修复**:修复下拉框无法点击的问题,通过正确的定位和层级设置确保下拉框可以正常交互 -- **点击外部关闭逻辑优化**:修复点击下拉框内容时意外关闭的问题,确保只有在真正点击外部时才关闭下拉框 -- **绑定关系校验**:添加创建时的绑定关系完整性校验,确保每个绑定项都完整填写或完全为空,避免部分填写的情况 -- **双重校验逻辑**:区分部分填写和完全空白两种情况,分别提示用户完成填写或移除绑定项 -- **内联警告显示**:将校验错误信息显示在取消按钮左边,替代弹窗提示,提供更好的用户体验 -- **RAN和绑定关系校验**:确保RAN配置和绑定关系至少选择一个,不能都不填写 - -## 2025-07-28 删除未使用的栈核心网IMS绑定服务 - -### 删除内容 -- **删除文件**:`X1.WebUI/src/services/stackCoreIMSBindingService.ts` - 栈核心网IMS绑定管理服务 -- **清理API路径**:从 `X1.WebUI/src/constants/api.ts` 中移除 `STACK_CORE_IMS_BINDINGS` 配置 - -### 删除原因 -- 该服务没有被任何页面组件引用或使用 -- 栈与核心网/IMS绑定关系管理已集成到网络栈配置服务中 -- 避免代码冗余和维护负担 - -### 技术说明 -- 栈与核心网/IMS绑定关系的接口定义已保留在 `networkStackConfigService.ts` 中 -- 绑定关系的CRUD操作通过网络栈配置服务进行管理 -- 保持了功能的完整性,只是简化了服务架构 - -## 2025-07-28 修复网络栈配置服务接口不匹配问题 - -### 问题描述 -前端 `networkStackConfigService.ts` 中的接口定义与后端API不匹配,导致以下问题: -- 字段名称不匹配:前端使用 `stackId`,后端使用 `NetworkStackName` -- 搜索参数不匹配:前端使用 `searchTerm`,后端使用 `NetworkStackName` -- 响应结构不匹配:前端期望 `items` 字段,后端返回 `NetworkStackConfigs` -- 删除响应不匹配:前端期望返回 `boolean`,后端返回 `DeleteNetworkStackConfigResponse` - -### 修复内容 - -#### 1. 修复前端接口定义 -- **字段名称统一**: - - `stackId` → `networkStackName` - - `searchTerm` → `networkStackName` - - `items` → `networkStackConfigs` - -- **新增接口定义**: - - 添加 `StackCoreIMSBinding` 接口 - - 添加 `CreateStackCoreIMSBindingItem` 接口 - - 添加 `UpdateStackCoreIMSBindingItem` 接口 - - 添加 `DeleteNetworkStackConfigResponse` 接口 - -- **更新请求/响应接口**: - - 所有接口中的 `stackId` 字段改为 `networkStackName` - - 添加 `stackCoreIMSBindings` 字段支持 - - 删除操作返回类型改为 `DeleteNetworkStackConfigResponse` - -#### 2. 修复页面组件 -- **NetworkStackConfigsView.tsx**: - - 更新搜索字段:`searchTerm` → `networkStackName` - - 更新表格列配置:`stackId` → `networkStackName` - - 修复所有字段引用和状态管理 - - 更新表单提交处理逻辑 - -- **NetworkStackConfigForm.tsx**: - - 更新表单字段:`stackId` → `networkStackName` - - 更新标签和占位符文本 - - 修复表单状态管理 - -- **NetworkStackConfigsTable.tsx**: - - 更新表格渲染逻辑:`stackId` → `networkStackName` - - 修复字段映射关系 - -#### 3. 技术细节 -- **接口一致性**:确保前端接口定义与后端API完全匹配 -- **类型安全**:提供完整的TypeScript类型定义 -- **功能完整性**:支持栈与核心网/IMS绑定关系管理 -- **错误处理**:保持统一的错误处理机制 - -### 影响范围 -- **前端服务**:网络栈配置服务现在与后端API完全匹配 -- **用户界面**:搜索、表格、表单功能正常工作 -- **数据完整性**:所有CRUD操作都能正确处理数据 -- **开发体验**:提供完整的类型安全和代码提示 - -### 测试建议 -1. 测试网络栈配置的创建、编辑、删除功能 -2. 验证搜索和过滤功能 -3. 检查表格显示和分页功能 -4. 确认表单验证和提交功能 -5. 测试栈与核心网/IMS绑定关系管理 - -## 2025-01-29 - 代码提交和.gitignore更新 - -### 修改内容 -1. **代码提交和推送** - - 提交了网络栈配置管理功能的重构代码 - - 推送代码到远程仓库 `feature/x1-web-request` 分支 - - 同步远程分支更新 - -2. **更新.gitignore文件** - - 添加 `X1.WebAPI/logs/` 目录到忽略列表 - - 添加 `*.log` 文件模式到忽略列表 - - 从版本控制中移除已跟踪的日志文件 - - 提交并推送.gitignore更新 - -### 技术细节 -- 使用 `git add .` 添加所有修改文件 -- 使用 `git commit -m` 提交代码,包含详细的提交信息 -- 使用 `git push origin feature/x1-web-request` 推送到远程分支 -- 使用 `git rm --cached` 从版本控制中移除日志文件 -- 更新.gitignore文件以忽略日志文件 - -### 提交信息 -``` -feat: 重构网络栈配置管理功能 -- 修复networkStackConfigService.ts接口不匹配问题 -- 删除未使用的stackCoreIMSBindingService.ts -- 重构NetworkStackConfigForm为NetworkStackConfigDrawer -- 实现RAN配置下拉框,支持搜索功能 -- 移除激活配置复选框,默认激活 -- 修复loadRANConfigurations使用正确服务 -- 实现核心网和IMS配置下拉框 -- 优化绑定关系布局和滚动条显示 -- 添加标签右对齐样式 -- 修复下拉框定位和点击交互问题 -- 实现下拉框互斥控制和自动关闭 -- 添加完整的表单校验逻辑 -- 实现内联错误提示替代弹窗 - -chore: 更新.gitignore忽略日志文件 -- 添加X1.WebAPI/logs/目录到忽略列表 -- 添加*.log文件模式到忽略列表 -- 从版本控制中移除已跟踪的日志文件 - -## 2024-12-19 添加设备编码字段 - -### 修改文件 -- `X1.Domain/Entities/Device/CellularDevice.cs` - 在蜂窝设备实体中添加设备编码字段 - -### 修改内容 - -#### 1. 添加设备编码属性 -- **字段名称**:`DeviceCode` -- **字段类型**:`string` -- **约束条件**: - - `[Required]` - 必填字段 - - `[MaxLength(50)]` - 最大长度50个字符 -- **访问修饰符**:`private set` - 只读属性,通过方法修改 - -#### 2. 更新创建方法 -- **方法签名**:`Create` 方法添加 `deviceCode` 参数 -- **参数位置**:在 `serialNumber` 参数之后,`description` 参数之前 -- **参数验证**:通过 `[Required]` 和 `[MaxLength(50)]` 进行验证 -- **属性赋值**:在创建设备时设置 `DeviceCode` 属性 - -#### 3. 更新更新方法 -- **方法签名**:`Update` 方法添加 `deviceCode` 参数 -- **参数位置**:在 `serialNumber` 参数之后,`description` 参数之前 -- **属性赋值**:在更新设备时设置 `DeviceCode` 属性 - -### 技术特性 -- **数据完整性**:设备编码作为必填字段,确保每个设备都有唯一标识 -- **长度限制**:最大50个字符,适合各种编码格式 -- **封装性**:使用私有setter,确保数据只能通过方法修改 -- **一致性**:与现有字段(如SerialNumber)保持相同的设计模式 - -### 业务价值 -- **设备标识**:提供额外的设备标识方式,便于设备管理 -- **系统集成**:支持与其他系统的设备编码对接 -- **数据追溯**:增强设备数据的可追溯性 -- **管理便利**:提供更灵活的设备识别和管理方式 - -### 影响范围 -- **实体模型**:CellularDevice实体增加了DeviceCode字段 -- **创建操作**:所有创建设备的操作都需要提供设备编码 -- **更新操作**:所有更新设备信息的操作都需要提供设备编码 -- **数据验证**:确保设备编码的完整性和有效性 - -### 后续工作建议 -1. **数据库迁移**:需要创建数据库迁移来添加DeviceCode字段 -2. **API更新**:更新相关的API接口以支持设备编码字段 -3. **前端界面**:更新前端界面以显示和编辑设备编码 -4. **数据验证**:在应用层添加设备编码的业务验证逻辑 -5. **测试用例**:为设备编码字段添加相应的测试用例 - -## 2024-12-19 修复设备命令处理器中的deviceCode字段 - -### 修改文件 -- `X1.Application/Features/Devices/Commands/CreateDevice/CreateDeviceCommand.cs` - 添加设备编码字段 -- `X1.Application/Features/Devices/Commands/CreateDevice/CreateDeviceResponse.cs` - 添加设备编码字段 -- `X1.Application/Features/Devices/Commands/UpdateDevice/UpdateDeviceCommand.cs` - 添加设备编码字段 -- `X1.Application/Features/Devices/Commands/UpdateDevice/UpdateDeviceResponse.cs` - 添加设备编码字段 -- `X1.Application/Features/Devices/Commands/CreateDevice/CreateDeviceCommandHandler.cs` - 修复设备编码字段处理 -- `X1.Application/Features/Devices/Commands/UpdateDevice/UpdateDeviceCommandHandler.cs` - 修复设备编码字段处理 - -### 修改内容 - -#### 1. 命令类修复 -- **CreateDeviceCommand**: - - 添加 `DeviceCode` 属性 - - 添加 `[Required]` 和 `[MaxLength(50)]` 验证特性 - - 位置:在 `SerialNumber` 字段之后,`Description` 字段之前 - -- **UpdateDeviceCommand**: - - 添加 `DeviceCode` 属性 - - 添加 `[Required]` 和 `[MaxLength(50)]` 验证特性 - - 位置:在 `SerialNumber` 字段之后,`Description` 字段之前 - -#### 2. 响应类修复 -- **CreateDeviceResponse**: - - 添加 `DeviceCode` 属性 - - 位置:在 `SerialNumber` 字段之后,`Description` 字段之前 - -- **UpdateDeviceResponse**: - - 添加 `DeviceCode` 属性 - - 位置:在 `SerialNumber` 字段之后,`Description` 字段之前 - -#### 3. 命令处理器修复 -- **CreateDeviceCommandHandler**: - - 在 `CellularDevice.Create()` 方法调用中添加 `deviceCode: request.DeviceCode` 参数 - - 在响应构建中添加 `DeviceCode = device.DeviceCode` 字段 - -- **UpdateDeviceCommandHandler**: - - 在 `existingDevice.Update()` 方法调用中添加 `deviceCode: request.DeviceCode` 参数 - - 在响应构建中添加 `DeviceCode = existingDevice.DeviceCode` 字段 - -### 技术特性 -- **数据验证**:设备编码字段为必填,最大长度50个字符 -- **参数传递**:正确传递设备编码参数到实体创建和更新方法 -- **响应映射**:在响应中包含设备编码字段 -- **一致性**:与实体模型中的DeviceCode字段保持一致 - -### 业务价值 -- **完整性**:确保设备编码在整个创建和更新流程中正确传递 -- **验证**:在应用层提供设备编码的验证 -- **API一致性**:确保API接口与实体模型保持一致 -- **用户体验**:提供完整的设备编码管理功能 - -### 影响范围 -- **创建操作**:设备创建API现在支持设备编码字段 -- **更新操作**:设备更新API现在支持设备编码字段 -- **数据验证**:应用层验证确保设备编码的完整性 -- **响应数据**:API响应包含设备编码信息 - -### 测试建议 -1. 测试设备创建API,验证设备编码字段的处理 -2. 测试设备更新API,验证设备编码字段的处理 -3. 验证设备编码字段的验证规则 -4. 确认API响应包含正确的设备编码信息 -5. 测试设备编码字段的边界值(空值、最大长度等) - -## 2025-07-28 - 自动生成设备编号,移除用户手动输入 - -### 修改原因 -根据用户需求,设备编号应该自动生成,格式为 `DEV-001-SN`(其中001是序号,SN是序列号),序号从001开始根据数据库中的设备数量自动递增,不需要用户手动输入。 - -### 修改文件 -- `X1.Application/Features/Devices/Commands/CreateDevice/CreateDeviceCommand.cs` - 移除DeviceCode字段 -- `X1.Application/Features/Devices/Commands/CreateDevice/CreateDeviceCommandHandler.cs` - 添加自动生成设备编号逻辑 -- `X1.Domain/Repositories/Device/ICellularDeviceRepository.cs` - 添加GetDeviceCountAsync方法 -- `X1.Infrastructure/Repositories/Device/CellularDeviceRepository.cs` - 实现GetDeviceCountAsync方法 -- `X1.WebUI/src/services/instrumentService.ts` - 移除DeviceCode字段 -- `X1.WebUI/src/pages/instruments/DeviceForm.tsx` - 移除设备编码输入字段 -- `X1.WebUI/src/pages/instruments/DevicesView.tsx` - 更新类型检查逻辑 - -### 修改内容 - -#### 1. 后端命令类修改 -- **CreateDeviceCommand**: - - 删除 `DeviceCode` 属性及其验证特性 - - 用户不再需要手动输入设备编号 - -#### 2. 后端命令处理器修改 -- **CreateDeviceCommandHandler**: - - 添加 `GenerateDeviceCodeAsync` 方法,自动生成设备编号 - - 设备编号格式:`DEV-{序号}-{序列号}`,序号为3位数字(001, 002, ...) - - 序号根据数据库中的设备总数自动递增 - - 在获取序列号成功后,移除并重新添加endpointManager - - 修改 `CreateAndSaveDeviceAsync` 方法签名,添加deviceCode参数 - -#### 3. 仓储接口扩展 -- **ICellularDeviceRepository**: - - 添加 `GetDeviceCountAsync` 方法 - - 用于获取当前设备总数,计算下一个序号 - -#### 4. 仓储实现 -- **CellularDeviceRepository**: - - 实现 `GetDeviceCountAsync` 方法 - - 使用 `QueryRepository.CountAsync` 获取设备总数 - -#### 5. 前端接口修改 -- **CreateDeviceRequest**: - - 删除 `deviceCode` 字段 - - 用户不再需要提供设备编号 - -#### 6. 前端表单修改 -- **DeviceForm**: - - 移除设备编码输入字段 - - 更新表单状态管理,移除deviceCode相关代码 - -#### 7. 前端页面修改 -- **DevicesView**: - - 更新类型检查逻辑,移除对deviceCode的检查 - - 修复语法错误 - -### 技术特性 -- **自动编号生成**:根据设备总数自动生成序号 -- **格式规范**:设备编号格式为 `DEV-001-SN` -- **序号递增**:序号从001开始,每次递增1 -- **endpointManager管理**:在获取序列号成功后重新管理endpoint -- **用户友好**:用户无需手动输入设备编号 - -### 业务价值 -- **简化操作**:用户无需手动输入设备编号 -- **避免重复**:自动生成的编号确保唯一性 -- **规范管理**:统一的编号格式便于管理 -- **减少错误**:避免用户输入错误 - -### 影响范围 -- **创建操作**:设备创建时自动生成设备编号 -- **前端界面**:移除设备编码输入字段 -- **API接口**:更新请求模型,移除deviceCode字段 -- **数据库操作**:添加获取设备总数的方法 - -### 设备编号生成逻辑 -1. **获取设备总数**:调用 `GetDeviceCountAsync` 获取当前设备数量 -2. **计算序号**:设备总数 + 1 -3. **格式化序号**:使用 `ToString("D3")` 格式化为3位数字 -4. **组装编号**:`DEV-{序号}-{序列号}` - -### 注意事项 -- 设备编号格式:`DEV-000-SN`、`DEV-001-SN` 等 -- 序号从000开始,最大到999 -- 如果设备数量超过999,需要扩展序号位数 - -## 2025-07-28 - 删除CreateDeviceCommand中的SerialNumber字段,改为通过IP地址自动获取 - -### 修改原因 -根据用户需求,设备序列号不应该由用户手动填写,而应该通过设备的IP地址自动获取。 - -### 修改文件 -- `X1.Application/Features/Devices/Commands/CreateDevice/CreateDeviceCommand.cs` - 删除SerialNumber字段 -- `X1.Application/Features/Devices/Commands/CreateDevice/CreateDeviceCommandHandler.cs` - 添加通过IP获取序列号的逻辑 -- `X1.Application/Features/Devices/Commands/UpdateDevice/UpdateDeviceCommand.cs` - 删除SerialNumber字段 -- `X1.Application/Features/Devices/Commands/UpdateDevice/UpdateDeviceCommandHandler.cs` - 移除序列号验证和更新逻辑 -- `X1.DynamicClientCore/Extensions/ServiceCollectionExtensions.cs` - 注册IBaseInstrumentClient服务 -- `X1.WebUI/src/services/instrumentService.ts` - 更新前端接口定义 -- `X1.WebUI/src/pages/instruments/DeviceForm.tsx` - 更新前端表单 -- `X1.WebUI/src/pages/instruments/DevicesView.tsx` - 更新前端页面 - -### 修改内容 - -#### 1. 后端命令类修改 -- **CreateDeviceCommand**: - - 删除 `SerialNumber` 属性及其验证特性 - - 保留 `DeviceCode` 属性用于设备标识 -- **UpdateDeviceCommand**: - - 删除 `SerialNumber` 属性及其验证特性 - - 保留 `DeviceCode` 属性用于设备标识 - -#### 2. 后端命令处理器修改 -- **CreateDeviceCommandHandler**: - - 添加 `IBaseInstrumentClient` 依赖注入 - - 在创建设备前通过IP地址和端口获取设备序列号 - - 使用 `ServiceEndpoint` 配置设备连接信息 - - 调用 `GetDeviceSerialNumberAsync` 方法获取序列号 - - 添加序列号获取失败的错误处理 - - 更新日志记录,移除对SerialNumber的引用 -- **UpdateDeviceCommandHandler**: - - 移除序列号验证逻辑 - - 在更新设备时保持原有序列号不变 - - 更新日志记录,移除对SerialNumber的引用 - -#### 3. 前端接口修改 -- **CreateDeviceRequest**: - - 删除 `serialNumber` 字段 - - 保留 `deviceCode` 字段 -- **UpdateDeviceRequest**: - - 删除 `serialNumber` 字段 - - 添加 `deviceCode` 字段 -- **Device**: - - 添加 `deviceCode` 字段 -- **CreateDeviceResponse**: - - 添加 `deviceCode` 字段 -- **UpdateDeviceResponse**: - - 添加 `deviceCode` 字段 - -#### 4. 前端表单修改 -- **DeviceForm**: - - 删除序列号输入字段 - - 添加设备编码输入字段 - - 更新表单状态管理 - -#### 5. 服务注册修改 -- **ServiceCollectionExtensions**: - - 注册 `IBaseInstrumentClient` 服务 - - 注册 `IInstrumentHttpClient` 服务 - - 使用 `InstrumentProtocolClient` 作为实现类 - -#### 6. 前端页面修改 -- **DevicesView**: - - 更新编辑设备时的初始数据传递 - - 移除对序列号字段的引用 - -### 技术特性 -- **自动序列号获取**:通过设备的IP地址和端口自动获取序列号 -- **错误处理**:当无法获取序列号时提供友好的错误信息 -- **服务集成**:集成 `IBaseInstrumentClient` 服务进行设备通信 -- **类型安全**:更新所有相关的TypeScript接口定义 - -### 业务价值 -- **用户体验**:用户无需手动输入序列号,减少输入错误 -- **数据准确性**:序列号直接从设备获取,确保数据准确性 -- **自动化**:简化设备创建流程,提高效率 -- **一致性**:确保序列号与设备实际状态一致 - -### 影响范围 -- **创建操作**:设备创建时自动获取序列号 -- **更新操作**:设备更新时保持序列号不变 -- **前端界面**:移除序列号输入字段,添加设备编码字段 -- **API接口**:更新请求和响应模型 -- **错误处理**:添加序列号获取失败的处理逻辑 -- **服务注册**:注册设备通信相关服务 - -### 依赖服务 -- `IBaseInstrumentClient`:用于与设备通信获取序列号 -- `ServiceEndpoint`:配置设备连接信息 -- `GetDeviceSerialNumberAsync`:获取设备序列号的方法 - -### 注意事项 -- 设备必须能够通过HTTP协议访问 -- 设备需要提供 `/System/serial-number` 接口 -- 网络连接必须正常才能获取序列号 -- 如果获取失败,会返回相应的错误信息 - -## 2025-01-29 网络栈配置仓储方法重构 - -**修改时间**: 2025年1月29日 -**修改文件**: -- `X1.Domain/Repositories/NetworkProfile/INetworkStackConfigRepository.cs` -- `X1.Infrastructure/Repositories/NetworkProfile/NetworkStackConfigRepository.cs` - -**修改内容**: -1. 重命名方法 `GetNetworkStackConfigByNetworkStackCodeWithBindingNamesAsync` → `GetNetworkStackConfigsByCodesAsync` -2. 修复 `GetNetworkStackConfigsByCodesAsync` 方法,添加 `ran.ConfigContent`、`cnc.ConfigContent`、`ims.ConfigContent` 字段 -3. 扩展 `NetworkStackConfigWithBindingNamesDto` DTO,添加配置内容字段 -4. 同步修复相关方法:`GetNetworkStackConfigByIdWithBindingNamesAsync` 和 `SearchNetworkStackConfigsWithBindingNamesAsync` - -### 技术细节 -- **DTO扩展**:添加 `RanConfigContent`、`CoreNetworkConfigContent`、`IMSConfigContent` 字段 -- **SQL查询优化**:在LEFT JOIN查询中添加配置内容字段的选择 -- **方法同步**:确保所有相关方法都返回完整的配置内容信息 -- **数据完整性**:确保网络栈配置查询结果包含所有相关的配置内容 - -## 2025-01-29 创建NetworkStackConfigBasicDto - -**修改时间**: 2025年1月29日 -**修改文件**: -- `X1.Domain/Models/NetworkStackConfigBasicDto.cs` (新增) - -**修改内容**: -1. 创建新的DTO类 `NetworkStackConfigBasicDto`,包含指定的字段子集: - - `NetworkStackName` - 网络栈名称 - - `NetworkStackCode` - 网络栈代码 - - `RanId` - RAN配置ID - - `CoreNetworkConfigId` - 核心网配置ID - - `IMSConfigId` - IMS配置ID - - `RanConfigContent` - RAN配置内容 - - `CoreNetworkConfigContent` - 核心网配置内容 - - `IMSConfigContent` - IMS配置内容 - -### 技术特性 -- **字段精简**:只包含用户指定的核心字段 -- **配置内容**:包含所有相关的配置内容字段 -- **类型安全**:完整的C#属性定义和XML文档注释 -- **命名规范**:遵循C#命名规范和项目约定 - -## 2025-01-29 修改GetNetworkStackConfigsByCodesAsync方法返回NetworkStackConfigBasicDto - -**修改时间**: 2025年1月29日 -**修改文件**: -- `X1.Domain/Repositories/NetworkProfile/INetworkStackConfigRepository.cs` - 更新接口方法签名 -- `X1.Infrastructure/Repositories/NetworkProfile/NetworkStackConfigRepository.cs` - 更新实现方法 - -**修改内容**: -1. **接口更新**: - - 将 `GetNetworkStackConfigsByCodesAsync` 方法的返回类型从 `IList` 改为 `IList` - - 更新方法注释,说明返回核心字段和配置内容 - -2. **实现更新**: - - 更新方法签名以匹配接口 - - 修改SQL查询,只选择 `NetworkStackConfigBasicDto` 需要的字段: - - `nsc."NetworkStackName"` - - `nsc."NetworkStackCode"` - - `nsc."RanId"` - - `cnc."Id"` (别名: `CoreNetworkConfigId`) - - `ims."Id"` (别名: `IMSConfigId`) - - `ran."ConfigContent"` (别名: `RanConfigContent`) - - `cnc."ConfigContent"` (别名: `CoreNetworkConfigContent`) - - `ims."ConfigContent"` (别名: `IMSConfigContent`) - - 移除不需要的字段:ID、描述、状态、时间戳、创建者等 - - 更新查询结果映射,使用 `NetworkStackConfigBasicDto` 类型 - -### 技术特性 -- **字段精简**:只返回用户指定的核心字段 -- **性能优化**:减少数据传输量,提高查询性能 -- **类型安全**:确保返回数据与DTO定义完全匹配 -- **向后兼容**:方法签名保持兼容,只改变返回类型 - -### 业务价值 -- **数据精确性**:只返回业务需要的核心字段 -- **网络效率**:减少不必要的数据传输 -- **接口清晰**:明确指定返回的数据结构 -- **维护便利**:简化数据结构,便于维护 - -### 影响范围 -- **API响应**:返回的数据结构更加精简 -- **查询性能**:减少字段选择,提高查询效率 -- **客户端处理**:客户端需要更新以处理新的数据结构 -- **数据完整性**:确保返回的数据包含所有必要的核心信息 - -## 2025-01-29 修改GetNetworkStackConfigsByCodesAsync方法参数类型 - -**修改时间**: 2025年1月29日 -**修改文件**: -- `X1.Domain/Repositories/NetworkProfile/INetworkStackConfigRepository.cs` - 更新接口方法签名 -- `X1.Infrastructure/Repositories/NetworkProfile/NetworkStackConfigRepository.cs` - 更新实现方法 - -**修改内容**: -1. **接口更新**: - - 修改参数类型从 `string NetworkStackCode` 改为 `string[] networkStackCodes` - - 更新方法注释,说明支持批量查询多个网络栈编码 - -2. **实现更新**: - - 更新方法签名以匹配接口 - - 修改SQL查询,使用动态构建的IN查询替代单一条件查询 - - 添加空数组检查逻辑 - - 优化排序逻辑,按网络栈编码和绑定索引排序 - -**修改原因**: -- 原方法名称过长,不符合命名规范 -- 支持批量查询多个网络栈编码,提高查询效率 -- 改善代码可读性和维护性 - -**影响范围**: -- 需要更新所有调用此方法的代码 -- 接口签名变更,需要重新编译相关项目 - -## 2025-07-28 - 修复endpointManager重新添加时机bug - -### 修改原因 -在获取设备序列号成功后,原来的代码立即重新添加了服务端点,但此时设备数据还没有保存到数据库。这可能导致服务端点与数据库中的设备数据不一致的问题。 - -### 修改文件 -- `X1.Application/Features/Devices/Commands/CreateDevice/CreateDeviceCommandHandler.cs` - 修复endpointManager重新添加时机 - -### 修改内容 - -#### 1. GetDeviceSerialNumberAsync方法修改 -- **移除立即重新添加逻辑**: - - 在获取序列号成功后,只移除临时服务端点 - - 不再立即重新添加服务端点 - - 确保临时端点被正确清理 - -#### 2. CreateAndSaveDeviceAsync方法修改 -- **添加延迟重新添加逻辑**: - - 在设备成功保存到数据库后,重新添加服务端点 - - 使用设备编号(deviceCode)作为端点名称 - - 确保服务端点与数据库中的设备数据一致 - -### 技术特性 -- **正确的执行顺序**:先保存数据,再添加服务端点 -- **数据一致性**:确保服务端点与设备数据的一致性 -- **错误处理**:如果设备保存失败,不会添加服务端点 -- **日志记录**:详细记录服务端点的添加过程 - -### 业务价值 -- **数据完整性**:确保服务端点与设备数据的一致性 -- **系统稳定性**:避免因数据不一致导致的问题 -- **可维护性**:清晰的执行流程便于调试和维护 - -### 影响范围 -- **创建流程**:修改了设备创建时的endpointManager管理逻辑 -- **数据一致性**:确保服务端点与设备数据同步 -- **错误处理**:改进了异常情况下的资源清理 - -### 执行流程 -1. **获取序列号**:使用临时服务端点获取设备序列号 -2. **清理临时端点**:移除临时服务端点 -3. **保存设备数据**:将设备信息保存到数据库 -4. **添加正式端点**:使用设备编号作为名称添加正式服务端点 - -### 注意事项 -- 临时服务端点使用时间戳生成名称,避免冲突 -- 正式服务端点使用设备编号作为名称,便于管理 -- 只有在设备数据保存成功后才会添加正式服务端点 - -## 2025-07-28 - 修复设备编号生成逻辑,从000开始 - -### 修改原因 -根据用户需求,设备编号应该从000开始,类似001、002的格式,而不是从1开始。 - -### 修改文件 -- `X1.Application/Features/Devices/Commands/CreateDevice/CreateDeviceCommandHandler.cs` - 修改CalculateRequiredDigits方法和GenerateDeviceCodeAsync方法 - -### 修改内容 - -#### 1. CalculateRequiredDigits方法修改 -- **最小位数设置**:将最小位数从1改为3,确保从000开始 -- **逻辑优化**:使用 `Math.Max(calculatedDigits, 3)` 确保至少3位数 -- **注释更新**:更新注释说明从000开始,至少3位数 - -#### 2. GenerateDeviceCodeAsync方法修改 -- **注释更新**:更新注释说明从000开始,确保至少3位数 -- **格式说明**:更新设备编号格式说明为 DEV-000-SN, DEV-001-SN, DEV-002-SN 等 - -### 技术特性 -- **从000开始**:设备编号从DEV-000-SN开始,而不是DEV-1-SN -- **至少3位数**:确保序号至少有3位数字,格式统一 -- **动态扩展**:当设备数量超过999时,自动扩展为4位数(1000、1001等) -- **格式一致**:所有设备编号都遵循统一的格式规范 - -### 业务价值 -- **格式规范**:统一的设备编号格式,便于管理和识别 -- **用户友好**:从000开始的编号更符合用户习惯 -- **可扩展性**:支持大量设备的编号需求 -- **一致性**:所有设备编号都遵循相同的格式规则 - -### 设备编号格式示例 -- 第1个设备:DEV-000-SN -- 第2个设备:DEV-001-SN -- 第3个设备:DEV-002-SN -- ... -- 第1000个设备:DEV-1000-SN -- 第1001个设备:DEV-1001-SN - -### 影响范围 -- **设备创建**:新创建的设备将使用从000开始的编号格式 -- **编号生成**:设备编号生成逻辑已更新 -- **格式统一**:所有设备编号都遵循新的格式规范 - -### 注意事项 -- 现有设备的编号不会自动更新 -- 新创建的设备将使用新的编号格式 -- 编号格式支持扩展到更多位数(当设备数量超过999时) - -## 2025-07-28 - 优化临时服务端点名称生成,使用GUID替代时间戳 - -### 修改原因 -使用时间戳生成临时服务端点名称可能存在冲突风险,特别是在高并发场景下。使用GUID可以确保端点名称的唯一性。 - -### 修改文件 -- `X1.Application/Features/Devices/Commands/CreateDevice/CreateDeviceCommandHandler.cs` - 修改CreateServiceEndpoint方法 - -### 修改内容 - -#### 1. CreateServiceEndpoint方法修改 -- **名称生成方式**:从时间戳改为GUID -- **格式变更**:`DEV-{DateTime.Now:yyyyMMddHHmmss}` → `DEV-{Guid.NewGuid():N}` -- **唯一性保证**:GUID确保每个临时端点名称都是唯一的 - -### 技术特性 -- **唯一性保证**:GUID提供全局唯一性,避免名称冲突 -- **并发安全**:在高并发场景下不会出现重复名称 -- **格式简洁**:使用 `:N` 格式去除GUID中的连字符,生成32位字符串 -- **性能优化**:GUID生成比时间戳更高效 - -### 业务价值 -- **系统稳定性**:避免因端点名称冲突导致的问题 -- **并发支持**:支持多用户同时创建设备 -- **可靠性提升**:确保每个临时端点都能正确创建和管理 - -### 临时端点名称示例 -- 修改前:`DEV-20250728143022` -- 修改后:`DEV-a1b2c3d4e5f678901234567890123456` - -### 影响范围 -- **临时端点创建**:临时服务端点名称生成方式已更新 -- **并发处理**:支持更好的并发创建设备场景 -- **系统稳定性**:提高了端点管理的可靠性 - -## 2025-07-28 - 移除设备表单中的启用和启动复选框 - -### 修改原因 -根据用户需求,设备表单中不需要显示"启用设备"和"启动设备"这两个复选框,这些状态应该通过其他方式管理。 - -### 修改文件 -- `X1.WebUI/src/pages/instruments/DeviceForm.tsx` - 移除启用和启动复选框 - -### 修改内容 - -#### 1. 表单状态管理修改 -- **初始状态设置**: - - `isEnabled` 默认设置为 `true` - - `isRunning` 默认设置为 `false` - - 这些值不再从 `initialData` 中获取 - -#### 2. 表单界面修改 -- **移除复选框组件**: - - 删除"启用设备"复选框及其相关代码 - - 删除"启动设备"复选框及其相关代码 - - 保留其他表单字段不变 - -#### 3. 表单提交逻辑 -- **创建模式**:提交所有字段,包括默认的启用和启动状态 -- **编辑模式**:只提交可修改的字段,启用和启动状态保持默认值 - -### 技术特性 -- **默认状态**:设备创建时默认启用,默认不启动 -- **界面简化**:移除不必要的复选框,简化用户界面 -- **状态管理**:启用和启动状态通过默认值管理 -- **功能保持**:其他表单功能保持不变 - -### 业务价值 -- **用户体验**:简化设备创建和编辑界面 -- **操作简化**:减少用户需要选择的选项 -- **界面清晰**:专注于设备的基本信息配置 -- **一致性**:所有设备使用统一的默认状态 - -### 影响范围 -- **设备创建**:新设备默认启用,默认不启动 -- **设备编辑**:编辑时不再显示启用和启动选项 -- **界面布局**:表单界面更加简洁 -- **状态管理**:启用和启动状态通过系统默认值管理 - -### 注意事项 -- 设备创建后默认启用状态为true -- 设备创建后默认启动状态为false -- 用户无法通过表单界面修改这些状态 -- 如果需要修改这些状态,需要通过其他方式(如设备管理列表) - -### 技术特性 -- **简化设计**:移除冗余字段,减少数据重复 -- **统一状态管理**:使用单一的 `RuntimeStatus` 枚举管理所有运行时状态 -- **启用状态管理**:独立的 `IsEnabled` 字段管理设备启用状态 -- **时间推断**:通过 `UpdatedAt` 字段推断设备最后活动时间 - -### 业务价值 -- **概念清晰**:消除 `IsRunning` 和 `ConnectionStatus` 的概念重叠 -- **状态统一**:使用统一的 `DeviceRuntimeStatus` 枚举管理所有状态 -- **设计简化**:减少字段数量,降低复杂度 -- **维护便利**:避免状态不同步问题,提高系统稳定性 - -### 状态管理逻辑 -- **设备在线**:`RuntimeStatus = Running`,`UpdatedAt` 反映最后活动时间 -- **设备离线**:`RuntimeStatus = Stopped` 或 `Error` -- **设备禁用**:`IsEnabled = false` -- **心跳检测**:通过 `UpdatedAt` 和 `RuntimeStatus` 判断设备状态 - -### 影响范围 -- **数据库结构**:移除 `LastHeartbeat` 字段,更新相关索引 -- **实体模型**:简化 `CellularDeviceRuntime` 实体结构 -- **状态管理**:统一使用 `DeviceRuntimeStatus` 枚举 -- **查询逻辑**:更新所有相关的查询方法 -- **业务逻辑**:简化状态管理逻辑,提高系统稳定性 - -### 后续工作建议 -1. **数据库迁移**:创建迁移移除 `LastHeartbeat` 字段 -2. **API更新**:更新相关的API接口以支持新的状态管理 -3. **前端更新**:更新前端界面以使用新的状态字段 -4. **测试验证**:全面测试新的状态管理功能 -5. **文档更新**:更新相关文档说明新的状态管理逻辑 - -## 2025-01-29 连表获取CellularDeviceRuntime的RuntimeStatus字段 - -### 修改原因 -根据用户需求,在获取设备列表时需要同时获取设备的运行时状态信息,通过连表查询 `CellularDeviceRuntime` 表获取 `RuntimeStatus` 字段。 - -### 修改文件 - -#### 1. 仓储接口修改 -- `X1.Domain/Repositories/Device/ICellularDeviceRepository.cs` - 添加 `SearchDevicesWithRuntimeAsync` 方法 - -#### 2. 仓储实现修改 -- `X1.Infrastructure/Repositories/Device/CellularDeviceRepository.cs` - 实现 `SearchDevicesWithRuntimeAsync` 方法,使用左连接查询 - -#### 3. 响应模型修改 -- `X1.Application/Features/Devices/Queries/GetDeviceById/GetDeviceByIdResponse.cs` - 添加 `RuntimeStatus` 字段 - -#### 4. 查询处理器修改 -- `X1.Application/Features/Devices/Queries/GetDevices/GetDevicesQueryHandler.cs` - 使用新的连表查询方法 - -### 修改内容 - -#### 1. 新增仓储方法 -- **SearchDevicesWithRuntimeAsync**: - - 支持分页查询设备列表 - - 使用 `Include(d => d.Runtime)` 进行左连接查询 - - 返回设备信息和对应的运行时状态信息 - - 支持关键词搜索功能 - -#### 2. 响应模型扩展 -- **GetDeviceByIdResponse**: - - 添加 `RuntimeStatus` 字段,类型为 `int` - - 当设备没有运行时状态时返回 `-1`(表示未知状态) - - 当设备有运行时状态时返回枚举值的整数表示 - -#### 3. 查询逻辑优化 -- **GetDevicesQueryHandler**: - - 使用 `SearchDevicesWithRuntimeAsync` 替代原有的 `SearchDevicesAsync` - - 在构建响应时映射运行时状态信息 - - 保持原有的分页和搜索功能 - -### 技术实现 - -#### 1. 数据库查询优化 -- 使用 Entity Framework 的 `Include` 方法进行左连接 -- 通过 `DeviceCode` 外键关联 `CellularDevice` 和 `CellularDeviceRuntime` 表 -- 保持查询性能,避免 N+1 查询问题 - -#### 2. 数据映射 -- 使用元组 `(CellularDevice Device, CellularDeviceRuntime? Runtime)` 返回查询结果 -- 在应用层进行数据映射,将运行时状态转换为整数 -- 处理空值情况,确保 API 响应的一致性 - -#### 3. 向后兼容 -- 保持原有接口的兼容性 -- 新增字段为必填字段,类型为 `int` -- 运行时状态为空时返回 `-1`(表示未知状态),客户端可以安全处理 - -### 影响范围 -- **API 响应**:设备列表接口现在包含运行时状态信息 -- **前端显示**:可以显示设备的当前运行状态 -- **性能影响**:轻微的性能提升,因为减少了额外的查询请求 -- **数据一致性**:确保设备状态信息的实时性 - -## 2025-01-29 修复设备搜索和获取方法,添加DeviceCode搜索支持和运行时状态 - -### 修改原因 -1. 设备搜索方法中缺少对 `DeviceCode` 字段的搜索支持 -2. `GetDeviceById` 查询处理器需要获取设备的运行时状态信息 -3. 确保所有设备相关的查询都能正确使用导航属性 - -### 修改文件 - -#### 1. 仓储接口修改 -- `X1.Domain/Repositories/Device/ICellularDeviceRepository.cs` - 添加 `GetDeviceByIdWithRuntimeAsync` 方法 - -#### 2. 仓储实现修改 -- `X1.Infrastructure/Repositories/Device/CellularDeviceRepository.cs` - 修复搜索方法并添加新的获取方法 - -#### 3. 查询处理器修改 -- `X1.Application/Features/Devices/Queries/GetDeviceById/GetDeviceByIdQueryHandler.cs` - 使用包含运行时状态的查询方法 - -### 修改内容 - -#### 1. 搜索方法优化 -- **SearchDevicesAsync**(两个重载版本): - - 在搜索条件中添加 `d.DeviceCode.Contains(keyword)` 支持 - - 现在支持按设备编码进行搜索 - -- **SearchDevicesWithRuntimeAsync**: - - 在搜索条件中添加 `d.DeviceCode.Contains(keyword)` 支持 - - 确保连表查询时也能按设备编码搜索 - -#### 2. 新增获取方法 -- **GetDeviceByIdWithRuntimeAsync**: - - 根据ID获取设备信息,包含运行时状态 - - 使用 `Include(d => d.Runtime)` 进行左连接查询 - - 返回完整的设备信息,包括运行时状态 - -#### 3. 查询处理器更新 -- **GetDeviceByIdQueryHandler**: - - 使用 `GetDeviceByIdWithRuntimeAsync` 替代 `GetDeviceByIdAsync` - - 在响应中包含 `RuntimeStatus` 字段 - - 当设备没有运行时状态时返回 `-1`(表示未知状态) - -### 技术实现 - -#### 1. 搜索条件完善 -```csharp -predicate = d => d.Name.Contains(keyword) || - d.SerialNumber.Contains(keyword) || - d.DeviceCode.Contains(keyword) || // 新增 - d.Description.Contains(keyword); -``` - -#### 2. 导航属性查询 -```csharp -return await QueryRepository.FirstOrDefaultAsync( - d => d.Id == id, - include: q => q.Include(d => d.Runtime), - cancellationToken: cancellationToken); -``` - -#### 3. 运行时状态映射 -```csharp -RuntimeStatus = device.Runtime?.RuntimeStatus != null ? (int)device.Runtime.RuntimeStatus : -1 -``` - -### 影响范围 -- **搜索功能**:现在支持按设备编码搜索设备 -- **API 响应**:单个设备查询接口现在包含运行时状态信息 -- **数据一致性**:确保所有设备查询都能正确获取关联的运行时状态 -- **用户体验**:提供更完整的设备信息,包括实时运行状态 - -### 业务价值 -- **搜索增强**:用户可以通过设备编码快速找到特定设备 -- **状态可见性**:单个设备详情页面显示实时运行状态 -- **数据完整性**:确保设备信息的完整性和一致性 -- **系统健壮性**:正确处理导航属性和关联数据 - -## 2025-01-29 简化DeviceRuntimeDto,只保留必要字段 - -### 修改原因 -根据用户需求,简化 `DeviceRuntimeDto` 类,只保留必要的字段: -- DeviceCode(设备编号) -- RuntimeStatus(运行时状态,使用int类型) -- NetworkStackCode(网络栈配置编号) -- Name(设备名称) -- CreatedAt(创建时间) - -### 修改文件 - -#### 1. 响应模型修改 -- `X1.Application/Features/DeviceRuntimes/Queries/GetDeviceRuntimes/GetDeviceRuntimesResponse.cs` - 简化 `DeviceRuntimeDto` 类 - -#### 2. 查询处理器修改 -- `X1.Application/Features/DeviceRuntimes/Queries/GetDeviceRuntimes/GetDeviceRuntimesQueryHandler.cs` - 更新 `MapToDto` 方法 - -### 修改内容 - -#### 1. DeviceRuntimeDto 简化 -**移除的字段**: -- Id(运行时状态ID) -- RuntimeCode(运行编码) -- UpdatedAt(更新时间) -- Device(设备信息对象) - -**保留的字段**: -- DeviceCode(设备编号) -- RuntimeStatus(运行时状态,改为int类型) -- NetworkStackCode(网络栈配置编号) -- Name(设备名称,新增) -- CreatedAt(创建时间) - -#### 2. MapToDto 方法优化 -```csharp -private static DeviceRuntimeDto MapToDto(CellularDeviceRuntime runtime) -{ - return new DeviceRuntimeDto - { - DeviceCode = runtime.DeviceCode, - RuntimeStatus = (int)runtime.RuntimeStatus, - NetworkStackCode = runtime.NetworkStackCode, - Name = runtime.Device?.Name, - CreatedAt = runtime.CreatedAt - }; -} -``` - -### 技术实现 - -#### 1. 类型转换 -- `RuntimeStatus` 从 `string` 改为 `int`,直接使用枚举的整数值 -- 使用 `runtime.Device?.Name` 安全访问设备名称 - -#### 2. 数据简化 -- 移除了复杂的嵌套对象 `DeviceInfoDto` -- 只保留最核心的运行时状态信息 -- 减少了数据传输量,提高API响应性能 - -### 影响范围 -- **API 响应**:设备运行时状态列表接口返回更简洁的数据结构 -- **前端处理**:前端可以更直接地使用运行时状态信息 -- **性能优化**:减少了不必要的数据传输,提高响应速度 -- **数据一致性**:确保返回的数据结构简洁明了 - -### 业务价值 -- **数据精简**:只返回业务必需的核心字段 -- **类型统一**:RuntimeStatus使用int类型,便于前端处理 -- **性能提升**:减少数据传输量,提高API响应速度 -- **维护便利**:简化数据结构,降低维护复杂度 - -## 2025-01-29 为CellularDeviceRuntimeDetail实体添加DeviceCode和NetworkStackCode字段 - -### 修改原因 -根据用户需求,`CellularDeviceRuntimeDetail` 实体需要添加 `DeviceCode` 和 `NetworkStackCode` 字段,用于标识该运行时明细记录属于哪个设备以及使用的网络栈配置。 - -### 修改文件 -- `X1.Domain/Entities/Device/CellularDeviceRuntimeDetail.cs` - 添加DeviceCode和NetworkStackCode字段 - -### 修改内容 - -#### 1. 添加DeviceCode属性 -- **字段名称**:`DeviceCode` -- **字段类型**:`string` -- **约束条件**: - - `[Required]` - 必填字段 - - `[MaxLength(50)]` - 最大长度50个字符 -- **访问修饰符**:`private set` - 只读属性,通过方法修改 -- **位置**:在 `RuntimeCode` 字段之前 - -#### 2. 添加NetworkStackCode属性 -- **字段名称**:`NetworkStackCode` -- **字段类型**:`string` -- **约束条件**: - - `[Required]` - 必填字段 - - `[MaxLength(50)]` - 最大长度50个字符 -- **访问修饰符**:`private set` - 只读属性,通过方法修改 -- **位置**:在 `RuntimeCode` 字段之后 - -#### 3. 更新Create方法 -- **方法签名**:`Create` 方法添加 `deviceCode` 和 `networkStackCode` 参数 -- **参数位置**:`deviceCode` 在 `runtimeCode` 参数之前,`networkStackCode` 在 `runtimeCode` 参数之后 -- **参数验证**:通过 `[Required]` 和 `[MaxLength(50)]` 进行验证 -- **属性赋值**:在创建明细记录时设置 `DeviceCode` 和 `NetworkStackCode` 属性 - -### 技术特性 -- **数据完整性**:设备编码和网络栈配置编号作为必填字段,确保每个运行时明细记录都能关联到具体设备和网络栈配置 -- **长度限制**:最大50个字符,适合各种编码格式 -- **封装性**:使用私有setter,确保数据只能通过方法修改 -- **一致性**:与现有字段保持相同的设计模式 - -### 业务价值 -- **设备关联**:通过设备编码关联运行时明细记录与具体设备 -- **网络栈关联**:通过网络栈配置编号关联运行时明细记录与网络栈配置 -- **数据追溯**:增强运行时明细数据的可追溯性 -- **查询便利**:支持按设备编码和网络栈配置编号查询相关的运行时明细记录 -- **管理便利**:提供更灵活的设备运行时明细管理方式 - -### 影响范围 -- **实体模型**:CellularDeviceRuntimeDetail实体增加了DeviceCode和NetworkStackCode字段 -- **创建操作**:所有创建运行时明细记录的操作都需要提供设备编码和网络栈配置编号 -- **数据验证**:确保设备编码和网络栈配置编号的完整性和有效性 -- **查询逻辑**:支持按设备编码和网络栈配置编号查询运行时明细记录 - -### 后续工作建议 -1. **数据库迁移**:需要创建数据库迁移来添加DeviceCode和NetworkStackCode字段 -2. **仓储更新**:更新相关的仓储方法以支持设备编码和网络栈配置编号字段 -3. **API更新**:更新相关的API接口以支持设备编码和网络栈配置编号字段 -4. **前端界面**:更新前端界面以显示和编辑设备编码和网络栈配置编号 -5. **测试用例**:为设备编码和网络栈配置编号字段添加相应的测试用例 - -## 2025-01-29 调整设备运行时管理路由位置并更新权限配置 - -### 修改原因 -根据用户需求,将设备运行时管理路由从独立路由调整为放在 `instruments` 路由内部,与 `list` 同一层级,同时更新相关的权限配置。 - -### 修改文件 - -#### 1. 路由配置调整 -- `X1.WebUI/src/routes/AppRouter.tsx` - 将设备运行时管理路由移动到 instruments 路由内部 - -#### 2. 菜单配置调整 -- `X1.WebUI/src/constants/menuConfig.ts` - 将设备运行时管理菜单项移动到仪表管理下面 - -#### 3. 权限配置更新 -- `X1.WebUI/src/contexts/AuthContext.tsx` - 在 getDefaultPermissions 函数中添加设备运行时管理权限 - -### 修改内容 - -#### 1. 路由结构调整 -- **原路由结构**: - ``` - /dashboard/device-runtimes/list - /dashboard/device-runtimes/detail/:deviceCode - ``` -- **新路由结构**: - ``` - /dashboard/instruments/device-runtimes/list - /dashboard/instruments/device-runtimes/detail/:deviceCode - ``` - -#### 2. 菜单结构调整 -- **原菜单结构**:设备运行时作为独立顶级菜单项 -- **新菜单结构**:设备运行时作为仪表管理的子菜单项 -- **菜单路径更新**:`/dashboard/device-runtimes/list` → `/dashboard/instruments/device-runtimes/list` - -#### 3. 权限配置更新 -- **新增权限**: - - `deviceruntimes.view` - 查看设备运行时权限 - - `deviceruntimes.manage` - 管理设备运行时权限 -- **权限位置**:添加到 `getDefaultPermissions` 函数中,确保用户登录后能够正确获取设备运行时管理权限 - -### 技术特性 -- **路由嵌套**:设备运行时管理现在嵌套在 instruments 路由下 -- **权限继承**:设备运行时管理继承仪表管理的基础权限结构 -- **菜单层次**:清晰的菜单层次结构,设备运行时管理属于仪表管理范畴 -- **向后兼容**:保持所有现有功能不变,只是调整了路由和菜单结构 - -### 业务价值 -- **逻辑分组**:将设备运行时管理归类到仪表管理下,符合业务逻辑 -- **用户体验**:更清晰的菜单结构,用户更容易找到相关功能 -- **权限管理**:统一的权限管理结构,便于权限分配和管理 -- **系统一致性**:保持系统整体架构的一致性 - -### 影响范围 -- **路由访问**:设备运行时管理页面的访问路径发生变化 -- **菜单导航**:用户需要通过仪表管理菜单访问设备运行时管理 -- **权限控制**:设备运行时管理权限已正确配置 -- **用户体验**:更符合用户预期的菜单结构 - -### 使用方式 -1. 用户登录后,在左侧菜单中点击"仪表管理" -2. 在仪表管理子菜单中点击"运行时状态" -3. 进入设备运行时管理页面:`/dashboard/instruments/device-runtimes/list` -4. 点击设备编号可查看详情:`/dashboard/instruments/device-runtimes/detail/:deviceCode` - -### 注意事项 -- 原有的直接访问路径 `/dashboard/device-runtimes/*` 已失效 -- 需要更新任何硬编码的链接或书签 -- 权限检查仍然正常工作,确保安全性 -- 所有设备运行时管理功能保持不变 - -## 2025-01-29 修复 device-runtimes 界面组件和依赖问题 - -### 修改原因 -修复 device-runtimes 界面中缺失的组件和依赖问题,确保界面能够正常运行。 - -### 新增文件 - -#### 1. UI 组件 -- `X1.WebUI/src/components/ui/card.tsx` - 创建 card 组件,包含 Card、CardHeader、CardTitle、CardContent、CardFooter 等子组件 -- `X1.WebUI/src/components/ui/separator.tsx` - 创建 separator 组件,基于 @radix-ui/react-separator -- `X1.WebUI/src/components/ui/dropdown-menu.tsx` - 创建 dropdown-menu 组件,包含完整的下拉菜单功能 - -### 修改文件 - -#### 1. Dialog 组件扩展 -- `X1.WebUI/src/components/ui/dialog.tsx` - 添加 DialogHeader 组件导出 - -#### 2. 设备运行时表格组件 -- `X1.WebUI/src/pages/device-runtimes/DeviceRuntimesTable.tsx` - 修复图标导入,将 MoreHorizontalIcon 改为 DotsHorizontalIcon - -#### 3. 设备运行时视图组件 -- `X1.WebUI/src/pages/device-runtimes/DeviceRuntimesView.tsx` - 修复服务方法调用,使用 deviceRuntimeService 实例方法 - -### 修复内容 - -#### 1. 组件创建 -- **Card 组件**:提供卡片布局功能,支持标题、内容、页脚等区域 -- **Separator 组件**:提供分隔线功能,支持水平和垂直方向 -- **Dropdown Menu 组件**:提供下拉菜单功能,支持菜单项、复选框、单选按钮等 - -#### 2. 图标修复 -- **图标名称修正**:将不存在的 MoreHorizontalIcon 改为正确的 DotsHorizontalIcon -- **导入修复**:确保所有图标都能正确导入和使用 - -#### 3. 服务调用修复 -- **方法调用修正**:将直接函数调用改为使用 deviceRuntimeService 实例方法 -- **导入清理**:移除不存在的函数导入,只保留类型和服务实例 - -### 技术特性 - -#### 1. 组件设计 -- **类型安全**:所有组件都使用 TypeScript 类型定义 -- **可访问性**:遵循 ARIA 标准,支持屏幕阅读器 -- **响应式**:支持不同屏幕尺寸的响应式布局 -- **主题支持**:支持深色/浅色主题切换 - -#### 2. 图标系统 -- **Radix UI 图标**:使用 @radix-ui/react-icons 提供的图标 -- **一致性**:确保图标名称与库中实际存在的图标一致 -- **可扩展性**:支持添加更多图标 - -#### 3. 服务架构 -- **实例方法**:使用服务实例的方法而不是独立函数 -- **类型安全**:完整的 TypeScript 类型支持 -- **错误处理**:统一的错误处理机制 - -### 影响范围 -- **UI 组件**:新增了三个重要的 UI 组件 -- **图标系统**:修复了图标导入问题 -- **服务调用**:统一了服务调用方式 -- **开发体验**:提供了更好的类型安全和代码提示 - -### 后续工作建议 -1. **组件测试**:为新创建的组件添加单元测试 -2. **文档编写**:为组件添加使用文档和示例 -3. **主题优化**:进一步完善主题支持 -4. **性能优化**:优化组件的渲染性能 - -## 2025-01-29 修复 Select 组件空值错误 - -### 修改原因 -修复 Select 组件中空值选项导致的错误:"A must have a value prop that is not an empty string"。 - -### 修改文件 -- `X1.WebUI/src/pages/device-runtimes/DeviceRuntimesView.tsx` - 修复运行时状态选择器的空值问题 - -### 修改内容 - -#### 1. 选项值修复 -- **空值选项**:将 `{ value: '', label: '全部状态' }` 改为 `{ value: 'all', label: '全部状态' }` -- **SelectItem 修复**:将 `全部状态` 改为 `全部状态` - -#### 2. 值处理逻辑修复 -- **默认值**:将 `value={runtimeStatus?.toString() || ''}` 改为 `value={runtimeStatus?.toString() || 'all'}` -- **值变化处理**:将 `onValueChange={(value) => setRuntimeStatus(value ? parseInt(value) : undefined)}` 改为 `onValueChange={(value) => setRuntimeStatus(value === 'all' ? undefined : parseInt(value))}` - -### 技术说明 -- **Radix UI 限制**:Radix UI 的 Select 组件不允许空字符串作为选项值 -- **特殊值处理**:使用 'all' 作为特殊值表示"全部状态" -- **逻辑转换**:在值变化时将 'all' 转换为 undefined,保持业务逻辑不变 - -### 影响范围 -- **用户界面**:Select 组件现在可以正常工作,不再报错 -- **业务逻辑**:功能保持不变,只是内部值处理方式调整 -- **用户体验**:界面更加稳定,不会出现错误提示 - -## 2025-01-29 修复 deviceRuntimeService 方法绑定问题 - -### 修改原因 -修复 `deviceRuntimeService` 中方法调用时的 `this` 上下文丢失问题,导致 `getRuntimeStatusString` 方法无法正确访问。 - -### 修改文件 -- `X1.WebUI/src/services/deviceRuntimeService.ts` - 修复方法绑定问题 - -### 修改内容 - -#### 1. 方法定义修复 -- **箭头函数**:将 `getRuntimeStatusDescription` 和 `getRuntimeStatusColor` 方法改为箭头函数 -- **this 绑定**:确保方法在传递时保持正确的 `this` 上下文 -- **方法顺序**:将 `getRuntimeStatusString` 方法移到前面,确保在调用前已定义 - -#### 2. 技术改进 -- **上下文保持**:使用箭头函数确保 `this` 始终指向 `DeviceRuntimeService` 实例 -- **方法传递**:支持将方法作为函数参数传递给其他组件 -- **错误修复**:解决 "Cannot read properties of undefined" 错误 - -### 技术说明 -- **问题原因**:当方法被作为函数传递时,`this` 上下文会丢失 -- **解决方案**:使用箭头函数确保 `this` 绑定到类实例 -- **性能影响**:箭头函数在实例化时创建,但避免了运行时绑定问题 - -### 影响范围 -- **错误修复**:解决了运行时状态描述和颜色获取的错误 -- **功能恢复**:设备运行时状态显示功能正常工作 -- **代码稳定性**:提高了方法调用的可靠性 - -## 2025-01-29 - 修复设备运行时表格单元格居中对齐问题 - -### 修改原因 -设备运行时表格的单元格内容没有居中对齐,与其他表格组件的显示效果不一致,影响用户体验。 - -### 修改文件 -- `X1.WebUI/src/pages/device-runtimes/DeviceRuntimesTable.tsx` - 修复表格单元格对齐 - -### 修改内容 - -#### 1. 表头居中对齐 -- **添加居中对齐**:为所有 `TableHead` 元素添加 `text-center` 类 -- **保持密度样式**:继续使用 `densityStyles` 控制行高 -- **视觉一致性**:与协议版本表格保持一致的显示效果 - -#### 2. 表格单元格居中对齐 -- **添加居中对齐**:为所有 `TableCell` 元素添加 `text-center` 类 -- **保持密度样式**:继续使用 `densityStyles` 控制行高 -- **内容对齐**:所有单元格内容现在都居中对齐 - -### 技术说明 -- **CSS类应用**:使用 `cn("text-center", densityStyles[density])` 组合样式类 -- **一致性**:与协议版本表格使用相同的对齐方式 -- **响应式设计**:保持密度样式的响应式特性 -- **用户体验**:提供统一的表格显示效果 - -### 影响范围 -- **视觉效果**:表格单元格内容现在居中对齐 -- **一致性**:与其他表格组件保持一致的显示效果 -- **用户体验**:提供更好的视觉体验和可读性 -- **设计统一**:保持整个系统的表格设计一致性 - -## 2025-01-29 - 优化设备运行时操作菜单逻辑 - -### 修改原因 -根据用户需求,操作菜单应该根据设备运行时状态显示不同的操作选项:当设备处于未知状态或停止状态时可以启动,当设备处于运行状态时可以停止。 - -### 修改文件 -- `X1.WebUI/src/pages/device-runtimes/DeviceRuntimesTable.tsx` - 修改操作菜单逻辑 -- `X1.WebUI/src/pages/device-runtimes/DeviceRuntimesView.tsx` - 添加启动单个设备处理函数 - -### 修改内容 - -#### 1. 操作菜单逻辑优化 -- **运行中状态(runtimeStatus === 1)**:显示"停止设备"选项,点击红色图标 -- **其他状态(未知-1、初始化0、已停止2、错误3)**:显示"启动设备"选项,点击绿色图标 -- **移除禁用状态**:不再显示禁用的"设备未运行"选项 - -#### 2. 接口扩展 -- **新增回调函数**:添加 `onStartDevice` 回调函数到 `DeviceRuntimesTableProps` 接口 -- **组件参数更新**:在 `DeviceRuntimesTable` 组件中添加 `onStartDevice` 参数 - -#### 3. 启动设备处理 -- **临时实现**:由于单个设备启动需要选择网络栈配置,暂时提示用户使用批量启动功能 -- **用户引导**:提供清晰的用户提示,引导用户使用正确的功能 - -### 技术说明 -- **状态判断**:根据 `runtimeStatus` 值判断显示的操作选项 -- **颜色区分**:启动操作使用绿色,停止操作使用红色 -- **用户体验**:提供直观的操作反馈和用户引导 -- **功能完整性**:保持批量启动和单个停止功能的完整性 - -### 影响范围 -- **操作逻辑**:操作菜单现在根据设备状态显示相应的操作选项 -- **用户体验**:提供更直观和合理的操作选择 -- **功能引导**:引导用户使用正确的功能进行设备启动 -- **视觉反馈**:通过颜色区分不同的操作类型 - -## 2025-01-29 - 修复设备运行时表格选择框对齐问题 - -### 修改原因 -用户反馈选择框(勾选框)没有居中对齐,需要修复表格中标题行和内容行的选择框对齐问题。 - -### 修改文件 -- `X1.WebUI/src/pages/device-runtimes/DeviceRuntimesTable.tsx` - 修复选择框对齐 - -### 修改内容 - -#### 1. 选择框列对齐修复 -- **表头选择框**:为 `TableHead` 添加 `text-center` 类,使全选复选框居中对齐 -- **内容行选择框**:为 `TableCell` 添加 `text-center` 类,使单个选择复选框居中对齐 - -#### 2. 样式统一 -- **对齐一致性**:确保选择框列与其他列的对齐方式保持一致 -- **视觉体验**:提供更好的表格视觉效果和用户体验 - -### 技术说明 -- **CSS类应用**:使用 Tailwind CSS 的 `text-center` 类实现居中对齐 -- **表格结构**:保持表格结构完整性,只修改对齐样式 -- **响应式设计**:确保在不同屏幕尺寸下选择框都能正确对齐 - -### 影响范围 -- **视觉效果**:选择框现在与其他列内容居中对齐 -- **用户体验**:提供更整洁和一致的表格显示效果 -- **设计统一**:保持整个表格的对齐一致性 - -## 2025-01-29 - 优化设备运行时操作列显示方式 - -### 修改原因 -用户希望操作列直接显示启动和停止按钮,而不是使用下拉菜单,提供更直观的操作体验。 - -### 修改文件 -- `X1.WebUI/src/pages/device-runtimes/DeviceRuntimesTable.tsx` - 修改操作列显示方式 - -### 修改内容 - -#### 1. 操作列显示方式优化 -- **移除下拉菜单**:不再使用 `DropdownMenu` 组件,直接显示操作按钮 -- **直接按钮显示**:根据设备状态直接显示启动或停止按钮 -- **图标按钮**:使用纯图标按钮,节省空间并提高视觉效果 - -#### 2. 按钮样式优化 -- **启动按钮**:绿色图标,悬停时显示绿色背景 -- **停止按钮**:红色图标,悬停时显示红色背景 -- **工具提示**:添加 `title` 属性提供操作说明 -- **居中对齐**:按钮在操作列中居中对齐 - -#### 3. 代码清理 -- **移除未使用导入**:删除不再使用的 `DropdownMenu` 相关导入 -- **简化代码结构**:移除复杂的下拉菜单逻辑,使用简单的条件渲染 - -### 技术说明 -- **条件渲染**:根据 `runtimeStatus` 值决定显示启动或停止按钮 -- **样式设计**:使用 `variant="ghost"` 和自定义颜色类实现按钮样式 -- **用户体验**:提供直观的图标按钮,减少操作步骤 -- **响应式设计**:按钮在不同屏幕尺寸下都能正确显示 - -### 影响范围 -- **操作体验**:用户可以直接点击按钮进行操作,无需打开下拉菜单 -- **视觉效果**:操作列更加简洁,图标按钮更加直观 -- **交互效率**:减少操作步骤,提高用户操作效率 -- **代码维护**:简化了操作列的实现逻辑 - -## 2025-01-29 - 优化批量启动对话框网络栈配置选择 - -### 修改原因 -用户希望将网络栈配置改为搜索下拉框选择,数据来源是 `networkStackConfigService.ts`,提供更好的搜索和选择体验。 - -### 修改文件 -- `X1.WebUI/src/pages/device-runtimes/DeviceRuntimesView.tsx` - 修改网络栈配置选择方式 - -### 修改内容 - -#### 1. 搜索下拉框实现 -- **移除Select组件**:不再使用简单的 `Select` 组件,改为自定义搜索下拉框 -- **搜索功能**:支持按网络栈名称、编号和描述进行搜索 -- **实时过滤**:输入搜索关键词时实时过滤匹配的配置项 -- **显示优化**:显示网络栈名称、编号和描述信息 - -#### 2. 状态管理 -- **搜索状态**:添加 `networkStackSearchTerm` 状态管理搜索关键词 -- **过滤状态**:添加 `filteredNetworkStackConfigs` 状态管理过滤后的配置列表 -- **下拉框状态**:添加 `isNetworkStackDropdownOpen` 状态管理下拉框开关 - -#### 3. 交互优化 -- **点击外部关闭**:添加点击外部区域关闭下拉框的功能 -- **搜索重置**:选择配置后自动清空搜索关键词并重置过滤列表 -- **无结果提示**:当搜索无结果时显示友好的提示信息 - -#### 4. 样式设计 -- **下拉框样式**:使用与系统一致的样式设计 -- **悬停效果**:配置项悬停时显示高亮效果 -- **描述显示**:在配置项下方显示描述信息(如果有) - -### 技术说明 -- **数据来源**:使用 `networkStackConfigService.getNetworkStackConfigs()` 获取配置数据 -- **搜索逻辑**:支持多字段搜索(名称、编号、描述) -- **性能优化**:使用本地过滤,避免频繁的API调用 -- **用户体验**:提供直观的搜索和选择体验 - -### 影响范围 -- **用户体验**:提供更便捷的网络栈配置搜索和选择功能 -- **功能完整性**:保持批量启动功能的完整性 -- **交互效率**:通过搜索功能快速定位目标配置 -- **视觉一致性**:与系统其他搜索下拉框保持一致的视觉风格 - -## 2025-01-29 - 优化设备运行时表格网络栈配置列 - -### 修改原因 -用户希望网络栈配置列显示为下拉框,只有当选择了网络栈配置值的时候才能启动设备,提供更直观的配置选择和启动控制。 - -### 修改文件 -- `X1.WebUI/src/pages/device-runtimes/DeviceRuntimesTable.tsx` - 修改网络栈配置列显示方式 -- `X1.WebUI/src/pages/device-runtimes/DeviceRuntimesView.tsx` - 添加网络栈配置变更处理 - -### 修改内容 - -#### 1. 网络栈配置列下拉框实现 -- **搜索下拉框**:将网络栈配置列改为可搜索的下拉框 -- **实时搜索**:支持按名称、编号和描述进行实时搜索 -- **配置显示**:显示网络栈名称和编号的组合信息 -- **选择功能**:点击配置项可选择对应的网络栈配置 - -#### 2. 启动按钮控制逻辑 -- **条件启动**:只有当设备选择了网络栈配置时,启动按钮才可用 -- **视觉反馈**:未选择配置时按钮显示为灰色禁用状态 -- **提示信息**:鼠标悬停时显示相应的提示信息 -- **错误处理**:尝试启动未配置设备时显示错误提示 - -#### 3. 状态管理优化 -- **下拉框状态**:管理每个设备的下拉框开关状态 -- **搜索状态**:管理每个设备的搜索关键词 -- **过滤状态**:管理每个设备的过滤结果 -- **点击外部关闭**:点击外部区域自动关闭所有下拉框 - -#### 4. 单个设备启动功能 -- **完整实现**:实现单个设备的启动功能 -- **配置验证**:启动前验证是否已选择网络栈配置 -- **API调用**:调用设备启动API进行实际启动操作 -- **结果反馈**:显示启动成功或失败的提示信息 - -### 技术说明 -- **组件接口扩展**:添加 `networkStackConfigs` 和 `onNetworkStackChange` 属性 -- **状态管理**:使用对象形式管理多个设备的状态 -- **搜索算法**:支持多字段模糊搜索 -- **用户体验**:提供直观的配置选择和启动控制 - -### 影响范围 -- **表格交互**:网络栈配置列现在支持下拉选择 -- **启动控制**:只有配置了网络栈的设备才能启动 -- **用户体验**:提供更直观的配置管理和启动流程 -- **功能完整性**:单个设备启动功能现在完全可用 - -## 2025-01-29 - 修复网络栈配置下拉框样式问题 - -### 修改原因 -用户反馈网络栈配置下拉框的样式不正确,存在红色圆点等视觉问题,需要修复样式以保持界面的一致性。 - -### 修改文件 -- `X1.WebUI/src/pages/device-runtimes/DeviceRuntimesTable.tsx` - 修复表格中网络栈配置下拉框样式 -- `X1.WebUI/src/pages/device-runtimes/DeviceRuntimesView.tsx` - 修复批量启动对话框中的网络栈配置下拉框样式 - -### 修改内容 - -#### 1. 文本颜色修复 -- **表格下拉框**:为文本添加 `text-foreground` 类,确保文本颜色正确 -- **对话框下拉框**:为文本添加 `text-foreground` 类,保持颜色一致性 - -#### 2. 搜索输入框样式优化 -- **移除边框**:为搜索输入框添加 `border-0 focus:ring-0 focus:border-0` 类 -- **简化样式**:移除不必要的边框和焦点环,使搜索框更简洁 -- **统一外观**:确保搜索框与下拉框整体样式协调 - -#### 3. 视觉一致性 -- **颜色统一**:确保所有文本使用正确的主题颜色 -- **边框处理**:移除搜索框的重复边框,避免视觉冲突 -- **焦点状态**:简化焦点状态的视觉反馈 - -### 技术说明 -- **CSS类应用**:使用 Tailwind CSS 类修复样式问题 -- **主题适配**:确保样式与系统主题保持一致 -- **视觉层次**:优化视觉层次,避免不必要的视觉元素 - -### 影响范围 -- **视觉效果**:修复了红色圆点等样式问题 -- **界面一致性**:保持下拉框与系统其他组件的视觉一致性 -- **用户体验**:提供更清洁和专业的界面外观 -- **主题适配**:确保在不同主题下都能正确显示 - -## 2025-01-29 - 修复网络栈配置下拉框定位问题 - -### 修改原因 -用户反馈下拉框不应该占用当前行的空间,应该覆盖在其他内容之上,需要修复下拉框的定位方式。 - -### 修改文件 -- `X1.WebUI/src/pages/device-runtimes/DeviceRuntimesTable.tsx` - 修复下拉框定位逻辑 - -### 修改内容 - -#### 1. 定位方式优化 -- **固定定位**:将下拉框改为 `fixed` 定位,不再占用表格行空间 -- **动态计算位置**:根据点击元素的位置动态计算下拉框显示位置 -- **高层级显示**:使用 `z-[9999]` 确保下拉框显示在最上层 - -#### 2. 位置计算逻辑 -- **点击事件处理**:在点击事件中获取元素的位置信息 -- **坐标计算**:计算下拉框应该显示的位置坐标 -- **状态管理**:添加 `dropdownPositions` 状态管理每个下拉框的位置 - -#### 3. 交互优化 -- **精确定位**:下拉框现在精确显示在触发元素下方 -- **不占用空间**:下拉框不再影响表格的布局和行高 -- **响应式定位**:支持滚动时的位置调整 - -### 技术说明 -- **getBoundingClientRect**:使用 DOM API 获取元素位置信息 -- **fixed 定位**:使用固定定位避免影响文档流 -- **事件处理**:在点击事件中传递事件对象以获取位置信息 -- **状态管理**:使用对象形式管理多个下拉框的位置状态 - -### 影响范围 -- **布局优化**:下拉框不再占用表格行空间 -- **视觉效果**:下拉框现在浮在内容上方,提供更好的视觉层次 -- **用户体验**:提供更流畅和直观的下拉选择体验 -- **交互响应**:下拉框位置更精确,响应更及时 - -## 2025-01-29 - 修复网络栈配置显示问题 - -### 修改原因 -用户反馈 `DeviceRuntimesView.tsx` 中的网络栈配置下拉框没有数据,但 `NetworkStackConfigsTable.tsx` 是有数据的,需要确保网络栈配置能正确显示网络栈名称。 - -### 修改文件 -- `X1.WebUI/src/pages/device-runtimes/DeviceRuntimesTable.tsx` - 修复网络栈配置显示逻辑 -- `X1.WebUI/src/pages/device-runtimes/DeviceRuntimesView.tsx` - 修复批量启动对话框中的网络栈配置显示 - -### 修改内容 - -#### 1. 显示逻辑优化 -- **表格列显示**:当找到匹配的网络栈配置时显示名称和编号,未找到时显示编号和提示 -- **对话框显示**:批量启动对话框中的网络栈配置显示逻辑与表格保持一致 -- **错误处理**:当网络栈配置不存在时提供友好的错误提示 - -#### 2. 数据匹配逻辑 -- **配置查找**:根据 `networkStackCode` 在 `networkStackConfigs` 中查找匹配的配置 -- **显示优先级**:优先显示网络栈名称,其次显示编号 -- **兜底显示**:当配置不存在时显示编号和"未找到配置"提示 - -#### 3. 用户体验改进 -- **清晰提示**:明确显示当前选择的网络栈配置状态 -- **错误反馈**:当配置不存在时提供明确的错误信息 -- **一致性**:表格和对话框中的显示逻辑保持一致 - -### 技术说明 -- **数据源**:使用 `networkStackConfigService.getNetworkStackConfigs()` 获取配置数据 -- **匹配逻辑**:使用 `find()` 方法根据 `networkStackCode` 匹配配置 -- **显示格式**:统一使用"名称 (编号)"的显示格式 -- **错误处理**:提供友好的错误提示而不是显示"未知配置" - -### 影响范围 -- **数据显示**:网络栈配置现在能正确显示网络栈名称 -- **用户体验**:提供更清晰和准确的配置信息显示 -- **错误处理**:当配置不存在时提供明确的错误提示 -- **一致性**:表格和对话框中的显示逻辑保持一致 - -## 2025-01-29 - 限制运行中设备的网络栈配置修改 - -### 修改原因 -用户要求当设备启动之后,网络栈配置不能再修改,需要限制运行中设备的网络栈配置编辑功能。 - -### 修改文件 -- `X1.WebUI/src/pages/device-runtimes/DeviceRuntimesTable.tsx` - 限制运行中设备的网络栈配置下拉框 -- `X1.WebUI/src/pages/device-runtimes/DeviceRuntimesView.tsx` - 限制运行中设备的网络栈配置变更 - -### 修改内容 - -#### 1. 下拉框状态控制 -- **运行中设备**:当 `runtimeStatus === 1` 时,下拉框显示为禁用状态 -- **视觉反馈**:禁用状态下使用灰色背景和降低透明度 -- **交互限制**:禁用状态下不允许点击打开下拉框 - -#### 2. 下拉框显示控制 -- **条件显示**:只有非运行中的设备才显示下拉框选项 -- **状态检查**:在显示下拉框前检查设备运行状态 -- **安全防护**:防止运行中设备意外修改配置 - -#### 3. 配置变更限制 -- **状态验证**:在配置变更前检查设备运行状态 -- **错误提示**:当尝试修改运行中设备配置时显示错误提示 -- **操作阻止**:阻止对运行中设备的配置修改操作 - -#### 4. 用户体验优化 -- **清晰状态**:通过视觉样式明确区分可编辑和不可编辑状态 -- **友好提示**:提供明确的错误提示说明为什么不能修改 -- **一致性**:保持界面交互逻辑的一致性 - -### 技术说明 -- **状态判断**:使用 `runtimeStatus === 1` 判断设备是否运行中 -- **条件渲染**:使用条件渲染控制下拉框的显示和交互 -- **样式控制**:使用 Tailwind CSS 类控制禁用状态的样式 -- **事件处理**:在事件处理函数中添加状态检查逻辑 - -### 影响范围 -- **功能限制**:运行中的设备无法修改网络栈配置 -- **视觉反馈**:运行中设备的网络栈配置列显示为禁用状态 -- **用户体验**:提供清晰的视觉和交互反馈 -- **数据安全**:防止运行中设备的配置被意外修改 - -## 2025-01-29 - 删除未使用的DeviceRuntimeDetail.tsx文件 - -### 修改原因 -经过检查发现 `DeviceRuntimeDetail.tsx` 文件虽然存在且有路由配置,但实际上没有被使用。在 `DeviceRuntimesView.tsx` 和 `DeviceRuntimesTable.tsx` 中都没有任何导航到详情页面的链接或按钮,表格中的操作菜单只包含"停止设备"和"设备未运行"选项,没有"查看详情"选项。 - -### 修改文件 - -#### 1. 删除文件 -- `X1.WebUI/src/pages/device-runtimes/DeviceRuntimeDetail.tsx` - 删除未使用的设备运行时详情页面组件 - -#### 2. 修改路由配置 -- `X1.WebUI/src/routes/AppRouter.tsx` - 移除DeviceRuntimeDetail组件的导入和路由配置 - -### 修改内容 - -#### 1. 删除DeviceRuntimeDetail.tsx文件 -- 删除了276行的设备运行时详情页面组件 -- 该组件包含设备运行时状态显示、网络配置信息、时间信息等功能 -- 但由于没有入口链接,用户无法访问此页面 - -#### 2. 更新路由配置 -- 移除 `const DeviceRuntimeDetail = lazy(() => import('@/pages/device-runtimes/DeviceRuntimeDetail'));` 导入语句 -- 删除 `/device-runtimes/detail/:deviceCode` 路由配置 -- 保留 `/device-runtimes/list` 路由,确保设备运行时列表页面正常工作 - -### 技术说明 -- **路由清理**:移除了未使用的路由配置,简化路由结构 -- **代码清理**:删除了未使用的组件文件,减少代码冗余 -- **功能完整性**:设备运行时管理功能仍然完整,只是移除了未使用的详情页面 -- **编译错误修复**:修复了因删除组件导致的编译错误 - -### 影响范围 -- **功能影响**:用户无法再访问设备运行时详情页面 -- **路由影响**:`/device-runtimes/detail/:deviceCode` 路径不再可用 -- **代码维护**:减少了未使用的代码,提高代码库的整洁性 -- **编译状态**:修复了编译错误,确保项目能够正常构建 - -### 后续建议 -1. **功能评估**:如果将来需要设备运行时详情功能,可以重新实现 -2. **用户反馈**:收集用户反馈,确认是否需要详情页面功能 -3. **替代方案**:考虑在列表页面中直接显示详细信息,而不是单独的详情页面 -4. **代码审查**:定期检查类似的未使用代码,保持代码库的整洁性 - -## 2025-01-29 - 修复批量启动按钮主题兼容性问题 - -### 修改原因 -批量启动按钮使用了硬编码的绿色样式(`bg-green-600 hover:bg-green-700 text-white`),与系统的主题切换不兼容,在深色主题下显示效果不佳。 - -### 修改文件 -- `X1.WebUI/src/pages/device-runtimes/DeviceRuntimesView.tsx` - 修复批量启动按钮的主题兼容性 - -### 修改内容 - -#### 1. 批量启动按钮样式修复 -- **移除硬编码样式**:删除 `className="bg-green-600 hover:bg-green-700 text-white"` -- **使用主题变量**:改为使用 `variant="default"`,让按钮自动适配当前主题 -- **保持功能不变**:按钮的禁用状态和点击功能保持不变 - -#### 2. 确认启动按钮样式修复 -- **移除硬编码样式**:删除 `className="bg-green-600 hover:bg-green-700"` -- **使用主题变量**:改为使用 `variant="default"`,确保与主题系统一致 -- **保持功能不变**:按钮的禁用状态和提交功能保持不变 - -### 技术说明 -- **主题兼容性**:使用 `variant="default"` 让按钮自动适配浅色/深色主题 -- **设计一致性**:与系统其他按钮保持一致的视觉风格 -- **可维护性**:移除硬编码样式,提高代码的可维护性 -- **用户体验**:在不同主题下都能提供良好的视觉体验 - -### 影响范围 -- **视觉效果**:批量启动按钮现在与主题系统完全兼容 -- **用户体验**:在浅色和深色主题下都有良好的显示效果 -- **代码质量**:移除了硬编码样式,提高了代码质量 -- **设计一致性**:与系统其他组件保持一致的视觉风格 - -## 2025-01-29 修复GetNetworkStackConfigsByCodesAsync方法添加ConfigContent字段 - -### 修改原因 -根据用户需求,`GetNetworkStackConfigsByCodesAsync` 方法需要获取 `ran.ConfigContent`、`cnc.ConfigContent` 和 `ims.ConfigContent` 字段,以便在前端显示完整的配置内容信息。 - -### 修改文件 -- `X1.Domain/Models/NetworkStackConfigWithBindingNamesDto.cs` - 添加ConfigContent字段 -- `X1.Infrastructure/Repositories/NetworkProfile/NetworkStackConfigRepository.cs` - 修复SQL查询 - -### 修改内容 - -#### 1. DTO模型扩展 -- **NetworkStackConfigWithBindingNamesDto**: - - 添加 `RanConfigContent?: string` - RAN配置内容 - - 添加 `CoreNetworkConfigContent?: string` - 核心网配置内容 - - 添加 `IMSConfigContent?: string` - IMS配置内容 - -#### 2. SQL查询修复 -- **GetNetworkStackConfigsByCodesAsync方法**: - - 在SELECT语句中添加 `ran."ConfigContent" AS "RanConfigContent"` - - 在SELECT语句中添加 `cnc."ConfigContent" AS "CoreNetworkConfigContent"` - - 在SELECT语句中添加 `ims."ConfigContent" AS "IMSConfigContent"` - -#### 3. 相关方法同步修复 -- **GetNetworkStackConfigByIdWithBindingNamesAsync方法**: - - 同步添加相同的ConfigContent字段到SQL查询中 -- **SearchNetworkStackConfigsWithBindingNamesAsync方法**: - - 同步添加相同的ConfigContent字段到SQL查询中 - -### 技术特性 -- **数据完整性**:现在能够获取完整的配置内容信息 -- **字段映射**:正确映射数据库字段到DTO属性 -- **一致性**:所有相关方法都包含相同的ConfigContent字段 -- **类型安全**:使用可空字符串类型,避免空值问题 - -### 业务价值 -- **配置内容显示**:前端可以显示RAN、核心网、IMS的完整配置内容 -- **数据关联**:提供网络栈配置与相关配置内容的完整关联信息 -- **调试支持**:便于开发人员查看和调试配置内容 -- **用户体验**:用户可以在一个查询中获取所有相关的配置信息 - -### 影响范围 -- **API响应**:网络栈配置查询现在包含完整的配置内容 -- **前端显示**:前端可以显示配置内容信息 -- **数据查询**:提供更完整的配置关联数据 -- **系统集成**:支持配置内容的完整传递和处理 - -### 后续工作建议 -1. 更新前端界面以显示配置内容信息 -2. 添加配置内容的格式化显示功能 -3. 考虑添加配置内容的搜索功能 -4. 优化大配置内容的显示方式 - -## 2025-01-29 - 修复StartDeviceRuntimeCommandHandler中的bug和命名规范问题 - -### 修改原因 -修复 `StartDeviceRuntimeCommandHandler` 中的多个bug问题,添加详细的跟踪日志,并修复命名规范问题。 - -### 修改文件 -- `X1.Application/Features/DeviceRuntimes/Commands/StartDeviceRuntime/StartDeviceRuntimeCommandHandler.cs` - 修复Handle方法中的bug和命名规范 - -### 修改内容 - -#### 1. Bug修复 -- **Bug 1**: `runtimeDetails` 列表被创建但从未添加元素 - - **修复**: 在循环中正确添加 `CellularDeviceRuntimeDetail` 对象到列表 - - **影响**: 现在运行时详情会被正确保存到数据库 - -- **Bug 2**: 变量命名不规范(`Requests` 应该是小写开头) - - **修复**: 将 `Requests` 重命名为 `networkRequests` - - **影响**: 符合C#命名规范,提高代码可读性 - -- **Bug 3**: 缺少详细的跟踪日志 - - **修复**: 添加了完整的跟踪日志,包括每个步骤的详细信息 - - **影响**: 便于问题排查和性能监控 - -- **Bug 4**: 没有验证网络配置是否成功获取 - - **修复**: 添加网络配置获取结果的验证 - - **影响**: 避免因配置不存在导致的运行时错误 - -- **Bug 5**: 没有处理设备运行时可能不存在的情况 - - **修复**: 添加设备运行时存在性检查 - - **影响**: 提高系统稳定性,避免空引用异常 - -#### 2. 命名规范修复 -- **变量命名**: `Requests` → `networkRequests` -- **参数命名**: `res` → `networkConfigs` -- **方法参数**: 使用更清晰的参数名称 -- **日志变量**: 使用描述性的变量名称 - -#### 3. 详细跟踪日志添加 -- **网络配置获取**: 记录获取过程和结果数量 -- **运行时编码生成**: 记录生成的编码信息 -- **网络配置构建**: 记录每个配置的构建过程 -- **网络启动**: 记录每个设备的启动过程 -- **运行时详情创建**: 记录详情创建和保存过程 -- **设备运行时更新**: 记录状态更新过程 -- **错误处理**: 详细的异常信息和上下文 - -#### 4. 错误处理改进 -- **网络配置验证**: 检查配置是否存在 -- **设备运行时检查**: 验证设备运行时是否存在 -- **异常分类**: 区分不同类型的异常 -- **错误传播**: 合理的异常传播策略 - -#### 5. 代码结构优化 -- **方法拆分**: 将复杂逻辑拆分为更小的方法 -- **变量作用域**: 优化变量作用域和生命周期 -- **代码注释**: 添加详细的代码注释 -- **逻辑清晰**: 改进代码逻辑的清晰度 - -### 技术特性 -- **数据完整性**: 确保所有运行时详情都被正确保存 -- **错误恢复**: 完善的错误处理和恢复机制 -- **性能监控**: 详细的日志记录便于性能分析 -- **代码质量**: 符合C#命名规范和最佳实践 - -### 业务价值 -- **系统稳定性**: 修复bug提高系统稳定性 -- **可维护性**: 清晰的代码结构和日志便于维护 -- **调试能力**: 详细的跟踪日志便于问题排查 -- **用户体验**: 更可靠的设备启动流程 - -### 影响范围 -- **设备启动流程**: 修复了批量启动设备的完整流程 -- **数据保存**: 确保运行时详情正确保存 -- **错误处理**: 改进了异常情况的处理 -- **日志记录**: 提供了完整的操作跟踪 - -### 测试建议 -1. 测试批量启动设备的完整流程 -2. 验证运行时详情的正确保存 -3. 检查错误处理机制 -4. 验证日志记录的完整性 -5. 测试网络配置不存在的情况 -6. 测试设备运行时不存在的情况 - -## 2025-01-29 - 为GenerateRuntimeCodeAsync方法的异常处理添加详细说明 - -### 修改原因 -为 `throw;` 语句添加详细的注释说明,解释为什么要重新抛出异常,提高代码的可读性和维护性。 - -### 修改文件 -- `X1.Application/Features/DeviceRuntimes/Commands/StartDeviceRuntime/StartDeviceRuntimeCommandHandler.cs` - 为异常处理添加详细说明 - -### 修改内容 - -#### 1. 异常处理说明 -- **重新抛出原因**: 添加了详细的注释说明为什么要重新抛出异常 -- **堆栈跟踪**: 保持异常的原始堆栈跟踪信息,便于调试和问题定位 -- **异常传播**: 确保上层调用者能够捕获到原始异常,进行适当的错误处理 -- **信息完整性**: 避免异常信息丢失,保持异常传播链的完整性 -- **最佳实践**: 符合异常处理的最佳实践:记录日志后重新抛出 - -#### 2. 代码可读性提升 -- **注释清晰**: 详细说明了每个重新抛出异常的原因 -- **维护友好**: 便于其他开发者理解异常处理逻辑 -- **调试支持**: 提供了调试和问题定位的指导 - -### 技术要点 -1. **异常传播链**: 保持完整的异常传播链,便于问题追踪 -2. **日志记录**: 在重新抛出前记录详细的错误日志 -3. **调试信息**: 包含线程ID等调试信息 -4. **最佳实践**: 遵循C#异常处理的最佳实践 - -### 测试建议 -1. 测试异常情况下的日志记录 -2. 验证异常传播链的完整性 -3. 检查调试信息的准确性 -4. 测试多线程环境下的异常处理 - -## 2025-01-29 - 修复网络配置请求构建中的设备-网络堆栈组合唯一性检查 - -### 修改原因 -修复了网络配置请求构建中的一个重要bug:原来的逻辑只检查设备代码的唯一性,但实际上一个设备可能需要运行多个不同的网络堆栈配置。需要改为检查设备-网络堆栈组合的唯一性。 - -### 修改文件 -- `X1.Application/Features/DeviceRuntimes/Commands/StartDeviceRuntime/StartDeviceRuntimeCommandHandler.cs` - 添加设备代码唯一性检查 - -### 修改内容 - -#### 1. 唯一性检查机制修复 -- **组合键跟踪**: 将 `processedDeviceCodes` 改为 `processedDeviceNetworkPairs`,用于跟踪已处理的设备-网络堆栈组合 -- **组合键生成**: 使用 `{DeviceCode}_{NetworkStackCode}` 格式生成唯一标识 -- **重复检查**: 在处理每个网络配置前检查设备-网络堆栈组合是否已被处理 -- **跳过重复**: 如果组合已存在,记录警告日志并跳过处理 - -#### 2. 日志增强 -- **重复警告**: 当发现重复设备代码时记录警告日志 -- **统计信息**: 添加成功构建网络配置请求的统计信息 -- **处理数量**: 记录实际处理的设备数量和请求数量 - -#### 3. 数据完整性保证 -- **组合唯一性**: 确保每个设备-网络堆栈组合只对应一个网络配置 -- **多配置支持**: 允许同一设备运行多个不同的网络堆栈配置 -- **避免冲突**: 防止同一设备-网络堆栈组合被重复处理 -- **数据一致性**: 保证后续处理的数据一致性 - -### 技术要点 -1. **HashSet性能**: 使用HashSet进行O(1)时间复杂度的重复检查 -2. **内存效率**: HashSet比List更高效地进行重复检查 -3. **线程安全**: 在单个请求处理中,HashSet是线程安全的 -4. **日志追踪**: 完整的操作日志便于问题排查 - -### 测试建议 -1. 测试同一设备运行多个网络堆栈配置的场景 -2. 测试包含重复设备-网络堆栈组合的请求 -3. 验证组合唯一性检查的正确性 -4. 检查日志记录的完整性 -5. 测试正常情况下的处理流程 - -## 2025-01-29 - 修复CoreNetworkImsConfiguration对象初始化问题 - -### 修改原因 -发现 `CoreNetworkImsConfiguration` 对象初始化时缺少必要的属性值,需要添加 `Index` 和 `Plmn` 属性以确保对象完整性。 - -### 修改文件 -- `X1.Application/Features/DeviceRuntimes/Commands/StartDeviceRuntime/StartDeviceRuntimeCommandHandler.cs` - 完善CoreNetworkImsConfiguration对象初始化 - -### 修改内容 - -#### 1. 对象完整性修复 -- **Index属性**: 添加 `Index = 0`,因为永远只有一条记录 -- **Plmn属性**: 添加 `Plmn = "000000"` 作为默认PLMN标识 -- **注释说明**: 添加注释说明为什么设置这些默认值 - -#### 2. 设计问题分析 -- **集合设计**: `CoreNetworkImsConfigurations` 定义为 `List` 但永远只有一条记录 -- **性能影响**: 创建不必要的集合对象,存在内存分配浪费 -- **代码冗余**: 使用集合但没有实际的多条记录需求 - -#### 3. 建议的长期改进 -- **模型重构**: 考虑将 `CoreNetworkImsConfiguration` 改为单个对象而非集合 -- **性能优化**: 避免不必要的集合创建和内存分配 -- **代码简化**: 简化对象创建和访问逻辑 - -## 2025-01-29 - 修复StartDeviceRuntimeCommandHandler语法错误 - -### 修改原因 -在 `StartDeviceRuntimeCommandHandler.cs` 文件的第330行存在语法错误,包含不完整的注释和错误的代码,导致编译失败。 - -### 修改文件 -- `X1.Application/Features/DeviceRuntimes/Commands/StartDeviceRuntime/StartDeviceRuntimeCommandHandler.cs` - 修复语法错误 - -### 修改内容 - -#### 1. 修复语法错误 -- **删除错误代码**:移除第330行的不完整注释和错误代码 -- **修复PLMN提取**:将硬编码的 `Plmn = "000000"` 改为调用 `ExtractPlmnFromConfig` 方法 -- **添加PLMN提取方法**:实现从网络配置中提取PLMN值的功能 - -#### 2. 新增ExtractPlmnFromConfig方法 -- **功能**:从网络配置内容中提取PLMN值 -- **实现**:使用正则表达式匹配PLMN值 -- **错误处理**:包含完整的异常处理和日志记录 -- **默认值**:如果未找到PLMN值,返回默认值"000000" - -#### 3. 技术特性 -- **正则表达式匹配**:使用 `@"plmn""\s*:\s*[""']([^""']+)[""']` 模式匹配PLMN值(支持双引号和单引号) -- **大小写不敏感**:使用 `RegexOptions.IgnoreCase` 忽略大小写 -- **空值处理**:正确处理空配置内容的情况 -- **异常处理**:捕获正则表达式异常并提供友好的错误处理 - -### 业务价值 -- **数据准确性**:从实际配置中提取PLMN值,而不是使用硬编码值 -- **系统稳定性**:修复编译错误,确保系统正常运行 -- **代码质量**:提高代码的可维护性和健壮性 - -### 影响范围 -- **编译错误**:修复了导致编译失败的语法错误 -- **PLMN处理**:改进了PLMN值的提取和处理逻辑 -- **错误处理**:增强了异常处理和日志记录功能 - ---- - -## 2025-01-29 - 修复StartNetworkAsync API请求体结构不匹配问题 - -### 修改原因 -根据API文档要求,`StartNetworkAsync` 方法发送的JSON请求体需要包含外层的 `cellularNetwork` 包装,但当前实现直接发送 `CellularNetworkConfiguration` 对象,导致请求体结构不匹配。 - -### 修改文件 -- `X1.DynamicClientCore/Models/CellularNetworkRequest.cs` - 新增包装类 -- `X1.DynamicClientCore/Features/IInstrumentProtocolClient.cs` - 修改接口签名 -- `X1.DynamicClientCore/Features/Service/InstrumentProtocolClient.cs` - 修改实现方法 -- `X1.Application/Features/DeviceRuntimes/Commands/StartDeviceRuntime/StartDeviceRuntimeCommandHandler.cs` - 修改调用方 - -### 修改内容 - -#### 1. 新增包装类 -- **类名**: `CellularNetworkRequest` -- **功能**: 包装 `CellularNetworkConfiguration` 对象,匹配API文档要求的JSON结构 -- **属性**: `CellularNetwork` - 包含实际的网络配置对象 - -#### 2. 修改接口签名 -- **参数类型**: 将 `StartNetworkAsync` 方法的参数从 `CellularNetworkConfiguration` 改为 `CellularNetworkRequest` -- **参数验证**: 添加对 `request` 参数的 null 检查 -- **文档更新**: 更新方法注释和异常说明 - -#### 3. 修改实现方法 -- **参数处理**: 从 `request.CellularNetwork` 中提取设备编号 -- **请求传递**: 直接将 `request` 对象传递给 `PostAsync` 方法 -- **错误处理**: 增强参数验证和错误处理 - -#### 4. 修改调用方 -- **包装创建**: 在调用 `StartNetworkAsync` 前创建 `CellularNetworkRequest` 包装对象 -- **参数传递**: 将包装后的对象传递给协议客户端 - -#### 5. API文档匹配 -**API文档要求的JSON结构**: -```json -{ - "cellularNetwork": { - "deviceCode": "string", - "runtimeCode": "string", - "radioAccessNetworkConfiguration": "string", - "coreNetworkImsConfigurations": [...] - } -} -``` - -**修复后的实现**: -```csharp -// 调用方 -var request = new CellularNetworkRequest -{ - CellularNetwork = networkRequest -}; -var startResult = await _protocolClient.StartNetworkAsync(request); - -// 实现方 -public async Task StartNetworkAsync( - CellularNetworkRequest request, - RequestOptions? options = null, - CancellationToken cancellationToken = default) -{ - // 直接传递 request 对象给 PostAsync - var response = await _dynamicHttpClient.PostAsync>( - instrumentNumber, - "CellularNetwork/generalStart", - request, // 使用包装后的请求对象 - options, - cancellationToken); -} -``` - -### 技术要点 -- **接口设计**: 将包装类作为接口参数,确保类型安全 -- **序列化匹配**: 确保JSON序列化后的结构与API文档要求一致 -- **参数验证**: 增强参数验证,提高代码健壮性 -- **类型安全**: 使用强类型对象确保编译时类型检查 - -### 业务价值 -- **API兼容性**: 确保与外部API的正确通信 -- **请求成功**: 修复可能导致API调用失败的结构问题 -- **调试便利**: 提供清晰的请求体结构,便于API调试 -- **代码清晰**: 明确区分请求包装和实际配置对象 - -### 影响范围 -- **接口变更**: 修改了 `IInstrumentProtocolClient` 接口的 `StartNetworkAsync` 方法签名 -- **实现更新**: 更新了 `InstrumentProtocolClient` 的实现逻辑 -- **调用方修改**: 修改了 `StartDeviceRuntimeCommandHandler` 中的调用方式 -- **API调用**: 修复了网络启动API调用的请求体结构 -- **序列化**: 改进了JSON序列化的结构匹配 -- **兼容性**: 确保与外部系统的API兼容性 - ---- - -## 2024-12-19 数据库表名规范化修改 - -### 修改内容 -将所有数据库表名从规范的PascalCase命名方式改为以`tb_`开头的小写下划线命名方式,使表名更加不规范。 - -### 修改的文件列表 - -#### 设备相关表 -- `X1.Infrastructure/Configurations/Device/CellularDeviceConfiguration.cs` - - 表名:`CellularDevices` → `tb_cellular_device` -- `X1.Infrastructure/Configurations/Device/CellularDeviceRuntimeConfiguration.cs` - - 表名:`CellularDeviceRuntimes` → `tb_cellular_device_runtimes` -- `X1.Infrastructure/Configurations/Device/CellularDeviceRuntimeDetailConfiguration.cs` - - 表名:`CellularDeviceRuntimeDetails` → `tb_cellular_device_runtime_details` -- `X1.Infrastructure/Configurations/Device/ProtocolVersionConfiguration.cs` - - 表名:`ProtocolVersions` → `tb_protocol_versions` - -#### 身份认证相关表 -- `X1.Infrastructure/Configurations/Identity/AppUserConfiguration.cs` - - 表名:`Users` → `tb_users` -- `X1.Infrastructure/Configurations/Identity/AppRoleConfiguration.cs` - - 表名:`Roles` → `tb_roles` -- `X1.Infrastructure/Configurations/Identity/UserRoleConfiguration.cs` - - 表名:`UserRoles` → `tb_user_roles` - -#### 权限相关表 -- `X1.Infrastructure/Configurations/Permission/PermissionConfiguration.cs` - - 表名:`Permissions` → `tb_permissions` -- `X1.Infrastructure/Configurations/Permission/RolePermissionConfiguration.cs` - - 表名:`RolePermissions` → `tb_role_permissions` - -#### 网络配置相关表 -- `X1.Infrastructure/Configurations/NetworkProfile/CoreNetworkConfigConfiguration.cs` - - 表名:`CoreNetworkConfigs` → `tb_core_network_configs` -- `X1.Infrastructure/Configurations/NetworkProfile/IMS_ConfigurationConfiguration.cs` - - 表名:`IMS_Configurations` → `tb_ims_configurations` -- `X1.Infrastructure/Configurations/NetworkProfile/NetworkStackConfigConfiguration.cs` - - 表名:`NetworkStackConfigs` → `tb_network_stack_configs` -- `X1.Infrastructure/Configurations/NetworkProfile/RAN_ConfigurationConfiguration.cs` - - 表名:`RAN_Configurations` → `tb_ran_configurations` -- `X1.Infrastructure/Configurations/NetworkProfile/Stack_CoreIMS_BindingConfiguration.cs` - - 表名:`Stack_CoreIMS_Bindings` → `tb_stack_core_ims_bindings` - -#### 日志相关表 -- `X1.Infrastructure/Configurations/Logging/LoginLogConfiguration.cs` - - 表名:`LoginLogs` → `tb_login_logs` -- `X1.Infrastructure/Configurations/Logging/ProtocolLogConfiguration.cs` - - 表名:`tb_ProtocolLog` → `tb_protocol_logs` - -### 修改说明 -- 所有表名都改为以`tb_`开头 -- 使用小写字母和下划线分隔 -- 保持原有的表注释不变 -- 索引名称也相应更新以匹配新的表名 - -### 影响 -- 需要重新生成数据库迁移文件 -- 如果数据库中已有数据,需要手动迁移数据 -- 所有相关的查询和存储过程可能需要更新 - ---- - -## 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 }; -} -``` - -### 技术改进 -- **性能优化**:减少数据库查询次数,提高查询性能 -- **代码简化**:移除复杂的运行时状态查询逻辑 -- **参数一致性**:确保方法调用参数与接口定义一致 -- **错误处理**:简化错误处理逻辑,减少潜在的错误点 - -### 影响范围 -- **查询性能**:提高了协议日志查询的性能 -- **代码维护性**:简化了代码逻辑,便于维护 -- **功能完整性**:保持了原有的过滤功能 -- **接口一致性**:确保所有调用都使用正确的参数顺序 - ---- - -## 2025-01-29 - 修复GetDeviceRuntimesAsync类型不匹配问题 - -### 问题描述 -- `StopDeviceRuntimeCommandHandler.GetDeviceRuntimesAsync` 方法期望返回 `Dictionary` -- 但 `ICellularDeviceRuntimeRepository.GetRuntimesByDeviceCodesAsync` 方法已改为返回 `IList` -- 导致类型不匹配的编译错误 - -### 解决方案 -1. **修改GetDeviceRuntimesAsync方法返回类型**: - - 将返回类型从 `Task>` 改为 `Task>` - - 简化方法实现,直接返回DTO字典,无需类型转换 - -2. **更新相关方法参数类型**: - - `ProcessDeviceStop` 方法参数从 `Dictionary` 改为 `Dictionary` - - `ProcessSingleDevice` 方法参数从 `Dictionary` 改为 `Dictionary` - -3. **修改ProcessSingleDevice方法逻辑**: - - 使用 `CellularDeviceRuntime.CreateForStopOperation` 静态方法从DTO创建临时实体 - - 临时实体用于调用 `Stop()` 方法和创建运行时详情 - -4. **优化SaveDataAsync方法**: - - 移除对临时实体的数据库更新操作 - - 改为通过设备编号获取真实实体,然后调用 `Stop()` 方法更新 - - 避免实体跟踪问题 - -5. **添加必要的using语句**: - - 添加 `using CellularManagement.Domain.Models;` 以使用 `DeviceRuntimeDto` - -### 修改的文件 -- `X1.Application/Features/DeviceRuntimes/Commands/StopDeviceRuntime/StopDeviceRuntimeCommandHandler.cs` -- `X1.Domain/Entities/Device/CellularDeviceRuntime.cs` (之前已添加 `CreateForStopOperation` 方法) - -### 技术要点 -- 使用DTO作为中间数据传输对象,避免复杂的实体转换 -- 临时实体仅用于业务逻辑处理,不用于数据库操作 -- 通过设备编号重新获取真实实体进行数据库更新,确保数据一致性 -- 保持代码简洁性和可维护性 - -### 验证结果 -- 项目编译成功,无类型错误 -- 保持了原有的业务逻辑功能 -- 符合用户"不要瞎改"的要求,只修改必要的类型适配 - ---- - -## 2025-01-29 - 实现ProtocolLogRepository高性能NOT IN查询方法 - -### 修改原因 -根据用户需求,在 `ProtocolLogRepository` 中实现一个高性能的查询方法,用于获取不在活跃运行时状态中的协议日志RuntimeCode和DeviceCode。 - -### 修改文件 - -#### 1. 新增DTO类 -- `X1.Domain/Models/ProtocolLogRuntimeDeviceDto.cs` - 创建新的DTO类,用于返回RuntimeCode和DeviceCode - -#### 2. 接口扩展 -- `X1.Domain/Repositories/Logging/IProtocolLogRepository.cs` - 添加新方法接口定义 - -#### 3. 实现类扩展 -- `X1.Infrastructure/Repositories/Logging/ProtocolLogRepository.cs` - 实现新的查询方法 - -### 修改内容 - -#### 1. 创建ProtocolLogRuntimeDeviceDto -- **类定义**:创建专门用于返回RuntimeCode和DeviceCode的DTO类 -- **属性设计**: - - `RuntimeCode`:运行时代码(string类型) - - `DeviceCode`:设备代码(string类型) -- **用途**:专门用于高性能查询,只返回必要的字段 - -#### 2. 接口方法定义 -- **方法名**:`GetRuntimeDeviceCodesNotInActiveRuntimesAsync` -- **参数**:只包含 `CancellationToken` 参数 -- **返回类型**:`Task>` -- **功能说明**:获取不在活跃运行时状态中的协议日志RuntimeCode和DeviceCode - -#### 3. 实现方法 -- **SQL查询**:使用NOT IN子查询实现高性能查询 -```sql -SELECT tpl."RuntimeCode", tpl."DeviceCode" -FROM "tb_protocol_logs" tpl -WHERE tpl."RuntimeCode" NOT IN ( - SELECT "RuntimeCode" - FROM "tb_cellular_device_runtimes" - WHERE "RuntimeStatus" = 1 -) -GROUP BY tpl."DeviceCode", tpl."RuntimeCode" -``` -- **性能优化**: - - 使用NOT IN子查询,避免复杂的JOIN操作 - - 使用GROUP BY去重,减少返回数据量 - - 只查询必要字段,减少数据传输 -- **错误处理**:完整的异常处理和日志记录 -- **日志记录**:记录查询结果数量,便于性能监控 - -### 技术特性 - -#### 1. 高性能设计 -- **NOT IN子查询**:对于大数据表,NOT IN通常比LEFT JOIN + IS NULL性能更好 -- **字段选择**:只查询必要的RuntimeCode和DeviceCode字段 -- **去重处理**:使用GROUP BY确保结果唯一性 -- **索引利用**:充分利用现有的RuntimeCode索引 - -#### 2. 代码质量 -- **类型安全**:使用强类型的DTO类 -- **异常处理**:完整的try-catch异常处理 -- **日志记录**:详细的调试和错误日志 -- **文档注释**:完整的XML文档注释 - -#### 3. 可维护性 -- **单一职责**:方法职责明确,只负责特定查询 -- **代码复用**:使用现有的QueryRepository基础设施 -- **扩展性**:为未来添加更多过滤条件预留接口 - -### 业务价值 -- **查询性能**:提供高性能的NOT IN查询实现 -- **数据准确性**:确保返回的数据准确反映不在活跃状态中的协议日志 -- **系统稳定性**:通过完善的错误处理提高系统稳定性 -- **开发效率**:为上层应用提供便捷的查询接口 - -### 影响范围 -- **新增功能**:添加了新的查询方法,不影响现有功能 -- **接口扩展**:扩展了仓储接口,提供更多查询能力 -- **性能提升**:为大数据表查询提供了高性能实现 -- **代码质量**:提高了代码的可维护性和可读性 - -### 使用示例 -```csharp -// 在应用层使用 -var inactiveRuntimeDevices = await _protocolLogRepository - .GetRuntimeDeviceCodesNotInActiveRuntimesAsync(cancellationToken); - -foreach (var item in inactiveRuntimeDevices) -{ - Console.WriteLine($"RuntimeCode: {item.RuntimeCode}, DeviceCode: {item.DeviceCode}"); -} -``` - -### 注意事项 -- 该方法适用于大数据表查询,建议在非高峰期使用 -- 查询结果会根据GROUP BY去重,确保唯一性 -- 建议在生产环境中监控查询性能,必要时添加索引优化 - ---- - -## 2025-01-29 - 实现ProtocolLogs查询功能 - -### 修改原因 -根据用户需求,在 `X1.Application.Features.ProtocolLogs.Queries` 中实现查询功能,参考 `GetMessageDetailJsonById` 的实现模式,为 `GetRuntimeDeviceCodesNotInActiveRuntimes` 方法提供完整的应用层支持。 - -### 修改文件 - -#### 1. 新增查询类 -- `X1.Application/Features/ProtocolLogs/Queries/GetRuntimeDeviceCodesNotInActiveRuntimes/GetRuntimeDeviceCodesNotInActiveRuntimesQuery.cs` - 查询请求类 - -#### 2. 新增响应类 -- `X1.Application/Features/ProtocolLogs/Queries/GetRuntimeDeviceCodesNotInActiveRuntimes/GetRuntimeDeviceCodesNotInActiveRuntimesResponse.cs` - 查询响应类 - -#### 3. 新增查询处理器 -- `X1.Application/Features/ProtocolLogs/Queries/GetRuntimeDeviceCodesNotInActiveRuntimes/GetRuntimeDeviceCodesNotInActiveRuntimesQueryHandler.cs` - 查询处理器 - -#### 4. 扩展控制器 -- `X1.Presentation/Controllers/ProtocolLogsController.cs` - 添加新的API端点 - -### 修改内容 - -#### 1. 查询类设计 -- **类名**:`GetRuntimeDeviceCodesNotInActiveRuntimesQuery` -- **接口实现**:`IRequest>` -- **参数设计**:无需参数,直接获取所有符合条件的记录 -- **设计模式**:遵循CQRS模式,使用MediatR进行查询处理 - -#### 2. 响应类设计 -- **类名**:`GetRuntimeDeviceCodesNotInActiveRuntimesResponse` -- **属性设计**: - - `Items`:`IEnumerable` - 数据集合 - - `TotalCount`:`int` - 总数量 - - `HasData`:`bool` - 是否有数据(计算属性) -- **数据模型**:使用之前创建的 `ProtocolLogRuntimeDeviceDto` 作为数据模型 - -#### 3. 查询处理器实现 -- **类名**:`GetRuntimeDeviceCodesNotInActiveRuntimesQueryHandler` -- **接口实现**:`IRequestHandler>` -- **依赖注入**: - - `IProtocolLogRepository` - 协议日志仓储 - - `ILogger` - 日志记录器 -- **业务逻辑**: - - 调用仓储方法获取数据 - - 构建响应对象 - - 完整的错误处理和日志记录 - -#### 4. 控制器扩展 -- **API端点**:`GET /api/protocollogs/runtime-device-codes-not-in-active-runtimes` -- **方法名**:`GetRuntimeDeviceCodesNotInActiveRuntimes` -- **认证要求**:需要授权访问 -- **响应格式**:`OperationResult` -- **日志记录**:完整的请求和响应日志记录 - -### 技术特性 - -#### 1. CQRS模式实现 -- **查询分离**:查询逻辑与命令逻辑分离 -- **MediatR集成**:使用MediatR进行查询处理 -- **单一职责**:每个类都有明确的职责 -- **可测试性**:便于单元测试和集成测试 - -#### 2. 错误处理 -- **异常捕获**:完整的try-catch异常处理 -- **错误响应**:使用 `OperationResult` 统一错误响应格式 -- **日志记录**:详细的错误日志记录,便于问题排查 - -#### 3. 性能优化 -- **异步处理**:使用async/await进行异步操作 -- **取消令牌**:支持CancellationToken进行操作取消 -- **数据转换**:高效的数据转换和映射 - -#### 4. 代码质量 -- **文档注释**:完整的XML文档注释 -- **命名规范**:遵循C#命名规范 -- **代码结构**:清晰的代码结构和职责分离 - -### 业务价值 -- **功能完整性**:为NOT IN查询提供完整的应用层支持 -- **API一致性**:与其他API端点保持一致的接口设计 -- **开发效率**:提供标准化的查询处理模式 -- **系统稳定性**:通过完善的错误处理提高系统稳定性 - -### 影响范围 -- **新增功能**:添加了新的查询功能和API端点 -- **接口扩展**:扩展了应用层的查询能力 -- **架构完善**:完善了CQRS模式的实现 -- **开发体验**:提供了标准化的查询开发模式 - -### 使用示例 -```csharp -// 在控制器中使用 -[HttpGet("runtime-device-codes-not-in-active-runtimes")] -public async Task> GetRuntimeDeviceCodesNotInActiveRuntimes() -{ - var query = new GetRuntimeDeviceCodesNotInActiveRuntimesQuery(); - var result = await mediator.Send(query); - return result; -} - -// 在应用层使用 -var handler = new GetRuntimeDeviceCodesNotInActiveRuntimesQueryHandler(repository, logger); -var query = new GetRuntimeDeviceCodesNotInActiveRuntimesQuery(); -var result = await handler.Handle(query, CancellationToken.None); -``` - -### 注意事项 -- 该查询适用于大数据表,建议在非高峰期使用 -- 查询结果会返回所有符合条件的记录,注意内存使用 -- 建议在生产环境中监控API性能,必要时进行优化 -- 遵循现有的错误处理和日志记录模式 +#### 修改时间: +2024年 ---- \ No newline at end of file +#### 修改原因: +用户需要一个新的方法来获取不在活跃运行时状态中的协议日志,同时保持与现有 `GetByDeviceWithFiltersAsync` 方法相同的参数和过滤条件。 \ No newline at end of file