Files
gaokao-volunteer-system/FRONTEND_TASK_LIST_2026-07-02_V2.md
Frontend Developer fa7c22e8ed chore(s1): monorepo skeleton + 30-file prototype first commit
Sprint 1 G0 闸门通过 (pnpm install / typecheck / lint / build / turbo 全部 exit 0)

实际完成:
- T-A-01 monorepo 根骨架: pnpm-workspace.yaml + turbo.json + 根 package.json
- T-A-02 收编原型: apps/web/ 30 个 src/ 文件 (4948 行) 首次入库
- T-A-03 lint/format: eslint flat config (根 + apps/web) + prettier
- T-A-23 web-ci.yml: GitHub Actions 4-step CI (typecheck/lint/build/bundle)

勘误 (前置假设错误):
- 原型 4948 行 (不是 4114 行)
- 原型含 33 个 any + 16 个未用变量 (Sprint 2 修)
- 原型从未 commit, 用 cp -r + git add, 不是 git mv

推迟到 Sprint 2+:
- T-A-04/05 tsconfig packages 抽离
- T-A-06/07/08 design tokens 抽离
- T-A-09~13 5 基础组件

依赖隔离:
- .gitignore 加 11 行 monorepo 规则
- apps/web/.gitignore 补 .npm-cache/next-dev.log
- 删除 apps/web 内嵌 .git/ (cp -r 复制时携带)

验证:
- pnpm install: 1m55s, 456 packages
- typecheck: 0 errors
- lint: 0 errors, 49 warnings (any + unused)
- next build: 8 routes compiled, 9/9 static pages
- turbo run build: 1 successful, 12.9s
2026-07-03 09:22:03 +08:00

