diff --git a/src/X1.Application/Features/DeviceRuntimes/Commands/StartDeviceRuntime/StartDeviceRuntimeResponse.cs b/src/X1.Application/Features/DeviceRuntimes/Commands/StartDeviceRuntime/StartDeviceRuntimeResponse.cs
index e8f1e36..0b7dc13 100644
--- a/src/X1.Application/Features/DeviceRuntimes/Commands/StartDeviceRuntime/StartDeviceRuntimeResponse.cs
+++ b/src/X1.Application/Features/DeviceRuntimes/Commands/StartDeviceRuntime/StartDeviceRuntimeResponse.cs
@@ -1,3 +1,5 @@
+using CellularManagement.Domain.Common;
+
namespace CellularManagement.Application.Features.DeviceRuntimes.Commands.StartDeviceRuntime;
///
@@ -25,8 +27,6 @@ public class StartDeviceRuntimeResponse
///
public string? NetworkStackCode { get; set; }
-
-
///
/// 更新时间
///
@@ -68,8 +68,6 @@ public class DeviceStartResult
///
public string? NetworkStackCode { get; set; }
-
-
///
/// 更新时间
///
@@ -84,30 +82,4 @@ public class DeviceStartResult
/// 错误信息
///
public string? ErrorMessage { get; set; }
-}
-
-///
-/// 批量操作统计
-///
-public class BatchOperationSummary
-{
- ///
- /// 总设备数
- ///
- public int TotalCount { get; set; }
-
- ///
- /// 成功数量
- ///
- public int SuccessCount { get; set; }
-
- ///
- /// 失败数量
- ///
- public int FailureCount { get; set; }
-
- ///
- /// 成功率
- ///
- public double SuccessRate => TotalCount > 0 ? (double)SuccessCount / TotalCount * 100 : 0;
}
\ No newline at end of file
diff --git a/src/X1.Application/Features/DeviceRuntimes/Commands/StopDeviceRuntime/StopDeviceRuntimeResponse.cs b/src/X1.Application/Features/DeviceRuntimes/Commands/StopDeviceRuntime/StopDeviceRuntimeResponse.cs
index 608f945..d0f6419 100644
--- a/src/X1.Application/Features/DeviceRuntimes/Commands/StopDeviceRuntime/StopDeviceRuntimeResponse.cs
+++ b/src/X1.Application/Features/DeviceRuntimes/Commands/StopDeviceRuntime/StopDeviceRuntimeResponse.cs
@@ -1,3 +1,5 @@
+using CellularManagement.Domain.Common;
+
namespace CellularManagement.Application.Features.DeviceRuntimes.Commands.StopDeviceRuntime;
///
@@ -90,30 +92,4 @@ public class DeviceStopResult
/// 错误信息
///
public string? ErrorMessage { get; set; }
-}
-
-///
-/// 批量操作统计
-///
-public class BatchOperationSummary
-{
- ///
- /// 总设备数
- ///
- public int TotalCount { get; set; }
-
- ///
- /// 成功数量
- ///
- public int SuccessCount { get; set; }
-
- ///
- /// 失败数量
- ///
- public int FailureCount { get; set; }
-
- ///
- /// 成功率
- ///
- public double SuccessRate => TotalCount > 0 ? (double)SuccessCount / TotalCount * 100 : 0;
}
\ No newline at end of file
diff --git a/src/X1.Domain/Common/BatchOperationSummary.cs b/src/X1.Domain/Common/BatchOperationSummary.cs
new file mode 100644
index 0000000..6e34459
--- /dev/null
+++ b/src/X1.Domain/Common/BatchOperationSummary.cs
@@ -0,0 +1,27 @@
+namespace CellularManagement.Domain.Common;
+
+///
+/// 批量操作统计
+///
+public class BatchOperationSummary
+{
+ ///
+ /// 总设备数
+ ///
+ public int TotalCount { get; set; }
+
+ ///
+ /// 成功数量
+ ///
+ public int SuccessCount { get; set; }
+
+ ///
+ /// 失败数量
+ ///
+ public int FailureCount { get; set; }
+
+ ///
+ /// 成功率
+ ///
+ public double SuccessRate => TotalCount > 0 ? (double)SuccessCount / TotalCount * 100 : 0;
+}
\ No newline at end of file
diff --git a/src/X1.Presentation/Controllers/ProtocolLogsController.cs b/src/X1.Presentation/Controllers/ProtocolLogsController.cs
index 4c4d3f7..56e613f 100644
--- a/src/X1.Presentation/Controllers/ProtocolLogsController.cs
+++ b/src/X1.Presentation/Controllers/ProtocolLogsController.cs
@@ -24,50 +24,82 @@ public class ProtocolLogsController : ApiController
///
/// 中介者
/// 日志记录器
- public ProtocolLogsController(IMediator mediator, ILogger logger)
+ public ProtocolLogsController(IMediator mediator, ILogger logger)
: base(mediator)
{
_logger = logger;
}
+ ///
+ /// 协议日志查询请求模型
+ ///
+ public class ProtocolLogsQueryRequest
+ {
+ ///
+ /// 设备代码
+ ///
+ public string? DeviceCode { get; set; }
+
+ ///
+ /// 开始时间戳
+ ///
+ public long? StartTimestamp { get; set; }
+
+ ///
+ /// 结束时间戳
+ ///
+ public long? EndTimestamp { get; set; }
+
+ ///
+ /// 协议层类型
+ ///
+ public string? LayerType { get; set; }
+
+ ///
+ /// 设备运行时状态
+ ///
+ public int? DeviceRuntimeStatus { get; set; }
+ ///
+ /// 运行时代码数组
+ ///
+ public string[]? RuntimeCodes { get; set; }
+
+ ///
+ /// 运行时状态数组
+ ///
+ public int[]? RuntimeStatuses { get; set; }
+
+ ///
+ /// 是否按时间戳降序排序
+ ///
+ public bool OrderByDescending { get; set; } = true;
+ }
///
/// 根据设备代码获取协议日志
///
/// 设备代码
- /// 开始时间戳
- /// 结束时间戳
- /// 协议层类型
- /// 设备运行时状态
- /// 运行时代码数组
- /// 运行时状态数组
- /// 是否按时间戳降序排序
+ /// 查询请求
/// 协议日志列表
- [HttpGet("device/{deviceCode}")]
+ [HttpPost("device/{deviceCode}")]
public async Task> GetProtocolLogsByDevice(
string deviceCode,
- [FromQuery] long? startTimestamp = null,
- [FromQuery] long? endTimestamp = null,
- [FromQuery] string? layerType = null,
- [FromQuery] int? deviceRuntimeStatus = null,
- [FromQuery] string[]? runtimeCodes = null,
- [FromQuery] int[]? runtimeStatuses = null,
- [FromQuery] bool orderByDescending = true)
+ [FromBody] ProtocolLogsQueryRequest request)
{
- _logger.LogInformation("开始获取设备 {DeviceCode} 的协议日志,开始时间戳: {StartTimestamp}, 结束时间戳: {EndTimestamp}, 协议层类型: {LayerType}, 运行时状态: {DeviceRuntimeStatus}, 运行时代码数量: {RuntimeCodesCount}, 运行时状态数量: {RuntimeStatusesCount}",
- deviceCode, startTimestamp, endTimestamp, layerType, deviceRuntimeStatus, runtimeCodes?.Length ?? 0, runtimeStatuses?.Length ?? 0);
+ _logger.LogInformation("开始获取设备{DeviceCode} 的协议日志,开始时间戳: {StartTimestamp}, 结束时间戳: {EndTimestamp}, 协议层类型: {LayerType}, 运行时状态: {DeviceRuntimeStatus}, 运行时代码数量: {RuntimeCodesCount}, 运行时状态数量: {RuntimeStatusesCount}",
+ deviceCode, request.StartTimestamp, request.EndTimestamp, request.LayerType, request.DeviceRuntimeStatus, request.RuntimeCodes?.Length ?? 0, request.RuntimeStatuses?.Length ?? 0);
- var query = new GetProtocolLogsByDeviceQuery
- {
+ var query = new GetProtocolLogsByDeviceQuery
+ {
DeviceCode = deviceCode,
- StartTimestamp = startTimestamp,
- EndTimestamp = endTimestamp,
- LayerType = layerType,
- DeviceRuntimeStatus = deviceRuntimeStatus.HasValue ? (DeviceRuntimeStatus)deviceRuntimeStatus.Value : null,
- RuntimeCodes = runtimeCodes ?? Array.Empty(),
- RuntimeStatuses = runtimeStatuses ?? Array.Empty(),
- OrderByDescending = orderByDescending
+ StartTimestamp = request.StartTimestamp,
+ EndTimestamp = request.EndTimestamp,
+ LayerType = request.LayerType,
+ DeviceRuntimeStatus = request.DeviceRuntimeStatus.HasValue ? (DeviceRuntimeStatus)request.DeviceRuntimeStatus.Value : null,
+ RuntimeCodes = request.RuntimeCodes ?? Array.Empty(),
+ RuntimeStatuses = request.RuntimeStatuses ?? Array.Empty(),
+ OrderByDescending = request.OrderByDescending
};
var result = await mediator.Send(query);
@@ -77,7 +109,7 @@ public class ProtocolLogsController : ApiController
return result;
}
- _logger.LogInformation("成功获取设备 {DeviceCode} 的协议日志,共 {Count} 条记录",
+ _logger.LogInformation("成功获取设备 {DeviceCode} 的协议日志,共{Count} 条记录",
deviceCode, result.Data?.Items?.Count ?? 0);
return result;
}
@@ -85,39 +117,25 @@ public class ProtocolLogsController : ApiController
///
/// 获取协议日志(支持可选的设备代码)
///
- /// 设备代码(可选)
- /// 开始时间戳
- /// 结束时间戳
- /// 协议层类型
- /// 设备运行时状态
- /// 运行时代码数组
- /// 运行时状态数组
- /// 是否按时间戳降序排序
+ /// 查询请求
/// 协议日志列表
- [HttpGet("logs")]
+ [HttpPost("logs")]
public async Task> GetProtocolLogs(
- [FromQuery] string? deviceCode = null,
- [FromQuery] long? startTimestamp = null,
- [FromQuery] long? endTimestamp = null,
- [FromQuery] string? layerType = null,
- [FromQuery] int? deviceRuntimeStatus = null,
- [FromQuery] string[]? runtimeCodes = null,
- [FromQuery] int[]? runtimeStatuses = null,
- [FromQuery] bool orderByDescending = true)
+ [FromBody] ProtocolLogsQueryRequest request)
{
_logger.LogInformation("开始获取协议日志,设备代码: {DeviceCode}, 开始时间戳: {StartTimestamp}, 结束时间戳: {EndTimestamp}, 协议层类型: {LayerType}, 运行时状态: {DeviceRuntimeStatus}, 运行时代码数量: {RuntimeCodesCount}, 运行时状态数量: {RuntimeStatusesCount}",
- deviceCode, startTimestamp, endTimestamp, layerType, deviceRuntimeStatus, runtimeCodes?.Length ?? 0, runtimeStatuses?.Length ?? 0);
+ request.DeviceCode, request.StartTimestamp, request.EndTimestamp, request.LayerType, request.DeviceRuntimeStatus, request.RuntimeCodes?.Length ?? 0, request.RuntimeStatuses?.Length ?? 0);
- var query = new GetProtocolLogsByDeviceQuery
- {
- DeviceCode = deviceCode,
- StartTimestamp = startTimestamp,
- EndTimestamp = endTimestamp,
- LayerType = layerType,
- DeviceRuntimeStatus = deviceRuntimeStatus.HasValue ? (DeviceRuntimeStatus)deviceRuntimeStatus.Value : null,
- RuntimeCodes = runtimeCodes ?? Array.Empty(),
- RuntimeStatuses = runtimeStatuses ?? Array.Empty(),
- OrderByDescending = orderByDescending
+ var query = new GetProtocolLogsByDeviceQuery
+ {
+ DeviceCode = request.DeviceCode,
+ StartTimestamp = request.StartTimestamp,
+ EndTimestamp = request.EndTimestamp,
+ LayerType = request.LayerType,
+ DeviceRuntimeStatus = request.DeviceRuntimeStatus.HasValue ? (DeviceRuntimeStatus)request.DeviceRuntimeStatus.Value : null,
+ RuntimeCodes = request.RuntimeCodes ?? Array.Empty(),
+ RuntimeStatuses = request.RuntimeStatuses ?? Array.Empty(),
+ OrderByDescending = request.OrderByDescending
};
var result = await mediator.Send(query);
@@ -127,7 +145,7 @@ public class ProtocolLogsController : ApiController
return result;
}
- _logger.LogInformation("成功获取协议日志,共 {Count} 条记录",
+ _logger.LogInformation("成功获取协议日志,共 {Count} 条记录",
result.Data?.Items?.Count ?? 0);
return result;
}
diff --git a/src/modify.md b/src/modify.md
index 3f38f5f..9037fbf 100644
--- a/src/modify.md
+++ b/src/modify.md
@@ -1,5 +1,108 @@
# 修改记录
+## 2025-01-29 - ProtocolLogsController 修复 GetProtocolLogsByDevice 和 GetProtocolLogs 改为 POST 方式
+
+### 修改概述
+根据用户需求,将 ProtocolLogsController 中的 `GetProtocolLogsByDevice` 和 `GetProtocolLogs` 方法从 GET 方式改为 POST 方式,并创建相应的请求模型来接收参数。
+
+### 修改文件
+- `X1.Presentation/Controllers/ProtocolLogsController.cs` - 修改协议日志控制器
+
+### 修改内容
+
+#### 1. 新增请求模型
+- **ProtocolLogsQueryRequest 类**:
+ - `DeviceCode?: string` - 设备代码(可选)
+ - `StartTimestamp?: long` - 开始时间戳
+ - `EndTimestamp?: long` - 结束时间戳
+ - `LayerType?: string` - 协议层类型
+ - `DeviceRuntimeStatus?: int` - 设备运行时状态
+ - `RuntimeCodes?: string[]` - 运行时代码数组
+ - `RuntimeStatuses?: int[]` - 运行时状态数组
+ - `OrderByDescending: bool` - 是否按时间戳降序排序(默认 true)
+
+#### 2. 方法签名修改
+- **GetProtocolLogsByDevice 方法**:
+ - 路由:`[HttpPost("device/{deviceCode}")]` 替代 `[HttpGet("device/{deviceCode}")]`
+ - 参数:`[FromBody] ProtocolLogsQueryRequest request` 替代多个 `[FromQuery]` 参数
+ - 设备代码:从路由参数获取,其他参数从请求体获取
+
+- **GetProtocolLogs 方法**:
+ - 路由:`[HttpPost("logs")]` 替代 `[HttpGet("logs")]`
+ - 参数:`[FromBody] ProtocolLogsQueryRequest request` 替代多个 `[FromQuery]` 参数
+ - 所有参数从请求体获取
+
+#### 3. 业务逻辑更新
+- **参数处理**:从 `request` 对象中获取所有查询参数
+- **默认值处理**:使用空合并运算符提供默认值
+- **日志记录**:更新日志记录,使用请求对象中的参数
+- **查询构建**:保持原有的查询逻辑不变,只修改参数来源
+
+### 技术特性
+
+#### 1. POST 方式优势
+- **参数复杂性**:支持复杂的查询参数,包括数组类型
+- **安全性**:敏感参数不会出现在 URL 中
+- **数据大小**:支持更大的查询参数
+- **一致性**:与其他复杂查询接口保持一致
+
+#### 2. 请求模型设计
+- **类型安全**:使用强类型的请求模型
+- **可选参数**:大部分参数都是可选的,提供灵活性
+- **默认值**:为常用参数提供合理的默认值
+- **文档完整**:为所有属性添加 XML 文档注释
+
+#### 3. 向后兼容性
+- **API 路径**:保持原有的 API 路径不变
+- **响应格式**:保持原有的响应格式不变
+- **业务逻辑**:保持原有的查询逻辑不变
+
+### API 使用示例
+
+#### 1. 根据设备代码获取协议日志
+```http
+POST /api/protocol-logs/device/DEV001
+Content-Type: application/json
+
+{
+ "startTimestamp": 1640995200000,
+ "endTimestamp": 1641081600000,
+ "layerType": "NAS",
+ "deviceRuntimeStatus": 1,
+ "runtimeCodes": ["RT-001-DEV001", "RT-002-DEV001"],
+ "runtimeStatuses": [1, 2],
+ "orderByDescending": true
+}
+```
+
+#### 2. 获取所有协议日志
+```http
+POST /api/protocol-logs/logs
+Content-Type: application/json
+
+{
+ "deviceCode": "DEV001",
+ "startTimestamp": 1640995200000,
+ "endTimestamp": 1641081600000,
+ "layerType": "RRC",
+ "runtimeStatuses": [1]
+}
+```
+
+### 影响范围
+- **API 接口**:从 GET 改为 POST 方式,需要更新客户端调用
+- **参数传递**:从 URL 查询参数改为请求体 JSON 参数
+- **客户端适配**:前端需要更新调用方式
+- **文档更新**:需要更新 API 文档
+
+### 注意事项
+- 客户端需要将原来的 GET 请求改为 POST 请求
+- 查询参数需要从 URL 移到请求体中
+- 需要设置正确的 Content-Type 头
+- 保持原有的业务逻辑和响应格式不变
+
+---
+
## 2025-01-29 - StopDeviceRuntimeCommandHandler重构优化
### 修改概述
@@ -1022,480 +1125,6 @@ const addResult = await rolePermissionService.addRolePermissions({
4. **错误处理**:完善错误处理和用户提示
5. **测试验证**:为所有服务方法添加单元测试
----
-
-## 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` - 运行时状态ID
-- `deviceCode?: string` - 设备编号
-- `runtimeStatus?: string` - 运行时状态
-- `networkStackCode?: string` - 网络栈配置编号
-- `updatedAt: string` - 更新时间
-- `deviceResults?: DeviceStartResult[]` - 设备启动结果列表
-- `summary?: BatchOperationSummary` - 批量操作统计
-
-#### 5. 设备启动结果接口 (DeviceStartResult)
-**对应后端 DeviceStartResult**:
-- `deviceCode: string` - 设备编号
-- `id: string` - 运行时状态ID
-- `runtimeStatus: 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` - 运行时状态ID
-- `deviceCode: 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. 搜索和过滤
-```typescript
-// 搜索条件
-const searchConditions = {
- searchTerm: string, // 设备编号或名称
- runtimeStatus: number, // 运行时状态过滤
- pageSize: number // 每页显示数量
-};
-```
-
-#### 2. 批量操作
-```typescript
-// 批量启动设备
-const batchStartDevices = async (deviceCodes: string[], networkStackCode: string) => {
- const deviceRequests = deviceCodes.map(code => ({
- deviceCode: code,
- networkStackCode: networkStackCode
- }));
- return await startDevices(deviceRequests);
-};
-```
-
-#### 3. 状态显示
-```typescript
-// 状态映射
-const statusMapping = {
- 0: { text: '初始化', color: 'default' },
- 1: { text: '运行中', color: 'success' },
- 2: { text: '已停止', color: 'warning' },
- 3: { text: '错误', color: 'error' }
-};
-```
-
-### 路由配置
-
-#### 1. 新增路由
-```typescript
-// 设备运行时管理路由
-
- } />
- } />
- } />
-
-```
-
-#### 2. 权限控制
-```typescript
-// 权限配置
-const permissions = {
- 'deviceruntimes.view': '查看设备运行时',
- 'deviceruntimes.manage': '管理设备运行时'
-};
-```
-
-### 菜单配置
-
-#### 1. 新增菜单项
-```typescript
-{
- title: '设备运行时',
- icon: Gauge,
- href: '/dashboard/device-runtimes',
- permission: 'deviceruntimes.view',
- children: [
- {
- title: '运行时状态',
- href: '/dashboard/device-runtimes/list',
- permission: 'deviceruntimes.view',
- }
- ],
-}
-```
-
-### 使用流程
-
-#### 1. 查看设备运行时状态
-1. 导航到"设备运行时" → "运行时状态"
-2. 查看设备运行时状态列表
-3. 使用搜索和过滤功能查找特定设备
-4. 点击设备编号查看详细信息
-
-#### 2. 批量启动设备
-1. 在设备列表中勾选要启动的设备
-2. 点击"批量启动"按钮
-3. 在弹出的对话框中输入网络栈配置编号
-4. 确认启动操作
-
-#### 3. 停止单个设备
-1. 在设备列表中找到运行中的设备
-2. 点击操作菜单中的"停止设备"
-3. 确认停止操作
-
-#### 4. 查看设备详情
-1. 点击设备编号进入详情页面
-2. 查看设备的运行时状态、网络配置等信息
-3. 使用刷新按钮更新状态
-4. 返回列表页面
-
-### 影响范围
-- **前端界面**:提供了完整的设备运行时管理界面
-- **用户体验**:改善了设备运行时管理的操作体验
-- **功能完整性**:实现了设备运行时管理的所有核心功能
-- **系统集成**:与现有的权限系统和导航系统完全集成
-
-### 后续优化建议
-1. **实时更新**:添加WebSocket支持,实现设备状态的实时更新
-2. **历史记录**:添加设备运行时历史记录查看功能
-3. **批量导入**:支持批量导入设备配置
-4. **监控告警**:添加设备状态异常告警功能
-5. **操作日志**:记录和查看设备操作历史
-
-### 修改原因
-根据后端 `DeviceRuntimesController` 的实现,为前端 `X1.WebUI/src/services` 目录创建对应的服务,实现设备运行时状态管理的完整功能。
-
-### 新增文件
-
-#### 1. 设备运行时服务
-- `X1.WebUI/src/services/deviceRuntimeService.ts` - 设备运行时状态管理服务
-
-#### 2. 设备管理服务
-- `X1.WebUI/src/services/deviceService.ts` - 设备管理服务
-
-#### 3. 权限管理服务
-- `X1.WebUI/src/services/permissionService.ts` - 权限管理服务
-
-#### 4. 角色权限管理服务
-- `X1.WebUI/src/services/rolePermissionService.ts` - 角色权限管理服务
-
-### 修改文件
-
-#### 1. API常量配置
-- `X1.WebUI/src/constants/api.ts` - 添加设备运行时、设备、权限、角色权限相关的API路径
-
-### 功能特性
-
-#### 1. 设备运行时服务 (deviceRuntimeService.ts)
-- **设备运行时状态枚举**:`DeviceRuntimeStatus`(Running、Stopped、Error、Unknown)
-- **核心功能**:
- - `getDeviceRuntimes()` - 获取设备运行时状态列表(支持分页、搜索、状态过滤)
- - `getDeviceRuntimeStatus()` - 根据设备编号获取设备运行时状态
- - `startDevices()` - 批量启动设备
- - `stopDevice()` - 停止单个设备
-- **辅助功能**:
- - `getRuntimeStatusDescription()` - 获取状态的可读描述
- - `getRuntimeStatusColor()` - 获取状态对应的颜色
-
-#### 2. 设备管理服务 (deviceService.ts)
-- **核心功能**:
- - `getDevices()` - 获取设备列表(支持分页、搜索、类型过滤、状态过滤)
- - `getDeviceById()` - 根据ID获取设备详情
- - `createDevice()` - 创建设备
- - `updateDevice()` - 更新设备
- - `deleteDevice()` - 删除设备
-- **辅助功能**:
- - `getDeviceStatusDescription()` - 获取设备状态描述
- - `getDeviceStatusColor()` - 获取设备状态颜色
-
-#### 3. 权限管理服务 (permissionService.ts)
-- **核心功能**:
- - `createPermission()` - 创建权限
- - `getPermissions()` - 获取权限列表
- - `getPermissionById()` - 根据ID获取权限详情
- - `deletePermission()` - 删除权限
-
-#### 4. 角色权限管理服务 (rolePermissionService.ts)
-- **核心功能**:
- - `getRolePermissions()` - 获取角色权限
- - `addRolePermissions()` - 添加角色权限
- - `deleteRolePermissions()` - 删除角色权限
- - `batchAddPermissions()` - 批量添加权限到角色
- - `batchRemovePermissions()` - 批量从角色删除权限
-- **辅助功能**:
- - `getRolePermissionStats()` - 获取角色权限统计信息
-
-### 技术特性
-
-#### 1. 类型安全
-- 完整的 TypeScript 接口定义
-- 与后端 API 响应格式完全匹配
-- 提供良好的开发体验和代码提示
-
-#### 2. 错误处理
-- 统一的错误处理机制
-- 使用 `OperationResult` 包装响应
-- 详细的错误信息记录
-
-#### 3. HTTP 客户端集成
-- 使用 `httpClient` 进行 API 调用
-- 支持 GET、POST、PUT、DELETE 方法
-- 自动处理查询参数构建
-
-#### 4. 查询参数支持
-- 分页参数:`pageNumber`、`pageSize`
-- 搜索参数:`searchTerm`
-- 过滤参数:状态、类型等
-- 排序参数:按时间、名称等排序
-
-### API 路径配置
-
-#### 1. 新增的 API 路径
-```typescript
-export const API_PATHS = {
- // 设备相关
- DEVICES: '/devices',
- DEVICE_RUNTIMES: '/api/device-runtimes',
-
- // 权限相关
- PERMISSIONS: '/api/permissions',
- ROLE_PERMISSIONS: '/api/role-permissions',
-
- // ... 其他现有路径
-}
-```
-
-### 使用示例
-
-#### 1. 设备运行时管理
-```typescript
-// 获取设备运行时状态列表
-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. 设备管理
-```typescript
-// 获取设备列表
-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. 权限管理
-```typescript
-// 创建权限
-const result = await permissionService.createPermission({
- name: 'CreateUser',
- description: '创建用户的权限'
-});
-```
-
-#### 4. 角色权限管理
-```typescript
-// 获取角色权限
-const result = await rolePermissionService.getRolePermissions('roleId', true);
-
-// 添加角色权限
-const addResult = await rolePermissionService.addRolePermissions({
- roleId: 'roleId',
- permissionIds: ['perm1', 'perm2']
-});
-```
-
-### 影响范围
-- **前端服务**:提供了完整的设备运行时、设备、权限、角色权限管理前端服务
-- **API 集成**:与后端控制器完全对应
-- **类型安全**:提供了完整的 TypeScript 类型定义
-- **开发体验**:统一的服务接口,便于前端开发使用
-
-### 后续工作建议
-1. **前端页面开发**:基于这些服务开发对应的前端页面
-2. **组件开发**:开发设备运行时状态显示组件
-3. **状态管理**:集成到前端状态管理系统中
-4. **错误处理**:完善错误处理和用户提示
-5. **测试验证**:为所有服务方法添加单元测试
-
## 2025-01-29 更新instrumentService.ts和DevicesView.tsx以匹配后端API
### 修改原因
@@ -2415,7 +2044,7 @@ return runtimes.OrderByDescending(r => r.CreatedAt).FirstOrDefault();
### 技术细节
- 将 `key={column.key}` 修改为 `key={`${configuration.raN_ConfigurationId}-${column.key}`}`、`key={`${configuration.ims_ConfigurationId}-${column.key}`}` 和 `key={`${config.CoreNetworkConfigId}-${column.key}`}`
-- 重构操作列按钮渲染:使用数组map方法替代静态JSX,确保每个按钮都有唯一key
+- 重构操作列按钮渲染:使用数组map渲染,确保每个按钮都有唯一key
- 使用动态key:将TableHeader和TableBody的key改为 `key={`header-${Date.now()}`}` 和 `key={`body-${Date.now()}`}`
- 确保每个表格单元格和子元素都有唯一的key属性
- 避免React渲染时的key冲突问题