diff --git a/docs/superpowers/specs/2026-07-06-component-refactoring-design.md b/docs/superpowers/specs/2026-07-06-component-refactoring-design.md new file mode 100644 index 0000000..6092ed4 --- /dev/null +++ b/docs/superpowers/specs/2026-07-06-component-refactoring-design.md @@ -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 { + // 标准 React ErrorBoundary 实现 +} +``` + +**收敛 3 个替代件为 preset**(保留外部 API,内部改用 ``): + +| 现有文件 | 收敛后 | 位置 | +|---------|-------|------| +| `shared/components/section-error-boundary.tsx` | `SectionErrorBoundary` preset | 保留原路径,内部改为 `` 包装 | +| `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) { + // 保留原语 +} +``` + +#### 3.1.4 FilterBar 与 StatCard + +- `FilterBar`:**保持现状**,不修改接口。模块层 `*-filters.tsx` 改为 `