feat(portal-shell): homework 模块 7 页迁移(教师域 §9.1 B2)

§9.1 教师域 homework 模块完整迁移(继 exams 之后第二个 B2 模块):

7 页路由结构(与旧 teacher-portal 同构):
- /shell/teacher/homework:列表页(?classId/status/q 筛选)
- /shell/teacher/homework/new:布置作业表单页
- /shell/teacher/homework/[id]:详情 + 内联批改(含提交列表 + recordGrade 表单)
- /shell/teacher/homework/submissions:跨作业提交评审列表
- /shell/teacher/homework/submissions/[submissionId]:单份提交批改 + AI 建议 + 上下份导航
- /shell/teacher/homework/submissions/[submissionId]/scan-grading:扫描批改工作台(三栏)
- /shell/teacher/homework/assignments/[id]/submissions:按作业批量批改 + 统计 + AI 批量评分

数据契约(混合):
-  homework(id: ID!) 真实查询(schema 已就绪,详情页用)
-  列表/mutation/submissions/grading/aiBatchGrading 全部 @contract-pending MSW 兜底
  · 9 个 hook 走 MSW,待后端补齐 mutation 后切换真实 fetcher

§11.3 DoD 11 项验收:
1. route-permissions:EXACT + PREFIX 表 /shell/teacher/homework 已配置
2. 页面模板:list/new 用 ListPageShell/FormPageShell;detail/grading 用 DetailPageShell;
   scan-grading 用 WorkbenchPageShell(三栏,未使用 emptyNode)
3. 三态:loading(Skeleton)/error(errorNode 或 errorSummary)/empty(emptyNode) 全实现
4. lib/api hooks:homework.ts 10 个 hooks(useHomework 真实 + 9 个 MSW)
5. @contract-pending MSW:graphql-data.ts 扩展 6 块 mock + 10 个 switch case
6. i18n:homework 节点扩展 8 个分区共 130+ keys(list/detail/new/submissions/grading/
   scan/assignment/error)中英对齐
7. lint:0 errors(4 warnings 在 __generated__)
8. lint:tokens:0 errors
9. notify:mutation 反馈走 @/shared/lib/notify(非 sonner 直引)
10. vitest:transformations 纯函数单测齐全,全量 323/323 通过(新增 ~50 测试)
11. typecheck:0 errors(noUncheckedIndexedAccess 安全访问)

附带修复:
- 修复 2 处遗留 broken link:
  · widgets/sidebar/quick-actions: /homework/new → /shell/teacher/homework/new
  · widgets/topbar/global-search: /homework → /shell/teacher/homework
- scripts/check-page-count.ts baseline 同步 13 → 26(与 exams 6 + homework 7 一致)

剩余模块:grades(5)+lesson-plans(6)+questions(1)+textbooks(2)+attendance(4)+classes(3)+
students(1)+course-plans(2)+elective(3)+error-book(1)+diagnostic(2)+analytics(2)+ai-*(3)+
knowledge-graph(1)+practice(1)+schedule-changes(1)+leave(1) 共 39 页。
This commit is contained in:
SpecialX
2026-07-22 18:11:15 +08:00
parent dca25fc42f
commit 081cb5fbc3
28 changed files with 4810 additions and 6 deletions

View File

