2026-06-01-FE-01.md 6.11 KB

FE-01 登录页 — AI 自审报告(第 1 轮)

  • 阶段:前端(frontend)
  • 关联 REQ:REQ-USR-004(主);配套 GET /api/usr/companies
  • 关联原型:prototype/erp.html<section id="screen-login">
  • 规格:docs/superpowers/specs/2026-06-01-FE-01.md
  • 裁决:approve
  • must-fix issues:无(空数组)

审阅范围

本轮 diff(自 2dce637^ 起的 FE-01 提交链)落在 frontend/ 内,作用域合规,未触碰 backend/ / sql/ / scripts/。核心文件:

  • frontend/src/pages/usr/Login/LoginPage.tsx
  • frontend/src/pages/usr/Login/Login.module.css
  • frontend/src/pages/usr/Login/loginMessages.ts
  • frontend/src/api/{request.ts,types.ts,usrApi.ts}
  • frontend/src/store/slices/authSlice.tsfrontend/src/router/index.tsxfrontend/src/App.tsxfrontend/src/styles/theme.ts

质量闸(独立复跑验证)

  • tsc --noEmit:通过(exit 0)。
  • vitest run:10 文件 / 32 用例全绿(含布局、版本预加载/空态/重试、校验、提交中态、错误码分流、成功落地、authSlice、request 拦截器)。
  • eslint .:通过(exit 0)。

前端 7 维 checklist

  1. 原型一致性(客观)— 通过:复刻 .login-wrap 三段式(品牌头 / 深蓝主视觉+右侧浮层登录卡 / 页脚版权);登录卡 right:8% top:50% translateY(-50%)、宽 380px、主操作为底部 block 主按钮,与原型 DOM 结构与主操作位置一致。下拉以 AntD Select 等价复刻原型 .lf.dropdown,属允许的实现差异。
  2. Design Tokens(客观)— 通过:语义色(按钮 / 文字 / 标题 / 占位 / 边框 / 背景 / 错误)全部走 var(--color-*),无硬编码。Login.module.css 中的 hex/rgba 全部位于 .hero 主视觉装饰(深蓝渐变 / 网格透视 / hero 文案)及阴影 alpha,属规格 D7 明确豁免的「登录页局部装饰,不挪用语义 token、不新增全局 token」。LoginPage.tsx 内两处 fill="#0e1216" / #3a6cb6 为原型逐字复刻的品牌 Logo / ICP 图标 SVG 装饰填充,非语义 UI 色,归同一装饰豁免。theme.ts#1890ff 为读取 --color-primary 失败时的兜底常量(= token 现值),运行时优先读 CSS 变量。token 优先于原型的色值精度差异处理正确(原型品牌名为琥珀色 #e0a020,实现改用 --color-primary,符合「tokens.css 优先于 prototype」)。
  3. 无障碍(best-effort):表单控件仅用 placeholder,无显式 <label>/aria-label——但原型本身即 placeholder-only 无 label 区,规格未要求可见标签,故按 best-effort 处理,不作 must-fix(建议项见下)。装饰 SVG 正确带 aria-hidden;无危险/不可逆操作,无需确认弹窗;支持回车提交(AntD Form 默认),键盘可达。
  4. 响应式(best-effort)@media (max-width:768px) 将卡片回流为居中静态布局(D4)。目标用户为桌面端 ERP,无 must-fix。
  5. 业务校验前端复刻(客观)— 通过:BR1/BR2/BR4 用 AntD Form 必填校验(文案「请输入用户名」「请输入密码」「请选择版本」);BR3 Input.Password 掩码;BR6/BR7/BR8 错误码 40101/40302/42901 文案与后端语义一致且不细化枚举;BR9 成功落地;BR10 submitting 期间禁用+早返回防重复提交;BR11 明文原样提交。
  6. API 调用一致性(客观)— 通过POST /api/usr/loginGET /api/usr/companies 均经统一 request.ts Axios 实例,无裸 fetch/手拼 URL。请求体 {sUserName,password,companyId}、响应 {token,user:{id,sUserName,sUserType,sLanguage}}、公司项 {id,sCompanyName,sVersion} 与 docs/05 + REQ-USR-004 后端规格(§2.3 / §8 D1,含 GET /api/usr/companies42901 限流码)一致。响应拦截器拆 Result、登录端点不强制带 token,符合 docs/04 § 2.3/2.4。
  7. 状态机覆盖(客观)— 通过:5 态齐备——companiesLoading(Select loading+禁用+占位「加载版本中…」)、idleemptynotFoundContent="暂无可用版本"+轻提示)、submitting(按钮 loading + Form 整体 disabled + 早返回)、error(错误码分流 message.error + 版本失败重试入口)、successsetCredentials + 持久化 + navigate('/',{replace:true}))。

通用四维

  • 计划对齐:实现与 spec §2-§7 / REQ-USR-004 输入表逐项对应,自主决策 D1-D8 在代码注释与结构中可追溯。
  • 质量:错误处理集中在响应拦截器 + 页面错误码映射;TS 类型契约(types.ts)跨 task 共享;测试覆盖充分;登录端点放行、token 仅登录态注入,无明显安全/性能问题。
  • 架构:api / store / pages / router / styles 分层清晰,页面只调 usrApi,不散用 axios;token 持久化键 TOKEN_STORAGE_KEY 单点定义。
  • 文档:文件含 REQ-USR-004 注释与决策追溯,符合 CLAUDE.md 约定。

非阻塞建议(口头,不入 issues)

  • A11y 增强(建议):可为用户名 / 密码 / 版本三控件补 aria-label(如「用户名」「密码」「版本」),在 placeholder-only 布局下提升读屏可用性。非 must-fix。
  • authSlice.setCredentials reducer 内做 localStorage 写副作用为 MVP 取舍(D6 已登记),后续如引入 SSR/严格纯 reducer 规范可迁至中间件或 thunk。非本轮阻塞。

决策(decisions)

本轮审阅未做改变源码语义的自主默认;对 D2/D7 的「装饰色豁免」「品牌 SVG 装饰填充非语义色」的判定均基于规格 D7 与原型逐字复刻证据,记录如下:

  • question: LoginPage.tsx/Login.module.css 中的 hex/rgba 是否构成 Design Token 违规? | choice: 不构成,判 approve | rationale: 全部位于主视觉装饰 / 品牌 Logo / ICP 图标 SVG / 阴影 alpha / 兜底常量,规格 D7 已豁免,且语义色无一硬编码 | confidence: high
  • question: 表单无 <label> 是否 must-fix? | choice: 否,降级为口头建议 | rationale: 原型即 placeholder-only 无 label 区,规格未要求可见标签,按 a11y best-effort 规则不单独触发 request-changes | confidence: high