feat(exams,homework,parent): V3 审计深度修复 — 批量批改/考试分析/提交反馈/家长视图/移动端优化

V3-5: exam-actions.tsx 集成 useExamHomeworkFeatures hook,按角色控制菜单项可见性
V3-7: 批量批改 — 新增 batchAutoGradeSubmissions data-access + Server Action + HomeworkBatchGradingView 组件
V3-8: 考试分析仪表盘 — 新增 getExamAnalytics stats-service + ExamAnalyticsDashboard 组件 + /teacher/exams/[id]/analytics 路由
V3-9: 提交后即时反馈页 — 新增 HomeworkSubmissionResult 组件 + /student/learning/assignments/[id]/result 路由
V3-11: 家长考试详情 — 新增 ChildExamDetail 组件 + getStudentExamResults data-access + child-detail-panel exams Tab
V3-12: 移动端触控优化 — 题目导航与考试操作按钮 44px 最小触控目标

修复: instrumentation.ts 适配器补全 questionCount/averageScore/overdueCount 字段
修复: exam-homework-port.ts 类型导入对齐 ExamWithQuestionsForHomework
修复: trend-line-chart.tsx 数据类型允许 undefined(classAverage 可选场景)

同步更新 004/005 架构文档
This commit is contained in:
SpecialX
2026-06-23 01:06:27 +08:00
parent 21c5eba96c
commit a60105455e
23 changed files with 2407 additions and 263 deletions

View File

