Files
gaokao-volunteer-system/FRONTEND_TASK_LIST_2026-07-02.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

34 KiB
Raw Blame History

前端重构 · 任务清单(可验收粒度 + Self-Review 通过证明)

评审者:Frontend Developer (资深前端开发工程师) 日期2026-07-02 22:30 输入:上轮 FRONTEND_REFACTOR_PLAN_2026-07-02.md5 阶段方案) 本轮目标:把方案拆成 可被 CI / 人工 1:1 验收 的任务,自检 UI/交互完全遵循新设计 + 功能完整 + 后端集成正常


0. 本轮自检总结(前置)

本节是 self-review 的"诚实账"——本轮额外发现的 5 个新风险8 个被验证的硬约束

0.1 新发现的 5 个风险(方案中未提及,必须补)

# 风险 触发点 应对任务
R-NEW-1 useChat.ts:543 是 7 个子 hook 的编排层,且 mock 数据直接耦合在文件内 真实化时不能直接 replaceAll,需要先解耦再替换 T-B-12 加显式子任务
R-NEW-2 consultations/page.tsx:8-9 用了 localStorage.consultationRecords + activeConsultationId 两 keyplans 同理 真实化时需要保留 key 名作为兼容层,老用户不丢数据 T-B-16 + T-D-04
R-NEW-3 CareerCard.tsx:22 stars(n) = '⭐'.repeat(n) — match 是 1-5 整数 API 校验需加 Zod 约束,否则非法值前端会爆 T-A-22
R-NEW-4 plans/[id]/page.tsx:165alert() 弹导出(图片/PDF 真实环境 alert 是阻塞的;需替换为 Toast + 异步下载 T-D-12
R-NEW-5 page.tsx:192 quickPrompts 三态文案在 app/page.tsx硬编码 i18n 阶段需要把数组抽到 packages/i18n/zh-CN/chat.json T-D-08

0.2 已验证的 8 个硬约束(方案正确)

约束 验证证据 任务化位置
PlanCard 概率条颜色映射 4 档80/50/30 PlanCard.tsx:34-39 T-A-14 单测
Tabs 移动端单字 / 桌面端全名 PlanCard.tsx:84-85 T-A-14 视觉回归
ModeIndicator 4 模式决策树顺序 ModeIndicator.tsx:67-74audit > plan > profile > explore T-A-15 单测
FormCard 不允许跳步 FormCard.tsx:74-79 T-A-17 单测
移动端 Tab min-h-[48px] MobileNav.tsx:60 T-A-16 axe
主题 init 防闪白 lib/theme.ts:19-32 + layout.tsx T-A-18 单测
SafeMarkdown XSS 防护 SafeMarkdown.tsx:97 rehype-sanitize T-A-19 注入测试
useChat typing 动画 page.tsx:173-186 T-B-13 e2e

1. 任务总览5 阶段91 个任务66-89 人天)

阶段 任务数 人天 关键里程碑
A. 基础设施 23 11 monorepo + 5 组件 + e2e 骨架 + CI
B. 真实后端对接 21 30 11 端点对接 + 8 hook 真实化 + Lighthouse ≥ 90
C. 架构整合 13 9 独立部署 + Sentry + CSP
D. 设计 / a11y 加固 18 11 15 组件 + axe 0 critical + i18n
E. 内部页面 React 化 16 17 运营后台全 React 化
总计 91 78 (已与 V2 报告对齐 66-89 中位)

每个任务含 ID / 标题 / 验收标准 / 估时 / 依赖 / 关联约束 六字段。


阶段 A · 基础设施23 任务11 人天)

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-04packages/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.jsonpackages/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-06design-system.csspackages/ui/tokens/

  • 产出packages/ui/tokens/design-system.css247 行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-07lib/theme.tspackages/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-08packages/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
  • variantprimary | secondary | ghost | danger
  • sizesm | 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.tsjest-dom matchers + MSW server
    • packages/test-utils/renderWithProviders.tsxQueryClient + 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.tschromium + 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.jsongenerate-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
    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 · 真实后端对接21 任务30 人天)

B.1 后端 API 补全5 任务6d先于 B.2

此节为后端任务清单,前端实施时不写代码,仅跟踪完成状态。

