按 ARCHITECTURE.md §9.4 规划口径 + admin-NeedTodo.md §四补充批次完成管理域全量页面迁移: 【§9.4 规划 24 页(B5)】 - users(2) + roles(1) + permissions(1) + audit-logs(4) + invitation-codes(1) - school(6: redirect/schools/classes/departments/academic-year/grades) - announcements(1) + files(1) + ai-settings(1) + system(1) + viewports(1) - students(1) + teachers(1) + organization(1) + plugins(1, config-service) - 仪表盘已存在(/shell/admin/page.tsx) 【§四补充批次 21 页】 - course-plans(4) + elective(4) + questions(1) + lesson-plans(2) + error-book(1) - scheduling(3: auto/changes/rules) + attendance(1) + curriculum-map(1) - announcements 详情/编辑(2) + roles/[id] 详情(1) + users/import(1) 【实现要点】 - 全部使用 ListPageShell + loading/error/empty 三态规范(§11.3 DoD) - 走 lib/api hooks;未就绪契约走 MSW + @contract-pending 注释(§11.4) - 文案走 useTranslations(zh-CN + en 两份同步更新) - 42 个 features/<domain>/transformations.ts 纯函数 + 配套 vitest 单测 - catch 块统一 notify.error;无空 catch;lint:tokens 通过 - 路由全部登记到 route-permissions.ts(39 EXACT + 8 PREFIX) 【验收】 - tsc --noEmit: 0 errors - ESLint src: 0 errors (4 generated-files warnings, pre-existing) - lint:tokens: 0 errors - vitest: 1639/1639 passed (含 23 admin 测试文件 671 用例) - check:routes: PASS (143 routes, 4 ghost entries pre-existing) - check:pages: PASS (146 pages) - check:codegen: PASS - arch:scan: 24 modules, 8262 symbols 关联:ARCHITECTURE.md §9.4 / §10 P5 / §11.3 DoD / §11.6
49 KiB
学生域(Student)待完成功能分析
参考项目:
e:\desktop\CICD\src\app\(dashboard)\student\当前项目:e:\Desktop\Edu\apps\portal-shell\src\app\shell\student\规划依据:apps/portal-shell/ARCHITECTURE.md§9.2(36 页,B3 批次) 分析日期:2026-07-24 任务范围:仅分析,不写代码
一、页面完成度总览
1.1 portal-shell 学生域现状
当前 apps/portal-shell/src/app/shell/student/ 下仅有 1 个页面:
| 路径 | 状态 | 说明 |
|---|---|---|
/shell/student/page.tsx |
✅ 已完成 | 学生仪表盘(仅基础版,缺 trend/weakness 详情页) |
1.2 完成度统计
| 状态 | 数量 | 说明 |
|---|---|---|
| ✅ 已完成 | 1 | /shell/student/page.tsx(仪表盘基础版,仍缺 2 个详情页) |
| 🟡 部分完成 | 1 | dashboard 模块(基础页有,trend/weakness 详情页缺) |
| ❌ 缺失 | 34 | 见下方模块清单 |
| 规划总数 | 36 | ARCHITECTURE.md §9.2 B3 批次 |
1.3 portal-shell 仪表盘与 CICD 仪表盘的技术差异(关键架构差异)
| 维度 | CICD 仪表盘 | portal-shell 仪表盘 |
|---|---|---|
| 渲染模式 | Server Component(async function) |
Client Component("use client") |
| 数据获取 | Server Action getStudentDashboardAction() + Suspense 流式渲染 |
useStudentDashboard() Hook(@/lib/api,走 BFF) |
| 国际化 | next-intl getTranslations |
无(硬编码中文) |
| 权限校验 | requirePermission + getAuthContext |
无 |
| 视图组件 | StudentDashboard 视图模块(拆分到 @/modules/dashboard/components) |
直接内联在 page.tsx |
| 数据来源 | 直查 DB(Drizzle) | 走 data-ana 微服务聚合 |
重要提示:portal-shell 已转向微服务 + BFF 架构,迁移时不能照搬 CICD 的 Server Action + Drizzle 直查模式。学生页面应通过
teacher-bff/data-ana等服务的 gRPC/HTTP API 获取数据,前端通过 hooks 消费。
二、缺失页面清单(按模块分组)
2.1 dashboard 模块(3 页规划,1 已完成,2 缺失)
2.1.1 ✅ /shell/student/page.tsx(已完成)
- portal-shell 实现:基础仪表盘,显示平均分 / 班级排名 / 待交作业 + 薄弱知识点 + 近期成绩趋势
- 技术栈:Client Component +
useStudentDashboard()Hook +DashboardShell/StatCard共享组件 - CICD 参考实现:
e:\desktop\CICD\src\app\(dashboard)\student\dashboard\page.tsx - CICD 技术栈:Server Component +
getStudentDashboardAction()Server Action +StudentDashboard视图组件 + Suspense 流式渲染 - ARCHITECTURE.md 契约:✅
studentDashboard
2.1.2 ❌ /shell/student/trend(学习趋势详情页,缺失)
- CICD 参考实现:CICD 无独立
/trend页面(融合在 dashboard 中以recent_trends字段呈现) - 功能描述:学生学习趋势详情页,应展示更完整的历史成绩趋势、知识点掌握趋势、对比基线
- 技术栈建议:复用
learningTrend契约 + 趋势图组件(Recharts/Echarts) - ARCHITECTURE.md 契约:✅
learningTrend - CICD 关键代码片段:dashboard 中仅以单条
recent_trends: { date, score }呈现,需 portal-shell 自行扩展为详情页
2.1.3 ❌ /shell/student/weakness(薄弱知识点详情页,缺失)
- CICD 参考实现:CICD 无独立
/weakness页面(融合在 dashboard 中以weak_points: { title, mastery, error_count }字段呈现) - 功能描述:学生薄弱知识点详情页,应展示完整的薄弱知识点列表、按学科分组、关联错题、推荐练习
- 技术栈建议:复用
studentWeakness契约 + 错题本 / 练习模块联动跳转 - ARCHITECTURE.md 契约:✅
studentWeakness - CICD 关键代码片段:dashboard 中仅以单条
weak_points呈现,需 portal-shell 自行扩展
2.2 grades 模块(2 页规划,0 已完成,2 缺失)
2.2.1 ❌ /shell/student/grades(我的成绩列表,缺失)
- CICD 参考实现:
e:\desktop\CICD\src\app\(dashboard)\student\grades\page.tsx - 功能描述:
- 学生本人成绩汇总(姓名 + 记录数)
- 学科 / 类型 / 学期 / 关键字 4 维过滤器
- 成绩趋势卡片(含班级平均对比线)
- 排名趋势卡片
- 班级分布直方图(隐私保护视图,仅展示本人位置标注)
- 学生纵向成长档案(跨学年/学期聚合)
- 成绩汇总明细表
- 技术栈:
- Server Component(
async function)+force-dynamic - Server Actions:
getStudentGradeSummary/getRankingTrend/getClassAverageTrend/getStudentPositionInClassDistribution/getStudentGrowthArchive/getSubjectOptions requirePermission(Permissions.GRADE_RECORD_READ)+ctx.dataScope- 组件:
StudentGradeSummary/StudentGradeFilters/GradeTrendCard/RankingTrendCard/GradeDistributionChart/GrowthArchiveChart/EmptyState - searchParams 过滤(
q/subject/type/semester)
- Server Component(
- ARCHITECTURE.md 契约:❌(列表,未定义)
2.2.2 ❌ /shell/student/grades/report-card(成绩报告卡,缺失)
- CICD 参考实现:
e:\desktop\CICD\src\app\(dashboard)\student\grades\report-card\page.tsx - 功能描述:
- 学年 / 学期可切换的成绩报告卡
- 报告卡视图(学生本人维度聚合)
- 打印操作(
ReportCardPrintAction) - 返回成绩列表的面包屑
- 技术栈:
- Server Component +
force-dynamic - Server Actions:
getReportCardData(ctx.userId, ctx.dataScope, { academicYearId, semester })+getAcademicYears() requirePermission(Permissions.GRADE_RECORD_READ)- 组件:
ReportCardView/ReportCardPrintAction/Button/EmptyState - searchParams:
academicYearId/semester
- Server Component +
- ARCHITECTURE.md 契约:❌(未单独定义)
2.3 exams 模块(3 页规划,0 已完成,3 缺失)⚠️ 重点
CICD 参考项目无 exams 模块学生页面。学生考试相关功能需 portal-shell 从零设计。
2.3.1 ❌ /shell/student/exams(我的考试列表,缺失)
- CICD 参考实现:❌ CICD 无对应源页面
- 功能描述:学生视角的考试列表,应展示:
- 即将到来的考试(含倒计时、考场、座位号)
- 已结束考试(含成绩、查看结果入口)
- 按学科 / 状态过滤
- 技术栈建议:参考 CICD
learning/assignments/page.tsx的列表分组 + 状态徽章模式 - ARCHITECTURE.md 契约:🟡(部分,需补充)
2.3.2 ❌ /shell/student/exams/[id]/result(考试结果页,缺失)
- CICD 参考实现:❌ CICD 无对应源页面(可参考
learning/assignments/[assignmentId]/result/page.tsx的同构模式) - 功能描述:
- 考试得分、排名、班级均分对比
- 题目作答详情(每题对错、参考答案、学生答案)
- 知识点掌握情况
- 错题一键加入错题本
- 技术栈建议:参考 CICD
HomeworkSubmissionResult组件 +getStudentSubmissionResult数据访问模式 - ARCHITECTURE.md 契约:🟡(部分,需补充)
2.3.3 ❌ /shell/student/exams/[id]/take(考试作答工作台,缺失)⚠️ 关键
- CICD 参考实现:❌ CICD 无对应源页面(可参考
learning/assignments/[assignmentId]/page.tsx的HomeworkTakeView同构模式) - 功能描述:考试作答工作台,应包含:
- 题目导航栏(题号、未答/已答/标记状态)
- 题目作答区(单选/多选/填空/简答)
- 倒计时(自动提交)
- 答案本地暂存(防刷新丢失)
- 提交确认 + 二次确认
- 中途断网恢复
- 技术栈建议:
- 客户端组件(
HomeworkTakeView是 client component) - 答案本地存储(localStorage / IndexedDB)
- 自动保存定时器
- 提交走 Server Action / BFF API
- 客户端组件(
- ARCHITECTURE.md 契约:🟡(部分,需补充)
⚠️ 此页是学生域最复杂、最关键的页面,需在 B3 中重点投入。CICD 的
HomeworkTakeView是最近的同构参考,但其路由是learning/assignments/[assignmentId]而非exams/[id]/take。
2.4 homework 模块(3 页规划,0 已完成,3 缺失)
CICD 实际路由是
learning/assignments/*,ARCHITECTURE.md §9.2 计划将其提升到homework/*顶层。
2.4.1 ❌ /shell/student/homework(我的作业列表,缺失)
- CICD 参考实现:
e:\desktop\CICD\src\app\(dashboard)\student\learning\assignments\page.tsx - 功能描述:
- 作业列表,按学科分组展示
- 每组内按"未答 / 已答"二分桶(PERF-05 单次遍历分桶)
- 每张卡片:标题、状态徽章、截止时间、剩余尝试次数、最新得分、逾期提示
- 学科 dot 颜色(hash 稳定映射)
- 状态过滤(all/pending/submitted/graded)+ 关键字搜索
AssignmentCard用React.memo优化高频渲染
- 技术栈:
- Server Component +
force-dynamic - Server Action:
getStudentHomeworkAssignments(student.id) - 组件:
AssignmentFilters/StatusBadge/Card/EmptyState/memo(AssignmentCard) - 工具:
formatDate/getParam/cn/STUDENT_HOMEWORK_PROGRESS_VARIANT
- Server Component +
- ARCHITECTURE.md 契约:🟡(部分)
2.4.2 ❌ /shell/student/homework/[id]/submit(作业作答/提交,缺失)⚠️ 关键
- CICD 参考实现:
e:\desktop\CICD\src\app\(dashboard)\student\learning\assignments\[assignmentId]\page.tsx - 功能描述:
- 根据
submission.status分流:graded/submitted→ 进入HomeworkReviewView(查看提交后/批改后视图)not_started/in_progress→ 进入HomeworkTakeView(作答工作台)
- 顶部展示作业标题、截止时间、最大尝试次数
- 根据
- 技术栈:
- Server Component(外壳)+ Client Component(
HomeworkTakeView/HomeworkReviewView) - Server Action:
getStudentHomeworkTakeData(assignmentId, student.id) - 组件:
HomeworkTakeView/HomeworkReviewView
- Server Component(外壳)+ Client Component(
- ARCHITECTURE.md 契约:🟡(部分)
2.4.3 ❌ /shell/student/homework/[id]/analysis(作业分析/结果,缺失)
- CICD 参考实现:
e:\desktop\CICD\src\app\(dashboard)\student\learning\assignments\[assignmentId]\result\page.tsx - 功能描述:
- 作业标题 + 提交结果详情
- 通过
HomeworkSubmissionResult组件展示分析(含每题得分、参考答案等)
- 技术栈:
- Server Component +
force-dynamic - Server Actions:
getHomeworkAssignmentById(assignmentId)+getStudentSubmissionResult(assignmentId, studentId) - 通过
getSession()获取 studentId(非requirePermission模式,需注意) - 组件:
HomeworkSubmissionResult
- Server Component +
- ARCHITECTURE.md 契约:🟡(部分)
2.5 schedule 模块(1 页规划,0 已完成,1 缺失)
2.5.1 ❌ /shell/student/schedule(学生课表,缺失)
- CICD 参考实现:
e:\desktop\CICD\src\app\(dashboard)\student\schedule\page.tsx - 功能描述:
- 学生个人课表(按班级聚合)
- 班级过滤器(
classIdsearchParam,默认all) - 顶部标题 + 班级筛选器
StudentScheduleView渲染课表
- 技术栈:
- Server Component +
force-dynamic+generateMetadata - Server Actions:
getStudentClasses(student.id)+getStudentSchedule(student.id) requirePermission(Permissions.CLASS_READ)+getCurrentStudentUser()- 组件:
StudentScheduleFilters/StudentScheduleView/EmptyState - searchParams:
classId
- Server Component +
- ARCHITECTURE.md 契约:❌
2.6 attendance 模块(1 页规划,0 已完成,1 缺失)
2.6.1 ❌ /shell/student/attendance(学生考勤,缺失)
- CICD 参考实现:
e:\desktop\CICD\src\app\(dashboard)\student\attendance\page.tsx - 功能描述:
- 学生本人考勤汇总(出勤率、迟到/早退/请假次数)
- 通过
StudentAttendanceView渲染详细记录 - 无数据时显示
EmptyState
- 技术栈:
- Server Component +
force-dynamic - Server Action:
getStudentAttendanceSummary(ctx.userId) requirePermission(Permissions.ATTENDANCE_READ)+getAuthContext()- 组件:
StudentAttendanceView/EmptyState
- Server Component +
- ARCHITECTURE.md 契约:❌
2.7 classes 模块(1 页规划,0 已完成,1 缺失)
2.7.1 ❌ /shell/student/classes(我的班级,缺失)
- CICD 参考实现:❌ CICD 学生端无独立
/classes路由(班级信息融合在learning/courses/*中) - 功能描述:
- 学生所在的班级列表(含班主任、教室、学校、年级、活跃状态)
- 区别于 courses(课程):classes 侧重"行政班/教学班"维度,courses 侧重"学科课程"维度
- 可跳转到该班的课表、作业、同学(受权限限制)
- 技术栈建议:参考 CICD
learning/courses/page.tsx的列表 + 过滤模式 - ARCHITECTURE.md 契约:❌
myClasses
2.8 courses 模块(2 页规划,0 已完成,2 缺失)
2.8.1 ❌ /shell/student/courses(课程列表,缺失)
- CICD 参考实现:
e:\desktop\CICD\src\app\(dashboard)\student\learning\courses\page.tsx - 功能描述:
- 学生报名的课程(班级)列表
- 关键字搜索(名称 / 教师 / 学校 / 班主任)
- 通过
StudentCoursesView渲染 - 仅有班级时才显示过滤器
- 技术栈:
- Server Component +
force-dynamic+generateMetadata - Server Action:
getStudentClasses(student.id) requirePermission(Permissions.CLASS_READ)+getCurrentStudentUser()- 组件:
CourseFilters/StudentCoursesView/EmptyState - searchParams:
q
- Server Component +
- ARCHITECTURE.md 契约:❌
2.8.2 ❌ /shell/student/courses/[id](课程详情,缺失)
- CICD 参考实现:
e:\desktop\CICD\src\app\(dashboard)\student\learning\courses\[classId]\page.tsx - 功能描述:
- 班级(课程)详情页:名称、年级、班主任、教室、学校
- 三列卡片:教师信息(姓名 + 邮箱 mailto)/ 学校信息 / 教室信息
- 本班课表:按 weekday 排序的列表
- 顶部按钮:跳转完整课表、跳转作业列表
- 技术栈:
- Server Component +
force-dynamic+generateMetadata - Server Actions:
getStudentClassById(student.id, classId)+getStudentSchedule(student.id) requirePermission(Permissions.CLASS_READ)+getCurrentStudentUser()- 组件:
Card/Badge/Button/EmptyState - 路由参数:
classId
- Server Component +
- ARCHITECTURE.md 契约:❌
2.9 course-plans 模块(2 页规划,0 已完成,2 缺失)
2.9.1 ❌ /shell/student/course-plans(课程计划列表,缺失)
- CICD 参考实现:
e:\desktop\CICD\src\app\(dashboard)\student\course-plans\page.tsx - 功能描述:
- 学生视角的课程计划列表(仅
status: "active") - 通过
class_membersscope 过滤可见的 classIds CoursePlanList渲染,detailBaseHref 指向/student/course-plans
- 学生视角的课程计划列表(仅
- 技术栈:
- Server Component +
force-dynamic - Server Action:
getCoursePlans({ status: "active" }, { userId, isAdmin: false, classIds }) requirePermission(Permissions.COURSE_PLAN_READ)- 组件:
CoursePlanList
- Server Component +
- ARCHITECTURE.md 契约:❌
2.9.2 ❌ /shell/student/course-plans/[id](课程计划详情,缺失)
- CICD 参考实现:
e:\desktop\CICD\src\app\(dashboard)\student\course-plans\[id]\page.tsx - 功能描述:
- 课程计划详情视图(学生只读)
- 通过 class_members scope 过滤
CoursePlanDetail渲染,关联教材跳转/student/learning/textbooks
- 技术栈:
- Server Component +
force-dynamic - Server Action:
getCoursePlanById(id, { userId, isAdmin: false, classIds }) requirePermission(Permissions.COURSE_PLAN_READ)- 组件:
CoursePlanDetail - 路由参数:
id notFound()兜底
- Server Component +
- ARCHITECTURE.md 契约:❌
2.10 lesson-plans 模块(2 页规划,0 已完成,2 缺失)
2.10.1 ❌ /shell/student/lesson-plans(教案列表,缺失)
- CICD 参考实现:
e:\desktop\CICD\src\app\(dashboard)\student\lesson-plans\page.tsx - 功能描述:
- 学生视角的教案列表(仅
status: "published") LessonPlanList学生视图模式(viewMode="student")LessonPlanProviderSetup注入学生角色配置(让筛选生效)
- 学生视角的教案列表(仅
- 技术栈:
- Server Component +
force-dynamic - Server Actions:
getLessonPlans({ status: "published" }, ctx.dataScope, ctx.userId)+getSubjectOptions() requirePermission(Permissions.LESSON_PLAN_READ)- 组件:
LessonPlanList/LessonPlanProviderSetup/STUDENT_ROLE_CONFIG/Skeleton+Suspense
- Server Component +
- ARCHITECTURE.md 契约:❌
2.10.2 ❌ /shell/student/lesson-plans/[planId]/view(教案只读查看,缺失)
- CICD 参考实现:
e:\desktop\CICD\src\app\(dashboard)\student\lesson-plans\[planId]\view\page.tsx - 功能描述:
- 教案只读视图
- 权限收敛:学生仅可查看本年级已发布教案(
assertPlanInScope),未发布显示提示 - 拉取教材标题 + 章节标题(并行
Promise.all) LessonPlanReadonlyView渲染文档内容
- 技术栈:
- Server Component +
force-dynamic - Server Actions:
getLessonPlanById(planId, ctx.userId)+getTextbookById+getChaptersByTextbookId+findChapterById requirePermission(Permissions.LESSON_PLAN_READ)+assertPlanInScope(plan, ctx)- 组件:
LessonPlanReadonlyView/Skeleton+Suspense - 路由参数:
planId
- Server Component +
- ARCHITECTURE.md 契约:❌
2.11 textbooks 模块(2 页规划,0 已完成,2 缺失)
2.11.1 ❌ /shell/student/textbooks(教材列表,缺失)
- CICD 参考实现:
e:\desktop\CICD\src\app\(dashboard)\student\learning\textbooks\page.tsx - 功能描述:
- 学生视角的教材列表
- 强制按学生所在年级过滤(
getGradeNameById解析 gradeId 为年级名称) - 关键字 / 学科 / 年级 3 维过滤器
TextbookCard网格(4 列响应式)- 学生端
hideActions(无编辑权限)
- 技术栈:
- Server Component +
force-dynamic - Server Actions:
getTextbooksWithScope(q, subject, grade, { grade: studentGradeName })+getGradeNameById requirePermission(Permissions.TEXTBOOK_READ)+getCurrentStudentUser()- 组件:
TextbookCard/TextbookFilters/EmptyState - searchParams:
q/subject/grade
- Server Component +
- ARCHITECTURE.md 契约:🟡
2.11.2 ❌ /shell/student/textbooks/[id]/chapters(教材章节阅读器,缺失)
- CICD 参考实现:
e:\desktop\CICD\src\app\(dashboard)\student\learning\textbooks\[id]\page.tsx - 功能描述:
- 教材阅读器(
TextbookReader) - 顶部固定标题栏:教材标题 + 学科 Badge + 年级 Badge
- 章节列表 + 阅读区
- 年级校验:教材年级与学生年级不匹配则
notFound()(防越权) - 学生端不传
renderQuestionCreator(无题目创建权限) - 高度自适应(
h-[calc(100vh-4rem-3rem)])
- 教材阅读器(
- 技术栈:
- Server Component +
force-dynamic - Server Actions:
getTextbookById(id)+getChaptersByTextbookId(id)+getGradeNameById requirePermission(Permissions.TEXTBOOK_READ)+getCurrentStudentUser()- 组件:
TextbookReader/Badge/EmptyState - 路由参数:
id
- Server Component +
- ARCHITECTURE.md 契约:🟡
- 注:ARCHITECTURE.md §9.2 路径为
/[id]/chapters,CICD 路径为/[id],迁移时需对齐
2.12 error-book 模块(1 页规划,0 已完成,1 缺失)
2.12.1 ❌ /shell/student/error-book(错题本,缺失)
- CICD 参考实现:
e:\desktop\CICD\src\app\(dashboard)\student\error-book\page.tsx - 功能描述:
- 5 列统计卡片:总数 / 新增 / 学习中 / 已掌握(含掌握率%)/ 待复习(高亮 overdue)
- 新增错题对话框(
AddErrorBookDialogWithQuestions,带题目选择器) - 筛选器:关键字 / 状态 / 来源 / 仅看待复习
- 错题列表(客户端组件
StudentErrorBookListClient) - AI 上下文注入:
AiClientProvider+createCoreAiClientService WidgetBoundary包裹关键 widget(降级容错)Suspense流式渲染过滤器 + 结果列表
- 技术栈:
- Server Component +
force-dynamic - Server Actions:
getErrorBookItems({ studentId, q, status, sourceType, dueOnly, pageSize: 50 })+getErrorBookStats(ctx.userId) requirePermission(Permissions.ERROR_BOOK_READ)- 组件:
StatsGrid/AddErrorBookDialogWithQuestions/ErrorBookFilters/StudentErrorBookListClient/WidgetBoundary/AiClientProvider - 状态枚举守卫:
isErrorBookStatus/isErrorBookSource(类型守卫)
- Server Component +
- ARCHITECTURE.md 契约:✅
2.13 learning 模块(2 页规划,0 已完成,2 缺失)
2.13.1 ❌ /shell/student/learning(学习中心首页,缺失)
- CICD 参考实现:
e:\desktop\CICD\src\app\(dashboard)\student\learning\page.tsx - 功能描述:
- 学习中心首页,3 张导航卡片:
- 课程(已报名班级数)
- 作业(待交数 + 即将到期数,7 天内)
- 教材(可用数)
- 每张卡片含图标 / 标题 / 描述 / 统计 / 箭头
- 学生身份校验(
getCurrentStudentUser),无则显示EmptyState
- 学习中心首页,3 张导航卡片:
- 技术栈:
- Server Component +
force-dynamic+generateMetadata - Server Actions:
getStudentClasses+getStudentHomeworkAssignments+getTextbooks requirePermission(Permissions.CLASS_READ)- 组件:
Card/EmptyState - 业务逻辑:
pendingCount(未提交+未批改)/dueSoonCount(7 天内到期)计算
- Server Component +
- ARCHITECTURE.md 契约:❌
2.13.2 ❌ /shell/student/learning-path(AI 学习路径,缺失)
- CICD 参考实现:
e:\desktop\CICD\src\app\(dashboard)\student\learning\study-path\page.tsx - 功能描述:
- AI 生成的个性化学习路径
AiStudyPath客户端组件,由 dashboard layout 注入AiClientProvider- 学生身份校验
- 技术栈:
- Server Component +
force-dynamic+generateMetadata requirePermission(Permissions.AI_CHAT)(与 AI_CHAT 权限点一致,防止学生角色被关闭后页面仍可访问)getCurrentStudentUser()- 组件:
AiStudyPath(client component)/EmptyState
- Server Component +
- ARCHITECTURE.md 契约:❌
- 注:ARCHITECTURE.md §9.2 路径为
/learning-path(顶层),CICD 路径为/learning/study-path,迁移时需对齐
2.14 practice 模块(2 页规划,0 已完成,2 缺失)
2.14.1 ❌ /shell/student/practice(自适应练习首页,缺失)
- CICD 参考实现:
e:\desktop\CICD\src\app\(dashboard)\student\practice\page.tsx - 功能描述:
- 4 列统计卡片:总练习次数 / 已完成 / 总答题数 / 正确率
- 左侧:
PracticeStarterWithNav(练习启动器 + 知识点选择 + 导航) - 右侧:
PracticeHistory(历史会话列表) PracticeServiceProvider包裹(注入练习服务)
- 技术栈:
- Server Component +
force-dynamic - Server Actions:
getPracticeStats(ctx.userId)+getPracticeSessions(ctx.userId, { pageSize: 20 })+getKnowledgePointOptions() requirePermission(Permissions.ADAPTIVE_PRACTICE_READ)- 组件:
StatsGrid/PracticeStarterWithNav/PracticeHistory/PracticeServiceProvider
- Server Component +
- ARCHITECTURE.md 契约:❌
2.14.2 ❌ /shell/student/practice/[sessionId](练习会话页,缺失)
- CICD 参考实现:
e:\desktop\CICD\src\app\(dashboard)\student\practice\[sessionId]\page.tsx - 功能描述:
- 单个练习会话详情
PracticeSessionView渲染(题目作答 + 即时反馈 + 进度)- 学生身份校验(防止跨用户访问)
- 技术栈:
- Server Component +
force-dynamic - Server Action:
getPracticeSessionById(sessionId, ctx.userId) requirePermission(Permissions.ADAPTIVE_PRACTICE_READ)- 组件:
PracticeSessionView/PracticeServiceProvider - 路由参数:
sessionId notFound()兜底
- Server Component +
- ARCHITECTURE.md 契约:❌
2.15 elective 模块(2 页规划,0 已完成,2 缺失)
2.15.1 ❌ /shell/student/elective(选课列表,缺失)
- CICD 参考实现:
e:\desktop\CICD\src\app\(dashboard)\student\elective\page.tsx - 功能描述:
- 上下两段式布局:
- 我的选课(
MySelectionsLoader,Suspense 流式加载) - 可选课程(
AvailableCoursesLoader,Suspense 流式加载 + searchParams 过滤)
- 我的选课(
- 学生身份校验
- 上下两段式布局:
- 技术栈:
- Server Component +
force-dynamic requirePermission(Permissions.ELECTIVE_READ)- 子组件:
MySelectionsLoader/AvailableCoursesLoader/MySelectionsSkeleton/AvailableCoursesSkeleton(均在_components/下) Suspense双段流式渲染- searchParams 透传到
AvailableCoursesLoader
- Server Component +
- ARCHITECTURE.md 契约:❌
2.15.2 ❌ /shell/student/elective/[id](选课详情,缺失)
- CICD 参考实现:
e:\desktop\CICD\src\app\(dashboard)\student\elective\[id]\page.tsx - 功能描述:
- 选修课程详情视图
- 学生视角隐私保护:只展示课程信息,不展示选课名单(
selections=[]),showEditButton=false - 通过
ElectivePageLayout+ElectiveCourseDetail组合渲染
- 技术栈:
- Server Component +
force-dynamic - Server Action:
getElectiveCourseById(id) requirePermission(Permissions.ELECTIVE_READ)- 组件:
ElectiveCourseDetail/ElectivePageLayout - 路由参数:
id notFound()兜底
- Server Component +
- ARCHITECTURE.md 契约:❌
2.16 ai-tutor 模块(1 页规划,0 已完成,1 缺失)
2.16.1 ❌ /shell/student/ai-tutor(AI 辅导,缺失)⚠️ B3 末
- CICD 参考实现:❌ CICD 无对应源页面
- 功能描述:
- 学生专属 AI 辅导对话(区别于通用 AI 聊天)
- 应基于学生学情(薄弱点、近期错题、当前进度)提供个性化辅导
- 可能的形态:聊天对话框 + 上下文卡片(学情摘要)
- 技术栈建议:参考 CICD
learning/study-path/page.tsx的AiStudyPath+AiClientProvider模式 +requirePermission(Permissions.AI_CHAT) - ARCHITECTURE.md 契约:❌
- 批次:B3 末
2.17 announcements 模块(共享 2 页规划,0 已完成,2 缺失)
2.17.1 ❌ /shell/announcements(公告列表,缺失,共享)
- CICD 参考实现:❌ CICD
student/下无对应源页面(应在(dashboard)/顶层共享路由中,但本次未读取) - 功能描述:公告列表(学生可见范围)
- ARCHITECTURE.md 契约:❌(列表未定义)
- 批次:B3,共享路由
2.17.2 ❌ /shell/announcements/[id](公告详情,缺失,共享)
- CICD 参考实现:❌ 同上
- 功能描述:单条公告详情
- ARCHITECTURE.md 契约:❌
- 批次:B3,共享路由
注:portal-shell 当前
/shell/announcements/*路由不存在。需在共享层(非 student/ 下)创建。
2.18 messages 模块(共享 1 页规划,0 已完成,1 缺失)
2.18.1 ❌ /shell/messages(消息中心,缺失,共享)⚠️ B3 末
- CICD 参考实现:❌ CICD
student/下无对应源页面 - 功能描述:站内消息中心(学生收件箱)
- ARCHITECTURE.md 契约:❌
- 批次:B3 末,共享路由
注:portal-shell 当前
/shell/messages路由不存在。
2.19 leave 模块(1 页规划,0 已完成,1 缺失)
2.19.1 ❌ /shell/student/leave(学生在线请假,缺失)
- CICD 参考实现:
e:\desktop\CICD\src\app\(dashboard)\student\leave\page.tsx - 功能描述:
- 顶部:在线请假表单(
LeaveRequestForm,defaultStudentId+defaultClassId自动填入当前活跃班级) - 底部:本人提交的请假申请列表(
LeaveRequestList) - 返回仪表盘的面包屑
- 无活跃班级时显示提示卡片
- 顶部:在线请假表单(
- 技术栈:
- Server Component +
force-dynamic - Server Actions:
getStudentActiveClass(ctx.userId)+getLeaveRequests({ scope, currentUserId, page: 1, pageSize: 50 }) getAuthContext()(注意:未用requirePermission,直接取 ctx)- 组件:
LeaveRequestForm/LeaveRequestList/Card/Button - scope 处理:学生 scope 为
class_members,buildScopeFilter返回1=0,但通过currentUserId = requesterId过滤本人记录
- Server Component +
- ARCHITECTURE.md 契约:❌
2.20 diagnostic 模块(CICD 额外页面,ARCHITECTURE.md 未规划)
2.20.1 ⚠️ CICD diagnostic/page.tsx(学生诊断报告,ARCHITECTURE.md 未列入 36 页)
- CICD 参考实现:
e:\desktop\CICD\src\app\(dashboard)\student\diagnostic\page.tsx - 功能描述:
- 学生诊断学情(
getStudentMasterySummary)+ 已发布诊断报告列表(getDiagnosticReports) StudentDiagnosticView渲染- 学生仅可见
status: "published"报告(防草稿泄露)
- 学生诊断学情(
- 技术栈:Server Component +
requirePermission(Permissions.DIAGNOSTIC_READ) - ARCHITECTURE.md 契约:❌ 未列入 §9.2 36 页清单
- 建议:若产品确认学生端诊断报告功能保留,需补充到 ARCHITECTURE.md §9.2;否则可在 dashboard/weakness 中替代承载
三、按模块汇总
| 模块 | 规划页数 | 已完成 | 缺失 | 备注 |
|---|---|---|---|---|
| dashboard | 3 | 1 | 2 | 仪表盘基础页有,trend/weakness 详情页缺 |
| grades | 2 | 0 | 2 | 列表 + 报告卡 |
| exams | 3 | 0 | 3 | ⚠️ CICD 无源页面,take 工作台最关键 |
| homework | 3 | 0 | 3 | ⚠️ CICD 路由为 learning/assignments/*,需迁移到 homework/* |
| schedule | 1 | 0 | 1 | |
| attendance | 1 | 0 | 1 | |
| classes | 1 | 0 | 1 | CICD 无独立路由(融合在 courses) |
| courses | 2 | 0 | 2 | CICD 路由为 learning/courses/* |
| course-plans | 2 | 0 | 2 | |
| lesson-plans | 2 | 0 | 2 | |
| textbooks | 2 | 0 | 2 | CICD 路由为 learning/textbooks/*,需对齐 /[id]/chapters |
| error-book | 1 | 0 | 1 | 含 AI 上下文 + 客户端列表 |
| learning | 2 | 0 | 2 | 学习中心首页 + AI 学习路径 |
| practice | 2 | 0 | 2 | 自适应练习 |
| elective | 2 | 0 | 2 | 含 Suspense 双段流式渲染 |
| ai-tutor | 1 | 0 | 1 | ⚠️ B3 末,CICD 无源页面 |
| announcements(共享) | 2 | 0 | 2 | 共享路由,非 student/ 下 |
| messages(共享) | 1 | 0 | 1 | ⚠️ B3 末,共享路由 |
| leave | 1 | 0 | 1 | |
| 合计 | 34 | 1 | 33 | 不含 notifications/settings 共享路由 |
加上 diagnostic(CICD 额外页)共 35;ARCHITECTURE.md §9.2 规划 36 页(含 notifications/settings 共享路由)。
四、关键技术差异 & 迁移注意事项
4.1 架构模式差异(最重要)
| 维度 | CICD(参考) | portal-shell(目标) |
|---|---|---|
| 渲染模式 | Server Component 为主 | 当前仪表盘是 Client Component,需确定后续页面模式 |
| 数据获取 | Server Action + Drizzle 直查 DB | 必须改为 BFF / 微服务 API(teacher-bff / data-ana 等) |
| 权限校验 | requirePermission + getAuthContext |
需通过 Gateway + BFF 鉴权,前端用 usePermission().hasPermission() |
| 国际化 | next-intl getTranslations |
portal-shell 当前仪表盘硬编码中文,需统一策略 |
| 共享 UI | @/shared/components/ui/* |
@/shared/components/ui/*(已迁移部分) |
| 模块组件 | @/modules/<domain>/components/* |
需在 portal-shell 重建或下沉到 BFF |
4.2 路由路径对齐
| CICD 路径 | ARCHITECTURE.md §9.2 目标路径 | 备注 |
|---|---|---|
learning/assignments |
homework |
提升到顶层 |
learning/assignments/[assignmentId] |
homework/[id]/submit |
路径参数改名 |
learning/assignments/[assignmentId]/result |
homework/[id]/analysis |
子路径改名 |
learning/courses |
courses |
提升到顶层 |
learning/courses/[classId] |
courses/[id] |
参数名 classId → id |
learning/textbooks |
textbooks |
提升到顶层 |
learning/textbooks/[id] |
textbooks/[id]/chapters |
增加子路径 chapters |
learning/study-path |
learning-path |
提升到顶层 |
(无) |
exams/* |
全新设计 |
(无) |
ai-tutor |
全新设计 |
(无) |
classes |
全新设计(与 courses 区分) |
4.3 权限点映射
CICD 中学生页面用到的权限点(迁移时需在 portal-shell Permissions 常量中对应):
GRADE_RECORD_READ(grades / report-card)CLASS_READ(schedule / courses)ATTENDANCE_READ(attendance)COURSE_PLAN_READ(course-plans)LESSON_PLAN_READ(lesson-plans)TEXTBOOK_READ(textbooks)ERROR_BOOK_READ(error-book)AI_CHAT(study-path / ai-tutor)ADAPTIVE_PRACTICE_READ(practice)ELECTIVE_READ(elective)DIAGNOSTIC_READ(diagnostic,CICD 额外)- leave 用
getAuthContext而非requirePermission(需统一)
4.4 共享组件清单(需在 portal-shell 补齐或确认已有)
DashboardShell/DashboardSection/StatCard(仪表盘已有)Card/CardContent/CardHeader/CardTitle(基础)Button/Badge/EmptyState/Skeleton(基础)StatsGrid(多列统计,error-book/practice 用)WidgetBoundary(widget 降级容错)StatusBadge+variantMap(作业状态徽章)TextbookReader/TextbookCard/TextbookFilters(教材相关)LessonPlanReadonlyView/LessonPlanList(教案相关)CoursePlanList/CoursePlanDetail(课程计划)StudentScheduleView/StudentScheduleFilters(课表)StudentCoursesView/CourseFilters(课程)StudentAttendanceView(考勤)StudentGradeSummary/GradeTrendCard/RankingTrendCard/GradeDistributionChart/GrowthArchiveChart/ReportCardView/ReportCardPrintAction/StudentGradeFilters(成绩,组件最多)HomeworkTakeView/HomeworkReviewView/HomeworkSubmissionResult/AssignmentFilters(作业,⚠️ take 是最复杂)PracticeStarterWithNav/PracticeHistory/PracticeSessionView/PracticeServiceProvider(练习)ElectiveCourseDetail/ElectivePageLayout/MySelectionsLoader/AvailableCoursesLoader(选课)LeaveRequestForm/LeaveRequestList(请假)StudentErrorBookListClient/AddErrorBookDialogWithQuestions/ErrorBookFilters(错题本)AiStudyPath/AiClientProvider/createCoreAiClientService(AI)
4.5 B3 实施优先级建议
按用户价值 + 实现复杂度排序:
- P0(必做,核心学习闭环):homework 列表 + submit 工作台 + analysis、exams 列表 + take 工作台 + result
- P1(高频查看):grades 列表 + report-card、schedule、attendance、error-book
- P2(学习资源):learning 首页、courses 列表 + 详情、textbooks 列表 + chapters、course-plans + 详情、lesson-plans + view
- P3(辅助功能):classes、practice + session、elective + 详情、leave
- P4(增强):dashboard trend/weakness 详情页、learning-path
- P5(B3 末):ai-tutor、messages
- 共享:announcements 列表 + 详情
五、CICD 与 ARCHITECTURE.md §9.2 对照表
| ARCH §9.2 源路由 | ARCH §9.2 目标路由 | CICD 是否有源页面 | portal-shell 是否已有 | 契约状态 | 备注 |
|---|---|---|---|---|---|
dashboard |
/shell/student |
✅ | ✅ | ✅ studentDashboard |
已完成基础版 |
/trend |
/shell/student/trend |
❌(融合在 dashboard) | ❌ | ✅ learningTrend |
需新建详情页 |
/weakness |
/shell/student/weakness |
❌(融合在 dashboard) | ❌ | ✅ studentWeakness |
需新建详情页 |
my-grades |
/shell/student/grades |
✅ | ❌ | ❌ | |
/report-card |
/shell/student/grades/report-card |
✅ | ❌ | ❌ | |
my-exams |
/shell/student/exams |
❌ | ❌ | 🟡 | CICD 无,全新设计 |
/[id]/result |
/shell/student/exams/[id]/result |
❌ | ❌ | 🟡 | 参考作业 result |
/[id]/take |
/shell/student/exams/[id]/take |
❌ | ❌ | 🟡 | ⚠️ 最关键,参考 HomeworkTakeView |
my-homework |
/shell/student/homework |
✅(learning/assignments) | ❌ | 🟡 | 路径迁移 |
/[id]/submit |
/shell/student/homework/[id]/submit |
✅(learning/assignments/[id]) | ❌ | 🟡 | ⚠️ take 工作台 |
/[id]/analysis |
/shell/student/homework/[id]/analysis |
✅(learning/assignments/[id]/result) | ❌ | 🟡 | |
schedule |
/shell/student/schedule |
✅ | ❌ | ❌ | |
my-attendance |
/shell/student/attendance |
✅ | ❌ | ❌ | |
my-classes |
/shell/student/classes |
❌(融合在 courses) | ❌ | ❌ myClasses |
全新设计 |
courses |
/shell/student/courses |
✅(learning/courses) | ❌ | ❌ | 路径迁移 |
/[id] |
/shell/student/courses/[id] |
✅(learning/courses/[classId]) | ❌ | ❌ | 参数名 classId→id |
course-plans |
/shell/student/course-plans |
✅ | ❌ | ❌ | |
/[id] |
/shell/student/course-plans/[id] |
✅ | ❌ | ❌ | |
lesson-plans |
/shell/student/lesson-plans |
✅ | ❌ | ❌ | |
/[id]/view |
/shell/student/lesson-plans/[planId]/view |
✅ | ❌ | ❌ | |
textbooks |
/shell/student/textbooks |
✅(learning/textbooks) | ❌ | 🟡 | 路径迁移 |
/[id]/chapters |
/shell/student/textbooks/[id]/chapters |
✅(learning/textbooks/[id]) | ❌ | 🟡 | 增加子路径 |
error-book |
/shell/student/error-book |
✅ | ❌ | ✅ | 含 AI 上下文 |
learning |
/shell/student/learning |
✅ | ❌ | ❌ | |
learning-path |
/shell/student/learning-path |
✅(learning/study-path) | ❌ | ❌ | 路径迁移 |
practice |
/shell/student/practice |
✅ | ❌ | ❌ | |
/[sessionId] |
/shell/student/practice/[sessionId] |
✅ | ❌ | ❌ | |
elective |
/shell/student/elective |
✅ | ❌ | ❌ | |
/[id] |
/shell/student/elective/[id] |
✅ | ❌ | ❌ | |
ai-tutor |
/shell/student/ai-tutor |
❌ | ❌ | ❌ | B3 末,全新设计 |
announcements |
/shell/announcements(共享) |
❌(不在 student/ 下) | ❌ | ❌ | 共享路由 |
/[id] |
/shell/announcements/[id](共享) |
❌ | ❌ | ❌ | 共享路由 |
messages |
/shell/messages(共享) |
❌ | ❌ | ❌ | B3 末,共享路由 |
leave |
/shell/student/leave |
✅ | ❌ | ❌ | |
notifications、settings |
共享路由 | — | ❌ | ✅ | B1/B3,不在 36 页内 |
diagnostic(CICD 额外) |
—(未列入 §9.2) | ✅ | ❌ | — | 需产品决策是否保留 |
六、风险与建议
6.1 高风险点
- exams/[id]/take 作答工作台:CICD 完全无源可参考(仅有
HomeworkTakeView同构参考),需从零设计考试特性(倒计时、断网恢复、批量提交、防作弊等) - 路由路径大调整:6 类路径需迁移(learning/* → 顶层),需同步更新导航、面包屑、内链
- 架构模式转变:portal-shell 已转向 BFF + 微服务,不能照搬 CICD 的 Server Action + Drizzle 直查模式,每个页面都需重新设计数据获取链路(BFF → data-ana / core-edu 等服务)
- 国际化缺失:当前仪表盘硬编码中文,36 页全部完成后需补 i18n,建议从一开始就用
next-intl - 权限校验缺失:当前仪表盘无
requirePermission,需建立 portal-shell 学生域权限校验中间件/装饰器
6.2 建议
- 先建契约:开工前先在
shared-proto中补齐 §9.2 标 ❌ / 🟡 的契约(特别是 exams 系列、my-classes、homework 等) - 统一渲染模式:建议学生页面统一采用 Server Component + BFF 数据获取(与 CICD 一致),避免当前仪表盘的 Client Component 模式
- 统一权限模型:建立 portal-shell 学生域
RequirePermission装饰器/中间件,覆盖所有页面 - 共享组件下沉:CICD 中
@/modules/<domain>/components/*的视图组件需评估是下沉到 BFF 返回结构化数据,还是在 portal-shell 重建 - CICD diagnostic 决策:产品需确认是否保留学生端诊断报告功能,若保留需补充 ARCHITECTURE.md §9.2
- 分批推进:按本报告 §4.5 的 P0→P5 优先级分批实施,每批完成后跑
pnpm run arch:scan同步 arch.db
分析完成。共发现 35 个待完成页面(含 CICD 额外的 diagnostic 1 页),其中 33 个完全缺失、2 个为 dashboard 详情页缺失。最关键的 exams/[id]/take 作答工作台在 CICD 中无源页面,需重点设计。