2026-06-01-FE-04.md
6.12 KB
FE-04 用户信息单据 — AI 代码评审报告(第 2 轮)
- 规格:
docs/superpowers/specs/2026-06-01-FE-04.md - 阶段:前端(frontend)
- 关联 REQ:REQ-USR-001(增加用户)/ REQ-USR-002(修改用户)
- 关联原型:
prototype/erp.html<section id="screen-userdetail"> - 本轮 fix commit:
96e88d3(编辑预填走 navigate state + 补 loadError 返回列表入口) - 裁决:approve
一、作用域核查(通过)
本轮 diff 实现文件全部落在 frontend/ 下(src/pages/usr/UserDetail/、src/pages/usr/UserList/index.tsx、tests/unit/),未触碰 backend/ / sql/ / scripts/,符合前端阶段路径作用域硬约束。工作树干净(fix 已 commit)。
二、上轮 must-fix 复验(核心维度)
B1(上轮 blocker)— 已修复 ✔
上轮判定:edit 态预填把路由主键 :id 当「用户号」去 GET /api/usr/users?queryField=用户号 精确匹配,真实后端必然返回空 → 误报 40401,无法满足 REQ-USR-002 编辑预填(BR17)。
本轮 fix(commit 96e88d3)按上轮修复方向 #1 落地,复验确认到位:
-
frontend/src/pages/usr/UserList/index.tsx:36双击行改为navigate('/usr/users/' + row.id, { state: { user: row } }),把列表行UserVO经 navigate state 透传。 -
frontend/src/pages/usr/UserDetail/index.tsx:43从location.state.user取presetUser传入 hook。 -
frontend/src/pages/usr/UserDetail/useUserDetail.ts:116-131edit 分支改为:有presetUser→initFromVo回填;缺presetUser(直链访问 / 刷新丢 state)→ 进入loadError(loadFailed=true+MSG_LOAD_DETAIL_FAIL),不再调getUserDetail、不再把主键塞进「用户号」查询。原getUserDetailimport 与notFound状态已彻底移除。 -
frontend/src/pages/usr/UserDetail/index.tsx:108-128loadError 整页态在 edit 模式额外提供「返回列表」入口(spec § 4「edit 详情失败给整页重试或返回列表」),替代原误导性的 40401「该用户不存在」页。 - 残留核查(grep):
src/内已无getUserDetail调用方(仅usrApi.ts保留导出,见 S1)、无notFound状态、无「按主键查用户号」路径;MSG_ERR_USER_NOT_FOUND仅在 submit 路径(useUserDetail.ts:225,PUT 返回 40401)保留使用,符合 spec § 4「edit submit 可命中 40401」,非误用。
测试同步更新且通过:
-
tests/unit/useUserDetail.test.tsx:新增「edit 缺 presetUser → loadFailed 且不调 getUserDetail」、保留「edit 带 presetUser 跳过 getUserDetail」。 -
tests/unit/UserDetailPage.test.tsx:edit 预填用例改为经 navigate state 注入presetUser并断言mockedDetail未被调用;新增「edit 缺 state → loadError 提供 点击重试 + 返回列表」。 -
tests/e2e/userdetail.spec.ts:97edit user prefill then save:经列表双击(携带 state)预填→改语言→PUT 保存→回流列表,通过。
结论:B1 已被真实修复(非掩盖),数据流自洽,且测试改造正确反映了「主键无 by-id 读端点、预填依赖列表行 state」这一事实约束。
三、本轮门禁证据(复跑确认)
-
npm run lint:exit 0(无 error/warning)。 -
npx tsc --noEmit:exit 0(含renderShell.tsx新增ShellInitialEntry本地类型,类型自洽)。 -
npm run test:unit:40 文件 / 193 用例全通过(FE-04 相关 UserDetailPage 10、useUserDetail、UserDetailToolbar 等全绿)。 -
npm run test:e2e -- userdetail.spec.ts:5 passed / 0 failed。ECONNREFUSED 为 route 层 mock 下的预期 vite proxy 噪声,不影响判定。
四、对照确认(七维 + 通用维,沿用上轮通过项,本轮 diff 未改动者不再赘述)
- 原型一致性:工具栏 / 3 列 form-grid / tabs-row(权限组 active + 5 占位页签 disabled)/ perm-list 结构与
#screen-userdetail一致,主操作「保存」置工具栏,无结构性偏移;本轮 diff 未触碰布局。 - Design Tokens:语义色仍走
var(--color-*);本轮 diff 未引入新色值。 - a11y(客观项):表单控件经 AntD
Form.Item label关联;「取消」脏表单二次确认(Modal.confirm)保留;loadError「返回列表」为标准Button,键盘可达。 - 业务校验前端复刻:BR3/BR4/BR6/BR7/BR8/BR5/BR9/BR11 与错误码 40001/40901/40401/40301 文案及就近高亮均保持。
- API 调用一致性:create/update/listEmployees/listPermissions 经统一
request.ts实例,无裸 fetch/axios;请求体字段对齐 docs/05。本轮去掉了 edit 预填对列表端点的误用,API 调用面更收敛。 - 状态机覆盖:loading / empty / error(loadError 重试 + edit 返回列表)/ 正常 / 提交中 五态齐备;edit 缺 state 归入 loadError,语义比上轮 40401 更准确。
五、建议项(非 must-fix,可后续消化,不影响本轮 approve)
- S1(沿上轮 S1,已部分自然消解):
frontend/src/api/usrApi.ts:107getUserDetail现已无生产调用方(仅测试 mock 中作为占位导出)。可在后续清理为「删除该函数」或「待后端补单用户详情/按主键定位端点后复用」。当前保留不构成缺陷(lint/tsc 均不报未用导出)。 - S2:
userVoToFormValues(constants.ts:146)因UserVO(FE-03 列表 VO)不含iEmployeeId/iCanModifyBill/ 已授权权限 id,edit 预填时这三项被置默认(iEmployeeId=null/iCanModifyBill=0/checkedPermissionIds=[])。这是 spec D4 已登记的数据模型限制(列表 VO 为唯一可用源),非本轮回归;待后端补单用户详情读端点后可完整回勾。已属 spec 决策范畴,不作 must-fix。 - S3(沿上轮 S3):
useUserDetail.ts:143catch 文案分支读permissions.length为闭包旧值,仅影响 loadError 文案精度,不影响功能。
六、裁决
上轮唯一 blocker(B1)已在本轮 diff 中真实修复,数据流自洽、测试改造正确、门禁四项(lint / tsc / unit / e2e)全绿,未引入新缺陷、未回归既有通过项。其余为可选建议项,均不构成 must-fix。
verdict: approve