- fix(server): getCourseClock 固定 UTC+8(Asia/Shanghai),与 attendance-settlement 保持一致, 修复 CI(UTC 容器)下 attendance.lesson-session.spec.ts 失败 - chore(deps): @ant-design/x 2.9.0 / @ant-design/x-markdown 2.9.0 / mermaid 11.16.1; 直接依赖 dompurify 3.4.13(修复生产依赖 audit 漏洞,mermaid/x-markdown 复用同一份) - ci: 新增 dependency-check workflow(生产依赖 moderate+ / 全局 critical 失败,outdated 报告)
44 lines
1.5 KiB
TypeScript
44 lines
1.5 KiB
TypeScript
import dayjs from '../common/dayjs';
|
||
|
||
export function toMinutes(time: string): number {
|
||
const [hour, minute] = time.split(':').map(Number);
|
||
return hour * 60 + minute;
|
||
}
|
||
|
||
export function getCourseClock(date: Date): { date: string; minutes: number } {
|
||
// Asia/Shanghai 无夏令时,固定 UTC+8(与 attendance-settlement 保持一致),
|
||
// 避免依赖服务器进程时区导致「课程是否已开始」判断漂移。
|
||
const d = dayjs(date).utcOffset(8);
|
||
return {
|
||
date: d.format('YYYY-MM-DD'),
|
||
minutes: d.hour() * 60 + d.minute(),
|
||
};
|
||
}
|
||
|
||
export function shiftDate(date: string, days: number): string {
|
||
return dayjs.utc(`${date}T00:00:00.000Z`).add(days, 'day').format('YYYY-MM-DD');
|
||
}
|
||
|
||
export function mapLessonScheduleTimeToSession(startTime: string): string {
|
||
const hour = parseInt(startTime.slice(0, 2), 10);
|
||
if (hour < 8) return 'morning_reading';
|
||
if (hour < 12) return 'morning';
|
||
if (hour < 17) return 'afternoon';
|
||
if (hour < 20) return 'evening_study';
|
||
return 'night_check';
|
||
}
|
||
|
||
export function isClassStudentActiveOnDate(
|
||
classStudent: Pick<
|
||
import('../entities/class-student.entity').ClassStudent,
|
||
'joinDate' | 'leaveDate' | 'status'
|
||
>,
|
||
lessonDate: string,
|
||
): boolean {
|
||
const status = classStudent.status ?? 'active';
|
||
if (!['active', 'left'].includes(status)) return false;
|
||
if (classStudent.joinDate && classStudent.joinDate > lessonDate) return false;
|
||
if (classStudent.leaveDate && classStudent.leaveDate < lessonDate) return false;
|
||
return true;
|
||
}
|