feat(attendance,elective): 考勤与选修课模块审计重构 — P0 修复 + i18n + Error Boundary

审计报告:docs/architecture/audit/attendance-elective-audit-report.md

P0 修复:
- attendance: getAttendanceStats 统计失真(仅基于前 20 条记录)改为 SQL 聚合查询
- attendance: getClassStudentsForAttendance 跨模块直查 classEnrollments 改为调用 classes data-access
- attendance: update/delete Action 新增资源归属校验(assertRecordOwnership)
- elective: update/delete/openSelection/closeSelection/runLottery Action 新增资源归属校验(assertCourseOwnership)

i18n 接入:
- 新增 attendance/elective 命名空间(zh-CN + en)
- attendance-stats-cards 接入 useTranslations
- elective-course-list/form 接入 useTranslations

类型安全(P1):
- elective-course-form: 移除 as 断言,改用类型守卫 isSelectionMode
- elective-course-list: 移除 null as never 类型逃逸,改用泛型

Error Boundary:
- 新增 admin/teacher attendance error.tsx
- 新增 admin/student elective error.tsx

架构图同步:
- 004: 修正 attendance/elective/parent 章节的导出函数、文件清单、已知问题
- 005: 修正 actions 的 usedBy(标记无调用方的死代码)、新增 issues 字段、更新依赖矩阵
This commit is contained in:
SpecialX
2026-06-22 16:17:00 +08:00
parent 5d42495480
commit 4833930834
16 changed files with 1431 additions and 48 deletions

View File

@@ -0,0 +1,95 @@
{
"title": {
"adminOverview": "Attendance Overview",
"teacherRecords": "Attendance Records",
"teacherStats": "Attendance Statistics",
"sheet": "Record Attendance",
"student": "My Attendance",
"parent": "Children Attendance",
"rules": "Attendance Rules"
},
"description": {
"adminOverview": "View attendance records for all classes school-wide.",
"teacherRecords": "Manage student attendance records.",
"teacherStats": "View class attendance statistics and analysis.",
"student": "View your attendance summary and records.",
"parent": "View your children's attendance summary and warnings."
},
"status": {
"present": "Present",
"absent": "Absent",
"late": "Late",
"early_leave": "Early Leave",
"excused": "Excused"
},
"stats": {
"totalRecords": "Total Records",
"present": "Present",
"absent": "Absent",
"late": "Late",
"earlyLeave": "Early Leave",
"excused": "Excused",
"attendanceRate": "Attendance Rate",
"lateRate": "Late Rate",
"recentRecords": "Recent Records"
},
"filters": {
"class": "Class",
"status": "Status",
"date": "Date",
"allClasses": "All Classes",
"allStatuses": "All Statuses"
},
"actions": {
"record": "Record Attendance",
"stats": "Statistics",
"save": "Save",
"delete": "Delete",
"cancel": "Cancel",
"markAllPresent": "Mark All Present"
},
"list": {
"empty": "No attendance records",
"emptyDescription": "No attendance records have been generated yet.",
"emptyTeacherDescription": "Start recording attendance for your class.",
"columns": {
"student": "Student",
"class": "Class",
"date": "Date",
"status": "Status",
"remark": "Remark",
"recorder": "Recorder",
"createdAt": "Created At"
}
},
"sheet": {
"selectClass": "Select Class",
"selectDate": "Select Date",
"noStudents": "No students in this class",
"confirmDelete": "Are you sure you want to delete this attendance record?",
"saved": "Attendance saved",
"updated": "Attendance updated",
"deleted": "Attendance record deleted"
},
"rules": {
"lateThreshold": "Late Threshold (minutes)",
"earlyLeaveThreshold": "Early Leave Threshold (minutes)",
"enableAutoMark": "Enable Auto Mark",
"saved": "Attendance rules saved"
},
"errors": {
"notFound": "Attendance record not found",
"noOwnership": "You do not own this attendance record",
"invalidForm": "Invalid form data",
"unexpected": "Unexpected error"
},
"parent": {
"warningTitle": "Attendance Warnings",
"rateCardTitle": "Attendance Rate Summary",
"calendarTitle": "Attendance Calendar",
"noWarnings": "No attendance warnings",
"absentWarning": "{count} absence(s)",
"lateWarning": "{count} late arrival(s)",
"lowRateWarning": "Attendance rate {rate}% below threshold"
}
}

