Files
NextEdu/docs/superpowers/specs/2026-07-06-component-refactoring-design.md
2026-07-06 17:44:15 +08:00

16 KiB
Raw Blame History

组件化重构专项设计文档

字段
文档版本 v1
创建日期 2026-07-06
作者 Trae 协作生成
状态 待用户审查
范围 巨型文件拆分9 个)+ 重复组件收敛49 个)+ 共享底座补全
策略 混合先收敛底座再按模块垂直闭环3 批风险分级)

1. 背景与现状

1.1 巨型文件清单9 个,>400 行)

基于 2026-07-06 实际扫描:

# 路径 行数 模块
1 src/modules/textbooks/components/textbook-reader.tsx >450 textbooks
2 src/modules/lesson-preparation/components/lesson-plan-editor.tsx >450 lesson-preparation
3 src/modules/grades/components/batch-grade-entry.tsx >450 grades
4 src/modules/grades/components/grade-record-list.tsx >450 grades
5 src/modules/homework/components/homework-take-view.tsx 428 homework
6 src/modules/homework/components/homework-grading-view.tsx >450 homework
7 src/modules/exams/components/exam-assembly.tsx >450 exams
8 src/modules/ai/components/ai-chat-panel.tsx 417 ai
9 src/modules/textbooks/components/knowledge-graph-inner.tsx 411 textbooks

已瘦身的 5 个文件不在本次范围内exam-rich-form.tsx (384)、message-list.tsx (396)、selection-toolbar.tsx (366)、error-book-detail-dialog.tsx (336)、admin-users-view.tsx (332)。

1.2 重复组件清单49 个)

类型 数量 示例路径
*-filters.tsx 20 grades/components/grade-filters.tsx
*-stats-cards.tsx / *-stats-card.tsx 8 attendance/components/attendance-stats-cards.tsx
*-skeleton.tsx 8 ai/components/ai-skeleton.tsx
*-error-boundary.tsx 8 audit/components/audit-error-boundary.tsx
*-dashboard.tsx 5 dashboard/components/admin-dashboard/admin-dashboard.tsx

已知冲突

  • textbooks/components/section-error-boundary.tsxshared/components/section-error-boundary.tsx 同名
  • attendance/components/attendance-stats-card.tsx(单数)与 attendance-stats-cards.tsx(复数)并存

1.3 共享底座现状(关键发现)

底座 状态 路径 当前接口
FilterBar 已存在 shared/components/ui/filter-bar.tsx (124 行) children-based 组合式:FilterBar + FilterSearchInput + FilterResetButton
StatCard 已存在 shared/components/ui/stat-card.tsx (95 行) 单卡片,无 grid 容器
Skeleton 已存在 shared/components/ui/skeleton.tsx (15 行) 仅原语,无 variant
ErrorBoundary 缺失 有 3 个分散替代件:section-error-boundary.tsx (148)、route-error.tsx (44)、widget-boundary.tsx (155)

1.4 架构文档缺口

docs/architecture/005_architecture_data.jsonlastUpdate 仅记录缓存策略重构2026-07-05未记录 filter-bar/stat-card/widget-boundary 等底座组件的存在,违反项目规则"新增组件必须同步 004/005"。


2. 目标与非目标

