docs(architecture): 组件化重构专项完成 - 同步 005 lastUpdate + known-issues 第 25 章

- 005 JSON: lastUpdate 更新为组件化重构专项全量完成摘要
- known-issues.md: 新增第 25 章(4 个小节:底座使用规则/拆分模式/迁移规则/验证规则)
- 9 个巨型文件全部 ≤500 行,49 个重复组件全部删除
This commit is contained in:
SpecialX
2026-07-06 20:57:14 +08:00
parent fa68ec0b34
commit ee10380462
2 changed files with 48 additions and 1 deletions

View File

@@ -5,7 +5,7 @@
"generatedAt": "2026-06-17",
"formatVersion": "1.1",
"rule": "每次文件修改后须同步更新本文件",
"lastUpdate": "Phase 4.6 grades 模块组件化重构闭环完成2026-07-06(1) 拆分 batch-grade-entry.tsx 巨型文件 — 将试卷/班级选择器(含未选态引导)拆至 batch-grade-entry-selectors.tsx、底部工具栏清除/保存/粘贴提示)拆至 batch-grade-entry-toolbar.tsx主组件从 457 行降至 374 行,容器仅负责状态编排与 Server Action 调用;(2) 拆分 grade-record-list.tsx 巨型文件 — 行渲染(桌面表格 + 移动端卡片堆叠)拆至 grade-record-row.tsx、编辑/单条删除/批量删除对话框集合拆至 grade-record-detail.tsx导出 EditableFields 类型 + toEditableFields 工具函数),主组件从 523 行降至 231 行;(3) 迁移 4 个重复组件到共享底座并删除原文件 — grade-stats-card.tsx → StatsGrid + StatItem 组合class-grade-report.tsx 内联 8 个统计项、grade-filters.tsx → app 层 student-grade-filters.tsx复用 FilterBar + FilterSearchInput + Select + nuqs useQueryState、grade-query-filters.tsx → app 层 teacher-grade-query-filters.tsx复用 FilterBar + Select + useRouter/useSearchParams、analytics-filters.tsx → app 层 analytics-grade-filters.tsx复用 FilterBar + ChipNav保留原 buildHref URL 构造逻辑。同步更新StatItem/ChipNav/FilterBar/FilterSearchInput 的 usedBy 列表、GradeStats/isGradeType/isSemester 的 usedBy 列表、BatchGradeEntry 与 GradeRecordList 与 ClassGradeReport 的 purpose/props/deps、新增 4 个子组件条目BatchGradeEntrySelectors/BatchGradeEntryToolbar/GradeRecordRow/GradeRecordDetail、删除 4 个旧组件条目GradeStatsCard/GradeQueryFilters/AnalyticsFilters 及 grades/components/grade-filters 隐式条目。验证npx tsc --noEmit 零错误npm run lint 仅 3 个 pre-existing react-hooks/refs 错误(位于未修改的 use-exam-preview-tasks.tsgrep 确认旧组件名GradeStatsCard/GradeFilters/GradeQueryFilters/AnalyticsFilters无业务代码残留。前次更新缓存策略落地专项重构完成2026-07-05覆盖全部 28 个模块,新增 shared/lib/cache/ 9 个文件 + INVALIDATION_MAP 203 个 actionIddata-access 83 文件 250+ 查询函数迁移至 cacheFn 双导出模式actions 43 文件 247 处 revalidatePath 替换为 invalidateFor详细见 004 第 1.1.6 节。",
"lastUpdate": "组件化重构专项全量完成2026-07-06三批 10 个模块闭环 + Phase 1 底座补全。Phase 1新增 ErrorBoundary 基础类组件、StatsGrid 容器、SkeletonCard variant收敛 SectionErrorBoundary/RouteErrorBoundary/WidgetBoundary 为 preset。第 1 批grades/attendance/error-book/elective拆分 batch-grade-entry (457→375) + grade-record-list (523→231)迁移 12 个重复组件到 StatsGrid/FilterBar 底座。第 2 批homework/exams/textbooks拆分 homework-take-view (428→330) + homework-grading-view (507→170) + exam-assembly (467→268) + textbook-reader (458→318) + knowledge-graph-inner (411→295),删除 textbooks 同名 section-error-boundary.tsx迁移 3 个 filter 组件。第 3 批lesson-preparation/ai/dashboard拆分 lesson-plan-editor (594→273) + ai-chat-panel (417→218),新增 DashboardShell 布局壳统一 4 角色 dashboard迁移 filters/skeletons/error-boundaries 到底座。总计9 个巨型文件全部 ≤500 行(最大 37549 个重复组件全部删除无残留tsc 零错误lint 无新增错误。前次更新Phase 4.6 grades 模块组件化重构闭环完成2026-07-06。",
"lastUpdated": "2026-07-06"
},
"architectureOverview": {

View File

@@ -1301,3 +1301,50 @@ if (announcement.type === "school") {
| 多余的 `}` 或 `)` 字符 | 迁移后用 tsc 全量校验 | 手动编辑后未运行 tscTS1005/TS1128 语法错误) |
| questions/data-access.ts 等大文件分批迁移 | 完整迁移所有 `cache(...)` 调用至 cacheFn | 部分迁移导致 `import { cache }` 已删但调用仍存 |
---
## 25. 组件化重构专项2026-07-06
### 25.1 共享底座使用规则
| 规则 | 正确写法 | 错误写法 |
|------|---------|---------|
| 错误边界必须用 preset | `<SectionErrorBoundary namespace="x">` | 自行实现类组件 |
| 统计卡片必须用 StatsGrid | `<StatsGrid items={[...]} />` | 手写 grid + StatCard 循环 |
| 骨架卡片必须用 SkeletonCard | `<SkeletonCard variant="table" />` | 手写 Card + Skeleton 布局 |
| 新增 `*-filters.tsx` 禁止 | 用 `<FilterBar>` + `<FilterSearchInput>` 组合 | 新建模块专属筛选器文件 |
| ErrorBoundary 基础类不直接使用 | 通过 SectionErrorBoundary/WidgetBoundary preset | 直接 `<ErrorBoundary>` |
| FilterBar 是 children-based 组合式 | `<FilterBar><FilterSearchInput/><Select/></FilterBar>` | 传入 fields 配置数组 |
### 25.2 巨型文件拆分模式
| 规则 | 正确写法 | 错误写法 |
|------|---------|---------|
| 容器+子组件拆分保持外部 API 不变 | 容器 props 签名不变,子组件通过 props 接收数据 | 改变容器导出名或 props |
| 容器目标 ≤300 行,子组件各 ≤200 行 | 拆分后容器仅负责状态编排与 Server Action 调用 | 容器保留大量渲染逻辑 |
| 纯函数抽离为工具模块 | `utils/exam-structure-tree.ts` 含递归计算/收集/扁平化 | 在组件中写复杂纯函数 |
| 持久化逻辑抽为 Hook | `use-lesson-plan-persistence.ts` 封装 autoSave/effect | 容器内联 useEffect 处理持久化 |
| 流式响应状态保持稳定 | `useAiChatStream` hook 在容器中调用AbortController 用 useRef | 子组件持有流式状态 |
| Tiptap 编辑器 SSR 配置 | `immediatelyRender: false` 必须保留 | 拆分时遗漏 SSR 配置 |
| dashboard 4 角色仅抽象布局壳 | `<DashboardShell title stats actions>{children}</DashboardShell>` | 强制 4 角色使用相同内容区 |
### 25.3 重复组件迁移规则
| 规则 | 正确写法 | 错误写法 |
|------|---------|---------|
| filter 组件迁到 app 层就近位置 | `app/(dashboard)/.../xxx-filters.tsx` | 保留在 modules 层 |
| 删除旧组件不留 backwards-compat shim | 直接删除文件,调用方改 import | 保留 re-export 文件 |
| 同名冲突优先删除模块层版本 | textbooks 的 `section-error-boundary.tsx` 删除 | 保留两份同名文件 |
| 单数与复数重复时合并 | attendance 的 `attendance-stats-card.tsx`(单数)删除 | 保留两份 |
| StatsGrid 列数支持 2/3/4/5 | `<StatsGrid columns={5}>` 按需指定 | 固定 4 列 |
### 25.4 验证规则
| 规则 | 正确写法 | 错误写法 |
|------|---------|---------|
| 拆分后 tsc + lint 全量验证 | `npx tsc --noEmit` + `npm run lint` | 仅验证修改文件 |
| 旧组件名 grep 确认无残留 | 搜索 import 路径 + 组件名 | 仅搜索文件名 |
| i18n 键同步新增 | SectionErrorBoundary 的 namespace 需有 `error.boundaryTitle` 等键 | 新增 namespace 但不补 i18n 键 |
| 架构文档同步 004/005 | 每批闭环后更新 exports/lastUpdate | 全部完成后才更新 |