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
This commit is contained in:
121
docs/architecture/audit/dashboard-audit-report-v2.md
Normal file
121
docs/architecture/audit/dashboard-audit-report-v2.md
Normal file
@@ -0,0 +1,121 @@
|
||||
# 仪表盘模块审计报告 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`:补充单测覆盖说明
|
||||
Reference in New Issue
Block a user