Files
CICD/docs/design/002_teacher_dashboard_implementation.md
SpecialX ade8d4346c feat(dashboard): optimize teacher dashboard ui and layout
- Refactor layout: move Needs Grading to main column, Homework to sidebar
- Enhance TeacherStats: replace static counts with actionable metrics (Needs Grading, Active Assignments, Avg Score, Submission Rate)
- Update RecentSubmissions: table view with quick grade actions and late status
- Update TeacherSchedule: vertical timeline view with scroll hints
- Update TeacherHomeworkCard: compact list view
- Integrate Recharts: add TeacherGradeTrends chart and shared chart component
- Update documentation
2026-01-12 11:38:27 +08:00

9.9 KiB
Raw Blame History

教师仪表盘实现与 Hydration 修复记录

日期: 2025-12-23 作者: 资深前端工程师 (Senior Frontend Engineer) 状态: 已实现

1. 概述

本文档详细说明了教师仪表盘 (Teacher Dashboard) 的实现细节,该实现严格遵循 Next_Edu 设计系统 v1.3.0。文档还记录了开发过程中遇到的 Hydration 错误及其解决方案。

2. 组件架构

仪表盘采用垂直切片架构 (Vertical Slice Architecture),代码位于 src/modules/dashboard

2.1 文件结构

src/modules/dashboard/
└── components/
    ├── teacher-stats.tsx        # 核心指标 (学生数, 课程数, 待批改作业)
    ├── teacher-schedule.tsx     # 今日日程列表
    ├── recent-submissions.tsx   # 最近的学生提交记录
    └── teacher-quick-actions.tsx # 常用操作 (创建作业等)

2.2 设计系统集成

所有组件严格遵循 v1.3.0 规范:

  • 排版 (Typography): 使用 Geist Sans,数据展示开启 tabular-nums
  • 色彩 (Colors): 使用语义化 HSL 变量 (muted, primary, destructive)。
  • 图标 (Icons): 使用 lucide-react (如 Users, BookOpen, Inbox)。
  • 状态 (States):
    • Loading: 使用自定义骨架屏 (Skeleton),拒绝全屏 Spinner。
    • Empty: 使用 EmptyState 组件处理无数据场景。

3. 组件详情

3.1 TeacherStats (教师统计)

  • 用途: 展示教师当前状态的高层概览。
  • 特性:
    • 在响应式网格中展示 4 个关键指标。
    • 支持 isLoading 属性以渲染骨架屏。
    • 使用 Card 组件作为容器。

3.2 TeacherSchedule (教师日程)

  • 用途: 展示今日课程安排。
  • 特性:
    • 列出课程时间及地点。
    • 使用 Badge 区分 "Lecture" (讲座) 和 "Workshop" (研讨会)。
    • 空状态: 当无日程时显示 "No Classes Today"。

3.3 RecentSubmissions (最近提交)

  • 用途: 追踪最新的学生活动。
  • 特性:
    • 展示学生头像、姓名、作业名称及时间。
    • "Late" (迟交) 状态指示器。
    • 空状态: 当列表为空时显示 "No New Submissions"。

3.4 EmptyState Component (空状态组件)

  • 位置: src/shared/components/ui/empty-state.tsx
  • 规范:
    • 虚线边框容器。
    • 居中图标 (Muted 背景)。
    • 清晰的标题和描述。
    • 可选的操作按钮插槽。

4. Hydration 错误修复

4.1 问题描述

开发过程中观察到 "Hydration failed" 错误,原因是 HTML 嵌套无效。具体来说,是 p 标签内包含了块级元素(或 React 在 hydration 检查期间视为块级的元素)。

4.2 根本原因分析

React 的 hydration 过程对 HTML 有效性要求极高。将 div 放入 p 标签中违反了 HTML5 标准,但浏览器通常会自动修正 DOM 结构,导致实际 DOM 与 React 基于虚拟 DOM 预期的结构不一致。

4.3 实施的修复

将所有仪表盘组件中存在风险的 p 标签替换为 div 标签,以确保嵌套结构的健壮性。

示例 (RecentSubmissions):

修改前 (有风险):

<p className="text-sm font-medium leading-none">
  {item.studentName}
</p>

修改后 (安全):

<div className="text-sm font-medium leading-none">
  {item.studentName}
</div>

受影响的组件:

  1. recent-submissions.tsx
  2. teacher-stats.tsx
  3. teacher-schedule.tsx

5. 更新记录2026-01-04

  • 教师仪表盘从 Mock Data 切换为真实数据查询:/teacher/dashboard 组合 getTeacherClassesgetClassSchedulegetHomeworkSubmissions({ creatorId }) 渲染 KPI / 今日课表 / 最近提交。
  • Quick Actions 落地为真实路由跳转(创建作业、查看列表等)。
  • Schedule / Submissions 增加 “View All” 跳转到对应列表页(并携带筛选参数)。

6. 教师端班级管理模块(真实数据接入记录)

日期: 2025-12-31
范围: 教师端「我的班级 / 学生 / 课表」页面与 MySQL(Drizzle) 真数据对接

6.1 页面入口与路由

班级管理相关页面位于:

  • src/app/(dashboard)/teacher/classes/my/page.tsx
  • src/app/(dashboard)/teacher/classes/students/page.tsx
  • src/app/(dashboard)/teacher/classes/schedule/page.tsx

为避免构建期/预渲染阶段访问数据库导致失败,以上页面显式启用动态渲染:

  • export const dynamic = "force-dynamic"

6.2 模块结构Vertical Slice

班级模块采用垂直切片架构,代码位于 src/modules/classes/