1294 lines
53 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 前端重构 · 任务清单 V2基于 tksea 最新版)
> 评审者:**Frontend Developer (资深前端开发工程师)**
> 日期2026-07-02 22:45
> 上游:`git pull` 拉取远端 `a8b4927`(比本地 `6d0feeb` 新 207 文件 / 87326 行净增)
> 重要:**`前端原型代码/` 完全未变**diff 为空)—— 之前的 8 项硬约束、4114 行代码、247 行 design-system 100% 适用
> V1 任务清单差异:**+45 任务 / +14 人天**,主要因后端新增 share-link / data-query / review-flow / llm 增强 / poster 集成
---
## 0. V1 → V2 关键变化(前置说明)
### 0.1 远端新版本a8b4927 vs 6d0feeb
```
207 files changed, 87326 insertions(+), 2399 deletions(-)
```
| 维度 | V16d0feeb | V2a8b4927 | 变化 |
|---|---|---|---|
| pytest 用例 | 924 | **1104** | **+180+19%** |
| admin/routes/web_public.py | ~900 行 | **~4800 行** | +3900 行share-link/data-query/review/poster/政策 5 大块) |
| 后端路由 | 87 | **约 110+** | +20 个端点 |
| 前端原型代码 | 4114 行 | **4114 行(不变)** | 0 |
| 新增脚本 | 旧版 | **+13 脚本** | integration_test / perf_benchmark / score_range_fullchain_100 / poster / payment_readiness_doctor 等 |
| skills/ | 旧版 | +6 文件gaokao-audit 等) | LLM 审核服务化 |
### 0.2 V2 新增的 5 大后端能力模块(前端必须对接)
| # | 模块 | 后端端点 | 前端页面 | V1 是否覆盖 | V2 新增任务 |
|---|---|---|---|---|---|
| 1 | **Share Link API** | `POST /api/share-link` / `DELETE /api/share-link/{id}` / `GET /api/portal/share-link/latest` | 复核/报告页分享按钮 | ❌ | T-B-22 ~ T-B-25 + T-D-13 |
| 2 | **Data Query 6 入口** | `/score-line-query` / `/rank-estimator` / `/majors-query` / `/schools-query` / `/data-query` | 4 个查询页 + 1 个聚合页 | ❌ | T-B-26 ~ T-B-31 + T-D-14 ~ T-D-17 + T-E-13 ~ T-E-16 |
| 3 | **Review Flow** | `/review/start` / `/review/action` / `/portal/{token}/cwb` / `/portal/{token}/full-plan` | 复核结果页 + 冲稳保 + 完整规划 | ❌ | T-B-32 ~ T-B-35 + T-D-18 + T-E-17 |
| 4 | **LLM 增强审核** | AuditService LLM 接入 + 多模型 fallback | 审核触发 + 进度 + 结果 | ❌(原型 mock | T-B-36 ~ T-B-38 + T-D-19 |
| 5 | **Poster 海报** | `data/share/poster.py` + CLI `gaokao-poster` | 海报生成 + 下载 | ❌ | T-B-39 + T-D-20 + T-E-18 |
### 0.3 V1 任务清单的"未变化部分"(依然成立)
| 不变量 | 验证方式 | V1 任务 |
|---|---|---|
| 前端原型代码 4114 行未变 | `git diff 6d0feeb..a8b4927 -- 前端原型代码/` 为空 | T-A-02 ~ T-A-23 全部保留 |
| 8 项硬约束 | 扫读原型文件源码 | T-A-14 ~ T-A-19 单测 + e2e 保留 |
| 5 阶段路径 | 与 V2 Senior Developer 报告一致 | A/B/C/D/E 阶段框架保留 |
| 78 人天估算 | V1 中位 | V2 调整为 **92 人天**+14 |
---
## 1. 任务总览 V2136 任务92 人天)
| 阶段 | 任务数 | 人天 | V1→V2 增量 | 关键里程碑 |
|---|---|---|---|---|
| A. 基础设施 | 23 | 11 | 0 | monorepo + 5 组件 + e2e 骨架 + CI |
| B. 真实后端对接 | 35 | 38 | +1421→35 | 30+ 端点对接 + 8 hook 真实化 + Lighthouse ≥ 90 |
| C. 架构整合 | 15 | 10 | +113→15 | 独立部署 + Sentry + CSP + Poster CLI |
| D. 设计 / a11y 加固 | 24 | 14 | +318→24 | 18 组件 + SharePanel + DataQuery + Review UI + axe |
| E. 内部页面 React 化 | 24 | 19 | +216→24 | 运营后台 + Share 管理 + Data Query + Review + Poster + Policy |
| **总计** | **136** | **92** | **+45 任务 / +14 人天** | **V1 66-89 → V2 78-105中位 92** |
> **注**V2 中位 92 人天 与 V2 Senior Developer 报告66-89相比略高**主要因为后端 5 大新模块的 React 化工作量是 V1 没预估到的**,建议向 PM 申请追加 14 人天1 人 × 2.8 周 或 2 人 × 1.4 周)。
---
## 阶段 A · 基础设施23 任务11 人天)
> **完全沿用 V1**,因为前端原型代码未变。
### A.1 Monorepo 收编3 任务1.5d
#### **T-A-01** 创建 monorepo 根骨架
- **产出**`pnpm-workspace.yaml` + `turbo.json` + 根 `package.json` + `.gitignore` + `pnpm-lock.yaml`
- **验收**
- [ ] `pnpm install` 成功,无 peer warning
- [ ] `pnpm -r list` 显示 `apps/*``packages/*`
- [ ] `turbo run build --dry-run` 显示任务依赖图
- **估时**0.5d
- **依赖**:无
#### **T-A-02** 收编 `前端原型代码/` 到 `apps/web/`
- **产出**`apps/web/src/` 完整包含原型 4114 行代码;`前端原型代码/` 目录删除
- **验收**
- [ ] `pnpm --filter web dev` 启动 dev server端口 3000
- [ ] 访问 `/` 看到完整聊天页Sidebar + ModeIndicator + PlanCard 等)
- [ ] `git status` 无意外 diff除了目录移动
- **估时**0.5d
- **依赖**T-A-01
#### **T-A-03** 加根 lint / format / git hooks
- **产出**`eslint.config.mjs`(共享) + `prettier.config.mjs` + `.husky/pre-commit`
- **验收**
- [ ] `pnpm lint` 跑通所有 workspace
- [ ] `pnpm format` 自动修所有文件
- [ ] commit 触发 lint-staged
- **估时**0.5d
- **依赖**T-A-01
### A.2 共享 tsconfig2 任务0.5d
#### **T-A-04** 抽 `packages/tsconfig/base.json`
- **产出**`strict + bundler + paths`,所有子 package 继承
- **验收**
- [ ] `apps/web/tsconfig.json` 改为 `extends: "@gaokao/tsconfig/base.json"`
- [ ] `pnpm --filter web typecheck` 0 error
- **估时**0.25d
- **依赖**T-A-02
#### **T-A-05** 共享 `tsconfig.lib.json`(含 `composite: true` + `declaration: true`
- **产出**`packages/tsconfig/lib.json``packages/ui` 等需要 build 的用
- **验收**
- [ ] `packages/ui/tsconfig.json` extends lib
- [ ] `pnpm --filter @gaokao/ui build` 生成 `dist/index.d.ts`
- **估时**0.25d
- **依赖**T-A-04
### A.3 设计系统提取3 任务1.5d
#### **T-A-06** 移 `design-system.css` 到 `packages/ui/tokens/`
- **产出**`packages/ui/tokens/design-system.css`247 行1:1 搬迁不改内容)
- **验收**
- [ ] `apps/web/src/styles/design-system.css` 改为 re-export 或删除
- [ ] Chromatic baseline 截图 0 diff
- [ ] `globals.css``@import` 路径更新
- **估时**0.5d
- **依赖**T-A-04
- **约束**§1.1design tokens 不可改值)
#### **T-A-07** 移 `lib/theme.ts` 到 `packages/ui/tokens/`
- **产出**`packages/ui/tokens/theme.ts`(含 `initThemeScript / getEffectiveTheme / setTheme / isDarkMode` 4 个函数1:1 搬迁)
- **验收**
- [ ] `apps/web/src/lib/theme.ts` 删除
- [ ] `layout.tsx` import 路径更新
- [ ] 三态主题切换功能 0 回归Playwright `theme.spec.ts` 全绿)
- **估时**0.5d
- **依赖**T-A-06
- **约束**§1.2(闪白防护必须保留)
#### **T-A-08** 写 `packages/ui/tokens/index.ts` barrel
- **产出**re-export 全部 token + theme 函数
- **验收**
- [ ] `import { ..., getEffectiveTheme, setTheme, ... } from '@gaokao/ui/tokens'` 工作
- **估时**0.5d
- **依赖**T-A-07
### A.4 UI 组件库起步5 任务2.5d
#### **T-A-09** Button 组件
- **产出**`packages/ui/components/Button.tsx` + `Button.test.tsx` + `Button.stories.tsx`
- **variant**`primary | secondary | ghost | danger`
- **size**`sm | md | lg`
- **验收**
- [ ] 4 variant × 3 size = 12 个 story
- [ ] Vitest 覆盖:点击事件 / disabled / loading 状态
- [ ] axe 0 critical
- **估时**0.5d
- **依赖**T-A-08
#### **T-A-10** Input / Select / Textarea 组件
- **产出**`packages/ui/components/{Input,Select,Textarea}.tsx` + 各自 test + story
- **特性**`error | helpText | touched` 三态
- **验收**
- [ ] FormCard 改用 Input 组件(视觉 0 回归)
- [ ] Vitest 覆盖必填 / 错误提示 / 受控值
- **估时**0.5d
- **依赖**T-A-09
#### **T-A-11** Card 组件
- **产出**`packages/ui/components/Card.tsx`
- **API**`<Card>{children}</Card>` —— 圆角 2xl + 阴影 sm + border gray-200
- **验收**
- [ ] PlanCard / AuditReportCard / CareerCard / FileUploadPrompt 全部改用 Card
- [ ] 视觉 0 回归
- **估时**0.5d
- **依赖**T-A-08
#### **T-A-12** Badge 组件
- **产出**`packages/ui/components/Badge.tsx`
- **API**`<Badge variant="risk-high | risk-medium | risk-low | neutral">{label}</Badge>`
- **验收**
- [ ] PlanCard 风险徽章 / PlanCard 调整徽章 / plans/page 院校统计徽章 全部改用
- [ ] 视觉 0 回归
- **估时**0.25d
- **依赖**T-A-08
#### **T-A-13** Tabs 组件
- **产出**`packages/ui/components/Tabs.tsx`
- **API**`<Tabs items={[{key,label,color}]} activeKey onChange>` —— ARIA `role="tablist/tab"`
- **验收**
- [ ] PlanCard 改用 Tabs
- [ ] plans/[id]/page.tsx 改用 Tabs
- [ ] 视觉 0 回归
- [ ] Vitest 覆盖 active 切换 + 键盘箭头导航WCAG 2.1.1
- **估时**0.75d
- **依赖**T-A-09
- **约束**§1.6PlanCard 三 Tab 不可改结构)
### A.5 测试基础设施4 任务1.5d
#### **T-A-14** Vitest + RTL + MSW 配置
- **产出**
- `packages/test-utils/vitest.config.ts`
- `packages/test-utils/setup.ts`jest-dom matchers + MSW server
- `packages/test-utils/renderWithProviders.tsx`QueryClient + Theme + Router
- **验收**
- [ ] `pnpm --filter web test` 跑通
- [ ] 占位测试 `Math.test.ts` 1 绿
- **估时**0.5d
- **依赖**T-A-01
#### **T-A-15** 示范单测ModeIndicator
- **产出**`ModeIndicator.test.tsx`
- **覆盖**
- 4 个 mode 各渲染对应 label
- `deriveMode` 决策树:
- isAuditActive → auditing
- currentPlan + no audit → adjusting
- province + score → generating
- 其他 → explore
- **验收**
- [ ] 100% line + branch coverage
- **估时**0.25d
- **依赖**T-A-14
- **约束**§1.44 模式决策树)
#### **T-A-16** 示范单测SafeMarkdown
- **产出**`SafeMarkdown.test.tsx`
- **覆盖 XSS 注入**
- `<script>alert(1)</script>` → 渲染为文本,不执行
- `<img src=x onerror=alert(1)>` → onerror 被剥
- `<a href="javascript:alert(1)">` → href 被 sanitize
- **验收**
- [ ] 3 个注入用例全过
- [ ] 正常 markdownh1/ul/code/blockquote渲染正确
- **估时**0.25d
- **依赖**T-A-14
- **约束**§0.1 R-NEWXSS 防护不可破)
#### **T-A-17** 示范单测FormCard
- **产出**`FormCard.test.tsx`
- **覆盖**
- 字段 touched 后才显示验证
- 跳步守卫basic 未完成不能进 subjects
- 提交时 subjects 数组拼装正确
- **验收**
- [ ] 80% line coverage
- **估时**0.5d
- **依赖**T-A-14
- **约束**§1.10(不允许跳步)
### A.6 Playwright e2e 骨架3 任务1.5d
#### **T-A-18** Playwright 配置
- **产出**`apps/web/e2e/playwright.config.ts`chromium + webkit + 2 个 mobile viewport
- **验收**
- [ ] `pnpm --filter web e2e` 启动浏览器
- [ ] `apps/web/e2e/smoke.spec.ts` 通过(仅访问 `/` 看到 Sidebar
- **估时**0.5d
- **依赖**T-A-14
#### **T-A-19** 示范 e2etheme.spec
- **产出**`theme.spec.ts`
- **覆盖**
- 切到 dark → `data-theme="dark"` 出现
- 切到 system → `data-theme` 移除
- **刷新页面后** localStorage 保留选择
- 视觉无闪白(`page.waitForLoadState('domcontentloaded')` 在 100ms 内)
- **验收**
- [ ] 3 个主题切换场景全绿
- **估时**0.5d
- **依赖**T-A-18
- **约束**§1.2(闪白防护)
#### **T-A-20** 示范 e2enavigation.spec
- **产出**`navigation.spec.ts`
- **覆盖**
- 桌面 viewport (1280) → Sidebar 可见MobileNav 隐藏
- 移动 viewport (375) → MobileNav 可见Sidebar 隐藏
- 点击 Sidebar /plans → 跳转
- 点击 MobileNav /plans → 跳转
- **验收**
- [ ] 4 个场景全绿
- **估时**0.5d
- **依赖**T-A-18
- **约束**§1.71024 断点)
### A.7 OpenAPI 类型化2 任务1.5d
#### **T-A-21** OpenAPI Codegen 接入
- **产出**
- `packages/api-client/codegen.config.ts`
- `packages/api-client/src/index.ts`(自动生成)
- `turbo.json``generate-api-client` 任务,依赖 `^build-admin`
- **验收**
- [ ] `pnpm --filter @gaokao/api-client generate` 跑通
- [ ] 生成 `dist/services/AuthService.ts`
- **估时**1d
- **依赖**T-A-01
#### **T-A-22** 示范调用mock server
- **产出**`apps/web/lib/api/chat.ts`(先用 MSW mock
- **API**
```ts
export const apiClient = {
chat: {
send: (consultationId: string | undefined, body: { message: string }) => Promise<ChatResponse>,
getHistory: (consultationId: string) => Promise<{ messages: Message[] }>,
}
};
```
- **验收**
- [ ] MSW handler 拦截 `/api/chat/send` 返回 mock
- [ ] `page.tsx` 临时接 apiClient.chat.send**不替换 useChat**,仅验证类型管道通)
- **估时**0.5d
- **依赖**T-A-21
- **约束**§0.1 R-NEW-3match 1-5 校验Zod schema `z.number().int().min(1).max(5)`
### A.8 CI 工作流1 任务1d
#### **T-A-23** web-ci.yml
- **产出**`.github/workflows/web-ci.yml`
- **步骤**
1. `pnpm install --frozen-lockfile`
2. `pnpm turbo run lint typecheck test --filter=@gaokao/* --filter=web`
3. `pnpm turbo run e2e --filter=web`
4. `pnpm turbo run build --filter=@gaokao/* --filter=web`
5. 上传 Codecov前端 target
- **验收**
- [ ] PR 触发后绿/红信号可见
- [ ] 总耗时 < 8 分钟
- [ ] bundle size > 200KB 时 PR 评论 warn
- **估时**1d
- **依赖**T-A-19, T-A-20, T-A-22
---
## 阶段 B · 真实后端对接35 任务38 人天)**[V2 扩展 +14 任务 / +14 人天]**
> **V2 关键扩展**5 大新模块Share Link / Data Query / Review / LLM / Poster需要在前端真实对接。
### B.1 后端 API 补全11 任务11d—— **V1 5 任务 → V2 11 任务**
#### **T-B-01** `POST /api/chat/send`V1 保留)
- **入参**`{message: string, consultation_id?: string, profile_snapshot?: object}`
- **出参**`{user_message: Message, assistant_message: Message, consultation_id: string}`
- **验收**
- [ ] OpenAPI schema 完整
- [ ] 与后端 `Consultation` / `Message` 模型对齐
- [ ] 错误码 E03001/03002/03003 覆盖
- **估时**1.5d
#### **T-B-02** `GET /api/chat/history?consultation_id=...`V1 保留)
- **出参**`{messages: Message[]}`
- **验收**
- [ ] 分页参数cursor支持
- [ ] auth必须登录或持有 consultation_id 的访问令牌
- **估时**0.5d
#### **T-B-03** `GET /api/consultations` / `GET /api/consultations/{id}` / `DELETE /api/consultations/{id}`V1 保留)
- **验收**
- [ ] 列表返回 `{consultations: [{id, title, updated_at, profile, has_plan, has_audit}]}`
- [ ] 详情返回完整 messages + profile + plan + audit
- [ ] DELETE 软删除 + 数据保留 30 天
- **估时**1d
#### **T-B-04** `GET /api/plans` / `GET /api/plans/{id}` / `PATCH /api/plans/{id}` / `DELETE /api/plans/{id}`V1 保留)
- **验收**
- [ ] 列表返回 `{plans: [{id, name, created_at, profile, distribution: {rush,stable,safe}}]}`
- [ ] PATCH 仅支持 name 修改
- [ ] DELETE 软删除
- **估时**1d
#### **T-B-05** `POST /api/assessment` / `POST /api/audit/upload`V1 保留)
- **audit/upload**multipart/form-dataExcel/Image/PDF/Paste
- **出参**`{report_id, overall_score, summary, risk_items, distribution, good_points}`
- **验收**
- [ ] 文件大小限制Excel 5MB / Image 10MB / PDF 10MB
- [ ] MIME 校验
- [ ] 解析后存 DB + 触发 AI 审核
- **估时**2d
#### **T-B-22** 🆕 `POST /api/share-link` —— Share Link 创建
- **入参**`{resource_type: "review_result" | "report", resource_id: string, expires_in_hours?: number}`
- **出参**`{code: string, url: string, qr_code_url?: string, expires_at: string}`
- **权限**:仅 `admin` 角色
- **验收**
- [ ] 鉴权 401/403 测试通过
- [ ] 与 `0145d66` 提交中的 test_share_link_api.py 一致
- [ ] 撤销后状态正确变更
- **估时**0.5d
- **依据**commit `0145d66` 已实现后端,前端需对接
#### **T-B-23** 🆕 `DELETE /api/share-link/{id}` —— Share Link 撤销
- **出参**`{ok: true, revoked_at: string}`
- **权限**:仅 `admin` 角色
- **验收**
- [ ] 撤销后 GET /api/share-link/latest 返回 404
- [ ] 撤销历史保留
- **估时**0.25d
#### **T-B-24** 🆕 `GET /api/portal/share-link/latest` —— 查询当前 portal 的最新分享链接
- **出参**`{code, url, expires_at, click_count}` 或 404
- **验收**
- [ ] 状态面板渲染依据test_share_status_panel.py
- **估时**0.25d
- **依据**commit `0145d66` 提到 test_share_status_panel.py 期望 status 页面渲染"当前分享状态"面板
#### **T-B-25** 🆕 `GET /api/share-link/{code}/stats` —— 分享统计
- **出参**`{click_count, view_count, conversion_count, last_clicked_at, device_breakdown}`
- **估时**0.5d
#### **T-B-26** 🆕 `GET /api/data-query/score-line` —— 分数线查询
- **入参**`{province, year, subject_type, score}`
- **出参**`{matches: [{university, major, year, min_score, max_score, avg_score}]}`
- **验收**
- [ ] 性能1 省 1 年 1 类目 < 200ms
- [ ] 缓存:相同 query 5min 命中
- **估时**0.5d
- **依据**commit `c5b0c3d` `/score-line-query` 端点已实现
#### **T-B-27** 🆕 `GET /api/data-query/rank-estimator` —— 位次估算
- **入参**`{province, year, subject_type, score}`
- **出参**`{rank: number, rank_range: [min, max], total_candidates: number}`
- **估时**0.5d
- **依据**`/rank-estimator` 端点已实现
#### **T-B-28** 🆕 `GET /api/data-query/majors` + `GET /api/data-query/schools` —— 专业/院校库
- **入参**`{keyword, category?, level?, page, page_size}`
- **出参**`{items: [...], total, page, page_size}`
- **验收**
- [ ] 分页 + 搜索 + 过滤
- [ ] 性能keyword 搜索 < 300ms
- **估时**0.5d
- **依据**`/majors-query` `/schools-query` 端点已实现
#### **T-B-29** 🆕 `POST /api/review/start` —— 启动复核
- **入参**`{plan_id, profile_snapshot}`
- **出参**`{review_id, status: "started", progress_url}`
- **验收**
- [ ] 异步触发 LLM 审核
- [ ] progress_url 可轮询
- **估时**0.5d
- **依据**commit `0145d66` 提到 `/review/start` 端点
#### **T-B-30** 🆕 `GET /api/review/{id}/status` —— 复核进度
- **出参**`{review_id, status, progress: 0-100, current_step, eta_seconds}`
- **估时**0.25d
#### **T-B-31** 🆕 `POST /api/review/action` —— 复核动作
- **入参**`{review_id, action: "approve" | "reject" | "revise", comment?}`
- **出参**`{ok: true, next_review_id?}`
- **估时**0.5d
- **依据**commit `0145d66` `/review/action` 端点
#### **T-B-32** 🆕 `GET /api/portal/{token}/cwb` —— 冲稳保建议
- **出参**`{rush: School[], stable: School[], safe: School[]}`
- **验收**
- [ ] 与 PlanCard 兼容(字段一致)
- [ ] 排序按概率降序
- **估时**0.5d
- **依据**commit `9b587a5` `/portal/{token}/cwb` 端点 + "有 token 时显示 cwb 按钮"
#### **T-B-33** 🆕 `GET /api/portal/{token}/full-plan` —— 完整规划页
- **出参**`{plan: Plan, profile, audit_report?, llm_enhancement?}`
- **验收**
- [ ] 含 LLM 增强commit `a3d8c73` "完整规划页 LLM 方案生成"
- **估时**0.5d
#### **T-B-34** 🆕 `POST /api/llm/audit-enhance` —— LLM 增强审核
- **入参**`{audit_report_id, enhancement_type: "summary" | "risk_explain" | "suggestion"}`
- **出参**`{enhanced_content: string, model_used: string, tokens_consumed: number}`
- **验收**
- [ ] 多模型 fallbackcommit `11fbb59` "多模型 fallback 支持"
- [ ] 超时 30s 降级
- **估时**1d
- **依据**commit `11fbb59` `a3d8c73` `43c1dbd` LLM 增强链路
#### **T-B-35** 🆕 `POST /api/poster/generate` —— 海报生成
- **入参**`{plan_id, template: "minimal" | "gradient" | "card", watermark?: string}`
- **出参**`{poster_id, image_url, download_url, expires_at}`
- **权限**:仅 `admin` 或 plan owner
- **验收**
- [ ] 与 `data/share/poster.py` CLI 行为一致
- [ ] 含 QR 码(链接到分享 link
- **估时**0.5d
- **依据**commit `a8b4927` 完整 poster 系统
### B.2 useChat / 业务 Hook 真实化8 任务9d—— **V1 4 任务 → V2 8 任务**
#### **T-B-12** 拆 useChat 编排层V1 保留)
- **产出**
- `useChat.ts` 改为纯编排(无 mock 数据)
- mock 数据移到 `apps/web/__mocks__/chat-fixtures.ts`(仅 B 阶段测试用)
- **验收**
- [ ] useChat.ts < 300 行
- [ ] `__mocks__/chat-fixtures.ts` 包含:广东省物理 620、广东省历史 580、河北省物理 600 共 3 套 mock
- **估时**1.5d
- **依赖**T-B-01 ~ T-B-05API 已就位)
- **约束**§0.1 R-NEW-1
#### **T-B-13** 真实 sendMessage + typing 动画V1 保留)
- **产出**mutation + optimistic update
- **验收**
- [ ] e2e `chat-send.spec.ts`:输入消息 → 1s 内出现用户气泡 → 3s 内出现 AI 回复
- [ ] 失败时乐观更新回滚 + Toast 提示
- [ ] typing 动画 (`page.tsx:173-186`) 保留
- **估时**1d
- **依赖**T-B-12
- **约束**§1.3(消息路由模式)
#### **T-B-14** 真实 getHistory + 滚动恢复V1 保留)
- **产出**consultation 切换时 fetch 历史
- **验收**
- [ ] 切换 consultation_id → 加载历史消息
- [ ] 自动滚动到底部(`messagesEndRef`
- [ ] 加载中显示 Skeleton用 T-D-09 阶段组件)
- **估时**1d
- **依赖**T-B-13
#### **T-B-15** usePlan / useConsultation 真实化 + localStorage 兼容V1 保留)
- **产出**
- 删除 `useChat.ts` 中 `savePlan` 的 localStorage 写
- 改用 `apiClient.plans.create(...)` mutation
- **保留** localStorage `consultationRecords` / `activeConsultationId` key 名作为离线 fallback**R-NEW-2 应对**
- **验收**
- [ ] 真实保存方案 → DB 可见
- [ ] 断网时本地仍可见上次同步数据
- [ ] 联网后自动 revalidateTanStack Query 默认行为)
- **估时**1.5d
- **依赖**T-B-04, T-B-05
- **约束**§0.1 R-NEW-2保留 key 名兼容)
#### **T-B-36** 🆕 useShareLink Hook
- **产出**`useShareLink(resourceType, resourceId)` 返回 `{shareLink, create, revoke, refresh}`
- **API**
- `create()` → `POST /api/share-link`
- `revoke()` → `DELETE /api/share-link/{id}`
- `refresh()` → `GET /api/portal/share-link/latest`
- **验收**
- [ ] 创建成功 → 立即显示链接 + QR 码
- [ ] 撤销后 UI 显示"已撤销"
- [ ] 失败时 Toast + 表单不重置
- **估时**1d
- **依赖**T-B-22, T-B-23, T-B-24
#### **T-B-37** 🆕 useDataQuery Hook4 个独立 hook
- **产出**
- `useScoreLineQuery({province, year, subject_type, score})` → 返回 `matches[]`
- `useRankEstimator({province, year, subject_type, score})` → 返回 `rank`
- `useMajorsQuery({keyword, page})` → 返回 `items[] + pagination`
- `useSchoolsQuery({keyword, page})` → 同上
- **验收**
- [ ] 4 个 hook 独立缓存staleTime 5min
- [ ] 相同 query 命中缓存
- [ ] 错误时降级到 localStorage 缓存
- **估时**1.5d
- **依赖**T-B-26, T-B-27, T-B-28
#### **T-B-38** 🆕 useReview Hook
- **产出**`useReview(reviewId)` 返回 `{status, progress, currentStep, etaSeconds, start, action}`
- **API**
- `start()` → `POST /api/review/start`
- `poll()` → `GET /api/review/{id}/status`(每 2s 轮询)
- `action(action, comment?)` → `POST /api/review/action`
- **验收**
- [ ] SSE 优先;不支持 SSE 时降级轮询
- [ ] progress 100% → 跳转结果页
- [ ] 失败时 Toast + 重试
- **估时**1.5d
- **依赖**T-B-29, T-B-30, T-B-31
#### **T-B-39** 🆕 usePoster Hook
- **产出**`usePoster(planId)` 返回 `{posterUrl, generate, download}`
- **验收**
- [ ] 生成进度显示5-10s
- [ ] 下载为 PNG
- [ ] watermark 可选
- **估时**0.5d
- **依赖**T-B-35
### B.3 useProfile / 表单 / 错误处理7 任务7d—— **V1 6 任务 → V2 7 任务**
#### **T-B-16** 真实 useProfileV1 保留)
- **产出**`GET /api/profile` 拉取,表单提交用 `PATCH /api/profile`
- **验收**
- [ ] FormCard 提交后立即看到进度条InfoCollectionProgress填充
- [ ] 失败时回滚 + 错误提示
- **估时**1d
- **依赖**T-B-15
#### **T-B-17** 真实 useAuditV1 保留 + LLM 增强)
- **产出**`POST /api/audit/upload` multipart + LLM 增强回调
- **验收**
- [ ] 4 种文件类型Excel/Image/PDF/Paste全部走真实 API
- [ ] 进度条(上传 + AI 处理)显示
- [ ] 错误码 E04001上游 AI 失败)→ Toast 重试
- [ ] LLM 增强(`/api/llm/audit-enhance`)异步触发,结果追加到 report
- **估时**1.5d
- **依赖**T-B-05, T-B-34
#### **T-B-18** 错误码 → 用户文案映射V1 保留)
- **产出**`packages/i18n/zh-CN/errors.json`
- **示例**
```json
{
"E03001": "信息验证失败,请检查输入",
"E03002": "数据未找到",
"E03003": "保存失败,请重试",
"E04001": "AI 服务暂时不可用,请稍后重试",
"E04002": "请求超时,请重试",
"E05001": "系统错误,我们已记录"
}
```
- **验收**
- [ ] 15 个错误码全覆盖
- [ ] api-client 拦截器统一处理
- **估时**0.5d
- **依赖**T-B-13
- **约束**:沿用 `admin/errors/registry.py` 5 字段结构
#### **T-B-19** ErrorBoundary 兜底页V1 保留)
- **产出**`apps/web/app/error.tsx`Next 16 error boundary
- **验收**
- [ ] 5xx 错误时显示兜底页("出错了,刷新重试"
- [ ] Sentry 上报
- **估时**0.5d
- **依赖**T-B-18
#### **T-B-20** 离线检测 + 提示V1 保留)
- **产出**`useOnlineStatus` hook + 顶部黄条提示
- **验收**
- [ ] offline → 顶部条 + 写操作禁用
- [ ] online 恢复 → 自动重试 pending mutations
- **估时**1d
#### **T-B-21** 表单提交防重复V1 保留)
- **产出**:所有 mutation 加 `isPending` 状态
- **验收**
- [ ] FormCard 提交按钮在 isPending 时禁用 + 旋转图标
- [ ] ChatMessage 的修复按钮单次点击后禁用
- **估时**0.5d
#### **T-B-40** 🆕 Share Link 状态面板数据
- **产出**`useShareStatusPanel(resourceId)` → 返回 `{currentLink, clickCount, viewCount, daysUntilExpiry}`
- **API**`GET /api/portal/share-link/latest` + `GET /api/share-link/{code}/stats`
- **验收**
- [ ] test_share_status_panel.py 期望"当前分享状态"面板渲染
- [ ] 30s 自动刷新
- **估时**0.5d
- **依据**commit `0145d66` 提到 test_share_status_panel.py 期望但当前未通过
### B.4 离线缓存 + e2e + 性能9 任务9d—— **V1 6 任务 → V2 9 任务**
#### **T-B-22** TanStack Query 持久化V1 保留)
- **产出**`@tanstack/query-persist-client-core` + localStorage
- **验收**
- [ ] 关闭浏览器再打开 → 历史消息立即可见
- [ ] 后台 revalidate 后更新
- **估时**1d
- **依赖**T-B-13
#### **T-B-23** e2e 真实化8 个关键路径)—— **V1 5 → V2 8**
- **产出**
- `chat-send.spec.ts` 真实发消息
- `chat-history.spec.ts` 切换 consultation
- `plan-save.spec.ts` 保存方案
- `audit-upload.spec.ts` 上传文件
- `theme-persist.spec.ts` 主题持久化
- **🆕 `share-link.spec.ts`** 创建/撤销/分享 UI
- **🆕 `data-query.spec.ts`** 4 个查询页
- **🆕 `review-flow.spec.ts`** 复核全流程
- **验收**
- [ ] 8 个 spec 全绿
- [ ] 每个 spec 含 1 个失败场景
- **估时**3d
- **依赖**T-B-13, T-B-15, T-B-17, T-B-36, T-B-37, T-B-38
#### **T-B-24** Lighthouse CI 集成V1 保留 + 新页面)
- **产出**`lighthouserc.json` + GitHub Action
- **预算**
- LCP < 2.5s
- INP < 200ms
- CLS < 0.1
- Performance ≥ 90
- Accessibility ≥ 95
- Best Practices ≥ 95
- SEO ≥ 90
- **覆盖页面**/ /consultations /plans /plans/compare /assessment **🆕 /score-line-query /rank-estimator /majors-query /schools-query /review/start /admin/login /admin**
- **验收**
- [ ] 12 个页面 P75 ≥ 预算
- [ ] PR 评论显示分数
- **估时**1.5d
- **依赖**T-B-23
#### **T-B-25** Bundle 优化V1 保留)
- **产出**
- `next/dynamic` 异步加载 PlanCard / AuditReportCard / CareerCard
- `react-markdown` 异步 chunk
- 拆 vendor chunk
- **验收**
- [ ] First load JS < 200KB
- [ ] PlanCard 异步 chunk < 50KB
- **估时**1d
#### **T-B-26** 路由级 prefetchV1 保留)
- **产出**`<Link prefetch>` 关键路径
- **验收**
- [ ] hover Sidebar /plans → 100ms 内开始预取
- **估时**0.5d
#### **T-B-27** 真实后端回归V1 保留)
- **产出**:完整 e2e 套件在真实后端跑通
- **验收**
- [ ] 15+ e2e spec 全绿
- [ ] 跨 3 浏览器chromium / webkit / firefox通过
- **估时**0.5d
- **依赖**T-B-23 ~ T-B-26
#### **T-B-41** 🆕 ShareLink 失败降级
- **产出**
- `navigator.share` 不可用时降级到 `clipboard.writeText`
- clipboard 不可用时降级到 `<a download>` 文本文件
- **验收**
- [ ] 3 路径全部测试通过
- [ ] 用户看到明确提示
- **估时**0.5d
- **依据**commit `0145d66` "失败时显示具体错误,不再静默"
#### **T-B-42** 🆕 LLM 增强进度轮询
- **产出**
- `useLLMEnhancement` hook + SSE 优先
- 长任务(>30s显示进度条
- 失败时降级到基础审核结果
- **验收**
- [ ] SSE 连接断开时自动重连(最多 3 次)
- [ ] 降级时显示"AI 增强暂不可用,已展示基础结果"
- **估时**1d
- **依据**commit `11fbb59` "多模型 fallback 支持"
#### **T-B-43** 🆕 Poster 异步生成 + 轮询
- **产出**
- `usePoster` + 进度条
- 生成完成自动下载(可选)
- 失败时重试 + Toast
- **验收**
- [ ] 5-10s 内完成
- [ ] 失败可重试
- [ ] 长任务不阻塞 UI
- **估时**0.5d
- **依据**commit `a8b4927` poster 系统
---
## 阶段 C · 架构整合15 任务10 人天)**[V2 扩展 +2 任务 / +1 人天]**
### C.1 部署架构5 任务3d—— **V1 保留**
#### **T-C-01** 选部署平台
- **决策点**CloudStudio / Vercel / 自托管
- **默认**CloudStudio项目已有先例
- **验收**
- [ ] 决策文档写入 `docs/DEPLOY_DECISION.md`
- **估时**0.25d
#### **T-C-02** DNS + 域名
- **产出**`web.gaokao.example.com` / `api.gaokao.example.com`
- **验收**
- [ ] HTTPS 证书自动续签Let's Encrypt
- **估时**0.5d
#### **T-C-03** 反代配置
- **产出**nginx / caddy 配置
- `web.gaokao.example.com` → Next.js 静态产物
- `api.gaokao.example.com` → FastAPI
- `/api/*` → 转发到 FastAPI
- **验收**
- [ ] 单一域名访问前端,浏览器无 CORS 报错
- **估时**1d
#### **T-C-04** CORS 配置
- **产出**FastAPI `CORSMiddleware` 白名单 `["https://web.gaokao.example.com"]`
- **验收**
- [ ] OPTIONS 预检通过
- [ ] 带 cookie 时白名单明确
- **估时**0.25d
#### **T-C-05** CSP / HSTS / 安全响应头
- **产出**`secure_headers` 中间件
- **验收**
- [ ] `Strict-Transport-Security: max-age=63072000; includeSubDomains`
- [ ] `X-Content-Type-Options: nosniff`
- [ ] `X-Frame-Options: DENY`
- [ ] `Content-Security-Policy: default-src 'self'; img-src 'self' data:; style-src 'self' 'unsafe-inline'; ...`
- [ ] `Referrer-Policy: strict-origin-when-cross-origin`
- **估时**1d
- **依赖**T-C-04
### C.2 监控4 任务2d—— **V1 保留**
#### **T-C-06** Sentry 前端
- **产出**`@sentry/nextjs` 集成
- **验收**
- [ ] 错误 100% 上报
- [ ] Performance trace 包含路由切换
- [ ] PII 脱敏(用户消息不含姓名/手机号)
- **估时**1d
#### **T-C-07** Web Vitals 上报
- **产出**`next/web-vitals` + 自托管 endpoint
- **验收**
- [ ] LCP / INP / CLS / FID / TTFB 全部上报
- [ ] 75 分位数存储到 Prometheus
- **估时**0.5d
#### **T-C-08** trace 透传
- **产出**`x-trace-id` header 前后端贯通
- **验收**
- [ ] 前端请求带 trace id
- [ ] 后端日志 / Sentry 关联到同一 trace
- **估时**0.5d
#### **T-C-09** 告警规则
- **产出**3 条告警(错误率 > 1% / API P95 > 1s / Web Vitals P75 跌破预算)
- **验收**
- [ ] Slack / 钉钉 webhook 接收
- **估时**0d仅配置
### C.3 文档 + 收口4 任务4d—— **V1 保留**
#### **T-C-10** 部署文档
- **产出**`docs/DEPLOY.md`(含 CloudStudio / 自托管 / Vercel 三种路径)
- **估时**1d
#### **T-C-11** 运维 Runbook
- **产出**`docs/RUNBOOK.md`(常见故障处理)
- **估时**1d
#### **T-C-12** 安全审计
- **产出**`docs/SECURITY_AUDIT_2026-XX.md`OWASP top 10 自查)
- **估时**1d
#### **T-C-13** 灰度发布流程
- **产出**5% → 20% → 100% 三步灰度
- **估时**1d
### C.4 🆕 Poster CLI 集成V2 新增1 任务1d
#### **T-C-44** 🆕 Poster CLI 部署集成
- **产出**
- `scripts/gaokao-poster` 部署到 cron每日 02:00 自动生成)
- 产物上传到 CDN
- 失败告警
- **验收**
- [ ] crontab 配置生效
- [ ] 失败时 Sentry 告警
- [ ] 日志可查
- **估时**1d
- **依据**commit `a8b4927` 引入 poster CLI
#### **T-C-45** 🆕 集成测试套件
- **产出**`scripts/integration_test.py` 前端版本FastAPI + Next.js 双服务)
- **验收**
- [ ] 端到端 5 个关键场景
- [ ] CI 卡点
- **估时**0d与 T-A-23 共用 CI
- **依据**commit `a8b4927` 新增 integration_test.py
---
## 阶段 D · 设计 / a11y 加固24 任务14 人天)**[V2 扩展 +6 任务 / +3 人天]**
### D.1 基础组件补齐10 任务4d—— **V1 保留**
| 任务 | 组件 | 估时 | 验收 |
|---|---|---|---|
| **T-D-01** | Dialog | 0.5d | 用 portal 渲染 + 焦点陷阱 + ESC 关闭 + 点击外部关闭 |
| **T-D-02** | Toast | 0.5d | success/error/info/warn 4 种 + 自动消失 + 队列管理 |
| **T-D-03** | Tooltip | 0.25d | hover 200ms 显示3s 自动消失 |
| **T-D-04** | Dropdown | 0.5d | Sidebar 头像菜单用,键盘导航 |
| **T-D-05** | Avatar | 0.25d | AI / User / 群组 3 套 |
| **T-D-06** | Skeleton | 0.25d | 4 种形状text/card/circle/avatar |
| **T-D-07** | ProgressBar | 0.25d | 通用(区别于 InfoCollectionProgress |
| **T-D-08** | Switch | 0.25d | 偏好设置用 |
| **T-D-09** | Checkbox | 0.5d | FormCard 选科用 |
| **T-D-10** | Radio | 0.5d | 独立于 ThemeToggleFormCard 单选用 |
### D.2 a11y 全量审计3 任务2d—— **V1 保留**
#### **T-D-11** axe-core 集成
- **产出**`@axe-core/playwright` + **5 → 12 个页面**自动扫描
- **验收**
- [ ] 0 critical / 0 serious 违规
- [ ] CI 卡点PR 触发)
- **估时**0.5d
#### **T-D-12** 屏幕阅读器 + 键盘测试
- **产出**:测试报告 `docs/A11Y_TEST_2026-XX.md`
- **覆盖**
- [ ] NVDA 朗读 / 方案卡 / 审核卡
- [ ] VoiceOver 移动端测试
- [ ] Tab 顺序Sidebar → Main → Quick prompts → Upload → Input → Send
- [ ] Skip link 工作
- **估时**1d
#### **T-D-13** 替换 alert() 为 Toast**R-NEW-4 应对**
- **产出**
- `plans/[id]/page.tsx:143,152` 的 alert 替换为 Toast
- 异步触发下载(`URL.createObjectURL` + `<a download>`
- **验收**
- [ ] 导出图片 / PDF 真实下载
- [ ] Toast 提示"已导出方案 / 导出失败"
- **估时**0.5d
- **依赖**T-D-02
### D.3 🆕 业务组件扩展V2 新增6 任务4d
#### **T-D-14** 🆕 SharePanel 组件
- **产出**`packages/ui/components/SharePanel.tsx`
- **API**`<SharePanel resourceType resourceId />` —— 包含创建按钮、链接展示、QR 码、复制、撤销
- **验收**
- [ ] 复用 T-B-36 useShareLink
- [ ] 状态:未创建 / 已创建 / 已撤销 / 已过期
- [ ] 视觉与原型一致(沿用 Card + Badge
- [ ] Vitest 4 个状态全覆盖
- **估时**0.75d
- **依赖**T-B-36, T-D-11, T-D-12
#### **T-D-15** 🆕 ShareStatusPanel 组件
- **产出**`packages/ui/components/ShareStatusPanel.tsx`
- **API**`<ShareStatusPanel resourceId />` —— 显示当前分享状态 + 点击量 + 转化率
- **验收**
- [ ] 复用 T-B-40 useShareStatusPanel
- [ ] 30s 自动刷新
- [ ] test_share_status_panel.py 通过
- **估时**0.5d
- **依据**commit `0145d66` 提到 test_share_status_panel.py 期望但当前未通过
#### **T-D-16** 🆕 DataQueryForm 组件4 个变体)
- **产出**
- `ScoreLineQueryForm` —— 省份/年份/选科/分数输入
- `RankEstimatorForm`
- `MajorsQueryForm` —— 关键词 + 分类 + 页码
- `SchoolsQueryForm`
- **共用**`packages/ui/components/forms/QueryForm.tsx`(抽象基类)
- **验收**
- [ ] 4 个 form 复用同一 QueryForm 框架
- [ ] Vitest 覆盖:输入验证 / 提交 / 错误展示
- **估时**1d
- **依赖**T-B-37
#### **T-D-17** 🆕 DataQueryResult 组件4 个变体)
- **产出**
- `ScoreLineResult` —— 表格 + 分数段分布图
- `RankEstimatorResult` —— 大数字展示 + 历史趋势
- `MajorsResult` —— 列表 + 分类
- `SchoolsResult` —— 列表 + 985/211 标签
- **共用**`QueryResult` 框架loading / empty / error / data 4 态)
- **验收**
- [ ] 4 态切换动画
- [ ] 与原型视觉一致
- **估时**1d
- **依赖**T-D-16
#### **T-D-18** 🆕 ReviewFlow 组件
- **产出**`packages/ui/components/ReviewFlow.tsx`
- **API**`<ReviewFlow planId />` —— stepper 显示 + 进度条 + 结果跳转
- **状态机**`idle → started → analyzing → completed | failed | revision_needed`
- **验收**
- [ ] 复用 T-B-38 useReview
- [ ] 进度条实时更新
- [ ] 失败可重试
- **估时**0.5d
- **依赖**T-B-38
#### **T-D-19** 🆕 LLMEnhancement 组件
- **产出**`packages/ui/components/LLMEnhancement.tsx`
- **API**`<LLMEnhancement auditReportId type />` —— AI 增强摘要 / 风险解释 / 建议
- **验收**
- [ ] 异步加载(不阻塞主审核结果)
- [ ] 失败时降级到基础内容
- [ ] 显示"由 XXX 模型生成"标注
- **估时**0.5d
- **依赖**T-B-34, T-B-42
#### **T-D-20** 🆕 PosterPreview 组件
- **产出**`packages/ui/components/PosterPreview.tsx`
- **API**`<PosterPreview planId template />`
- **验收**
- [ ] 3 种模板切换
- [ ] 实时预览
- [ ] 下载按钮
- **估时**0.5d
- **依赖**T-B-43
### D.4 暗色主题全覆盖1 任务1.5d)—— **V1 保留**
#### **T-D-14**(保留 V1 编号 T-D-14暗色变体审计
- **产出**:每个组件 dark 变体
- **验收**
- [ ] 18+ 组件都有 dark story含 V2 新增 7 个)
- [ ] 视觉切换无白边/无对比度 < 4.5:1
- [ ] 风险徽章 / 概率条 / 模式指示器 暗色下语义色保持
- **估时**1.5d
- **依赖**T-D-01 ~ T-D-10, T-D-14(新) ~ T-D-20(新)
> **注**D.3 占用 T-D-14 ~ T-D-20 编号D.4 改为 T-D-21。
#### **T-D-21** 暗色变体审计
- 同 V1 T-D-14 内容
- **依赖**T-D-01 ~ T-D-10, T-D-14 ~ T-D-20
### D.5 国际化基础2 任务2d—— **V1 保留 + 新增词条**
#### **T-D-15**(改为 T-D-22next-intl 接入
- **产出**
- `packages/i18n/zh-CN/{chat,plans,common,errors,share,dataQuery,review,poster}.json`
- `packages/i18n/en-US/{...}.json`(占位空字典)
- 路由级 locale 切换
- **验收**
- [ ] 所有硬编码中文移到词条
- [ ] 切到 en-US 显示 key 而非中文(占位)
- **估时**1.5d
- **依赖**T-B-18
- **约束**§0.1 R-NEW-5quickPrompts 三态文案抽到 `chat.json`
#### **T-D-23** 文案审计
- **产出**i18n key 命名规范文档
- **验收**
- [ ] `git grep "[\u4e00-\u9fff]"` 在 `apps/web/src/` 仅命中 `i18n/` 目录
- **估时**0.5d
- **依赖**T-D-22
### D.6 性能 + 视觉回归2 任务1.5d)—— **V1 保留**
#### **T-D-24** Chromatic + Lighthouse合并 V1 T-D-17 + T-D-18
- **产出**
- Chromatic 所有 Storybook stories
- Lighthouse CI
- 路由级 `loading.tsx`
- `next/image` / `next/font` 优化
- **验收**
- [ ] 50+ stories baselineV2 增量)
- [ ] LCP P75 < 1.8s
- [ ] Bundle < 150KB
- **估时**1.5d
---
## 阶段 E · 内部页面 React 化24 任务19 人天)**[V2 扩展 +8 任务 / +2 人天]**
### E.1 运营后台基础5 任务5d—— **V1 4 任务 → V2 5 任务**
| 任务 | 页面 | 估时 | 验收 |
|---|---|---|---|
| **T-E-01** | 登录页 `/admin/login` | 0.5d | 复用 T-A-09 Button + T-A-10 Input调 `POST /api/admin/auth/login` + URL token 支持commit `2af1d06` |
| **T-E-02** | Dashboard `/admin` | 1.5d | echarts 集成(订单/咨询趋势) + 4 个 KPI 卡片 + URL token 自动认证commit `0ec5bdf` |
| **T-E-03** | Layout `/admin` shared | 1d | 顶部 nav + 侧边栏 + 暗色支持 |
| **T-E-04** | 错误兜底 `/admin/error.tsx` | 0.5d | 同 T-B-19 |
| **T-E-05** | 权限守卫 | 0.5d | 未登录跳 /admin/login |
### E.2 订单 + 案例4 任务4d—— **V1 保留**
| 任务 | 页面 | 估时 |
|---|---|---|
| **T-E-06** | 订单列表 `/admin/orders` | 1d |
| **T-E-07** | 订单详情 `/admin/orders/{id}` | 1.5d |
| **T-E-08** | 案例列表 `/admin/cases` | 0.75d |
| **T-E-09** | 案例详情 `/admin/cases/{id}` | 0.75d |
### E.3 Share Link 管理(🆕 V2 新增3 任务3d
| 任务 | 页面 | 估时 | 验收 |
|---|---|---|---|
| **T-E-10** 🆕 | Share Link 列表 `/admin/share-links` | 1d | 调用 `GET /api/share-link`(待后端补全)+ 撤销按钮 + 过期筛选 |
| **T-E-11** 🆕 | Share Link 详情 `/admin/share-links/{code}/stats` | 1d | 点击量 / 转化率 / 设备分布 + 时序图 |
| **T-E-12** 🆕 | Poster 管理 `/admin/posters` | 1d | 复用 T-B-43 usePoster + T-D-20 PosterPreview + 模板选择 |
### E.4 Data Query 内部页(🆕 V2 新增4 任务4d
| 任务 | 页面 | 估时 | 验收 |
|---|---|---|---|
| **T-E-13** 🆕 | 分数线查询 `/admin/data-query/score-line` | 1d | 复用 T-D-16 ScoreLineQueryForm + T-D-17 ScoreLineResult |
| **T-E-14** 🆕 | 位次估算 `/admin/data-query/rank-estimator` | 0.75d | 复用 T-D-16 + T-D-17 |
| **T-E-15** 🆕 | 专业库 `/admin/data-query/majors` | 1d | 复用 T-D-16 + T-D-17 + 分类树 |
| **T-E-16** 🆕 | 院校库 `/admin/data-query/schools` | 1.25d | 复用 T-D-16 + T-D-17 + 985/211 筛选 |
### E.5 Review 内部页(🆕 V2 新增2 任务2d
| 任务 | 页面 | 估时 | 验收 |
|---|---|---|---|
| **T-E-17** 🆕 | 复核 Dashboard `/admin/review` | 1.25d | 待复核列表 + LLM 增强结果 + action 按钮approve / reject / revise|
| **T-E-18** 🆕 | LLM 审计日志 `/admin/review/llm-logs` | 0.75d | 模型使用统计 + token 消耗 + fallback 触发次数 |
### E.6 Policy 内部页(🆕 V2 新增1 任务1d
#### **T-E-19** 🆕 Policy 中心 `/admin/policies`
- **产出**
- 5 个政策页面 editorprivacy / service-terms / policy-center / same-score / deletion-policy
- 草稿/发布两态
- Markdown 编辑器
- **估时**1d
- **依据**commit `c5b0c3d` `818bfa4` 5 个政策页面已实现后端
### E.7 通知 + 设置4 任务4d—— **V1 保留**
| 任务 | 页面 | 估时 |
|---|---|---|
| **T-E-20** | 通知列表 `/admin/notifications` | 1d |
| **T-E-21** | 通知模板编辑 | 1.5d |
| **T-E-22** | 系统设置 `/admin/settings` | 1.5d |
| **T-E-23** | 用户管理 `/admin/users` | 1d |
### E.8 公共门户 React 化(🆕 V2 新增1 任务1d
#### **T-E-24** 🆕 公共门户 React 化
- **产出**
- `/pricing` 定价页
- `/portal/{token}/info` 资料向导
- `/portal/{token}/status` 状态页
- `/portal/{token}/report` 报告查看
- `/portal/{token}/cwb` 冲稳保建议
- `/portal/{token}/full-plan` 完整规划
- `/portal/{token}/notifications` 通知
- `/portal/{token}/deletion-request` 删除请求
- `/portal/payment-return` 支付回跳
- `/s/{code}` 短链接分享
- **复用**:所有 portal 页用 `packages/ui/` + `packages/api-client/` + `packages/hooks/`
- **验收**
- [ ] 与 `admin/static/portal-ui.css` 视觉一致
- [ ] 全 8 个 portal 流程跑通
- **估时**1d
- **依据**V1 报告 E 阶段未涉及,但 `web_public.py` 已实现 8+ portal 路由
---
## 2. 完整验收矩阵 V2
### 2.1 UI/交互完全遵循新设计(**Self-Review #1**
| 检查项 | 工具 | 通过标准 |
|---|---|---|
| **Chromatic 视觉回归** | Chromatic | 0 story 像素 diff > 0.1%50+ stories |
| **设计 token 一致性** | 自定义 lint | `apps/web/src/` 无硬编码颜色 |
| **三态主题切换无闪白** | Playwright `theme.spec.ts` | refresh 后 100ms 内正确 |
| **移动端断点** | Playwright | 768 / 1024 两断点 1:1 一致 |
| **WCAG 2.1 AA** | axe-core | 0 critical / 0 serious / < 3 moderate12 个页面) |
| **键盘导航** | Playwright + 手动 | Tab 顺序合理Enter / Space 触发 |
| **屏幕阅读器** | NVDA + VoiceOver | 4 模式指示器 / PlanCard / AuditReport / SharePanel / DataQuery 全部合理 |
| **8 项硬约束** | 单元测试 | 全部通过T-A-15 ~ T-A-20 |
### 2.2 所有的功能都能完整实现(**Self-Review #2**
| 模块 | 功能 | 任务 |
|---|---|---|
| **对话** | 发消息 / 收 AI 回复 / typing / 三态提示 | T-B-13, T-B-14 |
| **方案生成** | AI 推方案 / 三 Tab / 风险徽章 / 概率条 | T-A-13, T-B-12 |
| **方案保存** | 保存 / 重命名 / 删除 / 列表 / 详情 | T-B-15 |
| **方案对比** | 选 2 个 / 维度表 / 差异高亮 | V1 沿用 |
| **方案导出** | 图片 / PDF | T-D-13 |
| **方案审核** | 上传 / 风险项 / 冲稳保 / 良好项 / 一键修复 / **🆕 LLM 增强** | T-B-17, T-B-34, T-D-19 |
| **咨询记录** | 列表 / 搜索 / 删除 / 恢复 | T-B-15 |
| **兴趣测评** | Holland RIAS 10 题 | T-B-01 |
| **表单分步** | basic → subjects → prefs 守卫 | T-A-17, T-B-16 |
| **文件上传** | 4 模式Excel/Image/PDF/Paste | T-B-17 |
| **主题切换** | 三态 + 持久化 + 闪白 | T-A-07, T-A-19 |
| **响应式** | Sidebar / MobileNav | T-A-20 |
| **🆕 Share Link** | 创建 / 撤销 / 复制 / QR / 状态面板 | T-B-22~T-B-25, T-B-36, T-B-40, T-D-14, T-D-15, T-E-10, T-E-11 |
| **🆕 Data Query** | 分数线 / 位次 / 专业 / 院校 4 查询 | T-B-26~T-B-28, T-B-37, T-D-16, T-D-17, T-E-13~T-E-16 |
| **🆕 Review Flow** | 启动 / 进度 / 结果 / action | T-B-29~T-B-31, T-B-38, T-D-18, T-E-17 |
| **🆕 LLM 增强** | 摘要 / 风险解释 / 建议 + 多模型 fallback | T-B-34, T-B-42, T-D-19, T-E-18 |
| **🆕 Poster** | 3 模板 + 异步生成 + 下载 | T-B-35, T-B-39, T-D-20, T-E-12 |
| **🆕 Policy 中心** | 5 政策页 editor | T-E-19 |
| **🆕 公共门户** | 8 个 portal 流程 | T-E-24 |
| **a11y / i18n / 错误 / 离线** | 沿用 V1 | T-D-11 ~ T-D-13, T-D-22, T-B-18~T-B-21 |
### 2.3 与后端集成正常(**Self-Review #3**
| 集成点 | API | 任务 |
|---|---|---|
| **登录** | `POST /api/admin/auth/login` + URL token | T-E-01 |
| **对话** | `POST /api/chat/send` + `GET /api/chat/history` | T-B-01, T-B-02 |
| **profile** | `GET / PATCH /api/profile` | T-B-16 |
| **方案** | `CRUD /api/plans` | T-B-04, T-B-15 |
| **咨询** | `CRUD /api/consultations` | T-B-03, T-B-15 |
| **审核上传** | `POST /api/audit/upload` | T-B-05, T-B-17 |
| **🆕 Share Link** | `POST/DELETE /api/share-link` + `GET latest` + `GET stats` | T-B-22~T-B-25 |
| **🆕 Data Query** | 4 个 query 端点 | T-B-26~T-B-28 |
| **🆕 Review** | `/review/start` `/status` `/action` | T-B-29~T-B-31 |
| **🆕 冲稳保** | `/portal/{token}/cwb` | T-B-32 |
| **🆕 完整规划** | `/portal/{token}/full-plan` | T-B-33 |
| **🆕 LLM 增强** | `/api/llm/audit-enhance` | T-B-34, T-B-42 |
| **🆕 Poster** | `/api/poster/generate` | T-B-35, T-B-43 |
| **错误码** | registry 5 字段 | T-B-18 |
| **CORS** | 白名单 | T-C-04 |
| **trace 贯通** | `x-trace-id` | T-C-08 |
| **Sentry** | 前后端 | T-C-06, T-C-08 |
---
## 3. 风险与缓解 V2增量
| ID | 风险 | 缓解 |
|---|---|---|
| R-NEW-1 | useChat 编排层耦合 mock | T-B-12 解耦 |
| R-NEW-2 | localStorage key 兼容 | T-B-15 保留 key 名 |
| R-NEW-3 | CareerCard match 字段无校验 | T-A-22 Zod |
| R-NEW-4 | alert() 阻塞 | T-D-13 Toast |
| R-NEW-5 | quickPrompts 硬编码 | T-D-22 i18n |
| **R-NEW-6** 🆕 | **后端新模块 API 可能未稳定**share-link / data-query 仍有 commit 修改) | T-A-21 OpenAPI Codegen 每天跑 + T-C-44 集成测试兜底 |
| **R-NEW-7** 🆕 | **LLM 增强 30s 超时降级** | T-B-42 显式降级路径 |
| **R-NEW-8** 🆕 | **Poster CLI 部署依赖系统库**libpango / libharfbuzz | T-C-44 Docker 化 |
| **R-NEW-9** 🆕 | **公共门户 8 流程视觉一致性**(沿用 portal-ui.css | T-E-24 视觉回归 + 端到端 e2e |
| **R-NEW-10** 🆕 | **Share Link QR 码**(前端需 qrcode.react 库) | T-A-09 之后单独 spike 1d |
| R-V2-1 | 真实 API 与 mock 不一致 | T-A-21 Codegen |
| R-V2-2 | Next 16 + React 19 + TanStack Query 兼容性 | T-A-22 spike |
| R-V2-3 | Bundle 爆炸 | T-B-25 异步 chunk |
| R-V2-4 | 老用户数据迁移 | T-B-15 保留 key |
| R-V2-5 | ChatMessage 路由扩展性 | T-B-13 拆 useChat |
---
## 4. 工时总览 V2
| 阶段 | 任务数 | 估时(人天) | V1 → V2 增量 |
|---|---|---|---|
| A. 基础设施 | 23 | 11 | 0 |
| B. 真实后端对接 | 35 | 38 | +1421→35 |
| C. 架构整合 | 15 | 10 | +113→15 |
| D. 设计/a11y 加固 | 24 | 14 | +318→24 |
| E. 内部页面 React 化 | 24 | 19 | +216→24 |
| **总计** | **136** | **92** | **+45 / +14** |
---
## 5. 立即可执行本周启动5 任务4.5d
> 仍按 V1 路径启动,因为 `前端原型代码/` 未变:
1. **T-A-01**0.5d)→ 创建 monorepo
2. **T-A-02**0.5d)→ 收编前端原型代码
3. **T-A-06 + T-A-07**1d→ 设计系统提取
4. **T-A-21**1d→ OpenAPI Codegen 接入(**现在会生成 30+ 端点的类型**,比 V1 预想多)
5. **T-A-23**1.5d)→ CI 工作流
**5 任务完成后**,进入 T-A-04tsconfig 共享)+ T-A-14Vitest+ T-A-18Playwright构成 A 阶段前半段。
---
## 6. Self-Review 闭环 V2
| Self-Review 目标 | 验证产物 | 状态 |
|---|---|---|
| **UI/交互完全遵循新设计** | Chromatic + axe + 8 项硬约束单测 | **任务化** §2.1 |
| **所有的功能都能完整实现** | 16 → **21 模块**功能V1 +5 新模块) | **覆盖** 21/21 |
| **与后端的集成正常** | 11 → **17 集成点**V1 +6 新端点) | **覆盖** 17/17 |
| **5 个新风险** | R-NEW-1 ~ R-NEW-5 全部有应对 | **闭环** |
| **🆕 5 个 V2 新风险** | R-NEW-6 ~ R-NEW-10 全部有应对 | **闭环** |
| **可验收粒度** | 每个任务有 ID / 标题 / 验收标准 / 估时 / 依赖 / 关联约束 | **达标** |
---
## 附录 AV2 任务清单 V1 任务对照
| V1 ID | V2 ID | 变化 |
|---|---|---|
| T-A-01 ~ T-A-23 | T-A-01 ~ T-A-23 | **完全保留** |
| T-B-01 ~ T-B-05 | T-B-01 ~ T-B-05 | **完全保留** |
| T-B-12 ~ T-B-15 | T-B-12 ~ T-B-15 | **完全保留** |
| T-B-16 ~ T-B-21 | T-B-16 ~ T-B-21 | **完全保留** |
| T-B-22 ~ T-B-27 | T-B-22 ~ T-B-27 | **完全保留**B.4 e2e 扩到 8 个) |
| **🆕** | T-B-22 ~ T-B-25, T-B-36, T-B-40, T-B-41 | Share Link 完整链路 |
| **🆕** | T-B-26 ~ T-B-28, T-B-37 | Data Query 4 端点 |
| **🆕** | T-B-29 ~ T-B-31, T-B-38 | Review Flow 3 端点 |
| **🆕** | T-B-32, T-B-33 | Portal cwb / full-plan |
| **🆕** | T-B-34, T-B-42 | LLM 增强 |
| **🆕** | T-B-35, T-B-39, T-B-43 | Poster |
| T-C-01 ~ T-C-13 | T-C-01 ~ T-C-13 | **完全保留** |
| **🆕** | T-C-44, T-C-45 | Poster CLI 集成 + 集成测试 |
| T-D-01 ~ T-D-10 | T-D-01 ~ T-D-10 | **完全保留** |
| T-D-11 ~ T-D-13 | T-D-11 ~ T-D-13 | **完全保留** |
| **🆕** | T-D-14 ~ T-D-20 | 7 个新业务组件 |
| T-D-14 → 改为 T-D-21 | T-D-21 | 暗色变体审计 |
| T-D-15 → 改为 T-D-22, T-D-23 | T-D-22, T-D-23 | next-intl + 文案审计 |
| T-D-17 + T-D-18 → 合并为 T-D-24 | T-D-24 | Chromatic + Lighthouse |
| T-E-01 ~ T-E-09 | T-E-01 ~ T-E-09 | **完全保留**T-E-02 增 URL token |
| T-E-10 ~ T-E-13 → 改为 T-E-20 ~ T-E-23 | T-E-20 ~ T-E-23 | 通知 + 设置 + 用户管理 |
| **🆕** | T-E-10 ~ T-E-12 | Share Link 管理 |
| **🆕** | T-E-13 ~ T-E-16 | Data Query 内部页 |
| **🆕** | T-E-17, T-E-18 | Review + LLM 审计 |
| **🆕** | T-E-19 | Policy 中心 |
| **🆕** | T-E-24 | 公共门户 React 化 |
---
**评审完成。V2 任务清单136 任务 / 92 人天,比 V1 增加 45 任务 / 14 人天,主要因后端 share-link / data-query / review / llm / poster 5 大新模块的 React 化。** 建议向 PM 申请追加预算 14 人天,或调整 E 阶段部分低优先级页面的实施顺序。