174 KiB
修改记录
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
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数据格式完全一致
- 修复字段名称大小写问题,从
ims_ConfigurationId
改为imS_ConfigurationId
- 保持与后端数据结构的同步
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-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/*
已失效 - 需要更新任何硬编码的链接或书签
- 权限检查仍然正常工作,确保安全性
- 所有设备运行时管理功能保持不变