forked from wangziqi/gongxue-base
feat: 拆分学号/身份证字段 + 考勤教师展示 + 代码优化
- 入住导入模板:学号和身份证号拆为独立字段,前后端对齐 - 排课查询关联教师,考勤归档页展示教师姓名 - 抽查时段增加 IsIn 校验 - 抽取 withPessimisticWriteLock 去重悲观锁查询 - import 增加文件空 buffer 校验 - 测试 mock 补全,适配事务 manager - MySQL init.sql VALUES() 语法兼容修复
This commit is contained in:
@@ -74,9 +74,18 @@ const ADMIN_CORRECTION_OPTIONS = [
|
||||
{ value: 'absent', label: '缺勤' },
|
||||
];
|
||||
|
||||
interface ClassTeacherOption {
|
||||
userId: number;
|
||||
username: string | null;
|
||||
name: string | null;
|
||||
roleType: string;
|
||||
subject: string | null;
|
||||
}
|
||||
|
||||
interface ClassOption {
|
||||
classId: number;
|
||||
className: string;
|
||||
teachers?: ClassTeacherOption[];
|
||||
}
|
||||
|
||||
interface AttendanceRecordItem {
|
||||
@@ -126,6 +135,8 @@ interface HistoryScheduleOption {
|
||||
endDate: string;
|
||||
subject: string;
|
||||
teacherId: number | null;
|
||||
teacherName?: string | null;
|
||||
teacherUsername?: string | null;
|
||||
status: string;
|
||||
}
|
||||
|
||||
@@ -197,6 +208,28 @@ function displayAttendanceStatus(status?: string | null): string {
|
||||
return status === 'pending' || !status ? 'absent' : status;
|
||||
}
|
||||
|
||||
function getTeacherDisplayName(teacher?: {
|
||||
name?: string | null;
|
||||
username?: string | null;
|
||||
}): string {
|
||||
const name = teacher?.name?.trim();
|
||||
if (name) return name;
|
||||
return teacher?.username?.trim() || '未设置';
|
||||
}
|
||||
|
||||
function formatTeacherNames(
|
||||
teachers: readonly { name?: string | null; username?: string | null }[],
|
||||
): string {
|
||||
const names = [
|
||||
...new Set(
|
||||
teachers
|
||||
.map((teacher) => getTeacherDisplayName(teacher))
|
||||
.filter((name) => name && name !== '未设置'),
|
||||
),
|
||||
];
|
||||
return names.length > 0 ? names.join('、') : '未设置';
|
||||
}
|
||||
|
||||
function AttendanceStatusTag({ status }: { status: string }) {
|
||||
const displayStatus = displayAttendanceStatus(status);
|
||||
const meta = STATUS_META[displayStatus] ?? {
|
||||
@@ -916,9 +949,30 @@ const AdminAttendanceArchive: React.FC<{ canEdit: boolean }> = ({ canEdit }) =>
|
||||
});
|
||||
}, [metricFilter, studentPanels, studentSearch]);
|
||||
|
||||
const selectedClass = classId
|
||||
? classOptions.find((item) => item.classId === classId)?.className || `班级 ${classId}`
|
||||
: '全部班级';
|
||||
const selectedClassOption = classId
|
||||
? classOptions.find((item) => item.classId === classId)
|
||||
: undefined;
|
||||
const selectedClass = selectedClassOption?.className || (classId ? `班级 ${classId}` : '全部班级');
|
||||
const overviewTeachers = selectedClassOption?.teachers ?? [];
|
||||
const headTeacherNames = classId
|
||||
? formatTeacherNames(overviewTeachers.filter((teacher) => teacher.roleType === 'head_teacher'))
|
||||
: '请选择班级';
|
||||
const lifeTeacherNames = classId
|
||||
? formatTeacherNames(overviewTeachers.filter((teacher) => teacher.roleType === 'life_teacher'))
|
||||
: '请选择班级';
|
||||
const currentSchedule = scheduleId
|
||||
? scheduleOptions.find((item) => item.id === scheduleId)
|
||||
: undefined;
|
||||
const subjectTeacherNames = currentSchedule
|
||||
? getTeacherDisplayName({
|
||||
name: currentSchedule.teacherName,
|
||||
username: currentSchedule.teacherUsername,
|
||||
})
|
||||
: classId
|
||||
? formatTeacherNames(
|
||||
overviewTeachers.filter((teacher) => teacher.roleType === 'subject_teacher'),
|
||||
)
|
||||
: '请选择班级';
|
||||
const attendanceRate =
|
||||
summary.total > 0 ? Math.round((summary.present / summary.total) * 100) : 0;
|
||||
const dateLabel = attendanceDate?.format('YYYY-MM-DD') || '未选择日期';
|
||||
@@ -1121,21 +1175,21 @@ const AdminAttendanceArchive: React.FC<{ canEdit: boolean }> = ({ canEdit }) =>
|
||||
<Avatar>班</Avatar>
|
||||
<div>
|
||||
<span>班主任</span>
|
||||
<strong>按班级筛选后查看</strong>
|
||||
<strong>{headTeacherNames}</strong>
|
||||
</div>
|
||||
</div>
|
||||
<div className="student-teacher-item is-muted">
|
||||
<div className="student-teacher-item">
|
||||
<Avatar>生</Avatar>
|
||||
<div>
|
||||
<span>生活老师</span>
|
||||
<strong>暂未接入</strong>
|
||||
<strong>{lifeTeacherNames}</strong>
|
||||
</div>
|
||||
</div>
|
||||
<div className="student-teacher-item">
|
||||
<Avatar>任</Avatar>
|
||||
<div>
|
||||
<span>当前任课</span>
|
||||
<strong>{session ? sessionMap[session] : '全部时段'}</strong>
|
||||
<span>任课老师</span>
|
||||
<strong>{subjectTeacherNames}</strong>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user