2.1 目标

  1. 补全底座:新增 ui/error-boundary.tsx 基础组件 + 收敛 3 个分散替代件为 preset
  2. 扩展底座:新增 StatsGrid 容器(基于 StatCard)、SkeletonCard variant基于 Skeleton
  3. 拆分巨型文件9 个 >400 行组件全部拆为容器+子组件,目标 ≤500 行
  4. 迁移重复组件49 个重复组件迁移到底座,删除旧实现(不留 backwards-compat shim
  5. 同步架构文档004 / 005 / known-issues.md 全量更新

2.2 非目标YAGNI

  • shared/db/schema.ts (1111 行) 拆分 — 属于解耦专项
  • exams/actions.ts (633 行) 拆分 — 属于解耦专项
  • 各模块 data-access.ts 拆分 — 属于解耦专项
  • proctoring/exam-mode-config.tsx 死代码清理 — 单独任务
  • useDialogState 批量接入 — V5 状态专项收尾
  • 跨模块直接 DB 查询扫描 — 解耦专项遗留
  • FilterBar 接口改为配置驱动 — 当前 children-based 组合式更符合 React 模式,保持不变
  • 单元测试编写 — 项目无单测覆盖,本次不引入

3. 架构设计

3.1 Phase 1底座收敛与补全

3.1.1 ErrorBoundary 收敛方案

新增 src/shared/components/ui/error-boundary.tsx

interface ErrorBoundaryProps {
  fallback: React.ReactNode | ((error: Error, reset: () => void) => React.ReactNode);
  onError?: (error: Error, info: React.ErrorInfo) => void;
  children: React.ReactNode;
}

export class ErrorBoundary extends React.Component<ErrorBoundaryProps, { hasError: boolean; error: Error | null }> {
  // 标准 React ErrorBoundary 实现
}

收敛 3 个替代件为 preset(保留外部 API内部改用 <ErrorBoundary>

现有文件 收敛后 位置
shared/components/section-error-boundary.tsx SectionErrorBoundary preset 保留原路径,内部改为 <ErrorBoundary fallback={...}> 包装
shared/components/route-error.tsx RouteErrorBoundary preset 保留原路径
shared/components/widget-boundary.tsx WidgetBoundary preset 保留原路径(含 Suspense + Skeleton 三合一)

模块层 8 个 *-error-boundary.tsx:删除,改为直接使用 SectionErrorBoundary preset。

3.1.2 StatsGrid 新增方案

新增 src/shared/components/ui/stats-grid.tsx

interface StatItem {
  label: string;
  value: string | number;
  trend?: { direction: 'up' | 'down' | 'flat'; delta: string };
  icon?: React.ComponentType<{ className?: string }>;
  href?: string;
}

interface StatsGridProps {
  items: StatItem[];
  columns?: 2 | 3 | 4; // 默认响应式
  isLoading?: boolean;
}

内部用 StatCard 渲染,isLoading 时渲染 StatCardSkeleton

3.1.3 SkeletonCard variant 方案

扩展 src/shared/components/ui/skeleton.tsx15 行 → ~80 行):

interface SkeletonCardProps {
  variant: 'table' | 'list' | 'chart' | 'form' | 'stats-grid';
  rows?: number;
}

export function SkeletonCard({ variant, rows = 5 }: SkeletonCardProps) {
  // 按 variant 渲染不同骨架布局
}

export function Skeleton(props: React.HTMLAttributes<HTMLDivElement>) {
  // 保留原语
}

3.1.4 FilterBar 与 StatCard

  • FilterBar保持现状,不修改接口。模块层 *-filters.tsx 改为 <FilterBar><FilterSearchInput .../><select .../></FilterBar> 组合实现
  • StatCard保持现状,作为 StatsGrid 内部使用

3.1.5 Phase 1 交付物

文件 操作
shared/components/ui/error-boundary.tsx 新增
shared/components/ui/stats-grid.tsx 新增
shared/components/ui/skeleton.tsx 扩展(新增 SkeletonCard
shared/components/ui/filter-bar.tsx 不修改
shared/components/ui/stat-card.tsx 不修改
shared/components/section-error-boundary.tsx 内部改用 ErrorBoundary
shared/components/route-error.tsx 内部改用 ErrorBoundary
shared/components/widget-boundary.tsx 内部改用 ErrorBoundary
shared/components/index.ts 新增 re-export
docs/architecture/004 / 005 同步底座节点

3.2 Phase 2模块垂直闭环

3.2.1 批次划分

批次 模块 巨型文件 重复组件 风险
第 1 批 grades batch-grade-entry.tsxgrade-record-list.tsx grade-stats-cardgrade-filtersgrade-query-filtersanalytics-filters
attendance attendance-stats-cardsattendance-stats-card(单数,重复)、attendance-filters
error-book error-book-stats-cardserror-book-filtersanalytics-stats-cards
elective elective-stats-cardselective-filters
第 2 批 homework homework-take-view.tsx (428)、homework-grading-view.tsx assignment-filters
exams exam-assembly.tsx exam-filters
textbooks textbook-reader.tsxknowledge-graph-inner.tsx (411) textbook-filterssection-error-boundary.tsx(同名冲突)
第 3 批 lesson-preparation lesson-plan-editor.tsx lesson-plan-filterslesson-plan-skeletonlesson-plan-error-boundary
ai ai-chat-panel.tsx (417) ai-skeletonai-error-boundary
dashboard dashboard-loading-skeleton、4 个角色 dashboard 子组件(仅抽象布局壳)

3.2.2 单模块闭环流程6 步)

1. 模块审计     → Read 全部目标文件 + 重复组件,记录依赖与外部 API
2. 拆分巨型文件 → 拆为 容器 + 子组件(保持外部 API 不变)
3. 迁移到底座   → *-filters → FilterBar、*-stats-cards → StatsGrid、
                  *-skeleton → SkeletonCard、*-error-boundary → SectionErrorBoundary
4. 删除旧组件   → 直接删除,不留 backwards-compat shim
5. 验证        → tsc --noEmit + npm run lint + 手动回归
6. 文档同步    → 004 / 005 / known-issues.md

3.2.3 跨批次依赖规则

  • Phase 1 完成 → 启动第 1 批
  • 第 1 批完成 → 评估底座接口是否需调整(允许返回 Phase 1 调整)
  • 第 2 批启动前 → 第 1 批验证通过
  • 第 3 批启动前 → 第 2 批验证通过(高风险模块需底座稳定)

3.2.4 dashboard 4 角色抽象范围

仅抽象布局壳<DashboardShell> 含 PageHeader + StatsGrid 区 + 内容区),各角色业务逻辑保持独立。不强制 4 个 dashboard 使用相同内容区。