View File

@@ -0,0 +1,96 @@
{
"title": {
"adminList": "Elective Courses",
"create": "Create Course",
"edit": "Edit Course",
"teacher": "My Elective Courses",
"student": "Course Selection"
},
"description": {
"adminList": "Manage elective courses, open/close selection and lottery.",
"teacher": "View and manage the elective courses you teach.",
"student": "Browse available courses and make selections."
},
"status": {
"draft": "Draft",
"open": "Open",
"closed": "Closed",
"cancelled": "Cancelled"
},
"selectionMode": {
"fcfs": "First Come First Served",
"lottery": "Lottery"
},
"selectionStatus": {
"selected": "Selected",
"enrolled": "Enrolled",
"waitlist": "Waitlist",
"dropped": "Dropped",
"rejected": "Rejected"
},
"fields": {
"name": "Course Name",
"subject": "Subject",
"teacher": "Teacher",
"grade": "Grade",
"description": "Description",
"capacity": "Capacity",
"enrolled": "Enrolled",
"classroom": "Classroom",
"schedule": "Schedule",
"startDate": "Start Date",
"endDate": "End Date",
"selectionStart": "Selection Start",
"selectionEnd": "Selection End",
"selectionMode": "Selection Mode",
"credit": "Credit"
},
"actions": {
"create": "Create Course",
"edit": "Edit",
"delete": "Delete",
"openSelection": "Open Selection",
"closeSelection": "Close Selection",
"runLottery": "Run Lottery",
"select": "Select",
"drop": "Drop",
"cancel": "Cancel",
"save": "Save"
},
"list": {
"empty": "No elective courses",
"emptyStudent": "No available courses",
"emptyDescription": "No elective courses have been created yet."
},
"form": {
"createTitle": "Create Elective Course",
"editTitle": "Edit Elective Course",
"namePlaceholder": "Enter course name",
"descriptionPlaceholder": "Enter course description"
},
"student": {
"mySelections": "My Selections",
"availableCourses": "Available Courses",
"selected": "Selected",
"enrolled": "Enrolled",
"waitlist": "Waitlist",
"capacityFull": "Capacity full",
"selectSuccess": "Course selected successfully",
"dropSuccess": "Course dropped successfully",
"confirmDrop": "Are you sure you want to drop this course?"
},
"lottery": {
"result": "Lottery result: {enrolled} enrolled, {waitlist} waitlisted",
"running": "Running lottery..."
},
"errors": {
"notFound": "Course not found",
"noOwnership": "You do not own this course",
"capacityFull": "Course capacity is full",
"alreadySelected": "You have already selected this course",
"selectionClosed": "Selection is closed",
"gradeMismatch": "Your grade does not match the course requirement",
"invalidForm": "Invalid form data",
"unexpected": "Unexpected error"
}
}

View File