src/modules/classes/
├── components/
│   ├── my-classes-grid.tsx
│   ├── students-filters.tsx
│   ├── students-table.tsx
│   ├── schedule-filters.tsx
│   └── schedule-view.tsx
├── data-access.ts
└── types.ts

其中 data-access.ts 负责班级、学生、课表三类查询的服务端数据读取,并作为页面层唯一的数据入口。

6.3 数据库表与迁移

新增班级领域表:

  • classes
  • class_enrollments
  • class_schedule

对应 Drizzle Schema

  • src/shared/db/schema.ts
  • src/shared/db/relations.ts

对应迁移文件:

  • drizzle/0003_petite_newton_destine.sql

外键关系(核心):

  • classes.teacher_id -> users.id
  • class_enrollments.class_id -> classes.id
  • class_enrollments.student_id -> users.id
  • class_schedule.class_id -> classes.id

索引(核心):

  • classes_teacher_idx, classes_grade_idx
  • class_enrollments_class_idx, class_enrollments_student_idx
  • class_schedule_class_idx, class_schedule_class_day_idx

6.4 Seed 数据

Seed 脚本已覆盖班级相关数据,以便在开发环境快速验证页面渲染与关联关系:

  • scripts/seed.ts
  • 运行命令:npm run db:seed

6.5 开发过程中的问题与处理

  • 端口占用EADDRINUSE开发服务器端口被占用时通过更换端口启动规避例如 next dev -p <port>)。
  • Next dev 锁文件:出现 .next/dev/lock 无法获取锁时,需要确保只有一个 dev 实例在运行,并清理残留 lock。
  • 头像资源 404移除 Header 中硬编码的本地头像资源引用,避免 public/avatars/... 不存在导致的 404 噪音(见 src/modules/layout/components/site-header.tsx)。
  • 班级人数统计查询失败:class_enrollments 表实际列名为 class_enrollment_status,修复查询中引用的列名以恢复教师端班级列表渲染。
  • Students 页面 key 冲突:学生列表跨班级汇总时,<TableRow key={studentId}> 会重复,改为使用 classId:studentId 作为 key。
  • Build 预渲染失败(/loginLoginForm 使用 useSearchParams() 获取回跳地址,需在 /login 页面用 Suspense 包裹以避免 CSR bailout 报错。
  • 构建警告middlewareNext.js 16 将文件约定从 middleware.ts 改为 proxy.ts,已迁移以消除警告。

6.6 班级详情页(聚合视图 + Schedule Builder + Homework 统计)

日期: 2026-01-04
入口: src/app/(dashboard)/teacher/classes/my/[id]/page.tsx

聚合数据在单次 RSC 请求内并发获取:

  • 学生:getClassStudents({ classId })
  • 课表:getClassSchedule({ classId })
  • 作业统计:getClassHomeworkInsights({ classId, limit })(包含 latest、历史列表、overallScores、以及每次作业的 scoreStatsavg/median

页面呈现:

  • 顶部 KPI 卡片:学生数、课表条目数、作业数、整体 avg/median
  • Latest homework目标人数、提交数、批改数、avg/median直达作业与提交列表
  • Students / Schedule 预览:提供 View all 跳转到完整列表页
  • Homework history 表格:支持通过 URL query ?hw=all|active|overdue 过滤作业记录,并展示每条作业的 avg/median

课表编辑能力复用既有 Builder

  • 组件:src/modules/classes/components/schedule-view.tsx(新增/编辑/删除课表项)
  • 数据变更:src/modules/classes/actions.ts

6.7 班级邀请码6 位码)加入与管理

日期: 2026-01-08
范围: 为班级新增 6 位邀请码,支持学生通过输入邀请码加入班级;教师可查看与刷新邀请码


7. 教师仪表盘体验优化 (2026-01-12)

目标: 提升教师仪表盘的信息密度与易用性,优化核心指标展示,调整布局以符合教师工作流。

7.1 核心指标卡片重构 (TeacherStats)

  • 原有问题: 展示的总学生数、总课程数等静态指标对日常教学决策帮助有限。
  • 优化方案: 替换为高频动态指标,并增强视觉提示。
    • Needs Grading (待批改): 高亮显示待处理事项,使用 Amber 色彩引起注意。
    • Active Assignments (活跃作业): 显示当前发布的作业数量,反映教学负载。
    • Average Score (平均分): 展示近期作业平均分,快速了解学情。
    • Submission Rate (提交率): 展示整体作业完成度,反映学生参与度。

7.2 布局调整 (Layout Restructuring)

  • 原有问题: "Needs Grading" 位于侧边栏,空间受限;"Homework" 列表占据主栏,信息密度低。
  • 优化方案:
    • Needs Grading 移至主栏: 给予更多宽幅空间,展示详细的学生、作业信息及操作按钮。
    • Homework 移至侧边栏: 改为紧凑列表视图,作为快速导航入口。
    • Schedule 优化: 引入时间轴 (Timeline) 视图,支持滚动提示与当前状态指示。

7.3 组件功能增强

  • RecentSubmissions (Needs Grading):
    • 升级为 Table 视图,展示头像、作业名、提交时间。
    • 增加 "Grade" 快捷按钮,一键进入批改页面。
    • 增加 "Late" 状态标记。
  • TeacherSchedule:
    • 采用垂直时间轴设计。
    • 增加滚动提示 (Scroll Hint) 与 "No more classes" 状态提示。
  • TeacherHomeworkCard:
    • 优化为紧凑型列表,显示发布状态 (Published/Draft) 与截止日期。

7.4 技术细节

  • 引入 recharts 替换手写 SVG 图表,统一图表风格。
  • 优化 Grid 布局响应式表现 (lg:grid-cols-12)。