4. 验收标准

4.1 代码验收(硬性门禁)

检查项 命令 通过标准
TypeScript npx tsc --noEmit 零错误
ESLint npm run lint 零新增错误pre-existing warnings 不计入)
文件行数 Read 确认 9 个巨型文件拆分后 ≤500 行
重复组件删除 Grep 旧组件名 全局无残留引用
外部 API 不变 Grep 模块导出名 容器组件对外 API 签名不变
设计令牌合规 Grep #hex'Inter'w-[ 零违规(豁免场景除外)

4.2 行为验收(手动回归)

模块类型 验收方式
列表/筛选页 进入页面 → 应用筛选 → 重置 → 翻页 → 数据正确
表单页 打开 Dialog → 填写 → 提交 → 列表刷新
编辑器 进入 → 编辑内容 → 保存 → 重新加载内容存在
dashboard 4 角色分别登录 → 卡片渲染 → 数据正确

4.3 文档同步

  • 004_architecture_impact_map.md:模块章节组件清单 + shared/components 章节 + 文末"组件化重构专项"章节
  • 005_architecture_data.jsonmodules.*.exports + sharedComponents + lastUpdate + dependencyMatrix
  • known-issues.md:每批新增章节,速查手册风格记录底座使用规则与拆分模式

4.4 Commit 规范

每批一个 squash commit

refactor(grades,attendance,error-book,elective): 组件化重构第 1 批

- 新增 ErrorBoundary/StatsGrid/SkeletonCard 底座
- 拆分 grades/batch-grade-entry.tsx (XXX → YYY 行)
- 删除 12 个重复组件,迁移到底座
- 同步 004/005 架构图known-issues 新增章节

验收tsc + lint 零错误,手动回归 4 模块页面通过

5. 风险与缓解

风险 缓解
底座接口设计不准 → 返工 第 1 批低风险模块验证后允许调整底座
巨型文件拆分破坏外部 API 容器保持外部 API 不变,仅内部拆子组件
删除旧组件后引用未清理 tsc + lint + grep 三重校验
textbooks 同名 section-error-boundary.tsx 冲突 模块层版本删除,改用 shared 层
富文本/编辑器拆分难度高 textbooks 按 003_ui_refactoring_plan.md 已有方案执行
dashboard 4 角色抽象范围蔓延 仅抽象布局壳,业务逻辑保持独立

