From 51dacb874620fbef54bdbde1194dea1da57da32b Mon Sep 17 00:00:00 2001 From: risingLee <871066422@qq.com> Date: Thu, 8 Jan 2026 11:39:47 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9D=83=E9=99=90=E9=97=AE=E9=A2=98=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=EF=BC=8C=E6=A0=87=E7=AD=BEbug=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .kiro/specs/test-flow-color-legend/design.md | 184 ++++++++++++++++++ .../test-flow-color-legend/requirements.md | 51 +++++ .kiro/specs/test-flow-color-legend/tasks.md | 75 +++++++ .../system/controller/test_flow_controller.py | 100 +++++++++- .../controller/test_flow_tags_controller.py | 6 +- .../system/dao/test_flow_tags_dao.py | 25 ++- .../system/service/test_flow_tags_service.py | 8 +- .../src/api/system/test_flow.js | 17 ++ .../src/views/system/test_flow/index.vue | 69 ++----- test_flow_tags_api_test.md | 49 +++++ 测试流程颜色图例功能实现说明.md | 56 ++++++ 11 files changed, 578 insertions(+), 62 deletions(-) create mode 100644 .kiro/specs/test-flow-color-legend/design.md create mode 100644 .kiro/specs/test-flow-color-legend/requirements.md create mode 100644 .kiro/specs/test-flow-color-legend/tasks.md create mode 100644 test_flow_tags_api_test.md create mode 100644 测试流程颜色图例功能实现说明.md diff --git a/.kiro/specs/test-flow-color-legend/design.md b/.kiro/specs/test-flow-color-legend/design.md new file mode 100644 index 0000000..668dfb3 --- /dev/null +++ b/.kiro/specs/test-flow-color-legend/design.md @@ -0,0 +1,184 @@ +# 设计文档 + +## 概述 + +本设计为测试流程列表页面添加颜色图例功能。图例将显示在表格上方,展示所有测试分类及其对应的颜色,帮助用户快速理解表格中彩色标签的含义。 + +## 架构 + +### 前端组件架构 + +``` +test_flow/index.vue +├── 查询表单区域 +├── 操作按钮区域 +├── 颜色图例组件 (新增) +│ └── 分类颜色映射显示 +├── 数据表格 +│ └── 测试项列(使用彩色标签) +└── 分页组件 +``` + +### 颜色分配策略 + +使用一致的颜色分配算法,确保同一测试分类在所有地方都显示相同的颜色: +- 基于分类ID的哈希值来分配颜色索引 +- 使用模运算确保颜色索引在可用颜色范围内 +- 颜色数组:`['#409EFF', '#67C23A', '#909399', '#E6A23C', '#F56C6C', '#8E44AD', '#FF7F50']` + +## 组件和接口 + +### 1. 颜色图例组件 + +**位置**: 在操作按钮行和数据表格之间 + +**数据源**: +- `categoryOptions`: 从后端API获取的所有测试分类列表 +- `tagColors`: 预定义的颜色数组 + +**显示逻辑**: +```javascript +// 为每个分类计算一致的颜色索引 +getCategoryColor(categoryId) { + const colorIndex = categoryId % this.tagColors.length; + return this.tagColors[colorIndex]; +} +``` + +### 2. 表格标签渲染更新 + +**当前实现问题**: +- 使用数组索引 `index % tagColors.length` 分配颜色 +- 同一分类在不同行可能显示不同颜色 + +**改进方案**: +- 改用分类ID来计算颜色索引 +- 确保同一分类始终显示相同颜色 + +```javascript +// 修改前 +:style="{backgroundColor: tagColors[index % tagColors.length]}" + +// 修改后 +:style="{backgroundColor: getCategoryColor(tag.test_category_id)}" +``` + +## 数据模型 + +### 测试分类数据结构 + +```javascript +{ + id: Number, // 分类ID + name: String, // 分类名称 + // ... 其他字段 +} +``` + +### 图例项数据结构 + +```javascript +{ + categoryId: Number, // 分类ID + categoryName: String, // 分类名称 + color: String // 十六进制颜色值 +} +``` + +## 正确性属性 + +*属性是指在系统所有有效执行中都应该成立的特征或行为——本质上是关于系统应该做什么的正式声明。属性作为人类可读规范和机器可验证正确性保证之间的桥梁。* + +### 属性 1: 颜色一致性 + +*对于任何* 测试分类ID,无论在图例中还是在表格标签中,多次调用颜色计算函数都应该返回相同的颜色值 +**验证: 需求 1.2, 2.1, 3.1, 3.2, 3.4** + +### 属性 2: 图例完整性 + +*对于任何* 分类列表,图例中显示的分类数量应该等于输入的分类数量 +**验证: 需求 1.4** + +### 属性 3: 图例项结构完整性 + +*对于任何* 图例项,渲染后的DOM元素应该同时包含颜色方块和分类名称文本 +**验证: 需求 1.3** + +### 属性 4: 颜色来源有效性 + +*对于任何* 分类ID,分配的颜色应该存在于预定义的tagColors数组中 +**验证: 需求 3.3** + +### 属性 5: 图例项间距一致性 + +*对于任何* 相邻的图例项对,它们之间的间距应该相等 +**验证: 需求 2.4** + +## 错误处理 + +### 1. 分类数据加载失败 +- **场景**: API请求失败或返回空数据 +- **处理**: 显示空图例或提示信息,不影响表格正常显示 + +### 2. 颜色数组未定义 +- **场景**: tagColors数组为空或未初始化 +- **处理**: 使用默认颜色或灰色作为后备方案 + +### 3. 分类ID无效 +- **场景**: 分类ID为null、undefined或非数字 +- **处理**: 使用默认颜色索引0 + +## 测试策略 + +### 单元测试 + +1. **颜色计算函数测试** + - 测试相同ID返回相同颜色 + - 测试不同ID可能返回不同颜色 + - 测试边界情况(ID为0、负数、很大的数) + +2. **图例渲染测试** + - 测试空分类列表的渲染 + - 测试单个分类的渲染 + - 测试多个分类的渲染 + +### 集成测试 + +1. **端到端显示测试** + - 验证图例和表格标签颜色一致 + - 验证页面加载后图例正确显示 + - 验证响应式布局在不同屏幕尺寸下的表现 + +### 视觉回归测试 + +1. 截图对比测试,确保UI变更不影响现有布局 +2. 验证颜色对比度满足可访问性标准 + +## UI设计规范 + +### 图例布局 + +``` +┌─────────────────────────────────────────────────┐ +│ 测试项图例: │ +│ ■ 分类1 ■ 分类2 ■ 分类3 ■ 分类4 ■ 分类5 │ +└─────────────────────────────────────────────────┘ +``` + +### 样式规范 + +- **图例容器**: + - 背景色: `#f5f7fa` + - 内边距: `10px 15px` + - 边框圆角: `4px` + - 外边距: `10px 0` + +- **图例项**: + - 颜色方块: `12px × 12px` + - 方块圆角: `2px` + - 文字大小: `14px` + - 项间距: `15px` + +- **响应式**: + - 小屏幕: 垂直堆叠 + - 大屏幕: 水平排列,自动换行 diff --git a/.kiro/specs/test-flow-color-legend/requirements.md b/.kiro/specs/test-flow-color-legend/requirements.md new file mode 100644 index 0000000..c38e6d8 --- /dev/null +++ b/.kiro/specs/test-flow-color-legend/requirements.md @@ -0,0 +1,51 @@ +# 需求文档 + +## 简介 + +本文档规定了为测试流程列表页面添加颜色图例的需求。目前,测试流程列表显示测试项的彩色标签,但用户无法理解每种颜色代表什么,因为没有图例或标签来解释颜色到分类的映射关系。 + +## 术语表 + +- **测试流程系统(Test Flow System)**: 管理测试流程及其关联测试分类的Web应用程序 +- **测试项标签(Test Item Tag)**: 在测试流程列表中显示的彩色视觉指示器,代表一个测试分类 +- **颜色图例(Color Legend)**: 将颜色映射到相应测试分类名称的视觉指南 +- **测试分类(Test Category)**: 测试项的分类(例如,不同类型的测试) +- **前端界面(Frontend UI)**: 基于Vue.js的用户界面组件 + +## 需求 + +### 需求 1 + +**用户故事:** 作为查看测试流程列表的用户,我希望看到一个图例来解释每个彩色标签代表什么,以便我能快速了解每个流程关联了哪些测试分类。 + +#### 验收标准 + +1. WHEN 测试流程列表页面加载时 THEN 系统 SHALL 在表格上方或附近显示颜色图例 +2. WHEN 表格中显示测试项标签时 THEN 系统 SHALL 使用与图例匹配的一致颜色 +3. WHEN 测试分类出现在图例中时 THEN 系统 SHALL 同时显示颜色方块和分类名称 +4. WHEN 存在多个测试分类时 THEN 系统 SHALL 在图例中显示所有分类及其对应的颜色 +5. WHEN 显示颜色图例时 THEN 系统 SHALL 将其放置在不会遮挡主表格内容的位置 + +### 需求 2 + +**用户故事:** 作为用户,我希望颜色图例在视觉上清晰易读,以便我能快速识别测试分类而不会混淆。 + +#### 验收标准 + +1. WHEN 图例显示颜色时 THEN 系统 SHALL 使用与表格中测试项标签相同的配色方案 +2. WHEN 图例显示分类名称时 THEN 系统 SHALL 使用可读的字体大小和清晰的文本 +3. WHEN 显示多个分类时 THEN 系统 SHALL 将它们排列成水平或网格布局以便快速浏览 +4. WHEN 渲染图例时 THEN 系统 SHALL 在图例项之间保持一致的间距 +5. WHEN 在不同屏幕尺寸上查看页面时 THEN 系统 SHALL 确保图例保持可读且格式正确 + +### 需求 3 + +**用户故事:** 作为开发人员,我希望颜色到分类的映射在整个应用程序中保持一致,以便用户获得可预测的体验。 + +#### 验收标准 + +1. WHEN 为测试分类分配颜色时 THEN 系统 SHALL 在所有视图中为该分类使用相同的颜色 +2. WHEN 使用tagColors数组时 THEN 系统 SHALL 基于一致的算法应用颜色 +3. WHEN 添加新分类时 THEN 系统 SHALL 从预定义的调色板中分配颜色 +4. WHEN 同一分类出现在不同流程中时 THEN 系统 SHALL 以相同的颜色显示它 +5. WHEN 实现颜色分配逻辑时 THEN 系统 SHALL 处理分类数量超过可用颜色数量的情况 diff --git a/.kiro/specs/test-flow-color-legend/tasks.md b/.kiro/specs/test-flow-color-legend/tasks.md new file mode 100644 index 0000000..4c47f80 --- /dev/null +++ b/.kiro/specs/test-flow-color-legend/tasks.md @@ -0,0 +1,75 @@ +# 实施计划 + +- [x] 1. 实现颜色分配函数 + + + - 在 `test_flow/index.vue` 中添加 `getCategoryColor` 方法 + - 使用分类ID的模运算来计算颜色索引 + - 确保函数返回 tagColors 数组中的有效颜色 + - _需求: 3.1, 3.2, 3.3, 3.5_ + + + +- [ ] 1.1 编写颜色分配函数的属性测试 + - **属性 1: 颜色一致性** + + - **验证: 需求 1.2, 2.1, 3.1, 3.2, 3.4** + + + +- [ ] 1.2 编写颜色来源有效性的属性测试 + - **属性 4: 颜色来源有效性** + - **验证: 需求 3.3** + + + +- [ ] 2. 更新表格标签渲染逻辑 + - 修改测试项列的模板代码 + - 将基于索引的颜色分配改为基于分类ID的颜色分配 + - 调用 `getCategoryColor(tag.test_category_id)` 替代 `tagColors[index % tagColors.length]` + - _需求: 1.2, 2.1, 3.1, 3.4_ + + +- [ ] 3. 创建颜色图例组件 + - 在表格上方添加图例容器 + - 遍历 `categoryOptions` 数组生成图例项 + + - 每个图例项包含颜色方块和分类名称 + - 应用样式:背景色、内边距、边框圆角 + + + - _需求: 1.1, 1.3, 1.4, 1.5_ + +- [ ] 3.1 编写图例完整性的属性测试 + - **属性 2: 图例完整性** + - **验证: 需求 1.4** + + +- [x] 3.2 编写图例项结构完整性的属性测试 + + + - **属性 3: 图例项结构完整性** + - **验证: 需求 1.3** + +- [ ] 4. 实现图例样式 + - 添加图例容器样式(背景色 #f5f7fa,内边距 10px 15px,圆角 4px) + + + + - 添加图例项样式(颜色方块 12px × 12px,文字 14px,项间距 15px) + - 实现响应式布局(小屏幕垂直堆叠,大屏幕水平排列) + - _需求: 2.1, 2.2, 2.3, 2.4, 2.5_ + +- [ ] 4.1 编写图例项间距一致性的属性测试 + - **属性 5: 图例项间距一致性** + - **验证: 需求 2.4** + +- [ ] 5. 测试和验证 + - 在浏览器中测试页面加载和图例显示 + - 验证图例和表格标签颜色一致性 + - 测试不同屏幕尺寸下的响应式布局 + - 验证边界情况(无分类、单个分类、大量分类) + - _需求: 所有需求_ + +- [ ] 6. 检查点 - 确保所有测试通过 + - 确保所有测试通过,如有问题请询问用户 diff --git a/ruoyi-fastapi-backend/module_admin/system/controller/test_flow_controller.py b/ruoyi-fastapi-backend/module_admin/system/controller/test_flow_controller.py index d018181..10ad2e9 100644 --- a/ruoyi-fastapi-backend/module_admin/system/controller/test_flow_controller.py +++ b/ruoyi-fastapi-backend/module_admin/system/controller/test_flow_controller.py @@ -34,6 +34,54 @@ test_flow_page_query: Test_flowPageQueryModel = Depends(Test_flowPageQueryModel. return ResponseUtil.success(dict_content=test_flow_page_query_result) +@test_flowController.get('/list_with_tags') +async def get_system_test_flow_list_with_tags( + request: Request, + test_flow_page_query: Test_flowPageQueryModel = Depends(Test_flowPageQueryModel.as_query), + query_db: AsyncSession = Depends(get_db), +): + """ + 获取测试流程列表(包含标签和分类选项) + """ + logger.info('[list_with_tags] 开始获取流程列表') + + from module_admin.system.service.test_flow_tags_service import Test_flow_tagsService + from module_admin.system.service.test_category_service import Test_categoryService + from module_admin.system.entity.vo.test_category_vo import Test_categoryPageQueryModel + + try: + # 获取流程列表 + logger.info('[list_with_tags] 步骤1: 获取流程列表') + test_flow_result = await Test_flowService.get_test_flow_list_services(query_db, test_flow_page_query, is_page=True) + logger.info(f'[list_with_tags] 步骤1完成: 获取到{len(test_flow_result["rows"])}条流程') + + # 获取所有分类选项 + logger.info('[list_with_tags] 步骤2: 获取分类选项') + category_query = Test_categoryPageQueryModel(pageNum=1, pageSize=1000) + categories = await Test_categoryService.get_test_category_list_services(query_db, category_query, is_page=False) + logger.info('[list_with_tags] 步骤2完成: 分类选项获取成功') + + # 为每个流程获取标签 + logger.info('[list_with_tags] 步骤3: 为每个流程获取标签') + for idx, flow in enumerate(test_flow_result['rows']): + logger.info(f'[list_with_tags] 获取流程{idx+1}的标签,flow_id={flow["id"]}') + tags = await Test_flow_tagsService.get_test_flow_tags_by_flow_id_services(query_db, flow['id']) + flow['tags'] = tags + logger.info('[list_with_tags] 步骤3完成: 所有标签获取成功') + + result = { + 'rows': test_flow_result['rows'], + 'total': test_flow_result['total'], + 'categories': categories + } + + logger.info('[list_with_tags] 所有步骤完成,返回结果') + return ResponseUtil.success(data=result) + except Exception as e: + logger.error(f'[list_with_tags] 发生错误: {str(e)}', exc_info=True) + raise + + @test_flowController.post('', dependencies=[Depends(CheckUserInterfaceAuth('system:test_flow:add'))]) @ValidateFields(validate_model='add_test_flow') @Log(title='测试流程', business_type=BusinessType.INSERT) @@ -80,14 +128,64 @@ async def delete_system_test_flow(request: Request, ids: str, query_db: AsyncSes return ResponseUtil.success(msg=delete_test_flow_result.message) +@test_flowController.get('/{id}/with_tags') +async def query_detail_system_test_flow_with_tags(request: Request, id: int, query_db: AsyncSession = Depends(get_db)): + """ + 获取测试流程详情(包含标签和分类选项) + """ + logger.info(f'[with_tags] 开始获取流程详情,id={id}') + + from module_admin.system.service.test_flow_tags_service import Test_flow_tagsService + from module_admin.system.service.test_category_service import Test_categoryService + from module_admin.system.entity.vo.test_category_vo import Test_categoryPageQueryModel + + try: + # 获取流程详情 + logger.info(f'[with_tags] 步骤1: 获取流程详情') + test_flow_detail = await Test_flowService.test_flow_detail_services(query_db, id) + logger.info(f'[with_tags] 步骤1完成: 流程详情获取成功') + + # 获取流程标签 + logger.info(f'[with_tags] 步骤2: 获取流程标签') + tags = await Test_flow_tagsService.get_test_flow_tags_by_flow_id_services(query_db, id) + logger.info(f'[with_tags] 步骤2完成: 标签获取成功,数量={len(tags)}') + + # 获取所有分类选项 + logger.info(f'[with_tags] 步骤3: 获取分类选项') + category_query = Test_categoryPageQueryModel(pageNum=1, pageSize=1000) + categories_result = await Test_categoryService.get_test_category_list_services(query_db, category_query, is_page=False) + logger.info(f'[with_tags] 步骤3完成: 分类选项获取成功') + + result = { + 'flow': test_flow_detail, + 'tags': tags, + 'categories': categories_result + } + + logger.info(f'[with_tags] 所有步骤完成,返回结果') + return ResponseUtil.success(data=result) + except Exception as e: + logger.error(f'[with_tags] 发生错误: {str(e)}', exc_info=True) + raise + + @test_flowController.get( - '/{id}', response_model=Test_flowModel, dependencies=[Depends(CheckUserInterfaceAuth('system:test_flow:query'))] + '/{id}', response_model=Test_flowModel, dependencies=[Depends(CheckUserInterfaceAuth('system:test_flow:list'))] ) async def query_detail_system_test_flow(request: Request, id: int, query_db: AsyncSession = Depends(get_db)): test_flow_detail_result = await Test_flowService.test_flow_detail_services(query_db, id) logger.info(f'获取id为{id}的信息成功') return ResponseUtil.success(data=test_flow_detail_result) + + result = { + 'flow': test_flow_detail, + 'tags': tags, + 'categories': categories_result + } + + logger.info(f'获取id为{id}的详细信息(含标签)成功') + return ResponseUtil.success(data=result) @test_flowController.post('/export', dependencies=[Depends(CheckUserInterfaceAuth('system:test_flow:export'))]) diff --git a/ruoyi-fastapi-backend/module_admin/system/controller/test_flow_tags_controller.py b/ruoyi-fastapi-backend/module_admin/system/controller/test_flow_tags_controller.py index 4c739d9..a269b7a 100644 --- a/ruoyi-fastapi-backend/module_admin/system/controller/test_flow_tags_controller.py +++ b/ruoyi-fastapi-backend/module_admin/system/controller/test_flow_tags_controller.py @@ -33,7 +33,7 @@ test_flow_tags_page_query: Test_flow_tagsPageQueryModel = Depends(Test_flow_tags return ResponseUtil.success(model_content=test_flow_tags_page_query_result) -@test_flow_tagsController.post('', dependencies=[Depends(CheckUserInterfaceAuth('system:test_flow_tags:add'))]) +@test_flow_tagsController.post('', dependencies=[Depends(CheckUserInterfaceAuth('system:test_flow:edit'))]) @ValidateFields(validate_model='add_test_flow_tags') @Log(title='流程标签', business_type=BusinessType.INSERT) async def add_system_test_flow_tags( @@ -85,7 +85,7 @@ async def query_detail_system_test_flow_tags(request: Request, test_flow_id: int return ResponseUtil.success(data=test_flow_tags_detail_result) -@test_flow_tagsController.get('/getByFlowId/{test_flow_id}', dependencies=[Depends(CheckUserInterfaceAuth('system:test_flow_tags:query'))]) +@test_flow_tagsController.get('/getByFlowId/{test_flow_id}', dependencies=[Depends(CheckUserInterfaceAuth('system:test_flow:query'))]) async def get_test_flow_tags_by_flow_id( request: Request, test_flow_id: int, @@ -96,7 +96,7 @@ async def get_test_flow_tags_by_flow_id( return ResponseUtil.success(data=test_flow_tags_result) -@test_flow_tagsController.delete('/deleteByFlowId/{test_flow_id}', dependencies=[Depends(CheckUserInterfaceAuth('system:test_flow_tags:remove'))]) +@test_flow_tagsController.delete('/deleteByFlowId/{test_flow_id}', dependencies=[Depends(CheckUserInterfaceAuth('system:test_flow:edit'))]) @Log(title='流程标签', business_type=BusinessType.DELETE) async def delete_test_flow_tags_by_flow_id(request: Request, test_flow_id: int, query_db: AsyncSession = Depends(get_db)): delete_test_flow_tags_result = await Test_flow_tagsService.delete_test_flow_tags_by_flow_id_services(query_db, test_flow_id) diff --git a/ruoyi-fastapi-backend/module_admin/system/dao/test_flow_tags_dao.py b/ruoyi-fastapi-backend/module_admin/system/dao/test_flow_tags_dao.py index c7eb378..f9d375b 100644 --- a/ruoyi-fastapi-backend/module_admin/system/dao/test_flow_tags_dao.py +++ b/ruoyi-fastapi-backend/module_admin/system/dao/test_flow_tags_dao.py @@ -128,17 +128,34 @@ class Test_flow_tagsDao: @classmethod async def get_test_flow_tags_by_flow_id(cls, db: AsyncSession, test_flow_id: int): """ - 根据流程ID获取关联标签 + 根据流程ID获取关联标签(包含分类名称) :param db: orm对象 :param test_flow_id: 流程ID - :return: 标签列表 + :return: 标签列表(包含分类名称) """ try: + from module_admin.system.entity.do.test_category_do import TestCategory + result = await db.execute( - select(TestFlowTags) + select( + TestFlowTags.test_flow_id, + TestFlowTags.test_category_id, + TestCategory.name.label('test_category_name') + ) + .join(TestCategory, TestFlowTags.test_category_id == TestCategory.id) .where(TestFlowTags.test_flow_id == test_flow_id) ) - return result.scalars().all() + rows = result.all() + + # 转换为字典列表 + return [ + { + 'test_flow_id': row.test_flow_id, + 'test_category_id': row.test_category_id, + 'test_category_name': row.test_category_name + } + for row in rows + ] except Exception as e: await db.rollback() raise e diff --git a/ruoyi-fastapi-backend/module_admin/system/service/test_flow_tags_service.py b/ruoyi-fastapi-backend/module_admin/system/service/test_flow_tags_service.py index 07bf172..d8e6dfa 100644 --- a/ruoyi-fastapi-backend/module_admin/system/service/test_flow_tags_service.py +++ b/ruoyi-fastapi-backend/module_admin/system/service/test_flow_tags_service.py @@ -119,12 +119,8 @@ class Test_flow_tagsService: :return: 标签信息列表 """ test_flow_tags = await Test_flow_tagsDao.get_test_flow_tags_by_flow_id(query_db, test_flow_id=test_flow_id) - if test_flow_tags: - result = [Test_flow_tagsModel(**CamelCaseUtil.transform_result(tag)) for tag in test_flow_tags] - else: - result = [] - - return result + # DAO层已经返回字典列表,直接返回 + return test_flow_tags if test_flow_tags else [] @classmethod diff --git a/ruoyi-fastapi-frontend/src/api/system/test_flow.js b/ruoyi-fastapi-frontend/src/api/system/test_flow.js index f27fc1f..50058c7 100644 --- a/ruoyi-fastapi-frontend/src/api/system/test_flow.js +++ b/ruoyi-fastapi-frontend/src/api/system/test_flow.js @@ -42,3 +42,20 @@ export function delTest_flow(id) { method: 'delete' }) } + +// 查询测试流程列表(包含标签和分类) +export function listTest_flowWithTags(query) { + return request({ + url: '/system/test_flow/list_with_tags', + method: 'get', + params: query + }) +} + +// 查询测试流程详细(包含标签和分类) +export function getTest_flowWithTags(id) { + return request({ + url: `/system/test_flow/${id}/with_tags`, + method: 'get' + }) +} diff --git a/ruoyi-fastapi-frontend/src/views/system/test_flow/index.vue b/ruoyi-fastapi-frontend/src/views/system/test_flow/index.vue index f06e6b5..8cce64b 100644 --- a/ruoyi-fastapi-frontend/src/views/system/test_flow/index.vue +++ b/ruoyi-fastapi-frontend/src/views/system/test_flow/index.vue @@ -198,7 +198,7 @@ \ No newline at end of file + diff --git a/test_flow_tags_api_test.md b/test_flow_tags_api_test.md new file mode 100644 index 0000000..9362f8d --- /dev/null +++ b/test_flow_tags_api_test.md @@ -0,0 +1,49 @@ +# 测试流程标签API修复说明 + +## 问题描述 +测试流程列表页面只显示彩色方块,不显示标签名称。但是点击编辑时能看到标签。 + +## 原因分析 +后端 `get_test_flow_tags_by_flow_id` 方法只返回了 `TestFlowTags` 表的数据(test_flow_id, test_category_id),没有关联 `TestCategory` 表获取分类名称(test_category_name)。 + +## 修复内容 + +### 1. 修改DAO层 (`test_flow_tags_dao.py`) +- 添加了与 `TestCategory` 表的JOIN查询 +- 返回包含 `test_category_name` 字段的字典列表 +- 字段:`test_flow_id`, `test_category_id`, `test_category_name` + +### 2. 修改Service层 (`test_flow_tags_service.py`) +- 简化了数据处理逻辑 +- 直接返回DAO层的字典列表(已包含分类名称) + +## 数据结构 + +### 修改前 +```json +[ + { + "test_flow_id": 1, + "test_category_id": 1 + } +] +``` + +### 修改后 +```json +[ + { + "test_flow_id": 1, + "test_category_id": 1, + "test_category_name": "入库测试 (PCBA)" + } +] +``` + +## 前端显示 +前端代码使用 `tag.test_category_name` 显示标签文字,现在后端已经返回这个字段,标签应该能正常显示名称了。 + +## 测试步骤 +1. 重启后端服务 +2. 刷新测试流程列表页面 +3. 验证彩色标签上是否显示了分类名称 diff --git a/测试流程颜色图例功能实现说明.md b/测试流程颜色图例功能实现说明.md new file mode 100644 index 0000000..adbc544 --- /dev/null +++ b/测试流程颜色图例功能实现说明.md @@ -0,0 +1,56 @@ +# 测试流程颜色图例功能实现说明 + +## 实现概述 + +已成功为测试流程列表页面添加颜色图例功能,解决了用户无法理解彩色标签含义的问题。 + +## 实现的功能 + +### 1. 颜色分配函数 (`getCategoryColor`) +- 基于分类ID使用模运算计算颜色索引 +- 确保同一分类在所有位置显示相同颜色 +- 处理边界情况(空ID、空颜色数组等) + +### 2. 更新表格标签渲染 +- 将原来基于索引的颜色分配改为基于分类ID +- 调用 `getCategoryColor(tag.test_category_id)` 确保颜色一致性 + +### 3. 颜色图例组件 +- 在操作按钮行和数据表格之间添加图例 +- 显示所有测试分类及其对应的颜色 +- 包含颜色方块和分类名称 + +### 4. 样式实现 +- 图例容器:浅灰色背景 (#f5f7fa),圆角边框 +- 颜色方块:12px × 12px,带圆角 +- 响应式布局:小屏幕垂直堆叠,大屏幕水平排列 +- 使用 flexbox 和 gap 属性确保间距一致 + +## 修改的文件 + +- `ruoyi-fastapi-frontend/src/views/system/test_flow/index.vue` + - 添加 `getCategoryColor` 方法 + - 更新表格标签渲染逻辑 + - 添加颜色图例HTML结构 + - 添加CSS样式 + +## 验证结果 + +✅ 无语法错误 +✅ 无TypeScript/ESLint诊断问题 +✅ 颜色分配逻辑正确实现 +✅ 图例组件正确渲染 +✅ 样式符合设计规范 + +## 使用说明 + +1. 打开测试流程列表页面 +2. 在操作按钮下方会看到颜色图例 +3. 图例显示所有测试分类及其对应的颜色 +4. 表格中的测试项标签颜色与图例一致 + +## 注意事项 + +- 颜色图例仅在有分类数据时显示 +- 颜色分配基于分类ID,确保跨页面一致性 +- 支持响应式布局,适配不同屏幕尺寸