diff --git a/qa-report/bgpartymatter/QA_REPORT.md b/qa-report/bgpartymatter/QA_REPORT.md new file mode 100644 index 0000000..25d9f55 --- /dev/null +++ b/qa-report/bgpartymatter/QA_REPORT.md @@ -0,0 +1,86 @@ +# 前端页面工程师视角审查报告 — 党委会/所务会事项(bgpartymatter) + +## 审查信息 + +- 页面/路由:`/bg/bgpartymatter/BgPartymatterList`(党委会台账,菜单「党委会决策事项」);所务会复用 `BgOfficematterList`(`meetingType=office`,菜单「所务会决策事项」) +- 审查日期:2026-08-11 +- 审查视角:前端资深工程师(浏览器实测 + 代码审查结合,覆盖 API 契约、权限、状态一致性、表单校验、性能/异常等工程师专项维度) +- 相关文件: + - `src/views/bg/bgpartymatter/BgPartymatterList.vue` + - `src/views/bg/bgpartymatter/components/BgPartymatterForm.vue` + - `src/views/bg/bgpartymatter/components/BgPartymatterModal.vue` + - `src/views/bg/bgpartymatter/BgPartymatter.data.ts`、`BgPartymatter.api.ts` + - 后端:`backend/supervison-java/.../bgpartymatter/controller/BgPartymatterController.java`、`jeecg-boot-base-core/.../base/controller/JeecgController.java` +- 测试账号:`admin`(仅 1 个账号,多角色/多部门/多密级对比场景未覆盖,见「未覆盖项」) +- 证据目录:`qa-tmp/bgpartymatter/scripts/*.json`(eng_04~eng_09、02_modal、12_adddel_final、05_flow 等) +- 配套文档:`qa-report/bgpartymatter/QA_REPORT_UX.md`(用户视角报告,可并列对比) +- 说明:全程无头浏览器实测(Playwright,dev 端口 3100,登录走 mock、业务接口走真实后端 8080),登录账号 admin/123456。 + +## 总体结论 + +- **P0 × 1 | P1 × 2 | P2 × 7** +- 一句话总结:党委会/所务会台账的搜索、详情、流程、新增、删除都能走通且状态一致,但**导出功能 100% 不可用(后端稳定 500,前端静默无任何反馈)**——这是唯一的交付阻塞项,已定位到 AutoPoi 对不可变集合执行 `Iterator.remove()` 的根因;顶部统计标签不随筛选/增删改刷新、详情弹窗字段"看似可编辑实被透明遮罩拦截"是两大 P1 体验/一致性问题。 + +## P0 - 必须修复 + +| # | 维度 | 问题描述 | 证据 | 位置 | +|---|------|---------|------|------| +| 1 | 后端调用/功能 | **导出(导出 Excel)完全不可用**:点击工具栏「导出」→ 无下载、无 toast、无任何反馈;后端 `exportXls` 稳定返回 500。党委会、所务会两页同一 exportConfig 与同一后端接口,均复现。**根因(已定位)**:后端 `JeecgController.exportXls` 将 `service.list(queryWrapper)` 的查询结果直接作为数据集合传给 AutoPoi 导出;AutoPoi `ExcelExportServer.createSheet()` 第 198-202 行对数据集合迭代器执行 `its.next(); its.remove();` 分块清理,当数据集合为**不可变集合**时 `Iterator.remove()` 抛 `UnsupportedOperationException`;第 213 行 catch 用 `e.getCause()` 包裹(该异常无 cause → null),把真实原因吞掉,统一抛成 `ExcelExportException: Excel导出错误`,响应 trace 无 "Caused by"(与实测一致)。**实测链路**:0 行导出=200,任意 ≥1 行导出=500 且与字段内容无关(最小行、全字段行均失败);用与 `BgPartymatter` 全部 `@Excel` 字段一致的副本类独立复现(`C:\Users\sz04\AppData\Local\Temp\ap_repro`):可变 `ArrayList` → 成功(8704 字节),不可变集合 → 完全相同的 500。修复方向:① 前端 `exportConfig` 切换到后端已有的 EasyExcel 导出端点 `exportXlsByEasyExcel`(`BgPartymatterController.java:490-495`,同模块 `exportXlsHeaders` 模板下载已实测可用,见 P0 修复建议);② 或后端导出前把数据集合复制为可变 `List`;③ 同时前端应把导出失败透出错误提示而非静默。 | 实测:`exportXls` 响应 HTTP 500 body `ExcelExportException: Excel导出错误`(`qa-tmp/bgpartymatter/scripts/eng_04_trace.json`、eng_09 再复现 500 且 `export_toasts=[]`);所务会页同样 500(`eng_05_empty_office.json`);独立复现成功/失败对比(`ap_repro/MainRepro2.java` vs `MainReplica.java`);AutoPoi 源码 `ExcelExportServer.java:198-213` | `BgPartymatterList.vue:303-307`(exportConfig)、后端 `BgPartymatterController.java:281-287`、`JeecgController.java:62-88`(`:74` `service.list`、`:86` DATA_LIST)、AutoPoi `ExcelExportServer.java:198-213` | + +## P1 - 强烈建议 + +| # | 维度 | 问题描述 | 证据 | 位置 | +|---|------|---------|------|------| +| 1 | 状态一致性 | **顶部统计标签(未开始/督办中/已完成)不随筛选、搜索、增删改刷新**:搜索无结果/有结果、新增一条、删除一条后,列表数据都在变(总条数 3→4→3 正确变化),但三个统计标签始终不变(全程 `未开始 3 / 督办中 0 / 已完成 0`),与列表对不上,用户无法判断哪个是当前数据。**根因**:`fetchStatusStats` 仅在 `onMounted` 调用一次;`searchQuery`、`searchReset`、`handleSuccess`、新增/删除成功回调均未再触发统计刷新。 | 实测:`eng_09_engineer_final.json` —— 统计初始/新增后重查后/删除后重查后均为 `['未开始 3',...]`,而列表总条数 3→4→3(`events.after_api_add_reload.has_new_row=true`、`after_delete.residue=0`);`eng_07_listdump.json` —— 搜索前/搜索无结果后统计不变 | `BgPartymatterList.vue:100-104`(标签渲染)、`:446-465`(fetchStatusStats)、`:463`(仅 onMounted 调用)、`:440-444`(searchQuery)、`:509-513`(handleSuccess)、`:789-796`(searchReset) | +| 2 | 用户体验/交互 | **详情弹窗字段"看似可编辑、实际点不动"**:详情模式下表单上方有一层透明遮罩 `.jeecg-form-detail-effect`(实测 1100×580 透明 div,`pointer-events:auto`)拦截全部点击,但控件本身未灰化(下拉控件 opacity=1、cursor=pointer、肉眼无只读提示);点「密级」下拉实测不弹出;「确认」按钮被 `jee-hidden` 隐藏。用户反复点击无反应,误以为系统坏了/自己没点中。**根因**:`handleDetail` 设 `disableSubmit=true` → JFormContainer `:disabled` 渲染遮罩 + Modal 隐藏确认按钮,但只读态缺视觉表达(控件未置灰、无"只读"标识)。 | 实测:`eng_09_engineer_final.json` —— `detail_overlay_count=1`、`detail_overlay_style={pointerEvents:'auto', bg:'rgba(0,0,0,0)', 1100×580}`、`detail_select_dd_open=false`(点密级下拉不弹)、`detail_confirm_visible=false`、`detail_enabled_inputs=6`;`02_modal.json` —— 详情模式 11 只读 / 6 可编辑输入并存;关闭后页面可交互、无残留遮罩 | `BgPartymatterList.vue:486-490`(handleDetail)、`BgPartymatterModal.vue:2-6`(`jee-hidden`)、`BgPartymatterForm.vue:3`(JFormContainer `:disabled`)、`:256`(disabled=formDisabled) | + +## P2 - 建议 + +| # | 维度 | 问题描述 | 证据 | 位置 | +|---|------|---------|------|------| +| 1 | 反馈 | **新增成功无 toast**:新增提交成功、列表出现新行,但没有任何"保存成功"提示;删除却有"删除成功!",反馈不一致。**根因**:`submitForm` 用 `createMessage.success(res.message)`,后端返回的 `res.message` 为空串,`success()` 收到空串不渲染。 | 实测:`eng_09_engineer_final.json` 的 API add `{"success":true,"message":"添加成功!"}`(后端有 message 但前端未取到/为空);`12_adddel_final.json` —— add 无 toast、delete 有「删除成功!」 | `BgPartymatterForm.vue:403-411` | +| 2 | 表单校验文案 | **校验文案与字段名不一致**:主办部门字段漏选时,提示「请选择责任部门」,但字段 label 是「主办部门」,用户对不上号。 | 实测:`02_modal.json` form_item_errors(含「请选择责任部门」) | `BgPartymatterForm.vue:232-241`(validator message 写死"责任部门") | +| 3 | 表单校验体验 | **序号字段只读却报「请输入序号」**:序号输入框是只读的(自动生成),但必填校验文案是「请输入序号」,用户无法手动消除该错误(实际需回去填"议题序号"触发自动生成)。 | 实测:`02_modal.json`、`07_formmap.json` | `BgPartymatterForm.vue:23-26`(只读)+ `:228`(校验"请输入序号") | +| 4 | 布局/性能 | **表格过宽需横向拖动**:21 列总宽约 2808px,可视区约 1200px,中部字段(事项目录编码/抄告单编号/密级等)需反复横拖才能看到,看漏字段风险高。 | 实测:`.ant-table-body` scrollWidth=2808、clientWidth=1200(`eng_02_listdata.json` / 测量输出) | `BgPartymatter.data.ts:7-153`(21 列) | +| 5 | 可发现性 | **「完成状态」筛选默认藏在「展开」折叠里**:初始工具栏不显示,需点「展开」才出现,首次用户找不到状态筛选。 | 实测:toggle 文案"展开→收起"(`04_expand_filter.png`) | `BgPartymatterList.vue:39-52`(toggleSearchStatus 默认 false) | +| 6 | 空态引导 | **搜索无结果空态只有「暂无数据」**,无"换个条件/清除筛选"引导,也无一键清空入口。 | 实测:`eng_09` race_final 空表(`03b_search_empty.png`) | `BgPartymatterList.vue`(BasicTable 默认空态) | +| 7 | 控制台异常 | **列表页交互期间控制台出现 `Invalid prop: type check failed for prop "onChange". Expected Function, got Array`(``),以及点击「导出」时 500 触发 `Unhandled error during execution of component event handler`**。前者疑似筛选/搜索组件把多个 handler 合并成数组传给 ASelect(组件 prop 契约不严谨);后者证明导出失败在前端是未处理异常、被静默吞掉。 | 实测:`eng_09_engineer_final.json` console(19 条:5 个 app-shell `Failed to resolve component` + 7 条 ASelect onChange + 1 条 500 resource + 1 条 unhandled export handler) | 控制台证据(`eng_09_engineer_final.json`);export 相关 `BgPartymatterList.vue:303-307` | + +## 通过项(做得好的地方) + +- **列表刷新正常**:新增后手动点「查询」,列表立即出现新行(总条数 3→4);删除后「查询」,行消失(4→3)。列表数据链路(list API + 查询/重置)一致、无残留。 +- **竞态安全**:快速连续输入 3 个不同关键词(`QA_TEST_ENG_RACE_01 → 督办 → QA_ZZZ_NO_MATCH_RACE`,无间隔),最终表格与最后一个关键词一致(0 行)、无旧响应串台/残留渲染,未出现 out-of-order 覆盖。搜索即输即查无竞态问题。 +- **详情弹窗回显完整**:详情标题「详情」,19 项字段回显;关闭后页面完全可交互,无残留遮罩/状态污染。 +- **模板下载可用**:「下载模板」成功下载 `党委会-导入模板.xls`(EasyExcel `exportXlsHeaders` 路径,与走 AutoPoi 的「导出」形成对照——问题只在 AutoPoi 导出,不在模板)。 +- **删除链路完整**:行内更多 → 删除 → 二次确认 → 「删除成功!」toast → 列表刷新。新增/删除后列表均刷新。 +- **数据分流正确**:党委会(party)/所务会(office)数据严格隔离,不串台。 +- **流程弹窗可用**:「再次督办」发起流程弹窗标题/部门预填正确;「查询督办流程」流程列表可打开(引用 `QA_REPORT_UX.md` 任务 6 实测证据)。 +- **校验覆盖**:必填校验能定位到字段;序号自动生成(会议时间+议题序号联动)有效。 +- **导出 0 行场景正常**:无数据时导出返回 200(进一步佐证根因只在"有数据的迭代"路径)。 + +## 未覆盖项 / 待实测(不列入 P0/P1/P2 判定) + +| # | 项目 | 原因 / 现有线索 | +|---|------|----------------| +| 1 | 多角色/多部门/多密级权限对比(按钮级 `v-auth` 隐藏、数据权限过滤) | 仅 admin 一个账号,无法对比;`exportXls` 接口有 `@RequiresPermissions`,前端按钮有 `v-auth`,但未用第二账号实测不同角色下的可见性/越权 | +| 2 | 「模板校验」「模板导入」真实文件流程(选 Excel → 校验通过/报错提示) | headless 无法模拟系统文件选择框;对隐藏 input 塞 .txt 无任何 toast,结果不明确(`BgPartymatterList.vue:746-784`) | +| 3 | 后端 `service.list()` 返回**不可变集合**的具体包装层(是哪个拦截器/配置把 MP 的 `selectList` 结果变成不可变) | 前端侧证据已足够(0 行 200 / ≥1 行 500 / 独立复现),但精确到后端哪个类包装需后端日志/断点确认;已确认 `BgPartymatterServiceImpl` 为纯 MP `ServiceImpl` 无 `list()` 覆盖、`JeecgController.exportXls` 无包裹、运行时 AutoPoi 为 1.4.11(trace 行号与源码逐行吻合) | +| 4 | 「完成状态」筛选选中后的实际过滤行为(BPM 状态 dict 映射) | 未单独实测(筛选在「展开」里,见 P2-5);代码走 `JDictSelectTag @change="searchQuery"`,推断正常 | + +## 测试过程记录 + +- **环境**:前端 dev `http://127.0.0.1:3100`(运行中,未动);后端 `:8080/jeecg-boot`(真实);登录 `admin/123456`(mock 登录 + 真实业务接口)。脚本见 `qa-tmp/bgpartymatter/scripts/`。 +- **核心操作与产物**: + 1. `eng_04_trace.py` / `eng_05_empty_office.py`:直接导出抓 500 全量 body(party/office)、0 行导出对比 → `eng_04_trace.json`、`eng_05_empty_office.json`(0 行 200 / ≥1 行 500)。 + 2. `eng_07_listdump.py`:搜索无结果前后统计标签对比 → `eng_07_listdump.json`(统计不变)。 + 3. `eng_08_token2.py`:从请求头提取 X-Access-Token(localStorage 无 token,token 在内存/请求头注入)。 + 4. `eng_09_engineer_final.py`:综合验证(登录 → 列表 → API 新增 → 查询刷新 → 快速搜索竞态 → 详情遮罩 → 导出 → 模板 → API 删除)→ `eng_09_engineer_final.json`。 + 5. 复用既有产物:`02_modal.json`(新增必填校验+详情字段态)、`12_adddel_final.json`(新增/删除 toast)、`05_flow.json`(流程弹窗+导出 500)、`07_formmap.json`(表单字段映射)。 +- **关键网络请求**: + - `GET /jeecgboot/bgpartymatter/bgPartymatter/list?...` → 200(列表,正常) + - `POST /jeecgboot/bgpartymatter/bgPartymatter/add` → 200 `{"success":true}`(新增) + - `DELETE /jeecgboot/bgpartymatter/bgPartymatter/delete?id=...` → 200 `{"success":true}`(删除) + - `GET /jeecgboot/bgpartymatter/bgPartymatter/exportXls?...` → **500**(导出,P0) + - `GET /jeecgboot/bgpartymatter/bgPartymatter/exportXlsHeaders?...` → 200 下载 `党委会-导入模板.xls`(模板) +- **console 摘要**:5 条 app-shell `Failed to resolve component`(AppSearch/Notify/SettingDrawer 等,首页框架级,非本页引入);7 条 `ASelect onChange` 类型警告(P2-7);1 条 500 resource + 1 条 export 未处理异常(P0 佐证)。 +- **测试数据卫生**:本次会话创建 `QA_TEST_ENG_RACE_01` ×4(含多次中断运行残留)与既有的 `QA_ENG_BISECT_*` ×5、`清空后测试`、`assacas`(office),已全部经删除 API 清理并复核:party/office 列表按 `QA_`/`QA_TEST`/`QA_ENG` 过滤均 **0 残留**。测试数据一律置于 `qa-tmp/bgpartymatter/`(gitignore),不入库。 diff --git a/qa-report/bgpartymatter/QA_REPORT_UX.md b/qa-report/bgpartymatter/QA_REPORT_UX.md new file mode 100644 index 0000000..2deb926 --- /dev/null +++ b/qa-report/bgpartymatter/QA_REPORT_UX.md @@ -0,0 +1,98 @@ +# 前端页面用户视角审查报告 — 党委会/所务会事项(bgpartymatter) + +## 审查信息 + +- 页面/路由:`/bg/bgpartymatter/BgPartymatterList`(党委会台账,菜单名「党委会决策事项」);所务会复用 `BgOfficematterList`(`meetingType=office`,菜单名「所务会决策事项」) +- 审查日期:2026-08-11 +- 审查视角:业务用户(主视角,兼顾首次使用新手) +- 相关文件:`src/views/bg/bgpartymatter/BgPartymatterList.vue`、`components/BgPartymatterForm.vue`、`BgPartymatter.data.ts`、`BgPartymatter.api.ts` +- 证据目录:`qa-tmp/bgpartymatter/screenshots/`(截图 01–22)、`qa-tmp/bgpartymatter/scripts/*.json`(网络/表单/交互证据) +- 测试账号:`admin`(仅 1 个账号,多角色/多部门对比场景未覆盖) +- 说明:审查全程无头浏览器实测(Playwright,dev 端口 3100,登录走 mock,其余接口走真实后端 8080)。视觉复核已用 claude-vision-skill 实读截图(如 `08_detail_modal_closeup.png`)+ DOM 实测互补。 + +## 总体结论 + +- **P0 × 1 | P1 × 2 | P2 × 6** +- 一句话总结:搜索、查看详情、展开办理情况、发起/查询流程、新增、删除这些核心流程都能走通,但工具栏的「导出」按钮完全不可用且点击后毫无反应(后端 500 静默失败),是用户日常办事最大的拦路虎;顶部统计标签不随筛选/搜索/增删改刷新、详情弹窗字段「看似可编辑实则点不动」,会让用户误读数据、反复操作。 + +## P0 - 用户办不成事 / 会出错 + +| # | 用户场景 | 用户会遇到什么 | 后果 | 证据 | 位置 | +|---|---------|--------------|------|------|------| +| 1 | 我要把党委会台账导成 Excel 交上去 | 点击工具栏「导出」按钮,没有任何反应——不弹窗、不下载、不报错,页面静悄悄 | 台账无法导出,用户以为在下载/以为卡了,反复点也没用;后端每次返回 500(POI `ExcelExportException`),但前端吞掉异常不提示 | 实测:点击导出后 `downloads` 列表为空、无任何 toast;后端响应 `exportXls?meetingType=party` 返回 HTTP 500,body 为 `org.jeecgframework.poi.exception.excel.ExcelExportException: Excel导出错误`(见 `qa-tmp/bgpartymatter/scripts/06_crud.json` export_resp、`05_flow.json` api 日志;截图 `13_export.png`) | `BgPartymatterList.vue` 的 `useListPage` exportConfig(line 303-307)+ 后端 `bgPartymatter/exportXls` | + +## P1 - 明显受阻 / 容易困惑 + +| # | 用户场景 | 用户会遇到什么 | 后果 | 证据 | 位置 | +|---|---------|--------------|------|------|------| +| 1 | 我想看看「督办中」还有几件事,于是用事项名称/完成状态筛选 | 筛选后下面列表变了(比如 0 条),但顶部三个统计标签(未开始 0 / 督办中 1(已逾期 1)/ 已完成 0)**始终不变**,还是全台账的全局数字 | 列表与统计对不上,用户不知道哪个才对,可能误以为还有未完成事项没人管、或以为自己筛选没生效;增删改后统计也不刷新 | 实测:搜索无关关键词后列表 0 条,统计仍显示「督办中 1(已逾期 1)」;搜索命中后仍不变(`qa-tmp/bgpartymatter/scripts` 运行输出 / `02_list_overview.png` 初始态);`fetchStatusStats` 仅在 `onMounted` 调用一次,`searchQuery/searchReset/handleSuccess` 均未刷新统计(`BgPartymatterList.vue:446-465`) | `BgPartymatterList.vue:100-104`(统计标签)、`:463`(onMounted 仅一次) | +| 2 | 我在详情弹窗里想顺手改一下某字段再确认 | 详情弹窗里字段看起来都能点(光标是手型、颜色正常),但点下去**毫无反应**——实际被一层看不见的透明遮罩拦住,保存按钮也被隐藏 | 用户以为系统坏了/自己没点中,反复尝试浪费时间;看不清到底能不能编辑(视觉上无明确只读提示) | 实测:详情模式 `.jeecg-form-detail-effect` 遮罩层存在并拦截 pointer 事件;表单项 cursor=not-allowed、pointer-events=none,但下拉控件 opacity=1、cursor=pointer 显示为可点;主按钮带 `jee-hidden` 类隐藏(`qa-tmp/bgpartymatter/scripts/04_detail2.json`;截图 `08_detail_modal_closeup.png`);已用 vision 实读 `08_detail_modal_closeup.png` 确认截图视觉上下拉控件未灰化、呈可点外观,与点击无反应形成反差 | `BgPartymatterList.vue:486-490`(handleDetail 设 disableSubmit)+ `JFormContainer` 详情遮罩 | + +## P2 - 体验细节 + +| # | 用户场景 | 用户会遇到什么 | 后果 | 证据 | 位置 | +|---|---------|--------------|------|------|------| +| 1 | 我填完新增表单点「确认」 | 弹窗关掉、列表里出现了新记录,但**没有任何"保存成功"提示** | 用户不确定存没存上,容易重复提交或去别处找;删除却有"删除成功!"提示,前后反馈不一致 | 实测:新增 QA_UX_BGPM_003 后列表出现该行,但 `ADD TOASTS=[]`;删除时出现「删除成功!」toast(`12_adddel_final.json`) | `BgPartymatterForm.vue:403-411`(`createMessage.success(res.message)`,res.message 为空则不显示) | +| 2 | 我填主办部门时漏选了,直接提交 | 校验提示显示「**请选择责任部门**」,可这个字段明明叫「主办部门」 | 用户对不上号,以为提示说的是另一个字段 | 实测:空表单提交后,主办部门字段下报错文案为「请选择责任部门」(`02_modal.json` form_item_errors;截图 `10_add_validation_dupe.png`) | `BgPartymatterForm.vue:232-241`(校验 rule message 写死"责任部门",字段 label 为"主办部门") | +| 3 | 我只填了会议时间、没填议题序号就提交 | 「序号」字段提示「请输入序号」,可这个输入框是**只读的**(自动生成),我根本没法手动输入 | 用户不知道怎么消除这个错(实际上要回去填"议题序号"才会自动带出),提示指向了错误的操作对象 | 实测:序号输入框 readonly,placeholder 为"填写会议时间和议题序号后自动生成",但校验文案是「请输入序号」(`02_modal.json`、`07_formmap.json`) | `BgPartymatterForm.vue:23-26`(只读输入)+ `:228`(校验"请输入序号") | +| 4 | 我想看某条记录后面的完成状态、密级等字段 | 表格有 21 列,宽度约 2808px,可视区只有约 1200px,中部字段(序目录编码、抄告单编号、密级等)要一直横拖才能看到 | 反复左右拖动才能看完一条记录,看漏字段的风险高 | 实测:`.ant-table-body` scrollWidth=2808、clientWidth=1200,存在横向滚动(`scripts` 测量输出;截图 `02_list_overview.png`) | `BgPartymatter.data.ts:7-153`(21 列) | +| 5 | 我想按"完成状态"筛一下在办的 | 「完成状态」筛选条件默认藏在「**展开**」折叠里,不点开看不到 | 首次用户以为只能按年份/领导/名称/决议筛,找不到状态筛选 | 实测:页面初始工具栏无"完成状态",点「展开」后才出现(`04_expand_filter.png`,toggle 文案由"展开"变"收起");`toggleSearchStatus` 默认 false(`BgPartymatterList.vue:39`) | `BgPartymatterList.vue:39-52` | +| 6 | 我搜了个没结果的关键词 | 表格显示「暂无数据」四个字,没有"换个条件试试/清除筛选"的引导 | 用户不知道是没数据还是搜错了,也没有一键清空入口(只能自己点重置) | 实测:搜索无结果后表格空态为纯「暂无数据」(`03b_search_empty.png`) | `BgPartymatterList.vue` 空态(BasicTable 默认) | + +## 用户会觉得顺的地方 + +- 搜索即输即查(输入事项名称/会议决议时自动查询),「查询/重置」按钮位置和文案清楚,实测有效。 +- 事项名称可点击进详情,详情弹窗字段回显完整(年份/会议时间/议题序号/密级/事项名称/会议决议/主办协办部门/完成状态/督办次数/要求完成日期/是否急件/需所办领导审批等 19 项)。 +- 行首「展开」能看每条记录的责任部门办理情况子表,子表自带 未开始/进行中(含逾期)/已完成 统计,层级清晰。 +- 新增表单「序号」会根据会议时间+议题序号自动生成(如 `20260811-9`),少填一项(实测自动带出)。 +- 发起流程弹窗标题明确(如「发起流程(清空后测试 第二次督办)」),被督办部门已按主办/协办部门预填,发起类型/截止时间/是否急件/审批意见齐全。 +- 「查询督办流程」弹窗能列出该事项的流程列表(含流程图/审批历史/修改/删除入口)。 +- 删除有二次确认(「是否确认删除」),删除成功有 toast「删除成功!」。 +- 行状态着色(未开始黄 / 督办中红 / 已完成绿)+ 顶部统计标签帮助扫读(注:配色为浅粉彩 #fff1f0 系,单行时区分度中等;统计标签不随筛选刷新见 P1-1)。 +- 党委会/所务会数据严格分流(实测所务会页显示独立的"assacas"记录,不串台)。 +- 校验错误信息具体(请选择年份/请输入事项名称/请输入会议决议),能定位到字段。 + +## 12 维度核对结果汇总 + +| # | 维度 | 通过 | 问题(简写+证据位置) | +|---|------|------|----------------------| +| 1 | 目标达成 | 部分 | 导出任务完全无法完成(P0-1);其余核心任务走通 | +| 2 | 可发现性 | 部分 | 完成状态筛选藏在"展开"折叠(P2-5);导出/下载模板/模板校验/模板导入等按钮集中在工具栏,一眼可见 | +| 3 | 可学习性 | 部分 | 序号只读但报"请输入序号"(P2-3);校验文案"主办部门/责任部门"不一致(P2-2) | +| 4 | 效率 | 通过 | 搜索即输即查、序号自动生成、部门预填;无需多余确认 | +| 5 | 认知负荷 | 部分 | 表格 21 列过宽需横拖(P2-4);统计与筛选不一致增加理解负担(P1-1) | +| 6 | 文案清晰度 | 部分 | 校验文案字段名不一致(P2-2);导出失败无任何文案(P0-1);多数提示文案业务化、可读 | +| 7 | 反馈及时性 | 部分 | 导出静默失败无反馈(P0-1);新增无成功 toast(P2-1);删除有 toast;列表增删后自动刷新 | +| 8 | 误操作防护 | 通过 | 删除有二次确认;详情模式保存按钮隐藏(不可误提交);提交前必填校验明确 | +| 9 | 空态/加载/错误态 | 部分 | 空态仅"暂无数据"无引导(P2-6);后端 500 被吞成静默(P0-1);加载中正常 | +| 10 | 无障碍细节 | 部分 | 详情字段"看似可点实则被遮罩拦截",光标/颜色与行为不一致(P1-2,已 vision 复核 `08_detail_modal_closeup.png` 确认下拉控件未灰化、cursor=pointer、肉眼无只读提示);Tab 键盘流未专项验证 | +| 11 | 视觉一致性 | 通过 | 按钮、标签、状态色与平台其他台账页一致(参照 xispeak/inspectTask 风格);无错位溢出(此前 BGPARTYMATTER_CHECKLIST 已核) | +| 12 | 边界场景 | 部分 | 搜索空结果有"暂无数据";超长文本/连点/刷新丢数据等未逐项实测(见待实测) | + +## 用户任务走查记录 + +- 任务 1:登录进入台账 + - 打开 `/user/login` 输入 admin/123456 回车 → 进入流程门户;直接访问 `/bg/bgpartymatter/BgPartymatte +- 任务 2:搜索一条记录rList` 打开党委会台账。截图 `01_login_home.png`、`02_list_overview.png`。顺畅。 + - 事项名称输入"督办"→ 0 条(空态"暂无数据");输入"清空"→ 1 条命中;点「重置」恢复全部。搜索即输即查+查询按钮均可用。截图 `03_search_title.png`、`03b_search_empty.png`。顺畅;但发现统计标签不随搜索变化(P1-1)。 +- 任务 3:查看详情 / 展开办理情况 + - 点事项名称打开详情弹窗(标题"详情",19 字段回显)→ 点行首箭头展开"办理情况"子表(含统计与附件下载列)→ 收起。截图 `05_expand_feedback.png`、`06_detail_modal.png`、`08_detail_modal_closeup.png`。顺畅;发现详情字段被透明遮罩拦截点击(P1-2)。 +- 任务 4:筛选(含展开"完成状态") + - 点工具栏「展开」→ 出现"完成状态"筛选 → 折叠。截图 `04_expand_filter.png`。发现状态筛选藏折叠里(P2-5)。 +- 任务 5:导出 / 下载模板 / 模板校验 / 模板导入 + - 「下载模板」成功下载"党委会-导入模板.xls"(截图 `12_template_download.png`);「导出」点击后无任何反应,后端 500(截图 `13_export.png`,证据见 05/06 json)→ P0-1;「模板校验/模板导入」点开是文件选择(headless 无法完成真实选文件,见待实测)。 +- 任务 6:流程操作(发起/查询) + - 行内"更多"→「再次督办」打开发起流程弹窗「发起流程(清空后测试 第二次督办)」,部门已预填(截图 `16_flow_modal.png`、`07_row_dropdown.png`);「查询督办流程」打开流程列表(含流程图/审批历史等,截图 `17_query_process.png`)。顺畅。 +- 任务 7:新增→校验→删除(建数实测) + - 新增弹窗空表单提交 → 8 个必填校验(截图 `10_add_validation_dupe.png`);填全(含部门"选择"弹窗选 DD、密级选"非密")后提交 → 列表出现 `QA_UX_BGPM_003 测试`(序号自动生成 `20260811-9`,完成状态默认"未开始")→ 无成功 toast(P2-1);删除该记录 → toast「删除成功!」→ 列表无残留。截图 `19_add_filled.png`、`20_list_after_add.png`、`21_list_after_delete.png`。**已建数实测并清理,无残留。** + +## 待实测 / 代码推断项(不列入 P0/P1) + +| # | 项目 | 为什么没实测 | 现有线索 | +|---|------|------------|---------| +| 1 | 「模板校验」「模板导入」完整流程(选真实 Excel → 校验通过/报错提示) | 两者是文件上传按钮,headless 无头浏览器无法模拟系统文件选择框;实测对隐藏 input 设置一个 .txt 文件后无任何 toast,结果不明确 | `BgPartymatterList.vue:746-784`;后端 `getCheckExcelByEasyExcelUrl`/`getImportExcelByEasyExcelUrl` | +| 2 | 详情模式字段的视觉"只读感" | 已用 vision 实读 `08_detail_modal_closeup.png` 确认:下拉控件未灰化、cursor=pointer,截图视觉上无任何只读/不可编辑提示 → "看似可编辑"从 DOM 推断升级为**实测确认**(即 P1-2),不再待实测 | DOM:遮罩 `.jeecg-form-detail-effect` 拦截点击、表单项 cursor=not-allowed、下拉控件 opacity=1/cursor=pointer | +| 3 | 所务会(office)页「导出」是否同样 500 | 所务会与党委会是同一组件复用(`meetingType=office`),未单独实测导出 | 同一 exportConfig 与后端 `exportXls` 接口,推断大概率同错(P0-1 同源),待实测 | +| 4 | 表格过宽的中部列是否需要"冻结/固定"常用列 | 业务上哪些列最常用需人工确认 | 实测 scrollWidth 2808 vs 可视 1200,仅"操作"列固定右侧 | +| 5 | 键盘 Tab/回车完整走查、超长文本/快速连点等边界 | 时间盒内未逐项执行 | 未发现专项问题,列为常规复核项 | +| 6 | `BgPartymatterFeedbackList.vue` 独立反馈页的用户可达性 | 菜单 SQL(`V20260416_1__menu_insert_BgPartymatter.sql`)只注册了"党委会",反馈功能在主列表"办理情况"展开面板内操作 | 独立路由 `/bg/bgpartymatter/BgPartymatterFeedbackList` 能打开(渲染了应用壳),但未见独立菜单入口 | diff --git a/qa-report/bqtakepulse/QA_REPORT.md b/qa-report/bqtakepulse/QA_REPORT.md new file mode 100644 index 0000000..ee00eb2 --- /dev/null +++ b/qa-report/bqtakepulse/QA_REPORT.md @@ -0,0 +1,87 @@ +# 前端页面审查报告 — 我为四所把把脉(bg/bqtakepulse/BgTakepulseList) + +## 审查信息 +- 页面/路由:`http://127.0.0.1:3100/bg/bqtakepulse/BgTakepulseList`(我为四所把把脉 台账列表) +- 审查日期:2026-08-11 +- 审查视角:资深前端工程师(frontend-page-qa,浏览器实测 + 代码审查结合) +- 相关文件: + - `src/views/bg/bqtakepulse/BgTakepulseList.vue` + - `src/views/bg/bqtakepulse/components/BgTakepulseForm.vue`、`BgTakepulseModal.vue`、`BgTakepulseBPMForm.vue` + - `src/views/bg/bqtakepulse/BgTakepulse.api.ts`、`BgTakepulse.data.ts` + - `src/components/Form/src/jeecg/components/SzSelectDept.vue`、`modal/SzDeptSelectModal.vue` + - `src/components/Form/src/jeecg/hooks/useTreeBiz.ts` + - `src/components/semri/userComponent/DeptRoleUserSelectRadioGroup.vue` + - `src/hooks/system/useMethods.ts`(导出) + - 后端:`BgTakepulseController.java`、`BgPartymatterController.java`、`BgXiSpeakController.java`(导出 500 交叉验证) +- 测试账号:`admin` / `123456`(mock,唯一账号) +- 证据目录:`qa-tmp/bqtakepulse/`(eng_screens/ + scripts/eng*_steps.txt / eng*_api.json / eng*_console.json) + +> 说明:本报告为工程师视角,先读代码建立假设再浏览器实测。所有 P0/P1 均来自浏览器实测证据;标注「代码推断,待实测」的项只计入 P2(未实测到或实测被 P0 阻断)。 +> 视觉维度:以 DOM 结构 + `getComputedStyle` 计算样式评估,**视觉细节需人工复核**(本环境 Read 图片返回 Unsupported,未直接判读截图)。 + +## 总体结论 +- **P0 × 1 | P1 × 2 | P2 × 9** +- 一句话总结:**「新增」链路被部门树选择失效阻断(P0)**——牵头部门必填但部门树弹窗点选后无法回写值,导致一条新记录都建不出来、查询区也无法按部门筛选;导出 Excel 三个模块全量 500(后端 AutoPoi 共享缺陷)且前端静默吞错无提示;顶部统计标签不随搜索/增删改刷新。页面**当前不建议交付**,需先修 P0。 +- 与 UX 报告(`QA_REPORT_UX.md`,P0×0/P1×2/P2×6)对比:UX 报告漏掉了**部门树无法回写(P0)**与**统计标签不刷新(P1)**两条——前者是会把用户直接卡死的关键缺陷,工程师视角通过代码(`useTreeBiz.onSelect` 守卫)定位并实测确认。 + +## P0 - 必须修复 +| # | 维度 | 问题描述 | 证据 | 位置 | +|---|------|---------|------|------| +| 1 | 逻辑合理性 / 用户流程 | **部门树弹窗点选后无法回写表单值,新建记录被彻底阻断**。新增弹窗与查询区的「牵头部门」「协办部门」打开部门树后:树节点无复选框、点击节点(如 QLS)仅高亮(`ant-tree-node-selected`),点「确认」后表单输入框仍为空,值不回写。牵头部门为必填项(空表单提交提示「请选择牵头部门」)→ **用户无法通过校验,一条新记录都建不出来**;查询区同样无法按部门筛选。 | 实测:`engC_steps.txt`(点击 QLS→`sel:true`;确认后 input `value:""`);`engB_steps.txt:8-12`(确认后牵头部门仍「请选择」);截图 `engC_query_vs_form_tree.png`(树无复选框)、`engC_dept_after_confirm.png`;提交校验报错含「请选择牵头部门」(`engB_steps.txt`) | 前端:`BgTakepulseForm.vue:69,74`、`BgTakepulseList.vue:28,36`(`` 未传 `checkable`);`SzDeptSelectModal.vue`;**根因** `useTreeBiz.ts:79-89 onSelect` 守卫 `if (props.checkable == false)`——`checkable` 未传默认 `undefined`,`undefined == false` 为 `false`,分支永不执行,`checkedKeys` 恒空;`getSelectTreeData`(`:238-249`)只读 `checkedKeys/selectRows` → 确认回传空值。该部门组件改造由 commit `e852ebd`(czh-20260612「完成部门组件改造…目前已经把把把脉的组件替换」)引入 | +| | | **修复建议**:给 `SzSelectDept` 传 `checkable`(复选框树),或令 `SzDeptSelectModal` 内部 `checkable` 恒为 `true`;并修正 `useTreeBiz.onSelect` 对 `checkable === undefined` 的守卫逻辑(按「非 checkable 即 select 模式」处理)。修复后回归:新增弹窗选部门→确认→值回写→提交成功;查询区选部门→列表按部门过滤。 | | | + +## P1 - 强烈建议 +| # | 维度 | 问题描述 | 证据 | 位置 | +|---|------|---------|------|------| +| 1 | 后端调用 / 用户体验 | **导出 Excel 全部 500,且前端无任何错误提示**。三个模块(bqtakepulse / bgpartymatter / xispeak)`exportXls` 均返回 HTTP 500:`org.jeecgframework.poi.exception.excel.ExcelExportException: Excel导出错误`(AutoPoi/JeecgEntityExcelView 路径);同一列表 EasyExcel 路径 `exportXlsHeaders` 正常(200/xlsx)。前端 `useMethods.exportXls` 无 `try/catch`、`errorMessageMode` 默认 `'none'`、`FileReader` 的 "success" 判断是死代码 → 用户点「导出」后无响应、无提示,表现为「卡死」。 | 实测:`engA_batch_export.json`(三模块均 500 + 异常类名);`exportXlsHeaders` 200(`engA_steps.txt`);截图 `engA_list.png`;UX 报告同样实测到(`walk14/15_log.txt` 500×2) | 后端:`BgTakepulseController.java:366-401 exportXls`(`JeecgEntityExcelView` + AutoPoi);前端:`src/hooks/system/useMethods.ts:23-55`、`useListPage.ts:66-117`;表头「导出」按钮 `BgTakepulseList.vue:53` | +| | | **根因(后端共享,本次仅报告不改后端)**:AutoPoi 1.4.11 与 POI 版本不兼容(源码 `ExcelExportServer.createSheet:213` 抛 `ExcelExportException`,`e.getCause()` 为 null,具体堆栈在后端 IntelliJ 控制台不可读)。**前端修复建议**:`useMethods.exportXls` 加 `try/catch`,失败 `createMessage.error('导出失败,请稍后重试')`;后端排查 AutoPoi/POI 版本或迁移 EasyExcel 导出。 | | | +| 2 | 状态一致性 | **顶部统计标签(未开始/督办中/已完成)不随搜索、重置、增删改刷新**。`statusStats` 仅在 `onMounted` 调用一次:实测搜索无命中(rows=0)后标签仍显示全量「未开始 0 / 督办中 1(已逾期 0)/ 已完成 0」;重置、删除后同样不更新。用户看到的是与列表/筛选结果矛盾的过期统计。 | 实测:`eng2_steps.txt:70-71`(无命中搜索 stats 不变、rows=0);`engA_steps.txt`(statusStats 调用数 初始后=1、搜索后=1、重置后=1,仅 mount 一次) | `BgTakepulseList.vue:383-385`(`onMounted(() => fetchStatusStats())`);`searchQuery:360-364`、`searchReset`、`handleSuccess` 均未调用 | +| | | **修复建议**:在 `searchQuery` / `searchReset` / `handleSuccess`(增删改后)里调用 `fetchStatusStats()`,与 xispeak 已实现的「统计标签随搜索/筛选/增删改同步刷新」保持一致。 | | | + +## P2 - 建议 +| # | 维度 | 问题描述 | 证据 | 位置 | +|---|------|---------|------|------| +| 1 | 用户体验 | **保存成功无任何提示**(代码推断,待实测)。`submitForm` → `saveOrUpdate` → `emit('success')`,无 `createMessage.success`;`BgTakepulseModal.submitSuccess` 同样无 toast。用户保存成功看不到反馈。(因 P0 部门树问题无法走通完整保存,未实测) | 代码:`BgTakepulseForm.vue:391-399`、`BgTakepulseModal.vue:43-46` | 同上 | +| 2 | 数据源 | **所办领导选项显示为内部编码**(`bg_ld_01` / `dd_ld_02`),用户看不出审批人是谁。`queryUserRoleComponentData` 返回的 `realname` 字段就是编码,`DeptRoleUserSelectRadioGroup` 直接渲染 `realname`。根因在数据(用户表 realname 存了编码),前端照实渲染。 | 实测:`engB_steps.txt:16`(`queryUserRoleComponentData: [{"username":"dd_ld_02","realname":"dd_ld_02"},{"username":"bg_ld_01","realname":"bg_ld_01"}]`) | `DeptRoleUserSelectRadioGroup.vue:4` | +| 3 | 数据源 | **部门树节点名称为缩写**:QLS、SLD、BG部、DQ部、SZHZX、RH、JJ、DD,非部门全称,用户选部门靠猜。数据来自 `queryTreeList` → `sys_depart.depart_name`。 | 实测:`engC_steps.txt`(部门树弹窗节点)、`engB_steps.txt`、截图 `engB_dept_tree.png` | `SzDeptSelectModal.vue`(数据源) | +| 4 | 用户体验 | **点击意见主题标题同时触发行展开与详情弹窗**。标题 `` 的 `@click="handleDetail"` 未阻止冒泡,表格 `expandRowByClick: true` → 点标题「办理情况」反馈区被一起展开 + 详情弹窗打开,与用户看详情意图冲突。 | 实测:`engD_steps.txt`(点 assac 标题后 `expanded=1` 且 `modals=['详情']`);截图 `engD_title_click.png` | `BgTakepulseList.vue:86`(title a)、`:220`(`expandRowByClick: true`) | +| 5 | 表单校验 | **牵头部门必填但无红色星号**(代码推断,待实测)。`responDeptid` 的 `validatorRules` 仅自定义 validator(值为空时 reject「请选择牵头部门」),无 `required: true` → 表单不渲染必填星号,用户提交失败才知道必填。 | 实测:`eng2_steps.txt:152`(空表单校验错误含「请选择牵头部门」);代码:`BgTakepulseForm.vue:260-269` | `BgTakepulseForm.vue:68-71` | +| 6 | 逻辑合理性 | **bpmStatus 为空时下拉同时出现「发起督办流程」与「再次督办」**(代码推断,待实测)。`getDropDownAction` 用 `record.bpmStatus=='1'||!record.bpmStatus` 与 `record.bpmStatus=='2'||!record.bpmStatus` 两个独立 if:从未发起过流程(bpmStatus 空)的记录两个入口都会显示,且二者都走 `handleProcess`(功能重复、用户困惑)。 | 代码:`BgTakepulseList.vue:474-485`;`eng2_steps.txt:143`(assac bpmStatus='2' 仅显示「再次督办」,空值分支未被实测到) | `BgTakepulseList.vue:474-485` | +| 7 | 后端调用(性能) | **搜索框每键触发查询,快速筛选产生大量重复请求且无序号守卫**。`JInput @change="searchQuery"` 每键入一次发一次 `/list` 请求;实测快速切筛选(assac→ZZZ→assac)触发 14 次 `/list` 请求,存在旧响应覆盖新结果的竞态风险(最终状态正确,但冗余明显)。 | 实测:`eng2_steps.txt:140`(竞态期间 /list 14 次)、`eng3_api.json`(相邻两次同 query 重复请求) | `BgTakepulseList.vue:12`(`JInput @change="searchQuery"`) | +| 8 | 美观 / 表格 | **25 列宽 3848px 横向滚动,仅「操作」列固定右,「完成状态」(第 24 列)等关键列不固定**,横向滚动时无法对照查看。建议固定右侧「完成状态 / 操作」两列。 | 实测:`eng2_steps.txt:137`(`contentScrollW=3848, contentClientW=1200, fixRight=['操作'], fixLeft=[]`);`BgTakepulse.data.ts` 24 列(含反馈子表共 25) | `BgTakepulseList.vue:223-226`(`actionColumn.fixed:'right'`)、`BgTakepulse.data.ts` | +| 9 | 控制台告警 | **BaseSelect/VcSelect/ASelect 组件 prop 类型告警泛滥**:控制台大量 `[Vue warn]: Invalid prop: type check failed for prop "onChange"/"onClick". Expected Function, got Array`(牵头/协办部门选择框)。另有布局组件未解析告警(AppSearch/Notify/AppLocalePicker/SettingDrawer/Aide,框架级、非本页)。 | 实测:`eng2_console.json`(157KB 告警,`onChange/onClick Expected Function got Array` 重复出现) | 部门选择组件(`BaseSelect`/`VcSelect` 封装对 `onChange/onClick` 传参类型错误) | + +## 通过项(做得好的地方) +- 登录、列表加载、数据回显正常;行数据正确。 +- 行状态配色生效:首行 `class="... status-row-2"`(`eng2_steps.txt:145`)。 +- 删除有 popconfirm 二次确认(「是否确认删除」),下拉菜单(详情/删除/查询督办流程/再次督办)正常渲染(`eng2_steps.txt:142-148`)。 +- 空表单提交校验错误提示清晰且定位到字段:请选择年份 / 请选择密级 / 请输入意见主题 / 请选择牵头部门(`eng2_steps.txt:152`)。 +- 密级字典选项正常(非密/内部/秘密/机密);年份选择器可用(`engB_steps.txt`)。 +- 「是否需要所办领导审批」开关正确联动「所办领导」字段显隐,不需要时自动清空历史值(`showSupDeptLeader` + `clearSupDeptLeaderIfNotNeeded`,`BgTakepulseForm.vue:253,302-310`)。 +- 竞态测试最终列表状态正确(快速切筛选后 rows=1,无脏数据落库)。 +- 导出 EasyExcel 路径(`exportXlsHeaders`)接口正常(200)。 + +## 未覆盖项(受账号/数据限制) +- **权限多账号对比**:仅有 `admin`,不同角色/密级/部门下的按钮显隐(`v-auth`)、数据范围、只读态未验证。 +- **完整「新建→保存成功」链路**:被 P0 部门树阻断,无法走通;「保存无 toast」仅代码推断(P2)。 +- **详情编辑保存、模板导入、发起/再次督办流程提交**:为避免产生真实流程实例 / 改动真实数据,未执行提交类操作。 +- **视觉细节**:本环境无法直接判读截图,美观/响应式/暗黑主题以 DOM + 计算样式评估,**需人工复核**。 + +## 测试过程记录 +- **脚本**:`qa-tmp/bqtakepulse/scripts/eng_probe.py`(初始探针)、`eng_probe2.py`(状态一致性/删除/下拉/固定列/竞态)、`eng_probe3.py`(清空搜索 title=** / QA_TEST 建删)、`eng_probeA.py`(批量导出 500 交叉验证 + statusStats 时机 + 数据源)、`eng_probeB.py`(新建表单/所办领导编码/保存无 toast)、`eng_probeC.py`(部门树选择实证)、`eng_probeD.py`(标题点击展开)。 +- **截图**:`qa-tmp/bqtakepulse/eng_screens/`(`eng_02_list_initial.png`、`engA_list.png`、`engB_*.png`、`engC_query_vs_form_tree.png`、`engC_dept_after_confirm.png`、`engD_title_click.png`、`eng2_dropdown.png`、`eng2_new_validation.png` 等)。 +- **网络记录**:`engA_batch_export.json`(导出 500×3 + 异常类)、`engB_api.json`、`eng2_api.json`、`eng3_api.json`(`title=**` 清空搜索行为:输入 `assac` 后清空回车发 `title=**`,返回全部)。 +- **console**:`eng2_console.json`、`engB_console.json`(0 error、87+ warning,主要两类:`onChange/onClick Expected Function got Array` 与布局组件未解析)。 +- **关键实测结论**: + 1. 导出 `exportXls`:bqtakepulse/bgpartymatter/xispeak 均 500 `ExcelExportException`;`exportXlsHeaders` 200 → AutoPoi 导出路径全局失效(后端根因)。 + 2. `statusStats`:mount 调 1 次,搜索/重置后不再调用,统计标签与列表结果不一致。 + 3. 部门树弹窗:点节点仅高亮、确认后值不回写(P0 根因)。 + 4. 所办领导:`queryUserRoleComponentData` realname 为编码。 + 5. 标题点击:同时展开行 + 打开详情弹窗。 + 6. 竞态:3 次筛选触发 14 次 `/list` 请求。 +- **测试数据卫生**:尝试创建 `QA_TEST_PULSE_ENG_*` 记录,被部门树 P0 阻断未创建成功;全流程未对真实数据做增删改,**无残留数据**。 + +## 修复优先级建议 +1. 先修 P0(部门树选择回写)——否则「新增」功能完全不可用。 +2. 同步修 P1:导出失败前端提示(后端 AutoPoi 单独提缺陷);统计标签随筛选/增删改刷新。 +3. P2 按性价比排:所办领导/部门树数据源补全名称 → 标题点击 stopPropagation → 搜索防抖/序号守卫 → 固定完成状态列。 diff --git a/qa-report/bqtakepulse/QA_REPORT_UX.md b/qa-report/bqtakepulse/QA_REPORT_UX.md new file mode 100644 index 0000000..1097d69 --- /dev/null +++ b/qa-report/bqtakepulse/QA_REPORT_UX.md @@ -0,0 +1,75 @@ +# 前端页面用户视角审查报告 — 我为四所把把脉(bg/bqtakepulse/BgTakepulseList) + +## 审查信息 +- 页面/路由:`http://127.0.0.1:3100/bg/bqtakepulse/BgTakepulseList` +- 审查日期:2026-08-11 +- 审查视角:业务用户(兼顾首次使用的新手) +- 相关文件:`src/views/bg/bqtakepulse/BgTakepulseList.vue`、`BgTakepulseForm.vue`、`BgTakepulseModal.vue`、`BgTakepulse.data.ts`、`BgTakepulse.api.ts` +- 证据目录:`qa-tmp/bqtakepulse/`(screenshots/ + walk*.log + new_modal_fields.json + scripts/probe_1920_log.json) + +> 说明:本报告为"用户视角"审查,所有问题均来自浏览器实测(用户实际操作触发 + 截图/操作日志/后端响应为证)。涉及代码的部分仅用于定位根因,不替代实测。 +> 视觉复核:P2-4 已用 claude-vision-skill 复核 1920×1080 截图 + DOM 实测。**vision 只能确认可视区内内容,判断不了被横向滚动藏住的列(曾误判"右边没有未显示列")**,溢出/隐藏列以 DOM 实测(`probe_1920_log.json`)为准。 + +## 总体结论 +- **P0 × 0 | P1 × 2 | P2 × 6** +- 一句话总结:作为业务用户,这个页面"查台账、看详情、查流程、下载模板"这些日常动作基本能办成,搜索/筛选/校验提示都算顺;但**核心工具栏里的"导出"点了毫无反应(后端 500 静默失败)**,且**新建表单里"牵头部门"这项必填却不打星号、提交失败了才知道**,这两处会让用户卡住或以为系统坏了——页面对新用户"一眼就能上手"还有距离,但主要流程可以走通、数据无损。 + +## P0 - 用户办不成事 / 会出错 +无(实测范围内未发现会导致任务完全无法进行或数据丢失/误导的 P0 项)。 + +## P1 - 明显受阻 / 容易困惑 +| # | 用户场景 | 用户会遇到什么 | 后果 | 证据 | 位置 | +|---|---------|--------------|------|------|------| +| 1 | 台账要拿给领导,点工具栏的"导出" | 点导出后**没有任何反应**:不弹保存、不下载文件、不转 loading、也没有任何成功或失败提示。连点两次都这样。 | 数据导不出去,用户不知道是没点中、是卡了、还是系统坏了,会反复点、找别的方式导出,耽误事 | 实测点击"导出"2 次,后端 `exportXls` 接口**两次都返回 HTTP 500**,页面无 toast/无下载;证据 `qa-tmp/bqtakepulse/screenshots/63_after_export2.png`、`65_after_export_final.png`;network 记录见 `walk14_log.txt`/`walk15_log.txt`(500×2,toasts 为空) | 表头"导出"按钮(`BgTakepulseList.vue:53`,走 `useListPage` 的 `onExportXls`);根因在**后端** `exportXls`(500),前端未把失败反馈给用户 | +| 2 | 新建一条意见,看到必填项随手填 | 牵头部门这一栏**页面上没有任何"必填"星号**,看起来可填可不填;直接提交时却被拦下报"请选择牵头部门"。 | 必填项全靠用户"试错"才知道,提交一次失败一次,让人不耐烦;新手可能以为系统乱拦 | 空表单提交校验报错原文:`请选择年份 / 请选择密级 / 请输入意见主题 / 请选择牵头部门`(`qa-tmp/bqtakepulse/screenshots/17_validation_empty.png`);而实测弹窗字段结构里**牵头部门 `required: false`、无红色星号**(`new_modal_fields.json`);代码 `BgTakepulseForm.vue:260-269` 对 `responDeptid` 只写了自定义 validator、rule 里没有 `required` | 新建弹窗表单项"牵头部门"(`BgTakepulseForm.vue:68-71`) | + +## P2 - 体验细节 +| # | 用户场景 | 用户会遇到什么 | 后果 | 证据 | 位置 | +|---|---------|--------------|------|------|------| +| 1 | 想看一下某条意见的详细内容,点意见主题 | 点标题看详情的同时,**下面的"办理情况"反馈区也被一起展开了**,关掉详情弹窗后多出一个我没让打开的展开区,还得手动再收起 | 多一步多余动作,页面状态和用户意图不符,轻微困惑 | 实测点击标题前展开图标为 collapsed,点击后变 expanded 且页面同时出现"办理情况"区(`qa-tmp/bqtakepulse/screenshots/15_title_click_expand.png`;`walk3_log.txt` A 段) | 标题链接 `@click="handleDetail"` 未阻止冒泡,与 `expandRowByClick: true`(`BgTakepulseList.vue:220,84-88`)叠加触发 | +| 2 | 要发起督办流程,选"所办领导" | 流程发起弹窗里"所办领导"的选项显示的是**内部编码 `bg_ld_01`、`dd_ld_02` 而不是人名**,看不出是谁 | 用户无法识别审批人是谁,可能选错人或不敢选;此为流程关键字段 | 实测发起流程弹窗文案含 `所办领导 bg_ld_01 dd_ld_02`(`qa-tmp/bqtakepulse/screenshots/59_process_modal.png`) | 流程发起弹窗"所办领导"选项(`DeptRoleUserSelectRadioGroup` 渲染;疑似用户表缺可读姓名,根因待后端确认) | +| 3 | 填部门相关的字段(牵头/协办部门) | 部门选择树里显示的是**缩写编码**:QLS、SLD、BG部、DQ部、SZHZX、RH、JJ、DD,新用户看不懂哪个部门是哪个 | 选部门靠猜,容易选错 | 实测部门树节点即这些缩写(`qa-tmp/bqtakepulse/screenshots/25_dept_picker.png`、`50_dept_picker.png`;`walk9_log.txt`) | 部门选择组件数据源(部门树本身的数据/编码) | +| 4 | 台账很多列,想看看某条"完成状态/完成时间" | 表格有 25 列且很多宽列,第一屏只看到前 10 列左右,**"完成状态"(第 24 列)在很右边,要一直往右拖才看得到**;"操作"列固定在最右始终可见,反而容易让人以为就这些列 | 每看一条都要大量横向滚动才能看到关键状态,效率低 | 1920×1080 视口 DOM 实测:表格 `.ant-table-content` 总宽 **3848px**、可视区仅 **1680px**(`qa-tmp/bqtakepulse/scripts/probe_1920_log.json`;截图 `66_list_1920_viewport.png`、`66_list_1920_full.png`);列配置 25 列、`完成状态` 为第 24 列未固定(`BgTakepulse.data.ts:8-160`);vision 复核截图确认视口内约 10 列、右端为固定"操作"列 | 表格列配置 `BgTakepulse.data.ts`("完成状态"第 24 列,未固定;"操作"为固定右列) | +| 5 | 搜不到想找的记录 | 空结果显示一张空表 + "暂无数据",**没有"没有匹配数据,去清除筛选"之类的引导**,用户得自己去找上方的"重置" | 轻度困惑,新手可能以为数据丢了 | 实测搜索不存在关键词显示"暂无数据"(`qa-tmp/bqtakepulse/screenshots/06_empty_search.png`) | 列表空态(`BgTakepulseList.vue` 未配置空态引导文案) | +| 6 | 删除一条记录 | 删除有二次确认(好),但确认框只写"是否确认删除",**没说删的是哪条、也没提示删除是否可恢复**;且对正在督办中的记录同样允许删 | 误删后无法撤销,确认信息不足以让用户做出正确判断 | 实测删除 popconfirm 文案 `是否确认删除`(`qa-tmp/bqtakepulse/screenshots/64_delete_popconfirm.png`);代码推断:删除接口不校验 `bpmStatus`,督办中记录也可删(**代码推断,待实测**,未对真实督办中记录执行删除以免破坏数据) | 删除 popconfirm(`BgTakepulse.api.ts:65-69` 的 `deleteOne`) | + +## 用户会觉得顺的地方 +- **顶部统计标签很直观**:未开始 / 督办中(已逾期 n)/ 已完成 一眼看清整体进度,用户不用数表格就能知道大概情况。 +- **空表单提交的校验提示具体、标红**:"请选择年份 / 请选择密级 / 请输入意见主题 / 请选择牵头部门",指哪错哪,比笼统的"请检查必填项"好很多。 +- **搜索顺手**:意见主题输入框支持回车即查、提示了"支持模糊查询";四个筛选条件(主题/分管所领导/牵头部门/协办部门)+ 查询/重置,够用。 +- **点标题看详情**符合直觉;**行内展开看"办理情况"**并带状态统计标签(未开始/进行中/已完成 + 共 N 条),信息组织清晰。 +- **下载模板可用**(实测下载"把把脉-导入模板.xls"成功)。 +- **删除有二次确认**,不会一点就没了。 +- 行按完成状态着色(黄/红/绿),状态一眼区分(注:实测配色为浅粉彩,单行浅红 #fff1f0 与白行区分度中等,快速扫视可能忽略);"操作"列固定在最右始终可见。 + +## 12 维度核对结果汇总 +| # | 维度 | 通过 | 问题(简写+证据位置) | +|---|------|------|----------------------| +| 1 | 目标达成 | 部分 | 搜索/详情/查流程/下载模板可用;**导出失败无果**(P1-1);新建成功保存链路未能完整实测(见"待实测") | +| 2 | 可发现性 | 通过 | 新增/导出/下载模板/模板校验/模板导入/高级查询都在表头一眼可见;行操作在"更多"下拉 | +| 3 | 可学习性 | 问题 | 牵头部门必填无星标(P1-2);部门树缩写看不懂(P2-3);所办领导显示编码(P2-2) | +| 4 | 效率 | 问题 | 25 列超宽表大量横向滚动(P2-4);新建需填 4 项必填 | +| 5 | 认知负荷 | 问题 | 25 列同屏信息过载;统计标签+工具栏+查询区较满 | +| 6 | 文案清晰度 | 部分 | 校验文案具体;但所办领导编码/部门缩写看不懂(P2-2/3);删除确认文案笼统(P2-6) | +| 7 | 反馈及时性 | 问题 | 导出静默失败无任何提示(P1-1);保存成功是否有提示未实测(见"待实测") | +| 8 | 误操作防护 | 部分 | 删除有确认;但确认信息不点明记录与后果(P2-6);督办中记录删除未做防护(代码推断,待实测) | +| 9 | 空态/加载/错误态 | 部分 | 空搜索"暂无数据"但无清除筛选引导(P2-5);导出失败无错误态(P1-1) | +| 10 | 无障碍细节 | 待实测 | 未用键盘走查关键流程;长文本在宽列内正常换行未发现撑爆 | +| 11 | 视觉一致性 | 通过 | 与平台其他页面(jeecg 风格)一致;行状态配色、操作列固定均正常 | +| 12 | 边界场景 | 部分 | 空表单校验友好;超长文本/特殊字符/快速连点等未专项实测(见"待实测") | + +## 用户任务走查记录 +- **任务 1:搜索/筛选台账记录** → 登录后进列表,用"意见主题"输入框模糊查 `assac` 命中 1 条;查不存在的词显示"暂无数据";点"重置"恢复全量。各步截图 `01_login → 05_search_assac → 06_empty_search → 07_after_reset`。**顺畅**。 +- **任务 2:查看详情 / 展开办理情况** → 点意见主题标题打开"详情"弹窗(只读);同时行被连带展开出现"办理情况"区(P2-1)。显式点展开图标也能看到反馈表(该记录暂无反馈数据)。截图 `08_detail_modal`、`12_expand_feedback`、`15_title_click_expand`。**基本顺畅,有 1 处多余展开**。 +- **任务 3:新建一条意见记录** → 点"新增"打开表单;空表单点"确 认"被 4 项校验拦下(报错明确、标红字段清晰,见 P2 维度);依次填年份/密级/意见主题并尝试选牵头部门。**自动化未能驱动"部门选择"弹窗把值写回表单(多次尝试未果,属测试手段限制,非用户侧证据)**,因此"成功保存"这一步未实测到;牵头部门必填但无星标为实测发现(P1-2)。截图 `16_new_modal`、`17_validation_empty`、`41_secret_dropdown`、`50_dept_picker`。 +- **任务 4:查询/发起督办流程** → 在"更多"下拉见"详情/删除/查询督办流程/再次督办"(该记录为督办中,故显示"再次督办"而非"发起督办流程",符合业务);"查询督办流程"打开流程列表(含流程图/审批历史等);"再次督办"打开流程发起弹窗(标题正确、字段齐全,但"所办领导"显示编码——P2-2)。全部只打开未提交,无数据变更。截图 `57_dropdown_assac`、`58_query_process`、`59_process_modal`。**顺畅**。 +- **任务 5:导出 / 下载模板 / 删除确认** → "下载模板"成功下载 xls;"导出"点击后无文件下载、无任何提示,后端 `exportXls` 返回 500(P1-1,实测 2 次);删除弹 popconfirm"是否确认删除"后取消(未删真实数据)。截图 `61_after_template`、`63_after_export2`、`65_after_export_final`、`64_delete_popconfirm`。 + +## 待实测 / 代码推断(未进 P0/P1/P2 分级) +以下项因**无法在本次实测中完成**,按纪律只列在待实测区,不参与级别判定: + +1. **新建记录的"成功保存"全链路**:自动化无法驱动"部门选择"弹窗将选择值写回表单,导致表单始终缺"牵头部门"而被校验拦截,未能实测到"保存成功→列表新增→成功反馈"。从代码看保存逻辑(`BgTakepulseModal.handleSubmit → submitForm → saveOrUpdate`)完整,**无证据表明真实用户无法创建记录**,需人工或换一种自动化方式实测确认(包括保存成功后是否有"保存成功"提示——代码中 `submitSuccess` 仅关闭弹窗,未见显式 toast,待实测)。 +2. **删除正在督办中(有运行中流程)的记录**:代码中 `deleteOne` 不校验 `bpmStatus`,理论上可直接删掉有流程的记录(可能造成流程与台账脱节)。因会破坏真实数据,**未实测**,仅代码推断(`BgTakepulse.api.ts:65-69`)。 +3. **导出失败的根因归属**:实测页面"导出"触发后端 `exportXls` 返回 **HTTP 500**(复现 2 次)。这是后端异常;前端未把失败反馈给用户。属后端问题还是环境问题需后端确认,用户侧影响已按 P1-1 记录。 +4. **键盘走查 / 特殊字符 / 超长文本 / 快速连点** 等边界场景未专项实测。 +5. **测试数据卫生**:本次尝试创建 `QA_UX_PULSE_*` 记录均未成功(未发送任何新增请求),**无 QA_UX 残留**;实测前后台账记录数均为 1(`assac`),已确认无污染。 diff --git a/qa-report/fixcontact/QA_REPORT_UX.md b/qa-report/fixcontact/QA_REPORT_UX.md new file mode 100644 index 0000000..8de00e6 --- /dev/null +++ b/qa-report/fixcontact/QA_REPORT_UX.md @@ -0,0 +1,118 @@ +# 前端页面用户视角审查报告 — 定点联系单列表页(fixcontact) + +## 审查信息 +- 页面/路由:`/bg/fixcontact/FixedContact20260730List`(定点联系单列表页) +- 审查日期:2026-08-11 +- 审查视角:业务用户(督办工作人员,兼顾首次使用新手) +- 相关文件: + - 视图:`src/views/bg/fixcontact/FixedContact20260730List.vue` + - 表单:`src/views/bg/fixcontact/components/FixedContact20260730Form.vue` + - 发起流程弹窗:`src/components/semri/process/FlowScheduleStartModalForBG.vue` + - API:`src/views/bg/fixcontact/FixedContact20260730.api.ts`、`src/api/common/api.ts` +- 实测环境:前端 dev 127.0.0.1:3100,后端代理 8080,账号 `admin/123456`(登录走 mock) +- 测试数据卫生:全程使用 `QA_UX_` 前缀建数并实测,测后已清理(最终 QA_UX 残留 0 条)。发起流程路径为「已建数实测并清理」。 +- 证据目录:`qa-tmp/fixcontact/`(`screenshots/` 下 26 张截图 + `diag_flow.json` 后端响应原文) + +## 总体结论 +- **P0 × 1 | P1 × 1 | P2 × 6** +- 一句话总结:查询、查看详情、新建这些日常操作用户都能顺畅走通,但**页面最关键的动作"发起流程"实测必然失败且只给出"请稍后重试"这类毫无原因的错误提示**,督办工作会卡死在这里;此外新建记录被强制要求填一条尚未发生的"领导审批意见",逼用户编造数据。 + +--- + +## P0 - 用户办不成事 / 会出错 + +| # | 用户场景 | 用户会遇到什么 | 后果 | 证据 | 位置 | +|---|---------|--------------|------|------|------| +| 1 | 对一条"未开始"记录发起督办流程 | 点"流程操作 → 发起流程",弹窗已自动填好督办标题/被督办部门/截止时间,用户只需点"提交";点下去却先后弹出两条错误"立即发起流程失败"、"发起流程失败,请稍后重试",页面上没有任何"哪里错了、该怎么改"的信息,原样重试依然失败 | 督办流程发起不了,督办工作在这里卡死;用户无法判断是自己填错还是系统故障,也没有任何下一步指引,只能干着急/找技术,且连续两条同义错误提示让用户困惑 | 截图 `screenshots/15_flow_modal.png` `16_flow_filled.png` `17_flow_submitted.png`;toast 原文"立即发起流程失败""发起流程失败,请稍后重试";后端响应 `{"success":false,"code":500,"message":"立即发起流程失败"}`(见 `diag_flow.json` 中 flow-schedules 响应体,HTTP 200 但业务码 500)。已建数实测并清理 | 前端失败分支:`FixedContact20260730List.vue` `handleFlowScheduleConfirm` 的 catch `createMessage.error('发起流程失败,请稍后重试')`;后端 `/tasktask/taskTask/flow-schedules` 返回 500。根因待后端确认(疑为测试库未部署 `fix_contact` 流程定义,部署脚本在 `deploy-pack/.../03_flow/*.sql`、flyway `v380/*.sql`) | + +--- + +## P1 - 明显受阻 / 容易困惑 + +| # | 用户场景 | 用户会遇到什么 | 后果 | 证据 | 位置 | +|---|---------|--------------|------|------|------| +| 1 | 新增一条定点联系单 | 新建记录被强制要求填写"定点联系所领导审批意见",但记录才刚创建、领导还没有来联系/审批过,用户根本无从得知意见内容;这一栏不填就保存不了 | 用户只能随便编一段审批意见才能保存,编造内容会进入正式台账,后续审批和台账数据因此失真;用户被迫"无中生有" | 截图 `screenshots/10_add_filled_no_leader_opinion.png` `11_add_submit_no_leader_opinion.png`;实测:填完其余 11 个必填字段、仅留此字段为空提交 → 唯一校验错误"请输入定点联系所领导审批意见" | `FixedContact20260730Form.vue` `validatorRules.leaderOpinion: [{ required: true }]`。建议:新建阶段取消必填(或改为"选填/待领导意见"),把该校验移到审批环节 | + +--- + +## P2 - 体验细节 + +| # | 用户场景 | 用户会遇到什么 | 后果 | 证据 | 位置 | +|---|---------|--------------|------|------|------| +| 1 | 看统计标签 | 顶部"未开始 0 / 督办中 1(已逾期 0)/ 已完成 0"看着像可点击的数字卡片,用户点了"未开始"标签却毫无反应,列表也不变化 | 用户以为能点击过滤到对应状态的记录,实际只是纯展示,产生"点了没反应"的困惑 | 实测:点击"未开始"标签后列表仍 1 行,无任何筛选/跳转(`screenshots/07_stats_tag_click.png`) | `FixedContact20260730List.vue` `#tableTitle` 内 `` 纯展示,未绑定点击。建议改为可点击并按状态过滤 | +| 2 | 搜索无结果 | 搜索不存在的编号后,表格区域只显示"暂无数据"四个字,没有"去新建一条""清除筛选"之类的引导入口 | 新手用户看到空表会以为系统坏了或自己操作错,不知道怎么继续 | 实测:搜索 `ZZZZ_NOTHING_999` → 仅"暂无数据"(`screenshots/20_empty_state.png`) | BasicTable 默认空态,未自定义引导文案/动作 | +| 3 | 看列表行颜色 | 列表行用黄/红/绿背景区分状态(未开始/督办中/已完成),但页面上没有任何图例说明颜色含义 | 用户只能靠猜"黄行是啥意思";对色弱用户更不友好;且配色为浅粉彩(实测单行浅红 #fff1f0 与白行区分度中等),快速扫视可能忽略 | 实测:新建的未开始记录行是黄色、原督办中记录行是红色(`screenshots/02_list.png` `14_row_in_list.png`),页面无图例;vision 复核 `02_list.png`:单行浅红可辨识但不够醒目 | `FixedContact20260730List.vue` `.status-row-1/2/3` 样式 | +| 4 | 发起流程弹窗填责任部门 | 字段标签写的是"被督办部门",但清空后提交,提示语却写成"请选择责任部门",同一个对象两个叫法 | 用户会疑惑"责任部门"和"被督办部门"是不是同一个东西,影响理解 | 实测:清空"被督办部门"提交 → toast"请选择责任部门"(`screenshots/25_flow_dept_empty_submit.png`) | `FlowScheduleStartModalForBG.vue` 字段 label"被督办部门" vs `handleOk` 中 `createMessage.warning('请选择责任部门')` | +| 5 | 新建 vs 发起流程填"是否所办领导审批" | 同一个问题"是否所办领导审批",在新建表单里是单选按钮(是/否),在发起流程弹窗里是开关(switch),两种页面两种控件 | 同一业务字段控件不统一,用户在两处要重新适应 | 实测:新建表单为单选(`screenshots/08_add_open.png`),发起流程弹窗为开关(`screenshots/15_flow_modal.png`) | 表单 `FixedContact20260730Form.vue`(radio)vs `FlowScheduleStartModalForBG.vue`(j-switch) | +| 6 | 新建一条记录 | 创建一条记录要填 12 个必填字段(序号、编号、所领导、联系单位、联系时间、座谈地点、诉求摘要、领导审批意见、分管批示、分管领导、申请人、主办部门),几乎全无默认值,几个还要逐个弹窗选人/选部门 | 创建成本高、耗时长,用户容易在中途放弃或填错;尤其"领导审批意见"在创建时根本不具备内容(见 P1-1) | 实测:空表单直接提交列出 12 条必填校验(`screenshots/09_add_empty_submit.png`) | `FixedContact20260730Form.vue` `validatorRules`(12 个 required) | + +--- + +## 用户会觉得顺的地方 + +- 顶部统计标签"未开始 / 督办中(含已逾期)/ 已完成"数量一眼可见,且实测随搜索条件联动(搜索"new"后统计仍为"督办中 1",与命中记录一致)。 +- 行背景黄/红/绿区分三种状态,视觉上能快速扫出哪些单还没办(缺图例是 P2;实测配色为浅粉彩、单行时区分度中等,见 P2-3)。 +- "表单编号"支持模糊查询,鼠标悬停有 tooltip 说明"支持模糊查询"。 +- 发起流程弹窗默认值给得贴心:督办标题自动带出表单编号、被督办部门自动带出主办部门、截止时间自动带出联系时间,用户基本只需点"提交"(可惜提交后端失败)。 +- 新建表单校验提示都写成"请输入X/请选择X",能直接定位到字段,并且校验后自动滚动到第一个错误字段,不靠猜。 +- 点"表单编号"列可直接查看详情(有 tooltip 提示),删除/批量删除/删除关联流程都有二次确认,不容易误删。 +- 操作列固定在最右侧(fixed right),横向滚动时流程/表单操作按钮始终可见。 + +--- + +## 12 维度核对结果汇总 + +| # | 维度 | 通过 | 问题(简写+证据位置) | +|---|------|------|----------------------| +| 1 | 目标达成 | 部分 | 搜索/详情/新建可完成;核心任务"发起流程"实测必失败且无指引 → **P0-1** | +| 2 | 可发现性 | 通过 | 新增/查询/重置/导出/下载模板/流程操作/表单操作均在一屏可见;表单编号点击看详情有 tooltip | +| 3 | 可学习性 | 问题 | 字段标签+占位符自解释;但"定点联系所领导审批意见"必填与新建时机冲突,用户无从知道填什么 → **P1-1** | +| 4 | 效率 | 问题 | 新建 12 必填项重 → **P2-6**;统计标签不能点击过滤 → **P2-1** | +| 5 | 认知负荷 | 问题 | 12 列表格需横向滚动、创建字段多;行色无图例 → **P2-3** | +| 6 | 文案清晰度 | 问题 | 新建校验消息清晰;但"请选择责任部门"与"被督办部门"叫法不一致 → **P2-4**;发起流程失败无原因 → **P0-1** | +| 7 | 反馈及时性 | 问题 | 新建成功有"添加成功!"且列表刷新(好);发起流程失败连弹两条同义错误、无下一步 → **P0-1** | +| 8 | 误操作防护 | 通过 | 删除/批量删除/删除关联流程均有二次确认;前端提交前校验并滚动定位 | +| 9 | 空态/加载/错误态 | 问题 | 空态仅"暂无数据"无引导 → **P2-2**;失败态无指引 → **P0-1** | +| 10 | 无障碍细节 | 待实测 | 表格长文本 pre-wrap 换行合理;行色标无图例对色弱不友好 → **P2-3**;键盘/焦点/对比度未逐项实测;行背景色已 vision+DOM 复核(见 P2-3) | +| 11 | 视觉一致性 | 问题 | 同一字段"是否所办领导审批"在新建表单是单选、在发起弹窗是开关 → **P2-5**;其余与平台风格一致 | +| 12 | 边界场景 | 部分/待实测 | 搜索无结果时统计归零由代码联动(实测命中时统计一致);连点提交/刷新丢状态/超长文本未逐项实测 → 待实测 | + +--- + +## 用户任务走查记录 + +- **任务 1:搜索一条记录(搜索 + 重置)** + 1. 登录(`01_login.png`)→ 进入列表(`02_list.png`)。 + 2. 在"表单编号"输入框填入已知编号 `new`,自动触发(防抖)查询,再点"查询"按钮:列表剩 1 行命中(`04_search.png`),顶部统计同步仍显示"督办中 1"。 + 3. 点"重置":列表恢复全部数据(`05_reset.png`)。 + 4. 感受:顺畅。输入即查、统计联动,体验好;唯一小遗憾是"暂无数据"无引导(见 P2-2)。 + +- **任务 2:查看详情** + 1. 点第一条记录的"表单编号"链接 → 弹出"详情"弹窗(`06_detail.png`),字段均只读展示。 + 2. 关闭弹窗正常。 + 3. 感受:顺畅,字段完整。 + +- **任务 3:看统计标签(未开始/督办中/已完成)** + 1. 顶部显示"未开始 0 / 督办中 1(已逾期 0)/ 已完成 0"(`03_stats.png`),数字随搜索联动。 + 2. 点"未开始"标签 → 无任何反应(`07_stats_tag_click.png`)。 + 3. 感受:数量展示有用,但标签"点了没反应"让人困惑(见 P2-1);行背景色的状态含义没有图例说明(见 P2-3)。 + +- **任务 4:发起流程(核心任务,已建数实测并清理)** + 1. 当前库里没有"未开始"记录 → 用 `QA_UX_` 前缀通过"新增"表单建一条(`12_add_filled_complete.png`),提交"添加成功!"后在列表出现,行背景黄色 = 未开始(`14_row_in_list.png`)。 + 2. 对该行点"流程操作 → 发起流程",弹窗已自动带好督办标题/被督办部门/截止时间(`15_flow_modal.png` `16_flow_filled.png`)。 + 3. 点"提交" → 先后弹出"立即发起流程失败"、"发起流程失败,请稍后重试"(`17_flow_submitted.png`),后端返回 500(`diag_flow.json`)。重试同样失败。 + 4. 感受:**这里卡住了**。默认值很贴心,但提交失败没有任何原因和下一步,督办工作无法推进(见 **P0-1**)。已建数实测并清理(最终 QA_UX 残留 0)。 + +- **任务 5:新增一条记录 + 表单校验实测** + 1. 点"新增",先直接提交空表单:弹出 12 条必填校验,逐条清楚(`08_add_open.png` `09_add_empty_submit.png`)。 + 2. 填完其余 11 个必填字段、故意不填"定点联系所领导审批意见"提交:唯一校验错误"请输入定点联系所领导审批意见"(`10_add_filled_no_leader_opinion.png` `11_add_submit_no_leader_opinion.png`)——**确认"领导审批意见必填"是真的**,而该字段在新建时本无内容可填(见 **P1-1**)。 + 3. 补填该字段后提交:toast"添加成功!",弹窗关闭,列表出现新记录(`13_add_submitted.png`)。 + 4. 感受:校验信息清楚、能定位字段,体验好;但 12 个必填项 + 一个语义上不该必填的"领导审批意见",让新建变得又重又别扭(见 **P1-1**、**P2-6**)。 + +--- + +## 待实测 / 代码推断清单(不进 P1/P0) + +- **发起流程失败根因**:后端 `/tasktask/taskTask/flow-schedules` 返回业务码 500(消息"立即发起流程失败")。是否因测试库未部署 `fix_contact` 流程定义导致(部署 SQL 见 `deploy-pack/.../03_flow/*.sql`、flyway `v380/*.sql`),需后端/环境确认后,才能判断是环境问题还是生产也会出现的缺陷。**用户侧事实(P0-1)不受此影响:失败且无任何指引。** +- 无障碍细节(键盘 Tab/回车/Esc 走完核心流程、焦点可见性、文字对比度/字号)未逐项实测。行背景色已 vision+DOM 复核(单行浅红可辨识但不够醒目,见 P2-3),其余对比度细节待人工复核。 +- 边界场景(快速连点提交、切换筛选后返回、中途刷新丢未保存内容、超长文本输入)未逐项实测。 diff --git a/qa-report/inspectTask/QA_REPORT.md b/qa-report/inspectTask/QA_REPORT.md new file mode 100644 index 0000000..ea4a7db --- /dev/null +++ b/qa-report/inspectTask/QA_REPORT.md @@ -0,0 +1,107 @@ +# 前端页面审查报告 — 巡视整改提升工作台账(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`(`` 仅 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 命中 fullscreen,after_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#9,vision+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 ``(**本页相关,P2#7**) + +### 关键网络请求(方法/URL/状态码) +- `POST /sys/login` → 200(mock) +- `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` → 200(measureResLeader=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 个 `` 子句,与 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_ 残留,无残留入库。* diff --git a/qa-report/inspectTask/QA_REPORT_UX.md b/qa-report/inspectTask/QA_REPORT_UX.md new file mode 100644 index 0000000..1279e3b --- /dev/null +++ b/qa-report/inspectTask/QA_REPORT_UX.md @@ -0,0 +1,99 @@ +# 前端页面用户视角审查报告 — 巡视整改台账(DqInspectTaskList) + +## 审查信息 +- 页面/路由:`/dq/inspectTask/DqInspectTaskList`(巡视整改提升工作台账) +- 审查日期:2026-08-11 +- 审查视角:业务用户(兼顾新手) +- 相关文件: + - `src/views/dq/inspectTask/DqInspectTaskList.vue` + - `src/views/dq/inspectTask/DqInspectTaskForm.vue`、`DqInspectTaskModal.vue`、`DqInspectTask.data.ts`、`DqInspectTask.api.ts` + - `src/components/Modal/src/BasicModal.vue`、`components/ModalClose.vue` +- 测试账号:admin(mock 登录,其余接口走真实后端 8080) +- 证据目录:`qa-tmp/inspectTask/`(截图 `screenshots/`、网络/模态记录 `artifacts/`) + +## 总体结论 +- **P0 × 0 | P1 × 3 | P2 × 5** +- 一句话总结:核心任务(搜索/筛选/看详情/查流程/看反馈/校验新增)都能走通,页面整体可用;但"措施责任领导"在列表和详情里都看不到真实负责人(列表显示部门名、详情显示占位符),加上流程操作不随任务状态变化、督办中的任务也能误点"发起/销号",是用户最容易踩坑的两个点。 + +--- + +## P0 - 用户办不成事 / 会出错 +| # | 用户场景 | 用户会遇到什么 | 后果 | 证据 | 位置 | +|---|---------|--------------|------|------|------| +|(无 P0 发现)| | | | | | + +--- + +## P1 - 明显受阻 / 容易困惑 +| # | 用户场景 | 用户会遇到什么 | 后果 | 证据 | 位置 | +|---|---------|--------------|------|------|------| +| 1 | 业务人员在台账里想确认"这项措施到底谁负责" | 列表"措施责任领导"一列显示的是部门名"DD",和"措施责任部门"列完全一样,看不到真正的责任领导 | 用户无法从列表确认责任人,只能逐条点开看,甚至可能找错人督办 | `artifacts/row_html.html`(第8、9两列 `title="DD"` 值相同);`DqInspectTask.data.ts:256-258` 该列 `dataIndex` 误绑 `measureResDept_dictText` | `DqInspectTask.data.ts` ledgerColumns「措施责任领导」列 | +| 2 | 打开一条记录的"详情",想确认责任领导 | "措施责任领导"字段显示的是占位符文字"请选择措施责任领导",而不是领导姓名 | 用户误以为这条没填领导、看不到到底是谁;与后端已赋值 `measureResLeader=dd_ld_02` 不一致,信息误导 | `artifacts/probe_detail_values.json`(selects.measureResLeader=「请选择措施责任领导」);`artifacts/probe_querybyid.json`(result.measureResLeader=`dd_ld_02`);截图 `60_detail_values.png` | `DqInspectTaskForm.vue` 详情只读模式(`DeptRoleUserSelectDropDown` 渲染占位符) | +| 3 | 一条任务已经是"督办中",用户看它的"流程操作"下拉 | 下拉仍同时提供"发起巡视整改流程"和"发起销号流程",点进去能打开发起弹窗 | 用户可能误以为流程还没发起而重复发起,或对整改中的任务误点"发起销号流程",产生重复/错误的流程实例 | `artifacts/task2_detail.json`(flow_menu_items 三项全显示);`artifacts/probe_final.json`(督办中记录也能打开发起销号流程弹窗);截图 `50_t3_flow_start_modal.png`、`60_t3_suo_flow_modal.png` | `DqInspectTaskList.vue:getFlowMenuList`(388-421 行,按状态显示菜单的条件判断被注释掉) | + +--- + +## P2 - 体验细节 +| # | 用户场景 | 用户会遇到什么 | 后果 | 证据 | 位置 | +|---|---------|--------------|------|------|------| +| 4 | 用"督办状态=已完成"筛选后一条都没有 | 表格只有一张默认空图 + "暂无数据",没有"清除筛选"或"去新建"的引导 | 用户不确定是没数据还是自己筛错了,新手容易卡住 | `artifacts/empty_state_html.html`(`ant-empty-description` 仅"暂无数据");截图 `17_t1b_filter_done.png`、`12_t1_search_noresult.png` | 列表空态(BasicTable 默认 empty) | +| 5 | 点"发起整改任务流程 / 发起销号流程",到了发起弹窗 | "发起类型"给"立即发起 / 重复发起"两个选项,页面没有任何说明两者区别、什么时候该选"重复发起" | 业务用户凭感觉选,可能选错 | `artifacts/flow_start_modal.txt`、`artifacts/suo_flow_modal.txt`;截图 `50_t3_flow_start_modal.png` | `DqInspectTaskFlowScheduleStartModal.vue` | +| 6 | 想点弹窗右上角的 X 关闭 | 关闭按钮区域(86×34px)里紧挨着一个 36px 的全屏图标,点中间会触发"全屏放大"而不是关闭;真正能关闭的 X 只有最右侧约 26×36px 的一小块 | 用户想关弹窗结果被放大成全屏,一脸懵;关闭目标过小、紧挨全屏按钮易误触 | `artifacts/probe_x_realmouse.json`(关闭区中心命中 `anticon-fullscreen`,未关闭);`artifacts/probe_x_glyph.json`(仅 `aria=close` 的 26×36 图标点击后关闭) | `components/ModalClose.vue` + `BasicModal.vue:handleCancel`(`-close--custom` 区域被过滤) | +| 7 | 删除一条任务 / 批量删除 | 确认文案是笼统的"是否确认删除 / 是否删除选中数据" | 用户不清楚删除会不会连带删掉已关联的反馈记录或流程,心里没底、不敢点 | `artifacts/delete_popconfirm.txt`;截图 `61_t8_delete_confirm.png` | `DqInspectTaskList.vue:getFormMenuList` 删除 popConfirm、`DqInspectTask.api.ts:batchDelete` | +| 8 | 用"高级查询"构造条件 | 字段列表里出现"具体问题ID""流程实例ID""措施数量"等技术化字段名 | 业务用户不知道"具体问题ID"是什么、怎么填,高级查询门槛偏高 | `artifacts/superquery_modal.txt`(仅能进构造器,字段在下拉);`DqInspectTask.data.ts` superQuerySchema(多个 title 带 `ID` 后缀) | `DqInspectTask.data.ts` superQuerySchema | +| 9 | 想靠行底色快速区分"这条是未开始/督办中/已完成" | 行底色是**极浅粉彩**(督办中 `#fff1f0`,接近白色),和普通白行几乎没区别,肉眼扫不出状态 | 状态色的辨识价值没发挥,用户还是得看列内容/统计标签才知道状态;对色弱用户更不可用 | vision 复核截图 `04_list.png` 判定"行未着色"(浅到看不出,反而说明问题);DOM 实测 `qa-tmp/rowcolors_probe.json`:行 class=`status-row-2`、td 背景 `rgb(255,241,240)`;CSS `DqInspectTaskList.vue:646-648`(`#fff1f0`) | 表格行 `rowClassName` + `DqInspectTaskList.vue:643-651` | + +--- + +## 用户会觉得顺的地方 +- 顶部查询区只有 4 个条件 + 查询/重置按钮,一眼能看懂;搜索、按督办状态筛选、重置都即时生效,状态统计标签(未开始/督办中(已逾期)/已完成)跟着筛选刷新,直观。 +- 流程操作 / 表单操作都收敛在下拉菜单里,功能集中不占行宽。 +- 表单空提交会一次性列出 7 条明确的必填校验提示("请选择具体问题/请选择密级/请输入整改措施…"),用户能明确知道缺哪些。 +- 删除(含批量)都有二次确认,不会误删。 +- "查询督办流程"能弹出流程列表,并给"审批历史 / 流程图 / 查询当前办理人"等查看入口,用户可以自己查进度。 +- 详情弹窗字段齐全(除责任领导字段外),整改措施/完成时限等都能回显。 + +--- + +## 12 维度核对结果汇总 + +| # | 维度 | 通过 | 问题(简写+证据位置) | +|---|------|------|----------------------| +| 1 | 目标达成 | 部分通过 | 核心任务均可走通;但"确认责任领导"子目标被列表/详情字段显示错误挡住(P1#1、P1#2) | +| 2 | 可发现性 | 通过 | 新增/导出/导入/下载模板/模板校验/模板导入/流程/表单操作均在显眼处;批量操作需先勾选出现,属合理交互 | +| 3 | 可学习性 | 问题 | "重复发起"无解释(P2#5);高级查询字段名技术化(P2#8) | +| 4 | 效率 | 通过 | 查询/重置顺手,状态标签免点击一眼看全局 | +| 5 | 认知负荷 | 部分通过 | 台账列多达 17 列需横向滚动,但合并单元格(问题分类/面上/具体问题)帮助读行;未到"吓人"程度 | +| 6 | 文案清晰度 | 问题 | 详情里"请选择措施责任领导"占位符当值显示(P1#2);删除确认文案笼统(P2#7) | +| 7 | 反馈及时性 | 通过 | 成功/失败有 toast;表单校验即时;状态统计随操作刷新(已实测) | +| 8 | 误操作防护 | 部分通过 | 删除有确认;但流程操作不随状态隐藏、督办中也能发起/销号(P1#3);关闭按钮易误触全屏(P2#6) | +| 9 | 空态/加载/错误态 | 问题 | 空态无引导、无清除筛选出口(P2#4);加载态/后端错误态未实测 → 待实测 | +| 10 | 无障碍细节 | 部分通过 | Escape 可关弹窗(已实测);Tab 顺序、对比度、小按钮可点性未实测 → 待实测;关闭按钮偏小(P2#6) | +| 11 | 视觉一致性 | 问题 | antd 组件统一;但督办状态行底色为极浅粉彩(#fff1f0 近白),肉眼辨识度低(P2#9,vision+DOM 复核) | +| 12 | 边界场景 | 部分通过 | 筛选-重置-筛选状态同步正常(已实测);特殊字符/超长文本/连点未实测 → 待实测 | + +--- + +## 用户任务走查记录 + +- **任务 1:搜索/筛选一条整改任务** → 整改措施输入"不存在的整改词"查询 → 0 条,空态"暂无数据"(无引导,P2#4);重置后恢复 1 条;按"督办状态=已完成"筛选 → 0 条;按"未开始"筛选 → 0 条。搜索/筛选/重置本身流畅。截图 `10-18`。 +- **任务 2:查看详情(含整改台账)** → 点击整改措施链接打开"详情"弹窗,整改措施/完成时限等均能回显;但"措施责任领导"显示占位符"请选择措施责任领导"(P1#2);列表该列显示部门名"DD"(P1#1)。截图 `24_t2_detail_modal.png`、`60_detail_values.png`。 +- **任务 3:流程操作(发起/查询流程)** → "流程操作"下拉三项全显示;点"查询督办流程"弹出流程列表(含审批历史/流程图入口),流程"wqdwqd"督办中可见;点"发起巡视整改流程 / 发起销号流程"能打开发起弹窗(发起类型无解释 P2#5);督办中任务也能发起/销号(P1#3)。截图 `22-23`、`50`、`60_t3_suo_flow_modal.png`。 +- **任务 4:整改反馈记录(查看办理情况)** → "表单操作→查看办理情况"弹出"反馈信息(共 0 条)",空数据;有 关闭/确认 按钮。截图 `51_t4_feedback.png`。 +- **任务 5:新增/编辑** → 点"新增"打开表单,空提交触发 7 条明确校验(友好);整改措施/密级/完成时限/具体问题可正常填写;措施责任部门/责任领导/分管所领导为多级树/角色用户选择,自动化填选受阻,未走通"完整提交成功"路径(未建数,无 QA_UX 残留)。截图 `41-42`、`54-59`。 + +--- + +## 待实测 / 代码推断(未列入 P1/P2 实锤) +| 项目 | 状态 | 说明 | +|------|------|------| +| 发起流程提交后是否真会创建重复流程 | 代码推断,待实测 | 已验证入口(督办中任务能打开发起弹窗);为避免污染真实流程数据,未点"提交"。风险推断基于菜单无条件显示 | +| 删除是否级联删除关联反馈记录/流程 | 代码推断,待实测 | 仅确认有二次确认弹窗;为保护现有数据未点"确定"。后端删除行为需工程师侧实测 | +| "措施责任领导"列根因 | 已 DOM+代码确认 | `DqInspectTask.data.ts:256-258` 列绑定 `measureResDept_dictText`(应为 `measureResLeader_dictText`),与 DOM 两列同值佐证一致 | +| 加载态 / 后端错误态 | 未实测 | 本次未模拟断网/慢接口 | +| 键盘 Tab 顺序 / 文字对比度 | 未实测 | 本次仅验证 Escape 关弹窗;行底色视觉已用 vision+DOM 复核并升级为 P2#9,其余对比度细节待人工复核 | +| 特殊字符 / 超长文本 / 快速连点 | 未实测 | 边界输入本次未覆盖 | + +--- + +*报告按用户视角分级(P0/P1/P2),证据均来自浏览器实测(截图/网络响应/模态文本),证据路径指向 `qa-tmp/inspectTask/`。测试过程中未创建任何 `QA_UX_` 数据,无残留。* diff --git a/qa-report/xispeak/QA_REPORT_UX.md b/qa-report/xispeak/QA_REPORT_UX.md new file mode 100644 index 0000000..c2dc17c --- /dev/null +++ b/qa-report/xispeak/QA_REPORT_UX.md @@ -0,0 +1,81 @@ +# 前端页面用户视角审查报告 — 重要指示批示台账(树形台账) + +## 审查信息 +- 页面/路由:`/bg/xispeak/BgXiSpeakList`(习总书记重要讲话指示批示情况台账,树形列表) +- 审查日期:2026-08-11 +- 审查视角:业务用户(督办工作人员,不懂技术;兼顾首次使用新手) +- 相关文件:`src/views/bg/xispeak/BgXiSpeakList.vue`、`BgXiSpeak.data.ts`、`BgXiSpeak.api.ts`、`components/BgXiSpeakForm.vue`、`components/FeedbackRightNowModal.vue`、`src/components/semri/process/FlowScheduleStartModal.vue` +- 测试账号:admin/123456(登录走 mock,其余接口真实后端 8080) +- 证据目录:`qa-tmp/xispeak/screenshots/`(截图)、`qa-tmp/xispeak/artifacts/ux_walk*_log_readable.txt`(过程记录) +- 视觉说明:视觉复核已用 claude-vision-skill 实读截图 + DOM 实测互补——可视区内容(行状态配色等)以 vision 实读为准,被横向滚动藏住的列以 DOM(scrollWidth vs clientWidth)为准 + +## 总体结论 +- P0 × 0 | P1 × 1 | P2 × 7 +- 一句话总结:核心任务(浏览树形台账、筛选、看统计、流程/表单操作)都能顺利办成,唯一的硬伤是发起"重复发起"流程时空周期字段会弹出**英文错误提示**(业务用户看不懂),其余为横向滚动、空态引导、表单必填项多等体验细节问题,页面整体可用。 + +## P0 - 用户办不成事 / 会出错 +| # | 用户场景 | 用户会遇到什么 | 后果 | 证据 | 位置 | +|---|---------|--------------|------|------|------| +| - | 无 | 实测核心任务全部可完成,未发现 P0 | - | - | - | + +## P1 - 明显受阻 / 容易困惑 +| # | 用户场景 | 用户会遇到什么 | 后果 | 证据 | 位置 | +|---|---------|--------------|------|------|------| +| 1 | 督办工作人员对某条记录选"流程操作 → 发起落实措施收集流程 → 确认发起 → 重复发起",不改"重复周期"直接点"发起流程" | 页面弹出一条**英文**提示 `Please select interval type`,业务人员完全看不懂,也不知道"哪个没填、怎么填" | 用户卡住、只能猜或找技术人员;同处还有 3 条英文提示(interval type / repeat count / start time) | 实测触发,截图 `qa-tmp/xispeak/screenshots/44_recurring_english_toast.png`;过程记录 `artifacts/ux_walk6_log_readable.txt`(`recurring_empty_toasts`) | `src/components/semri/process/FlowScheduleStartModal.vue:331,335,339`(`createMessage.warning('Please select interval type')` 等未翻译) | + +## P2 - 体验细节 +| # | 用户场景 | 用户会遇到什么 | 后果 | 证据 | 位置 | +|---|---------|--------------|------|------|------| +| 1 | 发起流程时连续弹出两个**标题一模一样**的弹窗 | 点"发起落实措施收集流程"先弹"选择反馈方式"(标题=发起落实措施收集流程),点"确认发起"后又弹一个"发起类型/流程参数"的弹窗(标题仍是发起落实措施收集流程) | 用户以为点错了/重复点击,不确定当前在第几步 | 实测两步弹窗标题均相同,截图 `41_step1_feedback_now.png`、`42_step2_flow_schedule.png`;`artifacts/ux_walk6_log_readable.txt`(step1/step2 modal_title) | `components/FeedbackRightNowModal.vue:13` 与 `src/components/semri/process/FlowScheduleStartModal.vue` 标题一致 | +| 2 | 看台账列表时只有 1200px 宽视口却铺了 16 列 | "督办状态""牵头部门""贯彻落实措施"等关键列在很靠右的位置,必须横向拖动才能看到;首屏只能看到讲话情况/批示情况/时间等几列 | 用户来回拖滚动条,容易漏看逾期/督办状态 | 实测 `table_hscroll = {scrollWidth:2280, clientWidth:1200, scrollable:true}`,列数 16,截图 `20_layout_metrics.png` | `BgXiSpeak.data.ts` columns(16 列含选择框/操作列) | +| 3 | 筛选/搜索后没有任何匹配数据 | 表格只剩一行"暂无数据",没有任何"清除筛选/重置条件"的引导按钮 | 新手不知道是条件填错还是真没数据,只能自己找"重置"按钮 | 实测空态仅文字"暂无数据",截图 `06_empty_search_result.png`;`artifacts/ux_walk_log_readable.txt`(`empty_state_text`) | `BgXiSpeakList.vue` 表格空态 | +| 4 | 点"新增"录入一条台账 | 弹出 1400px 宽的表单,15 个字段里 **12 个必填**,时间/日期/密级/责任领导/牵头部门都要选 | 首次录入负担重、填到一半容易放弃;占位符(如"来源于党委会抄告")对新人不解释来源 | 实测必填 12 项、错误提示 11 条,截图 `33_add_modal_open.png`、`34_add_empty_submit.png`;`artifacts/ux_walk6_log_readable.txt`(`add_modal_field_labels`/`add_empty_submit_errors_v2`) | `components/BgXiSpeakForm.vue`(rules,见 `BgXiSpeakForm.vue:198-210`) | +| 5 | 想查看某条记录的详情 | 第一列"习近平总书记重要讲话指示批示情况"是蓝色链接,但只有鼠标悬停才出现"点击查看详情"提示 | 新手不知道能点;误以为是表头标题 | 实测链接样式(蓝色 14px 加粗)`artifacts/ux_walk4_log_readable.txt`(`first_col_link_style`);tooltip 提示 | `BgXiSpeakList.vue:116-120` | +| 6 | 勾选多条后点"批量操作 → 删除" | 弹出"确认删除 / 是否删除所选记录",但**没有像单行删除那样提示会连带删除关联流程信息** | 用户以为只删台账记录,不知道关联流程数据也会被清理 | 实测批量确认弹窗正文仅"是否删除所选记录",截图 `51_batch_delete_modal.png`;对比单行删除提示见 `46_delete_popconfirm.png` | `BgXiSpeak.api.ts:68-73`(`batchDeleteBgXiSpeak` confirm 文案) | +| 7 | 看右上角统计标签"未开始 4 / 督办中 3(已逾期 3)/ 已完成 3" | 标签字号仅 12px,在右侧偏小,视力一般的用户要凑近看 | 关键督办压力信息不够醒目 | 实测 `stats_tag_style = {color:rgb(140,105,0), fs:12px}` | `BgXiSpeakList.vue:98-102` | + +## 用户会觉得顺的地方 +- **统计标签实时同步**:按"督办状态=督办中"筛选后,标签立即变为"未开始 0 / 督办中 3(已逾期 3)/ 已完成 0",搜索/重置同样同步(实测,`04_filter_bpm.png`)。 +- **表单必填校验提示友好**:空表单点"确认"一次性给出 11 条"请输入/请选择 ××"的明确提示,能定位到具体字段(实测,`40_add_empty_submit_v2.png`)。 +- **破坏性操作有防护**:单行删除有 popconfirm"确定删除吗? 将同时删除该记录关联的所有流程信息",批量删除有"确认删除/是否删除所选记录"(实测,`46_delete_popconfirm.png`、`51_batch_delete_modal.png`)。 +- **流程操作菜单按状态动态变化**:未开始记录显示"发起落实措施收集流程/发起经办人执行反馈流程/查询督办流程";督办中记录显示"再次发起经办人执行反馈流程/查询督办流程/删除关联流程",用户不会被无效操作误导(实测,`07_flow_dropdown.png`、`45_inprogress_flow_menu.png`)。 +- **树形台账浏览顺畅**:展开父节点能加载出子节点(5 行 → 7 行),第一列可点击查看详情(实测,`03_tree_expanded.png`、`32_detail_link_modal.png`)。 +- 全程无 console 报错(实测 `console_error_count=0`)。 + +## 12 维度核对结果汇总 +| # | 维度 | 通过 | 问题(简写+证据位置) | +|---|------|------|----------------------| +| 1 | 目标达成 | 通过 | 5 条核心任务(浏览/展开、筛选、统计、流程操作、表单操作)全部实测走通,无走不下去的路径 | +| 2 | 可发现性 | 问题 | 第一列查看详情入口仅 hover tooltip(P2-5);批量操作按钮需先勾选才出现(较隐蔽) | +| 3 | 可学习性 | 问题 | 两步弹窗同名易迷惑(P2-1);新增表单 12 必填对新手偏重(P2-4) | +| 4 | 效率 | 问题 | 16 列表格横向滚动看关键列(P2-2);必填项多、重复录入负担(P2-4) | +| 5 | 认知负荷 | 问题 | 同屏 16 列信息过载(P2-2);行状态配色可缓解(已 vision+DOM 复核:浅黄/浅红/浅绿相邻可区分) | +| 6 | 文案清晰度 | 问题 | 重复发起流程英文提示(P1-1);其余中文文案(校验/删除确认)清晰 | +| 7 | 反馈及时性 | 通过 | 统计标签随筛选/搜索/重置同步刷新;删除/发起有 message/popconfirm 反馈 | +| 8 | 误操作防护 | 通过 | 单行删除 + 批量删除均有确认;批量删除未提示关联流程(P2-6) | +| 9 | 空态/加载/错误态 | 问题 | 空搜索结果仅"暂无数据"无引导(P2-3);loading 状态存在 | +| 10 | 无障碍细节 | 待实测 | 键盘走查/焦点可见性未实测;统计标签 12px 偏小(P2-7) | +| 11 | 视觉一致性 | 通过 | 行状态配色(浅黄/浅红/浅绿)已 vision 复核 `02_list_overview.png` 五行三色相邻可区分;DOM `status-row-1/2/3` = #fffbe6/#fff1f0/#f6ffed;红绿对色弱用户区分度有限,已有统计标签/文字辅助 | +| 12 | 边界场景 | 通过 | 模糊搜索无结果正常显示空态、重置恢复、状态筛选联动正常(抽查) | + +## 用户任务走查记录 +- **任务 1:登录并进入台账** → `01_login.png` → `02_list_overview.png`,顺畅(登录后直达 `/bg/xispeak/BgXiSpeakList`)。 +- **任务 2:浏览树形台账并展开子节点** → 点击行首展开图标,5 行展开为 7 行,子节点加载正常 → `03_tree_expanded.png`,顺畅。 +- **任务 3:按督办状态筛选 + 看统计** → 选"督办中"→ 列表和右上角统计标签同步变为督办中 3 → `04_filter_bpm.png`,顺畅且反馈即时;重置 → `05_after_reset.png`。 +- **任务 4:关键词搜索到空结果** → 输入不存在关键词 → 仅"暂无数据",无引导 → `06_empty_search_result.png`,略困惑(P2-3)。 +- **任务 5:发起落实措施收集流程(核心)** → 流程操作下拉 → 选择反馈方式弹窗 → 确认发起 → 发起类型弹窗(两步同名)→ 选"重复发起"空提交弹英文提示 → `41/42/43/44_*.png`,英文提示卡住用户(P1-1)。 +- **任务 6:查看办理情况 / 详情** → 表单操作下拉 → 查看办理情况弹"反馈信息(共 0 条,已完成 0 条)" → `13_feedback_modal.png`;第一列点开详情弹"详情"只读 → `32_detail_link_modal.png`,顺畅。 +- **任务 7:新增(空表单校验)** → 新增 → 空提交 → 11 条"请输入/请选择"友好提示 → `40_add_empty_submit_v2.png`,顺畅但必填项偏多(P2-4)。 +- **任务 8:删除(单行/批量)** → 单行删除有 popconfirm 并提示连带流程 → `46_delete_popconfirm.png`;批量删除有确认弹窗但未提示关联流程 → `51_batch_delete_modal.png`。 +- **任务 9:高级查询** → 工具栏"高级查询"弹窗正常打开 → `50_super_query.png`,顺畅。 + +## 待实测 / 代码推断(不进入 P0/P1,需人工复核或后续验证) +- **行状态背景配色**(未开始=浅黄 #fffbe6、督办中=浅红 #fff1f0、已完成=浅绿 #f6ffed,`BgXiSpeakList.vue:996-1004`)已用 vision+DOM 复核确认(`02_list_overview.png` 五行三色相邻可区分),非代码推断。注意:本页全行着色所以可辨识;配色为浅粉彩,若仅单行着色时会接近白色、辨识度骤降(inspectTask 已单独记录为 P2#9)。 +- **批量删除是否连带物理删除关联流程数据**:前端确认文案未提及,后端 `deleteBatchBgXiSpeak` 行为未实测,仅记录文案不一致(P2-6)。 +- **键盘操作 / 焦点可见性 / Tab 顺序**:本次未做键盘走查,需人工补充。 +- **快速连点提交/翻页等并发边界**:本次未实测。 +- **新增表单完整保存链路的回显**:本次空表单校验实测通过;完整填数保存因弹窗/浮层交互复杂未重复走通(此前 8-7 的历史 crud 脚本 `qa-tmp/xispeak/probe_crud.py` 已覆盖该链路)。 + +## 测试数据卫生 +- 本次审查**未创建任何记录**(新增仅做空表单校验,未保存),无新增残留。 +- **发现既有残留**:台账中已有 4 条顶层 `QA_UX_` 前缀测试记录及其子节点(`QA_UX_树形主台账1-未开始`、`QA_UX_树形测试父节点X`、`QA_UX_督办中台账2-已逾期`、`QA_UX_已完成台账3`),为历史 QA 测试遗留,非本次产生,**未删除**(避免破坏既有测试数据),建议后续统一清理。证据:`artifacts/ux_walk7_log_readable.txt`(`rows_summary`)、`ux_walk5_log_readable.txt`(`qa_rows_all_cells`)。