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;
}