278 KiB
修改记录
2025-01-29 - StopDeviceRuntimeCommandHandler重构优化
修改概述
根据用户需求,对StopDeviceRuntimeCommandHandler进行了全面重构,主要改进包括:
- 将Handle方法重构为多个私有方法,提高代码可读性
- 修复StopNetworkAsync的并行执行问题
- 提取方法以提高代码的可维护性
- 修复代码中的错误和逻辑问题
修改文件
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命令进行了批量操作性能优化,主要包括:
- 修改StopDeviceRuntimeCommand支持批量操作,参考StartDeviceRuntimeCommand结构
- 更新StopDeviceRuntimeResponse支持批量操作响应
- 重构StopDeviceRuntimeCommandHandler使用批量数据库操作
- 添加仓储批量操作方法,提高数据库操作性能
- 更新控制器支持批量停止操作,保持向后兼容性
修改文件
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. 批量停止设备
POST /api/device-runtimes/stop
Content-Type: application/json
{
"deviceRequests": [
{ "deviceCode": "DEV001", "networkStackCode": "STACK001" },
{ "deviceCode": "DEV002", "networkStackCode": "STACK002" },
{ "deviceCode": "DEV003", "networkStackCode": "STACK003" }
]
}
2. 单个设备停止(向后兼容)
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'.
解决方案
- 使用 IServiceScopeFactory:将直接注入的作用域服务改为注入 IServiceScopeFactory
- 创建安全的作用域执行方法:
ExecuteInScopeAsync<T>()
- 用于有返回值的操作ExecuteInScopeAsync()
- 用于无返回值的操作
- 统一错误处理:在作用域执行方法中统一处理异常和资源释放
修改的文件
X1.Application/BackendServiceManager/DeviceManagementService.cs
修改内容
-
构造函数参数修改:
- 移除:
ICellularDeviceRepository deviceRepository
- 移除:
IProtocolLogRepository repository
- 移除:
IUnitOfWork unitOfWork
- 添加:
IServiceScopeFactory serviceScopeFactory
- 移除:
-
添加安全的作用域执行方法:
private async Task<T> ExecuteInScopeAsync<T>(Func<IServiceProvider, Task<T>> operation, CancellationToken cancellationToken = default) private async Task ExecuteInScopeAsync(Func<IServiceProvider, Task> operation, CancellationToken cancellationToken = default)
-
修改所有使用作用域服务的方法:
ProcessProtocolLogs()
- 使用 ExecuteInScopeAsync 包装ProcessProtocolLogsIndividually()
- 使用 ExecuteInScopeAsync 包装InitializeDeviceEndpointsAsync()
- 使用 ExecuteInScopeAsync 包装
风险缓解措施
- 内存泄漏防护:使用 using 语句确保作用域正确释放
- 异常处理:统一的作用域异常处理和日志记录
- 资源管理:自动的作用域生命周期管理
- 代码可读性:通过辅助方法提高代码可读性和维护性
注意事项
- 每次调用都会创建新的作用域,有一定性能开销
- 需要确保所有作用域服务的使用都通过 ExecuteInScopeAsync 方法
- 异步操作中的作用域管理需要特别注意
潜在风险
- 内存泄漏风险:如果忘记使用 using 语句,会导致作用域无法正确释放
- 性能开销:每次调用都需要创建新的作用域,作用域创建和销毁有性能成本
- 资源管理复杂性:需要手动管理作用域的生命周期,错误处理时需要确保作用域正确释放
- 依赖关系不明确:从构造函数中无法直接看出服务依赖了哪些作用域服务
更好的解决方案
- 服务工厂模式:使用安全的作用域执行方法,统一管理作用域生命周期
- 错误处理增强:在作用域执行方法中统一处理异常和资源释放
- 代码可读性:通过辅助方法提高代码可读性和维护性
- 性能优化:避免频繁创建作用域,考虑缓存常用服务
错误处理优化
- 记录错误但不抛出:在作用域执行方法中记录错误日志,但不重新抛出异常
- 返回默认值:对于有返回值的方法,在异常时返回默认值
- 静默处理:对于无返回值的方法,在异常时静默处理,避免异常传播
- 日志记录:保持详细的错误日志记录,便于问题排查
代码健壮性增强
- 参数验证:添加操作委托和服务作用域工厂的空值检查
- 取消令牌支持:在执行操作前检查取消令牌状态
- 返回值验证:对于引用类型,检查返回值是否为null并记录警告
- 异常分类处理:
OperationCanceledException
:操作被取消,记录信息日志ObjectDisposedException
:服务作用域已被释放,记录错误日志InvalidOperationException
:作用域操作无效,记录错误日志Exception
:其他未预期的错误,记录详细错误信息
- 详细错误信息:在日志中包含具体的错误消息,便于问题排查
- 代码简化:移除冗余的
ExecuteInScopeAsync<T>
方法,统一使用ExecuteInScopeWithResultAsync<T>
通用化重构
- 提取通用接口:创建
IServiceScopeExecutor
接口,定义作用域服务执行的标准方法 - 创建通用实现:创建
ServiceScopeExecutor
类,实现IServiceScopeExecutor
接口 - 重命名结果类:将
OperationResult<T>
重命名为ScopeOperationResult<T>
,使其更加具体和明确 - 添加无返回值结果类:创建
ScopeOperationResult
类,用于无返回值的操作 - 接口设计:
ExecuteWithResultAsync<T>()
- 用于有返回值的操作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<CellularDeviceRuntimeDetail>
基类 - 接口实现:实现
ICellularDeviceRuntimeDetailRepository
接口的所有方法 - 依赖注入:通过构造函数注入
ICommandRepository
、IQueryRepository
和ILogger
2. 核心方法实现
- GetDetailsByRuntimeCodeAsync:根据运行编码查询明细列表
- GetDetailsByCreatedByAsync:根据创建人查询明细列表(按创建时间倒序)
- GetDetailsByRuntimeStatusAsync:根据运行时状态查询明细列表(按创建时间倒序)
- SearchDetailsAsync:支持多条件分页查询(运行编码、创建人、状态、时间范围)
- GetDetailCountAsync:获取明细记录总数
- AddDetailsRangeAsync:批量添加明细记录
3. 查询优化
- 条件组合:支持多个查询条件的组合查询
- 分页支持:提供标准的分页查询功能
- 排序优化:查询结果按创建时间倒序排列
- 性能考虑:利用数据库索引提升查询性能
4. 错误处理
- 空值处理:正确处理可选的查询参数
- 异常传播:将底层仓储的异常向上传播
- 日志记录:通过注入的Logger记录操作日志
技术特性
- CQRS模式:使用命令和查询分离的仓储模式
- 异步操作:所有方法都支持异步操作和取消令牌
- 类型安全:使用强类型的查询表达式
- 可扩展性:基于基类设计,便于扩展和维护
业务价值
- 数据查询:提供完整的运行时明细数据查询功能
- 历史追踪:支持按时间、状态、用户等维度追踪设备运行历史
- 统计分析:支持明细数据的统计和分页查询
- 批量操作:支持批量添加明细记录,提高数据录入效率
影响范围
- 依赖注入:修复了
ICellularDeviceRuntimeDetailRepository
的依赖注入问题 - 应用层:
StartDeviceRuntimeCommandHandler
现在可以正常使用明细仓储 - 数据访问:提供了完整的运行时明细数据访问能力
2025-01-29 - 修复StartDeviceRuntimeCommandHandler中网络启动返回值记录问题
修改原因
IInstrumentProtocolClient.StartNetworkAsync
方法返回 Task<bool>
表示网络启动是否成功,但原代码没有记录这个返回值,导致无法准确判断网络启动的实际结果。
修改文件
X1.Application/Features/DeviceRuntimes/Commands/StartDeviceRuntime/StartDeviceRuntimeCommandHandler.cs
- 修复网络启动返回值记录
修改内容
1. 记录网络启动返回值
- 获取返回值:将
await _protocolClient.StartNetworkAsync(networkRequest)
的返回值保存到startResult
变量 - 记录启动结果:添加日志记录网络启动的实际结果(成功/失败)
- 条件处理:根据返回值决定是否将设备标记为成功启动
2. 具体修改
// 修改前
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. 方法签名设计
private List<CellularNetworkConfiguration> BuildNetworkConfigurationRequests(
StartDeviceRuntimeCommand request,
IEnumerable<NetworkStackConfigBasicDto> 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函数式编程风格,提高代码可读性和维护性
业务价值
- 代码可读性:主方法逻辑更清晰,易于理解
- 可维护性:网络配置请求构建逻辑独立,便于修改和测试
- 可复用性:提取的方法可以在其他地方复用
- 调试便利:独立的日志记录,便于问题排查
影响范围
- 代码结构:改善了代码组织结构,提高了可读性
- 维护性:网络配置请求构建逻辑独立,便于后续维护
- 性能:保持了原有的性能特性,没有引入额外的开销
后续工作建议
- 单元测试:为BuildNetworkConfigurationRequestsAsync方法添加单元测试
- 性能监控:监控网络配置请求构建的性能表现
- 错误处理:进一步完善错误处理机制
- 文档更新:更新相关技术文档
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<T>
包装响应 - 详细的错误信息记录
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 类型定义
- 开发体验:统一的服务接口,便于前端开发使用
后续工作建议
- 前端页面开发:基于这些服务开发对应的前端页面
- 组件开发:开发设备运行时状态显示组件
- 状态管理:集成到前端状态管理系统中
- 错误处理:完善错误处理和用户提示
- 测试验证:为所有服务方法添加单元测试
2025-01-29 修复设备运行时服务接口与后端控制器完全对应
修改原因
确保前端设备运行时服务的接口定义与后端控制器完全对应,避免数据类型不匹配和字段缺失问题。
修改文件
X1.WebUI/src/services/deviceRuntimeService.ts
- 更新接口定义以匹配后端响应实体
修改内容
1. 设备运行时信息接口 (DeviceRuntime)
对应后端 DeviceRuntimeDto:
deviceCode: string
- 设备编号runtimeStatus: number
- 运行时状态(对应后端的 int 类型)networkStackCode?: string
- 网络栈配置编号name?: string
- 设备名称(对应后端的 Name 字段)createdAt: string
- 创建时间(对应后端的 DateTime)
2. 获取设备运行时状态响应接口 (GetDeviceRuntimeStatusResponse)
对应后端 GetDeviceRuntimeStatusResponse:
deviceCode: string
- 设备编号runtimeStatus: string
- 运行时状态(对应后端的 string 类型)runtimeCode?: string
- 运行编码networkStackCode?: string
- 网络栈配置编号
3. 启动设备请求接口 (StartDeviceRequest)
对应后端 DeviceStartRequest:
deviceCode: string
- 设备编号networkStackCode: string
- 网络栈配置编号(必填字段)
4. 启动设备响应接口 (StartDeviceRuntimeResponse)
对应后端 StartDeviceRuntimeResponse:
id?: string
- 运行时状态IDdeviceCode?: string
- 设备编号runtimeStatus?: string
- 运行时状态networkStackCode?: string
- 网络栈配置编号updatedAt: string
- 更新时间deviceResults?: DeviceStartResult[]
- 设备启动结果列表summary?: BatchOperationSummary
- 批量操作统计
5. 设备启动结果接口 (DeviceStartResult)
对应后端 DeviceStartResult:
deviceCode: string
- 设备编号id: string
- 运行时状态IDruntimeStatus: string
- 运行时状态networkStackCode?: string
- 网络栈配置编号updatedAt: string
- 更新时间isSuccess: boolean
- 是否成功errorMessage?: string
- 错误信息
6. 批量操作统计接口 (BatchOperationSummary)
对应后端 BatchOperationSummary:
totalCount: number
- 总设备数successCount: number
- 成功数量failureCount: number
- 失败数量successRate: number
- 成功率(对应后端的计算属性)
7. 停止设备响应接口 (StopDeviceRuntimeResponse)
对应后端 StopDeviceRuntimeResponse:
id: string
- 运行时状态IDdeviceCode: string
- 设备编号runtimeStatus: string
- 运行时状态runtimeCode?: string
- 运行编码networkStackCode?: string
- 网络栈配置编号updatedAt: string
- 更新时间
技术改进
1. 状态类型处理
- 数字状态转换:添加
getRuntimeStatusString()
方法,将数字状态转换为字符串状态 - 状态描述方法:更新
getRuntimeStatusDescription()
和getRuntimeStatusColor()
方法,支持数字和字符串状态 - 状态映射:
- 0: Initializing(初始化)
- 1: Running(运行中)
- 2: Stopped(已停止)
- 3: Error(错误)
2. 查询参数处理
- 运行时状态过滤:修复
runtimeStatus
参数处理,支持数字类型 - 参数验证:使用
!== undefined
检查,避免 0 值被忽略
3. 接口注释
- 对应关系说明:为每个接口添加注释,说明对应的后端实体
- 字段类型说明:标注字段类型与后端的对应关系
影响范围
- 类型安全:确保前端接口定义与后端API完全匹配
- 数据一致性:避免因字段不匹配导致的数据丢失
- 开发体验:提供准确的类型提示和代码补全
- 错误减少:减少运行时类型错误
使用示例更新
// 获取设备运行时状态列表(使用数字状态过滤)
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' }
]);
// 处理启动结果
if (startResult.isSuccess && startResult.data?.summary) {
console.log(`启动完成:总数 ${startResult.data.summary.totalCount},成功 ${startResult.data.summary.successCount},失败 ${startResult.data.summary.failureCount}`);
}
2025-01-29 实现设备运行时管理前端界面
修改原因
为设备运行时管理功能实现完整的前端界面,包括列表页面、详情页面、搜索功能、批量操作等,提供用户友好的操作体验。
新增文件
1. 设备运行时管理页面
X1.WebUI/src/pages/device-runtimes/DeviceRuntimesView.tsx
- 设备运行时管理主页面X1.WebUI/src/pages/device-runtimes/DeviceRuntimesTable.tsx
- 设备运行时表格组件X1.WebUI/src/pages/device-runtimes/DeviceRuntimeDetail.tsx
- 设备运行时详情页面
修改文件
1. 路由配置
X1.WebUI/src/routes/AppRouter.tsx
- 添加设备运行时管理路由
2. 菜单配置
X1.WebUI/src/constants/menuConfig.ts
- 添加设备运行时管理菜单项和权限
3. 服务接口
X1.WebUI/src/services/deviceRuntimeService.ts
- 修复GetDeviceRuntimeStatusResponse接口,添加updatedAt字段
功能特性
1. 设备运行时管理主页面 (DeviceRuntimesView.tsx)
- 统计卡片:显示总设备数、运行中、已停止、错误状态的数量
- 搜索功能:支持按设备编号/名称搜索、按运行时状态过滤
- 批量操作:支持批量启动设备,需要指定网络栈配置编号
- 表格显示:显示设备运行时状态列表,支持分页、排序、列显示控制
- 实时操作:支持单个设备停止操作
2. 设备运行时表格组件 (DeviceRuntimesTable.tsx)
- 选择功能:支持单选、全选设备
- 状态显示:使用不同颜色的Badge显示运行时状态
- 操作菜单:根据设备状态显示不同的操作选项
- 响应式设计:支持紧凑、默认、舒适三种密度模式
- 加载状态:显示加载中和空数据状态
3. 设备运行时详情页面 (DeviceRuntimeDetail.tsx)
- 状态概览:显示设备运行时状态和基本信息
- 详细信息:分卡片显示网络配置和时间信息
- 实时刷新:支持手动刷新设备状态
- 状态持续时间:计算并显示当前状态的持续时间
- 导航功能:提供返回列表的导航
技术特性
1. 组件设计
- 模块化:将功能拆分为独立的组件,便于维护和复用
- 类型安全:完整的TypeScript类型定义
- 响应式:支持不同屏幕尺寸的响应式布局
- 可访问性:遵循ARIA标准,支持键盘导航
2. 状态管理
- 本地状态:使用React hooks管理组件状态
- 加载状态:统一的加载和错误状态处理
- 表单状态:搜索条件和批量操作的表单状态管理
3. 用户体验
- 即时反馈:操作后立即显示结果和状态变化
- 错误处理:友好的错误提示和恢复机制
- 操作确认:重要操作提供确认对话框
- 进度指示:长时间操作显示进度状态
界面功能
1. 搜索和过滤
// 搜索条件
const searchConditions = {
searchTerm: string, // 设备编号或名称
runtimeStatus: number, // 运行时状态过滤
pageSize: number // 每页显示数量
};
2. 批量操作
// 批量启动设备
const batchStartDevices = async (deviceCodes: string[], networkStackCode: string) => {
const deviceRequests = deviceCodes.map(code => ({
deviceCode: code,
networkStackCode: networkStackCode
}));
return await startDevices(deviceRequests);
};
3. 状态显示
// 状态映射
const statusMapping = {
0: { text: '初始化', color: 'default' },
1: { text: '运行中', color: 'success' },
2: { text: '已停止', color: 'warning' },
3: { text: '错误', color: 'error' }
};
路由配置
1. 新增路由
// 设备运行时管理路由
<Route path="device-runtimes">
<Route index element={<Navigate to="list" replace />} />
<Route path="list" element={<DeviceRuntimesView />} />
<Route path="detail/:deviceCode" element={<DeviceRuntimeDetail />} />
</Route>
2. 权限控制
// 权限配置
const permissions = {
'deviceruntimes.view': '查看设备运行时',
'deviceruntimes.manage': '管理设备运行时'
};
菜单配置
1. 新增菜单项
{
title: '设备运行时',
icon: Gauge,
href: '/dashboard/device-runtimes',
permission: 'deviceruntimes.view',
children: [
{
title: '运行时状态',
href: '/dashboard/device-runtimes/list',
permission: 'deviceruntimes.view',
}
],
}
使用流程
1. 查看设备运行时状态
- 导航到"设备运行时" → "运行时状态"
- 查看设备运行时状态列表
- 使用搜索和过滤功能查找特定设备
- 点击设备编号查看详细信息
2. 批量启动设备
- 在设备列表中勾选要启动的设备
- 点击"批量启动"按钮
- 在弹出的对话框中输入网络栈配置编号
- 确认启动操作
3. 停止单个设备
- 在设备列表中找到运行中的设备
- 点击操作菜单中的"停止设备"
- 确认停止操作
4. 查看设备详情
- 点击设备编号进入详情页面
- 查看设备的运行时状态、网络配置等信息
- 使用刷新按钮更新状态
- 返回列表页面
影响范围
- 前端界面:提供了完整的设备运行时管理界面
- 用户体验:改善了设备运行时管理的操作体验
- 功能完整性:实现了设备运行时管理的所有核心功能
- 系统集成:与现有的权限系统和导航系统完全集成
后续优化建议
- 实时更新:添加WebSocket支持,实现设备状态的实时更新
- 历史记录:添加设备运行时历史记录查看功能
- 批量导入:支持批量导入设备配置
- 监控告警:添加设备状态异常告警功能
- 操作日志:记录和查看设备操作历史
修改原因
根据后端 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<T>
包装响应 - 详细的错误信息记录
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: DeviceRuntimeStatus.Running
});
// 启动设备
const startResult = await deviceRuntimeService.startDevices([
{ deviceCode: 'DEV001', deviceName: '设备1' },
{ deviceCode: 'DEV002', deviceName: '设备2' }
]);
// 停止设备
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 类型定义
- 开发体验:统一的服务接口,便于前端开发使用
后续工作建议
- 前端页面开发:基于这些服务开发对应的前端页面
- 组件开发:开发设备运行时状态显示组件
- 状态管理:集成到前端状态管理系统中
- 错误处理:完善错误处理和用户提示
- 测试验证:为所有服务方法添加单元测试
2025-01-29 更新instrumentService.ts和DevicesView.tsx以匹配后端API
修改原因
根据后端API的响应结构,需要更新前端的接口定义和组件,确保前后端数据格式一致。主要变化包括:
- 添加
runtimeStatus
字段到设备接口 - 移除
isRunning
字段(后端没有这个字段) - 更新表格显示以包含运行时状态
修改文件
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完全匹配
- 用户界面:设备列表显示运行时状态信息
- 数据完整性:确保所有设备数据都能正确显示
- 开发体验:提供完整的类型安全和代码提示
测试建议
- 测试设备列表的显示,确认运行时状态正确显示
- 验证不同状态的颜色编码是否正确
- 测试设备创建和编辑功能,确认表单正常工作
- 检查表格列配置,确认列显示顺序正确
- 验证搜索和过滤功能是否正常工作
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
// 修改前
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. 执行顺序
- 检查设备是否存在
- 软删除相关的设备运行时状态记录
- 删除设备本身
- 保存所有更改到数据库
4. 软删除基础设施
- BaseEntity接口实现:让
BaseEntity
实现ISoftDelete
接口 - 软删除机制:利用
UnitOfWork
中的软删除逻辑,自动将删除操作转换为软删除 - 查询过滤:通过 Entity Framework 的查询过滤器自动过滤已删除的记录
- 删除流程:
DeleteRuntimeByDeviceCodeAsync
→CommandRepository.DeleteWhereAsync
→UnitOfWork.SaveChangesAsync
→ 自动软删除
技术特性
- 数据一致性:确保设备删除时相关的运行时记录也被正确处理
- 软删除机制:利用
BaseEntity
的IsDeleted
字段实现软删除 - 事务安全:在同一个事务中执行所有删除操作
- 错误处理:保持原有的异常处理机制
业务价值
- 数据完整性:避免孤立的运行时记录
- 审计追踪:软删除保留历史数据,便于审计
- 系统稳定性:确保删除操作的原子性和一致性
影响范围
- 删除操作:设备删除时会同时处理运行时记录
- 数据存储:运行时记录被标记为已删除而非物理删除
- 查询结果:软删除的记录不会出现在正常查询结果中
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. 具体修改
// 修改前
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. 原子性操作流程
- 创建设备实体:使用
CellularDevice.Create()
创建设备 - 创建运行时状态实体:使用
CellularDeviceRuntime.Create()
创建运行时状态 - 添加到仓储:将两个实体分别添加到对应的仓储
- 原子性保存:调用
_unitOfWork.SaveChangesAsync()
一次性保存所有更改 - 错误处理:如果保存失败,整个事务回滚
5. 运行时状态配置
- 初始状态:新创建的设备运行时状态设置为
DeviceRuntimeStatus.Initializing
- 网络栈配置:初始时
NetworkStackCode
为null
- 创建者信息:记录创建运行时状态的用户ID
- 时间戳:自动设置创建和更新时间
技术特性
- 事务安全:通过工作单元模式确保数据一致性
- 原子性操作:设备和运行时状态创建要么全部成功,要么全部失败
- 错误回滚:任一操作失败时自动回滚整个事务
- 日志记录:完整的操作日志,便于问题排查
- 状态管理:统一的设备运行时状态管理
业务价值
- 数据一致性:确保设备和运行时状态的数据一致性
- 状态跟踪:为每个设备提供运行时状态跟踪
- 监控能力:支持设备运行状态的实时监控
- 系统稳定性:通过原子性操作提高系统稳定性
影响范围
- 设备创建流程:设备创建时会同时创建运行时状态(原子性操作)
- 数据库操作:增加运行时状态表的插入操作,但保证原子性
- 错误处理:统一的错误处理,确保数据一致性
- 日志记录:增加运行时状态创建相关的日志
原子性保证
- 事务边界:整个创建过程在一个事务中完成
- 回滚机制:如果运行时状态创建失败,设备创建也会回滚
- 数据完整性:确保不会出现只有设备没有运行时状态的情况
- 一致性保证:通过数据库事务确保ACID特性
后续工作建议
- 测试验证:测试设备创建和运行时状态创建的完整流程
- 事务测试:测试事务回滚机制是否正常工作
- 性能监控:监控原子性操作对性能的影响
- 错误处理验证:验证各种错误情况下的回滚机制
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接口
- 业务逻辑:新增设备启动/停止的业务逻辑
- 数据访问:通过仓储层访问设备运行时状态数据
- 前端集成:为前端提供设备运行时状态管理接口
后续工作建议
- 单元测试:为所有命令和查询处理器编写单元测试
- 集成测试:测试API接口的完整功能
- 前端开发:开发设备运行时状态管理的前端界面
- 文档编写:编写API接口文档和使用说明
- 性能优化:根据实际使用情况优化查询性能
2025-01-29 优化GetRuntimeByDeviceCodeAsync方法返回最新记录
修改原因
根据用户需求,GetRuntimeByDeviceCodeAsync
方法需要返回按创建时间排序的最新一条记录,而不是任意一条记录。
修改文件
X1.Infrastructure/Repositories/Device/CellularDeviceRuntimeRepository.cs
- 优化GetRuntimeByDeviceCodeAsync方法
修改内容
1. 方法实现优化
- 原实现:使用
FirstOrDefaultAsync
直接查询,返回任意一条匹配记录 - 新实现:使用
FindAsync
查询所有匹配记录,然后按CreatedAt
降序排序,返回第一条记录
2. 查询逻辑
var runtimes = await QueryRepository.FindAsync(r => r.DeviceCode == deviceCode, cancellationToken: cancellationToken);
return runtimes.OrderByDescending(r => r.CreatedAt).FirstOrDefault();
3. 性能考虑
- 内存排序:在应用层进行排序,适用于记录数量较少的情况
- 数据库排序:如果记录数量较多,建议在数据库层进行排序优化
技术特性
- 数据准确性:确保返回的是最新创建的运行时状态记录
- 向后兼容:方法签名保持不变,不影响现有调用
- 错误处理:保持原有的空值处理逻辑
业务价值
- 状态准确性:获取设备的最新运行时状态,而不是历史状态
- 数据一致性:确保查询结果的一致性,避免返回过时的状态信息
- 用户体验:提供更准确的设备状态信息
影响范围
- 查询结果:现在返回的是按创建时间排序的最新记录
- 性能影响:对于有多个运行时状态记录的设备,会有轻微的性能影响
- API行为:API返回的数据更加准确和有意义
后续工作建议
- 性能监控:监控查询性能,特别是对于有大量历史记录的设备
- 索引优化:考虑在数据库层面添加
(DeviceCode, CreatedAt)
的复合索引 - 数据清理:考虑清理过时的运行时状态记录,减少数据量
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方法替代静态JSX,确保每个按钮都有唯一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
,导致可访问性警告
修复内容
-
Dialog组件导出:
- 在
dialog.tsx
中添加DialogTitle
和DialogDescription
的导出
- 在
-
RAN配置视图:
- 添加
DialogTitle
导入 - 为创建和编辑对话框添加标题:"创建RAN配置" 和 "编辑RAN配置"
- 添加
-
IMS配置视图:
- 添加
DialogTitle
导入 - 为创建和编辑对话框添加标题:"创建IMS配置" 和 "编辑IMS配置"
- 添加
-
核心网络配置视图:
- 添加
DialogTitle
导入 - 为创建和编辑对话框添加标题:"创建核心网络配置" 和 "编辑核心网络配置"
- 添加
技术说明
- 确保所有Dialog组件都符合Radix UI的可访问性要求
- 为屏幕阅读器用户提供更好的体验
- 添加语义化的对话框标题,提高用户体验
- 使用一致的样式:
text-lg font-semibold mb-4
2024-12-19 修复配置字段名不匹配问题
问题描述
- 前端接口定义与后端API返回的数据字段名不匹配
- 导致前端访问配置ID时出现 undefined 错误
RAN配置修复内容
-
修复前端接口定义:
RANConfiguration
接口:id
→raN_ConfigurationId
CreateRANConfigurationResponse
接口:id
→raN_ConfigurationId
UpdateRANConfigurationRequest
接口:id
→raN_ConfigurationId
UpdateRANConfigurationResponse
接口:id
→raN_ConfigurationId
-
修复表格组件:
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}}
-
修复视图组件:
RANConfigurationsView.tsx
:删除和更新操作中的字段引用configuration.id
→configuration.raN_ConfigurationId
selectedConfiguration.id
→selectedConfiguration.raN_ConfigurationId
IMS配置修复内容
-
修复前端接口定义:
IMSConfiguration
接口:imsConfigurationId
→ims_ConfigurationId
CreateIMSConfigurationResponse
接口:imsConfigurationId
→ims_ConfigurationId
UpdateIMSConfigurationRequest
接口:imsConfigurationId
→ims_ConfigurationId
UpdateIMSConfigurationResponse
接口:imsConfigurationId
→ims_ConfigurationId
-
修复表格组件:
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}}
-
修复视图组件:
IMSConfigurationsView.tsx
:删除和更新操作中的字段引用configuration.imsConfigurationId
→configuration.ims_ConfigurationId
selectedConfiguration.imsConfigurationId
→selectedConfiguration.ims_ConfigurationId
核心网络配置修复内容
-
修复前端接口定义:
CoreNetworkConfig
接口:coreNetworkConfigId
→CoreNetworkConfigId
CreateCoreNetworkConfigResponse
接口:coreNetworkConfigId
→CoreNetworkConfigId
UpdateCoreNetworkConfigRequest
接口:coreNetworkConfigId
→CoreNetworkConfigId
UpdateCoreNetworkConfigResponse
接口:coreNetworkConfigId
→CoreNetworkConfigId
-
修复表格组件:
CoreNetworkConfigsTable.tsx
:config.coreNetworkConfigId
→config.CoreNetworkConfigId
- 表格行key:
key={config.coreNetworkConfigId}
→key={config.CoreNetworkConfigId}
- 表格单元格key:
key={
${config.coreNetworkConfigId}-${column.key}}
→key={
${config.CoreNetworkConfigId}-${column.key}}
-
修复视图组件:
CoreNetworkConfigsView.tsx
:删除和更新操作中的字段引用config.coreNetworkConfigId
→config.CoreNetworkConfigId
selectedConfig.coreNetworkConfigId
→selectedConfig.CoreNetworkConfigId
技术说明
- 统一前后端字段命名规范
- 确保前端接口定义与后端API返回数据格式一致
- 修复所有相关的字段引用
- 避免运行时出现 undefined 错误
- 注意后端返回的字段名大小写:
- RAN配置:
raN_ConfigurationId
- IMS配置:
ims_ConfigurationId
- 核心网络配置:
CoreNetworkConfigId
- RAN配置:
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 管理搜索状态和高亮内容
使用方式
<ConfigContentEditor
value={configContent}
onChange={setConfigContent}
placeholder="请输入配置内容"
rows={8}
required
disabled={false}
label="配置内容"
/>
界面布局
- 工具栏:只包含搜索按钮
- 搜索栏:可展开的搜索输入框和导航按钮
- 编辑器:主要的文本编辑区域,支持高亮显示
- 高亮层:覆盖在编辑器上的透明高亮层
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使用等宽字体,提高可读性
使用方式
- 通过菜单 "网络栈配置" 访问页面
- 支持创建、编辑、删除网络栈配置
- 支持按栈ID、描述搜索配置
- 支持按激活状态过滤配置
- 支持调整表格显示密度和列显示
- 编辑时栈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风格
- 响应式布局
- 美观的表格和表单设计
使用方式
- 通过菜单 "仪表管理" -> "核心网络配置" 访问页面
- 支持创建、编辑、删除核心网络配置
- 支持按名称、描述搜索配置
- 支持按启用状态过滤配置
- 支持调整表格显示密度和列显示
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风格
- 响应式布局
- 美观的表格和表单设计
使用方式
- 通过菜单 "仪表管理" -> "IMS配置" 访问页面
- 支持创建、编辑、删除IMS配置
- 支持按名称、描述搜索配置
- 支持按启用状态过滤配置
- 支持调整表格显示密度和列显示
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风格
- 响应式布局
- 美观的表格和表单设计
使用方式
- 通过菜单 "仪表管理" -> "RAN配置" 访问页面
- 支持创建、编辑、删除RAN配置
- 支持按名称、描述搜索配置
- 支持按启用状态过滤配置
- 支持调整表格显示密度和列显示
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 倍 - 原因:确保有足够空间处理分片消息,避免溢出
- 代码:
var bufferSize = (int)(_options.MaxMessageSize * 1.5);
using var messageBuffer = new WebSocketMessageBuffer(bufferSize);
2. 改进缓冲区写入逻辑
- 修复:在写入前检查总大小是否会超过限制
- 原因:提前检测溢出风险,避免不必要的写入操作
- 代码:
var totalSize = messageBuffer.Size + receiveResult.Count;
if (totalSize > _options.MaxMessageSize)
{
throw new WebSocketException("消息大小超过限制");
}
3. 增强分片消息处理
- 修复:添加分片消息的详细日志记录
- 原因:便于调试和监控分片消息的处理过程
- 代码:
_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%,但避免了溢出错误
- 处理效率:提前检测大小限制,避免无效的写入操作
- 稳定性:正确处理分片消息,提高系统稳定性
- 可维护性:详细的日志记录,便于问题排查
测试建议
- 测试大型消息的分片传输
- 验证缓冲区大小限制的正确性
- 检查分片消息的完整重组
- 监控内存使用情况
- 验证错误处理的正确性
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 异常通常不可恢复,不需要重试
- 代码:
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
- 内存优化:减少不必要的对象创建
- 代码简化:提高代码可读性和维护性
性能影响
- 响应速度:减少无效重试,提高错误响应速度
- 资源使用:减少系统资源浪费
- 稳定性:更准确的错误处理,提高系统稳定性
- 可维护性:代码更清晰,便于维护和调试
测试建议
- 测试缓冲区满时的错误处理
- 验证不同类型异常的处理策略
- 检查重试机制的正确性
- 监控系统资源使用情况
- 验证错误日志的准确性
2024-12-19 HandleWebSocketConnection 缓冲区大小修复
修改文件
X1.WebSocket/Middleware/WebSocketMiddleware.cs
问题描述
- 原实现中 buffer 大小为 4KB(
1024 * 4
),与 WebSocketOptions.MaxMessageSize(如 1MB)不匹配。 - 当接收大消息时,分片次数多,增加缓冲区溢出和性能问题风险。
修复方案
- 将 buffer 大小调整为
_options.MaxMessageSize
,与最大消息大小保持一致。 - 这样可减少分片次数,提高性能,降低溢出风险。
代码片段
// 修复前
var buffer = ArrayPool<byte>.Shared.Rent(1024 * 4);
// 修复后
var buffer = ArrayPool<byte>.Shared.Rent(_options.MaxMessageSize);
影响
- 提高了大消息处理的效率和健壮性。
- 降低了分片累积导致的缓冲区溢出风险。
- 代码更符合最佳实践。
2024-12-19 ProcessMessage 检查逻辑优化
修改文件
X1.WebSocket/Middleware/WebSocketMiddleware.cs
问题描述
ProcessMessage
方法中存在冗余的大小检查逻辑- 在已经提前检查
totalSize
的情况下,后续的检查理论上不应该失败 - 日志级别使用不当,某些错误情况应该使用 Error 级别
优化方案
1. 优化检查逻辑
- 保留提前的
totalSize
检查作为主要验证 - 将后续检查作为安全验证,并调整日志级别为 Error
- 添加注释说明检查的层次和目的
2. 改进日志记录
- 将不应该发生的错误情况日志级别调整为 Error
- 添加更明确的错误描述,便于问题排查
代码改进
// 主要检查:提前验证大小
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
代码改进
// 优化前
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
问题描述
原始实现中存在严重的设计问题:
// 问题代码
using var messageBuffer = new WebSocketMessageBuffer(_options.MaxMessageSize);
问题所在:
_options.MaxMessageSize
是服务器端的业务限制(默认 1MB)- 客户端发送的数据大小无法预知,可能超过服务器限制
- 缓冲区大小被硬编码为业务限制,无法处理更大的消息
- 混淆了"缓冲区容量"和"业务限制"的概念
根本原因分析
1. 概念混淆
- 业务限制:
MaxMessageSize
是业务层面的限制,用于防止过大的消息影响系统性能 - 缓冲区容量:应该为客户端数据提供足够的空间,通常大于业务限制
2. 实际场景问题
// 配置中的限制
options.MaxMessageSize = 1024 * 1024; // 1MB
// 但客户端可能发送:
// - 2MB 的文件
// - 5MB 的图片
// - 10MB 的视频片段
// - 等等...
修复方案
1. 改进 WebSocketOptions 配置
public class WebSocketOptions
{
/// <summary>
/// 最大消息大小(业务限制)
/// 超过此大小的消息会被记录警告,但不会导致连接关闭
/// </summary>
public int MaxMessageSize { get; set; } = 1024 * 1024; // 1MB
/// <summary>
/// 消息缓冲区大小倍数
/// 用于计算实际缓冲区大小:MaxMessageSize * MessageBufferMultiplier
/// </summary>
public int MessageBufferMultiplier { get; set; } = 5; // 5倍
/// <summary>
/// 计算实际缓冲区大小
/// </summary>
public int GetActualBufferSize() => MaxMessageSize * MessageBufferMultiplier;
}
2. 增强 WebSocketMessageBuffer
public sealed class WebSocketMessageBuffer : IDisposable
{
// 添加公共属性访问最大缓冲区大小
public int MaxSize => _maxSize;
}
3. 修改 ProcessWebSocketMessages 方法
private async Task ProcessWebSocketMessages(...)
{
// 使用动态缓冲区大小,为客户端数据提供足够空间
var bufferSize = _options.GetActualBufferSize(); // 5MB
using var messageBuffer = new WebSocketMessageBuffer(bufferSize);
_logger.LogDebug("创建消息缓冲区,缓冲区大小:{BufferSize}字节,业务限制:{MaxMessageSize}字节",
bufferSize, _options.MaxMessageSize);
}
4. 改进 AccumulateMessageFragment 验证逻辑
// 检查累积后的大小是否会超过缓冲区容量
// 这是技术层面的检查,防止缓冲区溢出
var totalSize = messageBuffer.Size + receiveResult.Count;
if (totalSize > messageBuffer.MaxSize)
{
throw new WebSocketException($"消息大小将超过缓冲区容量:{totalSize} > {messageBuffer.MaxSize}字节");
}
// 最终验证消息大小是否符合业务限制
// 这是业务层面的检查,超过限制会记录警告但继续处理
if (messageData.Length > _options.MaxMessageSize)
{
_logger.LogWarning("消息大小超过业务限制,但已完整接收");
// 记录警告但继续处理,确保数据完整性
}
5. 更新配置示例
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. 错误处理策略
- 缓冲区溢出:抛出异常,关闭连接
- 业务限制超限:记录警告,继续处理
- 数据完整性:优先保证数据完整性
性能影响
- 内存使用:缓冲区大小增加,但避免了数据丢失
- 处理能力:能够处理更大的客户端数据
- 稳定性:提高了系统的健壮性
- 可维护性:清晰的概念分离,便于理解和维护
测试建议
- 测试不同大小的消息传输
- 验证缓冲区容量检查的正确性
- 验证业务限制检查的正确性
- 测试分片消息的完整重组
- 监控内存使用情况
总结
这次修复解决了 WebSocket 中间件中缓冲区大小设计的根本问题:
- 分离了技术限制和业务限制
- 提供了足够的缓冲区空间处理客户端数据
- 保持了数据完整性
- 提高了系统的健壮性和可维护性
2024-12-19 WebSocketMessageHandlerAdapter 验证逻辑修复
修改文件
X1.WebSocket/Handlers/WebSocketMessageHandlerAdapter.cs
问题描述
在 ValidateMessage
方法中存在验证逻辑不一致的问题:
// 问题代码
if (message.Data.Length > _options.MaxMessageSize)
{
_logger.LogWarning("消息大小超过限制...");
return false; // 拒绝处理消息
}
问题所在:
- 与缓冲区大小修复不一致:我们刚刚修复了缓冲区大小问题,允许处理超过业务限制的消息
- 数据完整性冲突:拒绝处理大消息会导致数据丢失
- 业务逻辑混乱:业务限制应该是警告而非拒绝处理的理由
根本原因分析
1. 设计理念不一致
- 缓冲区修复:允许接收大消息,记录警告但继续处理
- 验证逻辑:拒绝处理大消息,导致数据丢失
- 结果:修复了接收问题,但处理时仍然拒绝
2. 业务限制的定位错误
- 业务限制:应该是性能监控和资源管理的参考
- 当前实现:被当作拒绝处理的硬性条件
- 影响:无法处理客户端发送的大数据
修复方案
1. 修改验证逻辑
// 检查消息大小是否超过缓冲区容量
// 这是技术层面的检查,防止缓冲区溢出
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. 业务逻辑一致性
- 接收层:负责缓冲区容量检查和业务限制检查
- 处理层:只负责缓冲区容量检查,业务限制已在接收层处理
- 整体策略:职责分离,避免重复验证
性能影响
- 处理效率:避免重复验证,提高处理性能
- 职责清晰:接收层和处理层职责分离
- 稳定性:保持必要的技术验证,确保系统稳定
- 一致性:与缓冲区大小修复保持一致
测试建议
- 测试不同大小消息的处理
- 验证缓冲区容量检查的正确性
- 确认消息处理的完整性
- 检查日志记录的准确性
总结
这次修复确保了 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)
影响范围
- 数据库结构:所有表结构已重新创建
- 数据丢失:所有现有数据已清除
- 迁移历史:迁移历史记录已重置
- 开发环境:开发环境数据库已重置为初始状态
注意事项
- 这是一个破坏性操作,所有现有数据已丢失
- 需要重新初始化测试数据
- 生产环境请谨慎执行此操作
- 建议在执行前备份重要数据
后续操作建议
- 重新初始化测试数据
- 验证所有实体关系是否正确
- 测试所有CRUD操作功能
- 确认数据库约束和索引设置正确
2024-12-19 修复IMS配置字段名称
修复内容
- 将
ims_ConfigurationId
改为imS_ConfigurationId
以匹配后端API返回的数据格式 - 修改
X1.WebUI/src/services/imsConfigurationService.ts
中的所有接口定义 - 修改
X1.WebUI/src/pages/ims-configurations/IMSConfigurationsTable.tsx
中的字段引用 - 修改
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操作都能正确处理数据
- 开发体验:提供完整的类型安全和代码提示
测试建议
- 测试网络栈配置的创建、编辑、删除功能
- 验证搜索和过滤功能
- 检查表格显示和分页功能
- 确认表单验证和提交功能
- 测试栈与核心网/IMS绑定关系管理
2025-01-29 - 代码提交和.gitignore更新
修改内容
-
代码提交和推送
- 提交了网络栈配置管理功能的重构代码
- 推送代码到远程仓库
feature/x1-web-request
分支 - 同步远程分支更新
-
更新.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<NetworkStackConfigWithBindingNamesDto>` 改为 `IList<NetworkStackConfigBasicDto>`
- 更新方法注释,说明返回核心字段和配置内容
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. 导航属性查询
return await QueryRepository.FirstOrDefaultAsync(
d => d.Id == id,
include: q => q.Include(d => d.Runtime),
cancellationToken: cancellationToken);
3. 运行时状态映射
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 方法优化
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字段
- 创建操作:所有创建运行时明细记录的操作都需要提供设备编码和网络栈配置编号
- 数据验证:确保设备编码和网络栈配置编号的完整性和有效性
- 查询逻辑:支持按设备编码和网络栈配置编号查询运行时明细记录
后续工作建议
- 数据库迁移:需要创建数据库迁移来添加DeviceCode和NetworkStackCode字段
- 仓储更新:更新相关的仓储方法以支持设备编码和网络栈配置编号字段
- API更新:更新相关的API接口以支持设备编码和网络栈配置编号字段
- 前端界面:更新前端界面以显示和编辑设备编码和网络栈配置编号
- 测试用例:为设备编码和网络栈配置编号字段添加相应的测试用例
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 路由下
- 权限继承:设备运行时管理继承仪表管理的基础权限结构
- 菜单层次:清晰的菜单层次结构,设备运行时管理属于仪表管理范畴
- 向后兼容:保持所有现有功能不变,只是调整了路由和菜单结构
业务价值
- 逻辑分组:将设备运行时管理归类到仪表管理下,符合业务逻辑
- 用户体验:更清晰的菜单结构,用户更容易找到相关功能
- 权限管理:统一的权限管理结构,便于权限分配和管理
- 系统一致性:保持系统整体架构的一致性
影响范围
- 路由访问:设备运行时管理页面的访问路径发生变化
- 菜单导航:用户需要通过仪表管理菜单访问设备运行时管理
- 权限控制:设备运行时管理权限已正确配置
- 用户体验:更符合用户预期的菜单结构
使用方式
- 用户登录后,在左侧菜单中点击"仪表管理"
- 在仪表管理子菜单中点击"运行时状态"
- 进入设备运行时管理页面:
/dashboard/instruments/device-runtimes/list
- 点击设备编号可查看详情:
/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-separatorX1.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 组件
- 图标系统:修复了图标导入问题
- 服务调用:统一了服务调用方式
- 开发体验:提供了更好的类型安全和代码提示
后续工作建议
- 组件测试:为新创建的组件添加单元测试
- 文档编写:为组件添加使用文档和示例
- 主题优化:进一步完善主题支持
- 性能优化:优化组件的渲染性能
2025-01-29 修复 Select 组件空值错误
修改原因
修复 Select 组件中空值选项导致的错误:"A <Select.Item /> 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 修复:将
<SelectItem value="">全部状态</SelectItem>
改为<SelectItem value="all">全部状态</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
路径不再可用 - 代码维护:减少了未使用的代码,提高代码库的整洁性
- 编译状态:修复了编译错误,确保项目能够正常构建
后续建议
- 功能评估:如果将来需要设备运行时详情功能,可以重新实现
- 用户反馈:收集用户反馈,确认是否需要详情页面功能
- 替代方案:考虑在列表页面中直接显示详细信息,而不是单独的详情页面
- 代码审查:定期检查类似的未使用代码,保持代码库的整洁性
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"
- 在SELECT语句中添加
3. 相关方法同步修复
- GetNetworkStackConfigByIdWithBindingNamesAsync方法:
- 同步添加相同的ConfigContent字段到SQL查询中
- SearchNetworkStackConfigsWithBindingNamesAsync方法:
- 同步添加相同的ConfigContent字段到SQL查询中
技术特性
- 数据完整性:现在能够获取完整的配置内容信息
- 字段映射:正确映射数据库字段到DTO属性
- 一致性:所有相关方法都包含相同的ConfigContent字段
- 类型安全:使用可空字符串类型,避免空值问题
业务价值
- 配置内容显示:前端可以显示RAN、核心网、IMS的完整配置内容
- 数据关联:提供网络栈配置与相关配置内容的完整关联信息
- 调试支持:便于开发人员查看和调试配置内容
- 用户体验:用户可以在一个查询中获取所有相关的配置信息
影响范围
- API响应:网络栈配置查询现在包含完整的配置内容
- 前端显示:前端可以显示配置内容信息
- 数据查询:提供更完整的配置关联数据
- 系统集成:支持配置内容的完整传递和处理
后续工作建议
- 更新前端界面以显示配置内容信息
- 添加配置内容的格式化显示功能
- 考虑添加配置内容的搜索功能
- 优化大配置内容的显示方式
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提高系统稳定性
- 可维护性: 清晰的代码结构和日志便于维护
- 调试能力: 详细的跟踪日志便于问题排查
- 用户体验: 更可靠的设备启动流程
影响范围
- 设备启动流程: 修复了批量启动设备的完整流程
- 数据保存: 确保运行时详情正确保存
- 错误处理: 改进了异常情况的处理
- 日志记录: 提供了完整的操作跟踪
测试建议
- 测试批量启动设备的完整流程
- 验证运行时详情的正确保存
- 检查错误处理机制
- 验证日志记录的完整性
- 测试网络配置不存在的情况
- 测试设备运行时不存在的情况
2025-01-29 - 为GenerateRuntimeCodeAsync方法的异常处理添加详细说明
修改原因
为 throw;
语句添加详细的注释说明,解释为什么要重新抛出异常,提高代码的可读性和维护性。
修改文件
X1.Application/Features/DeviceRuntimes/Commands/StartDeviceRuntime/StartDeviceRuntimeCommandHandler.cs
- 为异常处理添加详细说明
修改内容
1. 异常处理说明
- 重新抛出原因: 添加了详细的注释说明为什么要重新抛出异常
- 堆栈跟踪: 保持异常的原始堆栈跟踪信息,便于调试和问题定位
- 异常传播: 确保上层调用者能够捕获到原始异常,进行适当的错误处理
- 信息完整性: 避免异常信息丢失,保持异常传播链的完整性
- 最佳实践: 符合异常处理的最佳实践:记录日志后重新抛出
2. 代码可读性提升
- 注释清晰: 详细说明了每个重新抛出异常的原因
- 维护友好: 便于其他开发者理解异常处理逻辑
- 调试支持: 提供了调试和问题定位的指导
技术要点
- 异常传播链: 保持完整的异常传播链,便于问题追踪
- 日志记录: 在重新抛出前记录详细的错误日志
- 调试信息: 包含线程ID等调试信息
- 最佳实践: 遵循C#异常处理的最佳实践
测试建议
- 测试异常情况下的日志记录
- 验证异常传播链的完整性
- 检查调试信息的准确性
- 测试多线程环境下的异常处理
2025-01-29 - 修复网络配置请求构建中的设备-网络堆栈组合唯一性检查
修改原因
修复了网络配置请求构建中的一个重要bug:原来的逻辑只检查设备代码的唯一性,但实际上一个设备可能需要运行多个不同的网络堆栈配置。需要改为检查设备-网络堆栈组合的唯一性。
修改文件
X1.Application/Features/DeviceRuntimes/Commands/StartDeviceRuntime/StartDeviceRuntimeCommandHandler.cs
- 添加设备代码唯一性检查
修改内容
1. 唯一性检查机制修复
- 组合键跟踪: 将
processedDeviceCodes
改为processedDeviceNetworkPairs
,用于跟踪已处理的设备-网络堆栈组合 - 组合键生成: 使用
{DeviceCode}_{NetworkStackCode}
格式生成唯一标识 - 重复检查: 在处理每个网络配置前检查设备-网络堆栈组合是否已被处理
- 跳过重复: 如果组合已存在,记录警告日志并跳过处理
2. 日志增强
- 重复警告: 当发现重复设备代码时记录警告日志
- 统计信息: 添加成功构建网络配置请求的统计信息
- 处理数量: 记录实际处理的设备数量和请求数量
3. 数据完整性保证
- 组合唯一性: 确保每个设备-网络堆栈组合只对应一个网络配置
- 多配置支持: 允许同一设备运行多个不同的网络堆栈配置
- 避免冲突: 防止同一设备-网络堆栈组合被重复处理
- 数据一致性: 保证后续处理的数据一致性
技术要点
- HashSet性能: 使用HashSet进行O(1)时间复杂度的重复检查
- 内存效率: HashSet比List更高效地进行重复检查
- 线程安全: 在单个请求处理中,HashSet是线程安全的
- 日志追踪: 完整的操作日志便于问题排查
测试建议
- 测试同一设备运行多个网络堆栈配置的场景
- 测试包含重复设备-网络堆栈组合的请求
- 验证组合唯一性检查的正确性
- 检查日志记录的完整性
- 测试正常情况下的处理流程
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<CoreNetworkImsConfiguration>
但永远只有一条记录 - 性能影响: 创建不必要的集合对象,存在内存分配浪费
- 代码冗余: 使用集合但没有实际的多条记录需求
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结构:
{
"cellularNetwork": {
"deviceCode": "string",
"runtimeCode": "string",
"radioAccessNetworkConfiguration": "string",
"coreNetworkImsConfigurations": [...]
}
}
修复后的实现:
// 调用方
var request = new CellularNetworkRequest
{
CellularNetwork = networkRequest
};
var startResult = await _protocolClient.StartNetworkAsync(request);
// 实现方
public async Task<bool> StartNetworkAsync(
CellularNetworkRequest request,
RequestOptions? options = null,
CancellationToken cancellationToken = default)
{
// 直接传递 request 对象给 PostAsync
var response = await _dynamicHttpClient.PostAsync<ApiActionResult<NetworkStatus>>(
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<int>? runtimeStatuses
- 支持传入多个状态值
2. 实现逻辑优化
- 移除兼容逻辑:移除
onlyRunningStatus
的兼容处理逻辑 - 简化过滤条件:只保留
runtimeStatuses
的动态过滤逻辑 - 参数转换:使用
Cast<object>()
确保参数类型正确转换
3. 使用示例
// 查询运行中的设备日志
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. 优化代码逻辑
// 修改前:复杂的运行时状态查询逻辑
var deviceRuntimes = await _deviceRuntimeRepository.GetRuntimesByDeviceCodeAsync(...);
var matchingRuntimes = deviceRuntimes.Where(r => r.RuntimeStatus == request.DeviceRuntimeStatus.Value);
var runtimeCodes = matchingRuntimes.Select(r => r.RuntimeCode).ToList();
// 修改后:直接使用状态过滤
IEnumerable<int>? runtimeStatuses = null;
if (request.DeviceRuntimeStatus.HasValue)
{
runtimeStatuses = new[] { (int)request.DeviceRuntimeStatus.Value };
}
技术改进
- 性能优化:减少数据库查询次数,提高查询性能
- 代码简化:移除复杂的运行时状态查询逻辑
- 参数一致性:确保方法调用参数与接口定义一致
- 错误处理:简化错误处理逻辑,减少潜在的错误点
影响范围
- 查询性能:提高了协议日志查询的性能
- 代码维护性:简化了代码逻辑,便于维护
- 功能完整性:保持了原有的过滤功能
- 接口一致性:确保所有调用都使用正确的参数顺序