Files
supervision-test-frontend-repo/qa-report/inspectTask/QA_REPORT.md
T
wsm 237a5810cf !145 docs(xispeak): 归档前端页面 QA 审查报告(用户视角)
* docs(xispeak): 归档前端页面 QA 审查报告(用户视角)
* docs(fixcontact): 归档前端页面 QA 审查报告(用户视角)
* docs(inspectTask): 归档前端页面 QA 审查报告(工程师+用户视角)
* docs(bqtakepulse): 归档前端页面 QA 审查报告(工程师+用户视角)
* docs(bgpartymatter): 归档前端页面 QA 审查报告(工程师+用户视角)
2026-08-11 07:27:58 +00:00

108 lines
18 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 前端页面审查报告 — 巡视整改提升工作台账(DqInspectTaskList
## 审查信息
- 页面/路由:`/dq/inspectTask/DqInspectTaskList`(巡视整改提升工作台账)
- 审查日期:2026-08-11
- 审查视角:**资深前端工程师**(浏览器实测 + 代码审查结合)
- 审查账号:admin(mock 登录,其余接口打真实后端 8080)
- 相关文件:
- `src/views/dq/inspectTask/DqInspectTaskList.vue`
- `src/views/dq/inspectTask/components/DqInspectTaskForm.vue``DqInspectTaskModal.vue``DqInspectTaskFlowScheduleStartModal.vue`
- `src/views/dq/inspectTask/DqInspectTask.data.ts``DqInspectTask.api.ts`
- `src/components/semri/userComponent/DeptRoleUserSelectDropDown.vue`
- `src/components/Modal/src/BasicModal.vue``src/components/Modal/src/components/ModalClose.vue`
- 后端契约:`jeecg-module-supervision/.../DqInspectTaskController.java``DqInspectTaskMapper.xml``jeecg-module-system/.../tasktask/TaskTaskController.java``TaskTaskServiceImpl.java`
- 证据目录:`qa-tmp/inspectTask/`(截图 `screenshots/`、脚本/记录 `scripts/``artifacts/`
- 关联报告:`qa-report/inspectTask/QA_REPORT_UX.md`(用户视角,可并列对比)
## 总体结论
- **P0 × 1 P1 × 4 P2 × 7**
- 一句话总结:核心增删改查/详情/流程查看可走通,但**整改措施搜索框完全失效(P0)**——后端 ledger 自定义 SQL 对前端 `*like*` 通配符二次包裹导致永远查不到、清空也不恢复;另有责任领导列误绑/详情占位符(共享组件 watch 清值竞态)、流程操作不随状态且后端无守卫、分管所领导筛选被列表忽略等 4 个 P1,不建议按当前状态交付,需先修复 P0。
---
## P0 - 必须修复
| # | 维度 | 问题描述 | 证据 | 位置 |
|---|------|---------|------|------|
| 1 | 后端调用/功能错误 | **「整改措施」搜索框完全失效**。列表页 JInput `type="like"` 把输入值包装成 `*wqdwqd*` 发到后端,但后端台账自定义 SQL 又做了一次 `concat('%', value, '%')`,实际生成 `improve_measure like '%*wqdwqd*%'`——带字面量星号,任何真实值都匹配不到,搜索永远返回 0 行;**清空输入框时发送 `improveMeasure=**`(空值仍被包一层星号)→ 列表继续保持空**,直到点「重置」。期间顶部统计标签仍显示「督办中 1」,列表(0) 与统计(1) 自相矛盾,用户误以为数据丢了。 | 实测 `artifacts/eng_02_api_bodies.json`ledgerList?improveMeasure=*wqdwqd* → records:[] total:0,同参数 statusStats → inProgress:1);实测 `artifacts/eng_10_search_bug.json`(输入 wqdwqd → row_count:0;清空 → 请求 improveMeasure=** 仍 0 行);截图 `screenshots/eng_15_final_list.png` | 前端 `DqInspectTaskList.vue:9``JInput type="like" @change="reload"`);后端 `DqInspectTaskMapper.xml:50-52``t.improve_measure like concat('%', #{task.improveMeasure}, '%')` |
**技术根因**`DqInspectTaskMapper.xml``queryLedgerPage` 是手写 SQL,它的 like 分支假定前端传**普通值**;而 JInput `type="like"` 走 Jeecg QueryGenerator 的 `*...*` 约定传通配符。两者叠加 = 二次包裹。`statusStats` 接口用 QueryGenerator 直查实体(`*``%` 正确转换)所以能匹配,于是列表与统计对同一筛选结果不一致。
**修复建议**:二者取其一——(a) 前端 `DqInspectTaskList.vue:9` 去掉 `type="like"`(改普通输入,由 XML `concat('%',…,'%')` 负责模糊);或 (b) 后端 XML 把值里的 `*` 转成 `%` 再包裹,并兜底空值时不发该条件(避免 `**`)。建议同时做 (b) 的空值判断,彻底解决"清空后列表空"。
---
## P1 - 强烈建议修复
| # | 维度 | 问题描述 | 证据 | 位置 |
|---|------|---------|------|------|
| 1 | 逻辑/数据显示 | **列表「措施责任领导」列误绑 `measureResDept_dictText`**:该列与「措施责任部门」列显示完全相同的部门名「DD」,真实责任领导 `dd_ld_02` 看不到。后端已正确返回 `measureResLeader_dictText=dd_ld_02`。 | 实测 `artifacts/eng_01_rows.json`(第 7、8 列均为 "DD");`artifacts/eng_02_api_bodies.json`ledgerList 响应含 measureResLeader_dictText=dd_ld_02);截图 `04_list.png` | `DqInspectTask.data.ts:255-258`(措施责任领导列 `dataIndex: 'measureResDept_dictText'`,应为 `'measureResLeader_dictText'` |
| 2 | 状态一致性/竞态 | **详情/编辑弹窗「措施责任领导」显示占位符「请选择措施责任领导」**:后端已赋值 `measureResLeader=dd_ld_02` 且该下拉能查到 `dd_ld_02`,但 select 值为空。根因是 `DeptRoleUserSelectDropDown` 的 watch 在 deptId/roleId 变化时**无条件 `modelValue.value = ''`**:详情加载先赋 `measureResDept``measureResDeptId` computed 变化 → watch 触发 → 把刚加载的 `measureResLeader` 清掉(数据加载与 watch 的竞态)。因 `measureResLeader` 是动态 deptId,全表单只有它中招;`chargeLeaderId` 的 deptId 是静态常量不触发 watch,故正常。**编辑模式同路径也会被清空**(必填校验会拦下提交,不致静默丢数据,但每次编辑都要重选)。 | 实测 `artifacts/eng_09_leader_rootcause.json`queryUserRoleComponentData 对 measureResLeader 下拉返回 records 含 dd_ld_02 `has_dd_ld_02:true`,但 select `value_input:""``selection_items:[]`、placeholder_shown:true;对照 `chargeLeader_selection:["所领导01"]` 正常);`artifacts/probe_querybyid.json`queryById.result.measureResLeader=`dd_ld_02`);截图 `eng_09_detail_modal.png``60_detail_values.png` | `src/components/semri/userComponent/DeptRoleUserSelectDropDown.vue:63-69``watch(() => [props.deptId, props.roleId], () => { modelValue.value = ''; fetchUserList(); })`);使用处 `DqInspectTaskForm.vue:86-92``:deptId="measureResDeptId"` 动态) |
| 3 | 状态流转/后端调用 | **流程操作菜单不随任务状态变化,督办中任务也能「发起巡视整改流程/发起销号流程」→ 有创建重复/错误流程实例风险**。前端 `getFlowMenuList` 按状态显隐的 `if` 全被注释掉(388-421 行),所有记录都展示两个发起项;实测督办中(bpmStatus=2, completedStage=1)记录两项均可见、弹窗可打开。**后端 `singleFlowStart` 无任何业务状态守卫**`validateBusinessParams` 只校验 flowCode/businessId/formUrl 非空,提交会无条件新建 TaskTask 并 `startMutilProcess` 启动新 Flowable 流程实例。**为保护真实流程数据未点「提交」,创建重复实例为代码确认+实测入口,未实测触发**。 | 实测 `artifacts/eng_06_flow.json`(督办中记录 flow_menu_items=[发起巡视整改流程,发起销号流程,查询督办流程];弹窗可打开);后端代码 `TaskTaskServiceImpl.java:55-75,133-152`singleFlowStart 无守卫、validateBusinessParams 仅非空校验);`TaskTaskController.java:127-140`flow-schedules 无业务状态校验) | 前端 `DqInspectTaskList.vue:388-421``getFlowMenuList`,条件判断被注释);发起 `handleFlowScheduleConfirm` 491-524 行;后端 `TaskTaskServiceImpl.singleFlowStart` |
| 4 | 后端调用/状态一致性 | **查询筛选对台账列表部分失效:分管所领导筛选被列表忽略,且统计与列表不一致**。自定义 SQL `queryLedgerPage` 只实现了 improveMeasure/measureResLeader/measureResDept/problemId/completedStage/bpmStatus 6 个字段的子句,**没有 `charge_leader_id` 子句**;实测筛选「分管所领导=所党委01(无该领导记录)」列表仍显示全部 2 行(筛选被吞),而 `statusStats` 用 QueryGenerator 会应用该条件 → 统计归零、列表全量,自相矛盾。同机制下,高级查询暴露的 19 个字段里 13 个(targetNode/deadline/secretLevel 等)在列表侧同样无效(代码推断,与 chargeLeader 同路径)。 | 实测 `artifacts/eng_11_cleanup_filters.json`filter_chargeLeader_sdw01 → row_count:2,筛选被忽略);后端 `DqInspectTaskMapper.xml:49-68``<if test>` 仅 6 个字段);`DqInspectTaskController.java:98-107`ledgerList 透传 QueryGenerator 生成的实体条件) | 后端 `DqInspectTaskMapper.xml:49-68``DqInspectTask.data.ts:174-208`superQuerySchema 19 字段) |
---
## P2 - 建议
| # | 维度 | 问题描述 | 证据 | 位置 |
|---|------|---------|------|------|
| 1 | 用户体验/共享组件 | **弹窗关闭 X 与全屏图标紧邻易误触**:关闭按钮容器 86×34px 内先渲染 36×36 的全屏图标、再渲染约 26×36 的关闭 glyph,二者仅 12px 间距;`BasicModal.handleCancel` 又对容器 class`-close--custom`)点击直接 return 不关闭,于是点在图标间隙/偏左会触发全屏而非关闭。实测点击关闭区中心命中 `anticon-fullscreen`(弹窗未关),仅点最右侧 26×36 的 glyph 才关闭。该组件为全局共享,所有弹窗都受影响。 | 实测 `artifacts/probe_x_realmouse.json`center 命中 fullscreenafter_real_click_center=1 未关;glyph 26×36 点击后=0 关闭);`artifacts/probe_x_glyph.json`icons=[fullscreen,close]bbox 分别为 36×36、26×36 | `src/components/Modal/src/components/ModalClose.vue``--can-full``margin-left:12px`、glyph padding);`src/components/Modal/src/BasicModal.vue:203-215`handleCancel 过滤容器 class |
| 2 | 文案 | **删除确认文案笼统**:单删 popConfirm title 仅「是否确认删除」,批删 createConfirm content「是否删除选中数据」,未说明是否连带删除关联反馈记录/流程,用户无法评估影响。(UX 报告 P2#7 并列) | `artifacts/delete_popconfirm.txt`;截图 `61_t8_delete_confirm.png` | `DqInspectTaskList.vue:437``DqInspectTask.api.ts:82-93` |
| 3 | 空态 | **空数据无引导**:无「清除筛选/去新建」出口,只有 ant-empty 默认「暂无数据」;在搜索失效场景(P0#1)下尤其误导。(UX 报告 P2#4 并列) | `artifacts/empty_state_html.html`;截图 `17_t1b_filter_done.png` | 列表空态(BasicTable 默认 empty |
| 4 | 可学习性 | **发起弹窗「立即发起/重复发起」无解释**:两者区别、何时选「重复发起」没有任何说明,业务用户凭感觉选。(UX 报告 P2#5 并列) | `artifacts/flow_start_modal.txt`;截图 `50_t3_flow_start_modal.png` | `DqInspectTaskFlowScheduleStartModal.vue:4-9` |
| 5 | 可学习性 | **高级查询字段名技术化**superQuerySchema 多个 title 带「ID」「流程实例ID」等后缀,业务用户无法理解。 | `artifacts/superquery_modal.txt``DqInspectTask.data.ts:175-193` | `DqInspectTask.data.ts` superQuerySchema |
| 6 | 视觉 | **状态行底色浅粉彩近白**`status-row-2` 底色 `#fff1f0`(督办中)、`status-row-1` `#fffbe6`,肉眼几乎看不出,状态辨识价值为零;对色弱用户更不可用。(UX 报告 P2#9vision+DOM 已复核) | `artifacts/rowcolors_probe.json`td 背景 rgb(255,241,240));CSS `DqInspectTaskList.vue:643-651`;截图 `04_list.png` | `DqInspectTaskList.vue:643-651` |
| 7 | 性能/console | **`DeptRoleUserSelectDropDown` 未声明 emits 导致控制台 `onChange` 类型警告**:组件没写 `emits`,父级 `@change="reload"` 被当作 fallthrough 属性落到根 `a-select`,与组件内部 `onChange` 合并成数组 → `Invalid prop: type check failed for prop "onChange". Expected Function, got Array`,控制台持续刷警告;功能上父级 reload 仍会触发,但属隐患(若将来 antd 校验更严或改传参方式会坏)。 | 实测 `artifacts/eng_15_final.json`console_errors_warnings 含该警告);`eng_01_console.json` | `DeptRoleUserSelectDropDown.vue`(缺 `emits: ['change']`);使用处 `DqInspectTaskList.vue:14` |
---
## 通过项(做得好的地方)
- **表单校验体验**:空提交一次列出 7 条明确必填提示(`DqInspectTaskForm.vue:246-255`:请选择具体问题/密级/整改措施/完成时限/措施责任部门/措施责任领导/分管所领导/党群领导审批),且提交失败会 `scrollToField` 定位到首错字段(353-367 行)。
- **防误删**:单删/批删均有二次确认(popConfirm + `createConfirm`),批量删除需先勾选行。
- **状态统计随筛选/操作刷新**`afterFetch → fetchStatusStats` 复用当前 `queryParam`,实测按 `bpmStatus=3` 筛选时统计同步归零、按 `bpmStatus=2` 时统计正常(`eng_02_api_bodies.json`);操作成功后 `handleSuccess → reload` 刷新列表与统计。
- **台账合并单元格实现正确**`calcLedgerRowSpan` 在**当前页内**计算问题分类/面上/具体问题的 rowSpan,避免跨页合并导致分页不可控(`DqInspectTaskList.vue:353-365`)。
- **API 契约整体一致**:列表 `GET ledgerList`、详情 `GET queryById`、删除 `DELETE delete/deleteBatch`id 拼 URL)、保存 `POST add/edit`、状态统计 `GET statusStats`、发起流程 `POST tasktask/taskTask/flow-schedules`RecurringTaskDTO{taskTask,intervalType,startCount})——与后端 Controller 参数绑定一一对应。
- **流程查看能力完整**:「查询督办流程」弹窗含审批历史/流程图/查询当前办理人/修改信息/删除流程入口(实测 `eng_06_flow.json` query_process_modal)。
- **详情字段回显**:除「措施责任领导」外,具体问题/密级/完成时限/分管所领导等均正确回显(`eng_05_detail.json`)。
- **测试数据卫生**:本次仅复用既有只读记录做验证;清理了上一轮 eng 残留的 `QA_TEST_整改措施_0/_1``eng_13_cleanup_ui`DELETE id=2087061887133655042),最终列表 1 条原始数据、无 QA_TEST_ 残留(`eng_15_final.json`)。
---
## 测试过程记录
### 操作步骤与截图
1. 登录 `/user/login`admin/123456)→ 进列表页(`screenshots/eng_15_final_list.png`,最终干净态:1 条「wqdwqd/督办中」,统计 未开始0/督办中1/已完成0)。
2. 整改措施输入 `wqdwqd` 查询 → 列表 0 行;清空输入 → 仍 0 行(请求带 `improveMeasure=**`)→ 确认搜索失效(`artifacts/eng_10_search_bug.json`)。
3. 分管所领导选「所党委01」→ 列表仍显示全部行(筛选被忽略,`artifacts/eng_11_cleanup_filters.json`)。
4. 打开记录详情弹窗 → 「措施责任领导」占位符、value 为空;下拉查询返回 dd_ld_02 但未选中(`artifacts/eng_09_leader_rootcause.json`,截图 `eng_09_detail_modal.png`)。
5. 督办中记录「流程操作」下拉 → 三项全显示,发起整改/销号弹窗均可打开(`artifacts/eng_06_flow.json`;未点提交)。
6. 复用 UX 轮证据:关闭按钮 X 误触(`probe_x_realmouse.json`/`probe_x_glyph.json`)、删除确认(`delete_popconfirm.txt`)、空态(`empty_state_html.html`)。
7. 清理残留 `QA_TEST_整改措施_1``scripts/eng_13_cleanup_ui.py`DELETE 成功,QA_TEST 计数归 0)。
### console 报错/警告列表(`artifacts/eng_15_final.json`
- `error: Failed to load resource: net::ERR_CONNECTION_CLOSED`(单个资源,多为 iconify/后台请求,影响小)
- `warning: [Vue warn] Failed to resolve component: AppSearch/Notify/AppLocalePicker/SettingDrawer/Aide`(全局布局头部组件解析警告,与本页无关,框架级噪音)
- `warning: [Vue warn] Invalid prop: type check failed for prop "onChange". Expected Function, got Array` at `<DeptRoleUserSelectDropDown>`**本页相关,P2#7**
### 关键网络请求(方法/URL/状态码)
- `POST /sys/login` → 200mock
- `GET /dqinspecttask/dqInspectTask/ledgerList?column=createTime&order=desc&pageNo=1&pageSize=12[&improveMeasure=*wqdwqd*]` → 200(搜索参数下 records:[]
- `GET /dqinspecttask/dqInspectTask/statusStats[?improveMeasure=*wqdwqd*]` → 200(同参数 inProgress:1,与列表不一致)
- `GET /dqinspecttask/dqInspectTask/queryById?id=2085316903091015681` → 200measureResLeader=dd_ld_02
- `GET /sys/user/queryUserRoleComponentData?departId=2044677731423850498&roleId=2044680793306591234...` → 200(返回 dd_ld_02/dd_ld_01,共 2 条)
- `GET /tasktask/taskTask/queryByBusinessId?businessId=...` → 200(流程列表)
- `DELETE /dqinspecttask/dqInspectTask/delete?id=2087061887133655042` → 200(清理 QA_TEST
### 待实测 / 未覆盖(明确标注,不进 P0/P1 判定)
| 项目 | 状态 | 说明 |
|------|------|------|
| 发起流程「提交」是否真创建重复流程实例 | **代码确认 + 实测入口,未实测提交** | 前端菜单无条件显示 + 后端 `singleFlowStart` 无业务守卫(`TaskTaskServiceImpl.java:55-75,133-152`);为保护真实流程数据未点提交,重复实例风险为代码路径推断,建议后端侧加状态/幂等校验 |
| 删除是否级联删除关联反馈/流程记录 | 代码推断,待实测 | 仅确认有二次确认弹窗;未点「确定」,后端删除行为需工程师侧补测 |
| 高级查询非 6 字段(targetNode 等)对列表失效 | 代码推断 | XML `queryLedgerPage` 仅 6 个 `<if>` 子句,与 chargeLeader(已实测忽略)同机制 |
| 加载态/后端错误态(断网/500/超时) | 未实测 | 依赖 BasicTable 默认 loading/empty,未发现自定义错误兜底 |
| 权限按钮显隐(非 admin 角色) | **未覆盖** | 仅 admin 账号;按钮均有 `v-auth` 指令(`dqinspecttask:dq_inspect_task:add/exportXls/importExcel/deleteBatch`),但无法对比验证不同角色显隐 |
| 特殊字符/超长文本/快速连点/双标签页并发 | 未实测 | 边界输入本轮未覆盖 |
| 不同分辨率/小屏适配 | 未实测 | 默认 1440 视口 |
---
*报告按工程师视角分级(P0/P1/P2),证据均来自浏览器实测(截图/网络响应/模态/DOM)或 `file:line` 代码定位;代码推断项已明确标注"代码推断,待实测",未计入 P0/P1。与 `QA_REPORT_UX.md` 重叠问题并列呈现,并补充技术根因与修复建议。测试未创建任何新业务数据,清理了上一轮 QA_TEST_ 残留,无残留入库。*