@@ -302,7 +302,215 @@
}
},
"homework": {
"title": "Homework"
"title": "Homework",
"list": {
"title": "Homework",
"description": "View and manage all homework",
"new": "Assign Homework",
"searchPlaceholder": "Search homework name...",
"statusFilter": "Filter by status",
"statusAll": "All statuses",
"statusDraft": "Draft",
"statusPublished": "Published",
"statusClosed": "Closed",
"statusArchived": "Archived",
"total": "{count} total",
"colName": "Name",
"colStatus": "Status",
"colDueDate": "Due Date",
"colGracePeriod": "Grace Period",
"colActions": "Actions",
"viewDetail": "View Detail →",
"mswNotice": "List query contract is pending, please ensure NEXT_PUBLIC_MSW=1 is enabled."
},
"detail": {
"title": "Homework Detail",
"edit": "Edit",
"notFound": "Homework not found, may have been deleted",
"createdAtPrefix": "Created on {date}",
"sectionBasic": "Basic Info",
"sectionSubmissions": "Submissions",
"sectionInlineGrade": "Inline Grade",
"fieldTitle": "Title",
"fieldDescription": "Description",
"fieldDueDate": "Due Date",
"fieldGracePeriod": "Grace Period",
"fieldStatus": "Status",
"fieldClassId": "Class ID",
"fieldSubjectId": "Subject ID",
"fieldCreatedBy": "Created By",
"fieldUpdatedAt": "Updated At",
"viewAllSubmissions": "All Submissions",
"noSubmissions": "No submissions yet",
"colStudent": "Student",
"colStatus": "Status",
"colSubmittedAt": "Submitted At",
"colScore": "Score",
"colActions": "Actions",
"grade": "Grade",
"gradeStudentId": "Student ID",
"gradeScore": "Score",
"gradeFeedback": "Feedback",
"gradeFeedbackPlaceholder": "Write feedback to the student...",
"gradeSubmit": "Submit Grade",
"gradeSubmitting": "Submitting...",
"gradeSuccess": "Grade submitted successfully",
"gradeError": "Grading failed",
"gradeErrorStudentRequired": "Please fill in Student ID",
"gradeErrorScoreInvalid": "Score is invalid, please enter a non-negative number",
"gradeContractPending": "Grade contract is @contract-pending, currently backed by MSW."
},
"new": {
"title": "Assign Homework",
"description": "Fill in homework basic information",
"submit": "Assign",
"success": "Homework assigned successfully",
"error": "Assignment failed",
"classId": "Class ID",
"subjectId": "Subject ID",
"titleLabel": "Title",
"titlePlaceholder": "e.g. Set and Function Practice",
"descriptionLabel": "Description",
"descriptionPlaceholder": "Scope, notes, etc.",
"dueDate": "Due Date",
"gracePeriod": "Grace Period (hours)",
"gracePeriodHint": "Hours of grace after the deadline, 0 means no grace",
"errorClassRequired": "Please fill in Class ID",
"errorTitleRequired": "Please fill in homework title",
"errorDateRequired": "Please select due date",
"contractPending": "Assign homework contract is @contract-pending, currently backed by MSW. Will switch to real submission once backend mutation is ready."
},
"submissions": {
"title": "Submission Grading",
"description": "View all homework submissions and grade them",
"searchPlaceholder": "Search student/no/homework...",
"classIdFilter": "Filter by class",
"classIdPlaceholder": "Class ID",
"statusFilter": "Filter by status",
"statusAll": "All statuses",
"statusSubmitted": "Submitted",
"statusGrading": "Grading",
"statusGraded": "Graded",
"statusReturned": "Returned",
"statusLate": "Late",
"total": "{count} total",
"colStudent": "Student",
"colHomework": "Homework",
"colClass": "Class",
"colStatus": "Status",
"colSubmittedAt": "Submitted At",
"colScore": "Score",
"colActions": "Actions",
"toGrade": "Grade",
"mswNotice": "Submission query contract is pending, please ensure NEXT_PUBLIC_MSW=1 is enabled."
},
"grading": {
"title": "Grade: {name}",
"titleLoading": "Loading grade...",
"subtitle": "Homework: {homework} · No.: {no}",
"notFound": "Submission not found, may have been deleted",
"sectionStudent": "Student Info",
"sectionAnswers": "Answers",
"sectionNavigation": "Navigation",
"fieldStudentName": "Name",
"fieldStudentNo": "Student No.",
"fieldClass": "Class",
"fieldHomework": "Homework",
"fieldStatus": "Status",
"fieldSubmittedAt": "Submitted At",
"fieldFeedback": "Current Feedback",
"questionType": "Type",
"maxScore": "Max Score",
"maxScoreTotal": "Total Max",
"studentAnswer": "Student Answer",
"score": "Score",
"teacherComment": "Teacher Comment",
"overallFeedback": "Overall Feedback",
"overallFeedbackPlaceholder": "Write overall feedback to the student...",
"applyAi": "Apply AI Suggestion",
"aiSuggestionLabel": "AI Suggestion",
"aiSuggestionApplied": "AI suggestion applied",
"prev": "Previous",
"next": "Next",
"position": "{current}/{total}",
"submit": "Submit Grade",
"submitting": "Submitting...",
"success": "Grade submitted successfully",
"error": "Grading failed",
"errorScoreInvalid": "Score for question {qid} is invalid",
"contractPending": "Grading contract is @contract-pending, currently backed by MSW."
},
"scan": {
"title": "Scan Grade: {name}",
"titleLoading": "Loading scan grade...",
"subtitle": "Homework: {homework}",
"notFound": "Submission not found, may have been deleted",
"scanPreview": "Scan Preview",
"imagePlaceholder": "Scan image (submissionId: {id})",
"imageContractPending": "Scan image preview contract is @contract-pending, currently a placeholder.",
"recognizedAnswers": "Recognized Answers",
"recognizedAnswer": "Recognized Answer",
"recognizedCorrect": "Recognized correct",
"recognizedIncorrect": "Recognized incorrect",
"questionType": "Type",
"aiSuggestionLabel": "AI Suggestion",
"noAnswers": "No answer data",
"gradingForm": "Grading Form",
"scoreLabel": "Score for {qid}",
"totalScore": "Current Total",
"applyAllAi": "Apply All AI Suggestions",
"aiAppliedCount": "Applied {count} AI suggestions",
"confidence": "Confidence",
"overallFeedback": "Overall Feedback",
"overallFeedbackPlaceholder": "Write overall feedback to the student...",
"save": "Save Grade",
"saving": "Saving...",
"saveSuccess": "Scan grading saved successfully",
"saveError": "Save failed",
"errorScoreInvalid": "Score for question {qid} is invalid",
"unitScore": "pts",
"contractPending": "Scan grading contract is @contract-pending, currently backed by MSW."
},
"assignment": {
"title": "Batch Grading by Homework",
"description": "Homework: {title}",
"descriptionLoading": "Loading homework info...",
"backToHomework": "Back to Homework Detail",
"total": "{count} submissions",
"mswNotice": "Assignment submissions query contract is pending, please ensure NEXT_PUBLIC_MSW=1 is enabled.",
"sectionHomework": "Homework Info",
"sectionSubmissions": "Submissions",
"sectionAiGrading": "AI Batch Grading",
"homeworkTitle": "Title",
"homeworkId": "Homework ID",
"className": "Class",
"dueDate": "Due Date",
"colStudent": "Student",
"colStatus": "Status",
"colSubmittedAt": "Submitted At",
"colScore": "Score",
"colActions": "Actions",
"scanGrade": "Scan Grade",
"detailGrade": "Detail Grade",
"statsTotalStudents": "Expected",
"statsSubmitted": "Submitted",
"statsGraded": "Graded",
"statsPending": "Pending",
"statsAvgScore": "Avg",
"statsSubmissionRate": "Submission Rate",
"aiBatchGrade": "Batch Auto Grade",
"aiTriggered": "AI grading request triggered",
"aiSummary": "Processed {processed}/{total}, avg confidence {avg}",
"aiEmpty": "No AI suggestions yet, click the button to trigger",
"aiContractPending": "AI grading contract is @contract-pending, currently backed by MSW.",
"suggestedScore": "Suggested",
"confidence": "Confidence"
},
"error": {
"title": "Homework page error",
"unknown": "Unknown error",
"retry": "Retry"
}
},
"grades": {
"title": "Grades"