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:
95
src/shared/i18n/messages/en/attendance.json
Normal file
95
src/shared/i18n/messages/en/attendance.json
Normal 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"
|
||||
}
|
||||
}
|
||||
96
src/shared/i18n/messages/en/elective.json
Normal file
96
src/shared/i18n/messages/en/elective.json
Normal 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"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user