fix(schedules): support editable schedule notes

This commit is contained in:
2026-07-13 12:09:53 +08:00
parent dfd3cf6772
commit 6396d3e934
5 changed files with 70 additions and 0 deletions

View File

@@ -947,6 +947,19 @@ const SchedulesPage: React.FC = () => {
/>
</Form.Item>
<Form.Item
name="notes"
label="备注"
rules={[{ max: 500, message: '备注不能超过500字' }]}
>
<Input.TextArea
rows={3}
maxLength={500}
showCount
placeholder="可填写排课说明、设备需求或临时调整原因"
/>
</Form.Item>
<Form.Item
name="timeRange"
label="上课时段"

View File

@@ -15,10 +15,12 @@ describe('schedule edit form mapping', () => {
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();
});
});

View File

@@ -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'),

View File

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

View File

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