6. 失败回滚策略

  • 模块闭环中暴露底座接口问题 → 停止该模块,回 Phase 1 调整底座,已完成模块不回滚
  • 模块闭环中暴露业务逻辑问题(非组件化引起)→ 不在本次范围,记录到 known-issues组件化继续推进

7. 完成定义Definition of Done

  • Phase 1 完成ErrorBoundary/StatsGrid/SkeletonCard 落地3 个替代件收敛为 preset
  • 第 1 批完成grades/attendance/error-book/elective 闭环
  • 第 2 批完成homework/exams/textbooks 闭环
  • 第 3 批完成lesson-preparation/ai/dashboard 闭环
  • 9 个巨型文件全部 ≤500 行
  • 49 个重复组件全部删除并迁移到底座
  • 004 / 005 / known-issues 同步更新
  • 3 个批次 commit 全部提交

8. 附录:完整重复组件清单

8.1 *-filters.tsx20 个)

shared/components/question/question-bank-filters.tsx
modules/grades/components/grade-query-filters.tsx
modules/grades/components/grade-filters.tsx
modules/grades/components/analytics-filters.tsx
modules/classes/components/students-filters.tsx
modules/classes/components/schedule-filters.tsx
modules/attendance/components/attendance-filters.tsx
modules/error-book/components/error-book-filters.tsx
modules/exams/components/exam-filters.tsx
modules/audit/components/data-change-log-filters.tsx
modules/audit/components/login-log-filters.tsx
modules/audit/components/audit-log-filters.tsx
modules/lesson-preparation/components/lesson-plan-filters.tsx
modules/homework/components/assignment-filters.tsx
modules/questions/components/question-filters.tsx
modules/student/components/course-filters.tsx
modules/student/components/student-schedule-filters.tsx
modules/school/components/grade-insights-filters.tsx
modules/textbooks/components/textbook-filters.tsx
modules/elective/components/elective-filters.tsx

8.2 *-stats-cards.tsx / *-stats-card.tsx8 个)

modules/error-book/components/analytics-stats-cards.tsx
modules/error-book/components/error-book-stats-cards.tsx
modules/attendance/components/attendance-stats-cards.tsx
modules/attendance/components/attendance-stats-card.tsx  ← 单数,与复数重复
modules/elective/components/elective-stats-cards.tsx
modules/adaptive-practice/components/practice-overview-stats-cards.tsx
modules/adaptive-practice/components/practice-stats-cards.tsx
modules/grades/components/grade-stats-card.tsx

8.3 *-skeleton.tsx8 个)

modules/messaging/components/message-list-skeleton.tsx
modules/announcements/components/announcement-list-skeleton.tsx
modules/audit/components/audit-log-table-skeleton.tsx
modules/classes/components/class-skeleton.tsx
modules/ai/components/ai-skeleton.tsx
modules/school/components/school-skeleton.tsx
modules/dashboard/components/dashboard-loading-skeleton.tsx
modules/lesson-preparation/components/lesson-plan-skeleton.tsx

8.4 ErrorBoundary 相关文件10 个)

shared 层 preset3 个,保留并内部收敛到 <ErrorBoundary>

shared/components/section-error-boundary.tsx
shared/components/route-error.tsx
shared/components/widget-boundary.tsx

模块层待删除7 个,改为直接使用 SectionErrorBoundary preset

modules/audit/components/audit-error-boundary.tsx
modules/school/components/school-error-boundary.tsx
modules/classes/components/class-error-boundary.tsx
modules/textbooks/components/section-error-boundary.tsx  ← 与 shared 同名,删除
modules/settings/components/settings-section-error-boundary.tsx
modules/ai/components/ai-error-boundary.tsx
modules/lesson-preparation/components/lesson-plan-error-boundary.tsx

8.5 *-dashboard.tsx5 个)

modules/ai/components/ai-usage-dashboard.tsx
modules/dashboard/components/parent-dashboard/parent-dashboard.tsx
modules/dashboard/components/admin-dashboard/admin-dashboard.tsx
modules/proctoring/components/proctoring-dashboard.tsx
modules/exams/components/exam-analytics-dashboard.tsx