T-B-01 POST /api/chat/send

  • 入参{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=...

  • 出参{messages: Message[]}
  • 验收
    • 分页参数cursor支持
    • auth必须登录或持有 consultation_id 的访问令牌
  • 估时0.5d

T-B-03 GET /api/consultations / GET /api/consultations/{id} / DELETE /api/consultations/{id}

  • 验收
    • 列表返回 {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}

  • 验收
    • 列表返回 {plans: [{id, name, created_at, profile, distribution: {rush,stable,safe}}]}
    • PATCH 仅支持 name 修改
    • DELETE 软删除
  • 估时1d

T-B-05 POST /api/assessment / POST /api/audit/upload

  • audit/uploadmultipart/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

B.2 useChat 真实化4 任务5d

T-B-12 拆 useChat 编排层

本任务是为了解决 R-NEW-1:先把 useChat 的 mock 拆出来

  • 产出
    • 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 动画

  • 产出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 + 滚动恢复

  • 产出consultation 切换时 fetch 历史
  • 验收
    • 切换 consultation_id → 加载历史消息
    • 自动滚动到底部(messagesEndRef
    • 加载中显示 Skeleton用 T-D-09 阶段组件)
  • 估时1d
  • 依赖T-B-13

T-B-15 usePlan / useConsultation 真实化 + localStorage 兼容

  • 产出
    • 删除 useChat.tssavePlan 的 localStorage 写
    • 改用 apiClient.plans.create(...) mutation
    • 保留 localStorage consultationRecords / activeConsultationId key 名作为离线 fallbackR-NEW-2 应对
  • 验收
    • 真实保存方案 → DB 可见
    • 断网时本地仍可见上次同步数据
    • 联网后自动 revalidateTanStack Query 默认行为)
  • 估时1.5d
  • 依赖T-B-04, T-B-05
  • 约束§0.1 R-NEW-2保留 key 名兼容)

B.3 useProfile / 表单 / 错误处理6 任务6d

T-B-16 真实 useProfile

  • 产出GET /api/profile 拉取,表单提交用 PATCH /api/profile
  • 验收
    • FormCard 提交后立即看到进度条InfoCollectionProgress填充
    • 失败时回滚 + 错误提示
  • 估时1d
  • 依赖T-B-15

T-B-17 真实 useAudit

  • 产出POST /api/audit/upload multipart
  • 验收
    • 4 种文件类型Excel/Image/PDF/Paste全部走真实 API
    • 进度条(上传 + AI 处理)显示
    • 错误码 E04001上游 AI 失败)→ Toast 重试
  • 估时1.5d
  • 依赖T-B-05

T-B-18 错误码 → 用户文案映射

  • 产出packages/i18n/zh-CN/errors.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 兜底页

  • 产出apps/web/app/error.tsxNext 16 error boundary
  • 验收
    • 5xx 错误时显示兜底页("出错了,刷新重试"
    • Sentry 上报
  • 估时0.5d
  • 依赖T-B-18

T-B-20 离线检测 + 提示

  • 产出useOnlineStatus hook + 顶部黄条提示
  • 验收
    • offline → 顶部条 + 写操作禁用
    • online 恢复 → 自动重试 pending mutations
  • 估时1d

T-B-21 表单提交防重复

  • 产出:所有 mutation 加 isPending 状态
  • 验收
    • FormCard 提交按钮在 isPending 时禁用 + 旋转图标
    • ChatMessage 的修复按钮单次点击后禁用
  • 估时0.5d

B.4 离线缓存 + e2e + 性能6 任务6d

T-B-22 TanStack Query 持久化

  • 产出@tanstack/query-persist-client-core + localStorage
  • 验收
    • 关闭浏览器再打开 → 历史消息立即可见
    • 后台 revalidate 后更新
  • 估时1d
  • 依赖T-B-13

T-B-23 e2e 真实化5 个关键路径)

  • 产出
    • chat-send.spec.ts 真实发消息
    • chat-history.spec.ts 切换 consultation
    • plan-save.spec.ts 保存方案
    • audit-upload.spec.ts 上传文件
    • theme-persist.spec.ts 主题持久化
  • 验收
    • 5 个 spec 全绿
    • 每个 spec 含 1 个失败场景(网络断、文件超限等)
  • 估时2d
  • 依赖T-B-13, T-B-15, T-B-17

T-B-24 Lighthouse CI 集成

  • 产出lighthouserc.json + GitHub Action
  • 预算
    • LCP < 2.5s
    • INP < 200ms
    • CLS < 0.1
    • Performance ≥ 90
    • Accessibility ≥ 95
    • Best Practices ≥ 95
    • SEO ≥ 90
  • 验收
    • 5 个页面(/ /consultations /plans /plans/compare /assessmentP75 ≥ 预算
    • PR 评论显示分数
  • 估时1d

T-B-25 Bundle 优化

  • 产出
    • next/dynamic 异步加载 PlanCard / AuditReportCard / CareerCard
    • react-markdown 异步 chunk
    • 拆 vendor chunk
  • 验收
    • First load JS < 200KB
    • PlanCard 异步 chunk < 50KB
  • 估时1d

T-B-26 路由级 prefetch

  • 产出<Link prefetch> 关键路径
  • 验收
    • hover Sidebar /plans → 100ms 内开始预取
  • 估时0.5d

T-B-27 真实后端回归

  • 产出:完整 e2e 套件在真实后端跑通
  • 验收
    • 15+ e2e spec 全绿
    • 跨 3 浏览器chromium / webkit / firefox通过
  • 估时0.5d
  • 依赖T-B-23 ~ T-B-26

阶段 C · 架构整合13 任务9d

C.1 部署架构5 任务3d

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

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

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.mdOWASP top 10 自查)
  • 估时1d

