docs(spec): 组件化重构专项设计文档 v1

This commit is contained in:
SpecialX
2026-07-06 17:44:15 +08:00
parent 1a34d1f14e
commit ef2040edf4

View File

@@ -0,0 +1,380 @@
# 组件化重构专项设计文档
| 字段 | 值 |
|------|---|
| 文档版本 | 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.tsx``shared/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.json``lastUpdate` 仅记录缓存策略重构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`
```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`
```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.tsx`15 行 → ~80 行):
```tsx
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.tsx``grade-record-list.tsx` | `grade-stats-card``grade-filters``grade-query-filters``analytics-filters` | 低 |
| | attendance | — | `attendance-stats-cards``attendance-stats-card`(单数,重复)、`attendance-filters` | 低 |
| | error-book | — | `error-book-stats-cards``error-book-filters``analytics-stats-cards` | 低 |
| | elective | — | `elective-stats-cards``elective-filters` | 低 |
| **第 2 批** | homework | `homework-take-view.tsx` (428)、`homework-grading-view.tsx` | `assignment-filters` | 中 |
| | exams | `exam-assembly.tsx` | `exam-filters` | 中 |
| | textbooks | `textbook-reader.tsx``knowledge-graph-inner.tsx` (411) | `textbook-filters``section-error-boundary.tsx`(同名冲突) | 中 |
| **第 3 批** | lesson-preparation | `lesson-plan-editor.tsx` | `lesson-plan-filters``lesson-plan-skeleton``lesson-plan-error-boundary` | 高 |
| | ai | `ai-chat-panel.tsx` (417) | `ai-skeleton``ai-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.json``modules.*.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.tsx`20 个)
```
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.tsx`8 个)
```
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.tsx`8 个)
```
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.tsx`5 个)
```
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
```