docs(xispeak): 归档前端页面 QA 审查报告并忽略 qa-tmp 临时产物
- qa-report/xispeak/QA_REPORT.md 提交入库(P0×1 / P1×4 / P2×5) - .gitignore 忽略 qa-tmp/、__pycache__/、*.pyc,测试临时产物不入库 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -6,6 +6,11 @@ dist-electron
|
||||
.cache
|
||||
localDoc
|
||||
|
||||
# QA test temporary artifacts (scripts, screenshots, caches) — reports live in qa-report/ and are committed
|
||||
qa-tmp/
|
||||
__pycache__/
|
||||
*.pyc
|
||||
|
||||
tests/server/static
|
||||
tests/server/static/upload
|
||||
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
# 前端页面审查报告 — 习总书记重要讲话指示批示(xispeak)
|
||||
|
||||
## 审查信息
|
||||
- 页面/路由:`/bg/xispeak/bgXiSpeakList`(组件 `src/views/bg/xispeak/BgXiSpeakList.vue`)
|
||||
- 审查日期:2026-08-07
|
||||
- 审查方式:frontend-page-qa skill 四阶段流程(代码静态审查 + Playwright 浏览器实测 + checklist 系统化走查)
|
||||
- 环境:dev 端口 3100(mock 开启),后端 `http://localhost:8080/jeecg-boot`,账号 admin/123456
|
||||
- 相关文件:
|
||||
- `src/views/bg/xispeak/BgXiSpeakList.vue`(树形列表 + 查询 + 流程操作)
|
||||
- `src/views/bg/xispeak/BgXiSpeak.data.ts`(列定义 + 高级查询)
|
||||
- `src/views/bg/xispeak/BgXiSpeak.api.ts`(接口层)
|
||||
- `src/views/bg/xispeak/components/BgXiSpeakForm.vue`(新增/编辑表单)
|
||||
- `src/views/bg/xispeak/components/BgXiSpeakFeedbackForm.vue`(反馈子表单)
|
||||
- `src/views/bg/xispeak/components/BgXiSpeakBPMForm.vue`(流程表单)
|
||||
- `src/views/bg/xispeak/components/BgXiSpeakFeedbackViewModal.vue`(查看办理情况)
|
||||
- `src/views/bg/xispeak/components/BgXiSpeakFeedbackList.vue`(孤儿组件)
|
||||
- 后端 `backend/.../xispeak/controller/BgXiSpeakController.java`
|
||||
|
||||
## 总体结论
|
||||
- **P0 × 1 | P1 × 4 | P2 × 5**
|
||||
- 一句话总结:核心 CRUD(新增→编辑→详情→删除)、查看办理情况、批量删除、导出均可用且无 console 错误;但存在 1 个功能性 P0(**添加下级无法建立树层级,子记录退化为根记录**)与 4 个 P1(**占位文本写入业务字段、多部门筛选语义错误、JBR 批量流程部分失败状态丢失、编辑反馈覆盖部门**),不建议直接交付。
|
||||
|
||||
---
|
||||
|
||||
## P0 - 必须修复
|
||||
|
||||
| # | 维度 | 问题描述 | 证据 | 位置 |
|
||||
|---|------|---------|------|------|
|
||||
| 1 | 逻辑/操作顺序 | **"添加下级"无法创建子节点,树形层级功能整体失效**。"添加下级"把 `{ pid: parentId }` 传入表单,但 `edit()` 对无 id 的新记录直接重置 formData 并丢弃 pid,子记录以 `pid=''` 保存(后端落库为 `pid="0"`),变成平铺根记录;父节点永远不出现展开图标,无法构建层级。 | 实测 `probe_pid.py`:添加下级保存时 add 请求体 `pid=""`;`probe_tree.py`:rootList 返回子记录 `"pid":"0"`,父节点刷新前后均无展开图标,子行无缩进 | `BgXiSpeakForm.vue:255-262`(`edit()` 重置丢弃 pid)· 触发 `BgXiSpeakList.vue:543-546` / `:633` |
|
||||
|
||||
---
|
||||
|
||||
## P1 - 强烈建议
|
||||
|
||||
| # | 维度 | 问题描述 | 证据 | 位置 |
|
||||
|---|------|---------|------|------|
|
||||
| 1 | 逻辑/表单 | **占位模板文本被硬编码为表单默认值并写入业务字段**。新增弹窗打开时"企业负责同志批示情况"已填 `经单位主要负责同时签批同意,由xx部做好贯彻落实`、"学习传达研究部署情况"已填 `x月x日召开xxxx年第x次党委会议`,提交时原样入库。用户不手动改就把占位假数据写进记录;同时这两个字段的必填校验形同虚设。 | 实测 `probe_defaults.py`:默认值截图 + 提交请求体 `elmComment=经单位主要负责同时签批同意…, status=x月x日召开xxxx年第x次党委会议`;CRUD 回显列内容含占位文本 | `BgXiSpeakForm.vue:163-164` |
|
||||
| 2 | 后端调用 | **牵头部门多选筛选为 AND 语义**。前端把多个部门 id 逗号拼接成 `implDept=A,B`,后端在循环里逐个 `queryWrapper.apply("FIND_IN_SET(...)")`,生成 `A AND B AND …` 条件——一条记录必须同时包含所有选中部门才命中,选 2+ 部门时几乎查不到数据。应为 OR。 | 代码路径 `BgXiSpeakController.java:94-102`(循环 apply);前端拼接 `BgXiSpeakList.vue:916-923` | `BgXiSpeakController.java:94-102` |
|
||||
| 3 | 操作顺序 | **JBR 批量发起流程部分失败时状态不保存、列表不刷新**。`successCount === total` 守卫放在循环内,任一部门流程发起失败则 `bpmStatus`/`supervisionCount` 不更新、不 reload,已成功的流程成为"孤儿流程"且无部分成功提示。 | `probe_flows.py` 未覆盖(需真实流程引擎);代码 `BgXiSpeakList.vue:740-793` | `BgXiSpeakList.vue:783-787` |
|
||||
| 4 | 状态一致性 | **编辑反馈记录时部门被当前登录人部门无条件覆盖**。`edit()` 加载记录后无条件调用 `fillDeptFromLogin()`,把 `responDeptid/responDeptname` 覆盖为登录人部门;跨部门编辑/审批他人的反馈并保存会造成部门归属数据错乱。 | 代码 `BgXiSpeakFeedbackForm.vue:294` + `230-249` | `BgXiSpeakFeedbackForm.vue:294` |
|
||||
|
||||
---
|
||||
|
||||
## P2 - 建议
|
||||
|
||||
| # | 维度 | 问题描述 | 证据 | 位置 |
|
||||
|---|------|---------|------|------|
|
||||
| 1 | 性能/体验 | **搜索无防抖,逐字触发 rootList**。JInput `@change="searchQuery"` 每个按键发一次查询;实测输入 6 个字符新增 6 次 rootList 请求。 | `probe_flows.py`:输入前 rootList REQ=2,6 字符后=8 | `BgXiSpeakList.vue:12` + `:900-902` |
|
||||
| 2 | 安全/整洁 | **流程表单 14 处 console.log 调试输出**,含 `@props`、流程变量、部门过滤中间结果等,生产环境泄漏调试信息。 | 代码 `BgXiSpeakBPMForm.vue:311,312,596,603,607,612,618,624,627,659,662,664,671,686` | `BgXiSpeakBPMForm.vue`(14 处) |
|
||||
| 3 | 逻辑 | **反馈表单日期处理死代码 + 调试日志**。`value.format('YYYY-MM-DD HH:mm:ss')` 对 Date 对象调用 `.format()` 会抛 TypeError(当前 axios 返回字符串未触发,属潜在崩溃点);另有 3 处 console.log。 | `BgXiSpeakFeedbackForm.vue:281-289`(`value.format`);`:238,243,248` | `BgXiSpeakFeedbackForm.vue:281-289` |
|
||||
| 4 | 整洁 | **List.vue 死代码**:未使用 import `JDictSelectTag`、未使用 computed `showSdwLeaderSelect`、未使用函数 `handleFormJoinChange`、line 142 import 缩进错乱。 | 全文件 grep 仅定义处出现 | `BgXiSpeakList.vue:148,202,937,142` |
|
||||
| 5 | 整洁 | **孤儿组件** `BgXiSpeakFeedbackList.vue` 未被任何源码引用;`searchReset()` 调用 `formRef.value.resetFields()` 而 `formRef` 未定义,一旦被挂载使用即崩溃。 | `BgXiSpeakFeedbackList.vue:141`;全局 grep 仅 checklist 文档引用 | `BgXiSpeakFeedbackList.vue:141` |
|
||||
|
||||
---
|
||||
|
||||
## 通过项(做得好的地方)
|
||||
- **CRUD 全链路正常**:新增→保存→列表回显→编辑→详情→删除全部跑通,数据一致,无 console 错误。
|
||||
- **空表单校验**:9 项必填错误准确提示并指向字段,提交前整体校验 + `scrollToField` 聚焦。
|
||||
- **危险操作二次确认**:单条删除 Popconfirm(含"同时删除关联流程"说明文案)、批量删除 Modal.confirm,文案清晰。
|
||||
- **查看办理情况**:动态标题"反馈信息(共 N 条,已完成 N 条)",空态显示"暂无数据",接口正常。
|
||||
- **批量删除**:勾选→批量操作→确认→删除成功,选中后按 ids 传递。
|
||||
- **导出**:`exportXls` 请求正常发出并返回 200。
|
||||
- **接口契约**:add/edit/delete/rootList/statusStats/withDrawXiSpeak/queryFeedbackCounts 方法、URL、参数实测全部正确。
|
||||
- **权限控制**:新增/导出/模板校验/模板导入等按钮均有 `v-auth` 指令;导出走配置 URL。
|
||||
- **列表列宽**:长文本列均有 `ellipsis`,操作列 `fixed: right` 不换行。
|
||||
- **空响应兜底**:`bgXiSpeakFeedbackList` 无 mainId 时 `Promise.resolve({})` 兜底,不崩溃(`BgXiSpeak.api.ts:117-122`)。
|
||||
|
||||
---
|
||||
|
||||
## 未覆盖项(需人工复核或真实环境验证)
|
||||
- **流程发起**(发起落实措施收集流程 / 发起经办人执行反馈流程):需要真实 Flowable 引擎 + 部门审批人数据,本次未实测。JBR 部分失败场景据此推断代码逻辑,建议真实环境复测。
|
||||
- **树展开真实数据**:DB 中无既有树形数据,且 P0(添加下级)导致无法生成层级,树展开仅验证到"无展开图标"。
|
||||
- **导出文件内容**:headless 下导出经新窗口触发,仅确认请求 200,未核验 Excel 内容。
|
||||
- **上传类按钮**(模板校验/模板导入/下载模板):未实测,依赖 `/upload` 代理(3300 端口本次未运行,产生 `ERR_PROXY_CONNECTION_FAILED`,与 xispeak 逻辑无关)。
|
||||
- **多分辨率/暗黑主题**:headless 固定 1440×900,视觉细节需人工复核。
|
||||
- **长文本/特殊字符(含 XSS)注入、大数据量、断网异常**:未专项注入测试。
|
||||
- **双账号权限/密级过滤对比**:仅使用 admin 单账号。
|
||||
|
||||
---
|
||||
|
||||
## 测试过程记录
|
||||
|
||||
### 操作步骤与截图
|
||||
测试脚本与证据存于 `qa-tmp/xispeak/`(临时产物,gitignored;本报告为唯一提交的测试文档):
|
||||
|
||||
| 脚本 | 覆盖 | 截图/产物 |
|
||||
|------|------|----------|
|
||||
| `probe_crud2.py` | 空表单校验 → 全字段填充 → 保存 → 列表回显 → 编辑 → 详情 → 删除 | `crud_test2/shots/*.png` |
|
||||
| `probe_flows.py` | 查看办理情况 → 添加下级 → 搜索逐字输入(竞态)→ 清理 | `flows_test/shots/*.png` |
|
||||
| `probe_extra.py` | 父/子记录创建 → 展开 → 督办状态筛选 → 导出 | `extra_test/shots/*.png` |
|
||||
| `probe_batch2.py` | 勾选 → 批量删除 → 导出请求捕获 | `batch_test2/shots/*.png` |
|
||||
| `probe_tree.py` | 添加下级后展开图标(刷新前后)→ rootList hasChild 字段 | `tree_test/shots/*.png` |
|
||||
| `probe_pid.py` | 添加下级 add 请求体 pid 值 | 输出见运行记录 |
|
||||
| `probe_defaults.py` | 新增弹窗默认值 + 空表单校验 + 提交入参 | 输出见运行记录 |
|
||||
| `probe_secret.py` / `probe_fill*.py` | 密级/责任领导/部门选择弹窗结构 | 输出见运行记录 |
|
||||
|
||||
### console 报错
|
||||
- xispeak 业务操作全程 **0 个 error**(各脚本 console.json)。
|
||||
- 唯一 error 为 `ERR_PROXY_CONNECTION_FAILED`:来自 `/upload` 代理(3300 端口 mock 服务未运行),与 xispeak 逻辑无关。
|
||||
|
||||
### 关键网络请求(probe_flows.py 汇总)
|
||||
```
|
||||
GET /jeecgboot/bg/xispeak/bgXiSpeak/statusStats 200
|
||||
GET /jeecgboot/bg/xispeak/bgXiSpeak/rootList 200 (x10)
|
||||
GET /jeecgboot/bg/xispeak/bgXiSpeak/loadTreeRoot 200 (x2)
|
||||
GET /jeecgboot/bg/xispeak/bgXiSpeak/queryFeedbackCounts 200 (x4)
|
||||
POST /jeecgboot/bg/xispeak/bgXiSpeak/add 200
|
||||
GET /jeecgboot/bg/xispeak/bgXiSpeak/listBgXiSpeakFeedbackByMainId 200
|
||||
POST /jeecgboot/bg/xispeak/bgXiSpeak/withDrawXiSpeak 200
|
||||
DELETE /jeecgboot/bg/xispeak/bgXiSpeak/delete 200
|
||||
GET /jeecgboot/bg/xispeak/bgXiSpeak/exportXls 200 (probe_batch2)
|
||||
```
|
||||
|
||||
### 测试数据卫生
|
||||
- 所有测试数据使用 `QA_TEST_` / `QA_` / `QA_BATCH` / `QA_DEFAULTS` / `QA_PARENT` / `QA_CHILD` 前缀,测试后均通过 UI 删除清理(各脚本末步"清理"均归零)。无残留测试数据。
|
||||
Reference in New Issue
Block a user