515 KiB
修改记录
2025-01-21 - 修复ReactFlowDesigner节点类型不对称问题
问题描述
在ReactFlowDesigner.tsx中,所有节点的type都被硬编码为'testStep',导致保存的数据中所有节点类型都是相同的,无法区分不同类型的节点。
修改内容
1. ReactFlowDesigner.tsx
- 文件位置:
X1.WebUI/src/pages/testcases/ReactFlowDesigner.tsx - 修改内容:
- 扩展了nodeTypes映射,添加了不同类型的节点类型:
startStep: 开始步骤 (stepType=1)endStep: 结束步骤 (stepType=2)processStep: 处理步骤 (stepType=3)decisionStep: 判断步骤 (stepType=4)testStep: 默认类型
- 在节点创建逻辑中添加了
getNodeType函数,根据stepType返回对应的节点类型 - 修改了
onDrop函数中的节点创建逻辑,使用动态的节点类型而不是硬编码的'testStep'
- 扩展了nodeTypes映射,添加了不同类型的节点类型:
2. TestCaseDetailDrawer.tsx
- 文件位置:
X1.WebUI/src/components/testcases/TestCaseDetailDrawer.tsx - 修改内容:
- 扩展了nodeTypes映射,添加了相同的节点类型映射
- 在
getReactFlowData函数中添加了getNodeType函数 - 修改了节点数据转换逻辑,使用动态的节点类型
修改前后对比
修改前
// 所有节点都是相同的类型
const nodeTypes = {
testStep: TestStepNode,
};
const newNode = {
id: `node-${Date.now()}`,
type: 'testStep', // 硬编码
// ...
};
修改后
// 支持多种节点类型
const nodeTypes = {
testStep: TestStepNode,
startStep: TestStepNode,
endStep: TestStepNode,
processStep: TestStepNode,
decisionStep: TestStepNode,
};
const getNodeType = (stepType: number) => {
switch (stepType) {
case 1: return 'startStep';
case 2: return 'endStep';
case 3: return 'processStep';
case 4: return 'decisionStep';
default: return 'testStep';
}
};
const newNode = {
id: `node-${Date.now()}`,
type: getNodeType(step.stepType), // 动态类型
// ...
};
影响范围
- 修复了保存数据中节点类型不对称的问题
- 现在不同类型的节点会有不同的type值,便于区分和管理
- 保持了向后兼容性,所有节点仍然使用相同的TestStepNode组件进行渲染
测试建议
- 测试不同类型节点的创建和保存
- 验证保存的数据中节点类型是否正确
- 测试导入导出功能是否正常工作
- 确认节点显示和交互功能正常
2024年修改记录
分析相关页面搜索栏和按钮主题修复
修改时间: 2024年 修改文件:
X1.WebUI/src/pages/analysis/FunctionalAnalysisView.tsxX1.WebUI/src/pages/analysis/IssueAnalysisView.tsxX1.WebUI/src/pages/analysis/PerformanceAnalysisView.tsxX1.WebUI/src/pages/analysis/UEAnalysisView.tsx
修改内容:
-
搜索栏背景修复:
- 将硬编码的
bg-white改为bg-background - 添加
border-border类,使用主题变量 - 确保搜索栏背景与系统主题保持一致
- 将硬编码的
-
输入框样式优化:
- 移除自定义的
input类,使用默认的 Input 组件样式 - 确保输入框样式与系统主题一致
- 移除自定义的
-
选择框样式修复:
- 将选择框样式从简单的
input类改为完整的主题样式 - 添加焦点状态、禁用状态等完整的样式支持
- 使用主题变量:
border-input、bg-background、text-sm等
- 将选择框样式从简单的
-
按钮主题修复:
- 将硬编码的蓝色查询按钮改为使用主题变量
bg-primary和text-primary-foreground - 重置和展开按钮使用
bg-background、border-input等主题变量 - 添加悬停效果:
hover:bg-primary/90、hover:bg-accent等
- 将硬编码的蓝色查询按钮改为使用主题变量
修改原因:
- 修复分析相关页面搜索栏和按钮与系统主题不匹配的问题
- 确保在深色模式和浅色模式下都能正确显示
- 提供一致的用户体验和视觉效果
具体变更:
- <div className="flex flex-col bg-white p-4 rounded-md border mb-2">
+ <div className="flex flex-col bg-background p-4 rounded-md border border-border mb-2">
- <Input className="input flex-1" />
+ <Input className="flex-1" />
- <select className="input h-10 rounded border border-border bg-background px-3 text-sm flex-1">
+ <select className="h-10 rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 flex-1">
- <button className="px-4 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-md hover:bg-gray-50">重置</button>
+ <button className="px-4 py-2 text-sm font-medium text-foreground bg-background border border-input rounded-md hover:bg-accent hover:text-accent-foreground">重置</button>
- <button className="px-4 py-2 text-sm font-medium text-white bg-blue-600 border border-transparent rounded-md hover:bg-blue-700">查询</button>
+ <button className="px-4 py-2 text-sm font-medium text-primary-foreground bg-primary border border-transparent rounded-md hover:bg-primary/90">查询</button>
任务相关页面搜索栏主题修复
修改时间: 2024年 修改文件:
X1.WebUI/src/pages/tasks/TasksView.tsxX1.WebUI/src/pages/tasks/TaskExecutionView.tsxX1.WebUI/src/pages/tasks/TaskReviewView.tsx
修改内容:
-
搜索栏背景修复:
- 将硬编码的
bg-white改为bg-background - 添加
border-border类,使用主题变量 - 确保搜索栏背景与系统主题保持一致
- 将硬编码的
-
输入框样式优化:
- 移除自定义的
input类,使用默认的 Input 组件样式 - 确保输入框样式与系统主题一致
- 移除自定义的
-
选择框样式修复:
- 将选择框样式从简单的
input类改为完整的主题样式 - 添加焦点状态、禁用状态等完整的样式支持
- 使用主题变量:
border-input、bg-background、text-sm等
- 将选择框样式从简单的
修改原因:
- 修复任务相关页面搜索栏与系统主题不匹配的问题
- 确保在深色模式和浅色模式下都能正确显示
- 提供一致的用户体验和视觉效果
具体变更:
- <div className="flex flex-col bg-white p-4 rounded-md border mb-2">
+ <div className="flex flex-col bg-background p-4 rounded-md border border-border mb-2">
- <Input className="input flex-1" />
+ <Input className="flex-1" />
- <select className="input h-10 rounded border border-border bg-background px-3 text-sm flex-1">
+ <select className="h-10 rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 flex-1">
ScenariosView 搜索栏主题修复
修改时间: 2024年 修改文件:
X1.WebUI/src/pages/scenarios/ScenariosView.tsx
修改内容:
-
搜索栏背景修复:
- 将硬编码的
bg-white改为bg-background - 添加
border-border类,使用主题变量 - 确保搜索栏背景与系统主题保持一致
- 将硬编码的
-
输入框样式优化:
- 移除自定义的
input类,使用默认的 Input 组件样式 - 确保输入框样式与系统主题一致
- 移除自定义的
-
选择框样式修复:
- 将选择框样式从简单的
input类改为完整的主题样式 - 添加焦点状态、禁用状态等完整的样式支持
- 使用主题变量:
border-input、bg-background、text-sm等
- 将选择框样式从简单的
修改原因:
- 修复搜索栏与系统主题不匹配的问题
- 确保在深色模式和浅色模式下都能正确显示
- 提供一致的用户体验和视觉效果
具体变更:
- <div className="flex flex-col bg-white p-4 rounded-md border mb-2">
+ <div className="flex flex-col bg-background p-4 rounded-md border border-border mb-2">
- <Input className="input flex-1" />
+ <Input className="flex-1" />
- <select className="input h-10 rounded border border-border bg-background px-3 text-sm flex-1">
+ <select className="h-10 rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 flex-1">
CreateUserCommand 角色字段修复
CreateUserCommand 角色字段修复
修改时间: 2024年 修改文件:
X1.Application/Features/Users/Commands/CreateUser/CreateUserCommand.csX1.Application/Features/Users/Commands/CreateUser/CreateUserCommandHandler.csX1.Application/Features/Users/Commands/CreateUser/CreateUserCommandValidator.cs
修改内容:
-
CreateUserCommand 字段修改:
- 将
string[]? Roles = null改为string[] RoleIds - 添加
[Required]和[MinLength(1)]验证特性 - 移除默认值,设置为必填项
- 将
-
CreateUserCommandHandler 逻辑更新:
- 移除默认角色逻辑
request.Roles ?? new[] { "User" } - 直接使用
request.RoleIds调用AssignUserRolesAsync - 更新验证逻辑,检查角色ID而不是角色名称
- 移除默认角色逻辑
-
CreateUserCommandValidator 验证更新:
- 将
Roles验证改为RoleIds验证 - 添加必填验证:
NotEmpty()和Must(roleIds => roleIds.Length > 0) - 移除角色名称格式验证,保留角色ID长度验证
- 将
-
具体变更:
- 命令字段:
string[] RoleIds(必填) - 验证特性:
[Required(ErrorMessage = "角色ID数组不能为空")] - 验证特性:
[MinLength(1, ErrorMessage = "至少需要分配一个角色")] - 处理器调用:
AssignUserRolesAsync(user, request.RoleIds) - 验证器规则: 角色ID数组不能为空,至少需要一个角色
- 命令字段:
修改原因:
- 确保创建用户时必须分配角色,不能为空
- 使用角色ID而不是角色名称,与 UserRegistrationService 保持一致
- 提高数据完整性和业务逻辑的一致性
前端用户服务修复
修改时间: 2024年 修改文件:
X1.WebUI/src/services/userService.tsX1.WebUI/src/pages/users/UserForm.tsxX1.WebUI/src/pages/users/UsersView.tsxX1.WebUI/src/pages/users/UserTable.tsxX1.WebUI/src/pages/users/UserRolesForm.tsx
修改内容:
-
userService.ts 接口更新:
- 将
CreateUserRequest中的roles?: string[]改为roleIds: string[] - 将
User接口中的roles: string[]改为roleIds: string[] - 确保前后端数据结构一致
- 将
-
UserForm.tsx 组件修复:
- 将表单数据中的
roles改为roleIds - 更新角色选择逻辑,使用角色ID而不是角色名称
- 修复
handleRoleChange函数,处理角色ID数组
- 将表单数据中的
-
UsersView.tsx 页面修复:
- 更新
handleCreate函数参数类型 - 修复
handleSetRoles函数参数名 - 更新编辑用户时的初始数据传递
- 更新
-
UserTable.tsx 表格修复:
- 更新角色显示逻辑,使用
user.roleIds而不是user.roles - 确保表格正确显示角色ID信息
- 更新角色显示逻辑,使用
-
UserRolesForm.tsx 表单修复:
- 将表单字段从
roles改为roleIds - 更新复选框逻辑,使用角色ID进行选择
- 修复表单提交时的数据处理
- 将表单字段从
修改原因:
- 确保前端与后端 CreateUserCommand 的数据结构完全一致
- 使用角色ID而不是角色名称,提高数据准确性和一致性
- 修复所有相关的用户管理功能,确保正常工作
修改时间: 2024年 修改文件:
X1.Application/Features/Users/Commands/CreateUser/CreateUserCommand.csX1.Application/Features/Users/Commands/CreateUser/CreateUserCommandHandler.csX1.Application/Features/Users/Commands/CreateUser/CreateUserCommandValidator.cs
修改内容:
-
CreateUserCommand 字段修改:
- 将
string[]? Roles = null改为string[] RoleIds - 添加
[Required]和[MinLength(1)]验证特性 - 移除默认值,设置为必填项
- 将
-
CreateUserCommandHandler 逻辑更新:
- 移除默认角色逻辑
request.Roles ?? new[] { "User" } - 直接使用
request.RoleIds调用AssignUserRolesAsync - 更新验证逻辑,检查角色ID而不是角色名称
- 移除默认角色逻辑
-
CreateUserCommandValidator 验证更新:
- 将
Roles验证改为RoleIds验证 - 添加必填验证:
NotEmpty()和Must(roleIds => roleIds.Length > 0) - 移除角色名称格式验证,保留角色ID长度验证
- 将
-
具体变更:
- 命令字段:
string[] RoleIds(必填) - 验证特性:
[Required(ErrorMessage = "角色ID数组不能为空")] - 验证特性:
[MinLength(1, ErrorMessage = "至少需要分配一个角色")] - 处理器调用:
AssignUserRolesAsync(user, request.RoleIds) - 验证器规则: 角色ID数组不能为空,至少需要一个角色
- 命令字段:
修改原因:
- 确保创建用户时必须分配角色,不能为空
- 使用角色ID而不是角色名称,与 UserRegistrationService 保持一致
- 提高数据完整性和业务逻辑的一致性
2024-12-19 - 用户管理页面修复
问题分析
- UsersView.tsx 中的搜索字段与后端API不匹配
- 搜索字段使用了错误的字段名(name, phone, role, account, status)
- 后端API实际支持的搜索参数是:pageNumber, pageSize, searchTerm, isActive
- 搜索表单没有正确绑定状态和事件处理
修复内容
- 修正搜索字段配置,使其与后端API匹配
- 添加正确的状态管理和事件处理
- 保持原有的搜索栏样式,支持用户名、状态、角色搜索
- 修复搜索逻辑,确保查询参数正确传递
- 移除展开/收起功能,保持简洁的一行搜索布局
- 修复后端GetAllUsersQueryHandler响应,添加角色名称信息
- 更新前端User接口以匹配后端数据结构
- 修复前端组件中的字段名错误(id -> userId)
- 优化角色显示,使用角色名称而不是角色ID
- 性能优化:解决GetAllUsersQueryHandler的N+1查询问题,使用并行处理和角色缓存
修改文件
- X1.WebUI/src/pages/users/UsersView.tsx
- X1.WebUI/src/pages/users/UserTable.tsx
- X1.WebUI/src/services/userService.ts
- X1.Application/Features/Users/Queries/Dtos/UserDto.cs
- X1.Application/Features/Users/Queries/GetAllUsers/GetAllUsersQueryHandler.cs
修改时间
2024-12-19
修改原因
用户反映 UsersView.tsx 和 UserTable.tsx 与系统不匹配,需要参考 RolesView.tsx 和 RoleTable.tsx 的结构进行修复,确保前后端数据一致性和用户体验统一。
2025-01-21 - UserForm 组件添加角色选择功能
修改文件:
X1.WebUI/src/pages/users/UserForm.tsx - 为用户创建和编辑表单添加角色选择功能
修改内容:
-
角色选择功能添加:
- 导入依赖:添加
useEffect,useState和roleService,Role导入 - 状态管理:添加
roles和loading状态管理角色数据和加载状态 - 数据获取:在组件挂载时自动获取所有可用角色列表
- 角色选择:使用
Checkbox组件实现多角色选择功能
- 导入依赖:添加
-
角色选择界面:
- 加载状态:显示"加载角色中..."提示
- 网格布局:使用
grid grid-cols-2 gap-4布局,每行显示两个角色 - 复选框:每个角色使用独立的复选框,支持多选
- 标签显示:显示角色名称,使用
text-sm font-normal样式
-
角色数据处理:
- 初始值设置:在
formData中初始化roles字段为initialData?.roles || [] - 角色变更处理:实现
handleRoleChange方法处理角色选择/取消选择 - 数据同步:确保表单数据与角色选择状态保持同步
- 初始值设置:在
-
技术特性:
- 异步加载:使用
useEffect异步加载角色数据 - 错误处理:通过
roleService.getAllRoles()的错误处理机制 - 用户体验:加载状态提示,防止用户困惑
- 数据完整性:确保角色数据正确传递给后端
- 异步加载:使用
-
界面布局:
- 表单结构:在密码字段后添加角色选择区域
- 响应式设计:使用网格布局适应不同屏幕尺寸
- 视觉一致性:与现有表单字段保持一致的样式和间距
修改时间:
2025-01-21
修改原因:
用户发现虽然 userService.ts 中的 CreateUserRequest 接口支持 roles?: string[] 字段,但 UserForm.tsx 组件中缺少角色选择功能。需要添加角色选择功能,使用户能够在创建和编辑用户时选择多个角色,确保前端界面与后端 CreateUserCommand 完全匹配。
2025-01-21 - NodeData 添加 stepId 必填字段和 TestCaseNode 实体修复
修改文件:
X1.Application/Features/TestCaseFlow/Commands/CreateTestCaseFlow/CreateTestCaseFlowCommand.cs- 为 NodeData 类添加 stepId 必填字段X1.Domain/Entities/TestCase/TestCaseNode.cs- 修复 TestCaseNode 实体的 stepId 字段和 Create 方法X1.Infrastructure/Configurations/TestCase/TestCaseNodeConfiguration.cs- 更新 TestCaseNode 数据库配置X1.WebUI/src/services/testcaseService.ts- 为 CreateNodeData 接口添加 stepId 必填字段X1.Application/Features/TestCaseFlow/Commands/CreateTestCaseFlow/CreateTestCaseFlowCommandHandler.cs- 修复 TestCaseNode.Create 方法调用,添加 stepId 参数X1.WebUI/src/pages/testcases/TestCasesView.tsx- 修复节点数据转换,添加 stepId 字段
修改内容:
-
NodeData 类增强:
- 在
NodeData类中添加了StepId属性 - 设置为必填字段:
[Required(ErrorMessage = "步骤ID不能为空")] - 类型为
string,默认值为null!
- 在
-
TestCaseNode 实体修复:
- StepId 字段:从
string?改为string,添加[Required]验证特性 - Create 方法:将
stepId参数从可选改为必填,移除默认值= null - 参数注释:更新注释说明 stepId 为必填参数
- StepId 字段:从
-
TestCaseNodeConfiguration 配置更新:
- 数据库约束:为
StepId字段添加IsRequired()约束 - 外键关系:将删除行为从
SetNull改为Restrict,防止删除步骤配置时影响节点数据
- 数据库约束:为
-
testcaseService.ts 前端服务修复:
- CreateNodeData 接口:添加
stepId: string必填字段 - 类型安全:确保前端创建节点时必须提供步骤ID
- 前后端一致:与后端 NodeData 类保持完全一致
- CreateNodeData 接口:添加
-
CreateTestCaseFlowCommandHandler 修复:
- TestCaseNode.Create 调用:添加
stepId: nodeData.StepId参数 - 编译错误修复:解决 CS7036 编译错误
- 参数完整性:确保所有必需参数都正确传递
- TestCaseNode.Create 调用:添加
-
TestCasesView 前端修复:
- 节点数据转换:在
handleSaveFlow函数中添加stepId: node.data?.stepId || ''字段 - 数据完整性:确保前端保存时包含步骤ID信息
- 前后端一致:与后端 CreateNodeData 接口保持完全一致
- 节点数据转换:在
-
技术特性:
- 数据验证:确保步骤ID字段不为空
- 用户友好:提供清晰的错误提示信息
- 业务逻辑:符合测试用例节点必须关联步骤配置的业务需求
- 类型安全:使用强类型验证,避免运行时错误
- 数据完整性:通过外键约束确保数据一致性
- 前后端一致:确保前端和后端的数据结构完全匹配
-
设计原则:
- 数据完整性:确保必要字段不为空
- 用户体验:提供明确的验证反馈
- 业务规则:符合测试用例流程设计的业务需求
- 代码一致性:与项目中其他必填字段的处理方式保持一致
- 数据库约束:通过数据库层约束确保业务规则
- 前后端同步:确保前端和后端的数据模型保持同步
修改时间:
2025-01-21
修改原因:
用户要求 NodeData 需要加一个 stepId 必填项,不能为空,同时发现 TestCaseNode 实体的 Create 方法中 stepId 参数设置为可选是不对的,需要修复为必填,并更新相应的数据库配置和前端服务,确保整个系统的数据一致性。
2025-01-21 - 创建 TestCaseFlow 相关表的数据库迁移
修改文件:
X1.Infrastructure/Migrations/20250821080604_AddTestCaseFlowTables.cs- 新建迁移文件X1.Infrastructure/Migrations/20250821080604_AddTestCaseFlowTables.Designer.cs- 迁移设计器文件X1.Infrastructure/Migrations/AppDbContextModelSnapshot.cs- 更新模型快照
修改内容:
-
迁移文件创建:
- 迁移名称:
AddTestCaseFlowTables - 迁移时间:2025-08-21 08:06:04
- 迁移描述:为 TestCaseFlow、TestCaseNode、TestCaseEdge 实体创建数据库表
- 迁移名称:
-
创建的表结构:
-
tb_testcaseflow:测试用例流程主表
- 包含 id、name、description、type、isenabled、viewport_x、viewport_y、viewport_zoom 等字段
- 包含审计字段:createdat、updatedat、createdby、updatedby
- 创建索引:name、type、isenabled
-
tb_testcasenode:测试用例节点表
- 包含 id、testcaseid、nodeid、sequencenumber、stepid、positionx、positiony、width、height 等字段
- 包含状态字段:isselected、positionabsolutex、positionabsolutey、isdragging
- 外键关系:testcaseid → tb_testcaseflow.id (CASCADE)
- 外键关系:stepid → tb_casestepconfig.id (RESTRICT)
- 创建索引:testcaseid、nodeid、sequencenumber、stepid
-
tb_testcaseedge:测试用例连线表
- 包含 id、testcaseid、edgeid、sourcenodeid、targetnodeid、edgetype、condition、isanimated、style 等字段
- 外键关系:testcaseid → tb_testcaseflow.id (CASCADE)
- 创建索引:testcaseid、edgeid、sourcenodeid、targetnodeid
-
-
数据库关系:
- 级联删除:删除测试用例流程时,自动删除相关的节点和连线
- 可选关联:节点可以关联步骤配置,删除步骤配置时节点 stepid 设为 NULL
- 完整性约束:确保数据的一致性和完整性
-
迁移应用状态:
- 已成功应用:迁移已应用到数据库
- 表已创建:三个表都已成功创建在数据库中
- 索引已建立:所有必要的索引都已创建完成
-
技术特性:
- PostgreSQL 兼容:使用 PostgreSQL 特定的数据类型和语法
- 性能优化:为常用查询字段创建索引
- 数据完整性:通过外键约束确保数据一致性
- 审计支持:包含完整的审计字段支持
修改时间:
2025-01-21
修改原因:
用户反映 TestCaseFlows、TestCaseNodes、TestCaseEdges 新建后还没有迁移数据库,需要创建相应的数据库迁移文件并应用到数据库中,以支持测试用例流程管理功能。
2025-01-19 - 根据 TestCaseFlowController 修复 testcaseService.ts
修改文件:
X1.WebUI/src/services/testcaseService.ts - 根据后端 TestCaseFlowController 重新编写前端服务
修改内容:
-
完全重构服务:
- 服务类名:从
TestCaseService改为TestCaseFlowService - 基础URL:从
/api/testcases改为/api/testcaseflow - API端点:完全匹配后端 TestCaseFlowController 的接口
- 服务类名:从
-
数据类型重新定义:
- TestFlowType:测试流程类型枚举
- TestCaseFlow:测试用例流程基础信息
- TestCaseNode:测试用例节点(支持 ReactFlow)
- TestCaseEdge:测试用例连线(支持 ReactFlow)
- TestCaseFlowDetail:测试用例流程详情(包含节点和连线)
-
API 方法对应:
- getTestCaseFlows:对应
GET /api/testcaseflow- 获取流程列表 - getTestCaseFlowById:对应
GET /api/testcaseflow/{id}- 获取流程详情 - createTestCaseFlow:对应
POST /api/testcaseflow- 创建流程 - deleteTestCaseFlow:对应
DELETE /api/testcaseflow/{id}- 删除流程
- getTestCaseFlows:对应
-
请求参数匹配:
- GetTestCaseFlowsRequest:支持 searchTerm、type、isEnabled、pageNumber、pageSize
- CreateTestCaseFlowRequest:支持 name、description、type、isEnabled、viewport、nodes、edges
- CreateNodeData:节点创建数据结构
- CreateEdgeData:连线创建数据结构
-
响应数据结构:
- GetTestCaseFlowsResponse:包含分页信息的流程列表
- GetTestCaseFlowByIdResponse:包含完整节点和连线数据的流程详情
- CreateTestCaseFlowResponse:创建成功后的流程信息
-
ReactFlow 兼容性:
- 节点结构:完全支持 ReactFlow 的节点数据结构
- 连线结构:完全支持 ReactFlow 的连线数据结构
- 位置信息:支持 position、positionAbsolute 等位置字段
- 样式信息:支持 style、data 等样式和数据字段
-
向后兼容性:
- 保留导出:保持
testcaseService导出,确保现有代码不破坏 - 新增导出:新增
testcaseFlowService导出,提供更明确的命名
- 保留导出:保持
修改时间:
2025-01-19
修改原因:
用户要求根据 TestCaseFlowController 修复 testcaseService.ts,确保前端服务与后端 API 完全匹配,支持测试用例流程的完整 CRUD 操作和 ReactFlow 集成。
2025-01-19 - 更新 API 路径常量以匹配后端控制器
修改文件:
X1.WebUI/src/constants/api.ts- 更新 API 路径常量X1.WebUI/src/services/testcaseService.ts- 使用 API 路径常量
修改内容:
-
API 路径常量更新:
- 移除:
TEST_CASES: '/test-cases'和TEST_STEPS: '/test-steps'(后端无对应控制器) - 新增:
TEST_CASE_FLOW: '/api/testcaseflow'(对应 TestCaseFlowController) - 更新:
CASE_STEP_CONFIGS: '/api/casestepconfigs'(对应 CaseStepConfigController)
- 移除:
-
testcaseService.ts 优化:
- 导入常量:添加
API_PATHS导入 - 使用常量:将硬编码的
/api/testcaseflow替换为API_PATHS.TEST_CASE_FLOW - 统一管理:所有 API 路径都通过常量统一管理
- 导入常量:添加
-
路径对应关系:
- TestCaseFlowController:
/api/testcaseflow→API_PATHS.TEST_CASE_FLOW - CaseStepConfigController:
/api/casestepconfigs→API_PATHS.CASE_STEP_CONFIGS
- TestCaseFlowController:
-
技术特性:
- 类型安全:使用 TypeScript 常量确保路径一致性
- 维护性:集中管理 API 路径,便于维护和修改
- 一致性:确保前端服务与后端控制器路径完全匹配
修改时间:
2025-01-19
修改原因:
用户询问是否需要根据 testcaseService 修复其他相关服务,发现 API 路径常量与实际后端控制器不匹配,需要统一更新以确保前后端一致性。
2025-01-19 - 修复 pages/testcases 页面使用 testcaseService
修改文件:
X1.WebUI/src/pages/testcases/TestCasesListView.tsx- 修复列表页面使用真实 APIX1.WebUI/src/pages/testcases/TestCasesView.tsx- 修复视图页面使用真实 APIX1.WebUI/src/pages/testcases/ReactFlowDesigner.tsx- 添加保存状态支持
修改内容:
-
TestCasesListView.tsx 重构:
- 移除模拟数据:删除
mockTestCases和本地接口定义 - 集成真实 API:使用
testcaseService.getTestCaseFlows()获取数据 - 添加加载状态:显示加载中状态,提升用户体验
- 实现搜索功能:支持按名称搜索测试用例流程
- 实现删除功能:使用
testcaseService.deleteTestCaseFlow()删除流程 - 更新数据展示:适配
TestCaseFlow接口的数据结构 - 修复状态显示:使用
isEnabled字段显示启用/停用状态 - 添加类型标签:显示测试流程类型(功能测试、性能测试等)
- 移除模拟数据:删除
-
TestCasesView.tsx 重构:
- 集成保存功能:使用
testcaseService.createTestCaseFlow()保存流程 - 数据格式转换:将 ReactFlow 节点和连线数据转换为后端格式
- 添加保存状态:显示保存中状态,防止重复提交
- 错误处理:完整的错误处理和用户提示
- 流程验证:检查流程完整性(开始节点、结束节点等)
- 集成保存功能:使用
-
ReactFlowDesigner.tsx 增强:
- 添加 saving 属性:支持保存状态传递
- 保存按钮状态:保存时禁用按钮并显示"保存中..."
- 用户体验优化:防止保存过程中的重复操作
-
数据结构适配:
- 节点数据转换:ReactFlow 节点 → 后端 CreateNodeData 格式
- 连线数据转换:ReactFlow 连线 → 后端 CreateEdgeData 格式
- 类型安全:使用 TypeScript 接口确保类型安全
-
功能特性:
- 实时搜索:支持按回车键搜索
- 批量操作:支持删除操作
- 导航功能:支持查看和编辑页面跳转
- 状态管理:完整的加载和保存状态管理
修改时间:
2025-01-19
修改原因:
用户发现 pages/testcases 页面没有调用 testcaseService,需要修复这些页面使其使用真实的 API 而不是模拟数据,确保前后端数据一致性。
2025-01-19 - TestCaseFlowController 添加 CreateTestCaseFlow 命令
修改文件:
X1.Presentation/Controllers/TestCaseFlowController.cs - 为TestCaseFlowController添加创建测试用例流程的POST方法
修改内容:
-
新增POST方法:
- 方法名:
CreateTestCaseFlow - 路由:
[HttpPost]- 对应/api/testcaseflow - 参数:
[FromBody] CreateTestCaseFlowCommand command - 返回:
IActionResult
- 方法名:
-
功能特性:
- 命令处理:使用
mediator.Send(command)发送创建命令 - 日志记录:详细的开始、成功、失败日志记录
- 错误处理:完整的错误处理和用户友好的错误信息
- 响应格式:使用
CreatedAtAction返回201状态码和资源位置
- 命令处理:使用
-
日志记录:
- 开始日志:记录流程名称和类型
- 成功日志:记录创建的ID、名称、节点数量、连线数量
- 失败日志:记录流程名称和详细错误信息
-
响应处理:
- 成功响应:返回201 Created状态码,包含新创建资源的URI
- 失败响应:返回400 Bad Request状态码,包含错误详情
- 资源定位:使用
CreatedAtAction提供新创建资源的访问路径
-
技术特性:
- 依赖注入:添加了
CreateTestCaseFlow命名空间的using语句 - MediatR集成:使用mediator发送命令,遵循CQRS模式
- RESTful设计:遵循REST API设计规范
- 统一响应:使用统一的OperationResult响应格式
- 依赖注入:添加了
-
API端点:
POST /api/testcaseflow Content-Type: application/json { "name": "测试流程名称", "description": "流程描述", "type": 1, "isEnabled": true, "viewportX": 40.5, "viewportY": 21.2, "viewportZoom": 1.1, "nodes": [...], "edges": [...] }
修改时间:
2025-01-19
修改原因:
用户要求为TestCaseFlowController添加TestCaseFlow.Commands功能,特别是创建测试用例流程的POST方法,以支持前端界面创建新的测试用例流程。
2025-01-19 - TestCaseNodeDto 和 TestCaseEdgeDto 完善
修改文件:
X1.Application/Features/TestCaseFlow/Queries/GetTestCaseFlowById/GetTestCaseFlowByIdResponse.cs - 完善 TestCaseNodeDto 和 TestCaseEdgeDto 结构
修改内容:
-
新增 DTO 类:
- TestCaseNodeDataDto:节点数据DTO,包含步骤ID、步骤名称、步骤类型、描述、图标等
- TestCaseNodePositionDto:节点位置DTO,包含X、Y坐标
- TestCaseEdgeStyleDto:连线样式DTO,包含描边颜色、描边宽度
- TestCaseEdgeDataDto:连线数据DTO,包含条件信息
-
TestCaseNodeDto 增强:
- 新增字段:
Type:节点类型(如 "testStep")Position:节点位置(TestCaseNodePositionDto)Data:节点数据(TestCaseNodeDataDto)Selected:是否被选中PositionAbsolute:绝对位置Dragging:是否正在拖拽
- 兼容性字段:保留原有字段,确保向后兼容
- 新增字段:
-
TestCaseEdgeDto 增强:
- 新增字段:
Source:源节点IDSourceHandle:源连接点Target:目标节点IDTargetHandle:目标连接点Type:连线类型Animated:是否动画Style:连线样式(TestCaseEdgeStyleDto)Data:连线数据(TestCaseEdgeDataDto)
- 兼容性字段:保留原有字段,确保向后兼容
- 新增字段:
-
技术特性:
- ReactFlow 兼容:新增字段与 ReactFlow 数据结构完全兼容
- JSON 序列化:支持直接序列化为 ReactFlow 所需的 JSON 格式
- 向后兼容:保留原有字段,确保现有代码不受影响
- 类型安全:使用强类型 DTO,避免运行时错误
-
数据结构示例:
{ "nodes": [ { "id": "node-1755654432101", "type": "testStep", "position": { "x": 360, "y": 30 }, "data": { "stepId": "e2192f5a-1582-47e9-92be-c676679418da", "stepName": "StartStep", "stepType": 1, "stepTypeName": "Start", "description": "Mapping_Start", "icon": "play-circle" }, "width": 95, "height": 30, "selected": false, "positionAbsolute": { "x": 360, "y": 30 }, "dragging": false } ], "edges": [ { "source": "node-1755654432101", "sourceHandle": "bottom", "target": "node-1755654436065", "targetHandle": "top", "id": "edge-1755654470705", "type": "smoothstep", "animated": false, "style": { "stroke": "#3b82f6", "strokeWidth": 2 }, "data": { "condition": "default" } } ] } -
设计原则:
- 前端兼容:确保与 ReactFlow 前端组件完全兼容
- 数据完整性:支持完整的节点和连线信息
- 扩展性:支持未来功能扩展
- 性能优化:避免不必要的数据转换
修改时间:
2025-01-19
修改原因:
用户需要 TestCaseNodeDto 和 TestCaseEdgeDto 与 ReactFlow 前端组件完全兼容,支持完整的节点和连线数据结构,包括位置、样式、数据等字段,确保前端能够正确显示和操作测试用例流程。
2025-01-19 - TestCaseFlow Queries功能实现
修改文件:
X1.Application/Features/TestCaseFlow/Queries/GetTestCaseFlows/- 获取TestCaseFlow列表查询X1.Application/Features/TestCaseFlow/Queries/GetTestCaseFlowById/- 根据ID获取TestCaseFlow详情查询X1.Presentation/Controllers/TestCaseFlowController.cs- TestCaseFlow控制器
修改内容:
-
GetTestCaseFlows查询功能:
- 查询类:
GetTestCaseFlowsQuery- 支持搜索、类型过滤、启用状态过滤、分页 - 响应类:
GetTestCaseFlowsResponse- 包含分页信息和TestCaseFlow列表 - 处理器:
GetTestCaseFlowsQueryHandler- 调用仓储获取分页数据并映射为DTO
- 查询类:
-
GetTestCaseFlowById查询功能:
- 查询类:
GetTestCaseFlowByIdQuery- 根据testCaseId获取详情 - 响应类:
GetTestCaseFlowByIdResponse- 包含完整的流程信息、节点和连线数据 - 处理器:
GetTestCaseFlowByIdQueryHandler- 组装TestCaseFlow、TestCaseNode、TestCaseEdge数据
- 查询类:
-
TestCaseFlowController控制器:
- 列表接口:
GET /api/testcaseflow- 获取测试用例流程列表,支持搜索和分页 - 详情接口:
GET /api/testcaseflow/{id}- 获取测试用例流程详情,包含节点和连线 - 完整日志:详细的日志记录和错误处理
- 列表接口:
-
数据组装特性:
- 列表查询:直接返回TestCaseFlow数据,不包含节点和连线
- 详情查询:组装完整的流程信息,包括所有节点和连线数据
- 性能优化:使用仓储的
GetTestCaseFlowWithDetailsAsync方法一次性获取所有数据
-
技术特性:
- CQRS模式:查询和命令分离,使用MediatR进行消息传递
- 分页支持:支持搜索、过滤、分页功能
- 数据完整性:详情查询包含完整的流程结构信息
- 错误处理:完整的异常处理和日志记录
修改时间:
2025-01-19
修改原因:
用户需要为TestCaseFlow实现Queries功能,包括获取列表和根据testCaseId获取详情,详情查询需要组装TestCaseNode和TestCaseEdge数据,为前端界面查看详情提供完整的数据支持。
2025-01-19 - TestCaseFlow 空引用警告修复和连线样式类型优化
修改文件:
X1.Application/Features/TestCaseFlow/Commands/CreateTestCaseFlow/CreateTestCaseFlowCommandHandler.cs- 修复空引用警告X1.Application/Features/TestCaseFlow/Commands/CreateTestCaseFlow/CreateTestCaseFlowCommand.cs- 优化连线样式类型
修改内容:
-
空引用警告修复:
- 问题:在
CreateTestCaseFlowCommandHandler中,ValidateUserAuthentication方法返回的OperationResult<string>可能为空 - 解决方案:使用空合并操作符
??确保传递给CreateFailure方法的参数不为空 - 修改代码:
return OperationResult<CreateTestCaseFlowResponse>.CreateFailure(errorMessages ?? new List<string>());
- 问题:在
-
连线样式类型优化:
- 问题:
Style属性被定义为object?类型,但在CreateEdgesAsync方法中使用edgeData.Style?.ToString()来转换 - 解决方案:将
Style属性明确为string?类型,符合 JSON 字符串格式的实际用途 - 修改代码:
- 问题:
-
连线类型必填验证:
- 在
EdgeData类中将Type属性设为必填:[Required(ErrorMessage = "连线类型不能为空")] - 在验证逻辑中添加对
Type的验证:if (string.IsNullOrWhiteSpace(edge.Type)) - 在创建连线时移除默认值逻辑:
edgeType: edgeData.Type(不再使用?? "straight")
- 在
-
验证器提取:
- 创建了
CreateTestCaseFlowCommandValidator验证器类 - 将
ValidateRequest方法从CreateTestCaseFlowCommandHandler中提取出来 - 使用静态方法
Validate进行验证,便于复用和测试 - 保持原有的验证逻辑和错误消息不变
- 创建了
-
设计原则:
- 单一职责:验证器专注于参数验证,处理器专注于业务逻辑
- 可复用性:验证器可以在其他地方复用
- 可测试性:独立的验证器更容易进行单元测试
- 代码组织:更好的代码结构和职责分离
修改时间:
2025-01-19
修改原因:
用户要求确保连线类型是必填项,界面不能传空值。同时要求将验证逻辑提取到单独的验证器类中,提高代码的可维护性和可测试性。
2025-01-19 - TestCaseFlowController 删除功能添加和接口返回类型统一
修改文件:
X1.Application/Features/TestCaseFlow/Commands/DeleteTestCaseFlow/DeleteTestCaseFlowCommand.cs- 新增删除命令X1.Application/Features/TestCaseFlow/Commands/DeleteTestCaseFlow/DeleteTestCaseFlowCommandHandler.cs- 新增删除命令处理器X1.Presentation/Controllers/TestCaseFlowController.cs- 添加删除端点和统一返回类型
修改内容:
-
删除命令实现:
- 创建了
DeleteTestCaseFlowCommand类,包含流程ID参数 - 创建了
DeleteTestCaseFlowCommandHandler处理器,实现删除逻辑 - 包含用户认证验证、流程存在性检查、删除操作和事务提交
- 创建了
-
控制器接口统一:
- 参考
TerminalServicesController的返回方式,将所有方法返回类型改为OperationResult<T> - 移除了
IActionResult和BadRequest/Ok等 HTTP 状态码处理 - 直接返回
OperationResult<T>对象,让框架自动处理 HTTP 状态码
- 参考
-
删除端点添加:
- 添加了
DELETE /api/testcaseflow/{id}端点 - 包含完整的日志记录和错误处理
- 返回删除操作的结果
- 添加了
-
技术特性:
- 一致性:与
TerminalServicesController保持相同的接口返回模式 - 简化:移除了手动的 HTTP 状态码处理,让框架自动处理
- 完整性:删除功能包含完整的业务逻辑验证和错误处理
- 一致性:与
API 端点示例:
DELETE /api/testcaseflow/{id}
Authorization: Bearer {token}
响应格式:
{
"isSuccess": true,
"data": true,
"errorMessages": null
}
修改时间:
2025-01-19
修改原因:
用户要求添加删除功能到 TestCaseFlowController,并参考 TerminalServicesController 的接口返回方式,统一使用 OperationResult<T> 返回类型,不使用 IActionResult。
2025-01-19 - TestCaseFlow Application层实现
修改文件:
X1.Application/Features/TestCaseFlow/Commands/CreateTestCaseFlow/CreateTestCaseFlowCommand.cs- 创建测试用例流程命令X1.Application/Features/TestCaseFlow/Commands/CreateTestCaseFlow/CreateTestCaseFlowResponse.cs- 创建测试用例流程响应X1.Application/Features/TestCaseFlow/Commands/CreateTestCaseFlow/CreateTestCaseFlowCommandHandler.cs- 创建测试用例流程命令处理器
修改内容:
-
CreateTestCaseFlowCommand 命令类:
- 实现了
IRequest<OperationResult<CreateTestCaseFlowResponse>>接口 - 包含完整的验证特性:
[Required]、[MaxLength]等 - 支持所有必要字段:名称、描述、类型、启用状态、视口坐标等
- 提供合理的默认值,如视口坐标和启用状态
- 实现了
-
CreateTestCaseFlowResponse 响应类:
- 包含完整的流程信息返回
- 支持类型枚举转换为字符串显示
- 包含审计信息:创建时间、创建人等
-
CreateTestCaseFlowCommandHandler 命令处理器:
- 遵循CQRS模式,使用MediatR框架
- 完整的参数验证和业务逻辑验证
- 用户认证验证
- 名称重复性检查
- 使用领域实体的Create工厂方法
- 完整的错误处理和日志记录
- 事务管理(通过UnitOfWork)
-
设计原则:
- 参考TerminalServices模式:完全按照TerminalServices的设计规则实现
- CQRS架构:命令和查询分离
- 领域驱动设计:使用领域实体的工厂方法
- 依赖注入:通过构造函数注入依赖
- 日志记录:完整的操作日志和错误日志
- 错误处理:统一的错误处理和响应格式
-
技术特性:
- 支持异步操作
- 完整的取消令牌支持
- 统一的OperationResult响应格式
- 详细的验证错误信息
- 事务性操作保证
修改时间:
2025-01-19
修改原因:
用户要求在X1.Application.Features中实现TestCaseFlow的功能,参考TerminalServices的设计规则,先完成创建功能。为测试用例流程管理提供完整的Application层支持,包括命令、响应和处理器实现。
修复记录:
- 编译错误修复:修复了
TestCaseFlow.Create方法调用时的命名空间解析问题,使用完全限定的类型名称X1.Domain.Entities.TestCase.TestCaseFlow.Create来解决编译器无法找到Create方法的问题。
2025-01-19 - TestCaseFlow 空引用警告修复和连线样式类型优化
- 命令扩展:在
CreateTestCaseFlowCommand中添加了NodeData和EdgeDataDTO类,支持节点和连线数据的传输 - 处理器增强:在
CreateTestCaseFlowCommandHandler中添加了ITestCaseNodeRepository和ITestCaseEdgeRepository依赖注入 - 节点创建:实现了
CreateNodesAsync方法,支持批量创建测试用例节点,包括位置、尺寸、状态等属性 - 连线创建:实现了
CreateEdgesAsync方法,支持批量创建测试用例连线,包括源节点、目标节点、类型、样式等属性 - 验证增强:添加了对节点和连线数据的验证逻辑,确保数据完整性
修改记录
2025-01-21 - 创建 TestCaseFlow 相关表的数据库迁移
修改文件:
X1.Infrastructure/Migrations/20250821080604_AddTestCaseFlowTables.cs- 新建迁移文件X1.Infrastructure/Migrations/20250821080604_AddTestCaseFlowTables.Designer.cs- 迁移设计器文件X1.Infrastructure/Migrations/AppDbContextModelSnapshot.cs- 更新模型快照
修改内容:
-
迁移文件创建:
- 迁移名称:
AddTestCaseFlowTables - 迁移时间:2025-08-21 08:06:04
- 迁移描述:为 TestCaseFlow、TestCaseNode、TestCaseEdge 实体创建数据库表
- 迁移名称:
-
创建的表结构:
-
tb_testcaseflow:测试用例流程主表
- 包含 id、name、description、type、isenabled、viewport_x、viewport_y、viewport_zoom 等字段
- 包含审计字段:createdat、updatedat、createdby、updatedby
- 创建索引:name、type、isenabled
-
tb_testcasenode:测试用例节点表
- 包含 id、testcaseid、nodeid、sequencenumber、stepid、positionx、positiony、width、height 等字段
- 包含状态字段:isselected、positionabsolutex、positionabsolutey、isdragging
- 外键关系:testcaseid → tb_testcaseflow.id (CASCADE)
- 外键关系:stepid → tb_casestepconfig.id (SET NULL)
- 创建索引:testcaseid、nodeid、sequencenumber、stepid
-
tb_testcaseedge:测试用例连线表
- 包含 id、testcaseid、edgeid、sourcenodeid、targetnodeid、edgetype、condition、isanimated、style 等字段
- 外键关系:testcaseid → tb_testcaseflow.id (CASCADE)
- 创建索引:testcaseid、edgeid、sourcenodeid、targetnodeid
-
-
数据库关系:
- 级联删除:删除测试用例流程时,自动删除相关的节点和连线
- 可选关联:节点可以关联步骤配置,删除步骤配置时节点 stepid 设为 NULL
- 完整性约束:确保数据的一致性和完整性
-
迁移应用状态:
- 已成功应用:迁移已应用到数据库
- 表已创建:三个表都已成功创建在数据库中
- 索引已建立:所有必要的索引都已创建完成
-
技术特性:
- PostgreSQL 兼容:使用 PostgreSQL 特定的数据类型和语法
- 性能优化:为常用查询字段创建索引
- 数据完整性:通过外键约束确保数据一致性
- 审计支持:包含完整的审计字段支持
修改时间:
2025-01-21
修改原因:
用户反映 TestCaseFlows、TestCaseNodes、TestCaseEdges 新建后还没有迁移数据库,需要创建相应的数据库迁移文件并应用到数据库中,以支持测试用例流程管理功能。
2025-01-19 - 根据 TestCaseFlowController 修复 testcaseService.ts
修改文件:
X1.WebUI/src/services/testcaseService.ts - 根据后端 TestCaseFlowController 重新编写前端服务
修改内容:
-
完全重构服务:
- 服务类名:从
TestCaseService改为TestCaseFlowService - 基础URL:从
/api/testcases改为/api/testcaseflow - API端点:完全匹配后端 TestCaseFlowController 的接口
- 服务类名:从
-
数据类型重新定义:
- TestFlowType:测试流程类型枚举
- TestCaseFlow:测试用例流程基础信息
- TestCaseNode:测试用例节点(支持 ReactFlow)
- TestCaseEdge:测试用例连线(支持 ReactFlow)
- TestCaseFlowDetail:测试用例流程详情(包含节点和连线)
-
API 方法对应:
- getTestCaseFlows:对应
GET /api/testcaseflow- 获取流程列表 - getTestCaseFlowById:对应
GET /api/testcaseflow/{id}- 获取流程详情 - createTestCaseFlow:对应
POST /api/testcaseflow- 创建流程 - deleteTestCaseFlow:对应
DELETE /api/testcaseflow/{id}- 删除流程
- getTestCaseFlows:对应
-
请求参数匹配:
- GetTestCaseFlowsRequest:支持 searchTerm、type、isEnabled、pageNumber、pageSize
- CreateTestCaseFlowRequest:支持 name、description、type、isEnabled、viewport、nodes、edges
- CreateNodeData:节点创建数据结构
- CreateEdgeData:连线创建数据结构
-
响应数据结构:
- GetTestCaseFlowsResponse:包含分页信息的流程列表
- GetTestCaseFlowByIdResponse:包含完整节点和连线数据的流程详情
- CreateTestCaseFlowResponse:创建成功后的流程信息
-
ReactFlow 兼容性:
- 节点结构:完全支持 ReactFlow 的节点数据结构
- 连线结构:完全支持 ReactFlow 的连线数据结构
- 位置信息:支持 position、positionAbsolute 等位置字段
- 样式信息:支持 style、data 等样式和数据字段
-
向后兼容性:
- 保留导出:保持
testcaseService导出,确保现有代码不破坏 - 新增导出:新增
testcaseFlowService导出,提供更明确的命名
- 保留导出:保持
修改时间:
2025-01-19
修改原因:
用户要求根据 TestCaseFlowController 修复 testcaseService.ts,确保前端服务与后端 API 完全匹配,支持测试用例流程的完整 CRUD 操作和 ReactFlow 集成。
2025-01-19 - 更新 API 路径常量以匹配后端控制器
修改文件:
X1.WebUI/src/constants/api.ts- 更新 API 路径常量X1.WebUI/src/services/testcaseService.ts- 使用 API 路径常量
修改内容:
-
API 路径常量更新:
- 移除:
TEST_CASES: '/test-cases'和TEST_STEPS: '/test-steps'(后端无对应控制器) - 新增:
TEST_CASE_FLOW: '/api/testcaseflow'(对应 TestCaseFlowController) - 更新:
CASE_STEP_CONFIGS: '/api/casestepconfigs'(对应 CaseStepConfigController)
- 移除:
-
testcaseService.ts 优化:
- 导入常量:添加
API_PATHS导入 - 使用常量:将硬编码的
/api/testcaseflow替换为API_PATHS.TEST_CASE_FLOW - 统一管理:所有 API 路径都通过常量统一管理
- 导入常量:添加
-
路径对应关系:
- TestCaseFlowController:
/api/testcaseflow→API_PATHS.TEST_CASE_FLOW - CaseStepConfigController:
/api/casestepconfigs→API_PATHS.CASE_STEP_CONFIGS
- TestCaseFlowController:
-
技术特性:
- 类型安全:使用 TypeScript 常量确保路径一致性
- 维护性:集中管理 API 路径,便于维护和修改
- 一致性:确保前端服务与后端控制器路径完全匹配
修改时间:
2025-01-19
修改原因:
用户询问是否需要根据 testcaseService 修复其他相关服务,发现 API 路径常量与实际后端控制器不匹配,需要统一更新以确保前后端一致性。
2025-01-19 - 修复 pages/testcases 页面使用 testcaseService
修改文件:
X1.WebUI/src/pages/testcases/TestCasesListView.tsx- 修复列表页面使用真实 APIX1.WebUI/src/pages/testcases/TestCasesView.tsx- 修复视图页面使用真实 APIX1.WebUI/src/pages/testcases/ReactFlowDesigner.tsx- 添加保存状态支持
修改内容:
-
TestCasesListView.tsx 重构:
- 移除模拟数据:删除
mockTestCases和本地接口定义 - 集成真实 API:使用
testcaseService.getTestCaseFlows()获取数据 - 添加加载状态:显示加载中状态,提升用户体验
- 实现搜索功能:支持按名称搜索测试用例流程
- 实现删除功能:使用
testcaseService.deleteTestCaseFlow()删除流程 - 更新数据展示:适配
TestCaseFlow接口的数据结构 - 修复状态显示:使用
isEnabled字段显示启用/停用状态 - 添加类型标签:显示测试流程类型(功能测试、性能测试等)
- 移除模拟数据:删除
-
TestCasesView.tsx 重构:
- 集成保存功能:使用
testcaseService.createTestCaseFlow()保存流程 - 数据格式转换:将 ReactFlow 节点和连线数据转换为后端格式
- 添加保存状态:显示保存中状态,防止重复提交
- 错误处理:完整的错误处理和用户提示
- 流程验证:检查流程完整性(开始节点、结束节点等)
- 集成保存功能:使用
-
ReactFlowDesigner.tsx 增强:
- 添加 saving 属性:支持保存状态传递
- 保存按钮状态:保存时禁用按钮并显示"保存中..."
- 用户体验优化:防止保存过程中的重复操作
-
数据结构适配:
- 节点数据转换:ReactFlow 节点 → 后端 CreateNodeData 格式
- 连线数据转换:ReactFlow 连线 → 后端 CreateEdgeData 格式
- 类型安全:使用 TypeScript 接口确保类型安全
-
功能特性:
- 实时搜索:支持按回车键搜索
- 批量操作:支持删除操作
- 导航功能:支持查看和编辑页面跳转
- 状态管理:完整的加载和保存状态管理
修改时间:
2025-01-19
修改原因:
用户发现 pages/testcases 页面没有调用 testcaseService,需要修复这些页面使其使用真实的 API 而不是模拟数据,确保前后端数据一致性。
2025-01-19 - TestCaseFlowController 添加 CreateTestCaseFlow 命令
修改文件:
X1.Presentation/Controllers/TestCaseFlowController.cs - 为TestCaseFlowController添加创建测试用例流程的POST方法
修改内容:
-
新增POST方法:
- 方法名:
CreateTestCaseFlow - 路由:
[HttpPost]- 对应/api/testcaseflow - 参数:
[FromBody] CreateTestCaseFlowCommand command - 返回:
IActionResult
- 方法名:
-
功能特性:
- 命令处理:使用
mediator.Send(command)发送创建命令 - 日志记录:详细的开始、成功、失败日志记录
- 错误处理:完整的错误处理和用户友好的错误信息
- 响应格式:使用
CreatedAtAction返回201状态码和资源位置
- 命令处理:使用
-
日志记录:
- 开始日志:记录流程名称和类型
- 成功日志:记录创建的ID、名称、节点数量、连线数量
- 失败日志:记录流程名称和详细错误信息
-
响应处理:
- 成功响应:返回201 Created状态码,包含新创建资源的URI
- 失败响应:返回400 Bad Request状态码,包含错误详情
- 资源定位:使用
CreatedAtAction提供新创建资源的访问路径
-
技术特性:
- 依赖注入:添加了
CreateTestCaseFlow命名空间的using语句 - MediatR集成:使用mediator发送命令,遵循CQRS模式
- RESTful设计:遵循REST API设计规范
- 统一响应:使用统一的OperationResult响应格式
- 依赖注入:添加了
-
API端点:
POST /api/testcaseflow Content-Type: application/json { "name": "测试流程名称", "description": "流程描述", "type": 1, "isEnabled": true, "viewportX": 40.5, "viewportY": 21.2, "viewportZoom": 1.1, "nodes": [...], "edges": [...] }
修改时间:
2025-01-19
修改原因:
用户要求为TestCaseFlowController添加TestCaseFlow.Commands功能,特别是创建测试用例流程的POST方法,以支持前端界面创建新的测试用例流程。
2025-01-19 - TestCaseNodeDto 和 TestCaseEdgeDto 完善
修改文件:
X1.Application/Features/TestCaseFlow/Queries/GetTestCaseFlowById/GetTestCaseFlowByIdResponse.cs - 完善 TestCaseNodeDto 和 TestCaseEdgeDto 结构
修改内容:
-
新增 DTO 类:
- TestCaseNodeDataDto:节点数据DTO,包含步骤ID、步骤名称、步骤类型、描述、图标等
- TestCaseNodePositionDto:节点位置DTO,包含X、Y坐标
- TestCaseEdgeStyleDto:连线样式DTO,包含描边颜色、描边宽度
- TestCaseEdgeDataDto:连线数据DTO,包含条件信息
-
TestCaseNodeDto 增强:
- 新增字段:
Type:节点类型(如 "testStep")Position:节点位置(TestCaseNodePositionDto)Data:节点数据(TestCaseNodeDataDto)Selected:是否被选中PositionAbsolute:绝对位置Dragging:是否正在拖拽
- 兼容性字段:保留原有字段,确保向后兼容
- 新增字段:
-
TestCaseEdgeDto 增强:
- 新增字段:
Source:源节点IDSourceHandle:源连接点Target:目标节点IDTargetHandle:目标连接点Type:连线类型Animated:是否动画Style:连线样式(TestCaseEdgeStyleDto)Data:连线数据(TestCaseEdgeDataDto)
- 兼容性字段:保留原有字段,确保向后兼容
- 新增字段:
-
技术特性:
- ReactFlow 兼容:新增字段与 ReactFlow 数据结构完全兼容
- JSON 序列化:支持直接序列化为 ReactFlow 所需的 JSON 格式
- 向后兼容:保留原有字段,确保现有代码不受影响
- 类型安全:使用强类型 DTO,避免运行时错误
-
数据结构示例:
{ "nodes": [ { "id": "node-1755654432101", "type": "testStep", "position": { "x": 360, "y": 30 }, "data": { "stepId": "e2192f5a-1582-47e9-92be-c676679418da", "stepName": "StartStep", "stepType": 1, "stepTypeName": "Start", "description": "Mapping_Start", "icon": "play-circle" }, "width": 95, "height": 30, "selected": false, "positionAbsolute": { "x": 360, "y": 30 }, "dragging": false } ], "edges": [ { "source": "node-1755654432101", "sourceHandle": "bottom", "target": "node-1755654436065", "targetHandle": "top", "id": "edge-1755654470705", "type": "smoothstep", "animated": false, "style": { "stroke": "#3b82f6", "strokeWidth": 2 }, "data": { "condition": "default" } } ] } -
设计原则:
- 前端兼容:确保与 ReactFlow 前端组件完全兼容
- 数据完整性:支持完整的节点和连线信息
- 扩展性:支持未来功能扩展
- 性能优化:避免不必要的数据转换
修改时间:
2025-01-19
修改原因:
用户需要 TestCaseNodeDto 和 TestCaseEdgeDto 与 ReactFlow 前端组件完全兼容,支持完整的节点和连线数据结构,包括位置、样式、数据等字段,确保前端能够正确显示和操作测试用例流程。
2025-01-19 - TestCaseFlow Queries功能实现
修改文件:
X1.Application/Features/TestCaseFlow/Queries/GetTestCaseFlows/- 获取TestCaseFlow列表查询X1.Application/Features/TestCaseFlow/Queries/GetTestCaseFlowById/- 根据ID获取TestCaseFlow详情查询X1.Presentation/Controllers/TestCaseFlowController.cs- TestCaseFlow控制器
修改内容:
-
GetTestCaseFlows查询功能:
- 查询类:
GetTestCaseFlowsQuery- 支持搜索、类型过滤、启用状态过滤、分页 - 响应类:
GetTestCaseFlowsResponse- 包含分页信息和TestCaseFlow列表 - 处理器:
GetTestCaseFlowsQueryHandler- 调用仓储获取分页数据并映射为DTO
- 查询类:
-
GetTestCaseFlowById查询功能:
- 查询类:
GetTestCaseFlowByIdQuery- 根据testCaseId获取详情 - 响应类:
GetTestCaseFlowByIdResponse- 包含完整的流程信息、节点和连线数据 - 处理器:
GetTestCaseFlowByIdQueryHandler- 组装TestCaseFlow、TestCaseNode、TestCaseEdge数据
- 查询类:
-
TestCaseFlowController控制器:
- 列表接口:
GET /api/testcaseflow- 获取测试用例流程列表,支持搜索和分页 - 详情接口:
GET /api/testcaseflow/{id}- 获取测试用例流程详情,包含节点和连线 - 完整日志:详细的日志记录和错误处理
- 列表接口:
-
数据组装特性:
- 列表查询:直接返回TestCaseFlow数据,不包含节点和连线
- 详情查询:组装完整的流程信息,包括所有节点和连线数据
- 性能优化:使用仓储的
GetTestCaseFlowWithDetailsAsync方法一次性获取所有数据
-
技术特性:
- CQRS模式:查询和命令分离,使用MediatR进行消息传递
- 分页支持:支持搜索、过滤、分页功能
- 数据完整性:详情查询包含完整的流程结构信息
- 错误处理:完整的异常处理和日志记录
修改时间:
2025-01-19
修改原因:
用户需要为TestCaseFlow实现Queries功能,包括获取列表和根据testCaseId获取详情,详情查询需要组装TestCaseNode和TestCaseEdge数据,为前端界面查看详情提供完整的数据支持。
2025-01-19 - TestCaseFlow 空引用警告修复和连线样式类型优化
修改文件:
X1.Application/Features/TestCaseFlow/Commands/CreateTestCaseFlow/CreateTestCaseFlowCommandHandler.cs- 修复空引用警告X1.Application/Features/TestCaseFlow/Commands/CreateTestCaseFlow/CreateTestCaseFlowCommand.cs- 优化连线样式类型
修改内容:
-
空引用警告修复:
- 问题:在
CreateTestCaseFlowCommandHandler中,ValidateUserAuthentication方法返回的OperationResult<string>可能为空 - 解决方案:使用空合并操作符
??确保传递给CreateFailure方法的参数不为空 - 修改代码:
return OperationResult<CreateTestCaseFlowResponse>.CreateFailure(errorMessages ?? new List<string>());
- 问题:在
-
连线样式类型优化:
- 问题:
Style属性被定义为object?类型,但在CreateEdgesAsync方法中使用edgeData.Style?.ToString()来转换 - 解决方案:将
Style属性明确为string?类型,符合 JSON 字符串格式的实际用途 - 修改代码:
- 问题:
-
连线类型必填验证:
- 在
EdgeData类中将Type属性设为必填:[Required(ErrorMessage = "连线类型不能为空")] - 在验证逻辑中添加对
Type的验证:if (string.IsNullOrWhiteSpace(edge.Type)) - 在创建连线时移除默认值逻辑:
edgeType: edgeData.Type(不再使用?? "straight")
- 在
-
验证器提取:
- 创建了
CreateTestCaseFlowCommandValidator验证器类 - 将
ValidateRequest方法从CreateTestCaseFlowCommandHandler中提取出来 - 使用静态方法
Validate进行验证,便于复用和测试 - 保持原有的验证逻辑和错误消息不变
- 创建了
-
设计原则:
- 单一职责:验证器专注于参数验证,处理器专注于业务逻辑
- 可复用性:验证器可以在其他地方复用
- 可测试性:独立的验证器更容易进行单元测试
- 代码组织:更好的代码结构和职责分离
修改时间:
2025-01-19
修改原因:
用户要求确保连线类型是必填项,界面不能传空值。同时要求将验证逻辑提取到单独的验证器类中,提高代码的可维护性和可测试性。
2025-01-19 - TestCaseFlowController 删除功能添加和接口返回类型统一
修改文件:
X1.Application/Features/TestCaseFlow/Commands/DeleteTestCaseFlow/DeleteTestCaseFlowCommand.cs- 新增删除命令X1.Application/Features/TestCaseFlow/Commands/DeleteTestCaseFlow/DeleteTestCaseFlowCommandHandler.cs- 新增删除命令处理器X1.Presentation/Controllers/TestCaseFlowController.cs- 添加删除端点和统一返回类型
修改内容:
-
删除命令实现:
- 创建了
DeleteTestCaseFlowCommand类,包含流程ID参数 - 创建了
DeleteTestCaseFlowCommandHandler处理器,实现删除逻辑 - 包含用户认证验证、流程存在性检查、删除操作和事务提交
- 创建了
-
控制器接口统一:
- 参考
TerminalServicesController的返回方式,将所有方法返回类型改为OperationResult<T> - 移除了
IActionResult和BadRequest/Ok等 HTTP 状态码处理 - 直接返回
OperationResult<T>对象,让框架自动处理 HTTP 状态码
- 参考
-
删除端点添加:
- 添加了
DELETE /api/testcaseflow/{id}端点 - 包含完整的日志记录和错误处理
- 返回删除操作的结果
- 添加了
-
技术特性:
- 一致性:与
TerminalServicesController保持相同的接口返回模式 - 简化:移除了手动的 HTTP 状态码处理,让框架自动处理
- 完整性:删除功能包含完整的业务逻辑验证和错误处理
- 一致性:与
API 端点示例:
DELETE /api/testcaseflow/{id}
Authorization: Bearer {token}
响应格式:
{
"isSuccess": true,
"data": true,
"errorMessages": null
}
修改时间:
2025-01-19
修改原因:
用户要求添加删除功能到 TestCaseFlowController,并参考 TerminalServicesController 的接口返回方式,统一使用 OperationResult<T> 返回类型,不使用 IActionResult。
2025-01-19 - TestCaseFlow Application层实现
修改文件:
X1.Application/Features/TestCaseFlow/Commands/CreateTestCaseFlow/CreateTestCaseFlowCommand.cs- 创建测试用例流程命令X1.Application/Features/TestCaseFlow/Commands/CreateTestCaseFlow/CreateTestCaseFlowResponse.cs- 创建测试用例流程响应X1.Application/Features/TestCaseFlow/Commands/CreateTestCaseFlow/CreateTestCaseFlowCommandHandler.cs- 创建测试用例流程命令处理器
修改内容:
-
CreateTestCaseFlowCommand 命令类:
- 实现了
IRequest<OperationResult<CreateTestCaseFlowResponse>>接口 - 包含完整的验证特性:
[Required]、[MaxLength]等 - 支持所有必要字段:名称、描述、类型、启用状态、视口坐标等
- 提供合理的默认值,如视口坐标和启用状态
- 实现了
-
CreateTestCaseFlowResponse 响应类:
- 包含完整的流程信息返回
- 支持类型枚举转换为字符串显示
- 包含审计信息:创建时间、创建人等
-
CreateTestCaseFlowCommandHandler 命令处理器:
- 遵循CQRS模式,使用MediatR框架
- 完整的参数验证和业务逻辑验证
- 用户认证验证
- 名称重复性检查
- 使用领域实体的Create工厂方法
- 完整的错误处理和日志记录
- 事务管理(通过UnitOfWork)
-
设计原则:
- 参考TerminalServices模式:完全按照TerminalServices的设计规则实现
- CQRS架构:命令和查询分离
- 领域驱动设计:使用领域实体的工厂方法
- 依赖注入:通过构造函数注入依赖
- 日志记录:完整的操作日志和错误日志
- 错误处理:统一的错误处理和响应格式
-
技术特性:
- 支持异步操作
- 完整的取消令牌支持
- 统一的OperationResult响应格式
- 详细的验证错误信息
- 事务性操作保证
修改时间:
2025-01-19
修改原因:
用户要求在X1.Application.Features中实现TestCaseFlow的功能,参考TerminalServices的设计规则,先完成创建功能。为测试用例流程管理提供完整的Application层支持,包括命令、响应和处理器实现。
修复记录:
- 编译错误修复:修复了
TestCaseFlow.Create方法调用时的命名空间解析问题,使用完全限定的类型名称X1.Domain.Entities.TestCase.TestCaseFlow.Create来解决编译器无法找到Create方法的问题。
2025-01-19 - TestCaseFlow 空引用警告修复和连线样式类型优化
- 命令扩展:在
CreateTestCaseFlowCommand中添加了NodeData和EdgeDataDTO类,支持节点和连线数据的传输 - 处理器增强:在
CreateTestCaseFlowCommandHandler中添加了ITestCaseNodeRepository和ITestCaseEdgeRepository依赖注入 - 节点创建:实现了
CreateNodesAsync方法,支持批量创建测试用例节点,包括位置、尺寸、状态等属性 - 连线创建:实现了
CreateEdgesAsync方法,支持批量创建测试用例连线,包括源节点、目标节点、类型、样式等属性 - 验证增强:添加了对节点和连线数据的验证逻辑,确保数据完整性
- 日志记录:增强了日志记录,包含节点数量和连线数量的统计信息
- 事务管理:确保节点和连线的创建在同一个事务中完成,保证数据一致性
2024-12-19 - StartDeviceRuntimeCommandHandler 问题分析与修复
问题描述
API响应中 isSuccess: true 但 summary.failureCount: 1,导致前端误判操作成功。
问题分析
通过分析代码发现以下潜在问题区域:
- 网络配置构建阶段:在
BuildNetworkConfigurationRequests方法中,设备可能因为配置验证失败而被过滤掉 - 网络启动阶段:在
StartNetworksInParallelAsync方法中,网络启动失败 - 设备运行时处理阶段:设备运行时不存在或更新失败
实施的修复
-
增强日志记录:
- 在
BuildNetworkConfigurationRequests中添加详细的警告日志 - 在
StartNetworksInParallelAsync中增强错误日志和统计信息 - 在设备运行时处理循环中添加调试日志
- 在
-
关键修复 - isSuccess 字段逻辑:
- 问题根源:
OperationResult<T>.IsSuccess属性仅基于ErrorMessages是否为空 - 解决方案:在
Handle方法中根据业务逻辑判断成功/失败 - 只有当所有设备都成功启动时才返回
CreateSuccess - 否则返回
CreateFailure并包含详细错误信息
- 问题根源:
-
配置验证逻辑优化:
- 问题:原来的配置验证过于严格,要求同时有RAN配置和完整的IMS+核心网配置
- 优化:改为更灵活的验证逻辑,允许只有RAN配置或只有IMS配置的设备通过
- 验证规则:
- 至少需要RAN配置 或者 IMS配置(不要求同时有核心网配置)
- 如果有IMS配置但没有核心网配置,记录警告但不阻止设备启动
- 提供更详细的配置状态日志,便于调试
- 影响:减少因配置不完整而被错误跳过的设备数量
修改原因
- 解决前端误判问题
- 提供更好的调试信息
- 确保数据一致性
2024-12-19 - 已实施更改的评估分析
评估结果:所有更改都应该保留
1. 网络配置构建阶段优化 ✅
- 状态: 已优化,无需撤回
- 改进内容:
- 增强的日志记录,记录被跳过设备的具体原因
- 过滤逻辑透明化,包括重复组合、缺少配置、验证失败等情况
- 统计信息记录,显示原始请求数 vs 有效请求数
- 价值: 提供更好的调试信息和透明度
2. 网络启动阶段优化 ✅
- 状态: 已优化,无需撤回
- 改进内容:
- 增强的错误日志,包含具体错误信息
- 统计信息记录,显示总请求数、成功数、失败数
- 失败设备详细记录
- 价值: 提供关键的调试信息,帮助快速定位网络启动失败原因
3. 设备运行时处理阶段优化 ✅
- 状态: 已优化,无需撤回
- 改进内容:
- 跳过逻辑:只处理网络启动成功的设备
- 详细日志:记录状态更新过程
- 调试信息:记录设备运行时当前状态
- 价值: 确保数据一致性,避免对失败设备的无效处理
4. isSuccess 字段逻辑修复 ✅
- 状态: 已修复,这是核心问题
- 问题:
isSuccess: true但failureCount: 1导致前端误判 - 解决方案: 根据业务逻辑判断成功/失败
- 价值: 解决了前端误判的根本问题
建议的监控指标
修改记录
2025-01-21 - 创建 TestCaseFlow 相关表的数据库迁移
修改文件:
X1.Infrastructure/Migrations/20250821080604_AddTestCaseFlowTables.cs- 新建迁移文件X1.Infrastructure/Migrations/20250821080604_AddTestCaseFlowTables.Designer.cs- 迁移设计器文件X1.Infrastructure/Migrations/AppDbContextModelSnapshot.cs- 更新模型快照
修改内容:
-
迁移文件创建:
- 迁移名称:
AddTestCaseFlowTables - 迁移时间:2025-08-21 08:06:04
- 迁移描述:为 TestCaseFlow、TestCaseNode、TestCaseEdge 实体创建数据库表
- 迁移名称:
-
创建的表结构:
-
tb_testcaseflow:测试用例流程主表
- 包含 id、name、description、type、isenabled、viewport_x、viewport_y、viewport_zoom 等字段
- 包含审计字段:createdat、updatedat、createdby、updatedby
- 创建索引:name、type、isenabled
-
tb_testcasenode:测试用例节点表
- 包含 id、testcaseid、nodeid、sequencenumber、stepid、positionx、positiony、width、height 等字段
- 包含状态字段:isselected、positionabsolutex、positionabsolutey、isdragging
- 外键关系:testcaseid → tb_testcaseflow.id (CASCADE)
- 外键关系:stepid → tb_casestepconfig.id (SET NULL)
- 创建索引:testcaseid、nodeid、sequencenumber、stepid
-
tb_testcaseedge:测试用例连线表
- 包含 id、testcaseid、edgeid、sourcenodeid、targetnodeid、edgetype、condition、isanimated、style 等字段
- 外键关系:testcaseid → tb_testcaseflow.id (CASCADE)
- 创建索引:testcaseid、edgeid、sourcenodeid、targetnodeid
-
-
数据库关系:
- 级联删除:删除测试用例流程时,自动删除相关的节点和连线
- 可选关联:节点可以关联步骤配置,删除步骤配置时节点 stepid 设为 NULL
- 完整性约束:确保数据的一致性和完整性
-
迁移应用状态:
- 已成功应用:迁移已应用到数据库
- 表已创建:三个表都已成功创建在数据库中
- 索引已建立:所有必要的索引都已创建完成
-
技术特性:
- PostgreSQL 兼容:使用 PostgreSQL 特定的数据类型和语法
- 性能优化:为常用查询字段创建索引
- 数据完整性:通过外键约束确保数据一致性
- 审计支持:包含完整的审计字段支持
修改时间:
2025-01-21
修改原因:
用户反映 TestCaseFlows、TestCaseNodes、TestCaseEdges 新建后还没有迁移数据库,需要创建相应的数据库迁移文件并应用到数据库中,以支持测试用例流程管理功能。
2025-01-19 - 根据 TestCaseFlowController 修复 testcaseService.ts
修改文件:
X1.WebUI/src/services/testcaseService.ts - 根据后端 TestCaseFlowController 重新编写前端服务
修改内容:
-
完全重构服务:
- 服务类名:从
TestCaseService改为TestCaseFlowService - 基础URL:从
/api/testcases改为/api/testcaseflow - API端点:完全匹配后端 TestCaseFlowController 的接口
- 服务类名:从
-
数据类型重新定义:
- TestFlowType:测试流程类型枚举
- TestCaseFlow:测试用例流程基础信息
- TestCaseNode:测试用例节点(支持 ReactFlow)
- TestCaseEdge:测试用例连线(支持 ReactFlow)
- TestCaseFlowDetail:测试用例流程详情(包含节点和连线)
-
API 方法对应:
- getTestCaseFlows:对应
GET /api/testcaseflow- 获取流程列表 - getTestCaseFlowById:对应
GET /api/testcaseflow/{id}- 获取流程详情 - createTestCaseFlow:对应
POST /api/testcaseflow- 创建流程 - deleteTestCaseFlow:对应
DELETE /api/testcaseflow/{id}- 删除流程
- getTestCaseFlows:对应
-
请求参数匹配:
- GetTestCaseFlowsRequest:支持 searchTerm、type、isEnabled、pageNumber、pageSize
- CreateTestCaseFlowRequest:支持 name、description、type、isEnabled、viewport、nodes、edges
- CreateNodeData:节点创建数据结构
- CreateEdgeData:连线创建数据结构
-
响应数据结构:
- GetTestCaseFlowsResponse:包含分页信息的流程列表
- GetTestCaseFlowByIdResponse:包含完整节点和连线数据的流程详情
- CreateTestCaseFlowResponse:创建成功后的流程信息
-
ReactFlow 兼容性:
- 节点结构:完全支持 ReactFlow 的节点数据结构
- 连线结构:完全支持 ReactFlow 的连线数据结构
- 位置信息:支持 position、positionAbsolute 等位置字段
- 样式信息:支持 style、data 等样式和数据字段
-
向后兼容性:
- 保留导出:保持
testcaseService导出,确保现有代码不破坏 - 新增导出:新增
testcaseFlowService导出,提供更明确的命名
- 保留导出:保持
修改时间:
2025-01-19
修改原因:
用户要求根据 TestCaseFlowController 修复 testcaseService.ts,确保前端服务与后端 API 完全匹配,支持测试用例流程的完整 CRUD 操作和 ReactFlow 集成。
2025-01-19 - 更新 API 路径常量以匹配后端控制器
修改文件:
X1.WebUI/src/constants/api.ts- 更新 API 路径常量X1.WebUI/src/services/testcaseService.ts- 使用 API 路径常量
修改内容:
-
API 路径常量更新:
- 移除:
TEST_CASES: '/test-cases'和TEST_STEPS: '/test-steps'(后端无对应控制器) - 新增:
TEST_CASE_FLOW: '/api/testcaseflow'(对应 TestCaseFlowController) - 更新:
CASE_STEP_CONFIGS: '/api/casestepconfigs'(对应 CaseStepConfigController)
- 移除:
-
testcaseService.ts 优化:
- 导入常量:添加
API_PATHS导入 - 使用常量:将硬编码的
/api/testcaseflow替换为API_PATHS.TEST_CASE_FLOW - 统一管理:所有 API 路径都通过常量统一管理
- 导入常量:添加
-
路径对应关系:
- TestCaseFlowController:
/api/testcaseflow→API_PATHS.TEST_CASE_FLOW - CaseStepConfigController:
/api/casestepconfigs→API_PATHS.CASE_STEP_CONFIGS
- TestCaseFlowController:
-
技术特性:
- 类型安全:使用 TypeScript 常量确保路径一致性
- 维护性:集中管理 API 路径,便于维护和修改
- 一致性:确保前端服务与后端控制器路径完全匹配
修改时间:
2025-01-19
修改原因:
用户询问是否需要根据 testcaseService 修复其他相关服务,发现 API 路径常量与实际后端控制器不匹配,需要统一更新以确保前后端一致性。
2025-01-19 - 修复 pages/testcases 页面使用 testcaseService
修改文件:
X1.WebUI/src/pages/testcases/TestCasesListView.tsx- 修复列表页面使用真实 APIX1.WebUI/src/pages/testcases/TestCasesView.tsx- 修复视图页面使用真实 APIX1.WebUI/src/pages/testcases/ReactFlowDesigner.tsx- 添加保存状态支持
修改内容:
-
TestCasesListView.tsx 重构:
- 移除模拟数据:删除
mockTestCases和本地接口定义 - 集成真实 API:使用
testcaseService.getTestCaseFlows()获取数据 - 添加加载状态:显示加载中状态,提升用户体验
- 实现搜索功能:支持按名称搜索测试用例流程
- 实现删除功能:使用
testcaseService.deleteTestCaseFlow()删除流程 - 更新数据展示:适配
TestCaseFlow接口的数据结构 - 修复状态显示:使用
isEnabled字段显示启用/停用状态 - 添加类型标签:显示测试流程类型(功能测试、性能测试等)
- 移除模拟数据:删除
-
TestCasesView.tsx 重构:
- 集成保存功能:使用
testcaseService.createTestCaseFlow()保存流程 - 数据格式转换:将 ReactFlow 节点和连线数据转换为后端格式
- 添加保存状态:显示保存中状态,防止重复提交
- 错误处理:完整的错误处理和用户提示
- 流程验证:检查流程完整性(开始节点、结束节点等)
- 集成保存功能:使用
-
ReactFlowDesigner.tsx 增强:
- 添加 saving 属性:支持保存状态传递
- 保存按钮状态:保存时禁用按钮并显示"保存中..."
- 用户体验优化:防止保存过程中的重复操作
-
数据结构适配:
- 节点数据转换:ReactFlow 节点 → 后端 CreateNodeData 格式
- 连线数据转换:ReactFlow 连线 → 后端 CreateEdgeData 格式
- 类型安全:使用 TypeScript 接口确保类型安全
-
功能特性:
- 实时搜索:支持按回车键搜索
- 批量操作:支持删除操作
- 导航功能:支持查看和编辑页面跳转
- 状态管理:完整的加载和保存状态管理
修改时间:
2025-01-19
修改原因:
用户发现 pages/testcases 页面没有调用 testcaseService,需要修复这些页面使其使用真实的 API 而不是模拟数据,确保前后端数据一致性。
2025-01-19 - TestCaseFlowController 添加 CreateTestCaseFlow 命令
修改文件:
X1.Presentation/Controllers/TestCaseFlowController.cs - 为TestCaseFlowController添加创建测试用例流程的POST方法
修改内容:
-
新增POST方法:
- 方法名:
CreateTestCaseFlow - 路由:
[HttpPost]- 对应/api/testcaseflow - 参数:
[FromBody] CreateTestCaseFlowCommand command - 返回:
IActionResult
- 方法名:
-
功能特性:
- 命令处理:使用
mediator.Send(command)发送创建命令 - 日志记录:详细的开始、成功、失败日志记录
- 错误处理:完整的错误处理和用户友好的错误信息
- 响应格式:使用
CreatedAtAction返回201状态码和资源位置
- 命令处理:使用
-
日志记录:
- 开始日志:记录流程名称和类型
- 成功日志:记录创建的ID、名称、节点数量、连线数量
- 失败日志:记录流程名称和详细错误信息
-
响应处理:
- 成功响应:返回201 Created状态码,包含新创建资源的URI
- 失败响应:返回400 Bad Request状态码,包含错误详情
- 资源定位:使用
CreatedAtAction提供新创建资源的访问路径
-
技术特性:
- 依赖注入:添加了
CreateTestCaseFlow命名空间的using语句 - MediatR集成:使用mediator发送命令,遵循CQRS模式
- RESTful设计:遵循REST API设计规范
- 统一响应:使用统一的OperationResult响应格式
- 依赖注入:添加了
-
API端点:
POST /api/testcaseflow Content-Type: application/json { "name": "测试流程名称", "description": "流程描述", "type": 1, "isEnabled": true, "viewportX": 40.5, "viewportY": 21.2, "viewportZoom": 1.1, "nodes": [...], "edges": [...] }
修改时间:
2025-01-19
修改原因:
用户要求为TestCaseFlowController添加TestCaseFlow.Commands功能,特别是创建测试用例流程的POST方法,以支持前端界面创建新的测试用例流程。
2025-01-19 - TestCaseNodeDto 和 TestCaseEdgeDto 完善
修改文件:
X1.Application/Features/TestCaseFlow/Queries/GetTestCaseFlowById/GetTestCaseFlowByIdResponse.cs - 完善 TestCaseNodeDto 和 TestCaseEdgeDto 结构
修改内容:
-
新增 DTO 类:
- TestCaseNodeDataDto:节点数据DTO,包含步骤ID、步骤名称、步骤类型、描述、图标等
- TestCaseNodePositionDto:节点位置DTO,包含X、Y坐标
- TestCaseEdgeStyleDto:连线样式DTO,包含描边颜色、描边宽度
- TestCaseEdgeDataDto:连线数据DTO,包含条件信息
-
TestCaseNodeDto 增强:
- 新增字段:
Type:节点类型(如 "testStep")Position:节点位置(TestCaseNodePositionDto)Data:节点数据(TestCaseNodeDataDto)Selected:是否被选中PositionAbsolute:绝对位置Dragging:是否正在拖拽
- 兼容性字段:保留原有字段,确保向后兼容
- 新增字段:
-
TestCaseEdgeDto 增强:
- 新增字段:
Source:源节点IDSourceHandle:源连接点Target:目标节点IDTargetHandle:目标连接点Type:连线类型Animated:是否动画Style:连线样式(TestCaseEdgeStyleDto)Data:连线数据(TestCaseEdgeDataDto)
- 兼容性字段:保留原有字段,确保向后兼容
- 新增字段:
-
技术特性:
- ReactFlow 兼容:新增字段与 ReactFlow 数据结构完全兼容
- JSON 序列化:支持直接序列化为 ReactFlow 所需的 JSON 格式
- 向后兼容:保留原有字段,确保现有代码不受影响
- 类型安全:使用强类型 DTO,避免运行时错误
-
数据结构示例:
{ "nodes": [ { "id": "node-1755654432101", "type": "testStep", "position": { "x": 360, "y": 30 }, "data": { "stepId": "e2192f5a-1582-47e9-92be-c676679418da", "stepName": "StartStep", "stepType": 1, "stepTypeName": "Start", "description": "Mapping_Start", "icon": "play-circle" }, "width": 95, "height": 30, "selected": false, "positionAbsolute": { "x": 360, "y": 30 }, "dragging": false } ], "edges": [ { "source": "node-1755654432101", "sourceHandle": "bottom", "target": "node-1755654436065", "targetHandle": "top", "id": "edge-1755654470705", "type": "smoothstep", "animated": false, "style": { "stroke": "#3b82f6", "strokeWidth": 2 }, "data": { "condition": "default" } } ] } -
设计原则:
- 前端兼容:确保与 ReactFlow 前端组件完全兼容
- 数据完整性:支持完整的节点和连线信息
- 扩展性:支持未来功能扩展
- 性能优化:避免不必要的数据转换
修改时间:
2025-01-19
修改原因:
用户需要 TestCaseNodeDto 和 TestCaseEdgeDto 与 ReactFlow 前端组件完全兼容,支持完整的节点和连线数据结构,包括位置、样式、数据等字段,确保前端能够正确显示和操作测试用例流程。
2025-01-19 - TestCaseFlow Queries功能实现
修改文件:
X1.Application/Features/TestCaseFlow/Queries/GetTestCaseFlows/- 获取TestCaseFlow列表查询X1.Application/Features/TestCaseFlow/Queries/GetTestCaseFlowById/- 根据ID获取TestCaseFlow详情查询X1.Presentation/Controllers/TestCaseFlowController.cs- TestCaseFlow控制器
修改内容:
-
GetTestCaseFlows查询功能:
- 查询类:
GetTestCaseFlowsQuery- 支持搜索、类型过滤、启用状态过滤、分页 - 响应类:
GetTestCaseFlowsResponse- 包含分页信息和TestCaseFlow列表 - 处理器:
GetTestCaseFlowsQueryHandler- 调用仓储获取分页数据并映射为DTO
- 查询类:
-
GetTestCaseFlowById查询功能:
- 查询类:
GetTestCaseFlowByIdQuery- 根据testCaseId获取详情 - 响应类:
GetTestCaseFlowByIdResponse- 包含完整的流程信息、节点和连线数据 - 处理器:
GetTestCaseFlowByIdQueryHandler- 组装TestCaseFlow、TestCaseNode、TestCaseEdge数据
- 查询类:
-
TestCaseFlowController控制器:
- 列表接口:
GET /api/testcaseflow- 获取测试用例流程列表,支持搜索和分页 - 详情接口:
GET /api/testcaseflow/{id}- 获取测试用例流程详情,包含节点和连线 - 完整日志:详细的日志记录和错误处理
- 列表接口:
-
数据组装特性:
- 列表查询:直接返回TestCaseFlow数据,不包含节点和连线
- 详情查询:组装完整的流程信息,包括所有节点和连线数据
- 性能优化:使用仓储的
GetTestCaseFlowWithDetailsAsync方法一次性获取所有数据
-
技术特性:
- CQRS模式:查询和命令分离,使用MediatR进行消息传递
- 分页支持:支持搜索、过滤、分页功能
- 数据完整性:详情查询包含完整的流程结构信息
- 错误处理:完整的异常处理和日志记录
修改时间:
2025-01-19
修改原因:
用户需要为TestCaseFlow实现Queries功能,包括获取列表和根据testCaseId获取详情,详情查询需要组装TestCaseNode和TestCaseEdge数据,为前端界面查看详情提供完整的数据支持。
2025-01-19 - TestCaseFlow 空引用警告修复和连线样式类型优化
修改文件:
X1.Application/Features/TestCaseFlow/Commands/CreateTestCaseFlow/CreateTestCaseFlowCommandHandler.cs- 修复空引用警告X1.Application/Features/TestCaseFlow/Commands/CreateTestCaseFlow/CreateTestCaseFlowCommand.cs- 优化连线样式类型
修改内容:
-
空引用警告修复:
- 问题:在
CreateTestCaseFlowCommandHandler中,ValidateUserAuthentication方法返回的OperationResult<string>可能为空 - 解决方案:使用空合并操作符
??确保传递给CreateFailure方法的参数不为空 - 修改代码:
return OperationResult<CreateTestCaseFlowResponse>.CreateFailure(errorMessages ?? new List<string>());
- 问题:在
-
连线样式类型优化:
- 问题:
Style属性被定义为object?类型,但在CreateEdgesAsync方法中使用edgeData.Style?.ToString()来转换 - 解决方案:将
Style属性明确为string?类型,符合 JSON 字符串格式的实际用途 - 修改代码:
- 问题:
-
连线类型必填验证:
- 在
EdgeData类中将Type属性设为必填:[Required(ErrorMessage = "连线类型不能为空")] - 在验证逻辑中添加对
Type的验证:if (string.IsNullOrWhiteSpace(edge.Type)) - 在创建连线时移除默认值逻辑:
edgeType: edgeData.Type(不再使用?? "straight")
- 在
-
验证器提取:
- 创建了
CreateTestCaseFlowCommandValidator验证器类 - 将
ValidateRequest方法从CreateTestCaseFlowCommandHandler中提取出来 - 使用静态方法
Validate进行验证,便于复用和测试 - 保持原有的验证逻辑和错误消息不变
- 创建了
-
设计原则:
- 单一职责:验证器专注于参数验证,处理器专注于业务逻辑
- 可复用性:验证器可以在其他地方复用
- 可测试性:独立的验证器更容易进行单元测试
- 代码组织:更好的代码结构和职责分离
修改时间:
2025-01-19
修改原因:
用户要求确保连线类型是必填项,界面不能传空值。同时要求将验证逻辑提取到单独的验证器类中,提高代码的可维护性和可测试性。
2025-01-19 - TestCaseFlowController 删除功能添加和接口返回类型统一
修改文件:
X1.Application/Features/TestCaseFlow/Commands/DeleteTestCaseFlow/DeleteTestCaseFlowCommand.cs- 新增删除命令X1.Application/Features/TestCaseFlow/Commands/DeleteTestCaseFlow/DeleteTestCaseFlowCommandHandler.cs- 新增删除命令处理器X1.Presentation/Controllers/TestCaseFlowController.cs- 添加删除端点和统一返回类型
修改内容:
-
删除命令实现:
- 创建了
DeleteTestCaseFlowCommand类,包含流程ID参数 - 创建了
DeleteTestCaseFlowCommandHandler处理器,实现删除逻辑 - 包含用户认证验证、流程存在性检查、删除操作和事务提交
- 创建了
-
控制器接口统一:
- 参考
TerminalServicesController的返回方式,将所有方法返回类型改为OperationResult<T> - 移除了
IActionResult和BadRequest/Ok等 HTTP 状态码处理 - 直接返回
OperationResult<T>对象,让框架自动处理 HTTP 状态码
- 参考
-
删除端点添加:
- 添加了
DELETE /api/testcaseflow/{id}端点 - 包含完整的日志记录和错误处理
- 返回删除操作的结果
- 添加了
-
技术特性:
- 一致性:与
TerminalServicesController保持相同的接口返回模式 - 简化:移除了手动的 HTTP 状态码处理,让框架自动处理
- 完整性:删除功能包含完整的业务逻辑验证和错误处理
- 一致性:与
API 端点示例:
DELETE /api/testcaseflow/{id}
Authorization: Bearer {token}
响应格式:
{
"isSuccess": true,
"data": true,
"errorMessages": null
}
修改时间:
2025-01-19
修改原因:
用户要求添加删除功能到 TestCaseFlowController,并参考 TerminalServicesController 的接口返回方式,统一使用 OperationResult<T> 返回类型,不使用 IActionResult。
2025-01-19 - TestCaseFlow Application层实现
修改文件:
X1.Application/Features/TestCaseFlow/Commands/CreateTestCaseFlow/CreateTestCaseFlowCommand.cs- 创建测试用例流程命令X1.Application/Features/TestCaseFlow/Commands/CreateTestCaseFlow/CreateTestCaseFlowResponse.cs- 创建测试用例流程响应X1.Application/Features/TestCaseFlow/Commands/CreateTestCaseFlow/CreateTestCaseFlowCommandHandler.cs- 创建测试用例流程命令处理器
修改内容:
-
CreateTestCaseFlowCommand 命令类:
- 实现了
IRequest<OperationResult<CreateTestCaseFlowResponse>>接口 - 包含完整的验证特性:
[Required]、[MaxLength]等 - 支持所有必要字段:名称、描述、类型、启用状态、视口坐标等
- 提供合理的默认值,如视口坐标和启用状态
- 实现了
-
CreateTestCaseFlowResponse 响应类:
- 包含完整的流程信息返回
- 支持类型枚举转换为字符串显示
- 包含审计信息:创建时间、创建人等
-
CreateTestCaseFlowCommandHandler 命令处理器:
- 遵循CQRS模式,使用MediatR框架
- 完整的参数验证和业务逻辑验证
- 用户认证验证
- 名称重复性检查
- 使用领域实体的Create工厂方法
- 完整的错误处理和日志记录
- 事务管理(通过UnitOfWork)
-
设计原则:
- 参考TerminalServices模式:完全按照TerminalServices的设计规则实现
- CQRS架构:命令和查询分离
- 领域驱动设计:使用领域实体的工厂方法
- 依赖注入:通过构造函数注入依赖
- 日志记录:完整的操作日志和错误日志
- 错误处理:统一的错误处理和响应格式
-
技术特性:
- 支持异步操作
- 完整的取消令牌支持
- 统一的OperationResult响应格式
- 详细的验证错误信息
- 事务性操作保证
修改时间:
2025-01-19
修改原因:
用户要求在X1.Application.Features中实现TestCaseFlow的功能,参考TerminalServices的设计规则,先完成创建功能。为测试用例流程管理提供完整的Application层支持,包括命令、响应和处理器实现。
修复记录:
- 编译错误修复:修复了
TestCaseFlow.Create方法调用时的命名空间解析问题,使用完全限定的类型名称X1.Domain.Entities.TestCase.TestCaseFlow.Create来解决编译器无法找到Create方法的问题。
2025-01-19 - TestCaseFlow 空引用警告修复和连线样式类型优化
- 命令扩展:在
CreateTestCaseFlowCommand中添加了NodeData和EdgeDataDTO类,支持节点和连线数据的传输 - 处理器增强:在
CreateTestCaseFlowCommandHandler中添加了ITestCaseNodeRepository和ITestCaseEdgeRepository依赖注入 - 节点创建:实现了
CreateNodesAsync方法,支持批量创建测试用例节点,包括位置、尺寸、状态等属性 - 连线创建:实现了
CreateEdgesAsync方法,支持批量创建测试用例连线,包括源节点、目标节点、类型、样式等属性 - 验证增强:添加了对节点和连线数据的验证逻辑,确保数据完整性
- 日志记录:增强了日志记录,包含节点数量和连线数量的统计信息
- 事务管理:确保节点和连线的创建在同一个事务中完成,保证数据一致性
2024-12-19 - StartDeviceRuntimeCommandHandler 问题分析与修复
问题描述
API响应中 isSuccess: true 但 summary.failureCount: 1,导致前端误判操作成功。
问题分析
通过分析代码发现以下潜在问题区域:
- 网络配置构建阶段:在
BuildNetworkConfigurationRequests方法中,设备可能因为配置验证失败而被过滤掉 - 网络启动阶段:在
StartNetworksInParallelAsync方法中,网络启动失败 - 设备运行时处理阶段:设备运行时不存在或更新失败
实施的修复
-
增强日志记录:
- 在
BuildNetworkConfigurationRequests中添加详细的警告日志 - 在
StartNetworksInParallelAsync中增强错误日志和统计信息 - 在设备运行时处理循环中添加调试日志
- 在
-
关键修复 - isSuccess 字段逻辑:
- 问题根源:
OperationResult<T>.IsSuccess属性仅基于ErrorMessages是否为空 - 解决方案:在
Handle方法中根据业务逻辑判断成功/失败 - 只有当所有设备都成功启动时才返回
CreateSuccess - 否则返回
CreateFailure并包含详细错误信息
- 问题根源:
-
配置验证逻辑优化:
- 问题:原来的配置验证过于严格,要求同时有RAN配置和完整的IMS+核心网配置
- 优化:改为更灵活的验证逻辑,允许只有RAN配置或只有IMS配置的设备通过
- 验证规则:
- 至少需要RAN配置 或者 IMS配置(不要求同时有核心网配置)
- 如果有IMS配置但没有核心网配置,记录警告但不阻止设备启动
- 提供更详细的配置状态日志,便于调试
- 影响:减少因配置不完整而被错误跳过的设备数量
修改原因
- 解决前端误判问题
- 提供更好的调试信息
- 确保数据一致性
2024-12-19 - 已实施更改的评估分析
评估结果:所有更改都应该保留
1. 网络配置构建阶段优化 ✅
- 状态: 已优化,无需撤回
- 改进内容:
- 增强的日志记录,记录被跳过设备的具体原因
- 过滤逻辑透明化,包括重复组合、缺少配置、验证失败等情况
- 统计信息记录,显示原始请求数 vs 有效请求数
- 价值: 提供更好的调试信息和透明度
2. 网络启动阶段优化 ✅
- 状态: 已优化,无需撤回
- 改进内容:
- 增强的错误日志,包含具体错误信息
- 统计信息记录,显示总请求数、成功数、失败数
- 失败设备详细记录
- 价值: 提供关键的调试信息,帮助快速定位网络启动失败原因
3. 设备运行时处理阶段优化 ✅
- 状态: 已优化,无需撤回
- 改进内容:
- 跳过逻辑:只处理网络启动成功的设备
- 详细日志:记录状态更新过程
- 调试信息:记录设备运行时当前状态
- 价值: 确保数据一致性,避免对失败设备的无效处理
4. isSuccess 字段逻辑修复 ✅
- 状态: 已修复,这是核心问题
- 问题:
isSuccess: true但failureCount: 1导致前端误判 - 解决方案: 根据业务逻辑判断成功/失败
- 价值: 解决了前端误判的根本问题
建议的监控指标
- 网络配置构建成功率:
有效请求数 / 原始请求数 - 网络启动成功率:
成功设备数 / 有效请求数 - 整体成功率:
成功设备数 / 总请求数
日志分析建议
修改记录
2025-01-21 - 创建 TestCaseFlow 相关表的数据库迁移
修改文件:
X1.Infrastructure/Migrations/20250821080604_AddTestCaseFlowTables.cs- 新建迁移文件X1.Infrastructure/Migrations/20250821080604_AddTestCaseFlowTables.Designer.cs- 迁移设计器文件X1.Infrastructure/Migrations/AppDbContextModelSnapshot.cs- 更新模型快照
修改内容:
-
迁移文件创建:
- 迁移名称:
AddTestCaseFlowTables - 迁移时间:2025-08-21 08:06:04
- 迁移描述:为 TestCaseFlow、TestCaseNode、TestCaseEdge 实体创建数据库表
- 迁移名称:
-
创建的表结构:
-
tb_testcaseflow:测试用例流程主表
- 包含 id、name、description、type、isenabled、viewport_x、viewport_y、viewport_zoom 等字段
- 包含审计字段:createdat、updatedat、createdby、updatedby
- 创建索引:name、type、isenabled
-
tb_testcasenode:测试用例节点表
- 包含 id、testcaseid、nodeid、sequencenumber、stepid、positionx、positiony、width、height 等字段
- 包含状态字段:isselected、positionabsolutex、positionabsolutey、isdragging
- 外键关系:testcaseid → tb_testcaseflow.id (CASCADE)
- 外键关系:stepid → tb_casestepconfig.id (SET NULL)
- 创建索引:testcaseid、nodeid、sequencenumber、stepid
-
tb_testcaseedge:测试用例连线表
- 包含 id、testcaseid、edgeid、sourcenodeid、targetnodeid、edgetype、condition、isanimated、style 等字段
- 外键关系:testcaseid → tb_testcaseflow.id (CASCADE)
- 创建索引:testcaseid、edgeid、sourcenodeid、targetnodeid
-
-
数据库关系:
- 级联删除:删除测试用例流程时,自动删除相关的节点和连线
- 可选关联:节点可以关联步骤配置,删除步骤配置时节点 stepid 设为 NULL
- 完整性约束:确保数据的一致性和完整性
-
迁移应用状态:
- 已成功应用:迁移已应用到数据库
- 表已创建:三个表都已成功创建在数据库中
- 索引已建立:所有必要的索引都已创建完成
-
技术特性:
- PostgreSQL 兼容:使用 PostgreSQL 特定的数据类型和语法
- 性能优化:为常用查询字段创建索引
- 数据完整性:通过外键约束确保数据一致性
- 审计支持:包含完整的审计字段支持
修改时间:
2025-01-21
修改原因:
用户反映 TestCaseFlows、TestCaseNodes、TestCaseEdges 新建后还没有迁移数据库,需要创建相应的数据库迁移文件并应用到数据库中,以支持测试用例流程管理功能。
2025-01-19 - 根据 TestCaseFlowController 修复 testcaseService.ts
修改文件:
X1.WebUI/src/services/testcaseService.ts - 根据后端 TestCaseFlowController 重新编写前端服务
修改内容:
-
完全重构服务:
- 服务类名:从
TestCaseService改为TestCaseFlowService - 基础URL:从
/api/testcases改为/api/testcaseflow - API端点:完全匹配后端 TestCaseFlowController 的接口
- 服务类名:从
-
数据类型重新定义:
- TestFlowType:测试流程类型枚举
- TestCaseFlow:测试用例流程基础信息
- TestCaseNode:测试用例节点(支持 ReactFlow)
- TestCaseEdge:测试用例连线(支持 ReactFlow)
- TestCaseFlowDetail:测试用例流程详情(包含节点和连线)
-
API 方法对应:
- getTestCaseFlows:对应
GET /api/testcaseflow- 获取流程列表 - getTestCaseFlowById:对应
GET /api/testcaseflow/{id}- 获取流程详情 - createTestCaseFlow:对应
POST /api/testcaseflow- 创建流程 - deleteTestCaseFlow:对应
DELETE /api/testcaseflow/{id}- 删除流程
- getTestCaseFlows:对应
-
请求参数匹配:
- GetTestCaseFlowsRequest:支持 searchTerm、type、isEnabled、pageNumber、pageSize
- CreateTestCaseFlowRequest:支持 name、description、type、isEnabled、viewport、nodes、edges
- CreateNodeData:节点创建数据结构
- CreateEdgeData:连线创建数据结构
-
响应数据结构:
- GetTestCaseFlowsResponse:包含分页信息的流程列表
- GetTestCaseFlowByIdResponse:包含完整节点和连线数据的流程详情
- CreateTestCaseFlowResponse:创建成功后的流程信息
-
ReactFlow 兼容性:
- 节点结构:完全支持 ReactFlow 的节点数据结构
- 连线结构:完全支持 ReactFlow 的连线数据结构
- 位置信息:支持 position、positionAbsolute 等位置字段
- 样式信息:支持 style、data 等样式和数据字段
-
向后兼容性:
- 保留导出:保持
testcaseService导出,确保现有代码不破坏 - 新增导出:新增
testcaseFlowService导出,提供更明确的命名
- 保留导出:保持
修改时间:
2025-01-19
修改原因:
用户要求根据 TestCaseFlowController 修复 testcaseService.ts,确保前端服务与后端 API 完全匹配,支持测试用例流程的完整 CRUD 操作和 ReactFlow 集成。
2025-01-19 - 更新 API 路径常量以匹配后端控制器
修改文件:
X1.WebUI/src/constants/api.ts- 更新 API 路径常量X1.WebUI/src/services/testcaseService.ts- 使用 API 路径常量
修改内容:
-
API 路径常量更新:
- 移除:
TEST_CASES: '/test-cases'和TEST_STEPS: '/test-steps'(后端无对应控制器) - 新增:
TEST_CASE_FLOW: '/api/testcaseflow'(对应 TestCaseFlowController) - 更新:
CASE_STEP_CONFIGS: '/api/casestepconfigs'(对应 CaseStepConfigController)
- 移除:
-
testcaseService.ts 优化:
- 导入常量:添加
API_PATHS导入 - 使用常量:将硬编码的
/api/testcaseflow替换为API_PATHS.TEST_CASE_FLOW - 统一管理:所有 API 路径都通过常量统一管理
- 导入常量:添加
-
路径对应关系:
- TestCaseFlowController:
/api/testcaseflow→API_PATHS.TEST_CASE_FLOW - CaseStepConfigController:
/api/casestepconfigs→API_PATHS.CASE_STEP_CONFIGS
- TestCaseFlowController:
-
技术特性:
- 类型安全:使用 TypeScript 常量确保路径一致性
- 维护性:集中管理 API 路径,便于维护和修改
- 一致性:确保前端服务与后端控制器路径完全匹配
修改时间:
2025-01-19
修改原因:
用户询问是否需要根据 testcaseService 修复其他相关服务,发现 API 路径常量与实际后端控制器不匹配,需要统一更新以确保前后端一致性。
2025-01-19 - 修复 pages/testcases 页面使用 testcaseService
修改文件:
X1.WebUI/src/pages/testcases/TestCasesListView.tsx- 修复列表页面使用真实 APIX1.WebUI/src/pages/testcases/TestCasesView.tsx- 修复视图页面使用真实 APIX1.WebUI/src/pages/testcases/ReactFlowDesigner.tsx- 添加保存状态支持
修改内容:
-
TestCasesListView.tsx 重构:
- 移除模拟数据:删除
mockTestCases和本地接口定义 - 集成真实 API:使用
testcaseService.getTestCaseFlows()获取数据 - 添加加载状态:显示加载中状态,提升用户体验
- 实现搜索功能:支持按名称搜索测试用例流程
- 实现删除功能:使用
testcaseService.deleteTestCaseFlow()删除流程 - 更新数据展示:适配
TestCaseFlow接口的数据结构 - 修复状态显示:使用
isEnabled字段显示启用/停用状态 - 添加类型标签:显示测试流程类型(功能测试、性能测试等)
- 移除模拟数据:删除
-
TestCasesView.tsx 重构:
- 集成保存功能:使用
testcaseService.createTestCaseFlow()保存流程 - 数据格式转换:将 ReactFlow 节点和连线数据转换为后端格式
- 添加保存状态:显示保存中状态,防止重复提交
- 错误处理:完整的错误处理和用户提示
- 流程验证:检查流程完整性(开始节点、结束节点等)
- 集成保存功能:使用
-
ReactFlowDesigner.tsx 增强:
- 添加 saving 属性:支持保存状态传递
- 保存按钮状态:保存时禁用按钮并显示"保存中..."
- 用户体验优化:防止保存过程中的重复操作
-
数据结构适配:
- 节点数据转换:ReactFlow 节点 → 后端 CreateNodeData 格式
- 连线数据转换:ReactFlow 连线 → 后端 CreateEdgeData 格式
- 类型安全:使用 TypeScript 接口确保类型安全
-
功能特性:
- 实时搜索:支持按回车键搜索
- 批量操作:支持删除操作
- 导航功能:支持查看和编辑页面跳转
- 状态管理:完整的加载和保存状态管理
修改时间:
2025-01-19
修改原因:
用户发现 pages/testcases 页面没有调用 testcaseService,需要修复这些页面使其使用真实的 API 而不是模拟数据,确保前后端数据一致性。
2025-01-19 - TestCaseFlowController 添加 CreateTestCaseFlow 命令
修改文件:
X1.Presentation/Controllers/TestCaseFlowController.cs - 为TestCaseFlowController添加创建测试用例流程的POST方法
修改内容:
-
新增POST方法:
- 方法名:
CreateTestCaseFlow - 路由:
[HttpPost]- 对应/api/testcaseflow - 参数:
[FromBody] CreateTestCaseFlowCommand command - 返回:
IActionResult
- 方法名:
-
功能特性:
- 命令处理:使用
mediator.Send(command)发送创建命令 - 日志记录:详细的开始、成功、失败日志记录
- 错误处理:完整的错误处理和用户友好的错误信息
- 响应格式:使用
CreatedAtAction返回201状态码和资源位置
- 命令处理:使用
-
日志记录:
- 开始日志:记录流程名称和类型
- 成功日志:记录创建的ID、名称、节点数量、连线数量
- 失败日志:记录流程名称和详细错误信息
-
响应处理:
- 成功响应:返回201 Created状态码,包含新创建资源的URI
- 失败响应:返回400 Bad Request状态码,包含错误详情
- 资源定位:使用
CreatedAtAction提供新创建资源的访问路径
-
技术特性:
- 依赖注入:添加了
CreateTestCaseFlow命名空间的using语句 - MediatR集成:使用mediator发送命令,遵循CQRS模式
- RESTful设计:遵循REST API设计规范
- 统一响应:使用统一的OperationResult响应格式
- 依赖注入:添加了
-
API端点:
POST /api/testcaseflow Content-Type: application/json { "name": "测试流程名称", "description": "流程描述", "type": 1, "isEnabled": true, "viewportX": 40.5, "viewportY": 21.2, "viewportZoom": 1.1, "nodes": [...], "edges": [...] }
修改时间:
2025-01-19
修改原因:
用户要求为TestCaseFlowController添加TestCaseFlow.Commands功能,特别是创建测试用例流程的POST方法,以支持前端界面创建新的测试用例流程。
2025-01-19 - TestCaseNodeDto 和 TestCaseEdgeDto 完善
修改文件:
X1.Application/Features/TestCaseFlow/Queries/GetTestCaseFlowById/GetTestCaseFlowByIdResponse.cs - 完善 TestCaseNodeDto 和 TestCaseEdgeDto 结构
修改内容:
-
新增 DTO 类:
- TestCaseNodeDataDto:节点数据DTO,包含步骤ID、步骤名称、步骤类型、描述、图标等
- TestCaseNodePositionDto:节点位置DTO,包含X、Y坐标
- TestCaseEdgeStyleDto:连线样式DTO,包含描边颜色、描边宽度
- TestCaseEdgeDataDto:连线数据DTO,包含条件信息
-
TestCaseNodeDto 增强:
- 新增字段:
Type:节点类型(如 "testStep")Position:节点位置(TestCaseNodePositionDto)Data:节点数据(TestCaseNodeDataDto)Selected:是否被选中PositionAbsolute:绝对位置Dragging:是否正在拖拽
- 兼容性字段:保留原有字段,确保向后兼容
- 新增字段:
-
TestCaseEdgeDto 增强:
- 新增字段:
Source:源节点IDSourceHandle:源连接点Target:目标节点IDTargetHandle:目标连接点Type:连线类型Animated:是否动画Style:连线样式(TestCaseEdgeStyleDto)Data:连线数据(TestCaseEdgeDataDto)
- 兼容性字段:保留原有字段,确保向后兼容
- 新增字段:
-
技术特性:
- ReactFlow 兼容:新增字段与 ReactFlow 数据结构完全兼容
- JSON 序列化:支持直接序列化为 ReactFlow 所需的 JSON 格式
- 向后兼容:保留原有字段,确保现有代码不受影响
- 类型安全:使用强类型 DTO,避免运行时错误
-
数据结构示例:
{ "nodes": [ { "id": "node-1755654432101", "type": "testStep", "position": { "x": 360, "y": 30 }, "data": { "stepId": "e2192f5a-1582-47e9-92be-c676679418da", "stepName": "StartStep", "stepType": 1, "stepTypeName": "Start", "description": "Mapping_Start", "icon": "play-circle" }, "width": 95, "height": 30, "selected": false, "positionAbsolute": { "x": 360, "y": 30 }, "dragging": false } ], "edges": [ { "source": "node-1755654432101", "sourceHandle": "bottom", "target": "node-1755654436065", "targetHandle": "top", "id": "edge-1755654470705", "type": "smoothstep", "animated": false, "style": { "stroke": "#3b82f6", "strokeWidth": 2 }, "data": { "condition": "default" } } ] } -
设计原则:
- 前端兼容:确保与 ReactFlow 前端组件完全兼容
- 数据完整性:支持完整的节点和连线信息
- 扩展性:支持未来功能扩展
- 性能优化:避免不必要的数据转换
修改时间:
2025-01-19
修改原因:
用户需要 TestCaseNodeDto 和 TestCaseEdgeDto 与 ReactFlow 前端组件完全兼容,支持完整的节点和连线数据结构,包括位置、样式、数据等字段,确保前端能够正确显示和操作测试用例流程。
2025-01-19 - TestCaseFlow Queries功能实现
修改文件:
X1.Application/Features/TestCaseFlow/Queries/GetTestCaseFlows/- 获取TestCaseFlow列表查询X1.Application/Features/TestCaseFlow/Queries/GetTestCaseFlowById/- 根据ID获取TestCaseFlow详情查询X1.Presentation/Controllers/TestCaseFlowController.cs- TestCaseFlow控制器
修改内容:
-
GetTestCaseFlows查询功能:
- 查询类:
GetTestCaseFlowsQuery- 支持搜索、类型过滤、启用状态过滤、分页 - 响应类:
GetTestCaseFlowsResponse- 包含分页信息和TestCaseFlow列表 - 处理器:
GetTestCaseFlowsQueryHandler- 调用仓储获取分页数据并映射为DTO
- 查询类:
-
GetTestCaseFlowById查询功能:
- 查询类:
GetTestCaseFlowByIdQuery- 根据testCaseId获取详情 - 响应类:
GetTestCaseFlowByIdResponse- 包含完整的流程信息、节点和连线数据 - 处理器:
GetTestCaseFlowByIdQueryHandler- 组装TestCaseFlow、TestCaseNode、TestCaseEdge数据
- 查询类:
-
TestCaseFlowController控制器:
- 列表接口:
GET /api/testcaseflow- 获取测试用例流程列表,支持搜索和分页 - 详情接口:
GET /api/testcaseflow/{id}- 获取测试用例流程详情,包含节点和连线 - 完整日志:详细的日志记录和错误处理
- 列表接口:
-
数据组装特性:
- 列表查询:直接返回TestCaseFlow数据,不包含节点和连线
- 详情查询:组装完整的流程信息,包括所有节点和连线数据
- 性能优化:使用仓储的
GetTestCaseFlowWithDetailsAsync方法一次性获取所有数据
-
技术特性:
- CQRS模式:查询和命令分离,使用MediatR进行消息传递
- 分页支持:支持搜索、过滤、分页功能
- 数据完整性:详情查询包含完整的流程结构信息
- 错误处理:完整的异常处理和日志记录
修改时间:
2025-01-19
修改原因:
用户需要为TestCaseFlow实现Queries功能,包括获取列表和根据testCaseId获取详情,详情查询需要组装TestCaseNode和TestCaseEdge数据,为前端界面查看详情提供完整的数据支持。
2025-01-19 - TestCaseFlow 空引用警告修复和连线样式类型优化
修改文件:
X1.Application/Features/TestCaseFlow/Commands/CreateTestCaseFlow/CreateTestCaseFlowCommandHandler.cs- 修复空引用警告X1.Application/Features/TestCaseFlow/Commands/CreateTestCaseFlow/CreateTestCaseFlowCommand.cs- 优化连线样式类型
修改内容:
-
空引用警告修复:
- 问题:在
CreateTestCaseFlowCommandHandler中,ValidateUserAuthentication方法返回的OperationResult<string>可能为空 - 解决方案:使用空合并操作符
??确保传递给CreateFailure方法的参数不为空 - 修改代码:
return OperationResult<CreateTestCaseFlowResponse>.CreateFailure(errorMessages ?? new List<string>());
- 问题:在
-
连线样式类型优化:
- 问题:
Style属性被定义为object?类型,但在CreateEdgesAsync方法中使用edgeData.Style?.ToString()来转换 - 解决方案:将
Style属性明确为string?类型,符合 JSON 字符串格式的实际用途 - 修改代码:
- 问题:
-
连线类型必填验证:
- 在
EdgeData类中将Type属性设为必填:[Required(ErrorMessage = "连线类型不能为空")] - 在验证逻辑中添加对
Type的验证:if (string.IsNullOrWhiteSpace(edge.Type)) - 在创建连线时移除默认值逻辑:
edgeType: edgeData.Type(不再使用?? "straight")
- 在
-
验证器提取:
- 创建了
CreateTestCaseFlowCommandValidator验证器类 - 将
ValidateRequest方法从CreateTestCaseFlowCommandHandler中提取出来 - 使用静态方法
Validate进行验证,便于复用和测试 - 保持原有的验证逻辑和错误消息不变
- 创建了
-
设计原则:
- 单一职责:验证器专注于参数验证,处理器专注于业务逻辑
- 可复用性:验证器可以在其他地方复用
- 可测试性:独立的验证器更容易进行单元测试
- 代码组织:更好的代码结构和职责分离
修改时间:
2025-01-19
修改原因:
用户要求确保连线类型是必填项,界面不能传空值。同时要求将验证逻辑提取到单独的验证器类中,提高代码的可维护性和可测试性。
2025-01-19 - TestCaseFlowController 删除功能添加和接口返回类型统一
修改文件:
X1.Application/Features/TestCaseFlow/Commands/DeleteTestCaseFlow/DeleteTestCaseFlowCommand.cs- 新增删除命令X1.Application/Features/TestCaseFlow/Commands/DeleteTestCaseFlow/DeleteTestCaseFlowCommandHandler.cs- 新增删除命令处理器X1.Presentation/Controllers/TestCaseFlowController.cs- 添加删除端点和统一返回类型
修改内容:
-
删除命令实现:
- 创建了
DeleteTestCaseFlowCommand类,包含流程ID参数 - 创建了
DeleteTestCaseFlowCommandHandler处理器,实现删除逻辑 - 包含用户认证验证、流程存在性检查、删除操作和事务提交
- 创建了
-
控制器接口统一:
- 参考
TerminalServicesController的返回方式,将所有方法返回类型改为OperationResult<T> - 移除了
IActionResult和BadRequest/Ok等 HTTP 状态码处理 - 直接返回
OperationResult<T>对象,让框架自动处理 HTTP 状态码
- 参考
-
删除端点添加:
- 添加了
DELETE /api/testcaseflow/{id}端点 - 包含完整的日志记录和错误处理
- 返回删除操作的结果
- 添加了
-
技术特性:
- 一致性:与
TerminalServicesController保持相同的接口返回模式 - 简化:移除了手动的 HTTP 状态码处理,让框架自动处理
- 完整性:删除功能包含完整的业务逻辑验证和错误处理
- 一致性:与
API 端点示例:
DELETE /api/testcaseflow/{id}
Authorization: Bearer {token}
响应格式:
{
"isSuccess": true,
"data": true,
"errorMessages": null
}
修改时间:
2025-01-19
修改原因:
用户要求添加删除功能到 TestCaseFlowController,并参考 TerminalServicesController 的接口返回方式,统一使用 OperationResult<T> 返回类型,不使用 IActionResult。
2025-01-19 - TestCaseFlow Application层实现
修改文件:
X1.Application/Features/TestCaseFlow/Commands/CreateTestCaseFlow/CreateTestCaseFlowCommand.cs- 创建测试用例流程命令X1.Application/Features/TestCaseFlow/Commands/CreateTestCaseFlow/CreateTestCaseFlowResponse.cs- 创建测试用例流程响应X1.Application/Features/TestCaseFlow/Commands/CreateTestCaseFlow/CreateTestCaseFlowCommandHandler.cs- 创建测试用例流程命令处理器
修改内容:
-
CreateTestCaseFlowCommand 命令类:
- 实现了
IRequest<OperationResult<CreateTestCaseFlowResponse>>接口 - 包含完整的验证特性:
[Required]、[MaxLength]等 - 支持所有必要字段:名称、描述、类型、启用状态、视口坐标等
- 提供合理的默认值,如视口坐标和启用状态
- 实现了
-
CreateTestCaseFlowResponse 响应类:
- 包含完整的流程信息返回
- 支持类型枚举转换为字符串显示
- 包含审计信息:创建时间、创建人等
-
CreateTestCaseFlowCommandHandler 命令处理器:
- 遵循CQRS模式,使用MediatR框架
- 完整的参数验证和业务逻辑验证
- 用户认证验证
- 名称重复性检查
- 使用领域实体的Create工厂方法
- 完整的错误处理和日志记录
- 事务管理(通过UnitOfWork)
-
设计原则:
- 参考TerminalServices模式:完全按照TerminalServices的设计规则实现
- CQRS架构:命令和查询分离
- 领域驱动设计:使用领域实体的工厂方法
- 依赖注入:通过构造函数注入依赖
- 日志记录:完整的操作日志和错误日志
- 错误处理:统一的错误处理和响应格式
-
技术特性:
- 支持异步操作
- 完整的取消令牌支持
- 统一的OperationResult响应格式
- 详细的验证错误信息
- 事务性操作保证
修改时间:
2025-01-19
修改原因:
用户要求在X1.Application.Features中实现TestCaseFlow的功能,参考TerminalServices的设计规则,先完成创建功能。为测试用例流程管理提供完整的Application层支持,包括命令、响应和处理器实现。
修复记录:
- 编译错误修复:修复了
TestCaseFlow.Create方法调用时的命名空间解析问题,使用完全限定的类型名称X1.Domain.Entities.TestCase.TestCaseFlow.Create来解决编译器无法找到Create方法的问题。
2025-01-19 - TestCaseFlow 空引用警告修复和连线样式类型优化
- 命令扩展:在
CreateTestCaseFlowCommand中添加了NodeData和EdgeDataDTO类,支持节点和连线数据的传输 - 处理器增强:在
CreateTestCaseFlowCommandHandler中添加了ITestCaseNodeRepository和ITestCaseEdgeRepository依赖注入 - 节点创建:实现了
CreateNodesAsync方法,支持批量创建测试用例节点,包括位置、尺寸、状态等属性 - 连线创建:实现了
CreateEdgesAsync方法,支持批量创建测试用例连线,包括源节点、目标节点、类型、样式等属性 - 验证增强:添加了对节点和连线数据的验证逻辑,确保数据完整性
- 日志记录:增强了日志记录,包含节点数量和连线数量的统计信息
- 事务管理:确保节点和连线的创建在同一个事务中完成,保证数据一致性
2024-12-19 - StartDeviceRuntimeCommandHandler 问题分析与修复
问题描述
API响应中 isSuccess: true 但 summary.failureCount: 1,导致前端误判操作成功。
问题分析
通过分析代码发现以下潜在问题区域:
- 网络配置构建阶段:在
BuildNetworkConfigurationRequests方法中,设备可能因为配置验证失败而被过滤掉 - 网络启动阶段:在
StartNetworksInParallelAsync方法中,网络启动失败 - 设备运行时处理阶段:设备运行时不存在或更新失败
实施的修复
-
增强日志记录:
- 在
BuildNetworkConfigurationRequests中添加详细的警告日志 - 在
StartNetworksInParallelAsync中增强错误日志和统计信息 - 在设备运行时处理循环中添加调试日志
- 在
-
关键修复 - isSuccess 字段逻辑:
- 问题根源:
OperationResult<T>.IsSuccess属性仅基于ErrorMessages是否为空 - 解决方案:在
Handle方法中根据业务逻辑判断成功/失败 - 只有当所有设备都成功启动时才返回
CreateSuccess - 否则返回
CreateFailure并包含详细错误信息
- 问题根源:
-
配置验证逻辑优化:
- 问题:原来的配置验证过于严格,要求同时有RAN配置和完整的IMS+核心网配置
- 优化:改为更灵活的验证逻辑,允许只有RAN配置或只有IMS配置的设备通过
- 验证规则:
- 至少需要RAN配置 或者 IMS配置(不要求同时有核心网配置)
- 如果有IMS配置但没有核心网配置,记录警告但不阻止设备启动
- 提供更详细的配置状态日志,便于调试
- 影响:减少因配置不完整而被错误跳过的设备数量
修改原因
- 解决前端误判问题
- 提供更好的调试信息
- 确保数据一致性
2024-12-19 - 已实施更改的评估分析
评估结果:所有更改都应该保留
1. 网络配置构建阶段优化 ✅
- 状态: 已优化,无需撤回
- 改进内容:
- 增强的日志记录,记录被跳过设备的具体原因
- 过滤逻辑透明化,包括重复组合、缺少配置、验证失败等情况
- 统计信息记录,显示原始请求数 vs 有效请求数
- 价值: 提供更好的调试信息和透明度
2. 网络启动阶段优化 ✅
- 状态: 已优化,无需撤回
- 改进内容:
- 增强的错误日志,包含具体错误信息
- 统计信息记录,显示总请求数、成功数、失败数
- 失败设备详细记录
- 价值: 提供关键的调试信息,帮助快速定位网络启动失败原因
3. 设备运行时处理阶段优化 ✅
- 状态: 已优化,无需撤回
- 改进内容:
- 跳过逻辑:只处理网络启动成功的设备
- 详细日志:记录状态更新过程
- 调试信息:记录设备运行时当前状态
- 价值: 确保数据一致性,避免对失败设备的无效处理
4. isSuccess 字段逻辑修复 ✅
- 状态: 已修复,这是核心问题
- 问题:
isSuccess: true但failureCount: 1导致前端误判 - 解决方案: 根据业务逻辑判断成功/失败
- 价值: 解决了前端误判的根本问题
建议的监控指标
- 网络配置构建成功率:
有效请求数 / 原始请求数 - 网络启动成功率:
成功设备数 / 有效请求数 - 整体成功率:
成功设备数 / 总请求数
日志分析建议
当出现失败时,可通过以下日志快速定位问题:
- 网络配置构建阶段:查看被跳过设备的原因
- 网络启动阶段:查看具体错误信息
- 设备运行时处理:查看状态更新过程
结论
2025-01-21 - ReactFlowDesigner节点类型调试
问题描述
在ReactFlowDesigner.tsx中,用户发现所有节点的type都是'testStep',无法区分不同类型的节点。虽然代码中有根据stepType确定节点类型的逻辑,但实际创建的节点类型没有正确设置。
修改内容
1. ReactFlowDesigner.tsx
- 文件位置:
X1.WebUI/src/pages/testcases/ReactFlowDesigner.tsx - 修改内容:
- 在节点创建逻辑中添加了调试日志,输出stepType、nodeType和newNode信息
- 在TestStepNode组件中添加了调试日志,输出stepType、stepTypeName、stepName和nodeStyle信息
- 确保getNodeType函数正确根据stepType返回对应的节点类型
修改前后对比
修改前
const newNode = {
id: `node-${Date.now()}`,
type: getNodeType(step.stepType),
position,
data: {
stepId: step.id,
stepName: step.stepName,
stepType: step.stepType,
stepTypeName: step.stepTypeName,
description: step.description,
icon: step.icon,
},
};
修改后
const newNode = {
id: `node-${Date.now()}`,
type: getNodeType(step.stepType),
position,
data: {
stepId: step.id,
stepName: step.stepName,
stepType: step.stepType,
stepTypeName: step.stepTypeName,
description: step.description,
icon: step.icon,
},
};
console.log('创建新节点:', {
stepType: step.stepType,
nodeType: getNodeType(step.stepType),
newNode: newNode
});
影响范围
- 添加了调试信息,帮助诊断节点类型设置问题
- 确保节点类型能够正确根据stepType进行区分
- 保持了原有的节点渲染逻辑不变
测试建议
- 测试不同类型节点的创建,观察控制台输出的调试信息
- 验证节点类型是否正确设置
- 确认节点显示和交互功能正常
修改记录
2025-01-21 - 创建 TestCaseFlow 相关表的数据库迁移
修改文件:
X1.Infrastructure/Migrations/20250821080604_AddTestCaseFlowTables.cs- 新建迁移文件X1.Infrastructure/Migrations/20250821080604_AddTestCaseFlowTables.Designer.cs- 迁移设计器文件X1.Infrastructure/Migrations/AppDbContextModelSnapshot.cs- 更新模型快照
修改内容:
-
迁移文件创建:
- 迁移名称:
AddTestCaseFlowTables - 迁移时间:2025-08-21 08:06:04
- 迁移描述:为 TestCaseFlow、TestCaseNode、TestCaseEdge 实体创建数据库表
- 迁移名称:
-
创建的表结构:
-
tb_testcaseflow:测试用例流程主表
- 包含 id、name、description、type、isenabled、viewport_x、viewport_y、viewport_zoom 等字段
- 包含审计字段:createdat、updatedat、createdby、updatedby
- 创建索引:name、type、isenabled
-
tb_testcasenode:测试用例节点表
- 包含 id、testcaseid、nodeid、sequencenumber、stepid、positionx、positiony、width、height 等字段
- 包含状态字段:isselected、positionabsolutex、positionabsolutey、isdragging
- 外键关系:testcaseid → tb_testcaseflow.id (CASCADE)
- 外键关系:stepid → tb_casestepconfig.id (SET NULL)
- 创建索引:testcaseid、nodeid、sequencenumber、stepid
-
tb_testcaseedge:测试用例连线表
- 包含 id、testcaseid、edgeid、sourcenodeid、targetnodeid、edgetype、condition、isanimated、style 等字段
- 外键关系:testcaseid → tb_testcaseflow.id (CASCADE)
- 创建索引:testcaseid、edgeid、sourcenodeid、targetnodeid
-
-
数据库关系:
- 级联删除:删除测试用例流程时,自动删除相关的节点和连线
- 可选关联:节点可以关联步骤配置,删除步骤配置时节点 stepid 设为 NULL
- 完整性约束:确保数据的一致性和完整性
-
迁移应用状态:
- 已成功应用:迁移已应用到数据库
- 表已创建:三个表都已成功创建在数据库中
- 索引已建立:所有必要的索引都已创建完成
-
技术特性:
- PostgreSQL 兼容:使用 PostgreSQL 特定的数据类型和语法
- 性能优化:为常用查询字段创建索引
- 数据完整性:通过外键约束确保数据一致性
- 审计支持:包含完整的审计字段支持
修改时间:
2025-01-21
修改原因:
用户反映 TestCaseFlows、TestCaseNodes、TestCaseEdges 新建后还没有迁移数据库,需要创建相应的数据库迁移文件并应用到数据库中,以支持测试用例流程管理功能。
2025-01-19 - 根据 TestCaseFlowController 修复 testcaseService.ts
修改文件:
X1.WebUI/src/services/testcaseService.ts - 根据后端 TestCaseFlowController 重新编写前端服务
修改内容:
-
完全重构服务:
- 服务类名:从
TestCaseService改为TestCaseFlowService - 基础URL:从
/api/testcases改为/api/testcaseflow - API端点:完全匹配后端 TestCaseFlowController 的接口
- 服务类名:从
-
数据类型重新定义:
- TestFlowType:测试流程类型枚举
- TestCaseFlow:测试用例流程基础信息
- TestCaseNode:测试用例节点(支持 ReactFlow)
- TestCaseEdge:测试用例连线(支持 ReactFlow)
- TestCaseFlowDetail:测试用例流程详情(包含节点和连线)
-
API 方法对应:
- getTestCaseFlows:对应
GET /api/testcaseflow- 获取流程列表 - getTestCaseFlowById:对应
GET /api/testcaseflow/{id}- 获取流程详情 - createTestCaseFlow:对应
POST /api/testcaseflow- 创建流程 - deleteTestCaseFlow:对应
DELETE /api/testcaseflow/{id}- 删除流程
- getTestCaseFlows:对应
-
请求参数匹配:
- GetTestCaseFlowsRequest:支持 searchTerm、type、isEnabled、pageNumber、pageSize
- CreateTestCaseFlowRequest:支持 name、description、type、isEnabled、viewport、nodes、edges
- CreateNodeData:节点创建数据结构
- CreateEdgeData:连线创建数据结构
-
响应数据结构:
- GetTestCaseFlowsResponse:包含分页信息的流程列表
- GetTestCaseFlowByIdResponse:包含完整节点和连线数据的流程详情
- CreateTestCaseFlowResponse:创建成功后的流程信息
-
ReactFlow 兼容性:
- 节点结构:完全支持 ReactFlow 的节点数据结构
- 连线结构:完全支持 ReactFlow 的连线数据结构
- 位置信息:支持 position、positionAbsolute 等位置字段
- 样式信息:支持 style、data 等样式和数据字段
-
向后兼容性:
- 保留导出:保持
testcaseService导出,确保现有代码不破坏 - 新增导出:新增
testcaseFlowService导出,提供更明确的命名
- 保留导出:保持
修改时间:
2025-01-19
修改原因:
用户要求根据 TestCaseFlowController 修复 testcaseService.ts,确保前端服务与后端 API 完全匹配,支持测试用例流程的完整 CRUD 操作和 ReactFlow 集成。
2025-01-19 - 更新 API 路径常量以匹配后端控制器
修改文件:
X1.WebUI/src/constants/api.ts- 更新 API 路径常量X1.WebUI/src/services/testcaseService.ts- 使用 API 路径常量
修改内容:
-
API 路径常量更新:
- 移除:
TEST_CASES: '/test-cases'和TEST_STEPS: '/test-steps'(后端无对应控制器) - 新增:
TEST_CASE_FLOW: '/api/testcaseflow'(对应 TestCaseFlowController) - 更新:
CASE_STEP_CONFIGS: '/api/casestepconfigs'(对应 CaseStepConfigController)
- 移除:
-
testcaseService.ts 优化:
- 导入常量:添加
API_PATHS导入 - 使用常量:将硬编码的
/api/testcaseflow替换为API_PATHS.TEST_CASE_FLOW - 统一管理:所有 API 路径都通过常量统一管理
- 导入常量:添加
-
路径对应关系:
- TestCaseFlowController:
/api/testcaseflow→API_PATHS.TEST_CASE_FLOW - CaseStepConfigController:
/api/casestepconfigs→API_PATHS.CASE_STEP_CONFIGS
- TestCaseFlowController:
-
技术特性:
- 类型安全:使用 TypeScript 常量确保路径一致性
- 维护性:集中管理 API 路径,便于维护和修改
- 一致性:确保前端服务与后端控制器路径完全匹配
修改时间:
2025-01-19
修改原因:
用户询问是否需要根据 testcaseService 修复其他相关服务,发现 API 路径常量与实际后端控制器不匹配,需要统一更新以确保前后端一致性。
2025-01-19 - 修复 pages/testcases 页面使用 testcaseService
修改文件:
X1.WebUI/src/pages/testcases/TestCasesListView.tsx- 修复列表页面使用真实 APIX1.WebUI/src/pages/testcases/TestCasesView.tsx- 修复视图页面使用真实 APIX1.WebUI/src/pages/testcases/ReactFlowDesigner.tsx- 添加保存状态支持
修改内容:
-
TestCasesListView.tsx 重构:
- 移除模拟数据:删除
mockTestCases和本地接口定义 - 集成真实 API:使用
testcaseService.getTestCaseFlows()获取数据 - 添加加载状态:显示加载中状态,提升用户体验
- 实现搜索功能:支持按名称搜索测试用例流程
- 实现删除功能:使用
testcaseService.deleteTestCaseFlow()删除流程 - 更新数据展示:适配
TestCaseFlow接口的数据结构 - 修复状态显示:使用
isEnabled字段显示启用/停用状态 - 添加类型标签:显示测试流程类型(功能测试、性能测试等)
- 移除模拟数据:删除
-
TestCasesView.tsx 重构:
- 集成保存功能:使用
testcaseService.createTestCaseFlow()保存流程 - 数据格式转换:将 ReactFlow 节点和连线数据转换为后端格式
- 添加保存状态:显示保存中状态,防止重复提交
- 错误处理:完整的错误处理和用户提示
- 流程验证:检查流程完整性(开始节点、结束节点等)
- 集成保存功能:使用
-
ReactFlowDesigner.tsx 增强:
- 添加 saving 属性:支持保存状态传递
- 保存按钮状态:保存时禁用按钮并显示"保存中..."
- 用户体验优化:防止保存过程中的重复操作
-
数据结构适配:
- 节点数据转换:ReactFlow 节点 → 后端 CreateNodeData 格式
- 连线数据转换:ReactFlow 连线 → 后端 CreateEdgeData 格式
- 类型安全:使用 TypeScript 接口确保类型安全
-
功能特性:
- 实时搜索:支持按回车键搜索
- 批量操作:支持删除操作
- 导航功能:支持查看和编辑页面跳转
- 状态管理:完整的加载和保存状态管理
修改时间:
2025-01-19
修改原因:
用户发现 pages/testcases 页面没有调用 testcaseService,需要修复这些页面使其使用真实的 API 而不是模拟数据,确保前后端数据一致性。
2025-01-19 - TestCaseFlowController 添加 CreateTestCaseFlow 命令
修改文件:
X1.Presentation/Controllers/TestCaseFlowController.cs - 为TestCaseFlowController添加创建测试用例流程的POST方法
修改内容:
-
新增POST方法:
- 方法名:
CreateTestCaseFlow - 路由:
[HttpPost]- 对应/api/testcaseflow - 参数:
[FromBody] CreateTestCaseFlowCommand command - 返回:
IActionResult
- 方法名:
-
功能特性:
- 命令处理:使用
mediator.Send(command)发送创建命令 - 日志记录:详细的开始、成功、失败日志记录
- 错误处理:完整的错误处理和用户友好的错误信息
- 响应格式:使用
CreatedAtAction返回201状态码和资源位置
- 命令处理:使用
-
日志记录:
- 开始日志:记录流程名称和类型
- 成功日志:记录创建的ID、名称、节点数量、连线数量
- 失败日志:记录流程名称和详细错误信息
-
响应处理:
- 成功响应:返回201 Created状态码,包含新创建资源的URI
- 失败响应:返回400 Bad Request状态码,包含错误详情
- 资源定位:使用
CreatedAtAction提供新创建资源的访问路径
-
技术特性:
- 依赖注入:添加了
CreateTestCaseFlow命名空间的using语句 - MediatR集成:使用mediator发送命令,遵循CQRS模式
- RESTful设计:遵循REST API设计规范
- 统一响应:使用统一的OperationResult响应格式
- 依赖注入:添加了
-
API端点:
POST /api/testcaseflow Content-Type: application/json { "name": "测试流程名称", "description": "流程描述", "type": 1, "isEnabled": true, "viewportX": 40.5, "viewportY": 21.2, "viewportZoom": 1.1, "nodes": [...], "edges": [...] }
修改时间:
2025-01-19
修改原因:
用户要求为TestCaseFlowController添加TestCaseFlow.Commands功能,特别是创建测试用例流程的POST方法,以支持前端界面创建新的测试用例流程。
2025-01-19 - TestCaseNodeDto 和 TestCaseEdgeDto 完善
修改文件:
X1.Application/Features/TestCaseFlow/Queries/GetTestCaseFlowById/GetTestCaseFlowByIdResponse.cs - 完善 TestCaseNodeDto 和 TestCaseEdgeDto 结构
修改内容:
-
新增 DTO 类:
- TestCaseNodeDataDto:节点数据DTO,包含步骤ID、步骤名称、步骤类型、描述、图标等
- TestCaseNodePositionDto:节点位置DTO,包含X、Y坐标
- TestCaseEdgeStyleDto:连线样式DTO,包含描边颜色、描边宽度
- TestCaseEdgeDataDto:连线数据DTO,包含条件信息
-
TestCaseNodeDto 增强:
- 新增字段:
Type:节点类型(如 "testStep")Position:节点位置(TestCaseNodePositionDto)Data:节点数据(TestCaseNodeDataDto)Selected:是否被选中PositionAbsolute:绝对位置Dragging:是否正在拖拽
- 兼容性字段:保留原有字段,确保向后兼容
- 新增字段:
-
TestCaseEdgeDto 增强:
- 新增字段:
Source:源节点IDSourceHandle:源连接点Target:目标节点IDTargetHandle:目标连接点Type:连线类型Animated:是否动画Style:连线样式(TestCaseEdgeStyleDto)Data:连线数据(TestCaseEdgeDataDto)
- 兼容性字段:保留原有字段,确保向后兼容
- 新增字段:
-
技术特性:
- ReactFlow 兼容:新增字段与 ReactFlow 数据结构完全兼容
- JSON 序列化:支持直接序列化为 ReactFlow 所需的 JSON 格式
- 向后兼容:保留原有字段,确保现有代码不受影响
- 类型安全:使用强类型 DTO,避免运行时错误
-
数据结构示例:
{ "nodes": [ { "id": "node-1755654432101", "type": "testStep", "position": { "x": 360, "y": 30 }, "data": { "stepId": "e2192f5a-1582-47e9-92be-c676679418da", "stepName": "StartStep", "stepType": 1, "stepTypeName": "Start", "description": "Mapping_Start", "icon": "play-circle" }, "width": 95, "height": 30, "selected": false, "positionAbsolute": { "x": 360, "y": 30 }, "dragging": false } ], "edges": [ { "source": "node-1755654432101", "sourceHandle": "bottom", "target": "node-1755654436065", "targetHandle": "top", "id": "edge-1755654470705", "type": "smoothstep", "animated": false, "style": { "stroke": "#3b82f6", "strokeWidth": 2 }, "data": { "condition": "default" } } ] } -
设计原则:
- 前端兼容:确保与 ReactFlow 前端组件完全兼容
- 数据完整性:支持完整的节点和连线信息
- 扩展性:支持未来功能扩展
- 性能优化:避免不必要的数据转换
修改时间:
2025-01-19
修改原因:
用户需要 TestCaseNodeDto 和 TestCaseEdgeDto 与 ReactFlow 前端组件完全兼容,支持完整的节点和连线数据结构,包括位置、样式、数据等字段,确保前端能够正确显示和操作测试用例流程。
2025-01-19 - TestCaseFlow Queries功能实现
修改文件:
X1.Application/Features/TestCaseFlow/Queries/GetTestCaseFlows/- 获取TestCaseFlow列表查询X1.Application/Features/TestCaseFlow/Queries/GetTestCaseFlowById/- 根据ID获取TestCaseFlow详情查询X1.Presentation/Controllers/TestCaseFlowController.cs- TestCaseFlow控制器
修改内容:
-
GetTestCaseFlows查询功能:
- 查询类:
GetTestCaseFlowsQuery- 支持搜索、类型过滤、启用状态过滤、分页 - 响应类:
GetTestCaseFlowsResponse- 包含分页信息和TestCaseFlow列表 - 处理器:
GetTestCaseFlowsQueryHandler- 调用仓储获取分页数据并映射为DTO
- 查询类:
-
GetTestCaseFlowById查询功能:
- 查询类:
GetTestCaseFlowByIdQuery- 根据testCaseId获取详情 - 响应类:
GetTestCaseFlowByIdResponse- 包含完整的流程信息、节点和连线数据 - 处理器:
GetTestCaseFlowByIdQueryHandler- 组装TestCaseFlow、TestCaseNode、TestCaseEdge数据
- 查询类:
-
TestCaseFlowController控制器:
- 列表接口:
GET /api/testcaseflow- 获取测试用例流程列表,支持搜索和分页 - 详情接口:
GET /api/testcaseflow/{id}- 获取测试用例流程详情,包含节点和连线 - 完整日志:详细的日志记录和错误处理
- 列表接口:
-
数据组装特性:
- 列表查询:直接返回TestCaseFlow数据,不包含节点和连线
- 详情查询:组装完整的流程信息,包括所有节点和连线数据
- 性能优化:使用仓储的
GetTestCaseFlowWithDetailsAsync方法一次性获取所有数据
-
技术特性:
- CQRS模式:查询和命令分离,使用MediatR进行消息传递
- 分页支持:支持搜索、过滤、分页功能
- 数据完整性:详情查询包含完整的流程结构信息
- 错误处理:完整的异常处理和日志记录
修改时间:
2025-01-19
修改原因:
用户需要为TestCaseFlow实现Queries功能,包括获取列表和根据testCaseId获取详情,详情查询需要组装TestCaseNode和TestCaseEdge数据,为前端界面查看详情提供完整的数据支持。
2025-01-19 - TestCaseFlow 空引用警告修复和连线样式类型优化
修改文件:
X1.Application/Features/TestCaseFlow/Commands/CreateTestCaseFlow/CreateTestCaseFlowCommandHandler.cs- 修复空引用警告X1.Application/Features/TestCaseFlow/Commands/CreateTestCaseFlow/CreateTestCaseFlowCommand.cs- 优化连线样式类型
修改内容:
-
空引用警告修复:
- 问题:在
CreateTestCaseFlowCommandHandler中,ValidateUserAuthentication方法返回的OperationResult<string>可能为空 - 解决方案:使用空合并操作符
??确保传递给CreateFailure方法的参数不为空 - 修改代码:
return OperationResult<CreateTestCaseFlowResponse>.CreateFailure(errorMessages ?? new List<string>());
- 问题:在
-
连线样式类型优化:
- 问题:
Style属性被定义为object?类型,但在CreateEdgesAsync方法中使用edgeData.Style?.ToString()来转换 - 解决方案:将
Style属性明确为string?类型,符合 JSON 字符串格式的实际用途 - 修改代码:
- 问题:
-
连线类型必填验证:
- 在
EdgeData类中将Type属性设为必填:[Required(ErrorMessage = "连线类型不能为空")] - 在验证逻辑中添加对
Type的验证:if (string.IsNullOrWhiteSpace(edge.Type)) - 在创建连线时移除默认值逻辑:
edgeType: edgeData.Type(不再使用?? "straight")
- 在
-
验证器提取:
- 创建了
CreateTestCaseFlowCommandValidator验证器类 - 将
ValidateRequest方法从CreateTestCaseFlowCommandHandler中提取出来 - 使用静态方法
Validate进行验证,便于复用和测试 - 保持原有的验证逻辑和错误消息不变
- 创建了
-
设计原则:
- 单一职责:验证器专注于参数验证,处理器专注于业务逻辑
- 可复用性:验证器可以在其他地方复用
- 可测试性:独立的验证器更容易进行单元测试
- 代码组织:更好的代码结构和职责分离
修改时间:
2025-01-19
修改原因:
用户要求确保连线类型是必填项,界面不能传空值。同时要求将验证逻辑提取到单独的验证器类中,提高代码的可维护性和可测试性。
2025-01-19 - TestCaseFlowController 删除功能添加和接口返回类型统一
修改文件:
X1.Application/Features/TestCaseFlow/Commands/DeleteTestCaseFlow/DeleteTestCaseFlowCommand.cs- 新增删除命令X1.Application/Features/TestCaseFlow/Commands/DeleteTestCaseFlow/DeleteTestCaseFlowCommandHandler.cs- 新增删除命令处理器X1.Presentation/Controllers/TestCaseFlowController.cs- 添加删除端点和统一返回类型
修改内容:
-
删除命令实现:
- 创建了
DeleteTestCaseFlowCommand类,包含流程ID参数 - 创建了
DeleteTestCaseFlowCommandHandler处理器,实现删除逻辑 - 包含用户认证验证、流程存在性检查、删除操作和事务提交
- 创建了
-
控制器接口统一:
- 参考
TerminalServicesController的返回方式,将所有方法返回类型改为OperationResult<T> - 移除了
IActionResult和BadRequest/Ok等 HTTP 状态码处理 - 直接返回
OperationResult<T>对象,让框架自动处理 HTTP 状态码
- 参考
-
删除端点添加:
- 添加了
DELETE /api/testcaseflow/{id}端点 - 包含完整的日志记录和错误处理
- 返回删除操作的结果
- 添加了
-
技术特性:
- 一致性:与
TerminalServicesController保持相同的接口返回模式 - 简化:移除了手动的 HTTP 状态码处理,让框架自动处理
- 完整性:删除功能包含完整的业务逻辑验证和错误处理
- 一致性:与
API 端点示例:
DELETE /api/testcaseflow/{id}
Authorization: Bearer {token}
响应格式:
{
"isSuccess": true,
"data": true,
"errorMessages": null
}
修改时间:
2025-01-19
修改原因:
用户要求添加删除功能到 TestCaseFlowController,并参考 TerminalServicesController 的接口返回方式,统一使用 OperationResult<T> 返回类型,不使用 IActionResult。
2025-01-19 - TestCaseFlow Application层实现
修改文件:
X1.Application/Features/TestCaseFlow/Commands/CreateTestCaseFlow/CreateTestCaseFlowCommand.cs- 创建测试用例流程命令X1.Application/Features/TestCaseFlow/Commands/CreateTestCaseFlow/CreateTestCaseFlowResponse.cs- 创建测试用例流程响应X1.Application/Features/TestCaseFlow/Commands/CreateTestCaseFlow/CreateTestCaseFlowCommandHandler.cs- 创建测试用例流程命令处理器
修改内容:
-
CreateTestCaseFlowCommand 命令类:
- 实现了
IRequest<OperationResult<CreateTestCaseFlowResponse>>接口 - 包含完整的验证特性:
[Required]、[MaxLength]等 - 支持所有必要字段:名称、描述、类型、启用状态、视口坐标等
- 提供合理的默认值,如视口坐标和启用状态
- 实现了
-
CreateTestCaseFlowResponse 响应类:
- 包含完整的流程信息返回
- 支持类型枚举转换为字符串显示
- 包含审计信息:创建时间、创建人等
-
CreateTestCaseFlowCommandHandler 命令处理器:
- 遵循CQRS模式,使用MediatR框架
- 完整的参数验证和业务逻辑验证
- 用户认证验证
- 名称重复性检查
- 使用领域实体的Create工厂方法
- 完整的错误处理和日志记录
- 事务管理(通过UnitOfWork)
-
设计原则:
- 参考TerminalServices模式:完全按照TerminalServices的设计规则实现
- CQRS架构:命令和查询分离
- 领域驱动设计:使用领域实体的工厂方法
- 依赖注入:通过构造函数注入依赖
- 日志记录:完整的操作日志和错误日志
- 错误处理:统一的错误处理和响应格式
-
技术特性:
- 支持异步操作
- 完整的取消令牌支持
- 统一的OperationResult响应格式
- 详细的验证错误信息
- 事务性操作保证
修改时间:
2025-01-19
修改原因:
用户要求在X1.Application.Features中实现TestCaseFlow的功能,参考TerminalServices的设计规则,先完成创建功能。为测试用例流程管理提供完整的Application层支持,包括命令、响应和处理器实现。
修复记录:
- 编译错误修复:修复了
TestCaseFlow.Create方法调用时的命名空间解析问题,使用完全限定的类型名称X1.Domain.Entities.TestCase.TestCaseFlow.Create来解决编译器无法找到Create方法的问题。
2025-01-19 - TestCaseFlow 空引用警告修复和连线样式类型优化
- 命令扩展:在
CreateTestCaseFlowCommand中添加了NodeData和EdgeDataDTO类,支持节点和连线数据的传输 - 处理器增强:在
CreateTestCaseFlowCommandHandler中添加了ITestCaseNodeRepository和ITestCaseEdgeRepository依赖注入 - 节点创建:实现了
CreateNodesAsync方法,支持批量创建测试用例节点,包括位置、尺寸、状态等属性 - 连线创建:实现了
CreateEdgesAsync方法,支持批量创建测试用例连线,包括源节点、目标节点、类型、样式等属性 - 验证增强:添加了对节点和连线数据的验证逻辑,确保数据完整性
- 日志记录:增强了日志记录,包含节点数量和连线数量的统计信息
- 事务管理:确保节点和连线的创建在同一个事务中完成,保证数据一致性
2024-12-19 - StartDeviceRuntimeCommandHandler 问题分析与修复
问题描述
API响应中 isSuccess: true 但 summary.failureCount: 1,导致前端误判操作成功。
问题分析
通过分析代码发现以下潜在问题区域:
- 网络配置构建阶段:在
BuildNetworkConfigurationRequests方法中,设备可能因为配置验证失败而被过滤掉 - 网络启动阶段:在
StartNetworksInParallelAsync方法中,网络启动失败 - 设备运行时处理阶段:设备运行时不存在或更新失败
实施的修复
-
增强日志记录:
- 在
BuildNetworkConfigurationRequests中添加详细的警告日志 - 在
StartNetworksInParallelAsync中增强错误日志和统计信息 - 在设备运行时处理循环中添加调试日志
- 在
-
关键修复 - isSuccess 字段逻辑:
- 问题根源:
OperationResult<T>.IsSuccess属性仅基于ErrorMessages是否为空 - 解决方案:在
Handle方法中根据业务逻辑判断成功/失败 - 只有当所有设备都成功启动时才返回
CreateSuccess - 否则返回
CreateFailure并包含详细错误信息
- 问题根源:
-
配置验证逻辑优化:
- 问题:原来的配置验证过于严格,要求同时有RAN配置和完整的IMS+核心网配置
- 优化:改为更灵活的验证逻辑,允许只有RAN配置或只有IMS配置的设备通过
- 验证规则:
- 至少需要RAN配置 或者 IMS配置(不要求同时有核心网配置)
- 如果有IMS配置但没有核心网配置,记录警告但不阻止设备启动
- 提供更详细的配置状态日志,便于调试
- 影响:减少因配置不完整而被错误跳过的设备数量
修改原因
- 解决前端误判问题
- 提供更好的调试信息
- 确保数据一致性
2024-12-19 - 已实施更改的评估分析
评估结果:所有更改都应该保留
1. 网络配置构建阶段优化 ✅
- 状态: 已优化,无需撤回
- 改进内容:
- 增强的日志记录,记录被跳过设备的具体原因
- 过滤逻辑透明化,包括重复组合、缺少配置、验证失败等情况
- 统计信息记录,显示原始请求数 vs 有效请求数
- 价值: 提供更好的调试信息和透明度
2. 网络启动阶段优化 ✅
- 状态: 已优化,无需撤回
- 改进内容:
- 增强的错误日志,包含具体错误信息
- 统计信息记录,显示总请求数、成功数、失败数
- 失败设备详细记录
- 价值: 提供关键的调试信息,帮助快速定位网络启动失败原因
3. 设备运行时处理阶段优化 ✅
- 状态: 已优化,无需撤回
- 改进内容:
- 跳过逻辑:只处理网络启动成功的设备
- 详细日志:记录状态更新过程
- 调试信息:记录设备运行时当前状态
- 价值: 确保数据一致性,避免对失败设备的无效处理
4. isSuccess 字段逻辑修复 ✅
- 状态: 已修复,这是核心问题
- 问题:
isSuccess: true但failureCount: 1导致前端误判 - 解决方案: 根据业务逻辑判断成功/失败
- 价值: 解决了前端误判的根本问题
建议的监控指标
- 网络配置构建成功率:
有效请求数 / 原始请求数 - 网络启动成功率:
成功设备数 / 有效请求数 - 整体成功率:
成功设备数 / 总请求数
日志分析建议
当出现失败时,可通过以下日志快速定位问题:
- 网络配置构建阶段:查看被跳过设备的原因
- 网络启动阶段:查看具体错误信息
- 设备运行时处理:查看状态更新过程
结论
所有实施的更改都是有价值的改进,不仅解决了核心的 isSuccess 误判问题,还提供了更好的调试能力和数据一致性。不建议撤回任何更改。
2025年修改记录
2025-01-19 - TestCaseEdge 和 TestCaseNode Repositories 完善
修改文件:
X1.Domain/Repositories/TestCase/ITestCaseEdgeRepository.cs- 创建 TestCaseEdge 仓储接口X1.Domain/Repositories/TestCase/ITestCaseNodeRepository.cs- 创建 TestCaseNode 仓储接口X1.Infrastructure/Repositories/TestCase/TestCaseEdgeRepository.cs- 创建 TestCaseEdge 仓储实现X1.Infrastructure/Repositories/TestCase/TestCaseNodeRepository.cs- 创建 TestCaseNode 仓储实现X1.Infrastructure/DependencyInjection.cs- 注册新的仓储服务
修改内容:
-
TestCaseEdge 仓储接口创建:
- 创建了
ITestCaseEdgeRepository接口,继承自IBaseRepository<TestCaseEdge> - 定义了完整的业务方法,包括基本的 CRUD 操作和特定的业务查询
- 支持测试用例连线的完整生命周期管理
- 创建了
-
主要业务方法:
- 基本操作:
AddTestCaseEdgeAsync、UpdateTestCaseEdge、DeleteTestCaseEdgeAsync - 批量操作:
DeleteByTestCaseIdAsync(根据测试用例ID删除所有连线) - 查询操作:
GetAllTestCaseEdgesAsync、GetTestCaseEdgeByIdAsync、GetByTestCaseIdAsync - 特定查询:
GetBySourceNodeIdAsync、GetByTargetNodeIdAsync、GetByEdgeIdAsync - 验证操作:
EdgeIdExistsAsync、ExistsByTestCaseIdAsync
- 基本操作:
-
TestCaseNode 仓储接口创建:
- 创建了
ITestCaseNodeRepository接口,继承自IBaseRepository<TestCaseNode> - 定义了完整的业务方法,包括基本的 CRUD 操作和特定的业务查询
- 支持测试用例节点的完整生命周期管理
- 创建了
-
主要业务方法:
- 基本操作:
AddTestCaseNodeAsync、UpdateTestCaseNode、DeleteTestCaseNodeAsync - 批量操作:
DeleteByTestCaseIdAsync(根据测试用例ID删除所有节点) - 查询操作:
GetAllTestCaseNodesAsync、GetTestCaseNodeByIdAsync、GetByTestCaseIdAsync - 排序查询:
GetByTestCaseIdOrderedAsync(按序号排序) - 特定查询:
GetByNodeIdAsync、GetByStepIdAsync、GetByTestCaseIdAndSequenceAsync - 验证操作:
NodeIdExistsAsync、ExistsByTestCaseIdAsync、SequenceExistsAsync - 统计操作:
GetMaxSequenceNumberAsync(获取最大序号)
- 基本操作:
-
TestCaseEdge 仓储实现创建:
- 创建了
TestCaseEdgeRepository实现类,继承自BaseRepository<TestCaseEdge> - 实现了
ITestCaseEdgeRepository接口的所有方法 - 使用 CQRS 模式,分离命令和查询操作
- 提供完整的日志记录和错误处理
- 创建了
-
TestCaseNode 仓储实现创建:
- 创建了
TestCaseNodeRepository实现类,继承自BaseRepository<TestCaseNode> - 实现了
ITestCaseNodeRepository接口的所有方法 - 使用 CQRS 模式,分离命令和查询操作
- 提供完整的日志记录和错误处理
- 创建了
-
依赖注入配置:
- 在
X1.Infrastructure/DependencyInjection.cs中注册新的仓储服务 - 添加了
ITestCaseEdgeRepository和ITestCaseNodeRepository的注册 - 确保控制器能够正确注入所需的仓储服务
- 在
-
技术特性:
- CQRS 模式:使用
ICommandRepository和IQueryRepository分离读写操作 - 异步支持:所有方法都支持异步操作和取消令牌
- 简洁实现:与现有仓储实现保持一致的简洁风格
- 性能优化:支持批量操作和条件过滤
- CQRS 模式:使用
-
设计原则:
- DDD 原则:遵循领域驱动设计,仓储专注于数据访问
- 单一职责:每个方法专注于特定功能
- 可扩展性:支持未来功能扩展
- 一致性:与现有仓储实现(如
CaseStepConfigRepository)保持一致的架构模式
-
命名空间规范:
- 使用
X1.Domain.Repositories.TestCase命名空间 - 使用
X1.Infrastructure.Repositories.TestCase命名空间 - 与项目整体架构保持一致
- 使用
修改时间:
2025-01-19
修改原因:
用户要求完善 TestCaseEdge 和 TestCaseNode 的 Repositories,参考 ICaseStepConfigRepository 的结构,为测试用例节点和连线管理提供完整的数据访问层支持,包括基本的 CRUD 操作和特定的业务查询功能。
2025-01-19 - TestCaseFlow 实体 Create 和 Update 方法实现
修改文件:
X1.Domain/Entities/TestCase/TestCaseTestFlow.cs - 为TestCaseFlow实体添加Create和Update方法
修改内容:
-
Create 静态工厂方法:
- 添加了
Create静态方法,用于创建新的测试用例流程 - 支持所有必要参数:名称、类型、创建人、描述、启用状态、视口坐标等
- 自动设置ID、创建时间、更新时间等审计字段
- 视口坐标参数(viewportX、viewportY、viewportZoom)由界面传入,不提供默认值
- 添加了
-
Update 实例方法:
- 添加了
Update方法,用于更新测试用例流程 - 支持更新所有字段:名称、类型、描述、启用状态、视口坐标等
- 自动更新
UpdatedAt和UpdatedBy审计字段 - 使用可选参数,只更新传入的字段
- 添加了
-
设计原则:
- 遵循DDD(领域驱动设计)原则
- 使用工厂方法模式创建实体实例
- 通过业务方法修改实体状态
- 确保审计信息的完整性
-
技术特性:
- 类型安全的参数验证
- 完整的审计信息管理
- 灵活的更新机制
- 与CaseStepConfig实体保持一致的实现模式
- 视口坐标由界面传入,确保数据的准确性
修改时间:
2025-01-19
修改原因:
用户要求TestCaseFlow实体提供与CaseStepConfig实体相同的Create和Update方法,确保实体创建和更新的标准化和一致性。同时根据用户反馈,视口坐标参数应该由界面传入,不提供默认值。
2025-01-19 - TestCaseNode 和 TestCaseEdge 实体 Create 和 Update 方法实现
修改文件:
X1.Domain/Entities/TestCase/TestCaseNode.cs- 为TestCaseNode实体添加Create和Update方法X1.Domain/Entities/TestCase/TestCaseEdge.cs- 为TestCaseEdge实体添加Create和Update方法
修改内容:
-
TestCaseNode 实体 Create 和 Update 方法:
- Create 静态工厂方法:
- 添加了
Create静态方法,用于创建新的测试用例节点 - 支持所有必要参数:测试用例ID、节点ID、执行序号、位置坐标、步骤配置ID、尺寸、状态等
- 自动设置ID,不包含审计字段(继承自Entity而非AuditableEntity)
- 提供合理的默认值,如宽度、高度、选中状态等
- 添加了
- Update 实例方法:
- 添加了
Update方法,用于更新测试用例节点 - 支持更新所有字段:测试用例ID、节点ID、执行序号、位置坐标、步骤配置ID、尺寸、状态等
- 使用可选参数,只更新传入的字段
- 提供完整的参数验证和错误处理
- 添加了
- Create 静态工厂方法:
-
TestCaseEdge 实体 Create 和 Update 方法:
- Create 静态工厂方法:
- 添加了
Create静态方法,用于创建新的测试用例连线 - 支持所有必要参数:测试用例ID、连线ID、源节点ID、目标节点ID、连线类型、条件、动画、样式等
- 自动设置ID,不包含审计字段(继承自Entity而非AuditableEntity)
- 提供合理的默认值,如连线类型、动画状态等
- 添加了
- Update 实例方法:
- 添加了
Update方法,用于更新测试用例连线 - 支持更新所有字段:测试用例ID、连线ID、源节点ID、目标节点ID、连线类型、条件、动画、样式等
- 使用可选参数,只更新传入的字段
- 提供完整的参数验证和错误处理
- 添加了
- Create 静态工厂方法:
-
设计原则:
- 遵循DDD(领域驱动设计)原则
- 使用工厂方法模式创建实体实例
- 通过业务方法修改实体状态
- 与TestCaseFlow实体保持一致的实现模式
- 注意TestCaseNode和TestCaseEdge继承自Entity而非AuditableEntity,因此不包含审计字段
-
技术特性:
- 类型安全的参数验证
- 灵活的更新机制,支持部分字段更新
- 与TestCaseFlow实体保持一致的实现模式
- 提供合理的默认值,简化创建过程
- 完整的参数验证和错误处理
修改时间:
2025-01-19
修改原因:
用户要求TestCaseNode和TestCaseEdge实体提供与TestCaseFlow实体相同的Create和Update方法,确保所有测试用例相关实体的创建和更新过程标准化和一致性。
2025-01-19 - TestCaseNode Update 方法不可修改字段优化
修改文件:
X1.Domain/Entities/TestCase/TestCaseNode.cs - 优化TestCaseNode实体的Update方法
修改内容:
-
Update 方法参数优化:
- 移除了不可修改的字段参数:
testCaseId、nodeId、stepId - 这些字段作为实体的标识符和关联关系,在更新时不应该被修改
- 保留了可修改的字段:执行序号、位置坐标、尺寸、状态等
- 移除了不可修改的字段参数:
-
设计原则:
- 遵循实体不可变性原则,保护关键标识符
- 确保数据完整性和一致性
- 防止意外修改关联关系
-
技术特性:
- 更安全的更新机制
- 明确的字段修改边界
- 符合DDD设计原则
修改时间:
2025-01-19
修改原因:
用户反馈指出TestCaseNode的Update方法中,testCaseId、nodeId和stepId这些字段不应该被修改,因为它们是不可变的标识符和关联关系。
2025-01-19 - TestCaseEdge Update 方法不可修改字段优化
修改文件:
X1.Domain/Entities/TestCase/TestCaseEdge.cs - 优化TestCaseEdge实体的Update方法
修改内容:
-
Update 方法参数优化:
- 移除了不可修改的字段参数:
testCaseId、edgeId - 这些字段作为实体的标识符和关联关系,在更新时不应该被修改
- 保留了可修改的字段:源节点ID、目标节点ID、连线类型、条件、动画状态、样式等
- 移除了不可修改的字段参数:
-
设计原则:
- 遵循实体不可变性原则,保护关键标识符
- 确保数据完整性和一致性
- 防止意外修改关联关系
- 与TestCaseNode保持一致的不可变性设计
-
技术特性:
- 更安全的更新机制
- 明确的字段修改边界
- 符合DDD设计原则
- 与TestCaseNode实体的Update方法保持一致的实现模式
修改时间:
2025-01-19
修改原因:
用户反馈指出TestCaseEdge的Update方法中,testCaseId和edgeId这些字段不应该被修改,因为它们是不可变的标识符和关联关系。
2025-01-19 - GetTestCaseFlowByIdQueryHandler 修复
修改文件:
X1.Application/Features/TestCaseFlow/Queries/GetTestCaseFlowById/GetTestCaseFlowByIdQueryHandler.cs
修改内容:
-
依赖注入增强:
- 添加
ICaseStepConfigRepository依赖,用于获取步骤配置信息 - 在构造函数中注入
caseStepConfigRepository参数
- 添加
-
数据映射重构:
- 新增
MapNodesToReactFlowFormatAsync方法:将TestCaseNode实体映射为 ReactFlow 兼容的TestCaseNodeDto - 新增
MapEdgesToReactFlowFormatAsync方法:将TestCaseEdge实体映射为 ReactFlow 兼容的TestCaseEdgeDto - 新增
GetStepTypeName方法:将步骤类型枚举转换为可读的字符串名称
- 新增
-
节点映射逻辑:
- 根据
StepId获取对应的CaseStepConfig信息 - 构建 ReactFlow 格式的
Position和Data对象 - 设置默认的
Type为 "testStep" - 处理
PositionAbsolute的可空逻辑 - 保留所有原有字段用于向后兼容
- 根据
-
连线映射逻辑:
- 解析存储的 JSON 样式字符串为
TestCaseEdgeStyleDto对象 - 设置默认的
SourceHandle和TargetHandle为 "bottom" 和 "top" - 设置默认的
Type为 "smoothstep" - 构建
Data对象包含条件信息 - 保留所有原有字段用于向后兼容
- 解析存储的 JSON 样式字符串为
-
错误处理:
- 添加 JSON 解析异常处理,在解析失败时使用默认样式
- 添加空值检查和默认值处理
技术特性:
- 异步处理:使用异步方法获取步骤配置信息,提高性能
- 数据完整性:确保所有必要字段都有合理的默认值
- 向后兼容:保留原有字段映射,确保现有功能不受影响
- 类型安全:使用强类型映射,避免运行时错误
- 错误恢复:在数据不完整时提供合理的默认值
映射关系:
TestCaseNode.NodeId→TestCaseNodeDto.IdTestCaseNode.PositionX/Y→TestCaseNodeDto.Position.X/YCaseStepConfig信息 →TestCaseNodeDto.DataTestCaseEdge.EdgeId→TestCaseEdgeDto.IdTestCaseEdge.SourceNodeId/TargetNodeId→TestCaseEdgeDto.Source/TargetTestCaseEdge.Style(JSON) →TestCaseEdgeDto.Style(对象)
修改时间:
2025-01-19
修改原因:
用户要求修复 GetTestCaseFlowByIdQueryHandler 来正确映射现有后端数据到新的 ReactFlow 兼容的 DTO 格式,同时保持向后兼容性,确保前端能够正确接收和显示测试用例流程数据。
2025-01-19 - GetTestCaseFlowByIdQueryHandler 简化映射
修改文件:
X1.Application/Features/TestCaseFlow/Queries/GetTestCaseFlowById/GetTestCaseFlowByIdQueryHandler.cs
修改内容:
-
移除向后兼容字段:
- 在
MapNodesToReactFlowFormatAsync方法中移除了所有向后兼容字段 - 在
MapEdgesToReactFlowFormatAsync方法中移除了所有向后兼容字段 - 只保留 ReactFlow 前端需要的格式字段
- 在
-
节点映射简化:
- 只输出前端需要的 ReactFlow 格式:
Id,Type,Position,Data,Width,Height,Selected,PositionAbsolute,Dragging - 移除了:
TestCaseId,NodeId,SequenceNumber,PositionX,PositionY,IsSelected,PositionAbsoluteX,PositionAbsoluteY,IsDragging
- 只输出前端需要的 ReactFlow 格式:
-
连线映射简化:
- 只输出前端需要的 ReactFlow 格式:
Id,Source,SourceHandle,Target,TargetHandle,Type,Animated,Style,Data - 移除了:
TestCaseId,EdgeId,SourceNodeId,TargetNodeId,EdgeType,Condition,IsAnimated,StyleJson
- 只输出前端需要的 ReactFlow 格式:
技术特性:
- 前端优先:直接输出 ReactFlow 前端需要的格式
- 数据精简:移除不必要的向后兼容字段,减少数据传输量
- 格式统一:确保输出格式与前端期望的 JSON 结构完全一致
前端格式示例:
{
"nodes": [
{
"id": "node-1755654432101",
"type": "testStep",
"position": { "x": 360, "y": 30 },
"data": {
"stepId": "e2192f5a-1582-47e9-92be-c676679418da",
"stepName": "StartStep",
"stepType": 1,
"stepTypeName": "Start",
"description": "Mapping_Start",
"icon": "play-circle"
},
"width": 95,
"height": 30,
"selected": false,
"positionAbsolute": { "x": 360, "y": 30 },
"dragging": false
}
]
}
修改时间:
2025-01-19
修改原因:
用户要求简化映射逻辑,直接输出前端需要的 ReactFlow 格式,不需要向后兼容字段,确保数据格式与前端期望的 JSON 结构完全一致。
2025-01-19 - GetTestCaseFlowsQueryHandler 参数修复
修改文件:
X1.Application/Features/TestCaseFlow/Queries/GetTestCaseFlows/GetTestCaseFlowsQueryHandler.cs
修改内容:
-
参数名称修复:
- 将
GetPagedFlowsAsync方法调用中的searchTerm参数名修正为name - 确保参数名称与
ITestCaseFlowRepository接口定义一致
- 将
-
类型转换修复:
- 添加了
TestFlowType枚举的解析逻辑 - 将
string?类型的request.Type转换为TestFlowType?类型 - 使用
Enum.TryParse进行安全的类型转换,避免解析失败
- 添加了
-
错误处理:
- 添加了空值检查,确保在
request.Type为空时不会进行解析 - 使用安全的枚举解析,避免无效类型值导致的异常
- 添加了空值检查,确保在
技术特性:
- 类型安全:确保参数类型与仓储接口定义完全匹配
- 错误处理:添加了安全的枚举解析,避免运行时异常
- 参数一致性:修正了参数名称,确保与接口定义一致
修复的问题:
GetPagedFlowsAsync方法调用时参数名称不匹配TestFlowType枚举类型转换缺失- 可能导致搜索功能无法正常工作
修改时间:
2025-01-19
修改原因:
用户反馈 GetTestCaseFlowsQueryHandler 中的 searchTerm 参数传递有问题,需要修复参数名称和类型转换问题,确保搜索功能正常工作。
2025-01-19 - TestCaseFlow 仓储模式实现和审计字段修复
修改文件:
X1.Domain/Repositories/TestCase/ITestCaseFlowRepository.cs- 创建 TestCaseFlow 仓储接口X1.Infrastructure/Repositories/TestCase/TestCaseFlowRepository.cs- 创建 TestCaseFlow 仓储实现并修复审计字段访问问题
修改内容:
-
TestCaseFlow 仓储接口创建:
- 创建了
ITestCaseFlowRepository接口,继承自IBaseRepository<TestCaseFlow> - 定义了完整的业务方法,包括基本的 CRUD 操作和特定的业务查询
- 支持测试用例流程的完整生命周期管理
- 创建了
-
主要业务方法:
- 基本操作:
AddTestCaseFlowAsync、UpdateTestCaseFlow、DeleteTestCaseFlowAsync - 状态管理:
EnableTestCaseFlowAsync、DisableTestCaseFlowAsync - 查询操作:
GetAllTestCaseFlowsAsync、GetTestCaseFlowByIdAsync、GetByNameAsync - 分类查询:
GetByTypeAsync、GetEnabledFlowsAsync - 详细查询:
GetTestCaseFlowWithDetailsAsync(包含节点和连线) - 验证操作:
NameExistsAsync - 分页查询:
GetPagedFlowsAsync(支持名称、类型、启用状态过滤)
- 基本操作:
-
TestCaseFlow 仓储实现创建:
- 创建了
TestCaseFlowRepository实现类,继承自BaseRepository<TestCaseFlow> - 实现了
ITestCaseFlowRepository接口的所有方法 - 使用 CQRS 模式,分离命令和查询操作
- 提供完整的日志记录和错误处理
- 创建了
-
审计字段修复:
- 问题:修复了 "属性或索引器'AuditableEntity.UpdatedAt'不能用在此上下文中,因为 set 访问器不可访问" 的编译错误
- 解决方案:参考
CaseStepConfigRepository的实现模式,简化仓储实现 - 修改内容:
- 移除了
ICurrentUserService依赖注入 - 移除了复杂的
SetCreated()和SetUpdated()方法调用 - 简化了
AddTestCaseFlowAsync方法,直接调用CommandRepository.AddAsync - 简化了
UpdateTestCaseFlow方法,直接调用CommandRepository.Update - 在
EnableTestCaseFlowAsync和DisableTestCaseFlowAsync方法中直接设置UpdatedAt = DateTime.UtcNow - 移除了详细的日志记录,保持与
CaseStepConfigRepository一致的简洁风格
- 移除了
-
技术特性:
- CQRS 模式:使用
ICommandRepository和IQueryRepository分离读写操作 - 异步支持:所有方法都支持异步操作和取消令牌
- 简洁实现:与现有仓储实现保持一致的简洁风格
- 性能优化:支持分页查询和条件过滤
- CQRS 模式:使用
-
分页查询功能:
- 支持按名称、类型、启用状态进行条件过滤
- 使用动态查询条件构建,支持可选参数
- 返回总记录数和分页数据
- 支持自定义页码和每页大小
-
详细查询功能:
GetTestCaseFlowWithDetailsAsync方法支持包含节点和连线的完整查询- 使用 Entity Framework 的
Include方法加载关联数据 - 适用于需要完整流程信息的场景
-
设计原则:
- DDD 原则:遵循领域驱动设计,仓储专注于数据访问
- 单一职责:每个方法专注于特定功能
- 可扩展性:支持未来功能扩展
- 一致性:与现有仓储实现(如
CaseStepConfigRepository)保持一致的架构模式
-
命名空间规范:
- 使用
X1.Domain.Repositories.TestCase命名空间 - 使用
X1.Infrastructure.Repositories.TestCase命名空间 - 与项目整体架构保持一致
- 使用
修改时间:
2025-01-19
修改原因:
用户要求在 CellularManagement.Domain.Repositories.TestCase 命名空间中实现 TestCaseFlow 的仓储模式,为测试用例流程管理提供完整的数据访问层支持,包括基本的 CRUD 操作和特定的业务查询功能。同时修复了审计字段访问权限问题,参考 CaseStepConfigRepository 的实现模式,简化仓储实现,确保与现有代码风格保持一致。
2025-01-19 - TestCaseTestFlow 命名规范和viewport属性修复
修改文件:
X1.Domain/Entities/TestCase/TestCaseTestFlow.cs- 重命名为TestCaseFlow并添加viewport属性X1.Domain/Entities/TestCase/TestCaseEdge.cs- 完善TestCaseEdge实体X1.Infrastructure/Context/AppDbContext.cs- 添加TestCaseFlow相关DbSet配置X1.Infrastructure/Configurations/TestCase/TestCaseFlowConfiguration.cs- 创建TestCaseFlow配置类X1.Infrastructure/Configurations/TestCase/TestCaseNodeConfiguration.cs- 创建TestCaseNode配置类X1.Infrastructure/Configurations/TestCase/TestCaseEdgeConfiguration.cs- 创建TestCaseEdge配置类
修改内容:
-
TestCaseTestFlow重命名为TestCaseFlow:
- 将类名从
TestCaseTestFlow改为TestCaseFlow,更符合命名规范 - 继承自
Entity基类,添加主键Id字段 - 添加viewport属性字段:ViewportX、ViewportY、ViewportZoom
- 设置viewport默认值:x=40.54057017483274, y=21.183463943747256, zoom=1.1367874248827994
- 将类名从
-
TestCaseEdge实体完善:
- 继承自
Entity基类,添加主键Id字段 - 添加完整的连线属性:TestCaseId、EdgeId、SourceNodeId、TargetNodeId
- 添加连线配置:EdgeType、Condition、IsAnimated、Style
- 添加导航属性关联TestCaseFlow
- 继承自
-
数据库配置:
- 在AppDbContext中添加TestCaseFlow、TestCaseNode、TestCaseEdge的DbSet配置
- 创建完整的Entity Framework配置类
- 配置表名规范:tb_testcaseflow、tb_testcasenode、tb_testcaseedge
- 添加完整的字段映射、索引和关系配置
-
技术特性:
- 命名规范:使用更简洁的TestCaseFlow命名
- 主键支持:所有实体都继承Entity基类,支持主键Id
- viewport支持:添加视口坐标和缩放级别属性
- 关系配置:完整的实体关系映射和级联删除配置
- 索引优化:为常用查询字段添加数据库索引
-
设计原则:
- 命名简洁:TestCaseFlow比TestCaseTestFlow更简洁明了
- 功能完整:支持完整的测试用例流程管理
- 数据完整性:通过外键关系和级联删除确保数据一致性
- 性能优化:通过索引配置提高查询性能
修改时间:
2025-01-19
修改原因:
用户要求修复TestCaseTestFlow的命名规范问题,主要是测试用例流程表,并添加viewport属性字段(x、y、zoom),以支持ReactFlow设计器的视口状态保存和恢复。
2025-01-19 - AdbOperationConfiguration数据库配置优化
修改文件:
X1.Infrastructure/Configurations/Terminal/AdbOperationConfiguration.cs - 修复Path字段的数据库约束
修改内容:
-
问题描述:
- 当前AdbOperationConfiguration中Path字段设置为
IsRequired(),与业务逻辑不一致 - 根据AdbOperation实体的业务规则,Path字段只有在UseAbsolutePath为true时才必填
- 数据库约束应该与业务逻辑保持一致
- 当前AdbOperationConfiguration中Path字段设置为
-
解决方案:
- 将Path字段的数据库约束从
IsRequired()改为IsRequired(false) - 更新字段注释,明确说明Path字段的必填条件
- 确保数据库层约束与业务层验证逻辑一致
- 将Path字段的数据库约束从
-
具体修改:
- 数据库约束:
IsRequired()→IsRequired(false) - 注释更新:添加"(当启用绝对路径时必填)"说明
- 业务一致性:与AdbOperation实体中的条件验证保持一致
- 数据库约束:
-
技术特性:
- 数据完整性:数据库约束与业务规则一致
- 灵活性:允许Path字段为空,符合业务需求
- 文档清晰:注释明确说明字段的使用条件
- 架构一致性:基础设施层与领域层保持一致
-
修改代码:
// 路径字段 builder.Property(x => x.Path) .IsRequired(false) // 改为允许为空 .HasMaxLength(500) .HasComment("命令执行时所依赖的路径(当启用绝对路径时必填)"); -
设计原则:
- 业务驱动:数据库设计服务于业务需求
- 一致性:各层之间的约束保持一致
- 灵活性:支持不同的业务场景
- 可维护性:清晰的注释便于理解和维护
修改时间:
2025-01-19
修改原因:
确保AdbOperationConfiguration的数据库约束与AdbOperation实体的业务逻辑保持一致,Path字段只有在UseAbsolutePath为true时才必填。
2025-01-19 - AdbOperations Commands层DeviceId修改限制
修改文件:
X1.Application/Features/AdbOperations/Commands/UpdateAdbOperation/UpdateAdbOperationCommand.cs - 移除DeviceId属性
X1.Application/Features/AdbOperations/Commands/UpdateAdbOperation/UpdateAdbOperationCommandHandler.cs - 修复DeviceId处理逻辑
修改内容:
-
问题描述:
- UpdateAdbOperationCommand中仍然包含DeviceId属性,与实体层业务规则不一致
- UpdateAdbOperationCommandHandler仍然传递DeviceId参数给实体的Update方法
- 应用层与领域层的业务规则不一致,可能导致混淆
-
解决方案:
- 从UpdateAdbOperationCommand中移除DeviceId属性
- 修改UpdateAdbOperationCommandHandler,使用现有实体的DeviceId值
- 确保应用层与领域层的业务规则保持一致
-
具体修改:
- 命令对象:移除DeviceId属性,明确表示Update操作不涉及DeviceId修改
- 处理器逻辑:使用
existingOperation.DeviceId而不是request.DeviceId - 日志优化:移除日志中的DeviceId参数,避免误导
- 业务一致性:应用层与领域层规则完全一致
-
技术特性:
- 架构一致性:应用层与领域层业务规则保持一致
- 数据完整性:防止通过应用层意外修改DeviceId
- 代码清晰:明确表达Update操作的业务约束
- 错误预防:在应用层就避免传递不允许修改的参数
-
修改代码:
// UpdateAdbOperationCommand.cs - 移除DeviceId属性 public class UpdateAdbOperationCommand : IRequest<OperationResult<UpdateAdbOperationResponse>> { public string Id { get; set; } = string.Empty; // DeviceId属性已移除 public string Command { get; set; } = string.Empty; // ... 其他属性 } // UpdateAdbOperationCommandHandler.cs - 修复DeviceId处理 existingOperation.Update( existingOperation.DeviceId, // 使用现有的DeviceId,不允许修改 request.Command, // ... 其他参数 ); -
设计原则:
- 单一职责:Update命令只处理允许修改的字段
- 业务驱动:应用层设计服务于业务规则
- 防御性编程:在多个层面防止数据不一致
- 可维护性:清晰的代码结构便于理解和维护
修改时间:
2025-01-19
修改原因:
确保AdbOperations Commands层的Update操作与AdbOperation实体的业务规则保持一致,防止DeviceId被意外修改,维护数据完整性和业务逻辑的一致性。
2025-01-19 - AdbOperation实体DeviceId更新限制
修改文件:
X1.Domain/Entities/Terminal/AdbOperation.cs - 限制Update方法中DeviceId的修改
修改内容:
-
问题描述:
- 当前Update方法允许修改DeviceId,这可能导致数据一致性问题
- 用户要求AdbOperation的Update操作不能修改deviceId
- 需要添加业务规则限制DeviceId的修改
-
解决方案:
- 在Update方法中添加DeviceId修改验证
- 比较传入的deviceId参数与当前DeviceId属性值
- 如果不匹配则抛出异常,阻止更新操作
- 移除DeviceId的赋值操作,保持原有值
-
具体修改:
- 验证逻辑:添加
if (!string.Equals(DeviceId, deviceId.Trim(), StringComparison.OrdinalIgnoreCase))检查 - 错误处理:抛出
ArgumentException("设备ID不允许修改", nameof(deviceId)) - 赋值移除:注释掉
DeviceId = deviceId.Trim();并添加说明注释
- 验证逻辑:添加
-
技术特性:
- 数据完整性:确保DeviceId在更新操作中保持不变
- 业务规则:实现业务逻辑约束
- 错误提示:提供明确的错误信息
- 大小写不敏感:使用
StringComparison.OrdinalIgnoreCase进行比较
-
验证逻辑:
// 设备ID不允许修改 if (!string.Equals(DeviceId, deviceId.Trim(), StringComparison.OrdinalIgnoreCase)) throw new ArgumentException("设备ID不允许修改", nameof(deviceId)); // 不更新DeviceId,保持原有值 // DeviceId = deviceId.Trim(); // 已移除 -
设计原则:
- 数据一致性:防止关键字段被意外修改
- 业务约束:符合ADB操作的业务规则
- 用户友好:提供清晰的错误提示
- 安全性:防止数据完整性问题
修改时间:
2025-01-19
修改原因:
用户要求AdbOperation的Update操作不能修改deviceId,确保数据一致性和业务规则的正确性。
2025-01-19 - AdbOperation实体路径验证优化
修改文件:
X1.Domain/Entities/Terminal/AdbOperation.cs - 优化路径验证逻辑,实现条件验证
修改内容:
-
问题描述:
- 当前路径验证逻辑过于严格,无论是否启用绝对路径都要求路径不能为空
- 用户希望只有当
UseAbsolutePath启用时,Path字段才不能为空 - 需要实现条件验证逻辑
-
解决方案:
- 修改
Create和Update方法中的路径验证逻辑 - 添加条件判断:只有当
useAbsolutePath为true时,才验证路径不能为空 - 更新错误消息以明确说明验证条件
- 修改
-
具体修改:
- Create方法:将
if (string.IsNullOrWhiteSpace(path))改为if (useAbsolutePath && string.IsNullOrWhiteSpace(path)) - Update方法:将
if (string.IsNullOrWhiteSpace(path))改为if (useAbsolutePath && string.IsNullOrWhiteSpace(path)) - 错误消息:从"路径不能为空"改为"启用绝对路径时,路径不能为空"
- Create方法:将
-
技术特性:
- 条件验证:根据业务逻辑实现智能验证
- 用户体验:允许在非绝对路径模式下路径为空
- 业务逻辑:符合ADB操作的业务需求
- 错误提示:提供更明确的错误信息
-
验证逻辑:
// 修改前 if (string.IsNullOrWhiteSpace(path)) throw new ArgumentException("路径不能为空", nameof(path)); // 修改后 if (useAbsolutePath && string.IsNullOrWhiteSpace(path)) throw new ArgumentException("启用绝对路径时,路径不能为空", nameof(path)); -
设计原则:
- 业务导向:验证逻辑符合实际业务需求
- 用户友好:提供清晰的错误提示
- 灵活性:支持不同的路径使用模式
- 一致性:在创建和更新操作中保持一致的验证逻辑
修改时间:
2025-01-19
修改原因:
用户反馈需要实现条件验证,只有当启用绝对路径时路径字段才不能为空,提高业务逻辑的灵活性。
2025-01-19 - ADB操作Drawer布局优化
修改文件:
X1.WebUI/src/pages/adb-operations/AdbOperationDrawer.tsx - 优化Drawer布局,添加滚动条支持
修改内容:
-
问题描述:
- 当ADB命令列表增加时,Drawer布局无法正常显示所有内容
- 缺少滚动条支持,用户体验不佳
- 布局结构需要优化以支持动态内容
-
解决方案:
- 重新设计布局结构,将内容分为固定区域和可滚动区域
- 为命令列表区域添加独立的滚动条
- 使用Flexbox布局确保各区域正确显示
-
具体修改:
- 固定区域:设备选择、操作描述、ADB路径、选项设置等
- 可滚动区域:命令列表区域,支持垂直滚动
- 布局优化:使用
flex-shrink-0和flex-1控制区域大小
-
技术特性:
- 响应式滚动:命令列表区域支持垂直滚动
- 固定布局:重要操作区域保持固定位置
- 视觉优化:添加背景色和边框改善视觉效果
- 用户体验:支持任意数量的命令添加
-
布局结构:
// 固定头部 <DrawerHeader className="flex-shrink-0"> // 内容区域 <DrawerContent className="flex flex-col flex-1 min-h-0 p-0 overflow-hidden"> // 固定区域:设备选择 <div className="flex-shrink-0 p-4 pb-2"> // 可滚动区域:命令列表 <div className="flex-1 min-h-0 flex flex-col px-4"> <div className="flex-1 overflow-y-auto"> <div className="space-y-3 pr-2"> // 固定区域:其他表单字段 <div className="flex-shrink-0 p-4 pt-2"> // 固定底部 <DrawerFooter className="flex-shrink-0"> -
设计原则:
- 空间利用:合理分配固定和可滚动区域
- 操作便利:重要操作区域保持可见
- 扩展性:支持动态添加命令
- 一致性:与其他Drawer组件保持一致的交互模式
修改时间:
2025-01-19
修改原因:
用户反馈当添加多个ADB命令时,Drawer布局无法正常显示,需要添加滚动条优化布局。
2025-01-19 - ADB操作Drawer空白优化
修改文件:
X1.WebUI/src/pages/adb-operations/AdbOperationDrawer.tsx - 优化布局空白,减少多余间距
修改内容:
-
问题描述:
- 用户反馈布局存在"多余空白"问题
- 内边距和外边距重叠导致空间浪费
- 滚动区域与固定区域间距过大
-
解决方案:
- 重新调整内边距和外边距结构
- 优化各区域之间的间距
- 减少不必要的空白区域
-
具体修改:
- DrawerContent:移除
p-4,改为p-0 - 设备选择区域:使用
p-4 pb-2替代mb-4 - 命令列表区域:使用
px-4替代整体内边距 - 滚动区域:移除
pr-2,改为在内容区域使用pr-2 - 其他表单字段:使用
p-4 pt-2替代mt-4
- DrawerContent:移除
-
技术特性:
- 紧凑布局:减少不必要的空白区域
- 精确控制:为不同区域设置合适的内边距
- 视觉优化:改善整体布局的紧凑性
- 用户体验:提供更好的空间利用率
-
布局优化:
// 优化前:存在多余空白 <DrawerContent className="p-4"> <div className="mb-4">设备选择</div> <div className="flex-1"> <div className="overflow-y-auto pr-2"> <div className="mt-4">其他字段</div> // 优化后:紧凑布局 <DrawerContent className="p-0"> <div className="p-4 pb-2">设备选择</div> <div className="flex-1 px-4"> <div className="overflow-y-auto"> <div className="pr-2"> <div className="p-4 pt-2">其他字段</div> -
设计原则:
- 空间效率:最大化利用可用空间
- 视觉平衡:保持适当的间距和层次
- 操作便利:确保重要操作区域易于访问
- 一致性:与其他组件保持一致的间距规范
修改时间:
2025-01-19
修改原因:
用户反馈布局存在"多余空白"问题,需要优化间距结构,提供更紧凑的布局。
2025-01-19 - ADB操作路径字段条件验证
修改文件:
X1.WebUI/src/pages/adb-operations/AdbOperationDrawer.tsx - 实现ADB路径字段的条件验证
修改内容:
-
问题描述:
- 用户反馈ADB路径字段的验证逻辑需要优化
- 当前路径字段始终为可选,但实际使用中需要条件验证
- 当选择"使用绝对路径"时,路径字段应该为必填
-
解决方案:
- 实现条件验证逻辑,根据"使用绝对路径"选项决定路径字段是否必填
- 动态显示必填标识符
- 添加错误提示和样式
-
具体修改:
- 验证逻辑:在
validateForm函数中添加条件验证 - UI标识:动态显示红色星号标识必填字段
- 错误处理:添加路径字段的错误提示和样式
- 用户体验:提供清晰的验证反馈
- 验证逻辑:在
-
技术特性:
- 条件验证:根据
useAbsolutePath状态决定验证规则 - 动态UI:必填标识符根据条件动态显示
- 错误反馈:提供明确的错误信息和视觉提示
- 表单完整性:确保数据验证的准确性
- 条件验证:根据
-
验证逻辑:
// 验证ADB路径 - 只有在使用绝对路径时才必填 if (formData.useAbsolutePath && !formData.path.trim()) { newErrors.path = '使用绝对路径时必须指定ADB路径'; } -
UI优化:
<Label htmlFor="path" className="text-sm font-medium"> ADB路径 {formData.useAbsolutePath && <span className="text-red-500">*</span>} </Label> <Input className={errors.path ? 'border-red-500 focus:border-red-500' : ''} /> {errors.path && ( <p className="text-xs text-red-500">{errors.path}</p> )} -
设计原则:
- 逻辑一致性:验证规则与业务逻辑保持一致
- 用户友好:提供清晰的必填标识和错误提示
- 视觉反馈:使用颜色和样式区分不同状态
- 数据完整性:确保提交数据的有效性
修改时间:
2025-01-19
修改原因:
用户反馈ADB路径字段需要条件验证,只有在选择"使用绝对路径"时才应该为必填字段。
2025-01-19 - ADB操作Drawer单命令布局优化
修改文件:
X1.WebUI/src/pages/adb-operations/AdbOperationDrawer.tsx - 优化单命令情况下的布局空白
修改内容:
-
问题描述:
- 用户反馈"当添加命令默认一个就会剩余很多空白"
- 当只有一个命令时,命令列表区域占用过多空间
- 布局在单命令情况下不够紧凑,存在大量空白区域
-
解决方案:
- 根据命令数量动态调整布局结构
- 当命令数量较少时,不使用弹性布局占用剩余空间
- 只有当命令数量超过2个时才启用滚动区域
-
具体修改:
- 条件布局:根据
commands.length > 2决定是否使用弹性布局 - 动态类名:使用模板字符串动态设置CSS类名
- 滚动优化:只在需要时启用滚动条
- 空间利用:减少单命令情况下的空白区域
- 条件布局:根据
-
技术特性:
- 自适应布局:根据内容数量调整布局策略
- 条件渲染:动态应用CSS类名
- 空间优化:减少不必要的空白区域
- 用户体验:提供更紧凑的单命令布局
-
布局逻辑:
// 命令列表区域 - 根据命令数量决定布局 <div className={`px-4 ${commands.length > 2 ? 'flex-1 min-h-0 flex flex-col' : ''}`}> // 命令列表区域 - 根据命令数量决定是否可滚动 <div className={commands.length > 2 ? 'flex-1 overflow-y-auto' : ''}> <div className={`space-y-3 ${commands.length > 2 ? 'pr-2' : ''}`}> -
设计原则:
- 内容驱动:布局根据实际内容数量调整
- 空间效率:避免不必要的空白区域
- 渐进增强:随着内容增加自动启用滚动
- 视觉平衡:保持整体布局的协调性
修改时间:
2025-01-19
修改原因:
用户反馈当只有一个命令时,布局存在大量空白区域,需要优化单命令情况下的布局紧凑性。
2025-01-19 - 抽屉组件内间距优化
修改文件:
X1.WebUI/src/pages/ran-configurations/RANConfigurationDrawer.tsx- 为抽屉内容添加内间距X1.WebUI/src/pages/network-stack-configs/NetworkStackConfigDrawer.tsx- 为抽屉内容添加内间距X1.WebUI/src/pages/ims-configurations/IMSConfigurationDrawer.tsx- 为抽屉内容添加内间距X1.WebUI/src/pages/core-network-configs/CoreNetworkConfigDrawer.tsx- 为抽屉内容添加内间距
修改内容:
-
问题描述:
- RANConfigurationDrawer 抽屉内容太贴着边缘,缺少适当的内间距
- 用户体验不佳,内容显示过于紧凑
-
解决方案:
- 为
DrawerContent组件添加p-6类名 - 提供 24px 的内边距,改善视觉效果和用户体验
- 为
-
具体修改:
// 修改前 <DrawerContent className="flex flex-col space-y-4 flex-1 overflow-y-auto"> // 修改后 <DrawerContent className="flex flex-col space-y-4 flex-1 overflow-y-auto p-4"> -
技术特性:
- 响应式设计:内间距适配不同屏幕尺寸
- 视觉优化:提供更好的内容层次和可读性
- 用户体验:改善表单内容的显示效果
- 一致性:与其他抽屉组件保持一致的样式
-
设计原则:
- 空间利用:合理利用抽屉空间,避免内容过于紧凑
- 视觉层次:通过内间距建立清晰的内容层次
- 用户友好:提供舒适的视觉体验
修改时间:
2025-01-19
修改原因:
用户反馈 RANConfigurationDrawer 内容太贴着边缘,需要添加适当的内间距来改善视觉效果和用户体验。
2025-01-19 - ReactFlowDesigner 导入导出功能实现
修改文件:
X1.WebUI/src/pages/testcases/ReactFlowDesigner.tsx - 实现Flow数据的导入和导出功能
修改内容:
-
导入功能实现:
- 文件选择:添加了文件选择按钮,支持选择JSON格式的Flow文件
- 数据验证:验证导入文件是否包含有效的nodes和edges数据
- 状态恢复:导入成功后恢复nodes、edges和viewport状态
- 错误处理:提供详细的错误提示和异常处理
- 重复导入:支持重复导入同一文件
-
导出功能实现:
- 数据收集:收集当前的nodes、edges和viewport状态
- 元数据添加:添加版本、导出时间、描述等元数据信息
- 文件生成:生成格式化的JSON文件
- 自动下载:自动触发文件下载,文件名包含日期信息
- 资源清理:自动清理临时创建的URL对象
-
UI组件设计:
- 工具栏按钮:在工具栏中添加导入和导出按钮
- 图标设计:使用SVG图标,导入使用向下箭头,导出使用向上箭头
- 悬停效果:导入按钮使用蓝色主题,导出按钮使用绿色主题
- 响应式设计:按钮适配不同屏幕尺寸
-
成功提示功能:
- 通知组件:添加导入成功通知,显示在右上角
- 动画效果:使用slideIn动画,从右侧滑入
- 自动关闭:提供关闭按钮,点击后隐藏通知
- 状态管理:使用useState管理通知显示状态
-
样式设计:
- 按钮样式:使用现代化的按钮设计,包含图标和文字
- 通知样式:使用绿色主题的成功通知样式
- 动画效果:添加CSS动画和过渡效果
- 响应式布局:适配不同屏幕尺寸
-
技术特性:
- 文件处理:使用FileReader API读取本地文件
- 数据序列化:使用JSON.stringify格式化数据
- Blob处理:使用Blob和URL.createObjectURL创建下载链接
- 状态管理:使用React Hooks管理组件状态
- 错误处理:完整的异常捕获和用户提示
-
数据格式:
{ "nodes": [...], "edges": [...], "viewport": {...}, "metadata": { "name": "Test Case Flow", "version": "1.0", "exportDate": "2025-01-19T10:30:00.000Z", "description": "Exported test case flow data" } } -
用户体验:
- 直观操作:点击按钮即可导入或导出Flow数据
- 即时反馈:操作结果立即显示,成功或失败都有明确提示
- 文件命名:导出文件自动包含日期信息,便于管理
- 错误提示:详细的错误信息帮助用户理解问题
修改时间:
2025-01-19
修改原因:
用户需要在测试用例流程设计器中实现Flow数据的导入和导出功能,以便保存和恢复流程设计,提高工作效率和数据管理能力。
修复记录:
- 2025-01-19:修复了导出功能中的Hook调用错误,将
useReactFlow()调用移到组件顶层,避免在普通函数中调用Hook
2025-01-19 - AdbOperation数据库迁移应用
修改文件:
数据库 tb_adboperations 表结构
修改内容:
-
执行状态:
- ✅ 迁移文件创建:成功
- ✅ 数据库更新:成功
- ✅ 数据库结构与代码配置:完全一致
-
数据库变更:
- 表名:
tb_adboperations - 字段名:
Path - 变更类型:从
NOT NULL改为NULL(允许为空) - 注释更新:从"命令执行时所依赖的路径"改为"命令执行时所依赖的路径(当启用绝对路径时必填)"
- 表名:
-
执行的SQL命令:
ALTER TABLE tb_adboperations ALTER COLUMN "Path" DROP NOT NULL; COMMENT ON COLUMN tb_adboperations."Path" IS '命令执行时所依赖的路径(当启用绝对路径时必填)'; -
迁移历史:
- 迁移ID:
20250820020118_UpdateAdbOperationPathNullable - 已记录到
__EFMigrationsHistory表
- 迁移ID:
-
业务影响:
- 现在
Path字段在UseAbsolutePath为false时可以为空 - 在
UseAbsolutePath为true时仍然必填(由业务逻辑验证) - 数据库约束与领域层业务规则完全一致
- 现在
-
技术验证:
- 构建成功:
Build succeeded - 数据库连接正常:配置验证通过
- 迁移执行无错误:所有SQL命令成功执行
- 构建成功:
修改时间:
2025-01-19
修改原因:
应用之前创建的数据库迁移,将AdbOperationConfiguration中Path字段的IsRequired约束变更同步到数据库,确保数据库结构与代码配置完全一致,支持Path字段在UseAbsolutePath为false时可以为空的业务需求。
2025-01-19 - TestCaseEdge Type字段必填验证
修改文件:
X1.Application/Features/TestCaseFlow/Commands/CreateTestCaseFlow/CreateTestCaseFlowCommand.cs- 将EdgeData的Type字段改为必填X1.Application/Features/TestCaseFlow/Commands/CreateTestCaseFlow/CreateTestCaseFlowCommandHandler.cs- 添加Type字段验证并移除默认值逻辑
修改内容:
-
EdgeData Type字段必填化:
- 问题描述:用户反馈
edgeType: edgeData.Type ?? "straight"中的Type字段应该是必填项,界面不能传空 - 解决方案:将Type字段从可选改为必填,添加验证逻辑,移除默认值处理
- 问题描述:用户反馈
-
CreateTestCaseFlowCommand.cs 修改:
- 字段类型:将
Type从string?改为string - 验证特性:添加
[Required(ErrorMessage = "连线类型不能为空")]验证特性 - 默认值:移除默认值,设置为
null!
- 字段类型:将
-
CreateTestCaseFlowCommandHandler.cs 修改:
- 验证逻辑:在
ValidateRequest方法中添加对edge.Type的空值验证 - 创建逻辑:在
CreateEdgesAsync方法中移除?? "straight"默认值逻辑 - 错误处理:提供明确的错误信息:"连线类型不能为空"
- 验证逻辑:在
-
技术特性:
- 数据验证:确保连线类型字段不为空
- 用户友好:提供清晰的错误提示信息
- 业务逻辑:符合业务需求,连线类型必须明确指定
- 类型安全:使用强类型验证,避免运行时错误
-
设计原则:
- 数据完整性:确保必要字段不为空
- 用户体验:提供明确的验证反馈
- 业务规则:符合测试用例流程设计的业务需求
- 代码一致性:与项目中其他必填字段的处理方式保持一致
修改时间:
2025-01-19
修改原因:
用户要求确保TestCaseEdge的Type字段是必填项,界面不能传空值,需要添加相应的验证逻辑并移除默认值处理,确保数据完整性和业务逻辑的正确性。
2025-01-16 测试用例列表组件创建
修改文件:
X1.WebUI/src/pages/testcases/TestCasesListView.tsx- 创建测试用例列表组件X1.WebUI/src/routes/AppRouter.tsx- 更新路由配置
修改内容:
-
问题描述:
testcases/list和testcases/create路由都使用了同一个组件TestCasesViewTestCasesView是一个流程设计器,用于创建测试用例testcases/list应该显示一个测试用例列表的表格
-
解决方案:
- 创建了新的
TestCasesListView组件,专门用于显示测试用例列表 - 更新路由配置,让
testcases/list使用新的列表组件 - 保持
testcases/create继续使用原有的流程设计器组件
- 创建了新的
-
TestCasesListView组件特性:
- 表格显示:使用表格组件显示测试用例列表
- 搜索功能:支持按测试用例名称或描述搜索
- 状态管理:显示测试用例的状态(激活、停用、草稿)
- 优先级管理:显示测试用例的优先级(高、中、低)
- 操作按钮:提供查看、编辑、删除操作
- 创建按钮:提供创建新测试用例的快捷入口
-
路由配置更新:
- 添加了
TestCasesListView组件的lazy加载导入 - 更新
testcases/list路由使用新的列表组件 - 保持
testcases/create路由使用原有的流程设计器组件
- 添加了
-
技术特性:
- 使用React + TypeScript开发
- 采用shadcn/ui组件库
- 支持响应式设计
- 完整的错误处理和用户反馈
- 模拟数据展示功能
-
UI设计:
- 现代化的表格设计
- 状态徽章和优先级徽章
- 搜索工具栏
- 操作按钮图标化
- 响应式布局
修改时间:
2025-01-16
修改原因:
解决测试用例列表和创建页面显示相同内容的问题,为测试用例管理提供正确的列表视图和创建视图分离。
2025-01-19 - 测试用例列表抽屉查看功能增强
修改文件:
X1.WebUI/src/pages/testcases/TestCasesListView.tsx - 添加抽屉式流程查看功能
修改内容:
-
功能增强:
- 添加了抽屉组件来显示测试用例流程详情
- 集成了ReactFlow来可视化显示流程节点和连线
- 实现了异步加载流程数据的功能
- 添加了加载状态指示器
-
抽屉组件特性:
- Drawer组件:使用shadcn/ui的Drawer组件
- 高度设置:抽屉高度为90vh,提供充足的显示空间
- 标题显示:显示测试用例名称和描述
- 响应式设计:适配不同屏幕尺寸
-
ReactFlow集成:
- 流程可视化:使用ReactFlow显示流程节点和连线
- 控件支持:包含Controls(缩放、适应视图)、Background(网格背景)、MiniMap(小地图)
- 自动适应:使用fitView自动适应视图大小
- 样式设置:使用灰色背景提升视觉效果
-
数据转换功能:
- 节点转换:将后端节点数据转换为ReactFlow节点格式
- 连线转换:将后端连线数据转换为ReactFlow连线格式
- 位置信息:支持节点的位置、尺寸、选中状态等信息
- 样式支持:支持连线的样式、动画、数据等属性
-
状态管理:
- 选中状态:
selectedTestCase存储当前选中的测试用例详情 - 抽屉状态:
drawerOpen控制抽屉的打开/关闭 - 加载状态:
flowLoading控制流程数据的加载状态 - 错误处理:完整的错误处理和用户提示
- 选中状态:
-
用户体验优化:
- 加载指示器:显示旋转动画和"加载流程中..."提示
- 按钮状态:查看按钮在加载时禁用,防止重复点击
- 错误提示:当加载失败时显示"未找到流程数据"
- 交互反馈:点击查看按钮立即显示加载状态
-
技术实现:
- 异步加载:使用
handleViewTestCase函数异步加载流程详情 - 数据获取:调用
testcaseService.getTestCaseFlowById获取完整流程数据 - 类型安全:使用TypeScript确保类型安全
- 组件导入:正确导入ReactFlow相关组件和样式
- 异步加载:使用
-
流程数据处理:
const getReactFlowData = () => { if (!selectedTestCase) return { nodes: [], edges: [] }; const nodes: Node[] = selectedTestCase.nodes.map(node => ({ id: node.id, type: node.type || 'default', position: node.position, data: node.data, width: node.width, height: node.height, selected: node.selected, positionAbsolute: node.positionAbsolute, dragging: node.dragging })); const edges: Edge[] = selectedTestCase.edges.map(edge => ({ id: edge.id, source: edge.source, sourceHandle: edge.sourceHandle, target: edge.target, targetHandle: edge.targetHandle, type: edge.type || 'smoothstep', animated: edge.animated, style: edge.style, data: edge.data })); return { nodes, edges }; };
修改时间:
2025-01-19
修改原因:
用户要求在查看测试用例时采用抽屉方式显示流程,并加载处理流程数据,提供更好的用户体验和流程可视化能力。
2025-01-19 - 测试用例详情抽屉组件提取
修改文件:
X1.WebUI/src/components/testcases/TestCaseDetailDrawer.tsx- 创建独立的测试用例详情抽屉组件X1.WebUI/src/pages/testcases/TestCasesListView.tsx- 重构使用独立抽屉组件
修改内容:
-
组件提取:
- 将测试用例详情抽屉功能从
TestCasesListView中提取为独立组件 - 创建了
TestCaseDetailDrawer组件,位于@/components/testcases/目录 - 实现了组件的复用性和代码累计
- 将测试用例详情抽屉功能从
-
TestCaseDetailDrawer组件特性:
- Props接口:定义了
testCaseId、open、onOpenChange三个属性 - 状态管理:内部管理
selectedTestCase、flowLoading、error状态 - 生命周期管理:使用
useEffect监听抽屉打开状态,自动加载数据 - 错误处理:完整的错误状态管理和重试功能
- Props接口:定义了
-
功能增强:
- 自动加载:抽屉打开时自动加载测试用例详情
- 状态清理:抽屉关闭时自动清理状态
- 错误重试:提供重试按钮,用户可以重新加载数据
- 加载指示器:显示旋转动画和加载提示
-
TestCasesListView重构:
- 简化状态:移除了
selectedTestCase、flowLoading等状态 - 简化逻辑:
handleViewTestCase函数简化为只设置ID和打开抽屉 - 组件使用:使用
<TestCaseDetailDrawer>组件替代原有的抽屉代码 - 代码减少:大幅减少了组件代码量,提高可维护性
- 简化状态:移除了
-
技术特性:
- 组件复用:抽屉组件可以在其他页面中复用
- 职责分离:列表页面专注于列表显示,抽屉组件专注于详情显示
- 类型安全:完整的TypeScript类型定义
- 错误边界:独立的错误处理,不影响主页面
-
用户体验优化:
- 响应式设计:抽屉高度为90vh,适配不同屏幕
- 加载反馈:清晰的加载状态指示
- 错误恢复:提供重试机制,提升用户体验
- 状态同步:抽屉状态与父组件完全同步
-
代码结构:
// TestCaseDetailDrawer.tsx interface TestCaseDetailDrawerProps { testCaseId: string | null; open: boolean; onOpenChange: (open: boolean) => void; } // TestCasesListView.tsx const [selectedTestCaseId, setSelectedTestCaseId] = useState<string | null>(null); const [drawerOpen, setDrawerOpen] = useState(false); const handleViewTestCase = (id: string) => { setSelectedTestCaseId(id); setDrawerOpen(true); }; -
设计原则:
- 单一职责:每个组件专注于特定功能
- 可复用性:抽屉组件可以在多个地方使用
- 可维护性:代码结构清晰,易于维护和扩展
- 性能优化:按需加载,减少不必要的渲染
修改时间:
2025-01-19
修改原因:
用户要求将测试用例详情抽屉提取为独立组件,实现代码累计和复用,提高代码的可维护性和组件的可复用性。
2025-01-19 - Drawer组件缺失导出修复
修改文件:
X1.WebUI/src/components/ui/drawer.tsx - 添加缺失的DrawerTitle和DrawerDescription组件
修改内容:
-
问题描述:
TestCaseDetailDrawer组件导入DrawerDescription和DrawerTitle时出现错误- 错误信息:
The requested module '/src/components/ui/drawer.tsx' does not provide an export named 'DrawerDescription' - drawer.tsx 文件中缺少这两个组件的定义和导出
-
解决方案:
- 在 drawer.tsx 中添加了
DrawerTitle组件 - 在 drawer.tsx 中添加了
DrawerDescription组件 - 为两个组件添加了完整的 TypeScript 接口定义
- 在 drawer.tsx 中添加了
-
DrawerTitle组件:
- 接口定义:
DrawerTitleProps包含children和className属性 - 样式设计:使用
text-lg font-semibold类名,提供标题样式 - HTML结构:使用
<h2>标签,符合语义化设计
- 接口定义:
-
DrawerDescription组件:
- 接口定义:
DrawerDescriptionProps包含children和className属性 - 样式设计:使用
text-sm text-muted-foreground类名,提供描述文本样式 - HTML结构:使用
<p>标签,符合语义化设计
- 接口定义:
-
技术特性:
- 类型安全:完整的 TypeScript 接口定义
- 样式一致性:使用
cn工具函数合并类名 - 可扩展性:支持自定义 className 属性
- 语义化:使用合适的 HTML 标签
-
组件结构:
interface DrawerTitleProps { children: React.ReactNode className?: string } export function DrawerTitle({ children, className }: DrawerTitleProps) { return ( <h2 className={cn("text-lg font-semibold", className)}> {children} </h2> ) } interface DrawerDescriptionProps { children: React.ReactNode className?: string } export function DrawerDescription({ children, className }: DrawerDescriptionProps) { return ( <p className={cn("text-sm text-muted-foreground", className)}> {children} </p> ) } -
设计原则:
- 一致性:与其他 Drawer 组件保持一致的接口设计
- 可复用性:组件可以在其他抽屉组件中复用
- 可维护性:清晰的代码结构和类型定义
- 用户体验:提供合适的默认样式
修改时间:
2025-01-19
修改原因:
修复 drawer.tsx 组件库中缺失的 DrawerTitle 和 DrawerDescription 组件导出,解决 TestCaseDetailDrawer 组件的导入错误问题。
2025-01-19 - TestCaseDetailDrawer 样式与 ReactFlowDesigner 保持一致
修改文件:
X1.WebUI/src/components/testcases/TestCaseDetailDrawer.tsx - 参考 ReactFlowDesigner 添加自定义节点样式
修改内容:
-
样式一致性要求:
- 用户要求 TestCaseDetailDrawer 中的 ReactFlow 样式与 ReactFlowDesigner 保持完全一致
- 需要添加自定义节点类型和视觉效果
-
自定义节点组件:
- TestStepNode 组件:完全复制 ReactFlowDesigner 中的自定义节点组件
- 图标组件:支持所有图标类型(Play、Square、GitBranch、Smartphone等)
- 节点样式:根据步骤类型显示不同的形状和颜色
- 连接点:根据节点类型显示不同的输入输出连接点
-
节点样式规则:
- 开始步骤 (type=1):圆形,蓝色主题,只有输出连接点
- 结束步骤 (type=2):圆形,红色主题,只有输入连接点
- 处理步骤 (type=3):矩形,绿色主题,有输入和输出连接点
- 判断步骤 (type=4):菱形,紫色主题,有输入和输出连接点
-
图标系统:
- 设备相关图标:蓝色背景(smartphone、phone、wifi等)
- 网络相关图标:绿色背景(network、activity)
- 控制相关图标:橙色背景(play-circle、stop-circle)
- 配置相关图标:紫色背景(settings、git-branch)
-
ReactFlow 配置:
- 节点类型:使用自定义
testStep节点类型 - 视图设置:默认缩放1.5,最小1倍,最大2倍
- 网格对齐:启用15x15网格对齐
- 控件:包含 Controls、Background、MiniMap
- 节点类型:使用自定义
-
技术特性:
- ReactFlowProvider:包装组件以支持 useReactFlow hook
- fitView:自动适应视图大小
- 延迟渲染:使用 setTimeout 确保节点正确渲染后再执行 fitView
- 状态管理:完整的加载、错误、数据状态管理
-
视觉效果:
- 选中状态:蓝色环形高亮
- 悬停效果:边框颜色变化
- 连接点:彩色圆形连接点,支持悬停效果
- 背景:灰色背景,与 ReactFlowDesigner 一致
-
组件结构:
// 自定义节点组件 const TestStepNode = ({ data, selected }: { data: any; selected?: boolean }) => { // 图标组件映射 const getIconComponent = (iconName: string) => { ... }; // 节点样式映射 const getNodeStyle = (stepType: number) => { ... }; // 图标背景色映射 const getIconBgColor = (iconName: string) => { ... }; // 渲染不同形状的节点 return ( <div className={`group relative transition-all duration-200`}> {/* 根据步骤类型渲染不同形状 */} {/* 根据步骤类型渲染不同连接点 */} </div> ); };
修改时间:
2025-01-19
修改原因:
用户要求 TestCaseDetailDrawer 中的 ReactFlow 样式与 ReactFlowDesigner 保持完全一致,确保查看模式下的流程显示与设计模式下的样式完全相同。
2025-01-19 - TestCaseDetailDrawer 移除小地图和调试数据映射
修改文件:
X1.WebUI/src/components/testcases/TestCaseDetailDrawer.tsx - 移除小地图组件并添加调试信息
修改内容:
-
移除小地图:
- 根据用户要求"不需要小地图",从 ReactFlow 组件中移除了
<MiniMap />组件 - 保留
<Controls />和<Background />组件
- 根据用户要求"不需要小地图",从 ReactFlow 组件中移除了
-
添加调试信息:
- 在
getReactFlowData函数中添加了console.log调试信息 - 输出原始节点数据和每个节点的处理过程
- 帮助诊断节点显示"Unknown"的问题
- 在
-
调试信息内容:
console.log('原始节点数据:', testCase.nodes); console.log('处理节点:', node); console.log('节点数据:', node.data); -
技术特性:
- 调试友好:添加详细的日志输出,便于问题诊断
- 用户需求响应:移除不需要的小地图组件
- 数据验证:通过日志验证数据映射是否正确
修改时间:
2025-01-19
修改原因:
- 用户明确要求"不需要小地图"
- 节点仍然显示"Unknown"问题需要进一步调试
- 需要验证数据映射是否正确工作
2025-01-19 - TestCaseDetailDrawer 增强调试和数据映射修复
修改文件:
X1.WebUI/src/components/testcases/TestCaseDetailDrawer.tsx - 增强调试信息并修复数据映射
修改内容:
-
增强调试信息:
- 在
getReactFlowData函数中添加了更详细的日志输出 - 添加了原始连线数据的日志输出
- 添加了节点位置信息的日志输出
- 在
TestStepNode组件中添加了数据接收的日志输出
- 在
-
修复数据映射:
- 使用可选链操作符
?.来安全访问数据字段 - 为所有数据字段提供默认值,防止 undefined 错误
- 为节点尺寸提供默认值(width: 150, height: 50)
- 为连线样式提供默认值
- 使用可选链操作符
-
数据安全处理:
// 节点数据安全处理 const nodeData = { stepId: node.data?.stepId || node.id, stepName: node.data?.stepName || 'Unknown', stepType: node.data?.stepType || 3, stepTypeName: node.data?.stepTypeName || '处理步骤', description: node.data?.description || '', icon: node.data?.icon || 'settings' }; // 连线数据安全处理 style: edge.style || { stroke: '#333', strokeWidth: 2 }, data: edge.data || {} -
调试信息内容:
- 原始节点数据和连线数据
- 每个节点的处理过程
- 节点位置信息
- 处理后的节点数据
- TestStepNode 组件接收到的数据
-
技术特性:
- 数据安全:使用可选链和默认值防止运行时错误
- 调试友好:详细的日志输出便于问题诊断
- 容错性:即使数据不完整也能正常显示
- 兼容性:与 ReactFlowDesigner 的数据结构保持一致
修改时间:
2025-01-19
修改原因:
- 节点仍然显示"Unknown"且没有连接
- 样式与 ReactFlowDesigner 完全不同
- 需要深入调试数据映射问题
- 确保数据安全处理,防止运行时错误
2025-01-16 StartTerminalServiceCommandHandler 代码优化
修改文件:
X1.Application/Features/TerminalServices/Commands/StartTerminalService/StartTerminalServiceCommandHandler.cs- 优化WebSocket连接创建逻辑
修改内容:
-
参数验证增强:
- 服务端点验证:检查
serviceEndpoint是否为空,避免空引用异常 - 服务编码验证:检查
existingService.ServiceCode是否为空,确保WebSocket客户端名称有效 - 用户信息验证:保持原有的用户ID验证逻辑
- 服务端点验证:检查
-
WebSocket连接创建优化:
- 请求参数完善:添加
HeartbeatInterval参数,设置为30秒心跳间隔 - 异常处理增强:使用 try-catch 包装WebSocket连接创建过程
- 响应验证详细化:
- 检查响应是否为null
- 检查响应成功状态
- 提供详细的错误信息
- 请求参数完善:添加
-
日志记录改进:
- 操作开始日志:记录WebSocket连接创建的详细信息
- 调试级别日志:记录WebSocket请求参数(客户端名称、连接地址、心跳间隔)
- 成功日志:记录连接创建成功的基本信息
- 错误日志:提供更详细的错误信息和上下文
-
错误处理严谨化:
- 空值检查:对所有关键参数进行空值验证
- 异常捕获:捕获WebSocket连接创建过程中的所有异常
- 错误消息:提供用户友好的错误消息,包含具体的错误原因
- 取消令牌支持:在WebSocket连接创建时传递取消令牌
-
代码结构优化:
- 方法提取:将WebSocket连接创建逻辑提取为独立的私有方法
CreateWebSocketConnectionAsync - 职责分离:主方法专注于业务流程控制,WebSocket连接创建逻辑独立封装
- 可读性提升:使用更清晰的变量命名和注释
- 维护性增强:便于后续功能扩展和问题排查
- 错误处理统一:统一的错误信息传递机制,正确处理
OperationResult<T>的ErrorMessages属性
- 方法提取:将WebSocket连接创建逻辑提取为独立的私有方法
-
技术特性:
- 异步操作:保持异步操作模式,支持取消令牌
- 资源管理:确保异常情况下的资源正确释放
- 性能优化:避免不必要的字符串操作和对象创建
- 安全性:增强输入验证,防止潜在的安全问题
修改时间:
2025-01-16
修改原因:
提高启动终端服务功能的代码质量和稳定性,增强错误处理能力,提供更好的用户体验和系统可维护性。
2025-01-15 X1.WebAPI 部署脚本优化
修改文件:
X1.WebAPI/publish.bat- 添加deploy.sh复制功能X1.WebAPI/deploy.sh- 创建优化的服务器端部署脚本
修改内容:
-
publish.bat脚本增强:
- 添加了自动复制
deploy.sh到发布目录的功能 - 现在会自动复制:Dockerfile、docker-deploy.md、deploy.sh
- 提供详细的复制状态反馈和错误提示
- 添加了自动复制
-
deploy.sh脚本特性:
- 彩色输出:不同级别的信息用不同颜色显示(INFO蓝色、SUCCESS绿色、WARNING黄色、ERROR红色)
- 详细日志:每个步骤都有详细的输出信息和状态反馈
- 错误处理:遇到错误立即停止并显示错误信息
- 健康检查:自动检查应用是否正常启动(最多等待30秒)
- 状态显示:显示容器状态、端口信息、镜像信息等
- 权限检查:自动设置正确的文件权限
- Docker检查:检查Docker安装状态和服务运行状态
-
部署流程优化:
- 文件检查:验证所有必要文件是否存在
- 权限设置:自动设置可执行文件和目录权限
- 容器管理:自动停止和删除旧容器
- 镜像构建:显示构建过程和结果
- 容器启动:显示启动状态和端口监听情况
- 健康检查:验证应用是否正常响应
-
使用方式:
# 本地发布 publish.bat # 上传publish目录到服务器 # 在服务器上运行 chmod +x deploy.sh ./deploy.sh
修改时间:
2025-01-15
修改原因:
优化X1.WebAPI项目的部署流程,提供详细的部署输出信息,简化服务器端部署操作,提高部署的可视化和可维护性。
2025-01-16 路由冲突修复和当前用户服务增强
修改文件:
X1.Presentation/Controllers/TerminalServicesController.cs- 修复路由冲突X1.Domain/Services/ICurrentUserService.cs- 添加服务IP和端口获取方法X1.Infrastructure/Services/CurrentUserService.cs- 实现服务IP和端口获取方法X1.Application/Features/TerminalServices/Commands/StartTerminalService/StartTerminalServiceCommand.cs- 增强用户获取逻辑X1.WebUI/src/constants/api.ts- 添加终端服务API路径X1.WebUI/src/services/terminalService.ts- 更新API路径和修复命名冲突
修改内容:
-
路由冲突修复:
- 问题描述:
TerminalServicesController和TerminalDevicesController都使用了相同的路由路径api/terminal-devices,导致Swagger生成时出现冲突 - 解决方案:将
TerminalServicesController的路由改为api/terminal-services,保持TerminalDevicesController使用api/terminal-devices - 前端更新:更新前端API路径配置,添加
TERMINAL_SERVICES常量,更新终端服务使用新的API路径
- 问题描述:
-
当前用户服务增强:
- 新增方法:
GetCurrentServiceIpAddress():获取当前服务IP地址GetCurrentServicePort():获取当前服务端口GetCurrentServiceEndpoint():获取当前服务端点信息(IP:端口)
- 技术特性:
- 优先获取IPv4地址,支持IPv6到IPv4的映射
- 完整的空值检查和错误处理
- 从HttpContext中获取本地连接信息
- 新增方法:
-
启动终端服务命令处理器增强:
- 用户获取严谨化:
- 检查用户ID是否为空
- 检查用户是否已认证
- 获取当前服务端点信息用于日志记录
- 日志记录增强:
- 记录用户ID、服务端点、操作结果
- 提供更详细的操作追踪信息
- 用户获取严谨化:
-
前端服务修复:
- API路径更新:使用新的
TERMINAL_SERVICES路径 - 命名冲突修复:将
TerminalService类重命名为TerminalServiceClient,避免与接口冲突 - 类型安全:确保所有TypeScript类型定义正确
- API路径更新:使用新的
-
设计原则:
- RESTful API设计:使用语义化的路由路径
- 职责分离:终端服务和终端设备使用不同的API路径
- 安全性:增强用户认证和授权检查
- 可追溯性:完整的操作日志记录
修改时间:
2025-01-16
修改原因:
- 修复Swagger生成时的路由冲突问题,确保API文档正确生成
- 增强当前用户服务功能,提供更丰富的用户和服务信息
- 提高系统安全性和可追溯性,确保所有操作都有完整的审计信息
2025-01-16 终端消息事件模型创建和WebSocket集成
修改文件:
X1.Domain/Models/TerminalMessageEvent.cs- 创建终端消息事件模型X1.WebSocket/Handlers/TerminalMessageHandler.cs- 修改WebSocket消息处理器以使用IMediatorX1.BackendServices/TerminalManagement/TerminalManagementService.cs- 更新终端管理服务使用新的事件模型X1.BackendServices/TerminalManagement/TerminalMessageEventHandler.cs- 创建终端消息事件处理器X1.BackendServices/DependencyInjection.cs- 注册终端管理服务和事件处理器
修改内容:
-
TerminalMessageEvent模型特性:
- 实现
INotification接口,用于MediatR消息传递 - 包含三个基本字段:
ConnectionId、MessageData、Timestamp - 提供
Create和CreateWithTimestamp静态工厂方法 - 包含
GetMessageSummary和IsValid实用方法 - 遵循项目模型设计规范
- 实现
-
WebSocket消息处理集成:
- 修改
TerminalMessageHandler以使用IMediator - 在
HandleAsync方法中使用TerminalMessageEvent.Create创建事件 - 通过
IMediator.Publish发送消息事件 - 保持原有的WebSocket响应逻辑
- 修改
-
终端消息事件处理器:
- 创建
TerminalMessageEventHandler实现INotificationHandler<TerminalMessageEvent> - 负责接收和处理来自
TerminalMessageHandler的终端消息事件 - 提供完整的日志记录和错误处理
- 支持异步消息处理和业务逻辑扩展
- 创建
-
终端管理服务更新:
- 更新
TerminalManagementService使用新的事件模型 - 在
HandleTerminalMessageAsync方法中使用Create方法 - 确保事件传递的一致性
- 更新
-
依赖注入配置:
- 注册
TerminalManagementService为HostedService - 注册
TerminalMessageEventHandler为Scoped服务 - 确保服务在应用启动时正确初始化
- 注册
-
设计原则:
- 遵循CQRS模式,使用MediatR进行消息传递
- 采用事件驱动架构,解耦WebSocket处理和业务逻辑
- 使用工厂方法模式创建事件实例
- 提供完整的日志记录和错误处理机制
修改时间:
2025-01-16
修改原因:
需要创建一个标准的终端消息事件模型,用于WebSocket消息的事件传递,使用系统自带的 IMediator 进行消息处理,实现终端设备的统一消息管理。
2024年修改记录
2025-01-15 终端设备管理前端界面修复
修改文件:
X1.WebUI/src/services/terminalDeviceService.tsX1.WebUI/src/pages/terminal-devices/TerminalDevicesTable.tsxX1.WebUI/src/pages/terminal-devices/TerminalDeviceForm.tsxX1.WebUI/src/pages/terminal-devices/TerminalDevicesView.tsxX1.WebUI/src/components/ui/switch.tsxX1.WebUI/package.json
修改内容:
-
问题描述:
- 终端设备管理页面需要与 instruments 页面保持一致的样式和功能
- 缺少必要的 UI 组件和依赖包
- 表单实现与 instruments 页面不一致
-
解决方案:
- 修复了
terminalDeviceService.ts中的接口定义,使其与后端 API 保持一致 - 更新了
TerminalDevicesTable.tsx,使用TerminalDeviceStatusBadge组件显示状态 - 重写了
TerminalDeviceForm.tsx,移除 Switch 组件,使用简单的 useState 状态管理,与 instruments 页面保持一致 - 创建了
switch.tsx组件(虽然最终未使用,但为将来需要时做准备) - 安装了缺失的
@hookform/resolvers依赖包
- 修复了
-
关键修改:
- 表格状态显示:使用 Badge 组件而不是 Switch 组件来显示设备状态
- 表单实现:采用与 instruments 页面相同的简单状态管理方式,不使用 react-hook-form
- 字段映射:确保前端字段与后端 API 字段完全匹配
- 编辑模式:在编辑模式下禁用不可修改的字段(IP地址、Agent端口)
-
技术细节:
- 移除了复杂的表单验证库依赖
- 使用简单的 useState 进行状态管理
- 保持与 instruments 页面完全一致的 UI 交互模式
- 确保所有 TypeScript 类型定义正确
修改时间:
2025-01-15
修改原因:
确保终端设备管理页面与 instruments 页面保持完全一致的样式和功能,提供统一的用户体验。
2025-01-15 终端设备服务导入错误修复
修改文件:
X1.WebUI/src/services/terminalDeviceService.ts
修改内容:
-
问题描述:
terminalDeviceService.ts中导入httpClient时出现错误:The requested module '/src/services/axiosConfig.ts' does not provide an export named 'httpClient'OperationResult类型导入路径错误:Cannot find module '@/types/common'
-
解决方案:
- 修正
httpClient的导入路径:从'./axiosConfig'改为'@/lib/http-client' - 修正
OperationResult的导入路径:从'@/types/common'改为'@/types/auth'
- 修正
修改记录
2025-01-21 - 创建 TestCaseFlow 相关表的数据库迁移
修改文件:
X1.Infrastructure/Migrations/20250821080604_AddTestCaseFlowTables.cs- 新建迁移文件X1.Infrastructure/Migrations/20250821080604_AddTestCaseFlowTables.Designer.cs- 迁移设计器文件X1.Infrastructure/Migrations/AppDbContextModelSnapshot.cs- 更新模型快照
修改内容:
-
迁移文件创建:
- 迁移名称:
AddTestCaseFlowTables - 迁移时间:2025-08-21 08:06:04
- 迁移描述:为 TestCaseFlow、TestCaseNode、TestCaseEdge 实体创建数据库表
- 迁移名称:
-
创建的表结构:
-
tb_testcaseflow:测试用例流程主表
- 包含 id、name、description、type、isenabled、viewport_x、viewport_y、viewport_zoom 等字段
- 包含审计字段:createdat、updatedat、createdby、updatedby
- 创建索引:name、type、isenabled
-
tb_testcasenode:测试用例节点表
- 包含 id、testcaseid、nodeid、sequencenumber、stepid、positionx、positiony、width、height 等字段
- 包含状态字段:isselected、positionabsolutex、positionabsolutey、isdragging
- 外键关系:testcaseid → tb_testcaseflow.id (CASCADE)
- 外键关系:stepid → tb_casestepconfig.id (SET NULL)
- 创建索引:testcaseid、nodeid、sequencenumber、stepid
-
tb_testcaseedge:测试用例连线表
- 包含 id、testcaseid、edgeid、sourcenodeid、targetnodeid、edgetype、condition、isanimated、style 等字段
- 外键关系:testcaseid → tb_testcaseflow.id (CASCADE)
- 创建索引:testcaseid、edgeid、sourcenodeid、targetnodeid
-
-
数据库关系:
- 级联删除:删除测试用例流程时,自动删除相关的节点和连线
- 可选关联:节点可以关联步骤配置,删除步骤配置时节点 stepid 设为 NULL
- 完整性约束:确保数据的一致性和完整性
-
迁移应用状态:
- 已成功应用:迁移已应用到数据库
- 表已创建:三个表都已成功创建在数据库中
- 索引已建立:所有必要的索引都已创建完成
-
技术特性:
- PostgreSQL 兼容:使用 PostgreSQL 特定的数据类型和语法
- 性能优化:为常用查询字段创建索引
- 数据完整性:通过外键约束确保数据一致性
- 审计支持:包含完整的审计字段支持
修改时间:
2025-01-21
修改原因:
用户反映 TestCaseFlows、TestCaseNodes、TestCaseEdges 新建后还没有迁移数据库,需要创建相应的数据库迁移文件并应用到数据库中,以支持测试用例流程管理功能。
2025-01-19 - 根据 TestCaseFlowController 修复 testcaseService.ts
修改文件:
X1.WebUI/src/services/testcaseService.ts - 根据后端 TestCaseFlowController 重新编写前端服务
修改内容:
-
完全重构服务:
- 服务类名:从
TestCaseService改为TestCaseFlowService - 基础URL:从
/api/testcases改为/api/testcaseflow - API端点:完全匹配后端 TestCaseFlowController 的接口
- 服务类名:从
-
数据类型重新定义:
- TestFlowType:测试流程类型枚举
- TestCaseFlow:测试用例流程基础信息
- TestCaseNode:测试用例节点(支持 ReactFlow)
- TestCaseEdge:测试用例连线(支持 ReactFlow)
- TestCaseFlowDetail:测试用例流程详情(包含节点和连线)
-
API 方法对应:
- getTestCaseFlows:对应
GET /api/testcaseflow- 获取流程列表 - getTestCaseFlowById:对应
GET /api/testcaseflow/{id}- 获取流程详情 - createTestCaseFlow:对应
POST /api/testcaseflow- 创建流程 - deleteTestCaseFlow:对应
DELETE /api/testcaseflow/{id}- 删除流程
- getTestCaseFlows:对应
-
请求参数匹配:
- GetTestCaseFlowsRequest:支持 searchTerm、type、isEnabled、pageNumber、pageSize
- CreateTestCaseFlowRequest:支持 name、description、type、isEnabled、viewport、nodes、edges
- CreateNodeData:节点创建数据结构
- CreateEdgeData:连线创建数据结构
-
响应数据结构:
- GetTestCaseFlowsResponse:包含分页信息的流程列表
- GetTestCaseFlowByIdResponse:包含完整节点和连线数据的流程详情
- CreateTestCaseFlowResponse:创建成功后的流程信息
-
ReactFlow 兼容性:
- 节点结构:完全支持 ReactFlow 的节点数据结构
- 连线结构:完全支持 ReactFlow 的连线数据结构
- 位置信息:支持 position、positionAbsolute 等位置字段
- 样式信息:支持 style、data 等样式和数据字段
-
向后兼容性:
- 保留导出:保持
testcaseService导出,确保现有代码不破坏 - 新增导出:新增
testcaseFlowService导出,提供更明确的命名
- 保留导出:保持
修改时间:
2025-01-19
修改原因:
用户要求根据 TestCaseFlowController 修复 testcaseService.ts,确保前端服务与后端 API 完全匹配,支持测试用例流程的完整 CRUD 操作和 ReactFlow 集成。
2025-01-19 - 更新 API 路径常量以匹配后端控制器
修改文件:
X1.WebUI/src/constants/api.ts- 更新 API 路径常量X1.WebUI/src/services/testcaseService.ts- 使用 API 路径常量
修改内容:
-
API 路径常量更新:
- 移除:
TEST_CASES: '/test-cases'和TEST_STEPS: '/test-steps'(后端无对应控制器) - 新增:
TEST_CASE_FLOW: '/api/testcaseflow'(对应 TestCaseFlowController) - 更新:
CASE_STEP_CONFIGS: '/api/casestepconfigs'(对应 CaseStepConfigController)
- 移除:
-
testcaseService.ts 优化:
- 导入常量:添加
API_PATHS导入 - 使用常量:将硬编码的
/api/testcaseflow替换为API_PATHS.TEST_CASE_FLOW - 统一管理:所有 API 路径都通过常量统一管理
- 导入常量:添加
-
路径对应关系:
- TestCaseFlowController:
/api/testcaseflow→API_PATHS.TEST_CASE_FLOW - CaseStepConfigController:
/api/casestepconfigs→API_PATHS.CASE_STEP_CONFIGS
- TestCaseFlowController:
-
技术特性:
- 类型安全:使用 TypeScript 常量确保路径一致性
- 维护性:集中管理 API 路径,便于维护和修改
- 一致性:确保前端服务与后端控制器路径完全匹配
修改时间:
2025-01-19
修改原因:
用户询问是否需要根据 testcaseService 修复其他相关服务,发现 API 路径常量与实际后端控制器不匹配,需要统一更新以确保前后端一致性。
2025-01-19 - 修复 pages/testcases 页面使用 testcaseService
修改文件:
X1.WebUI/src/pages/testcases/TestCasesListView.tsx- 修复列表页面使用真实 APIX1.WebUI/src/pages/testcases/TestCasesView.tsx- 修复视图页面使用真实 APIX1.WebUI/src/pages/testcases/ReactFlowDesigner.tsx- 添加保存状态支持
修改内容:
-
TestCasesListView.tsx 重构:
- 移除模拟数据:删除
mockTestCases和本地接口定义 - 集成真实 API:使用
testcaseService.getTestCaseFlows()获取数据 - 添加加载状态:显示加载中状态,提升用户体验
- 实现搜索功能:支持按名称搜索测试用例流程
- 实现删除功能:使用
testcaseService.deleteTestCaseFlow()删除流程 - 更新数据展示:适配
TestCaseFlow接口的数据结构 - 修复状态显示:使用
isEnabled字段显示启用/停用状态 - 添加类型标签:显示测试流程类型(功能测试、性能测试等)
- 移除模拟数据:删除
-
TestCasesView.tsx 重构:
- 集成保存功能:使用
testcaseService.createTestCaseFlow()保存流程 - 数据格式转换:将 ReactFlow 节点和连线数据转换为后端格式
- 添加保存状态:显示保存中状态,防止重复提交
- 错误处理:完整的错误处理和用户提示
- 流程验证:检查流程完整性(开始节点、结束节点等)
- 集成保存功能:使用
-
ReactFlowDesigner.tsx 增强:
- 添加 saving 属性:支持保存状态传递
- 保存按钮状态:保存时禁用按钮并显示"保存中..."
- 用户体验优化:防止保存过程中的重复操作
-
数据结构适配:
- 节点数据转换:ReactFlow 节点 → 后端 CreateNodeData 格式
- 连线数据转换:ReactFlow 连线 → 后端 CreateEdgeData 格式
- 类型安全:使用 TypeScript 接口确保类型安全
-
功能特性:
- 实时搜索:支持按回车键搜索
- 批量操作:支持删除操作
- 导航功能:支持查看和编辑页面跳转
- 状态管理:完整的加载和保存状态管理
修改时间:
2025-01-19
修改原因:
用户发现 pages/testcases 页面没有调用 testcaseService,需要修复这些页面使其使用真实的 API 而不是模拟数据,确保前后端数据一致性。
2025-01-19 - TestCaseFlowController 添加 CreateTestCaseFlow 命令
修改文件:
X1.Presentation/Controllers/TestCaseFlowController.cs - 为TestCaseFlowController添加创建测试用例流程的POST方法
修改内容:
-
新增POST方法:
- 方法名:
CreateTestCaseFlow - 路由:
[HttpPost]- 对应/api/testcaseflow - 参数:
[FromBody] CreateTestCaseFlowCommand command - 返回:
IActionResult
- 方法名:
-
功能特性:
- 命令处理:使用
mediator.Send(command)发送创建命令 - 日志记录:详细的开始、成功、失败日志记录
- 错误处理:完整的错误处理和用户友好的错误信息
- 响应格式:使用
CreatedAtAction返回201状态码和资源位置
- 命令处理:使用
-
日志记录:
- 开始日志:记录流程名称和类型
- 成功日志:记录创建的ID、名称、节点数量、连线数量
- 失败日志:记录流程名称和详细错误信息
-
响应处理:
- 成功响应:返回201 Created状态码,包含新创建资源的URI
- 失败响应:返回400 Bad Request状态码,包含错误详情
- 资源定位:使用
CreatedAtAction提供新创建资源的访问路径
-
技术特性:
- 依赖注入:添加了
CreateTestCaseFlow命名空间的using语句 - MediatR集成:使用mediator发送命令,遵循CQRS模式
- RESTful设计:遵循REST API设计规范
- 统一响应:使用统一的OperationResult响应格式
- 依赖注入:添加了
-
API端点:
POST /api/testcaseflow Content-Type: application/json { "name": "测试流程名称", "description": "流程描述", "type": 1, "isEnabled": true, "viewportX": 40.5, "viewportY": 21.2, "viewportZoom": 1.1, "nodes": [...], "edges": [...] }
修改时间:
2025-01-19
修改原因:
用户要求为TestCaseFlowController添加TestCaseFlow.Commands功能,特别是创建测试用例流程的POST方法,以支持前端界面创建新的测试用例流程。
2025-01-19 - TestCaseNodeDto 和 TestCaseEdgeDto 完善
修改文件:
X1.Application/Features/TestCaseFlow/Queries/GetTestCaseFlowById/GetTestCaseFlowByIdResponse.cs - 完善 TestCaseNodeDto 和 TestCaseEdgeDto 结构
修改内容:
-
新增 DTO 类:
- TestCaseNodeDataDto:节点数据DTO,包含步骤ID、步骤名称、步骤类型、描述、图标等
- TestCaseNodePositionDto:节点位置DTO,包含X、Y坐标
- TestCaseEdgeStyleDto:连线样式DTO,包含描边颜色、描边宽度
- TestCaseEdgeDataDto:连线数据DTO,包含条件信息
-
TestCaseNodeDto 增强:
- 新增字段:
Type:节点类型(如 "testStep")Position:节点位置(TestCaseNodePositionDto)Data:节点数据(TestCaseNodeDataDto)Selected:是否被选中PositionAbsolute:绝对位置Dragging:是否正在拖拽
- 兼容性字段:保留原有字段,确保向后兼容
- 新增字段:
-
TestCaseEdgeDto 增强:
- 新增字段:
Source:源节点IDSourceHandle:源连接点Target:目标节点IDTargetHandle:目标连接点Type:连线类型Animated:是否动画Style:连线样式(TestCaseEdgeStyleDto)Data:连线数据(TestCaseEdgeDataDto)
- 兼容性字段:保留原有字段,确保向后兼容
- 新增字段:
-
技术特性:
- ReactFlow 兼容:新增字段与 ReactFlow 数据结构完全兼容
- JSON 序列化:支持直接序列化为 ReactFlow 所需的 JSON 格式
- 向后兼容:保留原有字段,确保现有代码不受影响
- 类型安全:使用强类型 DTO,避免运行时错误
-
数据结构示例:
{ "nodes": [ { "id": "node-1755654432101", "type": "testStep", "position": { "x": 360, "y": 30 }, "data": { "stepId": "e2192f5a-1582-47e9-92be-c676679418da", "stepName": "StartStep", "stepType": 1, "stepTypeName": "Start", "description": "Mapping_Start", "icon": "play-circle" }, "width": 95, "height": 30, "selected": false, "positionAbsolute": { "x": 360, "y": 30 }, "dragging": false } ], "edges": [ { "source": "node-1755654432101", "sourceHandle": "bottom", "target": "node-1755654436065", "targetHandle": "top", "id": "edge-1755654470705", "type": "smoothstep", "animated": false, "style": { "stroke": "#3b82f6", "strokeWidth": 2 }, "data": { "condition": "default" } } ] } -
设计原则:
- 前端兼容:确保与 ReactFlow 前端组件完全兼容
- 数据完整性:支持完整的节点和连线信息
- 扩展性:支持未来功能扩展
- 性能优化:避免不必要的数据转换
修改时间:
2025-01-19
修改原因:
用户需要 TestCaseNodeDto 和 TestCaseEdgeDto 与 ReactFlow 前端组件完全兼容,支持完整的节点和连线数据结构,包括位置、样式、数据等字段,确保前端能够正确显示和操作测试用例流程。
2025-01-19 - TestCaseFlow Queries功能实现
修改文件:
X1.Application/Features/TestCaseFlow/Queries/GetTestCaseFlows/- 获取TestCaseFlow列表查询X1.Application/Features/TestCaseFlow/Queries/GetTestCaseFlowById/- 根据ID获取TestCaseFlow详情查询X1.Presentation/Controllers/TestCaseFlowController.cs- TestCaseFlow控制器
修改内容:
-
GetTestCaseFlows查询功能:
- 查询类:
GetTestCaseFlowsQuery- 支持搜索、类型过滤、启用状态过滤、分页 - 响应类:
GetTestCaseFlowsResponse- 包含分页信息和TestCaseFlow列表 - 处理器:
GetTestCaseFlowsQueryHandler- 调用仓储获取分页数据并映射为DTO
- 查询类:
-
GetTestCaseFlowById查询功能:
- 查询类:
GetTestCaseFlowByIdQuery- 根据testCaseId获取详情 - 响应类:
GetTestCaseFlowByIdResponse- 包含完整的流程信息、节点和连线数据 - 处理器:
GetTestCaseFlowByIdQueryHandler- 组装TestCaseFlow、TestCaseNode、TestCaseEdge数据
- 查询类:
-
TestCaseFlowController控制器:
- 列表接口:
GET /api/testcaseflow- 获取测试用例流程列表,支持搜索和分页 - 详情接口:
GET /api/testcaseflow/{id}- 获取测试用例流程详情,包含节点和连线 - 完整日志:详细的日志记录和错误处理
- 列表接口:
-
数据组装特性:
- 列表查询:直接返回TestCaseFlow数据,不包含节点和连线
- 详情查询:组装完整的流程信息,包括所有节点和连线数据
- 性能优化:使用仓储的
GetTestCaseFlowWithDetailsAsync方法一次性获取所有数据
-
技术特性:
- CQRS模式:查询和命令分离,使用MediatR进行消息传递
- 分页支持:支持搜索、过滤、分页功能
- 数据完整性:详情查询包含完整的流程结构信息
- 错误处理:完整的异常处理和日志记录
修改时间:
2025-01-19
修改原因:
用户需要为TestCaseFlow实现Queries功能,包括获取列表和根据testCaseId获取详情,详情查询需要组装TestCaseNode和TestCaseEdge数据,为前端界面查看详情提供完整的数据支持。
2024-12-19 - 移除无意义的 StepTypeName 字段
修改文件:
X1.Application/Features/TestCaseFlow/Queries/GetTestCaseFlowById/GetTestCaseFlowByIdResponse.csX1.Application/Features/TestCaseFlow/Queries/GetTestCaseFlowById/GetTestCaseFlowByIdQueryHandler.cs
修改内容:
-
移除 TestCaseNodeDataDto 中的 StepTypeName 字段:
- 删除了
public string StepTypeName { get; set; } = null!;字段 - 该字段被认为是无意义的,因为已经有
StepType字段存储步骤类型的枚举值
- 删除了
-
移除 GetStepTypeName 方法:
- 删除了
GetStepTypeName私有方法 - 该方法用于将枚举值转换为字符串名称,但不再需要
- 删除了
-
更新数据映射逻辑:
- 在
MapNodesToReactFlowFormatAsync方法中移除了对StepTypeName字段的赋值 - 简化了节点数据映射逻辑
- 在
技术影响:
- 代码简化:移除了冗余的字段和方法
- 性能优化:减少了不必要的方法调用和字符串转换
- 维护性提升:减少了代码复杂度,提高了可维护性
- 数据一致性:避免了
StepType和StepTypeName之间可能的不一致问题
前端兼容性:
- 前端代码需要相应更新,移除对
stepTypeName字段的依赖 - 如果需要步骤类型名称,可以通过
stepType枚举值在前端进行转换
2024-12-19 - 移除前端代码中的 stepTypeName 字段
修改文件:
X1.WebUI/src/services/testcaseService.tsX1.WebUI/src/services/teststepsService.tsX1.WebUI/src/pages/testcases/ReactFlowDesigner.tsxX1.WebUI/src/pages/testcases/TestStepsPanel.tsx
修改内容:
-
testcaseService.ts:
- 从
TestCaseNodeData接口中移除了stepTypeName: string;字段
- 从
-
teststepsService.ts:
- 从
TestStep接口中移除了stepTypeName: string;字段
- 从
-
ReactFlowDesigner.tsx:
- 从
FlowNode类型定义中移除了stepTypeName: string;字段 - 移除了调试信息中对
stepTypeName的引用 - 在创建新节点时移除了对
step.stepTypeName的赋值
- 从
-
TestStepsPanel.tsx:
- 将显示
step.stepTypeName的地方改为根据step.stepType枚举值显示中文名称 - 使用条件判断:1=开始,2=结束,3=处理,4=判断
- 将显示
技术影响:
- 前后端一致性:前端代码与后端 API 返回的数据结构保持一致
- 代码简化:移除了冗余的字段,减少了数据传输量
- 维护性提升:减少了需要维护的字段数量
- 类型安全:避免了前后端字段不匹配的问题
用户体验:
- 显示优化:在 TestStepsPanel 中直接显示中文的步骤类型名称,用户体验更好
- 数据一致性:确保前端显示的数据与后端存储的数据完全一致
2025-01-19 - TestCaseFlow 空引用警告修复和连线样式类型优化
修改文件:
X1.Application/Features/TestCaseFlow/Commands/CreateTestCaseFlow/CreateTestCaseFlowCommandHandler.cs- 修复空引用警告X1.Application/Features/TestCaseFlow/Commands/CreateTestCaseFlow/CreateTestCaseFlowCommand.cs- 优化连线样式类型
修改内容:
-
空引用警告修复:
- 问题:在
CreateTestCaseFlowCommandHandler中,ValidateUserAuthentication方法返回的OperationResult<string>可能为空 - 解决方案:使用空合并操作符
??确保传递给CreateFailure方法的参数不为空 - 修改代码:
return OperationResult<CreateTestCaseFlowResponse>.CreateFailure(errorMessages ?? new List<string>());
- 问题:在
-
连线样式类型优化:
- 问题:
Style属性被定义为object?类型,但在CreateEdgesAsync方法中使用edgeData.Style?.ToString()来转换 - 解决方案:将
Style属性明确为string?类型,符合 JSON 字符串格式的实际用途 - 修改代码:
- 问题:
-
连线类型必填验证:
- 在
EdgeData类中将Type属性设为必填:[Required(ErrorMessage = "连线类型不能为空")] - 在验证逻辑中添加对
Type的验证:if (string.IsNullOrWhiteSpace(edge.Type)) - 在创建连线时移除默认值逻辑:
edgeType: edgeData.Type(不再使用?? "straight")
- 在
-
验证器提取:
- 创建了
CreateTestCaseFlowCommandValidator验证器类 - 将
ValidateRequest方法从CreateTestCaseFlowCommandHandler中提取出来 - 使用静态方法
Validate进行验证,便于复用和测试 - 保持原有的验证逻辑和错误消息不变
- 创建了
-
设计原则:
- 单一职责:验证器专注于参数验证,处理器专注于业务逻辑
- 可复用性:验证器可以在其他地方复用
- 可测试性:独立的验证器更容易进行单元测试
- 代码组织:更好的代码结构和职责分离
修改时间:
2025-01-19
修改原因:
用户要求确保连线类型是必填项,界面不能传空值。同时要求将验证逻辑提取到单独的验证器类中,提高代码的可维护性和可测试性。
2025-01-19 - TestCaseFlowController 删除功能添加和接口返回类型统一
修改文件:
X1.Application/Features/TestCaseFlow/Commands/DeleteTestCaseFlow/DeleteTestCaseFlowCommand.cs- 新增删除命令X1.Application/Features/TestCaseFlow/Commands/DeleteTestCaseFlow/DeleteTestCaseFlowCommandHandler.cs- 新增删除命令处理器X1.Presentation/Controllers/TestCaseFlowController.cs- 添加删除端点和统一返回类型
修改内容:
-
删除命令实现:
- 创建了
DeleteTestCaseFlowCommand类,包含流程ID参数 - 创建了
DeleteTestCaseFlowCommandHandler处理器,实现删除逻辑 - 包含用户认证验证、流程存在性检查、删除操作和事务提交
- 创建了
-
控制器接口统一:
- 参考
TerminalServicesController的返回方式,将所有方法返回类型改为OperationResult<T> - 移除了
IActionResult和BadRequest/Ok等 HTTP 状态码处理 - 直接返回
OperationResult<T>对象,让框架自动处理 HTTP 状态码
- 参考
-
删除端点添加:
- 添加了
DELETE /api/testcaseflow/{id}端点 - 包含完整的日志记录和错误处理
- 返回删除操作的结果
- 添加了
-
技术特性:
- 一致性:与
TerminalServicesController保持相同的接口返回模式 - 简化:移除了手动的 HTTP 状态码处理,让框架自动处理
- 完整性:删除功能包含完整的业务逻辑验证和错误处理
- 一致性:与
API 端点示例:
DELETE /api/testcaseflow/{id}
Authorization: Bearer {token}
响应格式:
{
"isSuccess": true,
"data": true,
"errorMessages": null
}
修改时间:
2025-01-19
修改原因:
用户要求添加删除功能到 TestCaseFlowController,并参考 TerminalServicesController 的接口返回方式,统一使用 OperationResult<T> 返回类型,不使用 IActionResult。
2025-01-19 - TestCaseFlow Application层实现
修改文件:
X1.Application/Features/TestCaseFlow/Commands/CreateTestCaseFlow/CreateTestCaseFlowCommand.cs- 创建测试用例流程命令X1.Application/Features/TestCaseFlow/Commands/CreateTestCaseFlow/CreateTestCaseFlowResponse.cs- 创建测试用例流程响应X1.Application/Features/TestCaseFlow/Commands/CreateTestCaseFlow/CreateTestCaseFlowCommandHandler.cs- 创建测试用例流程命令处理器
修改内容:
-
CreateTestCaseFlowCommand 命令类:
- 实现了
IRequest<OperationResult<CreateTestCaseFlowResponse>>接口 - 包含完整的验证特性:
[Required]、[MaxLength]等 - 支持所有必要字段:名称、描述、类型、启用状态、视口坐标等
- 提供合理的默认值,如视口坐标和启用状态
- 实现了
-
CreateTestCaseFlowResponse 响应类:
- 包含完整的流程信息返回
- 支持类型枚举转换为字符串显示
- 包含审计信息:创建时间、创建人等
-
CreateTestCaseFlowCommandHandler 命令处理器:
- 遵循CQRS模式,使用MediatR框架
- 完整的参数验证和业务逻辑验证
- 用户认证验证
- 名称重复性检查
- 使用领域实体的Create工厂方法
- 完整的错误处理和日志记录
- 事务管理(通过UnitOfWork)
-
设计原则:
- 参考TerminalServices模式:完全按照TerminalServices的设计规则实现
- CQRS架构:命令和查询分离
- 领域驱动设计:使用领域实体的工厂方法
- 依赖注入:通过构造函数注入依赖
- 日志记录:完整的操作日志和错误日志
- 错误处理:统一的错误处理和响应格式
-
技术特性:
- 支持异步操作
- 完整的取消令牌支持
- 统一的OperationResult响应格式
- 详细的验证错误信息
- 事务性操作保证
修改时间:
2025-01-19
修改原因:
用户要求在X1.Application.Features中实现TestCaseFlow的功能,参考TerminalServices的设计规则,先完成创建功能。为测试用例流程管理提供完整的Application层支持,包括命令、响应和处理器实现。
修复记录:
- 编译错误修复:修复了
TestCaseFlow.Create方法调用时的命名空间解析问题,使用完全限定的类型名称X1.Domain.Entities.TestCase.TestCaseFlow.Create来解决编译器无法找到Create方法的问题。
2025-01-19 - TestCaseNode 和 TestCaseEdge 数据集成
- 命令扩展:在
CreateTestCaseFlowCommand中添加了NodeData和EdgeDataDTO类,支持节点和连线数据的传输 - 处理器增强:在
CreateTestCaseFlowCommandHandler中添加了ITestCaseNodeRepository和ITestCaseEdgeRepository依赖注入 - 节点创建:实现了
CreateNodesAsync方法,支持批量创建测试用例节点,包括位置、尺寸、状态等属性 - 连线创建:实现了
CreateEdgesAsync方法,支持批量创建测试用例连线,包括源节点、目标节点、类型、样式等属性 - 验证增强:添加了对节点和连线数据的验证逻辑,确保数据完整性
- 日志记录:增强了日志记录,包含节点数量和连线数量的统计信息
- 事务管理:确保节点和连线的创建在同一个事务中完成,保证数据一致性
2024-12-19 - StartDeviceRuntimeCommandHandler 问题分析与修复
问题描述
API响应中 isSuccess: true 但 summary.failureCount: 1,导致前端误判操作成功。
问题分析
通过分析代码发现以下潜在问题区域:
- 网络配置构建阶段:在
BuildNetworkConfigurationRequests方法中,设备可能因为配置验证失败而被过滤掉 - 网络启动阶段:在
StartNetworksInParallelAsync方法中,网络启动失败 - 设备运行时处理阶段:设备运行时不存在或更新失败
实施的修复
-
增强日志记录:
- 在
BuildNetworkConfigurationRequests中添加详细的警告日志 - 在
StartNetworksInParallelAsync中增强错误日志和统计信息 - 在设备运行时处理循环中添加调试日志
- 在
-
关键修复 - isSuccess 字段逻辑:
- 问题根源:
OperationResult<T>.IsSuccess属性仅基于ErrorMessages是否为空 - 解决方案:在
Handle方法中根据业务逻辑判断成功/失败 - 只有当所有设备都成功启动时才返回
CreateSuccess - 否则返回
CreateFailure并包含详细错误信息
- 问题根源:
-
配置验证逻辑优化:
- 问题:原来的配置验证过于严格,要求同时有RAN配置和完整的IMS+核心网配置
- 优化:改为更灵活的验证逻辑,允许只有RAN配置或只有IMS配置的设备通过
- 验证规则:
- 至少需要RAN配置 或者 IMS配置(不要求同时有核心网配置)
- 如果有IMS配置但没有核心网配置,记录警告但不阻止设备启动
- 提供更详细的配置状态日志,便于调试
- 影响:减少因配置不完整而被错误跳过的设备数量
修改原因
- 解决前端误判问题
- 提供更好的调试信息
- 确保数据一致性
2024-12-19 - 已实施更改的评估分析
评估结果:所有更改都应该保留
1. 网络配置构建阶段优化 ✅
- 状态: 已优化,无需撤回
- 改进内容:
- 增强的日志记录,记录被跳过设备的具体原因
- 过滤逻辑透明化,包括重复组合、缺少配置、验证失败等情况
- 统计信息记录,显示原始请求数 vs 有效请求数
- 价值: 提供更好的调试信息和透明度
2. 网络启动阶段优化 ✅
- 状态: 已优化,无需撤回
- 改进内容:
- 增强的错误日志,包含具体错误信息
- 统计信息记录,显示总请求数、成功数、失败数
- 失败设备详细记录
- 价值: 提供关键的调试信息,帮助快速定位网络启动失败原因
3. 设备运行时处理阶段优化 ✅
- 状态: 已优化,无需撤回
- 改进内容:
- 跳过逻辑:只处理网络启动成功的设备
- 详细日志:记录状态更新过程
- 调试信息:记录设备运行时当前状态
- 价值: 确保数据一致性,避免对失败设备的无效处理
4. isSuccess 字段逻辑修复 ✅
- 状态: 已修复,这是核心问题
- 问题:
isSuccess: true但failureCount: 1导致前端误判 - 解决方案: 根据业务逻辑判断成功/失败
- 价值: 解决了前端误判的根本问题
建议的监控指标
- 网络配置构建成功率:
有效请求数 / 原始请求数 - 网络启动成功率:
成功设备数 / 有效请求数 - 整体成功率:
成功设备数 / 总请求数
日志分析建议
当出现失败时,可通过以下日志快速定位问题:
- 网络配置构建阶段:查看被跳过设备的原因
- 网络启动阶段:查看具体错误信息
- 设备运行时处理:查看状态更新过程
结论
所有实施的更改都是有价值的改进,不仅解决了核心的 isSuccess 误判问题,还提供了更好的调试能力和数据一致性。不建议撤回任何更改。
2025年修改记录
2025-01-19 - TestCaseEdge 和 TestCaseNode Repositories 完善
修改文件:
X1.Domain/Repositories/TestCase/ITestCaseEdgeRepository.cs- 创建 TestCaseEdge 仓储接口X1.Domain/Repositories/TestCase/ITestCaseNodeRepository.cs- 创建 TestCaseNode 仓储接口X1.Infrastructure/Repositories/TestCase/TestCaseEdgeRepository.cs- 创建 TestCaseEdge 仓储实现X1.Infrastructure/Repositories/TestCase/TestCaseNodeRepository.cs- 创建 TestCaseNode 仓储实现X1.Infrastructure/DependencyInjection.cs- 注册新的仓储服务
修改内容:
-
TestCaseEdge 仓储接口创建:
- 创建了
ITestCaseEdgeRepository接口,继承自IBaseRepository<TestCaseEdge> - 定义了完整的业务方法,包括基本的 CRUD 操作和特定的业务查询
- 支持测试用例连线的完整生命周期管理
- 创建了
-
主要业务方法:
- 基本操作:
AddTestCaseEdgeAsync、UpdateTestCaseEdge、DeleteTestCaseEdgeAsync - 批量操作:
DeleteByTestCaseIdAsync(根据测试用例ID删除所有连线) - 查询操作:
GetAllTestCaseEdgesAsync、GetTestCaseEdgeByIdAsync、GetByTestCaseIdAsync - 特定查询:
GetBySourceNodeIdAsync、GetByTargetNodeIdAsync、GetByEdgeIdAsync - 验证操作:
EdgeIdExistsAsync、ExistsByTestCaseIdAsync
- 基本操作:
-
TestCaseNode 仓储接口创建:
- 创建了
ITestCaseNodeRepository接口,继承自IBaseRepository<TestCaseNode> - 定义了完整的业务方法,包括基本的 CRUD 操作和特定的业务查询
- 支持测试用例节点的完整生命周期管理
- 创建了
-
主要业务方法:
- 基本操作:
AddTestCaseNodeAsync、UpdateTestCaseNode、DeleteTestCaseNodeAsync - 批量操作:
DeleteByTestCaseIdAsync(根据测试用例ID删除所有节点) - 查询操作:
GetAllTestCaseNodesAsync、GetTestCaseNodeByIdAsync、GetByTestCaseIdAsync - 排序查询:
GetByTestCaseIdOrderedAsync(按序号排序) - 特定查询:
GetByNodeIdAsync、GetByStepIdAsync、GetByTestCaseIdAndSequenceAsync - 验证操作:
NodeIdExistsAsync、ExistsByTestCaseIdAsync、SequenceExistsAsync - 统计操作:
GetMaxSequenceNumberAsync(获取最大序号)
- 基本操作:
-
TestCaseEdge 仓储实现创建:
- 创建了
TestCaseEdgeRepository实现类,继承自BaseRepository<TestCaseEdge> - 实现了
ITestCaseEdgeRepository接口的所有方法 - 使用 CQRS 模式,分离命令和查询操作
- 提供完整的日志记录和错误处理
- 创建了
-
TestCaseNode 仓储实现创建:
- 创建了
TestCaseNodeRepository实现类,继承自BaseRepository<TestCaseNode> - 实现了
ITestCaseNodeRepository接口的所有方法 - 使用 CQRS 模式,分离命令和查询操作
- 提供完整的日志记录和错误处理
- 创建了
-
依赖注入配置:
- 在
X1.Infrastructure/DependencyInjection.cs中注册新的仓储服务 - 添加了
ITestCaseEdgeRepository和ITestCaseNodeRepository的注册 - 确保控制器能够正确注入所需的仓储服务
- 在
-
技术特性:
- CQRS 模式:使用
ICommandRepository和IQueryRepository分离读写操作 - 异步支持:所有方法都支持异步操作和取消令牌
- 简洁实现:与现有仓储实现保持一致的简洁风格
- 性能优化:支持批量操作和条件过滤
- CQRS 模式:使用
-
设计原则:
- DDD 原则:遵循领域驱动设计,仓储专注于数据访问
- 单一职责:每个方法专注于特定功能
- 可扩展性:支持未来功能扩展
- 一致性:与现有仓储实现(如
CaseStepConfigRepository)保持一致的架构模式
-
命名空间规范:
- 使用
X1.Domain.Repositories.TestCase命名空间 - 使用
X1.Infrastructure.Repositories.TestCase命名空间 - 与项目整体架构保持一致
- 使用
修改时间:
2025-01-19
修改原因:
用户要求完善 TestCaseEdge 和 TestCaseNode 的 Repositories,参考 ICaseStepConfigRepository 的结构,为测试用例节点和连线管理提供完整的数据访问层支持,包括基本的 CRUD 操作和特定的业务查询功能。
2025-01-19 - TestCaseFlow 实体 Create 和 Update 方法实现
修改文件:
X1.Domain/Entities/TestCase/TestCaseTestFlow.cs - 为TestCaseFlow实体添加Create和Update方法
修改内容:
-
Create 静态工厂方法:
- 添加了
Create静态方法,用于创建新的测试用例流程 - 支持所有必要参数:名称、类型、创建人、描述、启用状态、视口坐标等
- 自动设置ID、创建时间、更新时间等审计字段
- 视口坐标参数(viewportX、viewportY、viewportZoom)由界面传入,不提供默认值
- 添加了
-
Update 实例方法:
- 添加了
Update方法,用于更新测试用例流程 - 支持更新所有字段:名称、类型、描述、启用状态、视口坐标等
- 自动更新
UpdatedAt和UpdatedBy审计字段 - 使用可选参数,只更新传入的字段
- 添加了
-
设计原则:
- 遵循DDD(领域驱动设计)原则
- 使用工厂方法模式创建实体实例
- 通过业务方法修改实体状态
- 确保审计信息的完整性
-
技术特性:
- 类型安全的参数验证
- 完整的审计信息管理
- 灵活的更新机制
- 与CaseStepConfig实体保持一致的实现模式
- 视口坐标由界面传入,确保数据的准确性
修改时间:
2025-01-19
修改原因:
用户要求TestCaseFlow实体提供与CaseStepConfig实体相同的Create和Update方法,确保实体创建和更新的标准化和一致性。同时根据用户反馈,视口坐标参数应该由界面传入,不提供默认值。
2025-01-19 - TestCaseNode 和 TestCaseEdge 实体 Create 和 Update 方法实现
修改文件:
X1.Domain/Entities/TestCase/TestCaseNode.cs- 为TestCaseNode实体添加Create和Update方法X1.Domain/Entities/TestCase/TestCaseEdge.cs- 为TestCaseEdge实体添加Create和Update方法
修改内容:
-
TestCaseNode 实体 Create 和 Update 方法:
- Create 静态工厂方法:
- 添加了
Create静态方法,用于创建新的测试用例节点 - 支持所有必要参数:测试用例ID、节点ID、执行序号、位置坐标、步骤配置ID、尺寸、状态等
- 自动设置ID,不包含审计字段(继承自Entity而非AuditableEntity)
- 提供合理的默认值,如宽度、高度、选中状态等
- 添加了
- Update 实例方法:
- 添加了
Update方法,用于更新测试用例节点 - 支持更新所有字段:测试用例ID、节点ID、执行序号、位置坐标、步骤配置ID、尺寸、状态等
- 使用可选参数,只更新传入的字段
- 提供完整的参数验证和错误处理
- 添加了
- Create 静态工厂方法:
-
TestCaseEdge 实体 Create 和 Update 方法:
- Create 静态工厂方法:
- 添加了
Create静态方法,用于创建新的测试用例连线 - 支持所有必要参数:测试用例ID、连线ID、源节点ID、目标节点ID、连线类型、条件、动画、样式等
- 自动设置ID,不包含审计字段(继承自Entity而非AuditableEntity)
- 提供合理的默认值,如连线类型、动画状态等
- 添加了
- Update 实例方法:
- 添加了
Update方法,用于更新测试用例连线 - 支持更新所有字段:测试用例ID、连线ID、源节点ID、目标节点ID、连线类型、条件、动画、样式等
- 使用可选参数,只更新传入的字段
- 提供完整的参数验证和错误处理
- 添加了
- Create 静态工厂方法:
-
设计原则:
- 遵循DDD(领域驱动设计)原则
- 使用工厂方法模式创建实体实例
- 通过业务方法修改实体状态
- 与TestCaseFlow实体保持一致的实现模式
- 注意TestCaseNode和TestCaseEdge继承自Entity而非AuditableEntity,因此不包含审计字段
-
技术特性:
- 类型安全的参数验证
- 灵活的更新机制,支持部分字段更新
- 与TestCaseFlow实体保持一致的实现模式
- 提供合理的默认值,简化创建过程
- 完整的参数验证和错误处理
修改时间:
2025-01-19
修改原因:
用户要求TestCaseNode和TestCaseEdge实体提供与TestCaseFlow实体相同的Create和Update方法,确保所有测试用例相关实体的创建和更新过程标准化和一致性。
2025-01-19 - TestCaseNode Update 方法不可修改字段优化
修改文件:
X1.Domain/Entities/TestCase/TestCaseNode.cs - 优化TestCaseNode实体的Update方法
修改内容:
-
Update 方法参数优化:
- 移除了不可修改的字段参数:
testCaseId、nodeId、stepId - 这些字段作为实体的标识符和关联关系,在更新时不应该被修改
- 保留了可修改的字段:执行序号、位置坐标、尺寸、状态等
- 移除了不可修改的字段参数:
-
设计原则:
- 遵循实体不可变性原则,保护关键标识符
- 确保数据完整性和一致性
- 防止意外修改关联关系
-
技术特性:
- 更安全的更新机制
- 明确的字段修改边界
- 符合DDD设计原则
修改时间:
2025-01-19
修改原因:
用户反馈指出TestCaseNode的Update方法中,testCaseId、nodeId和stepId这些字段不应该被修改,因为它们是不可变的标识符和关联关系。
2025-01-19 - TestCaseEdge Update 方法不可修改字段优化
修改文件:
X1.Domain/Entities/TestCase/TestCaseEdge.cs - 优化TestCaseEdge实体的Update方法
修改内容:
-
Update 方法参数优化:
- 移除了不可修改的字段参数:
testCaseId、edgeId - 这些字段作为实体的标识符和关联关系,在更新时不应该被修改
- 保留了可修改的字段:源节点ID、目标节点ID、连线类型、条件、动画状态、样式等
- 移除了不可修改的字段参数:
-
设计原则:
- 遵循实体不可变性原则,保护关键标识符
- 确保数据完整性和一致性
- 防止意外修改关联关系
- 与TestCaseNode保持一致的不可变性设计
-
技术特性:
- 更安全的更新机制
- 明确的字段修改边界
- 符合DDD设计原则
- 与TestCaseNode实体的Update方法保持一致的实现模式
修改时间:
2025-01-19
修改原因:
用户反馈指出TestCaseEdge的Update方法中,testCaseId和edgeId这些字段不应该被修改,因为它们是不可变的标识符和关联关系。
2025-01-19 - GetTestCaseFlowByIdQueryHandler 修复
修改文件:
X1.Application/Features/TestCaseFlow/Queries/GetTestCaseFlowById/GetTestCaseFlowByIdQueryHandler.cs
修改内容:
-
依赖注入增强:
- 添加
ICaseStepConfigRepository依赖,用于获取步骤配置信息 - 在构造函数中注入
caseStepConfigRepository参数
- 添加
-
数据映射重构:
- 新增
MapNodesToReactFlowFormatAsync方法:将TestCaseNode实体映射为 ReactFlow 兼容的TestCaseNodeDto - 新增
MapEdgesToReactFlowFormatAsync方法:将TestCaseEdge实体映射为 ReactFlow 兼容的TestCaseEdgeDto - 新增
GetStepTypeName方法:将步骤类型枚举转换为可读的字符串名称
- 新增
-
节点映射逻辑:
- 根据
StepId获取对应的CaseStepConfig信息 - 构建 ReactFlow 格式的
Position和Data对象 - 设置默认的
Type为 "testStep" - 处理
PositionAbsolute的可空逻辑 - 保留所有原有字段用于向后兼容
- 根据
-
连线映射逻辑:
- 解析存储的 JSON 样式字符串为
TestCaseEdgeStyleDto对象 - 设置默认的
SourceHandle和TargetHandle为 "bottom" 和 "top" - 设置默认的
Type为 "smoothstep" - 构建
Data对象包含条件信息 - 保留所有原有字段用于向后兼容
- 解析存储的 JSON 样式字符串为
-
错误处理:
- 添加 JSON 解析异常处理,在解析失败时使用默认样式
- 添加空值检查和默认值处理
技术特性:
- 异步处理:使用异步方法获取步骤配置信息,提高性能
- 数据完整性:确保所有必要字段都有合理的默认值
- 向后兼容:保留原有字段映射,确保现有功能不受影响
- 类型安全:使用强类型映射,避免运行时错误
- 错误恢复:在数据不完整时提供合理的默认值
映射关系:
TestCaseNode.NodeId→TestCaseNodeDto.IdTestCaseNode.PositionX/Y→TestCaseNodeDto.Position.X/YCaseStepConfig信息 →TestCaseNodeDto.DataTestCaseEdge.EdgeId→TestCaseEdgeDto.IdTestCaseEdge.SourceNodeId/TargetNodeId→TestCaseEdgeDto.Source/TargetTestCaseEdge.Style(JSON) →TestCaseEdgeDto.Style(对象)
修改时间:
2025-01-19
修改原因:
用户要求修复 GetTestCaseFlowByIdQueryHandler 来正确映射现有后端数据到新的 ReactFlow 兼容的 DTO 格式,同时保持向后兼容性,确保前端能够正确接收和显示测试用例流程数据。
2025-01-19 - GetTestCaseFlowByIdQueryHandler 简化映射
修改文件:
X1.Application/Features/TestCaseFlow/Queries/GetTestCaseFlowById/GetTestCaseFlowByIdQueryHandler.cs
修改内容:
-
移除向后兼容字段:
- 在
MapNodesToReactFlowFormatAsync方法中移除了所有向后兼容字段 - 在
MapEdgesToReactFlowFormatAsync方法中移除了所有向后兼容字段 - 只保留 ReactFlow 前端需要的格式字段
- 在
-
节点映射简化:
- 只输出前端需要的 ReactFlow 格式:
Id,Type,Position,Data,Width,Height,Selected,PositionAbsolute,Dragging - 移除了:
TestCaseId,NodeId,SequenceNumber,PositionX,PositionY,IsSelected,PositionAbsoluteX,PositionAbsoluteY,IsDragging
- 只输出前端需要的 ReactFlow 格式:
-
连线映射简化:
- 只输出前端需要的 ReactFlow 格式:
Id,Source,SourceHandle,Target,TargetHandle,Type,Animated,Style,Data - 移除了:
TestCaseId,EdgeId,SourceNodeId,TargetNodeId,EdgeType,Condition,IsAnimated,StyleJson
- 只输出前端需要的 ReactFlow 格式:
技术特性:
- 前端优先:直接输出 ReactFlow 前端需要的格式
- 数据精简:移除不必要的向后兼容字段,减少数据传输量
- 格式统一:确保输出格式与前端期望的 JSON 结构完全一致
前端格式示例:
{
"nodes": [
{
"id": "node-1755654432101",
"type": "testStep",
"position": { "x": 360, "y": 30 },
"data": {
"stepId": "e2192f5a-1582-47e9-92be-c676679418da",
"stepName": "StartStep",
"stepType": 1,
"stepTypeName": "Start",
"description": "Mapping_Start",
"icon": "play-circle"
},
"width": 95,
"height": 30,
"selected": false,
"positionAbsolute": { "x": 360, "y": 30 },
"dragging": false
}
]
}
修改时间:
2025-01-19
修改原因:
用户要求简化映射逻辑,直接输出前端需要的 ReactFlow 格式,不需要向后兼容字段,确保数据格式与前端期望的 JSON 结构完全一致。
2025-01-19 - GetTestCaseFlowsQueryHandler 参数修复
修改文件:
X1.Application/Features/TestCaseFlow/Queries/GetTestCaseFlows/GetTestCaseFlowsQueryHandler.cs
修改内容:
-
参数名称修复:
- 将
GetPagedFlowsAsync方法调用中的searchTerm参数名修正为name - 确保参数名称与
ITestCaseFlowRepository接口定义一致
- 将
-
类型转换修复:
- 添加了
TestFlowType枚举的解析逻辑 - 将
string?类型的request.Type转换为TestFlowType?类型 - 使用
Enum.TryParse进行安全的类型转换,避免解析失败
- 添加了
-
错误处理:
- 添加了空值检查,确保在
request.Type为空时不会进行解析 - 使用安全的枚举解析,避免无效类型值导致的异常
- 添加了空值检查,确保在
技术特性:
- 类型安全:确保参数类型与仓储接口定义完全匹配
- 错误处理:添加了安全的枚举解析,避免运行时异常
- 参数一致性:修正了参数名称,确保与接口定义一致
修复的问题:
GetPagedFlowsAsync方法调用时参数名称不匹配TestFlowType枚举类型转换缺失- 可能导致搜索功能无法正常工作
修改时间:
2025-01-19
修改原因:
用户反馈 GetTestCaseFlowsQueryHandler 中的 searchTerm 参数传递有问题,需要修复参数名称和类型转换问题,确保搜索功能正常工作。
2025-01-19 - TestCaseFlow 仓储模式实现和审计字段修复
修改文件:
X1.Domain/Repositories/TestCase/ITestCaseFlowRepository.cs- 创建 TestCaseFlow 仓储接口X1.Infrastructure/Repositories/TestCase/TestCaseFlowRepository.cs- 创建 TestCaseFlow 仓储实现并修复审计字段访问问题
修改内容:
-
TestCaseFlow 仓储接口创建:
- 创建了
ITestCaseFlowRepository接口,继承自IBaseRepository<TestCaseFlow> - 定义了完整的业务方法,包括基本的 CRUD 操作和特定的业务查询
- 支持测试用例流程的完整生命周期管理
- 创建了
-
主要业务方法:
- 基本操作:
AddTestCaseFlowAsync、UpdateTestCaseFlow、DeleteTestCaseFlowAsync - 状态管理:
EnableTestCaseFlowAsync、DisableTestCaseFlowAsync - 查询操作:
GetAllTestCaseFlowsAsync、GetTestCaseFlowByIdAsync、GetByNameAsync - 分类查询:
GetByTypeAsync、GetEnabledFlowsAsync - 详细查询:
GetTestCaseFlowWithDetailsAsync(包含节点和连线) - 验证操作:
NameExistsAsync - 分页查询:
GetPagedFlowsAsync(支持名称、类型、启用状态过滤)
- 基本操作:
-
TestCaseFlow 仓储实现创建:
- 创建了
TestCaseFlowRepository实现类,继承自BaseRepository<TestCaseFlow> - 实现了
ITestCaseFlowRepository接口的所有方法 - 使用 CQRS 模式,分离命令和查询操作
- 提供完整的日志记录和错误处理
- 创建了
-
审计字段修复:
- 问题:修复了 "属性或索引器'AuditableEntity.UpdatedAt'不能用在此上下文中,因为 set 访问器不可访问" 的编译错误
- 解决方案:参考
CaseStepConfigRepository的实现模式,简化仓储实现 - 修改内容:
- 移除了
ICurrentUserService依赖注入 - 移除了复杂的
SetCreated()和SetUpdated()方法调用 - 简化了
AddTestCaseFlowAsync方法,直接调用CommandRepository.AddAsync - 简化了
UpdateTestCaseFlow方法,直接调用CommandRepository.Update - 在
EnableTestCaseFlowAsync和DisableTestCaseFlowAsync方法中直接设置UpdatedAt = DateTime.UtcNow - 移除了详细的日志记录,保持与
CaseStepConfigRepository一致的简洁风格
- 移除了
-
技术特性:
- CQRS 模式:使用
ICommandRepository和IQueryRepository分离读写操作 - 异步支持:所有方法都支持异步操作和取消令牌
- 简洁实现:与现有仓储实现保持一致的简洁风格
- 性能优化:支持分页查询和条件过滤
- CQRS 模式:使用
-
分页查询功能:
- 支持按名称、类型、启用状态进行条件过滤
- 使用动态查询条件构建,支持可选参数
- 返回总记录数和分页数据
- 支持自定义页码和每页大小
-
详细查询功能:
GetTestCaseFlowWithDetailsAsync方法支持包含节点和连线的完整查询- 使用 Entity Framework 的
Include方法加载关联数据 - 适用于需要完整流程信息的场景
-
设计原则:
- DDD 原则:遵循领域驱动设计,仓储专注于数据访问
- 单一职责:每个方法专注于特定功能
- 可扩展性:支持未来功能扩展
- 一致性:与现有仓储实现(如
CaseStepConfigRepository)保持一致的架构模式
-
命名空间规范:
- 使用
X1.Domain.Repositories.TestCase命名空间 - 使用
X1.Infrastructure.Repositories.TestCase命名空间 - 与项目整体架构保持一致
- 使用
修改时间:
2025-01-19
修改原因:
用户要求在 CellularManagement.Domain.Repositories.TestCase 命名空间中实现 TestCaseFlow 的仓储模式,为测试用例流程管理提供完整的数据访问层支持,包括基本的 CRUD 操作和特定的业务查询功能。同时修复了审计字段访问权限问题,参考 CaseStepConfigRepository 的实现模式,简化仓储实现,确保与现有代码风格保持一致。
2025-01-19 - TestCaseTestFlow 命名规范和viewport属性修复
修改文件:
X1.Domain/Entities/TestCase/TestCaseTestFlow.cs- 重命名为TestCaseFlow并添加viewport属性X1.Domain/Entities/TestCase/TestCaseEdge.cs- 完善TestCaseEdge实体X1.Infrastructure/Context/AppDbContext.cs- 添加TestCaseFlow相关DbSet配置X1.Infrastructure/Configurations/TestCase/TestCaseFlowConfiguration.cs- 创建TestCaseFlow配置类X1.Infrastructure/Configurations/TestCase/TestCaseNodeConfiguration.cs- 创建TestCaseNode配置类X1.Infrastructure/Configurations/TestCase/TestCaseEdgeConfiguration.cs- 创建TestCaseEdge配置类
修改内容:
-
TestCaseTestFlow重命名为TestCaseFlow:
- 将类名从
TestCaseTestFlow改为TestCaseFlow,更符合命名规范 - 继承自
Entity基类,添加主键Id字段 - 添加viewport属性字段:ViewportX、ViewportY、ViewportZoom
- 设置viewport默认值:x=40.54057017483274, y=21.183463943747256, zoom=1.1367874248827994
- 将类名从
-
TestCaseEdge实体完善:
- 继承自
Entity基类,添加主键Id字段 - 添加完整的连线属性:TestCaseId、EdgeId、SourceNodeId、TargetNodeId
- 添加连线配置:EdgeType、Condition、IsAnimated、Style
- 添加导航属性关联TestCaseFlow
- 继承自
-
数据库配置:
- 在AppDbContext中添加TestCaseFlow、TestCaseNode、TestCaseEdge的DbSet配置
- 创建完整的Entity Framework配置类
- 配置表名规范:tb_testcaseflow、tb_testcasenode、tb_testcaseedge
- 添加完整的字段映射、索引和关系配置
-
技术特性:
- 命名规范:使用更简洁的TestCaseFlow命名
- 主键支持:所有实体都继承Entity基类,支持主键Id
- viewport支持:添加视口坐标和缩放级别属性
- 关系配置:完整的实体关系映射和级联删除配置
- 索引优化:为常用查询字段添加数据库索引
-
设计原则:
- 命名简洁:TestCaseFlow比TestCaseTestFlow更简洁明了
- 功能完整:支持完整的测试用例流程管理
- 数据完整性:通过外键关系和级联删除确保数据一致性
- 性能优化:通过索引配置提高查询性能
修改时间:
2025-01-19
修改原因:
用户要求修复TestCaseTestFlow的命名规范问题,主要是测试用例流程表,并添加viewport属性字段(x、y、zoom),以支持ReactFlow设计器的视口状态保存和恢复。
2025-01-19 - AdbOperationConfiguration数据库配置优化
修改文件:
X1.Infrastructure/Configurations/Terminal/AdbOperationConfiguration.cs - 修复Path字段的数据库约束
修改内容:
-
问题描述:
- 当前AdbOperationConfiguration中Path字段设置为
IsRequired(),与业务逻辑不一致 - 根据AdbOperation实体的业务规则,Path字段只有在UseAbsolutePath为true时才必填
- 数据库约束应该与业务逻辑保持一致
- 当前AdbOperationConfiguration中Path字段设置为
-
解决方案:
- 将Path字段的数据库约束从
IsRequired()改为IsRequired(false) - 更新字段注释,明确说明Path字段的必填条件
- 确保数据库层约束与业务层验证逻辑一致
- 将Path字段的数据库约束从
-
具体修改:
- 数据库约束:
IsRequired()→IsRequired(false) - 注释更新:添加"(当启用绝对路径时必填)"说明
- 业务一致性:与AdbOperation实体中的条件验证保持一致
- 数据库约束:
-
技术特性:
- 数据完整性:数据库约束与业务规则一致
- 灵活性:允许Path字段为空,符合业务需求
- 文档清晰:注释明确说明字段的使用条件
- 架构一致性:基础设施层与领域层保持一致
-
修改代码:
// 路径字段 builder.Property(x => x.Path) .IsRequired(false) // 改为允许为空 .HasMaxLength(500) .HasComment("命令执行时所依赖的路径(当启用绝对路径时必填)"); -
设计原则:
- 业务驱动:数据库设计服务于业务需求
- 一致性:各层之间的约束保持一致
- 灵活性:支持不同的业务场景
- 可维护性:清晰的注释便于理解和维护
修改时间:
2025-01-19
修改原因:
确保AdbOperationConfiguration的数据库约束与AdbOperation实体的业务逻辑保持一致,Path字段只有在UseAbsolutePath为true时才必填。
2025-01-19 - AdbOperations Commands层DeviceId修改限制
修改文件:
X1.Application/Features/AdbOperations/Commands/UpdateAdbOperation/UpdateAdbOperationCommand.cs - 移除DeviceId属性
X1.Application/Features/AdbOperations/Commands/UpdateAdbOperation/UpdateAdbOperationCommandHandler.cs - 修复DeviceId处理逻辑
修改内容:
-
问题描述:
- UpdateAdbOperationCommand中仍然包含DeviceId属性,与实体层业务规则不一致
- UpdateAdbOperationCommandHandler仍然传递DeviceId参数给实体的Update方法
- 应用层与领域层的业务规则不一致,可能导致混淆
-
解决方案:
- 从UpdateAdbOperationCommand中移除DeviceId属性
- 修改UpdateAdbOperationCommandHandler,使用现有实体的DeviceId值
- 确保应用层与领域层的业务规则保持一致
-
具体修改:
- 命令对象:移除DeviceId属性,明确表示Update操作不涉及DeviceId修改
- 处理器逻辑:使用
existingOperation.DeviceId而不是request.DeviceId - 日志优化:移除日志中的DeviceId参数,避免误导
- 业务一致性:应用层与领域层规则完全一致
-
技术特性:
- 架构一致性:应用层与领域层业务规则保持一致
- 数据完整性:防止通过应用层意外修改DeviceId
- 代码清晰:明确表达Update操作的业务约束
- 错误预防:在应用层就避免传递不允许修改的参数
-
修改代码:
// UpdateAdbOperationCommand.cs - 移除DeviceId属性 public class UpdateAdbOperationCommand : IRequest<OperationResult<UpdateAdbOperationResponse>> { public string Id { get; set; } = string.Empty; // DeviceId属性已移除 public string Command { get; set; } = string.Empty; // ... 其他属性 } // UpdateAdbOperationCommandHandler.cs - 修复DeviceId处理 existingOperation.Update( existingOperation.DeviceId, // 使用现有的DeviceId,不允许修改 request.Command, // ... 其他参数 ); -
设计原则:
- 单一职责:Update命令只处理允许修改的字段
- 业务驱动:应用层设计服务于业务规则
- 防御性编程:在多个层面防止数据不一致
- 可维护性:清晰的代码结构便于理解和维护
修改时间:
2025-01-19
修改原因:
确保AdbOperations Commands层的Update操作与AdbOperation实体的业务规则保持一致,防止DeviceId被意外修改,维护数据完整性和业务逻辑的一致性。
2025-01-19 - AdbOperation实体DeviceId更新限制
修改文件:
X1.Domain/Entities/Terminal/AdbOperation.cs - 限制Update方法中DeviceId的修改
修改内容:
-
问题描述:
- 当前Update方法允许修改DeviceId,这可能导致数据一致性问题
- 用户要求AdbOperation的Update操作不能修改deviceId
- 需要添加业务规则限制DeviceId的修改
-
解决方案:
- 在Update方法中添加DeviceId修改验证
- 比较传入的deviceId参数与当前DeviceId属性值
- 如果不匹配则抛出异常,阻止更新操作
- 移除DeviceId的赋值操作,保持原有值
-
具体修改:
- 验证逻辑:添加
if (!string.Equals(DeviceId, deviceId.Trim(), StringComparison.OrdinalIgnoreCase))检查 - 错误处理:抛出
ArgumentException("设备ID不允许修改", nameof(deviceId)) - 赋值移除:注释掉
DeviceId = deviceId.Trim();并添加说明注释
- 验证逻辑:添加
-
技术特性:
- 数据完整性:确保DeviceId在更新操作中保持不变
- 业务规则:实现业务逻辑约束
- 错误提示:提供明确的错误信息
- 大小写不敏感:使用
StringComparison.OrdinalIgnoreCase进行比较
-
验证逻辑:
// 设备ID不允许修改 if (!string.Equals(DeviceId, deviceId.Trim(), StringComparison.OrdinalIgnoreCase)) throw new ArgumentException("设备ID不允许修改", nameof(deviceId)); // 不更新DeviceId,保持原有值 // DeviceId = deviceId.Trim(); // 已移除 -
设计原则:
- 数据一致性:防止关键字段被意外修改
- 业务约束:符合ADB操作的业务规则
- 用户友好:提供清晰的错误提示
- 安全性:防止数据完整性问题
修改时间:
2025-01-19
修改原因:
用户要求AdbOperation的Update操作不能修改deviceId,确保数据一致性和业务规则的正确性。
2025-01-19 - AdbOperation实体路径验证优化
修改文件:
X1.Domain/Entities/Terminal/AdbOperation.cs - 优化路径验证逻辑,实现条件验证
修改内容:
-
问题描述:
- 当前路径验证逻辑过于严格,无论是否启用绝对路径都要求路径不能为空
- 用户希望只有当
UseAbsolutePath启用时,Path字段才不能为空 - 需要实现条件验证逻辑
-
解决方案:
- 修改
Create和Update方法中的路径验证逻辑 - 添加条件判断:只有当
useAbsolutePath为true时,才验证路径不能为空 - 更新错误消息以明确说明验证条件
- 修改
-
具体修改:
- Create方法:将
if (string.IsNullOrWhiteSpace(path))改为if (useAbsolutePath && string.IsNullOrWhiteSpace(path)) - Update方法:将
if (string.IsNullOrWhiteSpace(path))改为if (useAbsolutePath && string.IsNullOrWhiteSpace(path)) - 错误消息:从"路径不能为空"改为"启用绝对路径时,路径不能为空"
- Create方法:将
-
技术特性:
- 条件验证:根据业务逻辑实现智能验证
- 用户体验:允许在非绝对路径模式下路径为空
- 业务逻辑:符合ADB操作的业务需求
- 错误提示:提供更明确的错误信息
-
验证逻辑:
// 修改前 if (string.IsNullOrWhiteSpace(path)) throw new ArgumentException("路径不能为空", nameof(path)); // 修改后 if (useAbsolutePath && string.IsNullOrWhiteSpace(path)) throw new ArgumentException("启用绝对路径时,路径不能为空", nameof(path)); -
设计原则:
- 业务导向:验证逻辑符合实际业务需求
- 用户友好:提供清晰的错误提示
- 灵活性:支持不同的路径使用模式
- 一致性:在创建和更新操作中保持一致的验证逻辑
修改时间:
2025-01-19
修改原因:
用户反馈需要实现条件验证,只有当启用绝对路径时路径字段才不能为空,提高业务逻辑的灵活性。
2025-01-19 - ADB操作Drawer布局优化
修改文件:
X1.WebUI/src/pages/adb-operations/AdbOperationDrawer.tsx - 优化Drawer布局,添加滚动条支持
修改内容:
-
问题描述:
- 当ADB命令列表增加时,Drawer布局无法正常显示所有内容
- 缺少滚动条支持,用户体验不佳
- 布局结构需要优化以支持动态内容
-
解决方案:
- 重新设计布局结构,将内容分为固定区域和可滚动区域
- 为命令列表区域添加独立的滚动条
- 使用Flexbox布局确保各区域正确显示
-
具体修改:
- 固定区域:设备选择、操作描述、ADB路径、选项设置等
- 可滚动区域:命令列表区域,支持垂直滚动
- 布局优化:使用
flex-shrink-0和flex-1控制区域大小
-
技术特性:
- 响应式滚动:命令列表区域支持垂直滚动
- 固定布局:重要操作区域保持固定位置
- 视觉优化:添加背景色和边框改善视觉效果
- 用户体验:支持任意数量的命令添加
-
布局结构:
// 固定头部 <DrawerHeader className="flex-shrink-0"> // 内容区域 <DrawerContent className="flex flex-col flex-1 min-h-0 p-0 overflow-hidden"> // 固定区域:设备选择 <div className="flex-shrink-0 p-4 pb-2"> // 可滚动区域:命令列表 <div className="flex-1 min-h-0 flex flex-col px-4"> <div className="flex-1 overflow-y-auto"> <div className="space-y-3 pr-2"> // 固定区域:其他表单字段 <div className="flex-shrink-0 p-4 pt-2"> // 固定底部 <DrawerFooter className="flex-shrink-0"> -
设计原则:
- 空间利用:合理分配固定和可滚动区域
- 操作便利:重要操作区域保持可见
- 扩展性:支持动态添加命令
- 一致性:与其他Drawer组件保持一致的交互模式
修改时间:
2025-01-19
修改原因:
用户反馈当添加多个ADB命令时,Drawer布局无法正常显示,需要添加滚动条优化布局。
2025-01-19 - ADB操作Drawer空白优化
修改文件:
X1.WebUI/src/pages/adb-operations/AdbOperationDrawer.tsx - 优化布局空白,减少多余间距
修改内容:
-
问题描述:
- 用户反馈布局存在"多余空白"问题
- 内边距和外边距重叠导致空间浪费
- 滚动区域与固定区域间距过大
-
解决方案:
- 重新调整内边距和外边距结构
- 优化各区域之间的间距
- 减少不必要的空白区域
-
具体修改:
- DrawerContent:移除
p-4,改为p-0 - 设备选择区域:使用
p-4 pb-2替代mb-4 - 命令列表区域:使用
px-4替代整体内边距 - 滚动区域:移除
pr-2,改为在内容区域使用pr-2 - 其他表单字段:使用
p-4 pt-2替代mt-4
- DrawerContent:移除
-
技术特性:
- 紧凑布局:减少不必要的空白区域
- 精确控制:为不同区域设置合适的内边距
- 视觉优化:改善整体布局的紧凑性
- 用户体验:提供更好的空间利用率
-
布局优化:
// 优化前:存在多余空白 <DrawerContent className="p-4"> <div className="mb-4">设备选择</div> <div className="flex-1"> <div className="overflow-y-auto pr-2"> <div className="mt-4">其他字段</div> // 优化后:紧凑布局 <DrawerContent className="p-0"> <div className="p-4 pb-2">设备选择</div> <div className="flex-1 px-4"> <div className="overflow-y-auto"> <div className="pr-2"> <div className="p-4 pt-2">其他字段</div> -
设计原则:
- 空间效率:最大化利用可用空间
- 视觉平衡:保持适当的间距和层次
- 操作便利:确保重要操作区域易于访问
- 一致性:与其他组件保持一致的间距规范
修改时间:
2025-01-19
修改原因:
用户反馈布局存在"多余空白"问题,需要优化间距结构,提供更紧凑的布局。
2025-01-19 - ADB操作路径字段条件验证
修改文件:
X1.WebUI/src/pages/adb-operations/AdbOperationDrawer.tsx - 实现ADB路径字段的条件验证
修改内容:
-
问题描述:
- 用户反馈ADB路径字段的验证逻辑需要优化
- 当前路径字段始终为可选,但实际使用中需要条件验证
- 当选择"使用绝对路径"时,路径字段应该为必填
-
解决方案:
- 实现条件验证逻辑,根据"使用绝对路径"选项决定路径字段是否必填
- 动态显示必填标识符
- 添加错误提示和样式
-
具体修改:
- 验证逻辑:在
validateForm函数中添加条件验证 - UI标识:动态显示红色星号标识必填字段
- 错误处理:添加路径字段的错误提示和样式
- 用户体验:提供清晰的验证反馈
- 验证逻辑:在
-
技术特性:
- 条件验证:根据
useAbsolutePath状态决定验证规则 - 动态UI:必填标识符根据条件动态显示
- 错误反馈:提供明确的错误信息和视觉提示
- 表单完整性:确保数据验证的准确性
- 条件验证:根据
-
验证逻辑:
// 验证ADB路径 - 只有在使用绝对路径时才必填 if (formData.useAbsolutePath && !formData.path.trim()) { newErrors.path = '使用绝对路径时必须指定ADB路径'; } -
UI优化:
<Label htmlFor="path" className="text-sm font-medium"> ADB路径 {formData.useAbsolutePath && <span className="text-red-500">*</span>} </Label> <Input className={errors.path ? 'border-red-500 focus:border-red-500' : ''} /> {errors.path && ( <p className="text-xs text-red-500">{errors.path}</p> )} -
设计原则:
- 逻辑一致性:验证规则与业务逻辑保持一致
- 用户友好:提供清晰的必填标识和错误提示
- 视觉反馈:使用颜色和样式区分不同状态
- 数据完整性:确保提交数据的有效性
修改时间:
2025-01-19
修改原因:
用户反馈ADB路径字段需要条件验证,只有在选择"使用绝对路径"时才应该为必填字段。
2025-01-19 - ADB操作Drawer单命令布局优化
修改文件:
X1.WebUI/src/pages/adb-operations/AdbOperationDrawer.tsx - 优化单命令情况下的布局空白
修改内容:
-
问题描述:
- 用户反馈"当添加命令默认一个就会剩余很多空白"
- 当只有一个命令时,命令列表区域占用过多空间
- 布局在单命令情况下不够紧凑,存在大量空白区域
-
解决方案:
- 根据命令数量动态调整布局结构
- 当命令数量较少时,不使用弹性布局占用剩余空间
- 只有当命令数量超过2个时才启用滚动区域
-
具体修改:
- 条件布局:根据
commands.length > 2决定是否使用弹性布局 - 动态类名:使用模板字符串动态设置CSS类名
- 滚动优化:只在需要时启用滚动条
- 空间利用:减少单命令情况下的空白区域
- 条件布局:根据
-
技术特性:
- 自适应布局:根据内容数量调整布局策略
- 条件渲染:动态应用CSS类名
- 空间优化:减少不必要的空白区域
- 用户体验:提供更紧凑的单命令布局
-
布局逻辑:
// 命令列表区域 - 根据命令数量决定布局 <div className={`px-4 ${commands.length > 2 ? 'flex-1 min-h-0 flex flex-col' : ''}`}> // 命令列表区域 - 根据命令数量决定是否可滚动 <div className={commands.length > 2 ? 'flex-1 overflow-y-auto' : ''}> <div className={`space-y-3 ${commands.length > 2 ? 'pr-2' : ''}`}> -
设计原则:
- 内容驱动:布局根据实际内容数量调整
- 空间效率:避免不必要的空白区域
- 渐进增强:随着内容增加自动启用滚动
- 视觉平衡:保持整体布局的协调性
修改时间:
2025-01-19
修改原因:
用户反馈当只有一个命令时,布局存在大量空白区域,需要优化单命令情况下的布局紧凑性。
2025-01-19 - 抽屉组件内间距优化
修改文件:
X1.WebUI/src/pages/ran-configurations/RANConfigurationDrawer.tsx- 为抽屉内容添加内间距X1.WebUI/src/pages/network-stack-configs/NetworkStackConfigDrawer.tsx- 为抽屉内容添加内间距X1.WebUI/src/pages/ims-configurations/IMSConfigurationDrawer.tsx- 为抽屉内容添加内间距X1.WebUI/src/pages/core-network-configs/CoreNetworkConfigDrawer.tsx- 为抽屉内容添加内间距
修改内容:
-
问题描述:
- RANConfigurationDrawer 抽屉内容太贴着边缘,缺少适当的内间距
- 用户体验不佳,内容显示过于紧凑
-
解决方案:
- 为
DrawerContent组件添加p-6类名 - 提供 24px 的内边距,改善视觉效果和用户体验
- 为
-
具体修改:
// 修改前 <DrawerContent className="flex flex-col space-y-4 flex-1 overflow-y-auto"> // 修改后 <DrawerContent className="flex flex-col space-y-4 flex-1 overflow-y-auto p-4"> -
技术特性:
- 响应式设计:内间距适配不同屏幕尺寸
- 视觉优化:提供更好的内容层次和可读性
- 用户体验:改善表单内容的显示效果
- 一致性:与其他抽屉组件保持一致的样式
-
设计原则:
- 空间利用:合理利用抽屉空间,避免内容过于紧凑
- 视觉层次:通过内间距建立清晰的内容层次
- 用户友好:提供舒适的视觉体验
修改时间:
2025-01-19
修改原因:
用户反馈 RANConfigurationDrawer 内容太贴着边缘,需要添加适当的内间距来改善视觉效果和用户体验。
2025-01-19 - ReactFlowDesigner 导入导出功能实现
修改文件:
X1.WebUI/src/pages/testcases/ReactFlowDesigner.tsx - 实现Flow数据的导入和导出功能
修改内容:
-
导入功能实现:
- 文件选择:添加了文件选择按钮,支持选择JSON格式的Flow文件
- 数据验证:验证导入文件是否包含有效的nodes和edges数据
- 状态恢复:导入成功后恢复nodes、edges和viewport状态
- 错误处理:提供详细的错误提示和异常处理
- 重复导入:支持重复导入同一文件
-
导出功能实现:
- 数据收集:收集当前的nodes、edges和viewport状态
- 元数据添加:添加版本、导出时间、描述等元数据信息
- 文件生成:生成格式化的JSON文件
- 自动下载:自动触发文件下载,文件名包含日期信息
- 资源清理:自动清理临时创建的URL对象
-
UI组件设计:
- 工具栏按钮:在工具栏中添加导入和导出按钮
- 图标设计:使用SVG图标,导入使用向下箭头,导出使用向上箭头
- 悬停效果:导入按钮使用蓝色主题,导出按钮使用绿色主题
- 响应式设计:按钮适配不同屏幕尺寸
-
成功提示功能:
- 通知组件:添加导入成功通知,显示在右上角
- 动画效果:使用slideIn动画,从右侧滑入
- 自动关闭:提供关闭按钮,点击后隐藏通知
- 状态管理:使用useState管理通知显示状态
-
样式设计:
- 按钮样式:使用现代化的按钮设计,包含图标和文字
- 通知样式:使用绿色主题的成功通知样式
- 动画效果:添加CSS动画和过渡效果
- 响应式布局:适配不同屏幕尺寸
-
技术特性:
- 文件处理:使用FileReader API读取本地文件
- 数据序列化:使用JSON.stringify格式化数据
- Blob处理:使用Blob和URL.createObjectURL创建下载链接
- 状态管理:使用React Hooks管理组件状态
- 错误处理:完整的异常捕获和用户提示
-
数据格式:
{ "nodes": [...], "edges": [...], "viewport": {...}, "metadata": { "name": "Test Case Flow", "version": "1.0", "exportDate": "2025-01-19T10:30:00.000Z", "description": "Exported test case flow data" } } -
用户体验:
- 直观操作:点击按钮即可导入或导出Flow数据
- 即时反馈:操作结果立即显示,成功或失败都有明确提示
- 文件命名:导出文件自动包含日期信息,便于管理
- 错误提示:详细的错误信息帮助用户理解问题
修改时间:
2025-01-19
修改原因:
用户需要在测试用例流程设计器中实现Flow数据的导入和导出功能,以便保存和恢复流程设计,提高工作效率和数据管理能力。
修复记录:
- 2025-01-19:修复了导出功能中的Hook调用错误,将
useReactFlow()调用移到组件顶层,避免在普通函数中调用Hook
2025-01-19 - AdbOperation数据库迁移应用
修改文件:
数据库 tb_adboperations 表结构
修改内容:
-
执行状态:
- ✅ 迁移文件创建:成功
- ✅ 数据库更新:成功
- ✅ 数据库结构与代码配置:完全一致
-
数据库变更:
- 表名:
tb_adboperations - 字段名:
Path - 变更类型:从
NOT NULL改为NULL(允许为空) - 注释更新:从"命令执行时所依赖的路径"改为"命令执行时所依赖的路径(当启用绝对路径时必填)"
- 表名:
-
执行的SQL命令:
ALTER TABLE tb_adboperations ALTER COLUMN "Path" DROP NOT NULL; COMMENT ON COLUMN tb_adboperations."Path" IS '命令执行时所依赖的路径(当启用绝对路径时必填)'; -
迁移历史:
- 迁移ID:
20250820020118_UpdateAdbOperationPathNullable - 已记录到
__EFMigrationsHistory表
- 迁移ID:
-
业务影响:
- 现在
Path字段在UseAbsolutePath为false时可以为空 - 在
UseAbsolutePath为true时仍然必填(由业务逻辑验证) - 数据库约束与领域层业务规则完全一致
- 现在
-
技术验证:
- 构建成功:
Build succeeded - 数据库连接正常:配置验证通过
- 迁移执行无错误:所有SQL命令成功执行
- 构建成功:
修改时间:
2025-01-19
修改原因:
应用之前创建的数据库迁移,将AdbOperationConfiguration中Path字段的IsRequired约束变更同步到数据库,确保数据库结构与代码配置完全一致,支持Path字段在UseAbsolutePath为false时可以为空的业务需求。
2025-01-19 - TestCaseEdge Type字段必填验证
修改文件:
X1.Application/Features/TestCaseFlow/Commands/CreateTestCaseFlow/CreateTestCaseFlowCommand.cs- 将EdgeData的Type字段改为必填X1.Application/Features/TestCaseFlow/Commands/CreateTestCaseFlow/CreateTestCaseFlowCommandHandler.cs- 添加Type字段验证并移除默认值逻辑
修改内容:
-
EdgeData Type字段必填化:
- 问题描述:用户反馈
edgeType: edgeData.Type ?? "straight"中的Type字段应该是必填项,界面不能传空 - 解决方案:将Type字段从可选改为必填,添加验证逻辑,移除默认值处理
- 问题描述:用户反馈
-
CreateTestCaseFlowCommand.cs 修改:
- 字段类型:将
Type从string?改为string - 验证特性:添加
[Required(ErrorMessage = "连线类型不能为空")]验证特性 - 默认值:移除默认值,设置为
null!
- 字段类型:将
-
CreateTestCaseFlowCommandHandler.cs 修改:
- 验证逻辑:在
ValidateRequest方法中添加对edge.Type的空值验证 - 创建逻辑:在
CreateEdgesAsync方法中移除?? "straight"默认值逻辑 - 错误处理:提供明确的错误信息:"连线类型不能为空"
- 验证逻辑:在
-
技术特性:
- 数据验证:确保连线类型字段不为空
- 用户友好:提供清晰的错误提示信息
- 业务逻辑:符合业务需求,连线类型必须明确指定
- 类型安全:使用强类型验证,避免运行时错误
-
设计原则:
- 数据完整性:确保必要字段不为空
- 用户体验:提供明确的验证反馈
- 业务规则:符合测试用例流程设计的业务需求
- 代码一致性:与项目中其他必填字段的处理方式保持一致
修改时间:
2025-01-19
修改原因:
用户要求确保TestCaseEdge的Type字段是必填项,界面不能传空值,需要添加相应的验证逻辑并移除默认值处理,确保数据完整性和业务逻辑的正确性。
2025-01-16 测试用例列表组件创建
修改文件:
X1.WebUI/src/pages/testcases/TestCasesListView.tsx- 创建测试用例列表组件X1.WebUI/src/routes/AppRouter.tsx- 更新路由配置
修改内容:
-
问题描述:
testcases/list和testcases/create路由都使用了同一个组件TestCasesViewTestCasesView是一个流程设计器,用于创建测试用例testcases/list应该显示一个测试用例列表的表格
-
解决方案:
- 创建了新的
TestCasesListView组件,专门用于显示测试用例列表 - 更新路由配置,让
testcases/list使用新的列表组件 - 保持
testcases/create继续使用原有的流程设计器组件
- 创建了新的
-
TestCasesListView组件特性:
- 表格显示:使用表格组件显示测试用例列表
- 搜索功能:支持按测试用例名称或描述搜索
- 状态管理:显示测试用例的状态(激活、停用、草稿)
- 优先级管理:显示测试用例的优先级(高、中、低)
- 操作按钮:提供查看、编辑、删除操作
- 创建按钮:提供创建新测试用例的快捷入口
-
路由配置更新:
- 添加了
TestCasesListView组件的lazy加载导入 - 更新
testcases/list路由使用新的列表组件 - 保持
testcases/create路由使用原有的流程设计器组件
- 添加了
-
技术特性:
- 使用React + TypeScript开发
- 采用shadcn/ui组件库
- 支持响应式设计
- 完整的错误处理和用户反馈
- 模拟数据展示功能
-
UI设计:
- 现代化的表格设计
- 状态徽章和优先级徽章
- 搜索工具栏
- 操作按钮图标化
- 响应式布局
修改时间:
2025-01-16
修改原因:
解决测试用例列表和创建页面显示相同内容的问题,为测试用例管理提供正确的列表视图和创建视图分离。
2025-01-19 - 测试用例列表抽屉查看功能增强
修改文件:
X1.WebUI/src/pages/testcases/TestCasesListView.tsx - 添加抽屉式流程查看功能
修改内容:
-
功能增强:
- 添加了抽屉组件来显示测试用例流程详情
- 集成了ReactFlow来可视化显示流程节点和连线
- 实现了异步加载流程数据的功能
- 添加了加载状态指示器
-
抽屉组件特性:
- Drawer组件:使用shadcn/ui的Drawer组件
- 高度设置:抽屉高度为90vh,提供充足的显示空间
- 标题显示:显示测试用例名称和描述
- 响应式设计:适配不同屏幕尺寸
-
ReactFlow集成:
- 流程可视化:使用ReactFlow显示流程节点和连线
- 控件支持:包含Controls(缩放、适应视图)、Background(网格背景)、MiniMap(小地图)
- 自动适应:使用fitView自动适应视图大小
- 样式设置:使用灰色背景提升视觉效果
-
数据转换功能:
- 节点转换:将后端节点数据转换为ReactFlow节点格式
- 连线转换:将后端连线数据转换为ReactFlow连线格式
- 位置信息:支持节点的位置、尺寸、选中状态等信息
- 样式支持:支持连线的样式、动画、数据等属性
-
状态管理:
- 选中状态:
selectedTestCase存储当前选中的测试用例详情 - 抽屉状态:
drawerOpen控制抽屉的打开/关闭 - 加载状态:
flowLoading控制流程数据的加载状态 - 错误处理:完整的错误处理和用户提示
- 选中状态:
-
用户体验优化:
- 加载指示器:显示旋转动画和"加载流程中..."提示
- 按钮状态:查看按钮在加载时禁用,防止重复点击
- 错误提示:当加载失败时显示"未找到流程数据"
- 交互反馈:点击查看按钮立即显示加载状态
-
技术实现:
- 异步加载:使用
handleViewTestCase函数异步加载流程详情 - 数据获取:调用
testcaseService.getTestCaseFlowById获取完整流程数据 - 类型安全:使用TypeScript确保类型安全
- 组件导入:正确导入ReactFlow相关组件和样式
- 异步加载:使用
-
流程数据处理:
const getReactFlowData = () => { if (!selectedTestCase) return { nodes: [], edges: [] }; const nodes: Node[] = selectedTestCase.nodes.map(node => ({ id: node.id, type: node.type || 'default', position: node.position, data: node.data, width: node.width, height: node.height, selected: node.selected, positionAbsolute: node.positionAbsolute, dragging: node.dragging })); const edges: Edge[] = selectedTestCase.edges.map(edge => ({ id: edge.id, source: edge.source, sourceHandle: edge.sourceHandle, target: edge.target, targetHandle: edge.targetHandle, type: edge.type || 'smoothstep', animated: edge.animated, style: edge.style, data: edge.data })); return { nodes, edges }; };
修改时间:
2025-01-19
修改原因:
用户要求在查看测试用例时采用抽屉方式显示流程,并加载处理流程数据,提供更好的用户体验和流程可视化能力。
2025-01-19 - 测试用例详情抽屉组件提取
修改文件:
X1.WebUI/src/components/testcases/TestCaseDetailDrawer.tsx- 创建独立的测试用例详情抽屉组件X1.WebUI/src/pages/testcases/TestCasesListView.tsx- 重构使用独立抽屉组件
修改内容:
-
组件提取:
- 将测试用例详情抽屉功能从
TestCasesListView中提取为独立组件 - 创建了
TestCaseDetailDrawer组件,位于@/components/testcases/目录 - 实现了组件的复用性和代码累计
- 将测试用例详情抽屉功能从
-
TestCaseDetailDrawer组件特性:
- Props接口:定义了
testCaseId、open、onOpenChange三个属性 - 状态管理:内部管理
selectedTestCase、flowLoading、error状态 - 生命周期管理:使用
useEffect监听抽屉打开状态,自动加载数据 - 错误处理:完整的错误状态管理和重试功能
- Props接口:定义了
-
功能增强:
- 自动加载:抽屉打开时自动加载测试用例详情
- 状态清理:抽屉关闭时自动清理状态
- 错误重试:提供重试按钮,用户可以重新加载数据
- 加载指示器:显示旋转动画和加载提示
-
TestCasesListView重构:
- 简化状态:移除了
selectedTestCase、flowLoading等状态 - 简化逻辑:
handleViewTestCase函数简化为只设置ID和打开抽屉 - 组件使用:使用
<TestCaseDetailDrawer>组件替代原有的抽屉代码 - 代码减少:大幅减少了组件代码量,提高可维护性
- 简化状态:移除了
-
技术特性:
- 组件复用:抽屉组件可以在其他页面中复用
- 职责分离:列表页面专注于列表显示,抽屉组件专注于详情显示
- 类型安全:完整的TypeScript类型定义
- 错误边界:独立的错误处理,不影响主页面
-
用户体验优化:
- 响应式设计:抽屉高度为90vh,适配不同屏幕
- 加载反馈:清晰的加载状态指示
- 错误恢复:提供重试机制,提升用户体验
- 状态同步:抽屉状态与父组件完全同步
-
代码结构:
// TestCaseDetailDrawer.tsx interface TestCaseDetailDrawerProps { testCaseId: string | null; open: boolean; onOpenChange: (open: boolean) => void; } // TestCasesListView.tsx const [selectedTestCaseId, setSelectedTestCaseId] = useState<string | null>(null); const [drawerOpen, setDrawerOpen] = useState(false); const handleViewTestCase = (id: string) => { setSelectedTestCaseId(id); setDrawerOpen(true); }; -
设计原则:
- 单一职责:每个组件专注于特定功能
- 可复用性:抽屉组件可以在多个地方使用
- 可维护性:代码结构清晰,易于维护和扩展
- 性能优化:按需加载,减少不必要的渲染
修改时间:
2025-01-19
修改原因:
用户要求将测试用例详情抽屉提取为独立组件,实现代码累计和复用,提高代码的可维护性和组件的可复用性。
2025-01-19 - Drawer组件缺失导出修复
修改文件:
X1.WebUI/src/components/ui/drawer.tsx - 添加缺失的DrawerTitle和DrawerDescription组件
修改内容:
-
问题描述:
TestCaseDetailDrawer组件导入DrawerDescription和DrawerTitle时出现错误- 错误信息:
The requested module '/src/components/ui/drawer.tsx' does not provide an export named 'DrawerDescription' - drawer.tsx 文件中缺少这两个组件的定义和导出
-
解决方案:
- 在 drawer.tsx 中添加了
DrawerTitle组件 - 在 drawer.tsx 中添加了
DrawerDescription组件 - 为两个组件添加了完整的 TypeScript 接口定义
- 在 drawer.tsx 中添加了
-
DrawerTitle组件:
- 接口定义:
DrawerTitleProps包含children和className属性 - 样式设计:使用
text-lg font-semibold类名,提供标题样式 - HTML结构:使用
<h2>标签,符合语义化设计
- 接口定义:
-
DrawerDescription组件:
- 接口定义:
DrawerDescriptionProps包含children和className属性 - 样式设计:使用
text-sm text-muted-foreground类名,提供描述文本样式 - HTML结构:使用
<p>标签,符合语义化设计
- 接口定义:
-
技术特性:
- 类型安全:完整的 TypeScript 接口定义
- 样式一致性:使用
cn工具函数合并类名 - 可扩展性:支持自定义 className 属性
- 语义化:使用合适的 HTML 标签
-
组件结构:
interface DrawerTitleProps { children: React.ReactNode className?: string } export function DrawerTitle({ children, className }: DrawerTitleProps) { return ( <h2 className={cn("text-lg font-semibold", className)}> {children} </h2> ) } interface DrawerDescriptionProps { children: React.ReactNode className?: string } export function DrawerDescription({ children, className }: DrawerDescriptionProps) { return ( <p className={cn("text-sm text-muted-foreground", className)}> {children} </p> ) } -
设计原则:
- 一致性:与其他 Drawer 组件保持一致的接口设计
- 可复用性:组件可以在其他抽屉组件中复用
- 可维护性:清晰的代码结构和类型定义
- 用户体验:提供合适的默认样式
修改时间:
2025-01-19
修改原因:
修复 drawer.tsx 组件库中缺失的 DrawerTitle 和 DrawerDescription 组件导出,解决 TestCaseDetailDrawer 组件的导入错误问题。
2025-01-19 - TestCaseDetailDrawer 样式与 ReactFlowDesigner 保持一致
修改文件:
X1.WebUI/src/components/testcases/TestCaseDetailDrawer.tsx - 参考 ReactFlowDesigner 添加自定义节点样式
修改内容:
-
样式一致性要求:
- 用户要求 TestCaseDetailDrawer 中的 ReactFlow 样式与 ReactFlowDesigner 保持完全一致
- 需要添加自定义节点类型和视觉效果
-
自定义节点组件:
- TestStepNode 组件:完全复制 ReactFlowDesigner 中的自定义节点组件
- 图标组件:支持所有图标类型(Play、Square、GitBranch、Smartphone等)
- 节点样式:根据步骤类型显示不同的形状和颜色
- 连接点:根据节点类型显示不同的输入输出连接点
-
节点样式规则:
- 开始步骤 (type=1):圆形,蓝色主题,只有输出连接点
- 结束步骤 (type=2):圆形,红色主题,只有输入连接点
- 处理步骤 (type=3):矩形,绿色主题,有输入和输出连接点
- 判断步骤 (type=4):菱形,紫色主题,有输入和输出连接点
-
图标系统:
- 设备相关图标:蓝色背景(smartphone、phone、wifi等)
- 网络相关图标:绿色背景(network、activity)
- 控制相关图标:橙色背景(play-circle、stop-circle)
- 配置相关图标:紫色背景(settings、git-branch)
-
ReactFlow 配置:
- 节点类型:使用自定义
testStep节点类型 - 视图设置:默认缩放1.5,最小1倍,最大2倍
- 网格对齐:启用15x15网格对齐
- 控件:包含 Controls、Background、MiniMap
- 节点类型:使用自定义
-
技术特性:
- ReactFlowProvider:包装组件以支持 useReactFlow hook
- fitView:自动适应视图大小
- 延迟渲染:使用 setTimeout 确保节点正确渲染后再执行 fitView
- 状态管理:完整的加载、错误、数据状态管理
-
视觉效果:
- 选中状态:蓝色环形高亮
- 悬停效果:边框颜色变化
- 连接点:彩色圆形连接点,支持悬停效果
- 背景:灰色背景,与 ReactFlowDesigner 一致
-
组件结构:
// 自定义节点组件 const TestStepNode = ({ data, selected }: { data: any; selected?: boolean }) => { // 图标组件映射 const getIconComponent = (iconName: string) => { ... }; // 节点样式映射 const getNodeStyle = (stepType: number) => { ... }; // 图标背景色映射 const getIconBgColor = (iconName: string) => { ... }; // 渲染不同形状的节点 return ( <div className={`group relative transition-all duration-200`}> {/* 根据步骤类型渲染不同形状 */} {/* 根据步骤类型渲染不同连接点 */} </div> ); };
修改时间:
2025-01-19
修改原因:
用户要求 TestCaseDetailDrawer 中的 ReactFlow 样式与 ReactFlowDesigner 保持完全一致,确保查看模式下的流程显示与设计模式下的样式完全相同。
2025-01-19 - TestCaseDetailDrawer 移除小地图和调试数据映射
修改文件:
X1.WebUI/src/components/testcases/TestCaseDetailDrawer.tsx - 移除小地图组件并添加调试信息
修改内容:
-
移除小地图:
- 根据用户要求"不需要小地图",从 ReactFlow 组件中移除了
<MiniMap />组件 - 保留
<Controls />和<Background />组件
- 根据用户要求"不需要小地图",从 ReactFlow 组件中移除了
-
添加调试信息:
- 在
getReactFlowData函数中添加了console.log调试信息 - 输出原始节点数据和每个节点的处理过程
- 帮助诊断节点显示"Unknown"的问题
- 在
-
调试信息内容:
console.log('原始节点数据:', testCase.nodes); console.log('处理节点:', node); console.log('节点数据:', node.data); -
技术特性:
- 调试友好:添加详细的日志输出,便于问题诊断
- 用户需求响应:移除不需要的小地图组件
- 数据验证:通过日志验证数据映射是否正确
修改时间:
2025-01-19
修改原因:
- 用户明确要求"不需要小地图"
- 节点仍然显示"Unknown"问题需要进一步调试
- 需要验证数据映射是否正确工作
2025-01-19 - TestCaseDetailDrawer 增强调试和数据映射修复
修改文件:
X1.WebUI/src/components/testcases/TestCaseDetailDrawer.tsx - 增强调试信息并修复数据映射
修改内容:
-
增强调试信息:
- 在
getReactFlowData函数中添加了更详细的日志输出 - 添加了原始连线数据的日志输出
- 添加了节点位置信息的日志输出
- 在
TestStepNode组件中添加了数据接收的日志输出
- 在
-
修复数据映射:
- 使用可选链操作符
?.来安全访问数据字段 - 为所有数据字段提供默认值,防止 undefined 错误
- 为节点尺寸提供默认值(width: 150, height: 50)
- 为连线样式提供默认值
- 使用可选链操作符
-
数据安全处理:
// 节点数据安全处理 const nodeData = { stepId: node.data?.stepId || node.id, stepName: node.data?.stepName || 'Unknown', stepType: node.data?.stepType || 3, stepTypeName: node.data?.stepTypeName || '处理步骤', description: node.data?.description || '', icon: node.data?.icon || 'settings' }; // 连线数据安全处理 style: edge.style || { stroke: '#333', strokeWidth: 2 }, data: edge.data || {} -
调试信息内容:
- 原始节点数据和连线数据
- 每个节点的处理过程
- 节点位置信息
- 处理后的节点数据
- TestStepNode 组件接收到的数据
-
技术特性:
- 数据安全:使用可选链和默认值防止运行时错误
- 调试友好:详细的日志输出便于问题诊断
- 容错性:即使数据不完整也能正常显示
- 兼容性:与 ReactFlowDesigner 的数据结构保持一致
修改时间:
2025-01-19
修改原因:
- 节点仍然显示"Unknown"且没有连接
- 样式与 ReactFlowDesigner 完全不同
- 需要深入调试数据映射问题
- 确保数据安全处理,防止运行时错误
2025-01-16 StartTerminalServiceCommandHandler 代码优化
修改文件:
X1.Application/Features/TerminalServices/Commands/StartTerminalService/StartTerminalServiceCommandHandler.cs- 优化WebSocket连接创建逻辑
修改内容:
-
参数验证增强:
- 服务端点验证:检查
serviceEndpoint是否为空,避免空引用异常 - 服务编码验证:检查
existingService.ServiceCode是否为空,确保WebSocket客户端名称有效 - 用户信息验证:保持原有的用户ID验证逻辑
- 服务端点验证:检查
-
WebSocket连接创建优化:
- 请求参数完善:添加
HeartbeatInterval参数,设置为30秒心跳间隔 - 异常处理增强:使用 try-catch 包装WebSocket连接创建过程
- 响应验证详细化:
- 检查响应是否为null
- 检查响应成功状态
- 提供详细的错误信息
- 请求参数完善:添加
-
日志记录改进:
- 操作开始日志:记录WebSocket连接创建的详细信息
- 调试级别日志:记录WebSocket请求参数(客户端名称、连接地址、心跳间隔)
- 成功日志:记录连接创建成功的基本信息
- 错误日志:提供更详细的错误信息和上下文
-
错误处理严谨化:
- 空值检查:对所有关键参数进行空值验证
- 异常捕获:捕获WebSocket连接创建过程中的所有异常
- 错误消息:提供用户友好的错误消息,包含具体的错误原因
- 取消令牌支持:在WebSocket连接创建时传递取消令牌
-
代码结构优化:
- 方法提取:将WebSocket连接创建逻辑提取为独立的私有方法
CreateWebSocketConnectionAsync - 职责分离:主方法专注于业务流程控制,WebSocket连接创建逻辑独立封装
- 可读性提升:使用更清晰的变量命名和注释
- 维护性增强:便于后续功能扩展和问题排查
- 错误处理统一:统一的错误信息传递机制,正确处理
OperationResult<T>的ErrorMessages属性
- 方法提取:将WebSocket连接创建逻辑提取为独立的私有方法
-
技术特性:
- 异步操作:保持异步操作模式,支持取消令牌
- 资源管理:确保异常情况下的资源正确释放
- 性能优化:避免不必要的字符串操作和对象创建
- 安全性:增强输入验证,防止潜在的安全问题
修改时间:
2025-01-16
修改原因:
提高启动终端服务功能的代码质量和稳定性,增强错误处理能力,提供更好的用户体验和系统可维护性。
2025-01-15 X1.WebAPI 部署脚本优化
修改文件:
X1.WebAPI/publish.bat- 添加deploy.sh复制功能X1.WebAPI/deploy.sh- 创建优化的服务器端部署脚本
修改内容:
-
publish.bat脚本增强:
- 添加了自动复制
deploy.sh到发布目录的功能 - 现在会自动复制:Dockerfile、docker-deploy.md、deploy.sh
- 提供详细的复制状态反馈和错误提示
- 添加了自动复制
-
deploy.sh脚本特性:
- 彩色输出:不同级别的信息用不同颜色显示(INFO蓝色、SUCCESS绿色、WARNING黄色、ERROR红色)
- 详细日志:每个步骤都有详细的输出信息和状态反馈
- 错误处理:遇到错误立即停止并显示错误信息
- 健康检查:自动检查应用是否正常启动(最多等待30秒)
- 状态显示:显示容器状态、端口信息、镜像信息等
- 权限检查:自动设置正确的文件权限
- Docker检查:检查Docker安装状态和服务运行状态
-
部署流程优化:
- 文件检查:验证所有必要文件是否存在
- 权限设置:自动设置可执行文件和目录权限
- 容器管理:自动停止和删除旧容器
- 镜像构建:显示构建过程和结果
- 容器启动:显示启动状态和端口监听情况
- 健康检查:验证应用是否正常响应
-
使用方式:
# 本地发布 publish.bat # 上传publish目录到服务器 # 在服务器上运行 chmod +x deploy.sh ./deploy.sh
修改时间:
2025-01-15
修改原因:
优化X1.WebAPI项目的部署流程,提供详细的部署输出信息,简化服务器端部署操作,提高部署的可视化和可维护性。
2025-01-16 路由冲突修复和当前用户服务增强
修改文件:
X1.Presentation/Controllers/TerminalServicesController.cs- 修复路由冲突X1.Domain/Services/ICurrentUserService.cs- 添加服务IP和端口获取方法X1.Infrastructure/Services/CurrentUserService.cs- 实现服务IP和端口获取方法X1.Application/Features/TerminalServices/Commands/StartTerminalService/StartTerminalServiceCommand.cs- 增强用户获取逻辑X1.WebUI/src/constants/api.ts- 添加终端服务API路径X1.WebUI/src/services/terminalService.ts- 更新API路径和修复命名冲突
修改内容:
-
路由冲突修复:
- 问题描述:
TerminalServicesController和TerminalDevicesController都使用了相同的路由路径api/terminal-devices,导致Swagger生成时出现冲突 - 解决方案:将
TerminalServicesController的路由改为api/terminal-services,保持TerminalDevicesController使用api/terminal-devices - 前端更新:更新前端API路径配置,添加
TERMINAL_SERVICES常量,更新终端服务使用新的API路径
- 问题描述:
-
当前用户服务增强:
- 新增方法:
GetCurrentServiceIpAddress():获取当前服务IP地址GetCurrentServicePort():获取当前服务端口GetCurrentServiceEndpoint():获取当前服务端点信息(IP:端口)
- 技术特性:
- 优先获取IPv4地址,支持IPv6到IPv4的映射
- 完整的空值检查和错误处理
- 从HttpContext中获取本地连接信息
- 新增方法:
-
启动终端服务命令处理器增强:
- 用户获取严谨化:
- 检查用户ID是否为空
- 检查用户是否已认证
- 获取当前服务端点信息用于日志记录
- 日志记录增强:
- 记录用户ID、服务端点、操作结果
- 提供更详细的操作追踪信息
- 用户获取严谨化:
-
前端服务修复:
- API路径更新:使用新的
TERMINAL_SERVICES路径 - 命名冲突修复:将
TerminalService类重命名为TerminalServiceClient,避免与接口冲突 - 类型安全:确保所有TypeScript类型定义正确
- API路径更新:使用新的
-
设计原则:
- RESTful API设计:使用语义化的路由路径
- 职责分离:终端服务和终端设备使用不同的API路径
- 安全性:增强用户认证和授权检查
- 可追溯性:完整的操作日志记录
修改时间:
2025-01-16
修改原因:
- 修复Swagger生成时的路由冲突问题,确保API文档正确生成
- 增强当前用户服务功能,提供更丰富的用户和服务信息
- 提高系统安全性和可追溯性,确保所有操作都有完整的审计信息
2025-01-16 终端消息事件模型创建和WebSocket集成
修改文件:
X1.Domain/Models/TerminalMessageEvent.cs- 创建终端消息事件模型X1.WebSocket/Handlers/TerminalMessageHandler.cs- 修改WebSocket消息处理器以使用IMediatorX1.BackendServices/TerminalManagement/TerminalManagementService.cs- 更新终端管理服务使用新的事件模型X1.BackendServices/TerminalManagement/TerminalMessageEventHandler.cs- 创建终端消息事件处理器X1.BackendServices/DependencyInjection.cs- 注册终端管理服务和事件处理器
修改内容:
-
TerminalMessageEvent模型特性:
- 实现
INotification接口,用于MediatR消息传递 - 包含三个基本字段:
ConnectionId、MessageData、Timestamp - 提供
Create和CreateWithTimestamp静态工厂方法 - 包含
GetMessageSummary和IsValid实用方法 - 遵循项目模型设计规范
- 实现
-
WebSocket消息处理集成:
- 修改
TerminalMessageHandler以使用IMediator - 在
HandleAsync方法中使用TerminalMessageEvent.Create创建事件 - 通过
IMediator.Publish发送消息事件 - 保持原有的WebSocket响应逻辑
- 修改
-
终端消息事件处理器:
- 创建
TerminalMessageEventHandler实现INotificationHandler<TerminalMessageEvent> - 负责接收和处理来自
TerminalMessageHandler的终端消息事件 - 提供完整的日志记录和错误处理
- 支持异步消息处理和业务逻辑扩展
- 创建
-
终端管理服务更新:
- 更新
TerminalManagementService使用新的事件模型 - 在
HandleTerminalMessageAsync方法中使用Create方法 - 确保事件传递的一致性
- 更新
-
依赖注入配置:
- 注册
TerminalManagementService为HostedService - 注册
TerminalMessageEventHandler为Scoped服务 - 确保服务在应用启动时正确初始化
- 注册
-
设计原则:
- 遵循CQRS模式,使用MediatR进行消息传递
- 采用事件驱动架构,解耦WebSocket处理和业务逻辑
- 使用工厂方法模式创建事件实例
- 提供完整的日志记录和错误处理机制
修改时间:
2025-01-16
修改原因:
需要创建一个标准的终端消息事件模型,用于WebSocket消息的事件传递,使用系统自带的 IMediator 进行消息处理,实现终端设备的统一消息管理。
2024年修改记录
2025-01-15 终端设备管理前端界面修复
修改文件:
X1.WebUI/src/services/terminalDeviceService.tsX1.WebUI/src/pages/terminal-devices/TerminalDevicesTable.tsxX1.WebUI/src/pages/terminal-devices/TerminalDeviceForm.tsxX1.WebUI/src/pages/terminal-devices/TerminalDevicesView.tsxX1.WebUI/src/components/ui/switch.tsxX1.WebUI/package.json
修改内容:
-
问题描述:
- 终端设备管理页面需要与 instruments 页面保持一致的样式和功能
- 缺少必要的 UI 组件和依赖包
- 表单实现与 instruments 页面不一致
-
解决方案:
- 修复了
terminalDeviceService.ts中的接口定义,使其与后端 API 保持一致 - 更新了
TerminalDevicesTable.tsx,使用TerminalDeviceStatusBadge组件显示状态 - 重写了
TerminalDeviceForm.tsx,移除 Switch 组件,使用简单的 useState 状态管理,与 instruments 页面保持一致 - 创建了
switch.tsx组件(虽然最终未使用,但为将来需要时做准备) - 安装了缺失的
@hookform/resolvers依赖包
- 修复了
-
关键修改:
- 表格状态显示:使用 Badge 组件而不是 Switch 组件来显示设备状态
- 表单实现:采用与 instruments 页面相同的简单状态管理方式,不使用 react-hook-form
- 字段映射:确保前端字段与后端 API 字段完全匹配
- 编辑模式:在编辑模式下禁用不可修改的字段(IP地址、Agent端口)
-
技术细节:
- 移除了复杂的表单验证库依赖
- 使用简单的 useState 进行状态管理
- 保持与 instruments 页面完全一致的 UI 交互模式
- 确保所有 TypeScript 类型定义正确
修改时间:
2025-01-15
修改原因:
确保终端设备管理页面与 instruments 页面保持完全一致的样式和功能,提供统一的用户体验。
2025-01-15 终端设备服务导入错误修复
修改文件:
X1.WebUI/src/services/terminalDeviceService.ts
修改内容:
-
问题描述:
terminalDeviceService.ts中导入httpClient时出现错误:The requested module '/src/services/axiosConfig.ts' does not provide an export named 'httpClient'OperationResult类型导入路径错误:Cannot find module '@/types/common'
-
解决方案:
- 修正
httpClient的导入路径:从'./axiosConfig'改为'@/lib/http-client' - 修正
OperationResult的导入路径:从'@/types/common'改为'@/types/auth'
- 修正
-
修改代码:
// 修改前 import { httpClient } from './axiosConfig'; import { OperationResult } from '@/types/common'; // 修改后 import { httpClient } from '@/lib/http-client'; import { OperationResult } from '@/types/auth'; -
技术细节:
httpClient实际定义在@/lib/http-client.ts文件中,而不是axiosConfig.tsOperationResult类型定义在@/types/auth.ts文件中,与其他服务文件保持一致- 修复后与
instrumentService.ts的导入方式完全一致
修改时间:
2025-01-15
修改原因:
修复终端设备服务中的模块导入错误,确保前端应用能够正常启动和运行。
修复CreateTerminalDeviceCommandHandler中的空引用警告和并发问题
修改文件:
X1.Application/Features/TerminalDevices/Commands/CreateTerminalDevice/CreateTerminalDeviceCommandHandler.cs
修改内容:
-
问题描述:
- 在第95行出现可能的空引用警告
deviceInfoResult.ErrorMessages可能为 null,但CreateFailure(List<string> errorMessages)方法期望非空参数- 设备编码生成逻辑存在并发问题:多个请求可能生成相同的设备编码
-
解决方案:
- 使用空合并操作符
??提供默认值 - 使用空断言操作符
!处理已知非空的Data属性 - 重构设备编码生成逻辑,添加重试机制和并发处理
- 将原来的
GenerateDeviceCodeAsync和编码检查逻辑合并为GenerateUniqueDeviceCodeAsync
- 使用空合并操作符
-
修改代码:
// 修改前 - 空引用问题 return OperationResult<CreateTerminalDeviceResponse>.CreateFailure(deviceInfoResult.ErrorMessages); // 修改后 - 空引用问题 return OperationResult<CreateTerminalDeviceResponse>.CreateFailure(deviceInfoResult.ErrorMessages ?? new List<string> { "获取设备信息失败" }); // 修改前 - Data空引用问题 var serialNumber = deviceInfoResult.Data.SerialNumber; var deviceType = deviceInfoResult.Data.DeviceType; // 修改后 - Data空引用问题 var serialNumber = deviceInfoResult.Data!.SerialNumber; var deviceType = deviceInfoResult.Data!.DeviceType; // 修改前 - 并发问题 var deviceCode = await GenerateDeviceCodeAsync(serialNumber, cancellationToken); if (await _deviceRepository.DeviceCodeExistsAsync(deviceCode, cancellationToken)) { return OperationResult<CreateTerminalDeviceResponse>.CreateFailure($"终端设备编码 {deviceCode} 已存在"); } // 修改后 - 并发问题 var deviceCode = await GenerateUniqueDeviceCodeAsync(cancellationToken); -
新的GenerateUniqueDeviceCodeAsync方法特性:
- 使用短UUID(8位)生成简洁的设备编码
- 格式:
TERM-{8位短UUID},如TERM-a1b2c3d4 - 极低的冲突概率,理论上几乎不可能重复
- 如果发生冲突,自动添加时间戳后缀(6位数字)
- 简洁高效的实现,无需复杂的重试逻辑
- 无需序列号参数,使用纯UUID生成方式
- 完整的日志记录,便于调试和监控
-
技术细节:
- 使用
??空合并操作符处理可能的 null 值 - 提供有意义的默认错误消息
- 使用
Guid.NewGuid().ToString("N").Substring(0, 8)生成8位短UUID - 使用
DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() % 1000000生成6位时间戳后缀 - 保持代码的简洁性和高效性
- 使用
修改时间:
2024年
修改原因:
解决编译警告,确保代码的健壮性,避免运行时出现空引用异常。同时解决高并发场景下设备编码重复的问题,提高系统的可靠性和稳定性。
ADB操作和AT操作控制器实现
修改文件:
X1.Presentation/Controllers/AdbOperationsController.csX1.Presentation/Controllers/AtOperationsController.csX1.Infrastructure/DependencyInjection.cs
修改内容:
-
功能描述:
- 创建了
AdbOperationsController控制器,用于管理ADB操作 - 创建了
AtOperationsController控制器,用于管理AT操作 - 参考
TerminalDevicesController的实现结构和设计模式 - 提供完整的RESTful API接口
- 创建了
-
AdbOperationsController特性:
- 路由:
/api/adb-operations - 支持完整的CRUD操作:GET、POST、PUT、DELETE
- 提供列表查询(支持分页和搜索)
- 提供详情查询、创建、更新、删除功能
- 完整的日志记录和错误处理
- 路由:
-
AtOperationsController特性:
- 路由:
/api/at-operations - 支持完整的CRUD操作:GET、POST、PUT、DELETE
- 提供列表查询(支持分页、搜索和设备ID过滤)
- 提供详情查询、创建、更新、删除功能
- 完整的日志记录和错误处理
- 路由:
-
API端点:
- GET /api/adb-operations:获取ADB操作列表
- GET /api/adb-operations/{id}:获取ADB操作详情
- POST /api/adb-operations:创建ADB操作
- PUT /api/adb-operations/{id}:更新ADB操作
- DELETE /api/adb-operations/{id}:删除ADB操作
- GET /api/at-operations:获取AT操作列表
- GET /api/at-operations/{id}:获取AT操作详情
- POST /api/at-operations:创建AT操作
- PUT /api/at-operations/{id}:更新AT操作
- DELETE /api/at-operations/{id}:删除AT操作
-
技术特性:
- 继承自
ApiController基类 - 使用MediatR进行命令和查询处理
- 支持授权认证([Authorize]特性)
- 统一的响应格式(OperationResult)
- 详细的日志记录和错误处理
- 参数验证和ID匹配检查
- 继承自
-
依赖注入配置:
- 在
X1.Infrastructure/DependencyInjection.cs中添加了终端设备相关仓储的注册 - 注册了
ITerminalDeviceRepository、IAdbOperationRepository、IAtOperationRepository及其实现类 - 添加了相应的 using 语句引用终端设备相关的命名空间
- 确保控制器能够正确注入所需的仓储服务
- 在
-
设计原则:
- 遵循RESTful API设计规范
- 统一的错误处理和响应格式
- 完整的日志记录支持
- 与现有架构保持一致
- 支持异步操作
修改时间:
2024年
修改原因:
为ADB操作和AT操作提供完整的Web API控制器,支持终端设备管理系统的前端界面操作,提供标准的RESTful API接口。
AT操作仓储实现
修改文件:
X1.Infrastructure/Repositories/Terminal/AtOperationRepository.cs
修改内容:
-
功能描述:
- 创建了
AtOperationRepository实现类 - 实现了
IAtOperationRepository接口的所有方法 - 参考
AdbOperationRepository的实现方式 - 提供完整的AT操作数据访问功能
- 创建了
-
实现特性:
- 继承自
BaseRepository<AtOperation> - 使用CQRS模式,分离命令和查询操作
- 支持异步操作和取消令牌
- 提供完整的CRUD操作方法
- 支持搜索、分页、统计等功能
- 继承自
-
主要方法:
AddOperationAsync():添加AT操作UpdateOperation():更新AT操作DeleteOperationAsync():删除AT操作GetAllOperationsAsync():获取所有AT操作GetOperationByIdAsync():根据ID获取AT操作GetOperationsByDeviceIdAsync():根据设备ID获取AT操作SearchOperationsAsync():搜索AT操作(支持关键词搜索)SearchOperationsAsync():搜索AT操作(分页版本)ExistsAsync():检查AT操作是否存在GetOperationCountAsync():获取操作总数GetOperationByCommandAsync():根据命令内容获取操作CommandExistsAsync():检查命令是否已存在GetDeviceOperationStatsAsync():获取设备操作统计
-
搜索功能:
- 支持按命令内容、描述、设备ID、端口进行关键词搜索
- 提供分页搜索功能,支持排序和分页
- 搜索结果按ID降序排列
-
统计功能:
- 提供设备操作统计功能
- 按设备ID分组统计操作数量
- 返回字典格式的统计结果
-
设计原则:
- 遵循仓储模式设计
- 使用依赖注入管理依赖关系
- 提供完整的日志记录支持
- 支持异步操作和取消令牌
- 与现有架构保持一致
修改时间:
2024年
修改原因:
需要实现 IAtOperationRepository 接口,为AT操作提供完整的数据访问功能,支持串口通信的AT命令管理。
终端设备实体创建
修改文件:
X1.Domain/Entities/Device/TerminalDevice.csX1.Domain/Repositories/Device/ITerminalDeviceRepository.csX1.Infrastructure/Repositories/Device/TerminalDeviceRepository.csX1.Application/Features/TerminalDevices/Commands/CreateTerminalDevice/X1.Application/Features/TerminalDevices/Commands/UpdateTerminalDevice/X1.Application/Features/TerminalDevices/Commands/DeleteTerminalDevice/X1.Application/Features/TerminalDevices/Queries/GetTerminalDevices/X1.Application/Features/TerminalDevices/Queries/GetTerminalDeviceById/
修改内容:
-
功能描述:
- 创建了新的终端设备实体类
TerminalDevice - 主要用于支持ADB终端设备管理
- 基于
CellularDevice结构但去掉了ProtocolVersions和Runtime属性 - 创建了完整的仓储体系和Features层
- 创建了新的终端设备实体类
-
实体特性:
- 继承自
AuditableEntity,支持审计功能 - 包含设备基本信息:名称、序列号、设备编码、描述
- 包含网络配置:Agent端口、IP地址
- 支持设备状态管理:启用/禁用
- 提供完整的CRUD操作方法
- 继承自
-
主要属性:
Name:设备名称(必填,最大100字符)SerialNumber:设备序列号(必填,最大50字符)DeviceCode:设备编码(必填,最大50字符)Description:设备描述(最大500字符)AgentPort:Agent端口(必填)IpAddress:IP地址(必填,最大45字符)IsEnabled:是否启用(默认true)
-
业务方法:
Create():静态工厂方法,用于创建新的终端设备Update():更新设备信息Enable():启用设备Disable():禁用设备
-
仓储接口:
ITerminalDeviceRepository:终端设备仓储接口- 继承自
IBaseRepository<TerminalDevice> - 提供完整的CRUD操作方法
- 支持搜索、分页、存在性检查等功能
- 去掉了与运行时状态相关的方法
-
仓储实现:
TerminalDeviceRepository:终端设备仓储实现类- 继承自
BaseRepository<TerminalDevice> - 实现所有仓储接口方法
- 支持高性能查询和分页操作
- 提供设备基本信息查询功能
-
Features层:
- 命令(Commands):
CreateTerminalDevice:创建终端设备UpdateTerminalDevice:更新终端设备DeleteTerminalDevice:删除终端设备
- 查询(Queries):
GetTerminalDevices:获取终端设备列表(支持分页和搜索)GetTerminalDeviceById:根据ID获取终端设备详情
- 特性:
- 使用MediatR实现CQRS模式
- 完整的参数验证和错误处理
- 用户认证和权限验证
- 详细的日志记录
- 统一的响应格式
- 正确的泛型类型参数使用(OperationResult)
- 命令(Commands):
-
设计原则:
- 遵循DDD(领域驱动设计)原则
- 使用私有构造函数确保通过工厂方法创建实例
- 属性使用私有setter确保封装性
- 提供完整的业务操作方法
- 采用CQRS模式分离命令和查询操作
- 遵循Clean Architecture架构模式
修改时间:
2024年
修改原因:
需要创建一个专门用于管理ADB终端设备的完整体系,包括实体类、仓储接口和实现类、以及完整的Features层,与蜂窝设备保持相似的结构但去掉不需要的协议版本和运行时状态关联。
协议日志表格右键菜单功能
修改文件:
X1.WebUI/src/components/protocol-logs/ProtocolLogsTable.tsx
修改内容:
-
功能描述:
- 为协议日志表格添加了右键菜单功能
- 支持选择背景颜色和字体颜色
- 提供清空样式功能
-
新增功能:
- 右键菜单触发:在表格行上右键点击可打开菜单
- 背景颜色选择:提供7种浅色背景选项(浅红、浅橙、浅黄、浅绿、浅蓝、浅紫、浅灰)
- 字体颜色选择:提供8种字体颜色选项(黑、红、橙、黄、绿、蓝、紫、灰)
- 清空样式:一键清除当前行的所有自定义样式
-
技术实现:
- 添加了
RowStyle接口定义行样式结构 - 使用
useState管理行样式状态rowStyles - 实现了右键菜单状态管理
contextMenu - 添加了颜色选项配置数组
- 实现了样式设置和清空的相关函数
- 添加了
-
UI设计:
- 使用网格布局展示颜色选择器
- 背景颜色显示为彩色方块
- 字体颜色显示为带字母A的彩色方块
- 添加了悬停效果和过渡动画
- 使用图标区分不同功能区域
-
交互体验:
- 右键菜单在鼠标位置显示
- 点击外部自动关闭菜单
- 颜色选择器支持悬停预览
- 样式变更即时生效
-
代码结构:
// 行样式接口 interface RowStyle { backgroundColor?: string; color?: string; } // 右键菜单状态 const [contextMenu, setContextMenu] = useState<{ visible: boolean; x: number; y: number; rowId: string; }>(); // 行样式状态 const [rowStyles, setRowStyles] = useState<Record<string, RowStyle>>({});
修改时间:
2024年
修改原因:
增强协议日志表格的交互功能,允许用户通过右键菜单自定义行的背景颜色和字体颜色,提升数据可视化和用户体验。
协议日志表格高度适配性优化
修改文件:
X1.WebUI/src/components/protocol-logs/ProtocolLogsTable.tsx
修改内容:
-
问题描述:
- 原代码使用固定的
max-h-[600px]高度设置 - 导致在不同屏幕尺寸下无法良好适配
- 在小屏幕设备上可能出现显示问题
- 原代码使用固定的
-
解决方案:
- 将固定高度
max-h-[600px]替换为响应式高度设置 - 使用
calc()函数结合视口高度(vh)进行动态计算 - 添加最小高度限制确保在小屏幕上仍有足够的显示空间
- 将固定高度
-
具体修改:
// 修改前 <div className="max-h-[600px] overflow-auto"> // 修改后 <div className="h-[calc(100vh-400px)] min-h-[300px] max-h-[calc(100vh-200px)] overflow-auto"> -
新高度设置说明:
h-[calc(100vh-400px)]:设置表格高度为视口高度减去400px(为页面其他元素预留空间)min-h-[300px]:设置最小高度为300px,确保在小屏幕上仍有足够的显示空间max-h-[calc(100vh-200px)]:设置最大高度为视口高度减去200px,防止在大屏幕上占用过多空间overflow-auto:保持原有的滚动功能
-
优势:
- 响应式设计:能够根据不同的屏幕尺寸自动调整
- 更好的用户体验:在各种设备上都能提供合适的显示效果
- 保持功能完整性:滚动功能和其他交互特性保持不变
修改时间:
2024年
修改原因:
解决协议日志表格在不同屏幕尺寸下的适配性问题,提升用户体验。
协议日志仓储修改
修改文件:
X1.Domain/Repositories/Logging/IProtocolLogRepository.csX1.Infrastructure/Repositories/Logging/ProtocolLogRepository.cs
修改内容:
-
保留现有方法:
- 保留了
GetByDeviceWithFiltersAsync方法,该方法用于根据设备代码和运行时状态获取协议日志
- 保留了
-
新增方法:
- 在接口
IProtocolLogRepository中添加了GetProtocolLogsNotInActiveRuntimesAsync方法 - 在实现类
ProtocolLogRepository中实现了该方法
- 在接口
-
新方法特性:
- 方法名:
GetProtocolLogsNotInActiveRuntimesAsync - 功能:获取不在活跃运行时状态中的协议日志
- 参数:与
GetByDeviceWithFiltersAsync保持一致deviceCode:设备代码runtimeCodes:运行时代码集合startTimestamp:开始时间戳endTimestamp:结束时间戳layerTypes:协议层类型数组runtimeStatuses:运行时状态过滤orderByDescending:是否按时间戳降序排序cancellationToken:取消令牌
- 返回类型:
IEnumerable<ProtocolLogListDto>
- 方法名:
-
SQL查询逻辑:
- 基于用户提供的SQL查询
- 动态查询逻辑:根据
runtimeStatuses参数动态决定使用EXISTS还是NOT EXISTS- 当
runtimeStatuses包含值 1 时,使用EXISTS包含活跃运行时状态(RuntimeStatus = 1)的记录 - 当
runtimeStatuses不包含值 1 时,使用NOT EXISTS排除活跃运行时状态(RuntimeStatus = 1)的记录
- 当
- 支持所有与
GetByDeviceWithFiltersAsync相同的过滤条件 - 高性能查询,不包含
MessageDetailJson字段
-
动态查询逻辑示例:
当 runtimeStatuses 包含值 1 时(使用 EXISTS):
SELECT pl."Id", pl."MessageId", pl."LayerType", pl."CellID", pl."IMSI", pl."Direction", pl."UEID", pl."PLMN", pl."TimeMs", pl."Timestamp", pl."Info", pl."Message", pl."DeviceCode", pl."RuntimeCode" FROM "tb_protocol_logs" pl WHERE EXISTS ( SELECT 1 FROM "tb_cellular_device_runtimes" t WHERE t."RuntimeStatus" = 1 AND t."RuntimeCode" = pl."RuntimeCode" )当 runtimeStatuses 不包含值 1 时(使用 NOT EXISTS):
SELECT pl."Id", pl."MessageId", pl."LayerType", pl."CellID", pl."IMSI", pl."Direction", pl."UEID", pl."PLMN", pl."TimeMs", pl."Timestamp", pl."Info", pl."Message", pl."DeviceCode", pl."RuntimeCode" FROM "tb_protocol_logs" pl WHERE NOT EXISTS ( SELECT 1 FROM "tb_cellular_device_runtimes" t WHERE t."RuntimeStatus" = 1 AND t."RuntimeCode" = pl."RuntimeCode" )
修改时间:
2024年
修改原因:
用户需要一个新的方法来获取不在活跃运行时状态中的协议日志,同时保持与现有 GetByDeviceWithFiltersAsync 方法相同的参数和过滤条件。
终端设备序列号获取方式修改
修改文件:
X1.Application/Features/TerminalDevices/Commands/CreateTerminalDevice/CreateTerminalDeviceCommandHandler.cs
修改内容:
-
功能描述:
- 将终端设备创建时的序列号生成方式从本地生成改为从设备获取真实序列号
- 参考
CreateDeviceCommandHandler的实现方式 - 添加了设备连接和序列号获取功能
-
主要修改:
- 依赖注入:添加了
IBaseInstrumentClient和IServiceEndpointManager依赖 - 序列号获取:替换了本地生成序列号的逻辑,改为从设备获取真实序列号
- 设备编号生成:修改了设备编号生成逻辑,使用序列号作为后缀
- 错误处理:增强了错误处理和日志记录
- 依赖注入:添加了
-
新增方法:
CreateServiceEndpoint():创建服务端点配置GetDeviceSerialNumberAsync():从设备获取序列号CalculateRequiredDigits():计算设备编号位数
-
修改的方法:
GenerateDeviceCodeAsync():修改为接受序列号参数,生成格式为TERM-000-SN的设备编号
-
技术实现:
- 使用动态HTTP客户端连接设备
- 临时创建服务端点进行序列号获取
- 获取成功后清理临时端点
- 完整的异常处理和资源清理
-
设备编号格式:
- 新格式:
TERM-000-SN、TERM-001-SN、TERM-002-SN等 - 动态位数:根据设备总数自动调整位数(至少3位)
- 包含真实序列号:确保设备编号的唯一性和可追溯性
- 新格式:
修改时间:
2024年
修改原因:
需要从终端设备获取真实的序列号,而不是本地生成,以确保设备信息的准确性和唯一性。参考蜂窝设备的实现方式,提供一致的设备管理体验。
终端设备管理前端视图实现
修改文件:
X1.WebUI/src/services/terminalDeviceService.tsX1.WebUI/src/constants/api.tsX1.WebUI/src/pages/terminal-devices/TerminalDevicesTable.tsxX1.WebUI/src/pages/terminal-devices/TerminalDeviceForm.tsxX1.WebUI/src/pages/terminal-devices/TerminalDevicesView.tsxX1.WebUI/src/routes/AppRouter.tsxX1.WebUI/src/constants/menuConfig.ts
修改内容:
-
终端设备服务层:
- 创建了
terminalDeviceService.ts服务文件 - 定义了完整的终端设备接口类型
- 实现了CRUD操作的API调用方法
- 提供了状态描述和颜色映射方法
- 创建了
-
API路径配置:
- 在
api.ts中添加了TERMINAL_DEVICES: '/terminal-devices'路径 - 与后端控制器路径保持一致
- 在
-
终端设备表格组件:
- 创建了
TerminalDevicesTable.tsx表格组件 - 支持设备状态徽章显示
- 实现了编辑和删除操作按钮
- 支持表格密度调整和列显示控制
- 提供日期格式化功能
- 创建了
-
终端设备表单组件:
- 创建了
TerminalDeviceForm.tsx表单组件 - 使用 React Hook Form 和 Zod 进行表单验证
- 支持创建和编辑两种模式
- 包含设备名称、IP地址、Agent端口、描述等字段
- 编辑模式下支持启用/禁用状态切换
- 创建了
-
终端设备主视图:
- 创建了
TerminalDevicesView.tsx主视图组件 - 实现了完整的CRUD操作功能
- 支持搜索、分页、排序等功能
- 集成了表格工具栏和分页组件
- 提供Toast提示和错误处理
- 创建了
-
路由配置:
- 在
AppRouter.tsx中添加了终端设备路由 - 路径为
/dashboard/terminal-devices - 使用权限控制
terminaldevices.view
- 在
-
菜单配置:
- 在
menuConfig.ts中添加了终端设备菜单项 - 作为独立的顶级菜单项
- 标题为"终端管理"
- 使用 Smartphone 图标
- 配置了相应的权限要求
- 在
-
功能特性:
- 完整的终端设备管理功能
- 支持按设备名称、编码搜索
- 支持按启用状态筛选
- 表格密度和列显示可配置
- 响应式设计和现代化UI
- 完整的错误处理和用户反馈
修改时间:
2024年
修改原因:
需要为终端设备管理提供完整的前端用户界面,参考现有的设备管理页面实现,确保用户体验的一致性和功能的完整性。
终端设备控制器创建
修改文件:
X1.Presentation/Controllers/TerminalDevicesController.cs
修改内容:
-
功能描述:
- 创建了新的终端设备管理控制器
TerminalDevicesController - 参考
DevicesController的实现结构和设计模式 - 提供完整的终端设备CRUD操作API接口
- 创建了新的终端设备管理控制器
-
控制器特性:
- 继承自
ApiController基类 - 使用MediatR进行命令和查询处理
- 支持用户认证和授权
- 完整的日志记录和错误处理
- 统一的响应格式
- 继承自
-
API端点:
- GET /api/terminal-devices:获取终端设备列表(支持分页和搜索)
- GET /api/terminal-devices/{id}:根据ID获取终端设备详情
- POST /api/terminal-devices:创建新的终端设备
- **PUT /api/terminal-devices/{id}`:更新终端设备信息
- **DELETE /api/terminal-devices/{id}`:删除终端设备
-
技术实现:
- 使用CQRS模式分离命令和查询操作
- 统一的OperationResult响应格式
- 详细的日志记录,包括操作开始、成功和失败信息
- 参数验证和错误处理
- ID匹配验证确保数据一致性
-
日志记录:
- 操作开始日志:记录操作类型和关键参数
- 成功日志:记录操作结果和影响的数据量
- 失败日志:记录错误信息和失败原因
- 使用结构化日志记录,便于监控和调试
-
安全特性:
- 使用
[Authorize]特性确保用户认证 - 继承自
ApiController获得统一的错误处理 - 参数验证防止恶意输入
- 使用
修改时间:
2024年
修改原因:
需要为终端设备管理提供完整的Web API接口,参考现有的DevicesController实现,确保API设计的一致性和完整性。
终端设备控制器构造函数调用修复
修改文件:
X1.Presentation/Controllers/TerminalDevicesController.cs
修改内容:
-
问题描述:
GetTerminalDeviceByIdQuery和DeleteTerminalDeviceCommand类没有接受参数的构造函数- 这些类使用属性来接收参数,而不是构造函数参数
- 控制器中直接使用构造函数传递参数导致编译错误
-
修复方案:
- 修改
GetById方法中的查询对象创建方式 - 修改
Delete方法中的命令对象创建方式 - 使用对象初始化器语法设置属性值
- 修改
-
具体修改:
// 修改前 var result = await mediator.Send(new GetTerminalDeviceByIdQuery(id)); var result = await mediator.Send(new DeleteTerminalDeviceCommand(id)); // 修改后 var query = new GetTerminalDeviceByIdQuery { DeviceId = id }; var result = await mediator.Send(query); var command = new DeleteTerminalDeviceCommand { DeviceId = id }; var result = await mediator.Send(command); -
技术说明:
- 这些类遵循MediatR的标准模式,使用属性而不是构造函数参数
- 使用对象初始化器语法更清晰地表达意图
- 保持了代码的可读性和一致性
修改时间:
2024年
修改原因:
修复控制器中查询和命令对象的创建方式,确保与MediatR模式保持一致,解决编译错误。
ADB操作实体创建
修改文件:
X1.Domain/Entities/Terminal/AdbOperation.csX1.Domain/Repositories/Terminal/IAdbOperationRepository.cs
修改内容:
-
功能描述:
- 创建了新的ADB操作实体类
AdbOperation - 主要用于管理ADB命令操作
- 继承自
Entity基类,不包含审计功能 - 创建了完整的仓储接口
- 创建了新的ADB操作实体类
-
实体特性:
- 继承自
Entity,提供基础实体功能 - 包含ADB命令信息:命令内容、描述、路径
- 支持路径配置:绝对路径或相对路径
- 支持启用/禁用状态管理
- 提供完整的CRUD操作方法
- 继承自
-
主要属性:
Command:执行的ADB命令(必填)Description:ADB操作的描述(必填)Path:命令执行时所依赖的路径(必填)UseAbsolutePath:是否启用绝对路径(默认false)IsEnabled:是否启用(默认true)
-
业务方法:
Create():静态工厂方法,用于创建新的ADB操作Update():更新操作信息ToggleAbsolutePath():切换绝对路径设置Enable():启用操作Disable():禁用操作
-
仓储接口:
IAdbOperationRepository:ADB操作仓储接口- 继承自
IBaseRepository<AdbOperation> - 提供完整的CRUD操作方法
- 支持搜索、分页、存在性检查等功能
- 支持根据命令内容查询和检查重复
-
设计原则:
- 遵循DDD(领域驱动设计)原则
- 使用私有构造函数确保通过工厂方法创建实例
- 属性使用私有setter确保封装性
- 提供完整的业务操作方法
- 遵循Clean Architecture架构模式
修改时间:
2024年
修改原因:
需要创建一个专门用于管理ADB操作的实体类,支持ADB命令的存储、配置和管理,为终端设备管理提供ADB操作支持。
终端设备文件结构重组
修改文件:
X1.Domain/Entities/Terminal/AdbOperation.csX1.Domain/Entities/Terminal/TerminalDevice.csX1.Domain/Repositories/Terminal/IAdbOperationRepository.csX1.Domain/Repositories/Terminal/ITerminalDeviceRepository.cs
修改内容:
-
文件结构重组:
- 创建了新的
Terminal文件夹,专门用于终端设备相关的实体和仓储 - 将
AdbOperation和TerminalDevice实体从Device文件夹移动到Terminal文件夹 - 将相关的仓储接口也移动到
Terminal文件夹
- 创建了新的
-
命名空间更新:
AdbOperation实体:CellularManagement.Domain.Entities.TerminalTerminalDevice实体:CellularManagement.Domain.Entities.TerminalIAdbOperationRepository接口:CellularManagement.Domain.Repositories.TerminalITerminalDeviceRepository接口:CellularManagement.Domain.Repositories.Terminal
-
架构设计优化:
- 将终端设备相关功能与蜂窝设备(仪表)功能分离
- 终端设备:主要用于ADB操作和终端管理
- 蜂窝设备:主要用于仪表和协议管理
- 更清晰的领域边界和职责分离
-
删除的旧文件:
X1.Domain/Entities/Device/AdbOperation.csX1.Domain/Entities/Device/TerminalDevice.csX1.Domain/Repositories/Device/IAdbOperationRepository.csX1.Domain/Repositories/Device/ITerminalDeviceRepository.cs
修改时间:
2024年
修改原因:
为了更好地组织代码结构,将终端设备相关功能与蜂窝设备功能分离,创建独立的Terminal文件夹,使架构更加清晰和合理。
终端设备仓储实现创建
修改文件:
X1.Infrastructure/Repositories/Terminal/TerminalDeviceRepository.csX1.Infrastructure/Repositories/Terminal/AdbOperationRepository.cs
修改内容:
-
终端设备仓储实现:
- 创建了
TerminalDeviceRepository实现类 - 继承自
BaseRepository<TerminalDevice> - 实现
ITerminalDeviceRepository接口的所有方法 - 提供完整的CRUD操作和查询功能
- 创建了
-
ADB操作仓储实现:
- 创建了
AdbOperationRepository实现类 - 继承自
BaseRepository<AdbOperation> - 实现
IAdbOperationRepository接口的所有方法 - 提供ADB操作的完整管理功能
- 创建了
-
主要功能:
- 终端设备管理:
- 添加、更新、删除终端设备
- 根据ID、序列号查询设备
- 支持关键词搜索和分页查询
- 检查设备存在性和重复性
- 获取设备基本信息和统计
- ADB操作管理:
- 添加、更新、删除ADB操作
- 根据ID、命令内容查询操作
- 支持关键词搜索和分页查询
- 检查操作存在性和命令重复性
- 获取操作统计信息
- 终端设备管理:
-
技术特性:
- 使用CQRS模式分离命令和查询操作
- 支持异步操作和取消令牌
- 完整的日志记录
- 高性能查询和分页
- 统一的错误处理
-
删除的旧文件:
X1.Infrastructure/Repositories/Device/TerminalDeviceRepository.cs
修改时间:
2024年
修改原因:
完成终端设备仓储的完整实现,为终端设备管理和ADB操作提供完整的数据访问层支持。
ADB操作仓储类型修复
修改文件:
X1.Domain/Repositories/Terminal/IAdbOperationRepository.csX1.Infrastructure/Repositories/Terminal/AdbOperationRepository.cs
修改内容:
-
类型错误修复:
- 修复了
AdbOperation实体ID类型不匹配的问题 - 将
int类型改为string类型,与Entity基类保持一致
- 修复了
-
修复的方法:
DeleteOperationAsync(int id)→DeleteOperationAsync(string id)GetOperationByIdAsync(int id)→GetOperationByIdAsync(string id)ExistsAsync(int id)→ExistsAsync(string id)
-
修复范围:
- 仓储接口
IAdbOperationRepository中的方法签名 - 仓储实现
AdbOperationRepository中的方法实现 - 确保与
Entity基类的Id属性类型一致
- 仓储接口
-
技术说明:
Entity基类的Id属性为string类型- 所有继承自
Entity的实体都应该使用string类型的ID - 修复了编译错误:"运算符"=="无法应用于"string"和"int"类型的操作数"
修改时间:
2024年
修改原因:
修复ADB操作仓储中的类型错误,确保ID类型与Entity基类保持一致,解决编译错误。
ADB操作实体等待时间字段添加
修改文件:
X1.Domain/Entities/Terminal/AdbOperation.cs
修改内容:
-
新增字段:
- 添加了
WaitTimeMs属性,用于存储执行命令完需要等待的时间(毫秒) - 默认值为 0,表示不需要等待
- 添加了
-
字段特性:
- 类型:
int(毫秒) - 默认值:0
- 私有setter确保封装性
- 支持负数验证
- 类型:
-
方法更新:
- Create方法:添加了
waitTimeMs参数(默认值为0) - Update方法:添加了
waitTimeMs参数 - SetWaitTime方法:新增专门用于设置等待时间的方法
- Create方法:添加了
-
验证逻辑:
- 在
Create和Update方法中添加了等待时间验证 - 确保等待时间不能为负数
- 抛出
ArgumentException异常处理无效输入
- 在
-
业务场景:
- 支持ADB命令执行后的等待时间配置
- 适用于需要等待设备响应的场景
- 提高命令执行的可靠性和稳定性
-
设计原则:
- 保持与现有代码风格一致
- 遵循DDD原则,通过业务方法修改状态
- 提供完整的参数验证和错误处理
修改时间:
2024年
修改原因:
为ADB操作实体添加等待时间字段,支持命令执行后的等待配置,提高ADB操作的灵活性和可靠性。
ADB操作实体继承AuditableEntity并添加截图数据字段
修改文件:
X1.Domain/Entities/Terminal/AdbOperation.csX1.Infrastructure/Configurations/Terminal/AdbOperationConfiguration.csX1.Infrastructure/Context/AppDbContext.csX1.Application/Features/AdbOperations/Commands/CreateAdbOperation/CreateAdbOperationCommand.csX1.Application/Features/AdbOperations/Commands/CreateAdbOperation/CreateAdbOperationCommandHandler.csX1.Application/Features/AdbOperations/Commands/UpdateAdbOperation/UpdateAdbOperationCommand.csX1.Application/Features/AdbOperations/Commands/UpdateAdbOperation/UpdateAdbOperationCommandHandler.csX1.Application/Features/AdbOperations/Queries/GetAdbOperations/GetAdbOperationsQuery.csX1.Application/Features/AdbOperations/Queries/GetAdbOperations/GetAdbOperationsQueryHandler.csX1.Application/Features/AdbOperations/Queries/GetAdbOperationById/GetAdbOperationByIdQuery.csX1.Application/Features/AdbOperations/Queries/GetAdbOperationById/GetAdbOperationByIdQueryHandler.cs
修改内容:
-
实体基类修改:
- 将
AdbOperation从继承Entity改为继承AuditableEntity - 添加了审计字段:
CreatedAt、UpdatedAt、CreatedBy、UpdatedBy
- 将
-
新增截图数据字段:
- 添加了
ScreenshotData属性,类型为byte[]? - 用于存储操作截图数据(图片字节)
- 字段名从
data改为ScreenshotData,更具语义化
- 添加了
-
数据库配置:
- 创建了
AdbOperationConfiguration配置类 - 配置
ScreenshotData字段为BYTEA类型 - 表名使用规范命名:
tb_adboperations(全小写,tb_前缀) - 添加了完整的字段配置和索引
- 创建了
-
DbContext 更新:
- 在
AppDbContext中添加了AdbOperationsDbSet
- 在
-
命令和查询更新:
- 更新了所有相关的命令和查询 DTO
- 添加了
ScreenshotData字段支持 - 更新了处理器中的实体创建和更新逻辑
-
方法更新:
Create方法添加了screenshotData参数Update方法添加了screenshotData参数- 新增
SetScreenshotData方法用于单独设置截图数据
-
技术特性:
- 使用 PostgreSQL 的
BYTEA类型存储二进制数据 - 支持可空的截图数据字段
- 保持了原有的业务逻辑和验证规则
- 使用 PostgreSQL 的
修改时间:
2024年
修改原因:
将 AdbOperation 实体改为继承 AuditableEntity 以支持审计功能,并添加截图数据字段用于存储操作截图,提高 ADB 操作的可追溯性和可视化能力。
AT操作实体继承AuditableEntity并添加截图数据字段
修改文件:
X1.Domain/Entities/Terminal/AtOperation.csX1.Infrastructure/Configurations/Terminal/AtOperationConfiguration.csX1.Infrastructure/Context/AppDbContext.cs
修改内容:
-
实体基类修改:
- 将
AtOperation从继承Entity改为继承AuditableEntity - 添加了审计字段:
CreatedAt、UpdatedAt、CreatedBy、UpdatedBy
- 将
-
新增截图数据字段:
- 添加了
ScreenshotData属性,类型为byte[]? - 用于存储操作截图数据(图片字节)
- 字段名使用
ScreenshotData,更具语义化
- 添加了
-
数据库配置:
- 创建了
AtOperationConfiguration配置类 - 配置
ScreenshotData字段为BYTEA类型 - 表名使用规范命名:
tb_atoperations(全小写,tb_前缀) - 添加了完整的字段配置和索引
- 创建了
-
DbContext 更新:
- 在
AppDbContext中添加了AtOperationsDbSet
- 在
-
方法更新:
Create方法添加了screenshotData参数Update方法添加了screenshotData参数- 新增
SetScreenshotData方法用于单独设置截图数据
-
技术特性:
- 使用 PostgreSQL 的
BYTEA类型存储二进制数据 - 支持可空的截图数据字段
- 保持了原有的业务逻辑和验证规则
- 使用 PostgreSQL 的
修改时间:
2024年
修改原因:
将 AtOperation 实体改为继承 AuditableEntity 以支持审计功能,并添加截图数据字段用于存储操作截图,提高 AT 操作的可追溯性和可视化能力。
TerminalDevice Features层实现
修改文件:
X1.Application/Features/TerminalDevices/Queries/GetTerminalDevices/GetTerminalDevicesQuery.csX1.Application/Features/TerminalDevices/Queries/GetTerminalDevices/GetTerminalDevicesResponse.csX1.Application/Features/TerminalDevices/Queries/GetTerminalDevices/GetTerminalDevicesQueryHandler.csX1.Application/Features/TerminalDevices/Queries/GetTerminalDeviceById/GetTerminalDeviceByIdQuery.csX1.Application/Features/TerminalDevices/Queries/GetTerminalDeviceById/GetTerminalDeviceByIdResponse.csX1.Application/Features/TerminalDevices/Queries/GetTerminalDeviceById/GetTerminalDeviceByIdQueryHandler.csX1.Application/Features/TerminalDevices/Commands/UpdateTerminalDevice/UpdateTerminalDeviceCommand.csX1.Application/Features/TerminalDevices/Commands/UpdateTerminalDevice/UpdateTerminalDeviceResponse.csX1.Application/Features/TerminalDevices/Commands/UpdateTerminalDevice/UpdateTerminalDeviceCommandHandler.csX1.Application/Features/TerminalDevices/Commands/DeleteTerminalDevice/DeleteTerminalDeviceCommand.csX1.Application/Features/TerminalDevices/Commands/DeleteTerminalDevice/DeleteTerminalDeviceCommandHandler.cs
修改内容:
-
查询功能(Queries):
- GetTerminalDevices:获取终端设备列表,支持分页、搜索和状态过滤
- GetTerminalDeviceById:根据ID获取终端设备详情
-
命令功能(Commands):
- UpdateTerminalDevice:更新终端设备信息(描述、别名、启用状态、绑定状态)
- DeleteTerminalDevice:删除终端设备(包含业务逻辑验证)
-
技术特性:
- 使用MediatR实现CQRS模式
- 完整的参数验证和错误处理
- 详细的日志记录
- 统一的响应格式(OperationResult)
- 支持异步操作和取消令牌
-
业务逻辑:
- 支持设备状态管理:在线/离线、启用/禁用、绑定/解绑
- 支持设备信息更新:描述、别名等可编辑字段
- 删除前验证:检查设备是否被绑定,防止误删
- 完整的CRUD操作支持
-
设计原则:
- 遵循DDD(领域驱动设计)原则
- 采用CQRS模式分离命令和查询操作
- 遵循Clean Architecture架构模式
- 统一的错误处理和日志记录
- 完整的业务逻辑验证
修改时间:
2024年
修改原因:
为 TerminalDevice 实现完整的 Features 层功能,包括查询、修改和删除操作,参考 TerminalServices 的实现模式,提供统一的API接口和业务逻辑处理。
TerminalService 启动停止功能实现
修改文件:
X1.Application/Features/TerminalServices/Commands/StartTerminalService/StartTerminalServiceCommand.csX1.Application/Features/TerminalServices/Commands/StartTerminalService/StartTerminalServiceResponse.csX1.Application/Features/TerminalServices/Commands/StartTerminalService/StartTerminalServiceCommandHandler.csX1.Application/Features/TerminalServices/Commands/StopTerminalService/StopTerminalServiceCommand.csX1.Application/Features/TerminalServices/Commands/StopTerminalService/StopTerminalServiceResponse.csX1.Application/Features/TerminalServices/Commands/StopTerminalService/StopTerminalServiceCommandHandler.cs
修改内容:
-
启动服务功能(StartTerminalService):
- StartTerminalServiceCommand:启动终端服务命令,包含服务ID参数
- StartTerminalServiceResponse:启动服务响应,返回服务状态和更新时间
- StartTerminalServiceCommandHandler:启动服务命令处理器,包含业务逻辑验证
-
停止服务功能(StopTerminalService):
- StopTerminalServiceCommand:停止终端服务命令,包含服务ID参数
- StopTerminalServiceResponse:停止服务响应,返回服务状态和更新时间
- StopTerminalServiceCommandHandler:停止服务命令处理器,包含业务逻辑验证
-
业务逻辑验证:
- 启动服务验证:
- 检查服务是否存在
- 检查服务是否已启用(只有启用的服务才能启动)
- 检查服务是否已经启动(避免重复启动)
- 停止服务验证:
- 检查服务是否存在
- 检查服务是否已经停止(避免重复停止)
- 启动服务验证:
-
技术特性:
- 使用MediatR实现CQRS模式
- 完整的参数验证和错误处理
- 详细的日志记录
- 统一的响应格式(OperationResult)
- 支持异步操作和取消令牌
- 自动更新审计信息(UpdatedAt、UpdatedBy)
-
设计原则:
- 遵循DDD(领域驱动设计)原则
- 采用CQRS模式分离命令和查询操作
- 遵循Clean Architecture架构模式
- 统一的错误处理和日志记录
- 完整的业务逻辑验证
修改时间:
2024年
修改原因:
为 TerminalService 添加启动和停止服务的功能,通过 IsServiceStarted 属性控制服务状态,提供完整的服务生命周期管理能力。
AdbOperation 适配 AuditableEntity 审计功能
修改文件:
X1.Domain/Entities/Terminal/AdbOperation.csX1.Application/Features/AdbOperations/Commands/CreateAdbOperation/CreateAdbOperationCommandHandler.csX1.Application/Features/AdbOperations/Commands/UpdateAdbOperation/UpdateAdbOperationCommandHandler.cs
修改内容:
-
AdbOperation 实体更新:
- Create 方法:添加
createdBy参数,调用SetCreated(createdBy)设置审计信息 - Update 方法:添加
updatedBy参数,调用SetUpdated(updatedBy)设置审计信息 - 其他方法:为所有修改状态的方法添加
updatedBy参数ToggleAbsolutePath(string updatedBy)Enable(string updatedBy)Disable(string updatedBy)SetWaitTime(int waitTimeMs, string updatedBy)SetScreenshotData(byte[]? screenshotData, string updatedBy)
- Create 方法:添加
-
命令处理器更新:
- CreateAdbOperationCommandHandler:
- 注入
ICurrentUserService依赖 - 获取当前用户ID并传递给
Create方法
- 注入
- UpdateAdbOperationCommandHandler:
- 注入
ICurrentUserService依赖 - 获取当前用户ID并传递给
Update方法
- 注入
- CreateAdbOperationCommandHandler:
-
审计功能特性:
- 自动设置
CreatedAt、UpdatedAt时间戳 - 自动设置
CreatedBy、UpdatedBy用户信息 - 所有状态变更都会记录操作人
- 完整的操作审计追踪
- 自动设置
-
技术特性:
- 保持向后兼容性
- 统一的审计信息管理
- 完整的参数验证
- 详细的错误处理
修改时间:
2024年
修改原因:
将 AdbOperation 的 Create 和 Update 方法适配 AuditableEntity 基类,确保所有操作都有完整的审计信息记录,提高系统的可追溯性和安全性。
AtOperation 适配 AuditableEntity 审计功能
修改文件:
X1.Domain/Entities/Terminal/AtOperation.csX1.Application/Features/AtOperations/Commands/CreateAtOperation/CreateAtOperationCommandHandler.csX1.Application/Features/AtOperations/Commands/UpdateAtOperation/UpdateAtOperationCommandHandler.cs
修改内容:
-
AtOperation 实体更新:
- Create 方法:添加
createdBy参数,调用SetCreated(createdBy)设置审计信息 - Update 方法:添加
updatedBy参数,调用SetUpdated(updatedBy)设置审计信息 - 其他方法:为所有修改状态的方法添加
updatedBy参数Enable(string updatedBy)Disable(string updatedBy)SetTimeout(int timeout, string updatedBy)SetBaudRate(int baudRate, string updatedBy)SetScreenshotData(byte[]? screenshotData, string updatedBy)
- Create 方法:添加
-
命令处理器更新:
- CreateAtOperationCommandHandler:
- 注入
ICurrentUserService依赖 - 获取当前用户ID并传递给
Create方法
- 注入
- UpdateAtOperationCommandHandler:
- 注入
ICurrentUserService依赖 - 获取当前用户ID并传递给
Update方法
- 注入
- CreateAtOperationCommandHandler:
-
审计功能特性:
- 自动设置
CreatedAt、UpdatedAt时间戳 - 自动设置
CreatedBy、UpdatedBy用户信息 - 所有状态变更都会记录操作人
- 完整的操作审计追踪
- 自动设置
-
技术特性:
- 保持向后兼容性
- 统一的审计信息管理
- 完整的参数验证
- 详细的错误处理
修改时间:
2024年
修改原因:
将 AtOperation 的 Create 和 Update 方法适配 AuditableEntity 基类,确保所有操作都有完整的审计信息记录,提高系统的可追溯性和安全性。
TerminalServicesController 和前端页面启动停止功能更新
修改文件:
X1.Presentation/Controllers/TerminalServicesController.csX1.WebUI/src/services/terminalService.tsX1.WebUI/src/pages/terminal-services/TerminalServicesTable.tsxX1.WebUI/src/pages/terminal-services/TerminalServicesView.tsx
修改内容:
-
后端控制器更新:
- 添加启动服务端点:
POST /api/terminal-devices/{id}/start - 添加停止服务端点:
POST /api/terminal-devices/{id}/stop - 完整的日志记录和错误处理
- 统一的响应格式
- 添加启动服务端点:
-
前端服务接口更新:
- 添加
isServiceStarted字段到TerminalService接口 - 添加
StartTerminalServiceResponse和StopTerminalServiceResponse接口 - 添加
startTerminalService和stopTerminalService方法 - 更新所有相关接口以包含运行状态字段
- 添加
-
前端表格组件更新:
- 添加
onStart和onStop回调函数 - 添加
TerminalServiceStartedBadge组件显示运行状态 - 在操作列中添加启动/停止按钮
- 根据服务状态动态显示按钮(启用且未运行显示启动,运行中显示停止)
- 添加
-
前端主视图更新:
- 添加
handleStart和handleStop处理函数 - 导入启动和停止服务的方法
- 添加运行状态列到默认列配置
- 完整的错误处理和用户提示
- 添加
-
UI/UX 特性:
- 启动按钮使用绿色主题
- 停止按钮使用红色主题
- 根据服务状态智能显示按钮
- 完整的操作反馈和错误提示
-
技术特性:
- 遵循 RESTful API 设计
- 完整的错误处理和日志记录
- 统一的响应格式
- 类型安全的接口定义
修改时间:
2024年
修改原因:
为终端服务管理提供完整的启动和停止功能,包括后端 API 和前端用户界面,实现服务生命周期的完整管理。
TerminalDevicesController 创建
修改文件:
X1.Presentation/Controllers/TerminalDevicesController.cs
修改内容:
-
控制器创建:
- 创建了新的终端设备管理控制器
TerminalDevicesController - 参考
TerminalServicesController的结构和设计模式 - 使用相同的路由前缀:
api/terminal-devices
- 创建了新的终端设备管理控制器
-
API 端点实现:
- 获取设备列表:
GET /api/terminal-devices- 支持分页、搜索、状态筛选
- 返回
GetTerminalDevicesResponse
- 获取设备详情:
GET /api/terminal-devices/{id}- 根据设备ID获取详细信息
- 返回
GetTerminalDeviceByIdResponse
- 更新设备:
PUT /api/terminal-devices/{id}- 更新现有终端设备信息
- 返回
UpdateTerminalDeviceResponse
- 删除设备:
DELETE /api/terminal-devices/{id}- 删除指定的终端设备
- 返回操作结果
- 获取设备列表:
-
功能限制:
- 不包含创建功能:根据需求,只提供查询、修改、删除功能
- 不包含启动/停止功能:终端设备不需要启动/停止操作
-
技术特性:
- 继承自
ApiController基类 - 使用
IMediator进行命令和查询分发 - 完整的日志记录和错误处理
- 统一的响应格式
OperationResult<T> - 授权验证(需要登录)
- 继承自
-
设计模式:
- 遵循 CQRS 模式
- 使用 MediatR 进行消息传递
- RESTful API 设计
- 完整的参数验证和错误处理
-
依赖注入:
- 注入
IMediator用于命令查询分发 - 注入
ILogger<TerminalDevicesController>用于日志记录
- 注入
-
与 TerminalServicesController 的区别:
- 不包含
Create端点 - 不包含
Start和Stop端点 - 专注于设备的基本管理功能
- 不包含
修改时间:
2024年
修改原因:
为终端设备管理提供完整的 RESTful API 控制器,参考 TerminalServicesController 的实现模式,但只包含查询、修改、删除功能,不包含创建和启动/停止功能。
AT操作实体创建
修改文件:
X1.Domain/Entities/Terminal/AtOperation.csX1.Domain/Repositories/Terminal/IAtOperationRepository.cs
修改内容:
-
功能描述:
- 创建了新的AT操作实体类
AtOperation - 专门用于处理通过串口连接的设备的AT命令操作
- 继承自
Entity基类,不包含审计功能 - 创建了完整的仓储接口
- 创建了新的AT操作实体类
-
实体特性:
- 继承自
Entity,提供基础实体功能 - 包含串口通信配置:端口、波特率、数据位、校验位、停止位
- 支持AT命令管理:命令内容、参数、超时时间
- 支持启用/禁用状态管理
- 提供完整的CRUD操作方法
- 继承自
-
主要属性:
DeviceId:设备ID(必填)Port:串口端口(必填)BaudRate:波特率(默认115200)DataBits:数据位(默认8)Parity:校验位(默认NONE)StopBits:停止位(默认1)Command:AT命令内容(必填)Parameters:命令参数(JSON格式)Timeout:超时时间(默认30秒)Description: 操作描述(必填)IsEnabled:是否启用(默认true)
-
业务方法:
Create():静态工厂方法,用于创建新的AT操作Update():更新操作信息Enable():启用操作Disable():禁用操作SetTimeout():设置超时时间SetBaudRate():设置波特率
-
验证逻辑:
- 设备ID、端口、命令、描述不能为空
- 波特率必须大于0
- 数据位必须在5-8之间
- 校验位必须是NONE、EVEN或ODD
- 停止位必须是1、1.5或2
- 超时时间必须大于0
-
仓储接口:
IAtOperationRepository:AT操作仓储接口- 继承自
IBaseRepository<AtOperation> - 提供完整的CRUD操作方法
- 支持搜索、分页、存在性检查等功能
- 支持根据设备ID查询操作
- 支持根据命令内容查询和检查重复
- 提供设备操作统计功能
-
设计原则:
- 遵循DDD(领域驱动设计)原则
- 使用私有构造函数确保通过工厂方法创建实例
- 属性使用私有setter确保封装性
- 提供完整的业务操作方法
- 遵循Clean Architecture架构模式
- 专注于串口通信的核心功能,简化设计
修改时间:
2024年
修改原因:
需要创建一个专门用于管理AT操作的实体类,支持串口通信的AT命令存储、配置和管理,为终端设备管理提供AT操作支持。
AT操作和ADB操作Features层实现
修改文件:
X1.Application/Features/TerminalDevices/Commands/CreateAtOperation/X1.Application/Features/TerminalDevices/Commands/UpdateAtOperation/X1.Application/Features/TerminalDevices/Commands/DeleteAtOperation/X1.Application/Features/TerminalDevices/Queries/GetAtOperations/X1.Application/Features/TerminalDevices/Queries/GetAtOperationById/X1.Application/Features/TerminalDevices/Commands/CreateAdbOperation/X1.Application/Features/TerminalDevices/Commands/UpdateAdbOperation/X1.Application/Features/TerminalDevices/Commands/DeleteAdbOperation/X1.Application/Features/TerminalDevices/Queries/GetAdbOperations/X1.Application/Features/TerminalDevices/Queries/GetAdbOperationById/
修改内容:
-
AT操作Features层:
- Commands(命令):
CreateAtOperation:创建AT操作,支持串口通信配置UpdateAtOperation:更新AT操作信息DeleteAtOperation:删除AT操作
- Queries(查询):
GetAtOperations:获取AT操作列表(支持分页和搜索)GetAtOperationById:根据ID获取AT操作详情
- Commands(命令):
-
ADB操作Features层:
- Commands(命令):
CreateAdbOperation:创建ADB操作,支持命令和路径配置UpdateAdbOperation:更新ADB操作信息DeleteAdbOperation:删除ADB操作
- Queries(查询):
GetAdbOperations:获取ADB操作列表(支持分页和搜索)GetAdbOperationById:根据ID获取ADB操作详情
- Commands(命令):
-
技术特性:
- 使用MediatR实现CQRS模式
- 完整的参数验证和错误处理
- 详细的日志记录
- 统一的响应格式(OperationResult)
- 支持异步操作和取消令牌
- 完整的CRUD操作支持
-
AT操作特性:
- 支持串口通信配置:端口、波特率、数据位、校验位、停止位
- 支持AT命令管理:命令内容、参数、超时时间
- 支持启用/禁用状态管理
- 支持设备ID关联
-
ADB操作特性:
- 支持ADB命令管理:命令内容、描述、路径
- 支持路径配置:绝对路径或相对路径
- 支持启用/禁用状态管理
- 支持等待时间配置
-
设计原则:
- 遵循DDD(领域驱动设计)原则
- 采用CQRS模式分离命令和查询操作
- 遵循Clean Architecture架构模式
- 统一的错误处理和日志记录
- 完整的业务逻辑验证
修改时间:
2024年
修改原因:
为AT操作和ADB操作实现完整的Features层,提供标准的CRUD操作和查询功能,支持终端设备管理系统的完整功能。
2025-01-12 BackendServiceManager 迁移
迁移内容
将 X1.Application.BackendServiceManager 完全迁移到 X1.BackendServices.BackendServiceManager
迁移的文件
IServiceScopeExecutor.cs- 服务作用域执行器接口ServiceScopeExecutor.cs- 服务作用域执行器实现OperationResult.cs- 操作结果包装类ProtocolChannelManager.cs- 协议通道管理器DeviceManagementService.cs- 设备管理后台服务
修改的文件
X1.BackendServices/DependencyInjection.cs- 添加依赖注入配置X1.BackendServices/X1.BackendServices.csproj- 添加项目引用和包引用X1.Application/DependencyInjection.cs- 移除 BackendServiceManager 相关注册X1.WebAPI/Program.cs- 添加对 X1.BackendServices 的依赖注入X1.WebAPI/X1.WebAPI.csproj- 添加对 X1.BackendServices 的项目引用
命名空间变更
- 从
X1.Application.BackendServiceManager改为X1.BackendServices.BackendServiceManager
验证结果
- ✅ 编译成功,无错误
- ✅ 所有依赖关系已正确更新
- ✅ 服务注册已正确配置
完成状态
- ✅ 已成功删除
X1.Application/BackendServiceManager目录 - ✅ 项目编译正常,无错误
- ✅ 迁移完成,所有功能正常工作
2025-01-13 用例节点实体创建
创建的文件
X1.Domain/Entities/UseCase/UseCaseNode.cs- 用例节点实体类X1.Domain/Entities/UseCase/UseCaseNodeType.cs- 用例节点类型枚举
修改内容
-
用例节点实体特性:
- 继承自
AuditableEntity,支持审计功能 - 简化为纯配置实体,只包含核心字段
- 支持启用/禁用状态管理(默认启用)
- 提供基本的业务操作方法
- 继承自
-
主要属性:
NodeName:节点名称(必填,最大100字符)NodeType:节点类型(必填,使用枚举)IsEnabled:是否启用(默认true)
-
业务方法:
Update():更新节点信息Enable():启用节点Disable():禁用节点
-
节点类型枚举:
Start:开始节点End:结束节点Process:处理节点Decision:判断节点Wait:等待节点Parallel:并行节点Merge:合并节点SubProcess:子流程节点UserTask:用户任务节点SystemTask:系统任务节点Timer:定时器节点Message:消息节点ErrorHandler:错误处理节点Compensation:补偿节点Custom:自定义节点
-
设计原则:
- 遵循DDD(领域驱动设计)原则
- 使用枚举类型确保节点类型的类型安全
- 简化设计,专注于核心配置功能
- 默认启用状态,符合业务需求
完成状态
- ✅ 用例文件夹创建完成
- ✅ 用例节点实体类创建完成(简化版本)
- ✅ 节点类型枚举创建完成
- ✅ 核心配置字段完整
- ✅ 默认启用状态设置正确
2025-01-13 UpdateUseCaseNodeConfigCommand 字段限制修改
修改文件
X1.Application/Features/UseCaseNodeConfigs/Commands/UpdateUseCaseNodeConfig/UpdateUseCaseNodeConfigCommand.csX1.Application/Features/UseCaseNodeConfigs/Commands/UpdateUseCaseNodeConfig/UpdateUseCaseNodeConfigCommandHandler.cs
修改内容
-
功能描述:
- 限制
UpdateUseCaseNodeConfigCommand只能修改启用、图标和节点说明字段 - 移除对节点名称和节点类型的修改权限
- 确保数据安全性和业务逻辑的正确性
- 限制
-
命令类修改:
- 移除字段:
NodeName:节点名称字段(不再允许修改)NodeType:节点类型字段(不再允许修改)
- 保留字段:
Id:节点配置ID(用于标识要更新的配置)Description:节点说明(允许修改)Icon:节点图标(允许修改)IsEnabled:是否启用(允许修改)
- 移除字段:
-
命令处理器修改:
- 移除验证逻辑:
- 移除了节点名称重复性检查
- 移除了节点名称相关的日志记录
- 更新逻辑修改:
- 只更新
Description、Icon和IsEnabled字段 - 保持
NodeName和NodeType字段不变
- 只更新
- 日志记录优化:
- 简化了日志记录,移除了节点名称相关的信息
- 保持错误处理和用户认证逻辑不变
- 移除验证逻辑:
-
业务逻辑:
- 确保节点配置的核心标识信息(名称和类型)不被意外修改
- 只允许修改配置相关的辅助信息(说明、图标、启用状态)
- 保持数据一致性和业务规则的完整性
-
技术实现:
- 使用对象初始化器语法创建查询和命令对象
- 保持与MediatR模式的一致性
- 完整的错误处理和日志记录
- 统一的响应格式
完成状态
- ✅ 命令类字段限制完成
- ✅ 命令处理器逻辑更新完成
- ✅ 验证逻辑移除完成
- ✅ 日志记录优化完成
- ✅ 业务逻辑安全性确保完成
2025-01-13 UseCaseNodeConfigs Application.Features 实现
实现内容
参考ProtocolVersions的实现模式,为UseCaseNodeConfigs创建完整的Application.Features功能
创建的文件
Commands 命令
-
CreateUseCaseNodeConfig
CreateUseCaseNodeConfigCommand.cs- 创建用例节点配置命令CreateUseCaseNodeConfigResponse.cs- 创建响应CreateUseCaseNodeConfigCommandHandler.cs- 创建命令处理器
-
UpdateUseCaseNodeConfig
UpdateUseCaseNodeConfigCommand.cs- 更新用例节点配置命令(只能修改启用状态、图标和说明)UpdateUseCaseNodeConfigResponse.cs- 更新响应UpdateUseCaseNodeConfigCommandHandler.cs- 更新命令处理器
-
DeleteUseCaseNodeConfig
DeleteUseCaseNodeConfigCommand.cs- 删除用例节点配置命令DeleteUseCaseNodeConfigCommandHandler.cs- 删除命令处理器
Queries 查询
-
GetUseCaseNodeConfigs
GetUseCaseNodeConfigsQuery.cs- 获取用例节点配置列表查询(无分页)GetUseCaseNodeConfigsResponse.cs- 查询响应和DTOGetUseCaseNodeConfigsQueryHandler.cs- 查询处理器
-
GetUseCaseNodeConfigById
GetUseCaseNodeConfigByIdQuery.cs- 根据ID获取用例节点配置查询GetUseCaseNodeConfigByIdResponse.cs- 查询响应GetUseCaseNodeConfigByIdQueryHandler.cs- 查询处理器
Controller 控制器
- UseCaseNodeConfigsController.cs - 用例节点配置API控制器
- 参考ProtocolVersionsController的实现模式
- 包含完整的CRUD操作
- 添加了详细的日志记录
- 统一的错误处理和响应格式
主要特性
-
命令设计:
- 创建时支持所有字段
- 更新时只能修改启用状态、图标和说明(保护节点名称和类型)
- 删除时进行存在性验证
-
查询设计:
- 列表查询无分页(节点配置数量有限)
- 支持按搜索关键词、启用状态、节点类型过滤
- 详情查询包含完整的审计信息
-
控制器设计:
- 统一的API路由:
/api/usecasenodeconfigs - 完整的日志记录和错误处理
- 遵循RESTful API设计规范
- 返回统一的OperationResult格式
- 统一的API路由:
-
业务逻辑:
- 创建时检查节点名称唯一性
- 更新时保护核心字段不被修改
- 所有操作都需要用户认证
- 完整的审计信息记录
完成状态
- ✅ 所有命令和查询功能已实现
- ✅ 控制器已完善,参考ProtocolVersionsController模式
- ✅ 统一的错误处理和日志记录
- ✅ 符合DDD和CQRS架构模式
- ✅ 支持完整的CRUD操作
2025-01-19 - ADB命令配置功能实现
新增功能
-
ADB操作服务 (
X1.WebUI/src/services/adbOperationsService.ts)- 创建了完整的 ADB 操作 API 服务
- 包含获取列表、创建、更新、删除等操作
- 定义了完整的 TypeScript 接口类型
-
ADB操作管理页面 (
X1.WebUI/src/pages/adb-operations/AdbOperationsView.tsx)- 实现了 ADB 命令配置的主页面
- 支持搜索、分页、表格密度调整等功能
- 包含创建、编辑、删除 ADB 操作的功能
-
ADB操作表格组件 (
X1.WebUI/src/pages/adb-operations/AdbOperationsTable.tsx)- 实现了 ADB 操作的表格显示
- 支持列显示控制、表格密度调整
- 包含状态徽章和操作按钮
-
ADB操作表单组件 (
X1.WebUI/src/pages/adb-operations/AdbOperationForm.tsx)- 实现了 ADB 操作的创建和编辑表单
- 包含命令、描述、路径、绝对路径、启用状态、等待时间等字段
- 支持表单验证和提交
菜单和路由配置
-
菜单配置更新 (
X1.WebUI/src/constants/menuConfig.ts)- 将 ADB 命令配置添加到终端管理菜单下
- 添加了
adboperations.view和adboperations.manage权限 - 更新了菜单路径为
/dashboard/terminal-devices/adb-operations
-
路由配置更新 (
X1.WebUI/src/routes/AppRouter.tsx)- 将终端设备管理路由改为嵌套结构
- 添加了 ADB 操作管理路由
- 格式化了路由代码,使其更清晰易读
功能特性
- 完整的 CRUD 操作: 支持 ADB 操作的创建、读取、更新、删除
- 搜索功能: 支持按命令和描述搜索
- 分页支持: 支持分页显示和每页条数调整
- 表格控制: 支持列显示/隐藏、表格密度调整
- 状态管理: 支持启用/禁用状态切换
- 路径配置: 支持自定义执行路径和绝对路径设置
- 等待时间: 支持命令执行后的等待时间配置
技术实现
- 使用 React + TypeScript 开发
- 采用 CQRS 模式,前后端接口完全匹配
- 使用 shadcn/ui 组件库构建界面
- 支持响应式设计和现代化 UI/UX
- 完整的错误处理和用户反馈
权限控制
- 添加了
adboperations.view权限用于查看 ADB 操作列表 - 添加了
adboperations.manage权限用于管理 ADB 操作 - 集成到现有的权限系统中
后端接口
- 基于现有的
AdbOperationsController实现 - 支持完整的 RESTful API 操作
- 包含日志记录和错误处理
- ✅ 支持完整的CRUD操作
2025-01-13 TerminalDevice 添加设备类型枚举
修改文件
X1.Domain/Entities/Terminal/TerminalDeviceType.cs- 新增设备类型枚举X1.Domain/Entities/Terminal/TerminalDevice.cs- 添加设备类型属性X1.Application/Features/TerminalDevices/Queries/GetTerminalDevices/GetTerminalDevicesResponse.cs- 更新DTOX1.Application/Features/TerminalDevices/Queries/GetTerminalDevices/GetTerminalDevicesQueryHandler.cs- 更新映射X1.Application/Features/TerminalDevices/Queries/GetTerminalDeviceById/GetTerminalDeviceByIdResponse.cs- 更新响应X1.Application/Features/TerminalDevices/Queries/GetTerminalDeviceById/GetTerminalDeviceByIdQueryHandler.cs- 更新映射X1.Application/Features/TerminalDevices/Commands/CreateTerminalDevice/CreateTerminalDeviceCommand.cs- 添加设备类型参数X1.Application/Features/TerminalDevices/Commands/CreateTerminalDevice/CreateTerminalDeviceResponse.cs- 更新响应X1.Application/Features/TerminalDevices/Commands/CreateTerminalDevice/CreateTerminalDeviceCommandHandler.cs- 更新处理逻辑X1.Application/Features/TerminalDevices/Commands/UpdateTerminalDevice/UpdateTerminalDeviceCommand.cs- 添加设备类型参数X1.Application/Features/TerminalDevices/Commands/UpdateTerminalDevice/UpdateTerminalDeviceResponse.cs- 更新响应X1.Application/Features/TerminalDevices/Commands/UpdateTerminalDevice/UpdateTerminalDeviceCommandHandler.cs- 更新处理逻辑X1.Infrastructure/Context/AppDbContext.cs- 添加TerminalDevice DbSetX1.Infrastructure/Configurations/Terminal/TerminalDeviceConfiguration.cs- 新增数据库配置
修改内容:
-
设备类型枚举创建:
- 创建了
TerminalDeviceType枚举 - 包含
Windows = 1和Linux = 2两个选项 - 用于区分终端设备的操作系统类型
- 创建了
-
TerminalDevice实体更新:
- 添加了
DeviceType属性,类型为TerminalDeviceType - 默认值为
TerminalDeviceType.Windows - 更新了
Create和Update方法,添加设备类型参数 - 在数据库中以整数形式存储枚举值
- 添加了
-
Application层更新:
- DTO和响应类:所有相关的DTO和响应类都添加了
DeviceType字段 - 查询处理器:更新了映射逻辑,将枚举值转换为字符串
- 命令类:添加了设备类型参数,默认值为 "Windows"
- 命令处理器:添加了枚举解析逻辑和验证
- DTO和响应类:所有相关的DTO和响应类都添加了
-
数据库配置:
- 在
AppDbContext中添加了TerminalDevicesDbSet - 创建了
TerminalDeviceConfiguration配置类 - 配置了设备类型字段的数据库映射(使用整数存储)
- 添加了相关的索引和约束
- 在
-
技术特性:
- 使用枚举确保类型安全
- 在数据库中存储为整数,提高性能
- 在API中返回字符串,便于前端使用
- 完整的验证和错误处理
- 向后兼容,现有数据默认为Windows类型
-
设计原则:
- 遵循DDD原则,使用枚举表示领域概念
- 保持与现有架构的一致性
- 提供完整的CRUD操作支持
- 确保数据完整性和类型安全
完成状态
- ✅ 设备类型枚举创建完成
- ✅ TerminalDevice实体更新完成
- ✅ Application层所有相关文件更新完成
- ✅ 数据库配置完成
- ✅ 类型安全和验证逻辑完整
- ✅ 向后兼容性确保完成
2025-01-13 TerminalDevice 数据库表命名规范修正
修改文件
X1.Infrastructure/Configurations/Terminal/TerminalDeviceConfiguration.cs
修改内容
-
问题描述:
- 原表名
"TerminalDevices"不符合项目的命名规范 - 项目要求使用
tb_前缀并且都是小写
- 原表名
-
修正方案:
- 将表名从
"TerminalDevices"修改为"tb_terminal_devices" - 符合项目的命名规范:
tb_前缀 + 全小写 + 下划线分隔
- 将表名从
-
具体修改:
// 修改前 builder.ToTable("TerminalDevices"); // 修改后 builder.ToTable("tb_terminal_devices"); -
命名规范说明:
tb_:表名前缀,表示这是一个数据库表terminal_devices:实体名称的小写形式,使用下划线分隔单词- 符合项目的统一命名约定
完成状态
- ✅ 表名修正完成
- ✅ 符合项目命名规范
- ✅ 与现有数据库表命名保持一致
2025-01-13 TerminalDevice 命令字段限制修改
修改文件
X1.Application/Features/TerminalDevices/Commands/CreateTerminalDevice/CreateTerminalDeviceCommand.csX1.Application/Features/TerminalDevices/Commands/CreateTerminalDevice/CreateTerminalDeviceCommandHandler.csX1.Application/Features/TerminalDevices/Commands/UpdateTerminalDevice/UpdateTerminalDeviceCommand.csX1.Application/Features/TerminalDevices/Commands/UpdateTerminalDevice/UpdateTerminalDeviceCommandHandler.csX1.Domain/Entities/Terminal/TerminalDevice.cs
修改内容
-
CreateTerminalDeviceCommand 修改:
- 移除字段:删除了
DeviceType字段,不再由用户填写 - 自动检测:设备类型由系统根据设备连接信息自动检测
- 业务逻辑:系统会尝试获取设备系统信息来判断是Windows还是Linux
- 移除字段:删除了
-
CreateTerminalDeviceCommandHandler 修改:
- 自动检测逻辑:添加了
DetectDeviceTypeAsync方法 - 系统信息检测:通过
GetDeviceSystemInfoAsync获取设备系统信息 - 智能判断:根据系统信息中的关键词判断设备类型
- 默认处理:如果无法检测,默认使用Windows类型
- 错误处理:完整的异常处理和日志记录
- 自动检测逻辑:添加了
-
UpdateTerminalDeviceCommand 修改:
- 字段限制:只保留
DeviceId、Description和IsEnabled字段 - 移除字段:删除了
DeviceName、IpAddress、AgentPort、DeviceType字段 - 业务逻辑:只允许修改设备描述和启用状态,保护核心配置信息
- 字段限制:只保留
-
UpdateTerminalDeviceCommandHandler 修改:
- 更新逻辑:只更新允许修改的字段(描述和启用状态)
- 验证简化:移除了对已删除字段的验证
- 方法调用:使用专门的
UpdateDescription和Enable/Disable方法 - 审计信息:正确更新审计信息
-
TerminalDevice 实体修改:
- 新增方法:添加了
UpdateDescription方法用于更新描述 - 新增方法:添加了
UpdateAuditInfo方法用于更新审计信息 - 封装性:保持实体的封装性,通过方法修改状态
- 新增方法:添加了
-
技术特性:
- 自动检测:设备类型自动检测,无需用户干预
- 字段保护:核心配置字段不允许修改,确保数据安全
- 业务逻辑:符合实际业务需求,只允许修改非关键信息
- 错误处理:完整的异常处理和日志记录
完成状态
- ✅ CreateTerminalDeviceCommand 设备类型字段移除完成
- ✅ 自动设备类型检测逻辑实现完成
- ✅ UpdateTerminalDeviceCommand 字段限制完成
- ✅ 命令处理器逻辑更新完成
- ✅ TerminalDevice 实体方法扩展完成
- ✅ 业务逻辑安全性确保完成
2025-01-13 TerminalDevice DTO 序列号字段移除
修改文件
X1.Application/Features/TerminalDevices/Queries/GetTerminalDevices/GetTerminalDevicesResponse.csX1.Application/Features/TerminalDevices/Queries/GetTerminalDevices/GetTerminalDevicesQueryHandler.csX1.Application/Features/TerminalDevices/Queries/GetTerminalDeviceById/GetTerminalDeviceByIdResponse.csX1.Application/Features/TerminalDevices/Queries/GetTerminalDeviceById/GetTerminalDeviceByIdQueryHandler.cs
修改内容
-
GetTerminalDevicesResponse.cs 修改:
- 移除字段:从
TerminalDeviceDto中删除了SerialNumber字段 - 安全考虑:序列号是敏感信息,不应该在列表中显示
- 数据保护:保护设备序列号信息不被泄露
- 移除字段:从
-
GetTerminalDevicesQueryHandler.cs 修改:
- 映射移除:移除了对
SerialNumber字段的映射 - 数据过滤:确保列表查询不返回序列号信息
- 性能优化:减少不必要的数据传输
- 映射移除:移除了对
-
GetTerminalDeviceByIdResponse.cs 修改:
- 移除字段:从详情响应中删除了
SerialNumber字段 - 一致性:与列表查询保持一致,都不显示序列号
- 安全策略:统一的安全策略,保护敏感信息
- 移除字段:从详情响应中删除了
-
GetTerminalDeviceByIdQueryHandler.cs 修改:
- 映射移除:移除了对
SerialNumber字段的映射 - 详情保护:即使是在详情查询中也不显示序列号
- 数据安全:确保序列号信息不被任何API端点泄露
- 映射移除:移除了对
-
安全特性:
- 信息保护:序列号作为设备唯一标识,属于敏感信息
- 访问控制:通过API层面控制敏感信息的访问
- 数据最小化:只返回必要的设备信息
- 隐私保护:符合数据隐私保护原则
完成状态
- ✅ GetTerminalDevicesResponse 序列号字段移除完成
- ✅ GetTerminalDevicesQueryHandler 映射移除完成
- ✅ GetTerminalDeviceByIdResponse 序列号字段移除完成
- ✅ GetTerminalDeviceByIdQueryHandler 映射移除完成
- ✅ 数据安全保护策略实施完成
TestTerminalRequestClient GetDeviceSerialNumberAsync 方法完善
修改文件:
X1.Domain/ThirdPartyDeviceHttpClient/Models/MachineCodeResponse.cs- 新增机器码响应模型X1.DynamicClientCore/Service/TestTerminalRequestClient.cs- 完善GetDeviceSerialNumberAsync方法
修改内容:
-
功能描述:
- 完善了
TestTerminalRequestClient的GetDeviceSerialNumberAsync方法 - 实现了调用机器码API获取设备序列号的功能
- 创建了对应的响应模型来匹配API返回的数据结构
- 完善了
-
新增响应模型:
- MachineCodeResponse:机器码响应模型
Success:是否成功Message:响应消息Data:响应数据
- MachineCodeData:机器码数据
MachineCode:机器码(设备序列号)SystemType:系统类型
- MachineCodeResponse:机器码响应模型
-
API调用实现:
- 端点:
/api/v1/system/machine-code - 服务名称:
test-terminal - HTTP方法:GET
- 响应处理:完整的成功/失败状态检查
- 端点:
-
技术特性:
- 异步操作:使用
async/await模式 - 错误处理:完整的异常捕获和日志记录
- 参数验证:检查响应数据的有效性
- 日志记录:详细的操作日志,包括开始、成功、失败信息
- 资源清理:确保异常情况下的资源正确释放
- 异步操作:使用
-
业务逻辑:
- 调用机器码API获取设备序列号
- 验证API响应的成功状态
- 提取机器码作为设备序列号返回
- 记录系统类型信息用于调试
- 失败时返回空字符串
-
响应格式匹配:
{ "success": true, "message": "机器码获取成功", "data": { "machine_code": "03000200-0400-0500-0006-000700080009", "system_type": "windows" } } -
设计原则:
- 遵循现有架构模式
- 完整的错误处理和日志记录
- 使用依赖注入管理依赖关系
- 支持取消令牌和异步操作
- 统一的响应格式处理
修改时间:
2025年1月13日
修改原因:
需要完善 TestTerminalRequestClient 的 GetDeviceSerialNumberAsync 方法,实现从指定API端点获取设备机器码的功能,为终端设备管理提供真实的设备序列号获取能力。
MachineCodeResponse 重构为 TestTerminalResponse
修改文件:
X1.Domain/ThirdPartyDeviceHttpClient/Models/MachineCodeResponse.cs- 重构响应模型X1.DynamicClientCore/Service/TestTerminalRequestClient.cs- 更新使用新的响应模型
修改内容:
-
功能描述:
- 将
MachineCodeResponse重构为更通用的TestTerminalResponse - 使测试终端相关的所有API都可以使用这个响应实体
- 直接删除向后兼容的
MachineCodeResponse类,简化代码结构
- 将
-
响应模型重构:
- TestTerminalResponse:泛型版本,支持任意数据类型
Success:是否成功Message:响应消息Data:泛型响应数据
- TestTerminalResponse:非泛型版本,默认使用
MachineCodeData - MachineCodeResponse:已删除,不再提供向后兼容
- TestTerminalResponse:泛型版本,支持任意数据类型
-
数据模型:
- MachineCodeData:机器码数据模型
MachineCode:机器码(设备序列号)SystemType:系统类型
- MachineCodeData:机器码数据模型
-
技术特性:
- 泛型设计:支持任意数据类型的响应
- 简化结构:删除不必要的向后兼容类
- 类型安全:使用泛型确保编译时类型检查
- 可扩展性:未来可以轻松添加新的数据类型
-
使用示例:
// 使用泛型版本(推荐) var response = await _dynamicHttpClient.GetAsync<TestTerminalResponse<MachineCodeData>>( serviceName, endpoint, options, cancellationToken); // 使用非泛型版本(简化) var response = await _dynamicHttpClient.GetAsync<TestTerminalResponse>( serviceName, endpoint, options, cancellationToken); -
设计原则:
- 单一职责:专注于测试终端响应格式
- 开闭原则:对扩展开放,对修改封闭
- 简洁性:删除不必要的向后兼容代码
- 类型安全:编译时类型检查
-
未来扩展:
- 可以轻松添加新的数据类型,如设备状态、网络配置等
- 所有测试终端API都可以使用统一的响应格式
- 支持不同的业务场景和数据需求
修改时间:
2025年1月13日
修改原因:
需要将机器码响应模型重构为更通用的测试终端响应模型,使所有测试终端相关的API都可以使用统一的响应格式,提高代码的可复用性和类型安全性。删除不必要的向后兼容代码,简化代码结构。
TestTerminalRequestClient 添加 GetMachineCodeDataAsync 方法
修改文件:
X1.DynamicClientCore/Service/TestTerminalRequestClient.cs - 添加获取完整机器码数据的方法
修改内容:
-
功能描述:
- 添加了
GetMachineCodeDataAsync方法,返回完整的MachineCodeData对象 - 重构了
GetDeviceSerialNumberAsync方法,使其调用新的方法 - 保持接口兼容性的同时,提供更丰富的数据返回
- 添加了
-
新增方法:
- GetMachineCodeDataAsync:获取完整的机器码数据
- 返回类型:
Task<MachineCodeData?> - 包含机器码和系统类型信息
- 完整的错误处理和日志记录
- 返回类型:
- GetMachineCodeDataAsync:获取完整的机器码数据
-
方法重构:
- GetDeviceSerialNumberAsync:重构为调用
GetMachineCodeDataAsync- 保持原有接口兼容性
- 只返回机器码字符串
- 简化了实现逻辑
- GetDeviceSerialNumberAsync:重构为调用
-
技术特性:
- 代码复用:避免重复的API调用逻辑
- 类型安全:返回强类型的
MachineCodeData对象 - 错误处理:统一的异常处理和日志记录
- 向后兼容:保持原有接口不变
-
使用示例:
// 获取完整机器码数据(推荐) var machineCodeData = await client.GetMachineCodeDataAsync("terminal-001"); if (machineCodeData != null) { var machineCode = machineCodeData.MachineCode; var systemType = machineCodeData.SystemType; } // 获取机器码字符串(兼容原有接口) var serialNumber = await client.GetDeviceSerialNumberAsync("terminal-001"); -
设计原则:
- 单一职责:一个方法专注于获取机器码数据
- 代码复用:避免重复的API调用逻辑
- 向后兼容:保持原有接口不变
- 类型安全:提供强类型的数据返回
-
业务价值:
- 提供更丰富的设备信息(机器码 + 系统类型)
- 支持更复杂的业务逻辑处理
- 保持与现有代码的兼容性
- 提高代码的可维护性
修改时间:
2025年1月13日
修改原因:
需要提供获取完整机器码数据的功能,包括机器码和系统类型信息,同时保持与现有接口的兼容性,为测试终端管理提供更丰富的数据支持。
TestTerminalRequestClient 最终优化
修改文件:
X1.Domain/ThirdPartyDeviceHttpClient/ITerminal/IBaseTerminalClient.cs- 更新接口定义X1.DynamicClientCore/Service/TestTerminalRequestClient.cs- 优化实现和注释
修改内容:
-
接口定义优化:
- 将
GetDeviceSerialNumberAsync方法返回类型从Task<string>改为Task<MachineCodeData?> - 参数名从
instrumentNumber改为terminalId - 更新方法注释,明确返回测试终端机器码数据
- 将
-
实现优化:
- 移除重复的
GetMachineCodeDataAsync方法 - 直接使用
GetDeviceSerialNumberAsync返回MachineCodeData对象 - 使用
terminalId作为服务名称,而不是硬编码的 "test-terminal" - 添加完整的XML注释,包含参数说明、返回值说明、异常说明和备注
- 移除重复的
-
技术特性:
- 简化设计:移除重复方法,统一使用一个方法
- 正确命名:使用
terminalId作为服务名称 - 完整注释:提供详细的XML文档注释
- 类型安全:返回强类型的
MachineCodeData对象
-
XML注释内容:
- 参数说明:明确
terminalId用作服务名称 - 返回值说明:详细描述返回的数据结构
- 异常说明:列出可能抛出的异常类型
- 备注说明:解释方法的工作原理和API调用细节
- 参数说明:明确
-
使用示例:
// 获取测试终端机器码数据 var machineCodeData = await client.GetDeviceSerialNumberAsync("terminal-001"); if (machineCodeData != null) { var machineCode = machineCodeData.MachineCode; var systemType = machineCodeData.SystemType; } -
设计原则:
- 单一职责:一个方法专注于获取机器码数据
- 正确命名:参数名和方法名符合业务语义
- 完整文档:提供详细的XML注释
- 类型安全:使用强类型返回数据
修改时间:
2025年1月13日
修改原因:
优化TestTerminalRequestClient的设计,简化方法结构,修正命名规范,使用正确的服务名称,并提供完整的XML文档注释,提高代码的可读性和可维护性。
2025-01-15 终端设备管理前端界面修复
修复内容
根据TerminalDevicesController.cs控制器,修复pages.terminal-devices.view界面,参考pages.instruments样式实现完整的终端设备管理功能
修改的文件
1. 终端设备服务层更新
文件:X1.WebUI/src/services/terminalDeviceService.ts
修改内容:
- 更新终端设备接口定义,使其与后端响应结构匹配
- 移除serialNumber字段,添加deviceType字段
- 更新创建和更新请求接口,匹配后端命令结构
- 添加导出函数,与instruments服务保持一致
- 修复接口类型不匹配问题
2. 终端设备表格组件更新
文件:X1.WebUI/src/pages/terminal-devices/TerminalDevicesTable.tsx
修改内容:
- 移除serialNumber字段的显示
- 添加deviceType字段的显示
- 更新字段映射关系
- 保持与instruments表格组件相同的样式和功能
3. 终端设备表单组件修复
文件:X1.WebUI/src/pages/terminal-devices/TerminalDeviceForm.tsx
修改内容:
- 修复编码问题,重新创建文件确保UTF-8编码
- 更新表单验证逻辑,匹配后端接口
- 移除deviceName字段的更新功能,只保留description和isEnabled
- 创建模式下包含所有必要字段
- 编辑模式下只允许修改描述和启用状态
4. 终端设备主视图创建
文件:X1.WebUI/src/pages/terminal-devices/TerminalDevicesView.tsx
修改内容:
- 创建完整的终端设备管理页面
- 参考instruments页面的样式和功能
- 实现完整的CRUD操作:创建、读取、更新、删除
- 支持搜索、分页、排序等功能
- 集成表格工具栏和分页组件
- 提供Toast提示和错误处理
5. 依赖包安装
文件:X1.WebUI/package.json
修改内容:
- 安装缺失的
@hookform/resolvers依赖包 - 确保表单验证功能正常工作
功能特性
-
完整的终端设备管理:
- 支持终端设备的创建、查看、编辑、删除
- 自动获取设备序列号和系统类型
- 设备类型自动检测(Windows/Linux)
-
搜索和筛选功能:
- 支持按设备名称或设备编码搜索
- 支持按启用状态筛选
- 实时搜索和重置功能
-
表格功能:
- 支持表格密度调整(紧凑、默认、舒适)
- 支持列显示/隐藏控制
- 支持分页和每页条数调整
- 状态徽章显示
-
表单验证:
- 使用React Hook Form和Zod进行表单验证
- 完整的字段验证和错误提示
- 支持创建和编辑两种模式
-
用户体验:
- 响应式设计,适配不同屏幕尺寸
- Toast提示和错误处理
- 加载状态和提交状态管理
- 现代化的UI设计
技术实现
-
前端架构:
- 使用React + TypeScript开发
- 采用shadcn/ui组件库
- 使用React Hook Form进行表单管理
- 使用Zod进行数据验证
-
API集成:
- 基于TerminalDevicesController的RESTful API
- 完整的CRUD操作支持
- 统一的错误处理和响应格式
-
状态管理:
- 使用React Hooks管理组件状态
- 支持搜索、分页、表格配置等状态
- 完整的加载和错误状态管理
完成状态
- ✅ 终端设备服务层更新完成
- ✅ 表格组件更新完成
- ✅ 表单组件修复完成
- ✅ 主视图创建完成
- ✅ 依赖包安装完成
- ✅ 编码问题修复完成
- ✅ 功能测试通过
CreateTerminalDeviceCommandHandler 设备类型检测优化
修改文件:
X1.Application/Features/TerminalDevices/Commands/CreateTerminalDevice/CreateTerminalDeviceCommandHandler.cs - 优化设备类型检测逻辑
修改内容:
-
依赖注入修复:
- 将
IBaseInstrumentClient替换为IBaseTerminalClient - 更新字段名从
_instrumentClient到_terminalClient - 添加正确的using语句引用
- 将
-
设备类型检测优化:
- 实现真实的设备类型检测逻辑
- 通过调用
GetDeviceSerialNumberAsync获取系统类型信息 - 根据系统类型字符串智能判断设备类型
- 支持Linux和Windows系统的识别
-
系统类型识别逻辑:
- Linux系统识别:linux、ubuntu、centos、debian、fedora、redhat、suse、unix
- Windows系统识别:windows、win、nt
- 默认处理:未知系统类型默认使用Windows
-
技术特性:
- 真实检测:基于API返回的系统类型信息进行检测
- 智能识别:支持多种Linux发行版和Windows版本
- 错误处理:检测失败时使用默认类型
- 资源管理:自动清理临时服务端点
-
方法调用修复:
- 更新
GetDeviceSerialNumberAsync方法调用 - 处理返回的
MachineCodeData对象 - 提取
MachineCode和SystemType信息 - 完整的null检查和异常处理
- 更新
-
日志记录优化:
- 记录设备类型检测过程
- 记录系统类型和检测结果
- 记录检测失败的原因
- 详细的调试信息
-
使用示例:
// 设备类型检测流程 var deviceType = await DetectDeviceTypeByPortsAsync(request, serviceEndpoint, cancellationToken); // 根据API返回的系统类型自动判断是Windows还是Linux
修改时间:
2025年1月13日
修改原因:
需要实现真实的设备类型检测功能,通过API获取的系统类型信息智能判断设备是Windows还是Linux系统,提高设备管理的准确性和自动化程度。
CreateTerminalDeviceCommandHandler API调用优化
修改文件:
X1.Application/Features/TerminalDevices/Commands/CreateTerminalDevice/CreateTerminalDeviceCommandHandler.cs - 优化API调用逻辑
修改内容:
-
API调用优化:
- 合并序列号获取和设备类型检测为一次API调用
- 移除重复的
DetectDeviceTypeByPortsAsync方法 - 创建
DeviceInfo数据传输对象,包含序列号和设备类型
-
新增DeviceInfo类:
SerialNumber:设备序列号DeviceType:设备类型(Windows/Linux)- 用于封装API返回的完整设备信息
-
方法重构:
GetDeviceSerialNumberAsync→GetDeviceInfoAsync- 在一次API调用中同时获取序列号和系统类型
- 根据系统类型自动判断设备类型
- 返回包含完整信息的
DeviceInfo对象
-
技术特性:
- 性能优化:减少API调用次数,从2次减少到1次
- 数据完整性:确保序列号和系统类型信息的一致性
- 错误处理:统一的错误处理和资源清理
- 类型安全:使用强类型的
DeviceInfo对象
-
工作流程优化:
原流程:获取序列号 → 检测设备类型(重复API调用) 新流程:获取设备信息(一次API调用,包含序列号和系统类型) -
代码简化:
- 移除重复的API调用逻辑
- 简化主处理流程
- 统一的资源管理和错误处理
-
使用示例:
// 一次API调用获取完整设备信息 var deviceInfoResult = await GetDeviceInfoAsync(request, serviceEndpoint, cancellationToken); if (deviceInfoResult.IsSuccess) { var serialNumber = deviceInfoResult.Data.SerialNumber; var deviceType = deviceInfoResult.Data.DeviceType; }
修改时间:
2025年1月13日
修改原因:
优化API调用逻辑,避免重复的API请求,提高性能并确保数据一致性。将序列号获取和设备类型检测合并为一次API调用,简化代码结构并提升用户体验。
2025-01-15 - ADB 操作管理页面实现
新增文件
-
X1.WebUI/src/pages/adb-operations/AdbOperationsView.tsx
- 实现了完整的 ADB 操作管理页面
- 参考 AdbOperationsController 和 pages.protocols 的结构
- 包含搜索、分页、表格密度控制、列显示控制等功能
- 支持创建、编辑、删除 ADB 操作
-
X1.WebUI/src/pages/adb-operations/AdbOperationsTable.tsx
- 实现了 ADB 操作数据表格组件
- 支持自定义列显示和表格密度
- 包含状态徽章和绝对路径徽章组件
- 支持编辑和删除操作
-
X1.WebUI/src/pages/adb-operations/AdbOperationForm.tsx
- 实现了 ADB 操作表单组件
- 支持创建和编辑模式
- 包含所有必要的字段:命令、描述、路径、绝对路径、启用状态、等待时间
- 使用 Checkbox 组件替代 Switch 组件
修改文件
- X1.WebUI/src/services/adbOperationsService.ts
- 修复了 OperationResult 的导入路径
- 从 '@/types/auth' 改为 '@/config/types/config.types'
功能特性
- 搜索功能: 支持按关键词搜索命令和描述
- 分页功能: 支持分页显示和每页条数选择
- 表格控制: 支持表格密度调整和列显示控制
- CRUD 操作: 完整的创建、读取、更新、删除功能
- 状态管理: 实时状态反馈和错误处理
- 响应式设计: 适配不同屏幕尺寸
- 用户体验: Toast 提示、加载状态、防重复提交
技术实现
- 使用 React Hooks 进行状态管理
- 采用 TypeScript 进行类型安全
- 使用 shadcn/ui 组件库
- 遵循 Clean Architecture 架构模式
- 参考现有 protocols 页面的设计模式
2025-01-15 终端设备表格组件编码问题修复
修改文件
X1.WebUI/src/pages/terminal-devices/TerminalDevicesTable.tsx
修改内容
-
问题描述:
- 文件出现编码问题:
Unexpected character ''. (1:0) - 这通常是由于文件编码格式不正确导致的
- 文件出现编码问题:
-
解决方案:
- 删除原文件并重新创建,确保正确的UTF-8编码
- 修复字段映射问题:将
device.deviceName改为device.name - 修复日期处理问题:添加空值检查,避免
undefined日期转换错误
-
具体修复:
- 字段映射修复:
device.deviceName→device.name(匹配接口定义) - 日期处理修复:添加
device.createdAt ?和device.updatedAt ?空值检查 - 编码问题修复:重新创建文件确保UTF-8编码正确
- 字段映射修复:
-
技术细节:
- 确保所有字段映射与
TerminalDevice接口定义一致 - 添加完整的空值检查,提高代码健壮性
- 保持与
instruments页面表格组件相同的功能和样式
- 确保所有字段映射与
完成状态
- ✅ 文件编码问题修复完成
- ✅ 字段映射错误修复完成
- ✅ 日期处理错误修复完成
- ✅ 表格组件功能正常
2025-01-15 终端设备改为终端服务
修改内容
-
文件夹重命名:
- 将
X1.WebUI/src/pages/terminal-devices重命名为X1.WebUI/src/pages/terminal-services
- 将
-
服务文件重命名和更新:
- 将
terminalDeviceService.ts重命名为terminalService.ts - 更新所有接口名称,将"终端设备"改为"终端服务"
- 更新所有函数名称和变量名称
- 将
-
前端组件重命名和更新:
TerminalDevicesView.tsx→TerminalServicesView.tsxTerminalDevicesTable.tsx→TerminalServicesTable.tsxTerminalDeviceForm.tsx→TerminalServiceForm.tsx- 更新所有组件内部的文本和变量名称
-
路由配置更新:
- 更新
AppRouter.tsx中的路由路径从terminal-devices改为terminal-services - 更新组件引用名称
- 更新
-
菜单配置更新:
- 更新
menuConfig.ts中的菜单路径和标题 - 将"终端设备"改为"终端服务"
- 更新权限配置从
terminaldevices.view改为terminalservices.view
- 更新
-
权限配置更新:
- 更新权限类型定义从
terminaldevices.view/manage改为terminalservices.view/manage - 更新路由配置中的权限要求
- 更新权限类型定义从
修改原因
为了更好地反映系统的实际功能,将"终端设备"改为"终端服务",因为这里管理的是终端服务而不是物理设备。
影响范围
- 前端用户界面
- 路由配置
- 菜单显示
- 服务层接口
注意事项
- 后端API路径保持不变(仍使用
TERMINAL_DEVICES) - 权限配置已更新为
terminalservices.view和terminalservices.manage - 数据库表结构保持不变
2024-12-19 - 创建终端设备表 (TerminalDevice) 和更新终端服务字段名
新增文件
-
X1.Domain/Entities/Terminal/TerminalDevice.cs - 终端设备实体
- 继承自
Entity基类 - 包含设备基本信息:品牌、型号、设备标识、名称
- 包含Android相关信息:版本、SDK版本、构建信息
- 包含硬件信息:序列号、启动序列号、硬件平台
- 包含状态管理:设备状态、是否启用、是否被绑定
- 包含连接时间记录:最后连接时间、最后断开时间
- 继承自
-
X1.Domain/Repositories/Terminal/ITerminalDeviceRepository.cs - 终端设备仓储接口
- 基本的CRUD操作
- 按品牌、型号、状态查询
- 在线/离线设备查询
- 启用/禁用设备查询
- 已绑定/未绑定设备查询
- 统计功能:设备数量、品牌统计、Android版本统计
-
X1.Infrastructure/Repositories/Terminal/TerminalDeviceRepository.cs - 终端设备仓储实现
- 实现所有仓储接口方法
- 使用CQRS模式分离读写操作
- 支持分页查询和搜索功能
-
X1.Infrastructure/Configurations/Terminal/TerminalDeviceConfiguration.cs - Entity Framework配置
- 表名:
tb_terminal_devices - 字段长度和约束配置
- 索引配置:序列号、设备编码、品牌、型号、状态等
- 默认值配置
- 表名:
修改文件
-
X1.Infrastructure/Context/AppDbContext.cs
- 添加
TerminalDevicesDbSet
- 添加
-
X1.Infrastructure/DependencyInjection.cs
- 注册
ITerminalDeviceRepository和TerminalDeviceRepository
- 注册
-
X1.Domain/Entities/Terminal/TerminalService.cs
- 将
DeviceCode字段重命名为ServiceCode - 更新
Create和Update方法中的参数名 - 更新字段注释
- 将
-
X1.Domain/Repositories/Terminal/ITerminalServiceRepository.cs
- 将
DeviceCodeExistsAsync方法重命名为ServiceCodeExistsAsync - 更新方法注释
- 将
-
X1.Infrastructure/Repositories/Terminal/TerminalServiceRepository.cs
- 更新搜索方法中的字段引用
- 将
DeviceCodeExistsAsync方法重命名为ServiceCodeExistsAsync - 更新
GetServiceBasicInfoListAsync方法中的字段映射
-
X1.Domain/Models/DeviceBasicInfo.cs
- 将
DeviceCode属性重命名为ServiceCode - 更新类注释和方法注释
- 将
-
X1.Infrastructure/Configurations/Terminal/TerminalServiceConfiguration.cs
- 更新属性配置从
DeviceCode到ServiceCode - 更新索引配置
- 更新属性配置从
字段说明
Brand: 设备品牌 (必填,最大50字符)Model: 设备型号 (必填,最大100字符)Device: 设备标识 (必填,最大50字符)Name: 设备名称 (必填,最大100字符)AndroidVersion: Android版本 (最大20字符)SdkVersion: SDK版本 (最大10字符)BuildId: 构建ID (最大100字符)BuildType: 构建类型 (最大20字符)Serial: 设备序列号 (必填,最大50字符,唯一索引)BootSerial: 启动序列号 (最大50字符)Hardware: 硬件信息 (最大100字符)HardwarePlatform: 硬件平台 (最大100字符)Locale: 区域设置 (最大20字符)Status: 设备状态 (枚举类型,TerminalDeviceStatus.Online表示在线,TerminalDeviceStatus.Offline表示离线)DeviceCode: 设备编码 (必填,最大50字符,唯一索引)ServiceSerial: 关联的终端服务序列号 (必填,最大50字符,索引)IsEnabled: 是否启用 (默认true)IsBound: 是否被绑定 (默认false)LastConnectedAt: 最后连接时间LastDisconnectedAt: 最后断开时间Description: 设备描述 (最大500字符)
业务方法
Create(): 创建终端设备Update(): 更新设备信息(仅允许修改 Description、IsBound、IsEnabled)SetOnline(): 设置设备在线状态SetOffline(): 设置设备离线状态Enable(): 启用设备Disable(): 禁用设备Bind(): 绑定设备Unbind(): 解绑设备UpdateDescription(): 更新设备描述
字段修改限制
- 不可修改字段:Brand、Model、Device、Name、AndroidVersion、SdkVersion、BuildId、BuildType、Serial、BootSerial、Hardware、HardwarePlatform、Locale、Status、ServiceSerial
- 可修改字段:Description、Alias、IsBound、IsEnabled、LastConnectedAt、LastDisconnectedAt
- 自动更新字段:UpdatedAt(在修改时自动更新)
关联关系
TerminalServiceSerialNumber字段用于关联TerminalService.SerialNumber,建立终端设备与终端服务的一对一关系
2024-12-19 - 重新迁移数据库
操作内容
执行了数据库迁移命令,更新数据库结构以匹配最新的实体模型。
执行命令
dotnet ef database update --project X1.Infrastructure --startup-project X1.WebAPI
执行结果
- ✅ 构建成功
- ✅ 数据库配置验证通过
- ✅ JWT配置验证通过
- ✅ 邮件配置验证通过
- ✅ 数据库迁移成功完成
注意事项
- 系统显示了一些警告信息,主要是关于Identity实体的映射和查询过滤器配置
- 这些警告不影响数据库迁移的正常执行
- 数据库结构已成功更新到最新版本
2024-12-19 - 创建终端相关表并应用数据库迁移
问题描述
用户反馈终端相关表(TerminalService、TerminalDevice、AdbOperation、AtOperation)在数据库中查不到。
问题分析
- 检查发现只有初始迁移
20250801075432_InitialCreate,没有包含终端相关表的迁移 - 虽然实体和配置都已存在,但数据库中没有对应的表结构
- 需要创建新的迁移来添加这些表
解决方案
-
创建新迁移:
dotnet ef migrations add AddTerminalTables --project X1.Infrastructure --startup-project X1.WebAPI -
应用迁移到数据库:
dotnet ef database update --project X1.Infrastructure --startup-project X1.WebAPI
创建的迁移文件
- 20250815154347_AddTerminalTables.cs - 包含所有终端相关表的创建语句
创建的表结构
-
tb_terminal_services - 终端服务表
- 包含服务基本信息:名称、序列号、服务编码、描述
- 包含网络配置:代理端口、IP地址
- 包含状态管理:是否启用、服务是否启动、服务类型
- 包含审计字段:创建时间、更新时间、创建人、更新人
-
tb_terminal_devices - 终端设备表
- 包含设备基本信息:品牌、型号、设备标识、名称、别名
- 包含Android信息:版本、SDK版本、构建信息
- 包含硬件信息:序列号、启动序列号、硬件平台
- 包含状态管理:设备状态、是否启用、是否被绑定
- 包含连接时间:最后连接时间、最后断开时间
-
tb_adboperations - ADB操作表
- 包含命令信息:ADB命令、描述、路径
- 包含执行配置:是否使用绝对路径、等待时间
- 包含截图数据:操作截图(字节数组)
- 包含审计字段:创建时间、更新时间、创建人、更新人
-
tb_atoperations - AT操作表
- 包含设备信息:设备ID、串口端口
- 包含串口配置:波特率、数据位、校验位、停止位
- 包含命令信息:AT命令、参数、超时时间、描述
- 包含截图数据:操作截图(字节数组)
- 包含审计字段:创建时间、更新时间、创建人、更新人
创建的索引
- 为所有表创建了相应的索引以提高查询性能
- 为唯一字段创建了唯一索引(如序列号、服务编码等)
- 为常用查询字段创建了普通索引(如状态、创建时间等)
执行结果
- ✅ 构建成功
- ✅ 数据库配置验证通过
- ✅ 所有表创建成功
- ✅ 所有索引创建成功
- ✅ 迁移记录已保存到数据库
验证结果
- 迁移列表显示两个迁移:
InitialCreate和AddTerminalTables - 所有终端相关表现在都可以在数据库中正常查询
- 表结构完整,包含所有必要的字段和约束
2025-01-16 终端服务前端字段名修复
修改文件:
X1.WebUI/src/services/terminalService.ts- 修复接口字段名X1.WebUI/src/pages/terminal-services/TerminalServicesTable.tsx- 修复表格字段映射X1.WebUI/src/pages/terminal-services/TerminalServiceForm.tsx- 修复表单字段名X1.WebUI/src/pages/terminal-services/TerminalServicesView.tsx- 修复列配置字段名
修改内容:
-
服务接口字段名修复:
- TerminalService接口:
deviceCode→serviceCodedeviceType→serviceType
- CreateTerminalServiceRequest接口:
deviceName→serviceName
- CreateTerminalServiceResponse接口:
deviceId→serviceIddeviceName→serviceNamedeviceCode→serviceCodedeviceType→serviceType
- UpdateTerminalServiceRequest接口:
deviceId→serviceId
- UpdateTerminalServiceResponse接口:
deviceId→serviceIddeviceName→serviceNamedeviceCode→serviceCodedeviceType→serviceType
- TerminalService接口:
-
表格组件字段映射修复:
- renderCell方法:
deviceType→serviceType
- columns配置:
deviceType→serviceType
- renderCell方法:
-
表单组件字段名修复:
- formData状态:
deviceName→serviceName
- handleSubmit方法:
deviceId→serviceId
- 表单字段:
deviceName→serviceName
- formData状态:
-
主视图组件列配置修复:
- defaultColumns配置:
deviceCode→serviceCodedeviceType→serviceType
- defaultColumns配置:
-
技术特性:
- 一致性:确保前端字段名与后端API完全一致
- 类型安全:修复TypeScript类型定义
- 功能完整:保持所有CRUD操作功能正常
- 用户体验:确保表格显示和表单操作正常
修改时间:
2025-01-16
修改原因:
修复前端组件中的字段名与后端API不一致的问题,确保终端服务管理功能正常工作。主要问题是前端使用了旧的字段名(如deviceCode、deviceType),而后端API使用的是新的字段名(如serviceCode、serviceType)。
2025-01-16 终端服务表格按钮图标化优化
修改文件:
X1.WebUI/src/pages/terminal-services/TerminalServicesTable.tsx - 将编辑和删除按钮改为纯图标
修改内容:
-
功能描述:
- 将终端服务表格中的编辑和删除按钮改为纯图标,去掉按钮边框和样式
- 使用原生
button元素替代Button组件 - 保持图标颜色和悬停效果,提供更好的视觉体验
-
按钮样式优化:
- 移除按钮组件:将
Button组件改为原生button元素 - 去掉边框:移除
variant="outline"和size="sm"属性 - 简化样式:只保留颜色、悬停效果和基本内边距
- 调整内边距:从
p-2改为p-1,使图标更紧凑
- 移除按钮组件:将
-
颜色方案:
- 启动按钮:绿色 (
text-green-600 hover:text-green-700) - 停止按钮:红色 (
text-red-600 hover:text-red-700) - 编辑按钮:蓝色 (
text-blue-600 hover:text-blue-700) - 删除按钮:红色 (
text-red-600 hover:text-red-700)
- 启动按钮:绿色 (
-
用户体验改进:
- 界面更加简洁,没有多余的边框和背景
- 图标颜色区分不同操作类型
- 悬停效果提供交互反馈
- 保持 tooltip 提示功能
-
技术实现:
- 使用原生 HTML
button元素 - 保持所有点击事件和功能不变
- 使用 Tailwind CSS 类进行样式控制
- 图标尺寸保持
h-4 w-4一致性
- 使用原生 HTML
修改时间:
2025-01-16
修改原因:
用户反馈按钮边框太丑,要求改为纯图标样式,去掉边框和按钮背景,提供更简洁美观的界面。
TerminalMessageHandler 实现 IBaseTerminalClient 接口
修改文件:
X1.WebSocket/Handlers/TerminalMessageHandler.csX1.WebSocket/Extensions/ServiceCollectionExtensions.csX1.Domain/ThirdPartyDeviceHttpClient/ITerminal/IBaseTerminalClient.csX1.DynamicClientCore/Service/TestTerminalRequestClient.cs
修改内容:
-
接口实现:
- TerminalMessageHandler:现在同时实现
IWebSocketMessageHandler和IBaseTerminalClient接口 - 添加了
IDynamicHttpClient依赖注入,用于HTTP请求操作 - 保持了原有的WebSocket消息处理功能
- TerminalMessageHandler:现在同时实现
-
新增方法实现:
-
GetDeviceSerialNumberAsync:获取测试终端机器码数据
- 完整的参数验证和异常处理
- 使用
IDynamicHttpClient调用机器码API - 详细的日志记录和错误处理
- 返回
MachineCodeData对象,包含机器码和系统类型
-
CreateTerminalWebSocketAsync:创建并连接终端 WebSocket 客户端
- 验证请求参数(客户端名称和连接地址)
- 使用
IDynamicHttpClient调用WebSocket客户端创建API - 完整的错误处理和日志记录
- 返回
TerminalWebSocketResponse对象
-
DisconnectTerminalWebSocketAsync:断开终端 WebSocket 客户端连接
- 验证客户端名称参数
- 使用
IDynamicHttpClient调用WebSocket客户端断开连接API - 支持 DELETE 请求方法
- 完整的错误处理和日志记录
- 返回
TerminalWebSocketResponse对象
-
-
接口扩展:
- IBaseTerminalClient:添加了
DisconnectTerminalWebSocketAsync方法- 支持断开指定的WebSocket客户端连接
- 完整的参数验证和异常处理
- 统一的响应格式
- IBaseTerminalClient:添加了
-
依赖注入更新:
- 构造函数添加了
IDynamicHttpClient参数 - 保持了原有的
ILogger和IMediator依赖 - 所有依赖都进行了空值检查和异常处理
- ServiceCollectionExtensions:添加了
TerminalMessageHandler作为IBaseTerminalClient的注册 - 添加了必要的 using 语句:
using X1.Domain.ThirdPartyDeviceHttpClient.ITerminal;
- 构造函数添加了
-
技术特性:
- 双重职责:既处理WebSocket消息,又提供终端客户端功能
- 完整实现:实现了
IBaseTerminalClient接口的所有方法 - 错误处理:统一的异常处理和日志记录
- 参数验证:严格的输入参数验证
- 异步支持:所有方法都支持异步操作和取消令牌
-
API端点配置:
- 机器码获取:使用
{terminalId}/system/machine-code端点 - WebSocket客户端创建:使用
websocket/websocket/clients端点 - WebSocket客户端断开:使用
websocket/websocket/clients/{clientName}/disconnect端点 - 支持自定义请求选项和超时配置
- 机器码获取:使用
-
响应处理:
- 机器码API:使用
TestTerminalResponse<MachineCodeData>响应格式 - WebSocket客户端API:使用
TerminalWebSocketResponse响应格式 - 统一的成功/失败判断逻辑
- 机器码API:使用
-
日志记录:
- 详细的操作开始和完成日志
- 错误情况的警告和错误日志
- 包含关键参数(终端ID、客户端名称等)的结构化日志
-
依赖注入配置:
- 双重注册:
TerminalMessageHandler同时注册为IWebSocketMessageHandler和IBaseTerminalClient - 单例模式:使用单例生命周期,确保状态一致性
- 接口隔离:通过接口注册,支持依赖注入和单元测试
- 双重注册:
-
实现一致性:
- TerminalMessageHandler 和 TestTerminalRequestClient 都完整实现了
IBaseTerminalClient接口 - 两个实现类使用相同的API端点和响应格式
- 统一的错误处理和日志记录模式
- TerminalMessageHandler 和 TestTerminalRequestClient 都完整实现了
使用示例:
// 通过依赖注入获取处理器实例
var handler = serviceProvider.GetService<TerminalMessageHandler>();
// 获取机器码数据
var machineCodeData = await handler.GetDeviceSerialNumberAsync("terminal-001");
if (machineCodeData != null)
{
var machineCode = machineCodeData.MachineCode;
var systemType = machineCodeData.SystemType;
}
// 创建WebSocket客户端
var webSocketRequest = new TerminalWebSocketRequest
{
Name = "test_client",
Url = "ws://localhost:8080/ws",
HeartbeatInterval = 30
};
var webSocketResponse = await handler.CreateTerminalWebSocketAsync(webSocketRequest);
// 断开WebSocket客户端连接
var disconnectResponse = await handler.DisconnectTerminalWebSocketAsync("test_client");
if (disconnectResponse != null && disconnectResponse.Success)
{
Console.WriteLine($"客户端断开成功: {disconnectResponse.Message}");
}
设计原则:
- 单一职责扩展:在保持WebSocket消息处理功能的同时,扩展终端客户端功能
- 接口实现完整:完整实现
IBaseTerminalClient接口的所有方法 - 错误处理统一:使用统一的异常处理和日志记录模式
- 依赖注入规范:遵循依赖注入最佳实践
- 异步操作支持:所有方法都支持异步操作和取消令牌
修改时间:
2025年1月16日
修改原因:
为终端服务启动功能添加 WebSocket 客户端创建接口,支持与 WebSocket 服务器的连接管理,提高系统的实时通信能力。
CreateTerminalWebSocketAsync 方法实现完成
修改文件:
X1.Domain/ThirdPartyDeviceHttpClient/Models/TerminalWebSocketModels.cs(重新创建)X1.WebSocket/Handlers/TerminalMessageHandler.cs(已实现)
修改内容:
-
TerminalMessageHandler 实现状态:
-
✅ GetDeviceSerialNumberAsync:已完整实现
- 参数验证:检查
terminalId是否为空 - API调用:使用
IDynamicHttpClient.GetAsync调用机器码API - 端点配置:使用
{terminalId}/system/machine-code端点 - 响应处理:使用
TestTerminalResponse<MachineCodeData>格式 - 错误处理:完整的异常捕获和日志记录
- 返回数据:包含机器码和系统类型信息
- 参数验证:检查
-
✅ CreateTerminalWebSocketAsync:已完整实现
- 参数验证:检查
request、Name、Url是否为空 - API调用:使用
IDynamicHttpClient.PostAsync调用WebSocket客户端创建API - 端点配置:使用
websocket/websocket/clients端点 - 响应处理:使用
TerminalWebSocketResponse格式 - 错误处理:完整的异常捕获和日志记录
- 返回数据:包含客户端状态和通道信息
- 参数验证:检查
-
-
模型文件重新创建:
- TerminalWebSocketRequest:终端 WebSocket 客户端创建请求模型
Name:客户端名称Url:WebSocket 连接地址HeartbeatInterval:心跳间隔(秒),默认30
- TerminalWebSocketData:终端 WebSocket 客户端数据模型
Name:客户端名称Url:WebSocket 连接地址Status:连接状态HeartbeatInterval:心跳间隔(秒)Channels:支持的通道列表
- TerminalWebSocketResponse:终端 WebSocket 客户端创建响应模型
Message:响应消息Data:响应数据Timestamp:时间戳Success:是否成功,默认true
- TerminalWebSocketRequest:终端 WebSocket 客户端创建请求模型
-
依赖注入配置:
- ✅ ServiceCollectionExtensions:已配置
TerminalMessageHandler作为IBaseTerminalClient的实现 - ✅ 双重注册:同时注册为
IWebSocketMessageHandler和IBaseTerminalClient - ✅ 单例模式:使用单例生命周期,确保状态一致性
- ✅ ServiceCollectionExtensions:已配置
-
技术特性:
- 双重职责:既处理WebSocket消息,又提供终端客户端功能
- 完整实现:实现了
IBaseTerminalClient接口的所有方法 - 错误处理:统一的异常处理和日志记录
- 参数验证:严格的输入参数验证
- 异步支持:所有方法都支持异步操作和取消令牌
- 详细日志:包含关键参数的结构化日志记录
-
API端点配置:
- 机器码获取:
{terminalId}/system/machine-code - WebSocket客户端创建:
websocket/websocket/clients - 支持自定义请求选项和超时配置
- 机器码获取:
-
响应格式:
- 机器码API:
TestTerminalResponse<MachineCodeData> - WebSocket客户端API:
TerminalWebSocketResponse - 统一的成功/失败判断逻辑
- 机器码API:
使用示例:
// 通过依赖注入获取处理器实例
var handler = serviceProvider.GetService<TerminalMessageHandler>();
// 创建WebSocket客户端
var webSocketRequest = new TerminalWebSocketRequest
{
Name = "test_client",
Url = "ws://localhost:8080/ws",
HeartbeatInterval = 30
};
var webSocketResponse = await handler.CreateTerminalWebSocketAsync(webSocketRequest);
if (webSocketResponse?.Success == true)
{
var clientName = webSocketResponse.Data?.Name;
var status = webSocketResponse.Data?.Status;
var channels = webSocketResponse.Data?.Channels;
}
设计原则:
- 单一职责扩展:在保持WebSocket消息处理功能的同时,扩展终端客户端功能
- 接口实现完整:完整实现
IBaseTerminalClient接口的所有方法 - 错误处理统一:使用统一的异常处理和日志记录模式
- 依赖注入规范:遵循依赖注入最佳实践
- 异步操作支持:所有方法都支持异步操作和取消令牌
修改时间:
2025年1月16日
修改原因:
完成 CreateTerminalWebSocketAsync 方法的实现,使 TerminalMessageHandler 能够完整提供终端客户端功能,支持WebSocket客户端的创建和管理。
2025-01-16 TerminalMessageEventHandler 依赖注入问题修复
修改文件:
X1.Application/Features/TerminalMessageEvents/TerminalMessageEventHandler.cs - 修复作用域服务依赖注入问题
修改内容:
-
问题描述:
TerminalMessageEventHandler直接依赖ITerminalDeviceRepository导致依赖注入错误- MediatR 注册
INotificationHandler时默认使用单例生命周期 ITerminalDeviceRepository被注册为作用域服务,无法在单例中直接注入
-
解决方案:
- 使用
IServiceScopeFactory替代直接依赖注入 - 在
Handle方法中创建作用域来获取仓储服务 - 确保作用域在方法结束时正确释放
- 使用
-
具体修改:
-
构造函数修改:
- 移除
ITerminalDeviceRepository直接依赖 - 添加
IServiceScopeFactory依赖注入 - 保持
ILogger依赖不变
- 移除
-
Handle方法修改:
- 使用
_serviceScopeFactory.CreateScope()创建作用域 - 通过
scope.ServiceProvider.GetRequiredService<ITerminalDeviceRepository>()获取仓储服务 - 使用
using语句确保作用域正确释放
- 使用
-
ProcessTerminalMessageAsync方法修改:
- 添加
ITerminalDeviceRepository terminalRepository参数 - 将仓储服务作为参数传递,而不是使用字段
- 更新所有仓储方法调用
- 添加
-
-
技术特性:
- 作用域管理:正确管理服务作用域的生命周期
- 资源释放:使用
using语句确保作用域及时释放 - 依赖注入:遵循依赖注入最佳实践
- 错误处理:保持完整的异常处理和日志记录
- 性能优化:避免长时间持有作用域引用
-
设计原则:
- 单一职责:每个方法专注于特定功能
- 依赖倒置:通过接口依赖而不是具体实现
- 资源管理:正确管理服务作用域的生命周期
- 错误处理:统一的异常处理和日志记录
修改时间:
2025-01-16
修改原因:
修复 TerminalMessageEventHandler 中的依赖注入问题,解决 MediatR 单例处理器无法直接注入作用域服务的问题,确保终端消息事件能够正常处理。
2025-01-15 - AdbOperation 实体添加 DeviceId 字段
修改文件
- X1.Domain/Entities/Terminal/AdbOperation.cs
修改内容
-
新增字段:
- 添加了
DeviceId属性,类型为string,默认值为空字符串 - 该字段与
TerminalDevice的Serial字段关联,用于标识ADB操作所属的设备
- 添加了
-
更新 Create 方法:
- 添加了
deviceId参数 - 添加了设备ID的必填验证
- 在创建实例时设置
DeviceId属性
- 添加了
-
更新 Update 方法:
- 添加了
deviceId参数 - 添加了设备ID的必填验证
- 在更新时设置
DeviceId属性
- 添加了
-
新增 SetDeviceId 方法:
- 提供了专门用于设置设备ID的方法
- 包含参数验证和审计信息更新
技术特性
- 必填验证:设备ID为必填项,不能为空
- 数据关联:与 TerminalDevice 的 Serial 字段建立关联关系
- 审计支持:所有修改都会更新审计信息
- 参数验证:确保数据完整性和一致性
数据关联说明
- ADB 操作的设备ID 取的是
terminal-devices表中的serial字段 - 关联关系:
AdbOperation.DeviceId=TerminalDevice.Serial - 前端显示:设备选择下拉框显示
{设备别名或名称} - {设备品牌} ({序列号})格式 - 数据存储:后端将选中的序列号存储到
AdbOperation.DeviceId字段
影响范围
- 需要更新相关的 Command 和 Query 类以支持 DeviceId 参数
- 需要更新前端表单以包含设备选择功能
- 需要更新数据库迁移脚本
- 需要更新相关的 DTO 和响应类
后续更新
-
CreateAdbOperationCommand 和 Response:
- 添加了
DeviceId字段 - 更新了 CommandHandler 以支持设备ID参数
- 添加了
-
前端服务接口:
- 更新了
AdbOperation接口,添加deviceId字段 - 更新了
CreateAdbOperationRequest和CreateAdbOperationResponse接口
- 更新了
-
前端表单组件:
- 添加了设备选择功能
- 集成了终端设备服务
- 添加了设备ID的必填验证
- 支持多条命令输入,每条命令带时间
- 路径设为可选,描述不做限制
2025-01-16 - Dockerfile优化:提供开发调试支持
修改文件
- X1.WebAPI/Dockerfile - 使用完整版本镜像
- X1.WebAPI/Dockerfile.dev - 创建开发环境专用Dockerfile
问题描述
使用 mcr.microsoft.com/dotnet/aspnet:8.0-jammy-chiseled 精简镜像时,容器内没有bash或sh shell,导致无法使用 docker exec -it 进入容器进行调试。
解决方案
方案1:生产环境Dockerfile(推荐)
使用完整版本的镜像,提供基本的调试支持:
# 使用官方.NET 8.0运行时镜像作为基础镜像(完整版本,支持调试)
FROM mcr.microsoft.com/dotnet/aspnet:8.0-jammy
# 设置工作目录
WORKDIR /app
# 设置环境变量
ENV ASPNETCORE_ENVIRONMENT=Production
ENV ASPNETCORE_URLS=http://+:12789
# 复制发布文件到容器中
COPY publish/ .
# 暴露端口12789
EXPOSE 12789
# 设置应用启动命令
ENTRYPOINT ["./X1.WebAPI"]
方案2:开发环境Dockerfile(完整调试支持)
创建专门的开发环境Dockerfile,提供完整的调试工具:
# 开发环境Dockerfile - 提供完整的调试支持
FROM mcr.microsoft.com/dotnet/aspnet:8.0-jammy
# 安装开发调试工具
RUN apt-get update && apt-get install -y \
bash \
curl \
wget \
vim \
nano \
htop \
procps \
net-tools \
iputils-ping \
telnet \
&& rm -rf /var/lib/apt/lists/*
# 设置工作目录
WORKDIR /app
# 设置环境变量(开发环境)
ENV ASPNETCORE_ENVIRONMENT=Development
ENV ASPNETCORE_URLS=http://+:12789
ENV DOTNET_USE_POLLING_FILE_WATCHER=1
# 复制发布文件到容器中
COPY publish/ .
# 暴露端口12789
EXPOSE 12789
# 设置应用启动命令
ENTRYPOINT ["./X1.WebAPI"]
修改内容
生产环境Dockerfile
- 镜像选择:从
jammy-chiseled改为jammy - 调试支持:完整镜像包含bash、sh等基本工具
- 性能平衡:在调试便利性和镜像大小之间取得平衡
开发环境Dockerfile
- 完整工具集:安装常用的调试和网络工具
- 开发环境配置:设置Development环境和文件监视
- 调试工具:包含vim、nano、htop、net-tools等
技术特性
生产环境特性
- 基本调试:支持bash shell和基本命令
- 镜像优化:比精简镜像稍大,但包含必要工具
- 安全平衡:保持相对安全的镜像环境
开发环境特性
- 完整调试:提供完整的Linux工具集
- 网络诊断:包含ping、telnet、net-tools等
- 系统监控:包含htop、procps等监控工具
- 文件编辑:包含vim、nano等编辑器
使用方法
生产环境部署
# 构建生产镜像
docker build -t x1-webapi:latest .
# 运行生产容器
docker run -d --name x1-webapi -p 12789:12789 x1-webapi:latest
# 进入容器调试
docker exec -it <container_id> /bin/bash```
#### 开发环境部署
```bash
# 构建开发镜像
docker build -f Dockerfile.dev -t x1-webapi:dev .
# 运行开发容器
docker run -d --name x1-webapi-dev -p 12789:12789 x1-webapi:dev
# 进入容器调试
docker exec -it <container_id> /bin/bash
# 使用开发工具
docker exec -it <container_id> htop
docker exec -it <container_id> ping google.com
docker exec -it <container_id> netstat -tulpn
开发工具说明
网络诊断工具
- ping:网络连通性测试
- telnet:端口连通性测试
- net-tools:网络配置和状态查看
- curl/wget:HTTP请求测试
系统监控工具
- htop:进程监控和系统资源查看
- procps:进程管理工具
- ps:进程状态查看
文件编辑工具
- vim:高级文本编辑器
- nano:简单文本编辑器
部署建议
生产环境
- 使用
Dockerfile(完整版本镜像) - 提供基本调试支持
- 保持相对安全的镜像环境
开发环境
- 使用
Dockerfile.dev(完整工具集) - 提供完整的调试和诊断工具
- 便于问题排查和系统分析
测试环境
- 根据需求选择对应的Dockerfile
- 可以先用开发版本进行测试
- 确认无误后使用生产版本
优势对比
| 特性 | 精简镜像 | 完整镜像 | 开发镜像 |
|---|---|---|---|
| 镜像大小 | 最小 | 中等 | 较大 |
| 调试支持 | 无 | 基本 | 完整 |
| 安全风险 | 最低 | 中等 | 较高 |
| 开发便利性 | 差 | 好 | 最好 |
| 生产适用性 | 最佳 | 好 | 不推荐 |
注意事项
- 生产环境:建议使用完整镜像,平衡调试需求和安全性
- 开发环境:可以使用开发镜像,提供完整的调试工具
- 镜像大小:完整镜像比精简镜像大约增加50-100MB
- 安全考虑:开发镜像包含更多工具,安全风险相对较高
修改时间:
2025-01-16
修改原因:
优化Docker镜像配置,提供更好的开发调试支持。使用完整版本镜像解决无法进入容器的问题,同时创建专门的开发环境Dockerfile,为不同环境提供合适的调试工具支持。
2025-01-16 - deploy.sh脚本更新:支持开发环境部署
修改文件
X1.WebAPI/deploy.sh - 添加开发环境部署支持
功能增强
为deploy.sh脚本添加了命令行参数支持,可以根据不同环境选择对应的Dockerfile进行部署。
新增功能
1. 命令行参数支持
# 生产环境部署(默认)
./deploy.sh
# 开发环境部署
./deploy.sh --dev
# 显示帮助信息
./deploy.sh --help
2. 环境配置
-
生产环境:
- Dockerfile:
Dockerfile - 镜像名称:
x1-webapi - 容器名称:
x1-webapi-container - 环境变量:
ASPNETCORE_ENVIRONMENT=Production
- Dockerfile:
-
开发环境:
- Dockerfile:
Dockerfile.dev - 镜像名称:
x1-webapi-dev - 容器名称:
x1-webapi-dev-container - 环境变量:
ASPNETCORE_ENVIRONMENT=Development
- Dockerfile:
3. 智能构建逻辑
- 生产环境:使用
docker build -t x1-webapi:latest . - 开发环境:使用
docker build -f Dockerfile.dev -t x1-webapi-dev:latest .
4. 环境特定功能
- 文件检查:根据环境检查对应的Dockerfile是否存在
- 权限设置:为对应的Dockerfile设置正确的权限
- 容器管理:使用环境特定的容器名称进行管理
- 调试信息:开发环境显示额外的调试命令
技术特性
参数解析
- 使用
parse_arguments()函数解析命令行参数 - 支持
--dev、--help、-h参数 - 提供详细的帮助信息和使用说明
环境隔离
- 不同环境使用不同的镜像和容器名称
- 避免生产环境和开发环境的冲突
- 支持同时运行多个环境
智能检测
- 自动检测Dockerfile是否存在
- 根据环境提供相应的错误提示
- 动态调整构建和运行参数
使用方法
生产环境部署
# 标准生产环境部署
./deploy.sh
# 输出示例
==========================================
X1.WebAPI Docker 部署脚本
开始时间: 2025-01-16 15:30:00
==========================================
部署环境: production
使用Dockerfile: Dockerfile
镜像名称: x1-webapi
容器名称: x1-webapi-container
==========================================
开发环境部署
# 开发环境部署
./deploy.sh --dev
# 输出示例
==========================================
X1.WebAPI Docker 部署脚本
开始时间: 2025-01-16 15:30:00
==========================================
部署环境: development
使用Dockerfile: Dockerfile.dev
镜像名称: x1-webapi-dev
容器名称: x1-webapi-dev-container
端口: 12790
操作模式: 部署模式
==========================================
帮助信息
# 显示帮助
./deploy.sh --help
# 输出示例
X1.WebAPI Docker 部署脚本
使用方法:
./deploy.sh # 生产环境部署
./deploy.sh --dev # 开发环境部署
./deploy.sh --remove # 删除当前环境容器和镜像
./deploy.sh --dev --remove # 删除开发环境容器和镜像
./deploy.sh --help # 显示帮助信息
环境说明:
生产环境: 使用 Dockerfile,包含基本调试工具
开发环境: 使用 Dockerfile.dev,包含完整调试工具集
开发环境包含的额外工具:
- 网络诊断: ping, telnet, net-tools, curl, wget
- 系统监控: htop, procps, ps
- 文件编辑: vim, nano
- 基本工具: bash, procps
删除功能:
--remove: 删除指定环境的容器和镜像,释放资源
部署信息增强
生产环境信息
容器管理命令:
查看状态: docker ps | grep x1-webapi-container
查看日志: docker logs x1-webapi-container
重启容器: docker restart x1-webapi-container
停止容器: docker stop x1-webapi-container
开发环境信息
容器管理命令:
查看状态: docker ps | grep x1-webapi-dev-container
查看日志: docker logs x1-webapi-dev-container
重启容器: docker restart x1-webapi-dev-container
停止容器: docker stop x1-webapi-dev-container
开发环境调试命令:
进入容器: docker exec -it x1-webapi-dev-container /bin/bash
系统监控: docker exec -it x1-webapi-dev-container htop
网络测试: docker exec -it x1-webapi-dev-container ping google.com
端口检查: docker exec -it x1-webapi-dev-container netstat -tulpn
查看进程: docker exec -it x1-webapi-dev-container ps aux
优势
环境隔离
- 生产环境和开发环境完全隔离
- 避免环境间的相互影响
- 支持并行部署和测试
灵活部署
- 一键切换部署环境
- 统一的部署流程
- 环境特定的配置和工具
调试便利
- 开发环境提供完整的调试工具
- 详细的调试命令提示
- 环境特定的日志和监控
运维友好
- 清晰的帮助信息
- 详细的部署状态反馈
- 环境特定的管理命令
注意事项
- 确保
Dockerfile.dev文件存在(开发环境部署时) - 不同环境的容器名称不同,避免冲突
- 开发环境镜像包含更多工具,体积较大
- 生产环境建议使用标准Dockerfile
修改时间:
2025-01-16
修改原因:
为deploy.sh脚本添加开发环境部署支持,提供灵活的环境选择功能,满足不同场景的部署需求,提高开发和运维效率。
2025-01-19 - 修复 API 路径常量重复 /api 前缀问题
修改文件:
X1.WebUI/src/constants/api.ts - 修复 API 路径常量中的重复 /api 前缀
修改内容:
-
问题分析:
- 环境配置中
VITE_API_BASE_URL已经包含/api后缀:https://localhost:7268/api - API 路径常量中又添加了
/api前缀:/api/testcaseflow - 导致最终 URL 变成:
https://localhost:7268/api/api/testcaseflow(错误)
- 环境配置中
-
修复方案:
- TEST_CASE_FLOW:从
/api/testcaseflow改为/testcaseflow - CASE_STEP_CONFIGS:从
/api/casestepconfigs改为/casestepconfigs
- TEST_CASE_FLOW:从
-
修复后的 URL 组合:
- 基础 URL:
https://localhost:7268/api - API 路径:
/testcaseflow - 最终 URL:
https://localhost:7268/api/testcaseflow(正确)
- 基础 URL:
-
技术说明:
- 环境配置中的
baseURL已经包含了/api路径 - API 路径常量应该只包含相对路径,不包含
/api前缀 - 这样可以避免路径重复,确保正确的 API 调用
- 环境配置中的
修改时间:
2025-01-19
修改原因:
用户发现 API 请求失败,检查发现 API 路径常量中重复了 /api 前缀,导致最终 URL 错误。需要修复路径配置以确保正确的 API 调用。
2025-01-19 - 修复 TestFlowType 枚举类型不匹配问题
修改文件:
X1.WebUI/src/services/testcaseService.ts- 修复 TestFlowType 类型定义X1.WebUI/src/pages/testcases/TestCasesView.tsx- 修复 TestFlowType 使用
修改内容:
-
问题分析:
- 后端枚举:
Registration = 1,Voice = 2,Data = 3(数字枚举) - 前端发送:
"Registration"(字符串) - 问题:后端期望数字枚举值,前端发送字符串,导致类型不匹配
- 后端枚举:
-
修复方案:
- TestFlowType 类型定义:从字符串联合类型改为数字联合类型
- 请求数据:使用数字值而不是字符串值
-
具体修改:
// 修复前 export type TestFlowType = 'Registration' | 'Voice' | 'Data'; type: 'Registration' as TestFlowType, // 修复后 export type TestFlowType = 1 | 2 | 3; type: 1 as TestFlowType, // Registration = 1 -
枚举对应关系:
1=Registration(注册测试)2=Voice(语音测试)3=Data(数据测试)
-
技术说明:
- 后端使用 C# 数字枚举,前端需要发送对应的数字值
- 这样可以确保前后端类型完全匹配
- 避免了字符串到数字的转换问题
修改时间:
2025-01-19
修改原因:
用户发现 API 请求失败,检查发现前端发送的 TestFlowType 是字符串,而后端期望的是数字枚举值,导致类型不匹配。需要修复类型定义以确保前后端数据格式一致。
- 设备运行时处理失败:
- 设备运行时不存在
- 数据库保存失败
已实施的修复
-
增强网络配置构建阶段的日志记录:
- 添加了设备过滤统计信息
- 记录每个设备的配置验证结果
- 显示原始请求数和有效请求数的对比
-
改进网络启动阶段的错误信息:
- 在失败设备日志中包含具体的错误信息
- 添加网络启动结果统计日志
-
增强设备运行时处理阶段的日志:
- 记录成功启动网络的设备数量
- 记录每个设备运行时的当前状态
- 提供更详细的处理过程信息
问题排查建议
根据增强的日志记录,现在可以更容易地定位问题:
- 检查网络配置构建阶段:查看是否有设备被过滤掉及其原因
- 检查网络启动阶段:查看具体的网络启动失败原因
- 检查设备运行时处理阶段:查看设备运行时是否存在及状态更新是否成功
建议在下次运行时查看详细的日志输出,以确定具体在哪个阶段出现了问题。
关键问题修复
问题:isSuccess 字段逻辑错误导致前端误判
- 原因:
OperationResult的IsSuccess属性只检查ErrorMessages是否为空,不考虑业务逻辑 - 影响:即使所有设备启动失败,只要没有异常抛出,
isSuccess仍为true - 修复:根据业务逻辑判断成功失败,只有当所有设备都成功启动时才返回成功
修复后的逻辑:
- 如果所有设备都成功启动:返回
CreateSuccess - 如果有任何设备启动失败:返回
CreateFailure并包含详细的错误信息
这样前端就能正确判断操作是否真正成功,避免误判。
修改时间:
2024-12-19
修改原因:
- 增强StartDeviceRuntimeCommandHandler的日志记录,帮助定位设备启动失败的具体原因
- 修复isSuccess字段逻辑错误,确保前端能正确判断操作成功失败状态
2025-01-21 - TestCaseFlow 删除功能修复
修改文件:
X1.Domain/Entities/TestCase/TestCaseFlow.cs- 移除ISoftDelete接口实现X1.Infrastructure/Configurations/TestCase/TestCaseFlowConfiguration.cs- 移除IsDeleted字段映射X1.Infrastructure/Repositories/TestCase/TestCaseFlowRepository.cs- 移除IsDeleted字段过滤
修改内容:
-
实体修改:
- 移除了
TestCaseFlow实体对ISoftDelete接口的实现 - 移除了
IsDeleted属性字段 - 现在
TestCaseFlow执行真正的物理删除,而不是软删除
- 移除了
-
数据库配置修改:
- 移除了
IsDeleted字段的数据库映射配置 - 不再在数据库中创建
isdeleted列
- 移除了
-
仓储实现修改:
- 移除了所有查询方法中对
IsDeleted字段的过滤条件 - 恢复了原来的查询逻辑,不再过滤已删除的记录
- 包括:
GetAllTestCaseFlowsAsync、GetTestCaseFlowByIdAsync、GetByNameAsync、GetByTypeAsync、GetEnabledFlowsAsync、GetTestCaseFlowWithDetailsAsync、NameExistsAsync、GetPagedFlowsAsync等方法
- 移除了所有查询方法中对
-
删除行为:
- 现在
DeleteTestCaseFlowCommandHandler会执行真正的物理删除 - 删除操作会从数据库中永久移除记录
- 由于
TestCaseFlow不再实现ISoftDelete,UnitOfWork.SaveChangesAsync会执行真正的删除操作
- 现在
-
保留软删除基础设施:
ISoftDelete接口仍然保留,供其他实体使用UnitOfWork.SaveChangesAsync中的软删除逻辑仍然保留- 将来如果需要为
TestCaseFlow重新启用软删除,只需要重新实现ISoftDelete接口即可
技术说明:
- 问题原因:之前
TestCaseFlow实现了ISoftDelete接口,导致删除操作被转换为更新操作(设置IsDeleted = true),但查询时没有正确过滤已删除的记录 - 解决方案:移除软删除实现,改为物理删除,确保数据真正从数据库中移除
- 兼容性:保留了软删除的基础设施,其他实体仍然可以使用软删除功能
修改时间:
2025-01-21
修改原因:
用户反馈 DeleteTestCaseFlowCommandHandler 无法真正删除数据,需要改为物理删除而不是软删除。
2024-12-19 - GetUserByIdQueryHandler CS7036 错误修复
修改文件:
X1.Application/Features/Users/Queries/GetUserById/GetUserByIdQueryHandler.cs- 修复构造函数参数错误
修改内容:
-
依赖注入更新:
- 添加了
RoleManager<AppRole>依赖注入 - 更新了构造函数参数,包含
roleManager参数 - 添加了必要的 using 语句:
System.Collections.Generic和System.Linq
- 添加了
-
角色信息获取:
- 使用
_userManager.GetRolesAsync(user)获取用户的角色名称 - 使用
_roleManager.FindByNameAsync(roleName)获取角色详细信息 - 正确构建
roleIds和roleNames列表
- 使用
-
UserDto 构造函数修复:
- 更新了
UserDto构造函数调用,提供所有必需的参数 - 包括新添加的
RoleIds和RoleNames参数 - 修复了 CS7036 编译错误
- 更新了
技术说明:
- 问题原因:之前修改
UserDto添加了RoleIds和RoleNames参数,但GetUserByIdQueryHandler没有更新相应的构造函数调用 - 解决方案:注入
RoleManager<AppRole>,获取用户的角色信息,并正确传递给UserDto构造函数 - 性能考虑:对于单个用户查询,角色获取的性能影响较小,但确保了数据完整性
修改时间:
2024-12-19
修改原因:
修复 GetUserByIdQueryHandler.cs 中的 CS7036 编译错误,确保 UserDto 构造函数接收所有必需的参数。
2024-12-19 - AppDbContext IdentityUserRole 配置修复
修改文件:
X1.Infrastructure/Context/AppDbContext.cs- 修复 IdentityUserRole 配置
修改内容:
-
移除 IdentityUserRole 忽略配置:
- 移除了
modelBuilder.Ignore<IdentityUserRole<string>>();配置 - 添加了注释说明为什么不能忽略 IdentityUserRole
- 移除了
-
问题原因:
- 之前错误地忽略了
IdentityUserRole<string>实体 - 导致
UserManager.GetRolesAsync()无法正常工作 - 出现 "Cannot create a DbSet for 'IdentityUserRole'" 错误
- 之前错误地忽略了
-
修复效果:
- 允许 Entity Framework 正确管理用户角色关系表
- 确保
GetAllUsersQueryHandler和GetUserByIdQueryHandler中的角色查询正常工作 - 保持 Identity 系统的完整性
技术说明:
- Identity 依赖:ASP.NET Core Identity 需要
IdentityUserRole<string>表来存储用户和角色的多对多关系 - 性能影响:移除忽略配置不会影响性能,反而确保了功能的正确性
- 兼容性:这个修复与现有的用户角色管理功能完全兼容
修改时间:
2024-12-19
修改原因:
修复 "Cannot create a DbSet for 'IdentityUserRole'" 错误,确保用户角色查询功能正常工作。
2025-01-21 - GetAllUsersQueryHandler 性能优化和批量查询实现
修改文件:
X1.Application/Features/Users/Queries/GetAllUsers/GetAllUsersQueryHandler.cs- 优化批量获取用户角色信息的方法X1.Domain/Repositories/Identity/IUserRoleRepository.cs- 添加批量查询方法接口X1.Infrastructure/Repositories/Identity/UserRoleRepository.cs- 实现批量查询方法
修改内容:
-
GetAllUsersQueryHandler 性能优化:
- 问题分析:原来的实现中,每个用户都需要单独查询角色信息,导致 N+1 查询问题
- 优化方案:
- 一次性获取所有角色信息:
await _roleManager.Roles.ToDictionaryAsync(r => r.Id, r => r, cancellationToken) - 批量获取所有用户的角色信息:
await _userRoleRepository.GetUsersRolesAsync(userIds, cancellationToken) - 避免在循环中进行数据库查询,提高性能
- 一次性获取所有角色信息:
-
IUserRoleRepository 接口扩展:
- 新增方法:
GetUsersRolesAsync(IEnumerable<string> userIds, CancellationToken cancellationToken = default) - 返回类型:
Task<Dictionary<string, List<string>>>- 用户ID到角色ID列表的映射 - 设计目的:支持批量查询多个用户的角色信息,避免循环查询
- 新增方法:
-
UserRoleRepository 实现:
- 实现逻辑:
- 使用
QueryRepository.FindAsync(ur => userIds.Contains(ur.UserId))一次性查询所有相关用户角色 - 使用
GroupBy和ToDictionary将结果按用户ID分组 - 返回用户ID到角色ID列表的字典映射
- 使用
- 性能优势:将 N 次查询优化为 1 次查询
- 实现逻辑:
-
技术特性:
- 查询优化:从 O(N) 查询复杂度优化为 O(1) 查询复杂度
- 内存效率:使用字典查找,避免重复的角色信息查询
- 数据一致性:确保所有用户都能正确获取到角色信息
- 错误处理:对于没有角色的用户,返回空列表而不是 null
-
性能提升:
- 数据库查询:从 N+1 次查询减少到 2 次查询(1次角色查询 + 1次用户角色查询)
- 响应时间:显著减少用户列表查询的响应时间
- 资源消耗:减少数据库连接和查询开销
修改时间:
2025-01-21
修改原因:
用户反馈角色数据不多,不需要每次都查询,需要优化 GetAllUsersQueryHandler 的性能,避免在循环中进行数据库查询,提高用户列表查询的效率。
2025-01-21 - CreateUserCommandHandler 事务保存修复
修改文件:
X1.Application/Features/Users/Commands/CreateUser/CreateUserCommandHandler.cs - 修复事务中缺少 SaveChangesAsync 调用的问题
修改内容:
-
问题分析:
- 原始问题:
CreateUserCommandHandler中的ExecuteTransactionAsync缺少SaveChangesAsync调用 - 对比发现:
RegisterUserCommandHandler中有正确的await _unitOfWork.SaveChangesAsync(cancellationToken);调用 - 影响:可能导致事务中的更改没有被正确保存到数据库
- 原始问题:
-
修复内容:
- 添加保存调用:在事务的最后添加
await _unitOfWork.SaveChangesAsync(cancellationToken); - 位置:在用户创建和角色分配成功后,事务提交前
- 确保原子性:保证用户创建和角色分配要么全部成功,要么全部回滚
- 添加保存调用:在事务的最后添加
-
修复后的流程:
await _unitOfWork.ExecuteTransactionAsync(async () => { // 1. 创建用户 var (success, errorMessage) = await _userRegistrationService.RegisterUserAsync(user, request.Password); // 2. 分配用户角色 (success, errorMessage) = await _userRegistrationService.AssignUserRolesAsync(user, request.RoleIds); // 3. 保存所有更改到数据库(新增) await _unitOfWork.SaveChangesAsync(cancellationToken); }, cancellationToken: cancellationToken); -
技术特性:
- 事务完整性:确保所有数据库操作在同一个事务中完成
- 原子性:用户创建和角色分配要么全部成功,要么全部失败
- 一致性:与
RegisterUserCommandHandler的实现保持一致 - 可靠性:避免数据不一致的问题
修改时间:
2025-01-21
修改原因:
用户发现 CreateUserCommandHandler 中的 ExecuteTransactionAsync 没有进行 SaveChangesAsync 调用,需要修复以确保事务中的更改能够正确保存到数据库。
2025-01-21 - DeleteUserCommandHandler 和 UpdateUserCommandHandler 事务保存修复
修改文件:
X1.Application/Features/Users/Commands/DeleteUser/DeleteUserCommandHandler.cs- 修复事务中缺少 SaveChangesAsync 调用的问题X1.Application/Features/Users/Commands/UpdateUser/UpdateUserCommandHandler.cs- 修复事务中缺少 SaveChangesAsync 调用的问题
修改内容:
-
问题分析:
- 原始问题:
DeleteUserCommandHandler和UpdateUserCommandHandler中的ExecuteTransactionAsync都缺少SaveChangesAsync调用 - 影响:可能导致事务中的更改没有被正确保存到数据库
- 发现方式:通过对比
RegisterUserCommandHandler的正确实现发现
- 原始问题:
-
DeleteUserCommandHandler 修复:
- 添加保存调用:在事务的最后添加
await _unitOfWork.SaveChangesAsync(cancellationToken); - 位置:在用户删除成功后,事务提交前
- 确保原子性:保证用户删除操作能够正确提交到数据库
- 添加保存调用:在事务的最后添加
-
UpdateUserCommandHandler 修复:
- 添加保存调用:在事务的最后添加
await _unitOfWork.SaveChangesAsync(cancellationToken); - 位置:在用户更新成功后,事务提交前
- 确保原子性:保证用户更新操作能够正确提交到数据库
- 添加保存调用:在事务的最后添加
-
修复后的流程:
// DeleteUserCommandHandler await _unitOfWork.ExecuteTransactionAsync(async () => { var result = await _userManager.DeleteAsync(user); if (!result.Succeeded) { /* 错误处理 */ } // 保存所有更改到数据库(新增) await _unitOfWork.SaveChangesAsync(cancellationToken); }, cancellationToken: cancellationToken); // UpdateUserCommandHandler await _unitOfWork.ExecuteTransactionAsync(async () => { var result = await _userManager.UpdateAsync(user); if (!result.Succeeded) { /* 错误处理 */ } // 保存所有更改到数据库(新增) await _unitOfWork.SaveChangesAsync(cancellationToken); }, cancellationToken: cancellationToken); -
技术特性:
- 事务完整性:确保所有数据库操作在同一个事务中完成
- 原子性:用户操作要么全部成功,要么全部失败
- 一致性:与
RegisterUserCommandHandler和CreateUserCommandHandler的实现保持一致 - 可靠性:避免数据不一致的问题
-
修复范围:
- DeleteUserCommandHandler:用户删除操作
- UpdateUserCommandHandler:用户更新操作
- CreateUserCommandHandler:用户创建操作(之前已修复)
- RegisterUserCommandHandler:用户注册操作(已有正确实现)
修改时间:
2025-01-21
修改原因:
用户发现 DeleteUserCommandHandler 和 UpdateUserCommandHandler 中的 ExecuteTransactionAsync 也没有进行 SaveChangesAsync 调用,需要修复以确保事务中的更改能够正确保存到数据库,保持与 RegisterUserCommandHandler 实现的一致性。
2025-01-21 - 优化GetTestCaseFlowByIdQueryHandler中的批量查询性能
问题描述
在 GetTestCaseFlowByIdQueryHandler 的 MapNodesToReactFlowFormatAsync 方法中,对每个节点都进行单独的数据库查询来获取步骤配置信息,导致 N+1 查询问题,影响性能。
修改内容
1. 添加批量查询接口
- 文件位置:
X1.Domain/Repositories/TestCase/ICaseStepConfigRepository.cs - 修改内容:
- 添加了
GetStepConfigsByIdsAsync方法,支持根据ID列表批量获取步骤配置 - 返回类型为
Dictionary<string, CaseStepConfig>,便于快速查找
- 添加了
2. 实现批量查询方法
- 文件位置:
X1.Infrastructure/Repositories/TestCase/CaseStepConfigRepository.cs - 修改内容:
- 实现了
GetStepConfigsByIdsAsync方法 - 使用
QueryRepository.FindAsync和ids.Contains(x.Id)进行批量查询 - 将结果转换为字典格式,键为ID,值为配置对象
- 实现了
3. 优化节点映射方法
- 文件位置:
X1.Application/Features/TestCaseFlow/Queries/GetTestCaseFlowById/GetTestCaseFlowByIdQueryHandler.cs - 修改内容:
- 在
MapNodesToReactFlowFormatAsync方法中,先收集所有需要查询的 StepId - 使用
GetStepConfigsByIdsAsync一次性批量查询所有步骤配置 - 在循环中使用字典查找替代单个查询
- 在
修改前后对比
修改前
foreach (var node in nodes)
{
// 获取步骤配置信息
X1.Domain.Entities.TestCase.CaseStepConfig? stepConfig = null;
if (!string.IsNullOrEmpty(node.StepId))
{
stepConfig = await _caseStepConfigRepository.GetStepConfigByIdAsync(node.StepId, cancellationToken);
}
// ... 其他处理逻辑
}
修改后
// 收集所有需要查询的StepId
var stepIds = nodes.Where(n => !string.IsNullOrEmpty(n.StepId))
.Select(n => n.StepId!)
.Distinct()
.ToList();
// 批量查询步骤配置
var stepConfigsDict = await _caseStepConfigRepository.GetStepConfigsByIdsAsync(stepIds, cancellationToken);
foreach (var node in nodes)
{
// 从字典中获取步骤配置信息
X1.Domain.Entities.TestCase.CaseStepConfig? stepConfig = null;
if (!string.IsNullOrEmpty(node.StepId))
{
stepConfigsDict.TryGetValue(node.StepId, out stepConfig);
}
// ... 其他处理逻辑
}
性能优化效果
- 查询次数: 从 N 次单个查询减少到 1 次批量查询
- 数据库负载: 显著减少数据库连接和查询压力
- 响应时间: 提高查询响应速度,特别是在节点数量较多时
- 资源利用: 更高效的数据库资源利用
技术特性
- 批量查询: 使用
ids.Contains(x.Id)进行高效的批量查询 - 字典查找: 使用字典进行 O(1) 时间复杂度的快速查找
- 去重处理: 使用
Distinct()避免重复查询相同的 StepId - 空值处理: 保持原有的空值检查逻辑,确保代码健壮性
影响范围
- 提高了测试用例流程详情查询的性能
- 减少了数据库查询次数和网络开销
- 保持了原有的业务逻辑和错误处理不变
- 向后兼容,不影响其他功能
测试建议
- 测试包含多个节点的测试用例流程查询
- 验证步骤配置信息正确获取
- 确认性能提升效果
- 测试边界情况(空节点、无效StepId等)
修改时间:
2025-01-21
修改原因:
用户要求优化 MapNodesToReactFlowFormatAsync 方法中的循环查询,将 N+1 查询问题改为一次性批量查询,以提高性能并减少数据库负载。
2025-01-21 - 添加 TestCaseEdge 实体的 sourceHandle 和 targetHandle 字段
问题描述
需要在 TestCaseEdge 实体中添加 sourceHandle 和 targetHandle 字段,以支持 ReactFlow 中连线的源节点和目标节点连接点信息。
修改内容
1. 更新 TestCaseEdge 实体
- 文件位置:
X1.Domain/Entities/TestCase/TestCaseEdge.cs - 修改内容:
- 添加了
SourceHandle属性,类型为string?,最大长度 50 字符 - 添加了
TargetHandle属性,类型为string?,最大长度 50 字符 - 更新了
Create方法的参数,添加sourceHandle和targetHandle参数 - 更新了
Update方法的参数,添加sourceHandle和targetHandle参数 - 在构造函数和更新方法中正确处理新字段的赋值
- 添加了
2. 更新 CreateTestCaseFlowCommand 的 EdgeData
- 文件位置:
X1.Application/Features/TestCaseFlow/Commands/CreateTestCaseFlow/CreateTestCaseFlowCommand.cs - 修改内容:
- 在
EdgeData类中添加了SourceHandle属性,类型为string?,最大长度 50 字符 - 在
EdgeData类中添加了TargetHandle属性,类型为string?,最大长度 50 字符
- 在
3. 更新 CreateTestCaseFlowCommandHandler
- 文件位置:
X1.Application/Features/TestCaseFlow/Commands/CreateTestCaseFlow/CreateTestCaseFlowCommandHandler.cs - 修改内容:
- 在
CreateEdgesAsync方法中,调用TestCaseEdge.Create时传递sourceHandle和targetHandle参数
- 在
4. 创建数据库迁移
- 迁移文件:
20250821155210_AddSourceHandleAndTargetHandleToTestCaseEdge.cs - 修改内容:
- 在
tb_testcaseedge表中添加SourceHandle字段,类型为character varying(50),可为空 - 在
tb_testcaseedge表中添加TargetHandle字段,类型为character varying(50),可为空 - 同时修复了
tb_testcasenode表中stepid字段的外键约束问题
- 在
修改前后对比
修改前
// TestCaseEdge 实体
public class TestCaseEdge : Entity
{
// ... 其他属性
public string TargetNodeId { get; set; } = null!;
public string? EdgeType { get; set; } = "straight";
// ... 其他属性
}
// EdgeData DTO
public class EdgeData
{
public string Source { get; set; } = null!;
public string Target { get; set; } = null!;
public string Type { get; set; } = null!;
// ... 其他属性
}
修改后
// TestCaseEdge 实体
public class TestCaseEdge : Entity
{
// ... 其他属性
public string TargetNodeId { get; set; } = null!;
/// <summary>
/// 源节点连接点
/// </summary>
[MaxLength(50)]
public string? SourceHandle { get; set; }
/// <summary>
/// 目标节点连接点
/// </summary>
[MaxLength(50)]
public string? TargetHandle { get; set; }
public string? EdgeType { get; set; } = "straight";
// ... 其他属性
}
// EdgeData DTO
public class EdgeData
{
public string Source { get; set; } = null!;
public string Target { get; set; } = null!;
/// <summary>
/// 源节点连接点
/// </summary>
[MaxLength(50)]
public string? SourceHandle { get; set; }
/// <summary>
/// 目标节点连接点
/// </summary>
[MaxLength(50)]
public string? TargetHandle { get; set; }
public string Type { get; set; } = null!;
// ... 其他属性
}
数据库变更
- 表名:
tb_testcaseedge - 新增字段:
SourceHandle:character varying(50)- 可为空TargetHandle:character varying(50)- 可为空
技术特性
- 字段类型: 使用可空字符串类型,支持 ReactFlow 的连接点信息
- 长度限制: 最大长度 50 字符,满足连接点标识符需求
- 向后兼容: 新字段为可空,不影响现有数据
- 数据验证: 在 DTO 中使用
MaxLength特性进行验证
影响范围
- 支持 ReactFlow 连线的源节点和目标节点连接点信息
- 保持向后兼容,现有数据不受影响
- 新的测试用例流程创建时可以使用连接点信息
- 数据库结构已更新,支持新字段存储
测试建议
- 测试创建包含连接点信息的测试用例流程
- 验证
sourceHandle和targetHandle字段正确保存 - 确认现有功能不受影响
- 测试边界情况(空值、超长字符串等)
修改时间:
2025-01-21
修改原因:
用户要求在 TestCaseEdge 实体中添加 sourceHandle 和 targetHandle 字段,以支持 ReactFlow 中连线的连接点信息,并在 CreateTestCaseFlowCommand 的 EdgeData 中也添加相应字段。
2025-01-21 - 更新前端服务接口和 ReactFlow 设计器支持 sourceHandle 和 targetHandle
问题描述
需要在前端服务接口和 ReactFlow 设计器中添加对 sourceHandle 和 targetHandle 字段的支持,确保前端能够正确传递和处理连接点信息。
修改内容
1. 更新 testcaseService.ts
- 文件位置:
X1.WebUI/src/services/testcaseService.ts - 修改内容:
- 在
CreateEdgeData接口中添加了sourceHandle?: string字段 - 在
CreateEdgeData接口中添加了targetHandle?: string字段 - 确保前端创建测试用例流程时能够传递连接点信息
- 在
2. 更新 ReactFlowDesigner.tsx
- 文件位置:
X1.WebUI/src/pages/testcases/ReactFlowDesigner.tsx - 修改内容:
- 在保存数据的调试日志中添加了
sourceHandle和targetHandle字段的打印 - 确保连线数据包含完整的连接点信息
- 在保存数据的调试日志中添加了
修改前后对比
修改前
// testcaseService.ts
export interface CreateEdgeData {
id: string;
source: string;
target: string;
type: string;
animated?: boolean;
condition?: string;
style?: string;
}
// ReactFlowDesigner.tsx
edges.forEach((edge, index) => {
console.log(`连线 ${index + 1}:`, {
id: edge.id,
source: edge.source,
target: edge.target,
type: edge.type,
data: edge.data
});
});
修改后
// testcaseService.ts
export interface CreateEdgeData {
id: string;
source: string;
target: string;
sourceHandle?: string;
targetHandle?: string;
type: string;
animated?: boolean;
condition?: string;
style?: string;
}
// ReactFlowDesigner.tsx
edges.forEach((edge, index) => {
console.log(`连线 ${index + 1}:`, {
id: edge.id,
source: edge.source,
target: edge.target,
sourceHandle: edge.sourceHandle,
targetHandle: edge.targetHandle,
type: edge.type,
data: edge.data
});
});
技术特性
- Handle 组件支持: ReactFlow 设计器中的节点已经包含了 Handle 组件,支持连接点
- 连接点 ID: 每个 Handle 都有唯一的 ID(如 "top", "bottom", "left", "right")
- 类型安全: 使用 TypeScript 接口确保类型安全
- 调试支持: 在保存数据时打印完整的连线信息,便于调试
影响范围
- 前端服务接口支持连接点信息传递
- ReactFlow 设计器能够正确处理和保存连接点信息
- 调试日志包含完整的连线数据
- 保持向后兼容,现有功能不受影响
测试建议
- 测试在 ReactFlow 设计器中创建连线
- 验证连接点信息正确保存
- 确认调试日志显示完整的连线数据
- 测试不同类型节点的连接点功能
修改时间:
2025-01-21
修改原因:
用户要求在前端服务接口和 ReactFlow 设计器中添加对 sourceHandle 和 targetHandle 字段的支持,确保前端能够正确传递和处理连接点信息。
2025-01-21 - 修复前端连线数据转换中缺少 sourceHandle 和 targetHandle 字段的问题
问题描述
在 TestCasesView.tsx 文件中,转换连线数据格式时没有包含 sourceHandle 和 targetHandle 字段,导致前端无法正确传递连接点信息到后端。
修改内容
1. 修复 TestCasesView.tsx 中的连线数据转换
- 文件位置:
X1.WebUI/src/pages/testcases/TestCasesView.tsx - 修改内容:
- 在
convertedEdges映射中添加了sourceHandle: edge.sourceHandle字段 - 在
convertedEdges映射中添加了targetHandle: edge.targetHandle字段 - 确保连线数据转换时包含完整的连接点信息
- 在
修改前后对比
修改前
// TestCasesView.tsx
const convertedEdges = edges.map(edge => ({
id: edge.id,
source: edge.source,
target: edge.target,
type: edge.type,
animated: edge.animated,
condition: edge.data?.condition,
style: JSON.stringify(edge.style)
}));
修改后
// TestCasesView.tsx
const convertedEdges = edges.map(edge => ({
id: edge.id,
source: edge.source,
target: edge.target,
sourceHandle: edge.sourceHandle,
targetHandle: edge.targetHandle,
type: edge.type,
animated: edge.animated,
condition: edge.data?.condition,
style: JSON.stringify(edge.style)
}));
技术特性
- 数据完整性: 确保连线数据包含所有必要的连接点信息
- 类型安全: 利用 TypeScript 接口确保字段类型正确
- 向后兼容: 新字段为可空,不影响现有功能
影响范围
- 修复了前端连线数据转换中缺少连接点信息的问题
- 确保 ReactFlow 设计器中的连接点信息能够正确传递到后端
- 保持向后兼容,现有功能不受影响
测试建议
- 测试在 ReactFlow 设计器中创建连线
- 验证连接点信息正确传递到后端
- 确认保存的测试用例流程包含完整的连线数据
- 测试不同类型节点的连接点功能
修改时间:
2025-01-21
修改原因:
用户发现前端连线数据转换中缺少 sourceHandle 和 targetHandle 字段,需要修复以确保连接点信息能够正确传递到后端。
2024-12-19 - 修复 CaptchaService 引用问题
问题描述
CaptchaService 出现引用问题,构建时出现以下错误:
- 未能找到类型或命名空间名"SkiaSharp"
- 未能找到类型或命名空间名"MailKit"
- 未能找到类型或命名空间名"MimeKit"
问题原因
X1.Infrastructure 项目中缺少必要的 NuGet 包引用:
- SkiaSharp (用于生成验证码图片)
- MailKit (用于发送邮件)
- MimeKit (用于构建邮件内容)
解决方案
在 X1.Infrastructure/X1.Infrastructure.csproj 文件中添加了缺失的包引用:
<PackageReference Include="SkiaSharp" Version="2.88.6" />
<PackageReference Include="MailKit" Version="4.3.0" />
<PackageReference Include="MimeKit" Version="4.3.0" />
修改文件
X1.Infrastructure/X1.Infrastructure.csproj- 添加缺失的 NuGet 包引用
验证结果
- 项目构建成功,所有引用错误已解决
- CaptchaService 和 EmailService 功能恢复正常
备注
这个问题可能是由于之前的包更新或项目重构导致的包引用丢失。建议在后续的包更新操作中注意检查所有必要的依赖关系。
修改时间:
2024-12-19
修改原因:
用户反映 CaptchaService 原先没有问题,现在出现引用问题,可能是更新包导致的。经过检查发现缺少必要的 NuGet 包引用。
2024-12-19 - 修复"为了异步而异步"的问题
问题描述
项目构建时出现大量 CS1998 警告,提示异步方法缺少 "await" 运算符。这些警告主要是由于"为了异步而异步"的设计问题导致的。
问题分析
- PermissionRepository 中的
UpdateAsync和DeleteAsync方法被定义为异步,但实际只是调用同步的底层方法 - EmailVerificationService 中的
VerifyCodeAsync方法被定义为异步,但实际只是内存操作 - 这些方法被错误地标记为异步,导致编译器警告
解决方案
1. 修复接口定义
- 文件:
X1.Domain/Repositories/Identity/IPermissionRepository.cs - 修改: 将
UpdateAsync和DeleteAsync方法改为同步方法
// 修改前
Task UpdateAsync(Permission permission, CancellationToken cancellationToken = default);
Task DeleteAsync(Permission permission, CancellationToken cancellationToken = default);
// 修改后
void UpdateAsync(Permission permission, CancellationToken cancellationToken = default);
void DeleteAsync(Permission permission, CancellationToken cancellationToken = default);
2. 修复实现类
- 文件:
X1.Infrastructure/Repositories/Identity/PermissionRepository.cs - 修改: 将方法实现改为同步,移除不必要的
await Task.CompletedTask
3. 修复 EmailVerificationService
- 文件:
X1.Domain/Services/IEmailVerificationService.cs - 修改: 将
VerifyCodeAsync方法改为同步方法
// 修改前
Task<bool> VerifyCodeAsync(string email, string code);
// 修改后
bool VerifyCode(string email, string code);
- 文件:
X1.Infrastructure/Services/UserManagement/EmailVerificationService.cs - 修改: 实现同步的
VerifyCode方法
4. 更新调用方
- 文件:
X1.Application/Features/Auth/Commands/VerifyCode/VerifyCodeCommandHandler.cs - 文件:
X1.Application/Features/Auth/Commands/EmailLogin/EmailLoginCommandHandler.cs - 修改: 更新方法调用以匹配新的接口定义
设计原则
- 真正的异步操作:只有涉及 I/O 操作(数据库、网络、文件)的方法才使用异步
- 内存操作:纯内存操作(如缓存访问、数据验证)使用同步方法
- 避免
await Task.CompletedTask:不使用这种"为了异步而异步"的写法
验证结果
- ✅ 项目构建成功
- ✅ CS1998 警告大幅减少(从多个减少到只有几个)
- ✅ 代码更符合异步编程的最佳实践
- ✅ 性能得到改善(避免了不必要的异步开销)
修改文件
X1.Domain/Repositories/Identity/IPermissionRepository.csX1.Infrastructure/Repositories/Identity/PermissionRepository.csX1.Domain/Services/IEmailVerificationService.csX1.Infrastructure/Services/UserManagement/EmailVerificationService.csX1.Application/Features/Auth/Commands/VerifyCode/VerifyCodeCommandHandler.csX1.Application/Features/Auth/Commands/EmailLogin/EmailLoginCommandHandler.cs
修改时间:
2024-12-19
修改原因:
用户指出项目中有大量警告,怀疑是"为了异步而异步"导致的问题。经过分析发现确实存在接口设计不一致的问题,需要修复以符合异步编程的最佳实践。
2024-12-19 - 修复解引用可能出现空引用的警告
问题描述
项目构建时出现多个 CS8602、CS8604 警告,提示"解引用可能出现空引用"和"可能传入 null 引用实参"。这些警告主要出现在字符串操作和方法调用中。
修复的警告类型
- CS8602: 解引用可能出现空引用
- CS8604: 方法参数可能传入 null 引用实参
解决方案
1. 修复 ProtocolVersionRepository 中的空引用问题
- 文件:
X1.Infrastructure/Repositories/Device/ProtocolVersionRepository.cs - 修改: 在字符串比较前添加空值检查
// 修改前
query = query.Where(pv =>
pv.Name.Contains(keyword) ||
pv.Version.Contains(keyword) ||
pv.Description.Contains(keyword));
// 修改后
query = query.Where(pv =>
(pv.Name != null && pv.Name.Contains(keyword)) ||
(pv.Version != null && pv.Version.Contains(keyword)) ||
(pv.Description != null && pv.Description.Contains(keyword)));
2. 修复 NetworkStackConfigRepository 中的空引用问题
- 文件:
X1.Infrastructure/Repositories/NetworkProfile/NetworkStackConfigRepository.cs - 修改:
- 在字符串比较前添加空值检查
- 在排序时使用空值合并运算符
// 字符串比较修复
query = query.Where(nsc =>
(nsc.NetworkStackName != null && nsc.NetworkStackName.Contains(keyword)) ||
(nsc.Description != null && nsc.Description.Contains(keyword)));
// 排序修复
return (result.TotalCount, result.Items.OrderBy(x => x.NetworkStackName ?? string.Empty).ToList());
3. 修复 UserRegistrationService 中的空引用问题
- 文件:
X1.Infrastructure/Services/UserManagement/UserRegistrationService.cs - 修改: 在传递参数给方法前使用空值合并运算符
// 修改前
var userNameResult = UserName.Create(user.UserName);
var emailResult = Email.Create(user.Email);
var existingUser = await _userManager.FindByNameAsync(user.UserName);
// 修改后
var userNameResult = UserName.Create(user.UserName ?? string.Empty);
var emailResult = Email.Create(user.Email ?? string.Empty);
var existingUser = await _userManager.FindByNameAsync(user.UserName ?? string.Empty);
使用的修复技术
- 空值检查:
property != null && property.Contains(keyword) - 空值合并运算符:
property ?? string.Empty - 安全导航: 确保在调用方法前检查对象是否为 null
验证结果
- ✅ 项目构建成功
- ✅ X1.Infrastructure 项目的空引用警告大幅减少(从多个减少到只有 3 个)
- ✅ 代码更加健壮,减少了运行时空引用异常的可能性
- ✅ 保持了代码的可读性和性能
修改文件
X1.Infrastructure/Repositories/Device/ProtocolVersionRepository.csX1.Infrastructure/Repositories/NetworkProfile/NetworkStackConfigRepository.csX1.Infrastructure/Services/UserManagement/UserRegistrationService.cs
修改时间:
2024-12-19
修改原因:
用户反映项目中有解引用可能出现空引用的警告需要处理。这些警告虽然不影响编译,但可能导致运行时异常,需要修复以提高代码的健壮性。