Files
NextEdu/docs/architecture/audit/exam-homework-audit-report.md
SpecialX 21c7e65fee feat(exam-homework): add audit report, i18n, error boundaries, and permission hardening
- Add comprehensive audit report for exam and homework module

- Create exam-homework i18n message files (zh-CN + en) and register namespace

- Add permission check to gradeHomeworkSubmissionAction to prevent horizontal privilege escalation

- Add Error Boundary + loading.tsx for 5 key pages (exam build/proctoring, homework assignment/submissions, student assignment)

- Refactor exam-columns to createExamColumns(t) factory for i18n support

- Refactor exam-data-table to manage columns internally via useTranslations

- Replace hardcoded strings with i18n keys in all exam/homework components and pages

- Add getHomeworkSubmissionForGrading data-access for secure grading flow
2026-06-22 16:08:39 +08:00

26 KiB
Raw Permalink Blame History

考试和作业模块审计报告

审计范围:exams(考试/试卷/AI 出题)、homework(作业/指派/作答/批改)、proctoring(监考/防作弊)三个相互耦合的模块,以及它们在 app/(dashboard) 下的对应路由页面。


一、现有实现概要

1.1 文件分布

模块 关键文件 行数
app 路由 teacher/exams page.tsx / all/page.tsx / create/page.tsx / [id]/build/page.tsx / [id]/proctoring/page.tsx / grading/page.tsx(重定向) / grading/[submissionId]/page.tsx(重定向) -
app 路由 teacher/homework assignments/page.tsx / assignments/create/page.tsx / assignments/[id]/page.tsx / assignments/[id]/submissions/page.tsx -
app 路由 student/learning/assignments page.tsx / [assignmentId]/page.tsx + loading.tsx -
modules exams actions.ts(691) / ai-pipeline.ts(857) / data-access.ts(473) / types.ts(31) / hooks/use-exam-preview.ts(295) / utils/normalize-structure.ts(57) / components/*(18 文件) -
modules homework actions.ts(239) / data-access.ts(598) / data-access-write.ts(285) / data-access-classes.ts(232) / stats-service.ts(425) / schema.ts(29) / types.ts(186) / components/*(11 文件) -
modules proctoring actions.ts(139) / data-access.ts(409) / types.ts(136) / components/*(3 文件) -

1.2 主要数据流

  1. 考试创建teacher/exams/createcreateExamAction / createAiExamActionpersistExamDraft / persistAiGeneratedExamDraftdb.insert(exams)
  2. 组卷teacher/exams/[id]/buildgetExamById + getQuestionsExamAssemblyupdateExamAction
  3. 作业下发teacher/homework/assignments/createcreateHomeworkAssignmentActiongetExamWithQuestionsForHomework(跨模块调用 exams data-accesscreateHomeworkAssignment(事务写入 assignments + questions + targets
  4. 学生作答student/learning/assignments/[assignmentId]getStudentHomeworkTakeDataHomeworkTakeViewstartHomeworkSubmissionAction / saveHomeworkAnswerAction / submitHomeworkAction
  5. 教师批改teacher/homework/assignments/[id]/submissionsgetHomeworkSubmissions → 跳转 [submissionId]getHomeworkSubmissionDetailsHomeworkGradingViewgradeHomeworkSubmissionAction
  6. 监考teacher/exams/[id]/proctoringgetProctoringDashboardActiongetExamForProctoring + getExamProctoringSummary + getStudentProctoringStatuses + getRecentProctoringEvents

1.3 架构图覆盖情况

docs/architecture/004_architecture_impact_map.md 已记录 exams§2.2、homework§2.3、proctoring§2.21)三个模块的导出函数、依赖关系、已知问题和文件清单。架构图信息基本完整,但以下细节未记录:

  • homework/components/homework-assignment-exam-error-explorer.tsx 等错误分析组件未在文件清单中列出。
  • exams/components/assembly/* 子目录的 4 个组件未单独记录行数。
  • proctoring 的 exam-mode-config.tsx 死代码状态已在已知问题中标注,但未记录其与 ExamForm 的集成缺失原因。

二、现存问题与原因分析

2.1 国际化缺失(严重)

问题:该模块几乎所有用户可见文本均为硬编码,且中英文混杂。

出现位置

  • src/modules/exams/components/exam-form.tsx:硬编码英文 "Exam draft created""Redirecting to exam builder...""Missing subject or grade configuration"
  • src/modules/exams/components/exam-columns.tsx:硬编码 "Exam Info""Status""Stats""Difficulty""Easy""Medium""Hard"
  • src/modules/exams/components/exam-actions.tsx:硬编码 "Preview Exam""Copy ID""Edit""Build""Publish""Archive""Delete""Are you absolutely sure?"
  • src/modules/homework/components/homework-take-view.tsx:硬编码 "Questions""Start Assignment""Submit Assignment""Save Answer""Due Date""Attempts""Description""Progress""Confirm Submission"
  • src/modules/homework/components/homework-grading-view.tsx:硬编码 "Grading Summary""Total Score""Correct""Incorrect""Partial""Submit Grades""Previous Student""Next Student"
  • src/modules/homework/components/homework-assignment-form.tsx:硬编码中文 "快速作业""考试派生作业""直接输入标题和描述,无需建题""从已有考试派生作业"
  • src/app/(dashboard)/teacher/homework/assignments/page.tsx:硬编码中文 "作业列表""管理作业,查看提交率与批改进度。""创建作业""暂无作业""按班级筛选:""清除筛选""标题""状态""截止时间""提交率""平均分""逾期""来源考试""创建时间"
  • src/app/(dashboard)/teacher/homework/assignments/[id]/submissions/page.tsx:硬编码英文 "Submissions""Student""Status""Submitted""Score""Action""Grade""Back""Open Assignment"
  • src/app/(dashboard)/student/learning/assignments/page.tsx:硬编码英文 "Assignments""Your homework and practice assignments.""No assignments""Pending""Completed""Overdue""Due""Attempts""Score""Start""Continue""View""Review"
  • src/modules/proctoring/components/exam-mode-config.tsx:硬编码中文 "考试模式""模式""考试时长(分钟)""题目乱序""启用防作弊监控""允许迟开始""迟到宽限时间(分钟)"

问题原因:模块在 v3 i18n 体系建立前已实现,后续未回填翻译键。

违反规则:项目规则"所有用户可见文本必须适配 i18n使用 next-intl提取翻译键"。

直接后果

  • 切换到英文 locale 后作业列表页仍显示中文考试列表页仍显示英文。多角色admin/teacher/parent/student无法获得一致的语言体验。
  • 国际化交付阻塞,无法满足 K12 学校多语言场景。

2.2 类型安全问题

问题:多处使用 as any / as unknown 断言,违反 TypeScript 严格规范。

出现位置

  • src/modules/exams/components/exam-form.tsx:38resolver: zodResolver(formSchema) as any(注释 eslint-disable)。
  • src/modules/exams/components/exam-form.tsx:163,168form.handleSubmit(onSubmit as any)(两处 eslint-disable)。
  • src/modules/exams/components/exam-actions.tsx:60questionById.set(q.id, q as unknown as Question)
  • src/modules/exams/components/exam-actions.tsx:63const hydrate = (nodes: any[]): ExamNode[]eslint-disable)。
  • src/modules/homework/components/homework-take-view.tsx:346-347(prev[q.questionId]?.answer as string[])
  • src/modules/homework/components/homework-take-view.tsx:468(answersByQuestionId[q.questionId]?.answer as unknown[])
  • src/modules/homework/components/homework-grading-view.tsx:199(ans.questionContent.options as ChoiceOption[])
  • src/modules/homework/data-access.ts:484structure: assignment.structure as unknown

问题原因zodResolver 与 react-hook-form 类型不兼容时偷懒用 as any;题目内容为 unknown 时未做类型守卫直接断言。

违反规则:项目规则"禁止 any"、"禁止 as 断言(除非从 unknown 转换或测试中,需注释原因)"。

直接后果:类型系统形同虚设,运行时错误无法在编译期捕获;重构时易引入隐性 bug。

2.3 权限校验不完整

问题gradeHomeworkSubmissionAction 未校验教师对该提交记录的访问权限。

出现位置src/modules/homework/actions.ts:249-292

问题原因gradeHomeworkSubmissionAction 仅调用 requirePermission(Permissions.HOMEWORK_GRADE),未校验当前教师是否为该作业的创建者、或该学生所在班级的任课教师。任意拥有 HOMEWORK_GRADE 权限的教师均可批改任意学生的任意作业。

违反规则:项目规则"所有敏感数据查询必须在 data-access 层结合当前用户权限过滤Server Action 二次校验"。

直接后果:横向越权风险——教师 A 可批改教师 B 的学生作业,篡改成绩。

2.4 错误边界与加载状态缺失

问题:考试和作业模块的页面缺少 React Error Boundary 和 Suspense 骨架屏。

出现位置

  • src/app/(dashboard)/teacher/exams/[id]/build/page.tsx:无 error.tsx、无 loading.tsxgetExamById 失败时整页 500。
  • src/app/(dashboard)/teacher/exams/[id]/proctoring/page.tsx:无 error.tsx、无 loading.tsx
  • src/app/(dashboard)/teacher/homework/assignments/[id]/page.tsx:无 error.tsx、无 loading.tsx
  • src/app/(dashboard)/teacher/homework/assignments/[id]/submissions/page.tsx:无 error.tsx、无 loading.tsx
  • src/app/(dashboard)/teacher/homework/assignments/create/page.tsx:无 loading.tsx
  • src/app/(dashboard)/student/learning/assignments/[assignmentId]/page.tsx:有 loading.tsx 但无 error.tsx
  • exams/allexams/createloading.tsx

问题原因页面开发时未配套错误边界Suspense 仅在 exams/all 使用。

违反规则:项目规则"每个独立的数据区块必须用 React Error Boundary 包裹"、"异步数据使用 React Suspense + 骨架屏"、"明确处理空数据、无权限、网络异常等边界状态"。

直接后果:数据库连接抖动或单条记录缺失会导致整页崩溃,无法降级展示。

2.5 组件复用不足

问题:题目渲染逻辑在作答页、批改页、复习页三处重复实现。

出现位置

  • src/modules/homework/components/homework-take-view.tsx:248-400:渲染 single_choice / multiple_choice / judgment / text 四种题型。
  • src/modules/homework/components/homework-grading-view.tsx:155-328:再次渲染同样四种题型(带正确答案高亮)。
  • src/modules/homework/components/student-homework-review-view.tsx:第三次渲染同样四种题型(带批改反馈)。
  • 三处都重复实现 getQuestionText / getOptions / isRecord 等工具函数。

问题原因:未抽象 QuestionRenderer / QuestionAnswerInput / QuestionResultDisplay 等复用组件。

违反规则:项目规则"最大化复用:识别四个角色共用的 UI 块和业务逻辑块,抽象为泛型组件和 hooks"、"组合优先:所有 UI 通过组件组合实现灵活性"。

直接后果:题型扩展(如填空、排序、拖拽)需改三处;样式不一致风险高;单测难以覆盖。

2.6 监考模块死代码

问题ExamModeConfig 组件已实现但未集成到考试创建/编辑表单。

出现位置src/modules/proctoring/components/exam-mode-config.tsx230 行)从未被 import。

问题原因:架构图 §2.21 已标注" P0exam-mode-config.tsx 未集成到考试表单(死代码,监考功能无法启用)",但至今未修复。

违反规则:项目规则"如果架构图未覆盖该模块的任何部分,必须优先补全架构图再继续"——此处架构图已记录但代码未修复。

直接后果:监考功能(防作弊、限时、全屏强制)完全不可用;proctoring 模块的 recordProctoringEventAction 无前端触发路径。

2.7 文件行数超限

问题ai-pipeline.ts 857 行,超过 800 行建议值。

出现位置src/modules/exams/ai-pipeline.ts

问题原因:混合了 AI 请求构造、响应解析、Zod 校验、题目归一化、结构生成 5 类职责。

违反规则:项目规则"Server Actions / Data Access 模块:建议 ≤ 800 行"、"超过建议行数时应考虑拆分"。

直接后果维护困难AI 供应商切换需改动整个文件。

2.8 可访问性缺陷

问题:交互元素缺少 ARIA 属性,颜色作为唯一信息载体。

出现位置

  • src/modules/homework/components/homework-grading-view.tsx:156-158:用 border-l-emerald-500 / border-l-red-500 表示对错,无文本替代。
  • src/modules/exams/components/exam-columns.tsx:110-121:难度仅用色块表示,text-[10px] 标签为英文缩写。
  • src/modules/homework/components/homework-take-view.tsx:471-486:题目导航按钮 aria-label 为英文 Jump to question ${i+1},未 i18n。
  • 批改页 Correct/Incorrect 按钮仅靠颜色区分状态。

违反规则:项目规则"可访问性a11y语义化标签、ARIA 属性、键盘导航"。

直接后果:色盲教师无法区分对错;屏幕阅读器用户体验差。

2.9 性能问题

问题getHomeworkSubmissionDetails 为获取前后导航 ID 拉取全部提交记录。

出现位置src/modules/homework/data-access.ts:540-548

const allSubmissions = await db.query.homeworkSubmissions.findMany({
  where: eq(homeworkSubmissions.assignmentId, submission.assignmentId),
  orderBy: [desc(homeworkSubmissions.updatedAt)],
  columns: { id: true },
})
const currentIndex = allSubmissions.findIndex((s) => s.id === submissionId)

问题原因:未用 SQL 窗口函数或 OFFSET/LIMIT 获取相邻记录。

违反规则:项目规则"性能:优先使用 React Server Components 获取初始数据"——此处为 data-access 层低效查询。

直接后果:班级 50 人作业批改时,每次打开详情都拉取 50 条记录的 ID。

2.10 答案保存无防抖与离线支持

问题:学生作答时每题手动点击"Save Answer",无自动保存、无离线缓存。

出现位置src/modules/homework/components/homework-take-view.tsx:139-151

问题原因:未实现自动保存(防抖)和 localStorage 离线缓存。

违反规则:项目规则"明确处理网络异常等边界状态"。

直接后果:网络抖动时学生答案丢失;刷新页面(尽管有 beforeunload 警告)仍可能丢失未保存答案。


三、行业差距对比

3.1 与主流 K12 考试系统对比

功能 行业主流如智学网、猿题库、Google Classroom 当前实现 差距影响
限时考试 支持设定考试时长,到时自动提交 ExamModeConfig 已实现但未集成 教师无法组织课堂限时测验
题目乱序 每位学生题目顺序随机 ExamModeConfig 已实现但未集成 防作弊能力缺失
监考模式 切屏检测、强制全屏、AI 行为分析 proctoring 模块后端已实现,前端无入口 远程考试无法防作弊
自动批改 选择题/判断题提交后即时出分 homework-grading-viewapplyAutoGrades 但仅在打开批改页时计算,不回写 学生提交后看不到即时成绩
批量批改 列表页勾选多份提交批量打分 仅支持逐份批改 50 人班级批改效率低
评分量规Rubric 文本题按维度打分 仅支持单分数 主观题批改粗放
考试分析 题目难度、区分度、知识点掌握度 homework/stats-service 有作业分析,考试无分析 考试后无法复盘教学质量
学生答案草稿 自动保存 + 离线缓存 手动保存,无离线 弱网环境答案易丢
部分分自动判分 多选题漏选得部分分 全对才得分 评分不够精细
重考与补考 支持重考流程与成绩记录 maxAttempts 已支持但无补考入口 补考场景需手动创建新作业

3.2 多角色体验差距

角色 行业主流体验 当前实现 差距
教师 一站式工作台:创建→发布→监考→批改→分析 分散在 /teacher/exams/*/teacher/homework/* 两个独立菜单 考试到作业的链路割裂
学生 统一"待办"入口:作业+考试+复习 /student/learning/assignments,考试作答也走作业流程 考试与作业概念混淆
家长 查看孩子考试详情、错题本、趋势 parent 模块仅有作业摘要,无考试详情 家长无法了解考试表现
管理员 全校考试统计、年级对比、教师工作量 无管理员视角的考试仪表盘 管理层无法宏观决策

3.3 UI/UX 差距

  • 空状态exams/all 有空状态,但 homework/assignments/[id]/submissions 无空状态(无提交时显示空表格)。
  • 加载骨架屏:仅 exams/allexams/createstudent/learning/assignments 有;其余页面白屏加载。
  • 错误降级:全模块无 error.tsx,任何数据加载失败均导致整页 500。
  • 移动端适配homework-take-viewhomework-grading-view 使用 lg:grid-cols-12,移动端可正常显示但未优化触控体验(题目导航按钮过小)。

四、改进优先级建议

P0紧急影响安全与核心功能

  1. 补全 gradeHomeworkSubmissionAction 权限校验:在 data-access 层新增 getHomeworkSubmissionForGrading(submissionId, teacherId, dataScope)校验教师对该作业的访问权创建者或班级任课教师。Server Action 二次校验。
  2. i18n 全量回填:新建 messages/zh-CN/exam-homework.jsonmessages/en/exam-homework.json,提取该模块所有硬编码文本为翻译键;在 i18n/request.ts 注册新命名空间;组件改用 useTranslations('examHomework')
  3. 集成 ExamModeConfig 到考试表单:在 exam-form.tsx 中引入 ExamModeConfig,将 examMode / durationMinutes / shuffleQuestions / antiCheatEnabled 等字段纳入 ExamFormValues,持久化到 exams 表;proctoring 模块读取这些配置启用监考。

P1重要影响可维护性与体验

  1. 添加 Error Boundary 与 loading.tsx:为 exams/[id]/buildexams/[id]/proctoringhomework/assignments/[id]homework/assignments/[id]/submissionshomework/assignments/createstudent/learning/assignments/[assignmentId] 配套 error.tsx + loading.tsx
  2. 抽象题目渲染组件:新建 homework/components/question-renderer.tsx,导出 QuestionRenderer(只读展示)、QuestionAnswerInput(作答交互)、QuestionGradingPanel(批改面板),三处页面改用组合模式复用。
  3. 清理类型断言exam-form.tsxas any 改为正确泛型;exam-actions.tsxhydrate 函数用类型守卫替代 any[]homework-take-view.tsx / homework-grading-view.tsxas 断言改为类型守卫。
  4. 拆分 ai-pipeline.ts:按职责拆为 ai-pipeline/request.ts(请求构造)、ai-pipeline/parse.ts(响应解析+校验)、ai-pipeline/structure.ts(结构生成),原文件作为 re-export 入口。
  5. 优化 getHomeworkSubmissionDetails 相邻记录查询:用 LEAD/LAG 窗口函数或两次 LIMIT 1 查询替代全量拉取。

P2增强提升体验与可扩展性

  1. 学生答案自动保存 + 离线缓存homework-take-view 增加 useDebouncedAutoSave hook答案变更后 3 秒自动保存;同时写入 localStorage,断网时队列化重试。
  2. 考试分析仪表盘:新增 exams/components/exam-analytics-dashboard.tsx,复用 homework/stats-service 模式,展示题目难度、区分度、知识点掌握度。
  3. 批量批改 UIhomework/assignments/[id]/submissions 增加多选 + 批量打分(全对/全错/自定义分数)。
  4. a11y 修复:颜色指示器增加文本替代;题目导航按钮 aria-label i18n批改页 Correct/Incorrect 按钮增加 aria-pressed
  5. 配置驱动的角色渲染:定义 ExamHomeworkRoleConfig 接口,各角色模块仅组合复用单元,新增角色只改配置。

五、架构图同步说明

本次审计发现架构图需补充以下信息:

5.1 需补充的节点

  1. 004_architecture_impact_map.md §2.2 exams 模块

    • 文件清单补充 components/assembly/exam-paper-preview.tsxquestion-bank-list.tsxselected-question-list.tsxstructure-editor.tsx 四个组件的行数与职责。
    • 已知问题补充:exam-mode-config.tsx 未集成(与 proctoring 模块联动缺失)。
  2. 004_architecture_impact_map.md §2.3 homework 模块

    • 文件清单补充 components/homework-assignment-exam-content-card.tsxhomework-assignment-exam-error-explorer.tsxhomework-assignment-exam-error-explorer-lazy.tsxhomework-assignment-exam-preview-pane.tsxhomework-assignment-question-error-detail-panel.tsxhomework-assignment-question-error-overview-card.tsxstudent-homework-review-view.tsx 七个组件的行数与职责。
    • 已知问题补充:gradeHomeworkSubmissionAction 权限校验不完整P0 安全问题)。
  3. 004_architecture_impact_map.md §2.21 proctoring 模块

    • 已知问题补充:ExamModeConfig 未集成的根因是 ExamFormValues 未包含 examMode 字段,需扩展表单 schema。
  4. 005_architecture_data.json

    • modules.exams.exports 补充 ExamModeConfig 集成状态字段。
    • modules.homework.knownIssues 新增 gradeHomeworkPermissionGap 节点。
    • dependencyMatrix 补充 proctoring → examsexamModeConfig 依赖关系(当前仅记录 data-access 依赖,未记录 UI 集成依赖)。

5.2 无需修改的部分

  • 三层架构依赖关系记录准确(app → modules → shared)。
  • 跨模块 data-access 调用关系记录完整exams ↔ homework ↔ proctoring
  • 文件行数统计基本准确(ai-pipeline.ts 857 行已记录)。

六、重构方案设计(概要)

6.1 完全解耦

定义 ExamHomeworkServicePort 接口,抽象数据依赖:

// modules/exam-homework/types/service-port.ts
export interface ExamHomeworkServicePort {
  getExams(scope: DataScope): Promise<ExamListItem[]>
  getExamById(id: string): Promise<ExamDetail | null>
  getHomeworkAssignments(scope: DataScope): Promise<HomeworkAssignmentListItem[]>
  getStudentHomeworkTakeData(assignmentId: string, studentId: string): Promise<StudentHomeworkTakeData | null>
  // ... 其余数据访问方法
}

export interface ExamHomeworkPermissionPort {
  canGradeSubmission(teacherId: string, submissionId: string): Promise<boolean>
  canViewExam(userId: string, examId: string, scope: DataScope): Promise<boolean>
}

通过 ExamHomeworkServiceProviderReact Context注入实现模块内部组件绝不 import 其他业务模块的 actions。

6.2 组合优先

抽象题目渲染组件:

// modules/exam-homework/components/question-renderer.tsx
export function QuestionRenderer({
  question,
  mode,
  children,
}: {
  question: QuestionData
  mode: 'take' | 'grade' | 'review'
  children?: React.ReactNode
}) { ... }

export function QuestionAnswerInput({ question, value, onChange, disabled }: TakeProps) { ... }
export function QuestionGradingPanel({ answer, onScoreChange, onFeedbackChange }: GradeProps) { ... }

6.3 国际化就绪

翻译文件结构示例:

// messages/zh-CN/exam-homework.json
{
  "exam": {
    "list": { "title": "考试列表", "create": "创建考试", "empty": "暂无考试" },
    "form": { "title": "考试标题", "subject": "科目", "grade": "年级", "difficulty": "难度" },
    "status": { "draft": "草稿", "published": "已发布", "archived": "已归档" },
    "actions": { "preview": "预览", "edit": "编辑", "build": "组卷", "publish": "发布", "duplicate": "复制", "delete": "删除" }
  },
  "homework": {
    "list": { "title": "作业列表", "create": "创建作业", "submissionRate": "提交率", "averageScore": "平均分", "overdue": "逾期" },
    "take": { "start": "开始作答", "submit": "提交作业", "saveAnswer": "保存答案", "confirmSubmit": "确认提交", "unansweredWarning": "您有 {{count}} 道题未作答" },
    "grade": { "summary": "批改摘要", "totalScore": "总分", "correct": "正确", "incorrect": "错误", "partial": "部分正确", "submitGrades": "提交成绩" }
  },
  "proctoring": {
    "mode": { "homework": "作业模式", "timed": "限时模式", "proctored": "监考模式" },
    "config": { "duration": "考试时长(分钟)", "shuffleQuestions": "题目乱序", "antiCheat": "启用防作弊监控" }
  }
}

6.4 错误与边界处理

  • 每个页面配套 error.tsxReact Error Boundary
  • 每个页面配套 loading.tsx(骨架屏)。
  • ExamHomeworkErrorBoundary 组件区分 NetworkError / PermissionDenied / NotFound 三种状态。

6.5 可测试性

  • 纯逻辑函数(applyAutoGrades / computeIsCorrect / normalizeStructure)已与 UI 分离,补充单测。
  • 数据获取逻辑通过 ServicePort 接口可 mock。
  • 新增 __tests__/exam-homework-service.test.ts 覆盖权限校验与数据流转。

6.6 可扩展性

配置驱动设计:

// modules/exam-homework/config/role-config.ts
export const EXAM_HOMEWORK_ROLE_CONFIG: Record<Role, ExamHomeworkRoleConfig> = {
  admin: { widgets: ['stats', 'all-exams', 'all-homework'], canGrade: false },
  teacher: { widgets: ['my-exams', 'my-homework', 'grading-queue'], canGrade: true },
  parent: { widgets: ['child-exam-results', 'child-homework-summary'], canGrade: false },
  student: { widgets: ['pending-exams', 'pending-homework', 'results'], canGrade: false },
}

6.7 企业级补充

  • a11y:颜色指示器增加 sr-only 文本;aria-pressed / aria-label 全覆盖。
  • 性能RSC 获取初始数据(已实现);客户端组件仅负责交互(已实现);流式渲染(Suspense 已部分使用)。
  • 安全data-access 层结合 dataScope 过滤已实现Server Action 二次校验P0 待补全)。
  • 监控:预留 trackExamEvent(eventName, payload) 接口,关键操作(创建/提交/批改)埋点。