@@ -41,7 +41,7 @@ export interface TrendLineSeries {
interface TrendLineChartProps {
/** 图表数据 */
data: Array<Record<string, string | number>>
data: Array<Record<string, string | number | undefined>>
/** 折线系列配置(支持单条或多条) */
series: TrendLineSeries[]
/** X 轴数据字段名(默认 "title" */

View File

@@ -96,6 +96,33 @@
"error": {
"notFound": "Exam not found",
"loadFailed": "Failed to load exam"
},
"analytics": {
"title": "Exam Analytics",
"description": "View score distribution and per-question analysis",
"totalStudents": "Total Students",
"submitted": "Submitted",
"gradedCount": "Graded",
"assignmentCount": "Assignments",
"averageScore": "Average Score",
"passRate": "Pass Rate",
"scoreDistribution": "Score Distribution",
"scoreDistributionDesc": "Student count by percentage range",
"questionAnalysis": "Question Analysis",
"questionAnalysisDesc": "Error rate and difficulty (error rate >= 70% is hard)",
"questionType": "Type",
"questionText": "Question",
"maxScore": "Max Score",
"errorCount": "Errors",
"errorRate": "Error Rate",
"difficulty": "Difficulty",
"difficultyEasy": "Easy",
"difficultyMedium": "Medium",
"difficultyHard": "Hard",
"highErrorWarning": "High Error Rate Warning",
"highErrorWarningDesc": "The following questions have an error rate above 70% and are recommended for focused review",
"noData": "No analytics data yet. Data will be available after students submit and grading is complete.",
"viewAnalytics": "View Analytics"
}
},
"homework": {
@@ -249,7 +276,13 @@
"nextStudent": "Next Student",
"prev": "Prev",
"next": "Next",
"gradesAutoSaveNote": "Grades are saved automatically when you click Submit. Students will see their grades and feedback immediately after you submit."
"gradesAutoSaveNote": "Grades are saved automatically when you click Submit. Students will see their grades and feedback immediately after you submit.",
"batchAutoGrade": "Batch Auto-Grade",
"batchSelected": "{{count}} submissions selected",
"batchSelectAtLeastOne": "Please select at least one submission",
"batchFailed": "Batch grading failed",
"selectAll": "Select All",
"selectRow": "Select this row"
},
"review": {
"title": "Review",
@@ -269,7 +302,23 @@
"responseSummary": "Response Summary",
"description": "Description",
"noDescription": "No description provided.",
"totalScore": "Total Score"
"totalScore": "Total Score",
"correctAnswerTrue": "True",
"correctAnswerFalse": "False"
},
"result": {
"title": "Submission Result",
"scoreRate": "Score Rate",
"fullyGraded": "All questions have been graded",
"partiallyGraded": "Objective questions auto-graded. Subjective questions awaiting teacher review.",
"correctCount": "Correct",
"incorrectCount": "Incorrect",
"partialCount": "Partial",
"pendingCount": "Pending",
"wrongAnswersTitle": "Wrong Answers Preview",
"wrongAnswersDesc": "These questions need focused review",
"backToList": "Back to Assignments",
"viewErrorBook": "View Error Book"
},
"status": {
"draft": "Draft",

View File

@@ -96,6 +96,33 @@
"error": {
"notFound": "考试不存在",
"loadFailed": "加载考试失败"
},
"analytics": {
"title": "考试分析",
"description": "查看考试成绩分布与逐题分析",
"totalStudents": "应考人数",
"submitted": "已提交",
"gradedCount": "已批改",
"assignmentCount": "关联作业数",
"averageScore": "平均分",
"passRate": "及格率",
"scoreDistribution": "分数段分布",
"scoreDistributionDesc": "按百分比区间统计学生人数",
"questionAnalysis": "逐题分析",
"questionAnalysisDesc": "错误率与难度等级错误率≥70%为难题)",
"questionType": "题型",
"questionText": "题目",
"maxScore": "满分",
"errorCount": "错误数",
"errorRate": "错误率",
"difficulty": "难度",
"difficultyEasy": "简单",
"difficultyMedium": "中等",
"difficultyHard": "困难",
"highErrorWarning": "高错误率预警",
"highErrorWarningDesc": "以下题目错误率超过 70%,建议重点讲解",
"noData": "暂无分析数据,需等待学生提交并批改后生成",
"viewAnalytics": "查看分析"
}
},
"homework": {
@@ -249,7 +276,13 @@
"nextStudent": "下一名学生",
"prev": "上一页",
"next": "下一页",
"gradesAutoSaveNote": "点击提交后成绩将自动保存。学生将在您提交后立即看到成绩和反馈。"
"gradesAutoSaveNote": "点击提交后成绩将自动保存。学生将在您提交后立即看到成绩和反馈。",
"batchAutoGrade": "批量自动批改",
"batchSelected": "已选 {{count}} 份提交",
"batchSelectAtLeastOne": "请至少选择一份提交",
"batchFailed": "批量批改失败",
"selectAll": "全选",
"selectRow": "选择此行"
},
"review": {
"title": "复习",
@@ -269,7 +302,23 @@
"responseSummary": "作答概览",
"description": "描述",
"noDescription": "无描述。",
"totalScore": "总分"
"totalScore": "总分",
"correctAnswerTrue": "正确",
"correctAnswerFalse": "错误"
},
"result": {
"title": "提交结果",
"scoreRate": "得分率",
"fullyGraded": "所有题目已批改完成",
"partiallyGraded": "客观题已自动批改,主观题等待教师批改",
"correctCount": "正确",
"incorrectCount": "错误",
"partialCount": "部分正确",
"pendingCount": "待批改",
"wrongAnswersTitle": "错题预览",
"wrongAnswersDesc": "以下题目需要重点复习",
"backToList": "返回作业列表",
"viewErrorBook": "查看错题本"
},
"status": {
"draft": "草稿",

View File

@@ -18,6 +18,7 @@
import type { DataScope } from "@/shared/types/permissions"
import type { Exam } from "@/modules/exams/types"
import type { HomeworkAssignmentListItem } from "@/modules/homework/types"
import type { ExamWithQuestionsForHomework } from "@/modules/exams/data-access"
/**
* 考试/作业模块对外暴露的服务契约。
@@ -54,15 +55,7 @@ export interface ExamHomeworkServicePort {
// ===== 跨模块 =====
/** 获取考试及其题目(供作业模块引用考试内容时使用) */
getExamWithQuestionsForHomework(examId: string): Promise<{
exam: Pick<Exam, "id" | "title" | "totalScore" | "durationMin">
questions: Array<{
id: string
questionType: string
questionContent: unknown
maxScore: number
}>
} | null>
getExamWithQuestionsForHomework(examId: string): Promise<ExamWithQuestionsForHomework | null>
}
/**