diff --git a/apps/admin/src/pages/Schedules/index.tsx b/apps/admin/src/pages/Schedules/index.tsx index 42547cf..c37e756 100644 --- a/apps/admin/src/pages/Schedules/index.tsx +++ b/apps/admin/src/pages/Schedules/index.tsx @@ -947,6 +947,19 @@ const SchedulesPage: React.FC = () => { /> + + + + { endTime: '18:00', startDate: '2026-07-01', endDate: '2026-07-31', + notes: '需要投影设备', }); expect(values.classroomId).toBe(1); expect(values.weekDay).toBe(5); + expect(values.notes).toBe('需要投影设备'); expect(values.timeRange.map((item) => item.format('HH:mm'))).toEqual(['14:00', '18:00']); expect(values.dateRange.map((item) => item.format('YYYY-MM-DD'))).toEqual([ '2026-07-01', @@ -36,6 +38,7 @@ describe('schedule edit form mapping', () => { teacherId: 4, timeRange: [dayjs('2026-01-01 13:30'), dayjs('2026-01-01 17:20')], dateRange: [dayjs('2026-08-01'), dayjs('2026-08-31')], + notes: ' 临时调整教室 ', }), ).toEqual({ classId: 1, @@ -47,6 +50,24 @@ describe('schedule edit form mapping', () => { endTime: '17:20', startDate: '2026-08-01', endDate: '2026-08-31', + notes: '临时调整教室', }); }); }); + + +describe('schedule notes normalization', () => { + it('omits whitespace-only notes from the payload', () => { + expect( + buildSchedulePayload({ + classId: 1, + classroomId: 2, + weekDay: 6, + subject: '作文', + timeRange: [dayjs('2026-01-01 13:30'), dayjs('2026-01-01 17:20')], + dateRange: [dayjs('2026-08-01'), dayjs('2026-08-31')], + notes: ' ', + }).notes, + ).toBeUndefined(); + }); +}); diff --git a/apps/admin/src/pages/Schedules/schedule-form.ts b/apps/admin/src/pages/Schedules/schedule-form.ts index 42d1d7f..dc4560c 100644 --- a/apps/admin/src/pages/Schedules/schedule-form.ts +++ b/apps/admin/src/pages/Schedules/schedule-form.ts @@ -6,6 +6,7 @@ export interface ScheduleFormValues { weekDay: number; subject: string; teacherId?: number; + notes?: string; timeRange: [Dayjs, Dayjs]; dateRange: [Dayjs, Dayjs]; } @@ -17,6 +18,7 @@ export interface EditableSchedule { weekDay: number; subject: string; teacherId: number | null; + notes?: string | null; startTime: string; endTime: string; startDate: string; @@ -29,6 +31,7 @@ export const scheduleToFormValues = (schedule: EditableSchedule): ScheduleFormVa weekDay: schedule.weekDay, subject: schedule.subject, teacherId: schedule.teacherId ?? undefined, + notes: schedule.notes ?? undefined, timeRange: [dayjs(`2000-01-01 ${schedule.startTime}`), dayjs(`2000-01-01 ${schedule.endTime}`)], dateRange: [dayjs(schedule.startDate), dayjs(schedule.endDate)], }); @@ -39,6 +42,7 @@ export const buildSchedulePayload = (values: ScheduleFormValues) => ({ weekDay: values.weekDay, subject: values.subject, teacherId: values.teacherId, + notes: values.notes?.trim() || undefined, startTime: values.timeRange[0].format('HH:mm'), endTime: values.timeRange[1].format('HH:mm'), startDate: values.dateRange[0].format('YYYY-MM-DD'), diff --git a/apps/server/src/schedules/dto/schedule.dto.spec.ts b/apps/server/src/schedules/dto/schedule.dto.spec.ts new file mode 100644 index 0000000..5e85269 --- /dev/null +++ b/apps/server/src/schedules/dto/schedule.dto.spec.ts @@ -0,0 +1,29 @@ +import 'reflect-metadata'; +import { validate } from 'class-validator'; +import { CreateScheduleDto, UpdateScheduleDto } from './schedule.dto'; + +const createSchedule = (notes: string) => + Object.assign(new CreateScheduleDto(), { + classId: 1, + classroomId: 2, + weekDay: 1, + startTime: '09:00', + endTime: '10:00', + startDate: '2026-07-01', + endDate: '2026-07-31', + subject: '语文', + notes, + }); + +describe('schedule notes validation', () => { + it('rejects notes longer than 500 characters when creating', async () => { + const errors = await validate(createSchedule('a'.repeat(501))); + expect(errors.some((error) => error.property === 'notes')).toBe(true); + }); + + it('rejects notes longer than 500 characters when updating', async () => { + const dto = Object.assign(new UpdateScheduleDto(), { notes: 'a'.repeat(501) }); + const errors = await validate(dto); + expect(errors.some((error) => error.property === 'notes')).toBe(true); + }); +}); diff --git a/apps/server/src/schedules/dto/schedule.dto.ts b/apps/server/src/schedules/dto/schedule.dto.ts index 3d6869f..016560a 100644 --- a/apps/server/src/schedules/dto/schedule.dto.ts +++ b/apps/server/src/schedules/dto/schedule.dto.ts @@ -7,6 +7,7 @@ import { Matches, Min, Max, + MaxLength, } from 'class-validator'; import { Type } from 'class-transformer'; @@ -59,6 +60,7 @@ export class CreateScheduleDto { @IsOptional() @IsString() + @MaxLength(500) notes?: string; @IsOptional() @@ -115,6 +117,7 @@ export class UpdateScheduleDto { @IsOptional() @IsString() + @MaxLength(500) notes?: string; }