@@ -0,0 +1,95 @@
{
"title": {
"adminOverview": "考勤总览",
"teacherRecords": "考勤记录",
"teacherStats": "考勤统计",
"sheet": "录入考勤",
"student": "我的考勤",
"parent": "子女考勤",
"rules": "考勤规则"
},
"description": {
"adminOverview": "查看全校所有班级的考勤记录。",
"teacherRecords": "管理学生考勤记录。",
"teacherStats": "查看班级考勤统计分析。",
"student": "查看个人考勤汇总与记录。",
"parent": "查看子女考勤汇总与异常预警。"
},
"status": {
"present": "出勤",
"absent": "缺勤",
"late": "迟到",
"early_leave": "早退",
"excused": "请假"
},
"stats": {
"totalRecords": "总记录数",
"present": "出勤",
"absent": "缺勤",
"late": "迟到",
"earlyLeave": "早退",
"excused": "请假",
"attendanceRate": "出勤率",
"lateRate": "迟到率",
"recentRecords": "最近记录"
},
"filters": {
"class": "班级",
"status": "状态",
"date": "日期",
"allClasses": "全部班级",
"allStatuses": "全部状态"
},
"actions": {
"record": "录入考勤",
"stats": "统计分析",
"save": "保存",
"delete": "删除",
"cancel": "取消",
"markAllPresent": "全部标记到场"
},
"list": {
"empty": "暂无考勤记录",
"emptyDescription": "系统中尚未产生任何考勤记录。",
"emptyTeacherDescription": "开始为您的班级录入考勤。",
"columns": {
"student": "学生",
"class": "班级",
"date": "日期",
"status": "状态",
"remark": "备注",
"recorder": "记录人",
"createdAt": "创建时间"
}
},
"sheet": {
"selectClass": "选择班级",
"selectDate": "选择日期",
"noStudents": "该班级暂无学生",
"confirmDelete": "确定删除此条考勤记录吗?",
"saved": "考勤已保存",
"updated": "考勤已更新",
"deleted": "考勤记录已删除"
},
"rules": {
"lateThreshold": "迟到阈值(分钟)",
"earlyLeaveThreshold": "早退阈值(分钟)",
"enableAutoMark": "启用自动标记",
"saved": "考勤规则已保存"
},
"errors": {
"notFound": "考勤记录不存在",
"noOwnership": "您无权操作此考勤记录",
"invalidForm": "表单数据无效",
"unexpected": "发生未知错误"
},
"parent": {
"warningTitle": "考勤异常预警",
"rateCardTitle": "出勤率汇总",
"calendarTitle": "考勤月历",
"noWarnings": "暂无考勤异常",
"absentWarning": "{count} 次缺勤",
"lateWarning": "{count} 次迟到",
"lowRateWarning": "出勤率 {rate}% 低于阈值"
}
}

View File

@@ -0,0 +1,96 @@
{
"title": {
"adminList": "选修课程",
"create": "创建课程",
"edit": "编辑课程",
"teacher": "我的选修课",
"student": "选课中心"
},
"description": {
"adminList": "管理选修课程、开放/关闭选课与抽签。",
"teacher": "查看和管理您教授的选修课程。",
"student": "浏览可选课程并进行选课。"
},
"status": {
"draft": "草稿",
"open": "开放选课",
"closed": "已关闭",
"cancelled": "已取消"
},
"selectionMode": {
"fcfs": "先到先得",
"lottery": "抽签"
},
"selectionStatus": {
"selected": "已选",
"enrolled": "已录取",
"waitlist": "候补",
"dropped": "已退选",
"rejected": "已拒绝"
},
"fields": {
"name": "课程名称",
"subject": "科目",
"teacher": "授课教师",
"grade": "年级",
"description": "课程描述",
"capacity": "容量",
"enrolled": "已录取",
"classroom": "教室",
"schedule": "上课时间",
"startDate": "开始日期",
"endDate": "结束日期",
"selectionStart": "选课开始",
"selectionEnd": "选课结束",
"selectionMode": "选课模式",
"credit": "学分"
},
"actions": {
"create": "创建课程",
"edit": "编辑",
"delete": "删除",
"openSelection": "开放选课",
"closeSelection": "关闭选课",
"runLottery": "执行抽签",
"select": "选课",
"drop": "退课",
"cancel": "取消",
"save": "保存"
},
"list": {
"empty": "暂无选修课程",
"emptyStudent": "暂无可选课程",
"emptyDescription": "系统中尚未创建任何选修课程。"
},
"form": {
"createTitle": "创建选修课程",
"editTitle": "编辑选修课程",
"namePlaceholder": "请输入课程名称",
"descriptionPlaceholder": "请输入课程描述"
},
"student": {
"mySelections": "我的选课",
"availableCourses": "可选课程",
"selected": "已选",
"enrolled": "已录取",
"waitlist": "候补",
"capacityFull": "名额已满",
"selectSuccess": "选课成功",
"dropSuccess": "退课成功",
"confirmDrop": "确定退选此课程吗?"
},
"lottery": {
"result": "抽签结果:录取 {enrolled} 人,候补 {waitlist} 人",
"running": "抽签进行中..."
},
"errors": {
"notFound": "课程不存在",
"noOwnership": "您无权操作此课程",
"capacityFull": "课程名额已满",
"alreadySelected": "您已选过此课程",
"selectionClosed": "选课已关闭",
"gradeMismatch": "您的年级不符合课程要求",
"invalidForm": "表单数据无效",
"unexpected": "发生未知错误"
}
}