Commit aae9bd692363f89acc2a6b22251d1d9e5e01ea6c

Authored by zichun
1 parent 4dbc4a74

chore(frontend): 渲染前端阶段 12 节模块完成报告(test-gate r1 green,4 FE approved)

docs/superpowers/module-reports/2026-06-02-frontend-phase.md 0 → 100644
  1 +# 模块完成报告 — 前端阶段(frontend-phase)
  2 +
  3 +> 标准化 12 节《模块完成报告》。本报告由 test-gate 绿后渲染,供 milestone 标记使用。
  4 +> 数据来源:仅取 git 摘要(`diff --stat` / `log --oneline`)、FE specs/plans/reviews、test-gate 证据,未读 diff 正文进上下文。
  5 +> 输出语言:中文。阶段 = 前端(frontend),实现作用域 = `frontend/`。
  6 +
  7 +---
  8 +
  9 +## ① 模块标识
  10 +
  11 +| 字段 | 值 |
  12 +|---|---|
  13 +| module_id | `frontend-phase` |
  14 +| module_name | 前端阶段(整体) |
  15 +| 阶段 | 前端(frontend) |
  16 +| 分支 | `frontend-phase`(自默认分支 `master` 分叉) |
  17 +| 默认分支 | `master` |
  18 +| 分叉点(merge-base) | `236c42b1e28ff8ecd775faf06071be595fbf81d3` |
  19 +| 里程碑 | 整个前端阶段 1 个里程碑 tag(`milestone/frontend-phase`),由本报告 commit 后于 milestone 步骤标记 |
  20 +| 报告日期 | 2026-06-02 |
  21 +
  22 +---
  23 +
  24 +## ② FE 完成清单
  25 +
  26 +前端阶段以 `frontend-phase` 单一阶段聚合 4 个 FE 业务功能(粒度=业务功能,可关联多个 prototype 区域与多个 REQ)。按 FE-NN 顺序:
  27 +
  28 +| FE-NN | 业务功能 | 关联原型区域 | 关联 REQ | spec / plan / review / verify 产物 | docs/08 § 三状态 |
  29 +|---|---|---|---|---|---|
  30 +| FE-01 | 登录页(用户名/密码/版本下拉登录,对接 `POST /api/usr/login`) | `#screen-login`(`.login-wrap` / `.login-card` / `.login-foot`) | REQ-USR-004(主);配套读端点 `GET /api/usr/companies` | spec `2026-06-01-FE-01.md` / plan 同名 / review `2026-06-01-FE-01.md`(approve)/ verify `2026-06-01-FE-01-verify.md` | [x] approved |
  31 +| FE-02 | 主页与导航框架(顶栏 + 全部导航总览 + 主页 KPI 看板 + 常用操作;登录后落地页与路由壳) | `#topbar` / `#nav-overlay` / `#screen-main`(`.kpi-head` / `.three-col` / `.common-ops`) | 壳层无直接 CRUD REQ,承载 FE-01/03/04;当前用户身份来自 REQ-USR-004 响应 | spec `2026-06-01-FE-02.md` / plan 同名 / review `2026-06-01-FE-02.md`(approve)/ verify `2026-06-01-FE-02-verify.md` | [x] approved |
  32 +| FE-03 | 用户列表与查询(工具栏刷新/导出 + 筛选条件 + 用户表格 + 分页,对接 `GET /api/usr/users`) | `#screen-userlist`(`.toolbar` / `.filterbar` / `.grid-table` / `.pager`) | REQ-USR-003(主) | spec `2026-06-01-FE-03.md` / plan 同名 / review `2026-06-01-FE-03.md`(approve)/ verify `2026-06-01-FE-03-verify.md` | [x] approved |
  33 +| FE-04 | 用户信息单据(新增/修改用户表单 + 权限组勾选,对接 `POST /api/usr/users` + `PUT /api/usr/users/{id}`) | `#screen-userdetail`(`.toolbar` / `.form-grid` / `.tabs-row` / `.perm-list`) | REQ-USR-001(增)+ REQ-USR-002(改) | spec `2026-06-01-FE-04.md` / plan 同名 / review `2026-06-01-FE-04.md`(r1 request-changes → r2 approve)/ verify `2026-06-01-FE-04-verify.md` + `-verify-r1.md` | [x] approved |
  34 +
  35 +> 4 个 FE 在 docs/08 § 三均为 `[x]`(已 approved)。FE-04 经历 1 轮 request-changes(must-fix B1:edit 态预填把用户主键当「用户号」查询)后 fix 复验通过,详见 § ⑧/§ ⑨。
  36 +
  37 +---
  38 +
  39 +## ③ 文件变更(git diff --stat master...HEAD,三点 diff)
  40 +
  41 +区间 = 功能分支 `frontend-phase` 自默认分支 `master` 分叉以来的全部改动。
  42 +
  43 +- **总计**:126 files changed,**17860 insertions(+)**,4 deletions(-)。
  44 +- **实现代码(`frontend/`)**:源码 + 配置 + 测试,全部落在 `frontend/` 作用域内(无 `backend/` / `sql/` / `scripts/` 越界)。
  45 +- **文档(`docs/`)**:FE-01~04 的 specs/plans/reviews/verify + test-gate 证据 + docs/08 § 三勾选更新。
  46 +- **根级**:`.gitignore`(+3)。
  47 +
  48 +### 分类汇总
  49 +
  50 +| 分类 | 主要文件(节选) | 量级 |
  51 +|---|---|---|
  52 +| 工程骨架 / 配置 | `frontend/package.json` / `package-lock.json`(+6352)/ `vite.config.ts` / `tsconfig.json` / `.eslintrc.cjs` / `playwright.config.ts` / `index.html` | 8 文件 |
  53 +| API 基建 | `src/api/request.ts`(Axios 实例 + Result 拆包 + 401 拦截)/ `src/api/types.ts` / `src/api/usrApi.ts`(login/companies/listUsers/create/update/detail/employees/permissions) | 3 文件 |
  54 +| Store | `src/store/store.ts` / `hooks.ts` / `slices/authSlice.ts`(登录态 + token 持久化) | 3 文件 |
  55 +| 路由 | `src/router/index.tsx` / `RequireAuth.tsx` / `RedirectIfAuthed.tsx` / `AppErrorBoundary.tsx` | 4 文件 |
  56 +| 外壳(FE-02) | `src/layouts/AppLayout/*`(AppLayout / TopBar / NavOverlay / CurrentUserMenu / AppFooter / useTabStack / navConfig / shellMessages) | 10 文件 |
  57 +| 登录页(FE-01) | `src/pages/usr/Login/*`(LoginPage / Login.module.css / loginMessages) | 3 文件 |
  58 +| 主页(FE-02) | `src/pages/home/HomePage/*`(HomePage / KpiBoard / KpiHeadBar / RoleProcessTree / CommonOps / dashboardData / 样式) | 7 文件 |
  59 +| 用户列表(FE-03) | `src/pages/usr/UserList/*`(index / UserToolbar / UserFilterBar / UserTable / columns / constants / exportUtils / useUserList / 样式) | 9 文件 |
  60 +| 用户单据(FE-04) | `src/pages/usr/UserDetail/*`(index / UserDetailToolbar / UserBasicForm / PermissionTabs / PermissionGroupList / useUserDetail / constants / 样式) | 9 文件 |
  61 +| 全局样式 / 入口 | `src/main.tsx` / `App.tsx` / `styles/global.css` / `styles/theme.ts` / `vite-env.d.ts` | 5 文件 |
  62 +| 测试 | `tests/setup.ts` + `tests/unit/*`(40 单测文件)+ `tests/e2e/*`(login / shell / userlist / userdetail 4 spec) | 45 文件 |
  63 +| 文档证据 | `docs/superpowers/{specs,plans,reviews}/2026-06-01-FE-0*.md` + `module-reports/frontend-phase-test-gate-r1.md` + docs/08 § 三 | 17 文件 |
  64 +
  65 +---
  66 +
  67 +## ④ 数据库使用表
  68 +
  69 +`N/A(前端阶段)` —— 前端阶段不直接访问数据库,所有数据经后端端点(`/api/usr/*`)消费。
  70 +
  71 +---
  72 +
  73 +## ⑤ 测试闸(test-gate)记录与 flake 判定
  74 +
  75 +> 汇总 `docs/superpowers/module-reports/frontend-phase-test-gate-r*.md`(按 attempt 升序)。
  76 +
  77 +- **attempt 总数**:1(仅 `frontend-phase-test-gate-r1.md`)。
  78 +- **flake 判定**:**无 flake**(仅 1 次 attempt,无 red→green 切换)。最后一份(也是唯一一份)= **GREEN**,前置闸通过。
  79 +
  80 +### attempt 1(r1)— GREEN
  81 +
  82 +| 套件 | 命令 | exit_code | passed | failed | 时间窗口 |
  83 +|---|---|---|---|---|---|
  84 +| 单元(vitest) | `npm run test:unit`(= `vitest run`) | 0 | **193**(40 文件) | 0 | 2026-06-02 09:26:46 → 09:26:53 |
  85 +| E2E(playwright) | `npm run test:e2e`(= `playwright test`,chromium,Vite dev server 5173,`page.route` 桩后端) | 0 | **20** | 0 | 2026-06-02 09:26:57 → 09:27:04 |
  86 +
  87 +- **结论**:两套件 `exit_code` 均 0、`failed=0`,覆盖全部 FE 回归(vitest 193 + playwright 20)。
  88 +- E2E 覆盖 spec:`login.spec.ts` / `shell.spec.ts` / `userlist.spec.ts` / `userdetail.spec.ts`。
  89 +- **非致命噪声(不影响断言)**:jsdom 侧 `window.getComputedStyle not implemented`、React Router v7 future flag 警告;E2E 侧 `[vite] http proxy error ... ECONNREFUSED`(dev proxy 向未启动的真实后端转发,用例已用 `page.route` 拦截 `/api/**`,与断言无关)。
  90 +- 命令来源:`docs/04-技术规范.md § 零` 命令清单(前端 unit=`vitest run`、e2e=`playwright test`)。执行方式:派发独立(detached)子进程跑测试,主会话仅消费结构化结果,未在主会话直接跑测试。
  91 +
  92 +---
  93 +
  94 +## ⑥ Migration(Flyway)
  95 +
  96 +`N/A(前端阶段)` —— 前端阶段不涉及 schema 演化,未新增 `sql/migrations/V*.sql`。
  97 +
  98 +---
  99 +
  100 +## ⑦ 跨模块改动
  101 +
  102 +`N/A(前端阶段)` —— 实现改动全部落在 `frontend/` 作用域内(git diff --stat 确认无 `backend/` / `sql/` / `scripts/` 文件变更);无跨模块日志(`docs/superpowers/cross-module-log*` 不存在),无需记录跨模块影响评估。
  103 +
  104 +> 待对齐项(非本阶段改动,记于此供后端编码期消化):FE-04 § 8 D1/D2 的支撑只读端点 `GET /api/usr/employees`(员工下拉)/ `GET /api/usr/permissions`(权限组)需在后端 REQ-USR-001/002 实现内补齐契约(同 FE-01 `GET /api/usr/companies` 先例)。这是跨阶段(前端→后端)的接口对齐项,前端已按既有先例消费,未越界改后端代码。
  105 +
  106 +---
  107 +
  108 +## ⑧ 偏离清单(实际渲染 DOM ↔ 各 FE 关联原型主结构)
  109 +
  110 +> 硬验证项:逐 FE 列举「实际渲染 DOM 与关联原型主结构的差异」。原型 `prototype/erp.html` 为单文件静态 demo(4 个 `#screen-*` 区段),实现为 React + AntD 5 路由化应用。下列偏离**均为 spec 已登记的有意决策(D 系列)或交互语义复刻取舍**,非缺陷;每条注明对应决策来源。
  111 +
  112 +### FE-01 登录页(原型 `#screen-login`)
  113 +
  114 +| # | 偏离 | 性质 | 来源 |
  115 +|---|---|---|---|
  116 +| 1 | 原型「屏切换」demo(`goTo('login')` + 按钮 `data-go="main"` 直接切主页)→ 实现为独立路由 `/login`,提交走 `POST /api/usr/login`,成功才 `navigate('/')` | 有意(交互语义复刻) | FE-01 spec § 6.4 / D3 |
  117 +| 2 | 原型版本下拉硬编码「标准版」demo 项 → 实现 options 全部来自 `GET /api/usr/companies`,不硬编码 | 有意 | FE-01 D1/D8 |
  118 +| 3 | 主视觉深蓝渐变 / 网格透视背景作为登录页局部 scoped 装饰样式保留,不新增全局 token、不挪用语义 token | 有意(tokens.css 无对应品牌深色) | FE-01 D7 |
  119 +| 4 | 登录失败(40101/42901)后清空密码并聚焦 —— 原型无此交互 | 有意(通用安全交互增强) | FE-01 D5 |
  120 +
  121 +### FE-02 主页与导航框架(原型 `#topbar` / `#nav-overlay` / `#screen-main`)
  122 +
  123 +| # | 偏离 | 性质 | 来源 |
  124 +|---|---|---|---|
  125 +| 1 | 原型单页多屏(`goTo(name)` 切 `.screen.active`)→ 实现为 React Router v6 真实路由 + `<AppLayout>` 布局路由包裹受保护子路由 | 有意(核心架构复刻) | FE-02 spec § 6.1/6.3 |
  126 +| 2 | KPI 看板 / 角色流程树 / 导航分组 = 原型静态 demo → 实现为前端静态配置(`dashboardData.ts` / `navConfig.ts`),**不新增后端取数**(docs/05 无 KPI/导航端点) | 有意(不杜撰端点) | FE-02 D1/D2 |
  127 +| 3 | 搜索 / 通知 / 更多 / AI 助手图标、导航总览中无路由的叶子项 → 占位(不绑后端,点击关 overlay 不跳转或 `message.info`) | 有意(占位化) | FE-02 D4 |
  128 +| 4 | 顶栏 / 导航 overlay 深色底作为 `AppLayout` 局部 scoped 装饰样式保留 | 有意(tokens.css 无对应品牌深色) | FE-02 D9 |
  129 +| 5 | 退出登录为纯前端注销(清 `authSlice` + 删 token + 跳 `/login`),无后端注销端点 | 有意(无状态 JWT) | FE-02 D6 |
  130 +| 6 | 标签栈 / overlay 开关用 `AppLayout` 本地 `useState`(`useTabStack`),未上提全局 store | 有意(就近态) | FE-02 D3 |
  131 +
  132 +### FE-03 用户列表与查询(原型 `#screen-userlist`)
  133 +
  134 +| # | 偏离 | 性质 | 来源 |
  135 +|---|---|---|---|
  136 +| 1 | 原型 `users` 静态数组直接渲染 `tbody` → 实现真实对接 `GET /api/usr/users`(服务端分页 + 筛选 + 加载/空/错误态) | 有意(核心功能复刻) | FE-03 D1 |
  137 +| 2 | 原型分页写死「共37条记录 / 10000 条/页」→ 实现 `pageSize` 默认 10、`showSizeChanger=[10,20,50,100]`(上限对齐 docs/05 最大 100),不沿用 demo 10000 | 有意(对齐契约约束) | FE-03 D4 |
  138 +| 3 | 筛选栏首个下拉「全部用户」(原型单项 demo)→ 保留控件位但不向后端传额外「范围」参数(契约无此参数) | 有意(不杜撰参数) | FE-03 D2 |
  139 +| 4 | 筛选栏「▾」更多条件、工具栏设置齿轮「⚙」→ 占位(无额外后端参数/端点) | 有意(占位化) | FE-03 D3/D7 |
  140 +| 5 | 「导出Excel」原型无后端脚本 → 实现为前端导出当前查询结果(不杜撰后端导出端点) | 有意(前端实现) | FE-03 D5 |
  141 +| 6 | 「作废」列原型为 demo 复选框 → 实现只读展示 `iIsVoid`(0/1→否/是,不可勾选) | 有意(只读查询语义) | FE-03 BR6 |
  142 +| 7 | 行 `dblclick` 原型 `goTo('userdetail')` → 实现 `navigate('/usr/users/'+row.id)` 携 id 进 FE-04 | 有意(路由复刻) | FE-03 BR12 |
  143 +
  144 +### FE-04 用户信息单据(原型 `#screen-userdetail`)
  145 +
  146 +| # | 偏离 | 性质 | 来源 |
  147 +|---|---|---|---|
  148 +| 1 | 原型表单字段值写死 + `setUserDetailMode('new')` 仅做 DOM 文本清空 → 实现按路由 mode(`/new`=create / `/:id`=edit)分支,create 默认值预填、edit 回填原值 | 有意(核心功能复刻) | FE-04 spec § 2/3 |
  149 +| 2 | 员工名下拉 / 权限组列表 = 原型静态 demo → 实现消费支撑只读端点 `GET /api/usr/employees` / `GET /api/usr/permissions`(端点须后端补齐,见 § ⑦ 待对齐项) | 有意(下拉需读源) | FE-04 D1/D2 |
  150 +| 3 | edit 态预填复用列表端点 `GET /api/usr/users`(「等于」匹配 + pageSize=1 取 `records[0]`),不杜撰单用户详情端点;并支持 FE-03 经路由 state 携行数据免二次请求 | 有意(不杜撰端点);**含 1 处经 review 修复的偏离**:r1 误把用户主键当「用户号」查询导致 40401,r2 已修为走 navigate state + loadError 返回列表入口 | FE-04 D4 / review B1(见 § ⑨) |
  151 +| 4 | 权限页签条除「权限组」外的 5 个查看权限页签(客户/供应商/人员/工序/司机)→ 占位页签(无 REQ/端点) | 有意(占位化) | FE-04 D9 |
  152 +| 5 | 工具栏「删除/作废/重置密码/取消作废/功能」按钮 → 占位(无对应端点);其中「作废」语义经 PUT 已有字段 `iIsVoid` 承载,不新增端点 | 有意(占位化) | FE-04 D8 |
  153 +| 6 | 密码字段不在 UI 呈现(create 后端默认 666666 初始化,edit 不改密码) | 有意(契约语义) | FE-04 BR9 |
  154 +| 7 | 工具栏深色底作为 `UserDetail` 局部 scoped 装饰样式;原型必填红 `--label` 映射到 `var(--color-error)` | 有意(tokens 优先) | FE-04 D10 |
  155 +
  156 +> **偏离总结**:所有偏离均为「静态 demo → 真实路由/API」「不杜撰后端端点的占位化」「tokens.css 优先于原型私有色值」三类有意决策,无未登记的非预期偏离。唯一一处经 review 纠错的偏离(FE-04 edit 预填数据流 B1)已于 r2 修复并复验通过。各 FE 实现组件与原型 4 个 `#screen-*` 主结构一一对应(登录/主页/列表/单据 + 顶栏 + 导航 overlay)。
  157 +
  158 +---
  159 +
  160 +## ⑨ Review 与缺陷修复记录
  161 +
  162 +| FE-NN | review 轮次 | 裁决 | must-fix | 修复 commit |
  163 +|---|---|---|---|---|
  164 +| FE-01 | r1 | approve | 无 | — |
  165 +| FE-02 | r1 | approve | 无 | — |
  166 +| FE-03 | r1 | approve | 无 | — |
  167 +| FE-04 | r1 | request-changes | B1:edit 态预填把用户主键当「用户号」查询,正常导航流必然取不到记录 → 40401 | `96e88d3 fix(usr): 修复 review must-fix FE: FE-04 编辑预填走 navigate state 并补 loadError 返回列表入口` |
  168 +| FE-04 | r2 | approve | 无(B1 已修复复验,verify-r1 全 PASS) | — |
  169 +
  170 +> FE-04 修复后单测 55 passed / E2E 5 passed(`2026-06-01-FE-04-verify-r1.md`),edit 预填用例(`useUserDetail`/`UserDetailPage` edit 分支、E2E `edit user prefill then save`)全部通过。最终 test-gate r1 GREEN 覆盖全量回归。
  171 +
  172 +---
  173 +
  174 +## ⑩ 关键技术决策与约定(跨 FE 复用资产)
  175 +
  176 +| 约定 | 落地 | 来源 |
  177 +|---|---|---|
  178 +| 请求基建 | `src/api/request.ts`:Axios 实例 `baseURL=/api`,开发期 Vite proxy 转发到后端 `http://localhost:5172`(`config-vars.yaml backend.http_port`);响应拦截器拆 `Result`(code=0 取 data,非 0 抛错),401 统一跳 `/login` | docs/04 § 2.3/2.4;FE-01 D2 |
  179 +| 登录态 | `authSlice`(RTK)持 token + user;token 持久化 localStorage 键 `xly_erp_token`,刷新后由 `request.ts` 注入 `Authorization: Bearer` | docs/04 § 2.2;FE-01 D6 |
  180 +| 路由守卫 | `RequireAuth`(三态:authResolving/unauthenticated/ready)+ `RedirectIfAuthed`(已登录访问 /login 回主页)+ `AppErrorBoundary`(路由级兜底) | docs/04 § 2.1;FE-02 § 6.2 |
  181 +| 状态分层 | 服务端数据就近用页面 hook(`useUserList` / `useUserDetail`),不进全局 store;仅登录态进 store | docs/04 § 2.2;FE-03 D6 / FE-04 D7 |
  182 +| 色值 SSoT | 组件样式只用 `var(--color-*)`(`src/styles/tokens.css`),tokens.css 优先于原型私有色值;品牌深色(顶栏/overlay/登录主视觉/工具条)作局部 scoped 装饰,不新增全局 token、不挪用语义 token | 各 FE § 7 + D7/D9/D10 |
  183 +| 不杜撰后端端点 | 仅消费 docs/05 已定义端点 + 既有先例支撑只读端点(companies/employees/permissions);导出、注销、KPI/导航均不杜撰端点 | 硬约束 + 各 FE D 系列 |
  184 +
  185 +---
  186 +
  187 +## ⑪ 下一模块预览(上线 / 部署后续步骤)
  188 +
  189 +前端阶段是 Coding 阶段最后一个聚合阶段(排在所有后端模块之后)。本报告 commit + milestone 标记后,进入上线 / 部署后续:
  190 +
  191 +1. **里程碑标记**:本报告 commit 落地后,于 milestone 步骤打 `milestone/frontend-phase` tag(前置依赖工作树干净,本 commit 满足)。
  192 +2. **分支合并**:`frontend-phase` 合并回默认分支 `master`(按 superpowers `finishing-a-development-branch` 流程,PR 或直接合并由上层编排决定)。
  193 +3. **跨阶段接口对齐(阻塞上线联调)**:后端需补齐 FE 消费的支撑只读端点契约——`GET /api/usr/companies`(FE-01 版本下拉,REQ-USR-004 后端规格已记)、`GET /api/usr/employees`(FE-04 员工下拉)、`GET /api/usr/permissions`(FE-04 权限组);否则前后端联调时对应下拉无真实数据。详见 § ⑦ 待对齐项。
  194 +4. **前后端联调验证**:当前 E2E 用 `page.route` 桩后端,上线前需起真实后端(端口 5172)+ Vite proxy 做端到端联调,验证登录 / 列表分页 / 单据增改 / 401 被动登出全链路。
  195 +5. **导出端点取舍**:FE-03「导出Excel」当前为前端实现(SheetJS);若后续后端补 `/export` 端点可切换为服务端导出(D5 已留切换口)。
  196 +6. **私有化部署**:按 CLAUDE.md「私有化部署」,前端构建产物(`vite build`)随后端打包部署,`baseURL=/api` 经反向代理指向后端。
  197 +
  198 +---
  199 +
  200 +## ⑫ 结论
  201 +
  202 +- **前置闸**:test-gate **GREEN**(唯一 attempt r1,**无 flake**),vitest 193 + playwright 20 全绿,覆盖 4 个 FE 全量回归。
  203 +- **作用域**:实现改动全部落在 `frontend/`,无 `backend/` / `sql/` / `scripts/` 越界,无跨模块改动。
  204 +- **完成度**:FE-01~04 全部 approved(docs/08 § 三 `[x]`);FE-04 经 1 轮 request-changes 修复(edit 预填 B1)后复验通过。
  205 +- **偏离**:§ ⑧ 已逐 FE 列举全部偏离,**均为 spec 登记的有意决策**(静态 demo→真实路由/API、不杜撰端点的占位化、tokens 优先),**无未登记的非预期偏离**;实现组件与原型 4 个 `#screen-*` 主结构一一对应。
  206 +- **可进入 milestone 标记**:本报告 commit 后工作树干净,满足里程碑前置。