Files
NextEdu/docs/architecture/audit/dashboard-audit-report-v2.md
SpecialX e997abaf5e refactor(dashboard): V2 审计重构 — i18n 补齐 + 共享抽象 + 单测 + a11y
V2 审计报告(docs/architecture/audit/dashboard-audit-report-v2.md)发现并修复:

- P0 i18n:10 个子组件硬编码字符串全部接入 next-intl(teacher-quick-actions /
  teacher-classes-card / teacher-homework-card / teacher-schedule /
  recent-submissions / teacher-grade-trends / student-grades-card /
  student-today-schedule-card / student-upcoming-assignments-card /
  admin-dashboard),新增 ~50 个翻译键
- P1 共享抽象:新增 DashboardGreetingHeader 组件,消除 teacher/student
  头部 90% 重复代码,两个 Header 改为薄包装
- P2 单测:为 6 个纯函数添加 31 个单元测试
  (tests/integration/dashboard/dashboard-utils.test.ts)
- P2 a11y:admin 表格 caption、teacher/student 视图语义化标签
  (header / section aria-label / aside aria-label)
- 同步架构图 004/005
2026-06-22 17:01:00 +08:00

122 lines
8.6 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 仪表盘模块审计报告 v2
> 审查日期2026-06-22第二轮
> 审查范围:基于 v1 重构后代码commit `868ac5f` + `21c1e7a`)的再次分析
> 前置报告:`docs/architecture/audit/dashboard-audit-report.md`v1
> 架构图参考:`docs/architecture/004_architecture_impact_map.md` §2.12、`docs/architecture/005_architecture_data.json`
---
## 一、v1 重构成果回顾
v1 报告识别的 P0/P1/P2 项目已完成的部分:
| # | 项目 | 状态 | 证据 |
|---|------|------|------|
| P0-1 | 权限校验 | ✅ 已完成 | [actions.ts](file:///e:/Desktop/CICD/src/modules/dashboard/actions.ts) 4 个 Server Action 均调用 `requirePermission()` |
| P0-2 | 根重定向角色硬编码 | ✅ 已完成 | [dashboard/page.tsx](file:///e:/Desktop/CICD/src/app/(dashboard)/dashboard/page.tsx) 改用 `resolvePermissions()` |
| P0-3 | i18n 零覆盖 | ⚠️ 部分完成 | 仅容器组件接入 i18n**10 个子组件仍英文硬编码** |
| P0-4 | 页面层越权编排 | ✅ 已完成 | teacher/student/parent 编排下沉至 actions.ts |
| P1-1 | 业务逻辑耦合 UI | ✅ 已完成 | [lib/dashboard-utils.ts](file:///e:/Desktop/CICD/src/modules/dashboard/lib/dashboard-utils.ts) 抽取 6 个纯函数 |
| P1-3 | 仅路由级错误边界 | ✅ 已完成 | [dashboard-section.tsx](file:///e:/Desktop/CICD/src/modules/dashboard/components/dashboard-section.tsx) 分区 Error Boundary + Suspense |
| P2-2 | a11y 不足 | ❌ 未完成 | 仍缺语义化标签、表格 caption |
---
## 二、v2 新发现问题
### 2.1 i18n 覆盖严重不完整P0 — v1 遗漏)
v1 仅对容器组件(`admin-dashboard.tsx``teacher-dashboard-view.tsx``teacher-dashboard-header.tsx``teacher-stats.tsx``teacher-todo-card.tsx``student-stats-grid.tsx``student-dashboard-header.tsx``parent-dashboard.tsx``user-growth-chart.tsx`)接入 i18n**10 个子组件仍全英文硬编码**
| # | 文件 | 硬编码示例 | 违反规则 |
|---|------|-----------|----------|
| 1 | [teacher-quick-actions.tsx](file:///e:/Desktop/CICD/src/modules/dashboard/components/teacher-dashboard/teacher-quick-actions.tsx) L12-24 | `"Create Assignment"` / `"Grade"` / `"My Classes"` | "所有用户可见文本必须适配 i18n" |
| 2 | [teacher-classes-card.tsx](file:///e:/Desktop/CICD/src/modules/dashboard/components/teacher-dashboard/teacher-classes-card.tsx) L15-27 | `"My Classes"` / `"View all"` / `"No classes yet"` / `"Create a class to start managing students and schedules."` / `"Create class"` / `"Homeroom"` / `"Room"` | 同上 |
| 3 | [teacher-homework-card.tsx](file:///e:/Desktop/CICD/src/modules/dashboard/components/teacher-dashboard/teacher-homework-card.tsx) L17-87 | `"Homework"` / `"Create new assignment"` / `"No assignments"` / `"Create an assignment to get started."` / `"Create"` / `"No due date"` / `"View all assignments"` | 同上 |
| 4 | [teacher-schedule.tsx](file:///e:/Desktop/CICD/src/modules/dashboard/components/teacher-dashboard/teacher-schedule.tsx) L41-141 | `"Today's Schedule"` / `"No Classes Today"` / `"No timetable entries."` / `"View schedule"` / `"LIVE"` / `"Scroll for more"` / `"No more classes today"` | 同上 |
| 5 | [recent-submissions.tsx](file:///e:/Desktop/CICD/src/modules/dashboard/components/teacher-dashboard/recent-submissions.tsx) L22-105 | `"Recent Submissions"` / `"No New Submissions"` / `"All caught up!..."` / `"View All"` / `"View submissions"` / `"Student"` / `"Assignment"` / `"Submitted"` / `"Action"` / `"Late"` / `"Grade"` | 同上 |
| 6 | [teacher-grade-trends.tsx](file:///e:/Desktop/CICD/src/modules/dashboard/components/teacher-dashboard/teacher-grade-trends.tsx) L25-69 | `"Class Performance"` / `"Average scores for the last X assignments"` / `"No data available"` / `"Publish assignments to see class performance trends."` / `"Average Score (%)"` / `"X/Y submitted"` | 同上 |
| 7 | [student-grades-card.tsx](file:///e:/Desktop/CICD/src/modules/dashboard/components/student-dashboard/student-grades-card.tsx) L30-101 | `"Recent Grades"` / `"No graded work yet"` / `"Finish and submit assignments to see your score trend."` / `"View all"` / `"Score (%)"` / `"Latest:"` / `"Points:"` / `"Assignment"` / `"Score"` / `"When"` | 同上 |
| 8 | [student-today-schedule-card.tsx](file:///e:/Desktop/CICD/src/modules/dashboard/components/student-dashboard/student-today-schedule-card.tsx) L52-83 | `"Today's Schedule"` / `"View all"` / `"No classes today"` / `"Your timetable is clear for today."` / `"In Progress"` / `"Up Next"` | 同上 |
| 9 | [student-upcoming-assignments-card.tsx](file:///e:/Desktop/CICD/src/modules/dashboard/components/student-dashboard/student-upcoming-assignments-card.tsx) L17-22,49-72 | `"Review"` / `"View"` / `"Continue"` / `"Start"` / `"Upcoming Assignments"` / `"View all"` / `"No assignments"` / `"You have no assigned homework right now."` / `"Title"` / `"Status"` / `"Due"` / `"Score"` / `"Action"` / `"Late"` | 同上 |
| 10 | [admin-dashboard.tsx](file:///e:/Desktop/CICD/src/modules/dashboard/components/admin-dashboard/admin-dashboard.tsx) L212 | `{u.role ?? "unknown"}` 硬编码 `"unknown"` | 同上 |
**后果**:中文用户看到大量英文,体验割裂;无法切换语言;维护时需逐文件改字符串。
### 2.2 四角色仍零共享抽象P1 — v1 未处理)
| 维度 | 现状 | 期望 |
|------|------|------|
| 问候语头部 | `TeacherDashboardHeader``StudentDashboardHeader` 代码 90% 重复(仅 props 名不同) | 抽象为 `DashboardGreetingHeader` |
| 快捷操作 | admin 的 `QuickActionCard`内联、parent 的 `QUICK_ENTRIES`内联、teacher 的 `TeacherQuickActions` — 三套独立实现 | 抽象为 `DashboardQuickActions` |
| 仪表盘布局容器 | admin/teacher/student 各写一套 `<div className="space-y-*">` | 抽象为 `DashboardLayout` |
**违反规则**"最大化复用:识别四个角色共用的 UI 块和业务逻辑块,抽象为泛型组件和 hooks"。
### 2.3 无单测P2 — v1 未处理)
`lib/dashboard-utils.ts` 抽取了 6 个纯函数但**无任何单测**
| 函数 | 测试覆盖 | 风险 |
|------|----------|------|
| `toWeekday` | ❌ 无 | 周日映射错误未被发现 |
| `countStudentAssignments` | ❌ 无 | 边界条件(无截止日期/已批改)未验证 |
| `sortUpcomingAssignments` | ❌ 无 | 排序稳定性未验证 |
| `filterTodaySchedule` | ❌ 无 | 空课表/排序未验证 |
| `computeTeacherMetrics` | ❌ 无 | 提交率分母为零等边界未验证 |
| `getGreetingKey` | ❌ 无 | 时段边界12:00/18:00未验证 |
**违反规则**"数据获取、计算、格式化等纯逻辑全部放入纯函数或 hooks与 UI 分离;导出清晰的接口类型以便 mock" + "可测试性"。
### 2.4 a11y 不足P2 — v1 未处理)
| 位置 | 问题 | 违反规则 |
|------|------|----------|
| `admin-dashboard.tsx` 表格 | 无 `<caption>` | "语义化标签、ARIA 属性、键盘导航" |
| `recent-submissions.tsx` 表格 | 无 `<caption>` | 同上 |
| `student-upcoming-assignments-card.tsx` 表格 | 无 `<caption>` | 同上 |
| `teacher-dashboard-view.tsx` 布局 | 无 `<section>` / `<aside>` 语义化标签 | 同上 |
| `student-dashboard-view.tsx` 布局 | 同上 | 同上 |
| `teacher-schedule.tsx` 时间线 | 无 `aria-label` 描述当前/过去/未来状态 | 同上 |
### 2.5 流式渲染未实现P1 — v1 未处理)
所有 `page.tsx``export const dynamic = "force-dynamic"` + `Promise.all` 等全部数据就绪后才渲染。虽然 `DashboardSection` 内部有 Suspense但 page 层已无 Suspense 边界,无法流式渲染首屏。
---
## 三、改进优先级v2
### P0紧急 — v1 遗漏的 i18n
| # | 问题 | 改进方向 |
|---|------|----------|
| v2-P0-1 | 10 个组件英文硬编码 | 全部接入 `useTranslations` / `getTranslations`;补充翻译键 |
### P1较严重 — 共享抽象 + 单测)
| # | 问题 | 改进方向 |
|---|------|----------|
| v2-P1-1 | 问候语头部重复 | 抽象 `DashboardGreetingHeader` 组件 |
| v2-P1-2 | 纯函数无单测 | 为 `lib/dashboard-utils.ts` 6 个函数添加单测 |
### P2优化 — a11y + 流式)
| # | 问题 | 改进方向 |
|---|------|----------|
| v2-P2-1 | 表格无 caption / 布局无语义化标签 | 补充 `<caption>` / `<section>` / `aria-label` |
---
## 四、架构图同步说明
v2 修改完成后需同步更新:
### 4.1 `004_architecture_impact_map.md`
- §2.12 dashboard 章节:补充新增共享组件(`DashboardGreetingHeader`)、单测文件(`lib/dashboard-utils.test.ts`
### 4.2 `005_architecture_data.json`
- `modules.dashboard.exports.components`:新增 `DashboardGreetingHeader`
- `modules.dashboard.exports.lib`:补充单测覆盖说明