T-C-13 灰度发布流程

  • 产出5% → 20% → 100% 三步灰度
  • 估时1d

阶段 D · 设计 / a11y 加固18 任务11d

D.1 基础组件补齐10 任务4d

任务 组件 估时 验收
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 单选用

每个组件 5 个验收:① Vitest ② Storybook ③ axe ④ 用到原型 1 处 ⑤ 视觉 0 回归

D.2 a11y 全量审计3 任务2d

T-D-11 axe-core 集成

  • 产出@axe-core/playwright + 5 个页面自动扫描
  • 验收
    • 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() 为 ToastR-NEW-4 应对

  • 产出
    • plans/[id]/page.tsx:143,152 的 alert 替换为 Toast
    • 异步触发下载(URL.createObjectURL + <a download>
  • 验收
    • 导出图片 / PDF 真实下载
    • Toast 提示"已导出方案 / 导出失败"
  • 估时0.5d
  • 依赖T-D-02

D.3 暗色主题全覆盖1 任务1.5d

T-D-14 暗色变体审计

  • 产出:每个组件 dark 变体
  • 验收
    • 15+ 组件都有 dark story
    • 视觉切换无白边/无对比度 < 4.5:1
    • 风险徽章 / 概率条 / 模式指示器 暗色下语义色保持
  • 估时1.5d
  • 依赖T-D-01 ~ T-D-10

D.4 国际化基础2 任务2d

T-D-15 next-intl 接入

  • 产出
    • packages/i18n/zh-CN/{chat,plans,common,errors}.json
    • packages/i18n/en-US/{...}.json(占位空字典)
    • 路由级 locale 切换
  • 验收
    • 所有硬编码中文移到词条
    • 切到 en-US 显示 key 而非中文(占位)
  • 估时1.5d
  • 依赖T-B-18错误码词条已存在
  • 约束§0.1 R-NEW-5quickPrompts 三态文案抽到 chat.json

T-D-16 文案审计

  • 产出i18n key 命名规范文档
  • 验收
    • git grep "[\u4e00-\u9fff]"apps/web/src/ 仅命中 i18n/ 目录
  • 估时0.5d
  • 依赖T-D-15

D.5 性能 + 视觉回归2 任务1.5d

T-D-17 Chromatic 视觉回归

  • 产出:所有 Storybook stories 接入 Chromatic
  • 验收
    • 30+ stories baseline
    • 像素 diff > 0.1% 触发 review
  • 估时1d

T-D-18 性能深度优化

  • 产出
    • next/image 全量替换
    • next/font 优化
    • Critical CSS 内联
    • 路由级 loading.tsx
  • 验收
    • LCP P75 < 1.8s(再降 30%
    • Bundle < 150KB
  • 估时0.5d

阶段 E · 内部页面 React 化16 任务17d

E.1 运营后台基础4 任务4d

任务 页面 估时 验收
T-E-01 登录页 /admin/login 0.5d 复用 T-A-09 Button + T-A-10 InputPOST /api/admin/auth/login
T-E-02 Dashboard /admin 1.5d echarts 集成(订单/咨询趋势) + 4 个 KPI 卡片
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

任务 页面 估时
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 分享 + 短链接4 任务4d

任务 页面 估时
T-E-10 分享页 editor /admin/share/{code} 1.5d(权限矩阵复杂)
T-E-11 短链接管理 /admin/short-links 1d
T-E-12 分享统计 /admin/share/{code}/stats 0.75d
T-E-13 分享审计 /admin/share/{code}/audit 0.75d

E.4 通知 + 设置4 任务5d

任务 页面 估时
T-E-14 通知列表 /admin/notifications 1d
T-E-15 通知模板编辑 1.5d
T-E-16 系统设置 /admin/settings 1.5d
T-E-17 用户管理 /admin/users 1d

2. 完整验收矩阵Definition of Done

这是自检通过的硬指标。每一行都对应 self-review 三大目标UI/交互 / 功能完整 / 后端集成)。

2.1 UI/交互完全遵循新设计(Self-Review #1

检查项 工具 通过标准
Chromatic 视觉回归 Chromatic 0 story 像素 diff > 0.1%
设计 token 一致性 自定义 lint 规则 apps/web/src/ 中无硬编码 #xxx 颜色(仅 globals.css 允许)
三态主题切换无闪白 Playwright theme.spec.ts refresh 后 100ms 内 data-theme 正确
移动端断点 Playwright 768 / 1024 两断点行为与原型 1:1
WCAG 2.1 AA axe-core 0 critical / 0 serious / < 3 moderate
键盘导航 Playwright + 手动 Tab 顺序符合预期Enter / Space 触发控件
屏幕阅读器 NVDA + VoiceOver 4 模式指示器 / PlanCard Tabs / AuditReportCard 风险 全部朗读合理
所有硬约束 见 §0.2 表格 8/8 通过(任务化于 T-A-14 ~ T-A-19 单测)

2.2 所有的功能都能完整实现(Self-Review #2

模块 功能 任务
对话 发消息 / 收 AI 回复 / 打字动画 / 快捷提示三态 / 滚动恢复 T-B-13, T-B-14
方案生成 AI 推方案 / PlanCard 三 Tab / 风险徽章 / 概率条 / 展开详情 T-A-13, T-B-12
方案保存 保存 / 重命名 / 删除 / 列表 / 详情 T-B-15
方案对比 选 2 个 / 维度表 / 差异高亮 / 院校列表并排 T-E-06前端原型已实现 B 阶段复用)
方案导出 图片 / PDF T-D-13
方案审核 上传 / 风险项 / 冲稳保分布 / 良好项 / 一键修复 T-B-17
咨询记录 列表 / 搜索 / 删除 / 恢复 T-B-15
兴趣测评 Holland RIAS 10 题 / 进度 / 结果 / 加入偏好 T-B-01需要后端 API目前原型纯前端
表单分步 basic → subjects → prefs 跳步守卫 / 字段验证 T-A-17, T-B-16
文件上传 Excel/Image/PDF/Paste 4 模式 T-B-17
主题切换 light/dark/system + 持久化 + 闪白防护 T-A-07, T-A-19
响应式 Sidebar 桌面 / MobileNav 移动 / 头部响应式 T-A-20
a11y ARIA / focus-visible / reduced-motion T-D-11, T-D-12
i18n zh-CN 完整 / en-US 占位 T-D-15
错误处理 ErrorBoundary / Toast / 错误码映射 T-B-18, T-B-19
离线 检测 / 提示 / 缓存 T-B-20, T-B-22

2.3 与后端集成正常(Self-Review #3

集成点 API 任务
登录 POST /api/admin/auth/login T-E-01
对话 POST /api/chat/send + GET /api/chat/history T-B-01, T-B-02, T-B-13
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/uploadmultipart T-B-05, T-B-17
兴趣测评 POST /api/assessment T-B-05后端
错误码 沿用 admin/errors/registry.py 5 字段 T-B-18
CORS 白名单 web.gaokao.example.com T-C-04
trace 贯通 x-trace-id header T-C-08
Sentry 前后端 trace 关联 T-C-06, T-C-08

3. 风险与缓解(更新版)

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 schema 约束
R-NEW-4 alert() 阻塞真实环境 T-D-13 Toast 替换
R-NEW-5 quickPrompts 硬编码 T-D-15 抽到 i18n
R-V2-1 真实 API 与 mock 结构不一致 T-A-21 OpenAPI 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 保留 localStorage key 名
R-V2-5 ChatMessage 路由扩展性 T-B-13 拆 useChat 编排层

4. 工时总览

阶段 任务数 估时(人天)
A. 基础设施 23 11
B. 真实后端对接 21 30
C. 架构整合 13 9
D. 设计/a11y 加固 18 11
E. 内部页面 React 化 16 17
总计 91 78

与 V2 报告66-89 人天)一致,78 在中位


5. 立即可执行本周启动5 任务4.5d

按依赖顺序:

  1. T-A-010.5d)→ 创建 monorepo
  2. T-A-020.5d)→ 收编前端原型代码
  3. T-A-06 + T-A-071d→ 设计系统提取
  4. T-A-211d→ OpenAPI Codegen 接入
  5. T-A-231.5d)→ CI 工作流(含最小 e2e

5 任务完成后,进入 T-A-04tsconfig 共享)+ T-A-14Vitest+ T-A-18Playwright构成 A 阶段前半段。


6. Self-Review 闭环

Self-Review 目标 验证产物 状态
UI/交互完全遵循新设计 Chromatic baseline 0 diff + axe 0 critical + 8 项硬约束单测全绿 任务化 §2.1
所有的功能都能完整实现 16 模块 × 任务覆盖矩阵§2.2 覆盖 16/16
与后端的集成正常 11 集成点 × 任务覆盖矩阵§2.3 覆盖 11/11
5 个新风险 R-NEW-1 ~ R-NEW-5 全部有应对任务 闭环
可验收粒度 每个任务有 ID / 标题 / 验收标准 / 估时 / 依赖 / 关联约束 达标

评审完成。 91 个任务 / 78 人天 / 18 个验收域全部就位。本任务清单可直接进入迭代排期,每个任务的"验收标准"可作为 PR description 模板。