feat(teacher): 退出上课放弃课时记录; 课时列表按创建/更新时间倒序

Made-with: Cursor
This commit is contained in:
zhonghua 2026-03-24 16:43:25 +08:00
parent 1038a70d92
commit 51b94cf5cb
5 changed files with 63 additions and 4 deletions

View File

@ -272,6 +272,11 @@ export function cancelLesson(id: number | string): Promise<any> {
return http.post(`/v1/teacher/lessons/${id}/cancel`) as any;
}
/** 退出上课:删除未完成的授课记录(非已完成) */
export function abandonLesson(id: number | string): Promise<any> {
return http.post(`/v1/teacher/lessons/${id}/abandon`, {}) as any;
}
// 保存学生评价记录lessonId 使用 string 避免 Long 精度丢失)
export function saveStudentRecord(
lessonId: number | string,

View File

@ -922,11 +922,23 @@ const resetTimer = () => {
const exitLesson = () => {
Modal.confirm({
title: '确认退出',
content: '确定要退出上课吗?课堂记录将不会保存。',
content: '确定要退出上课吗?当前未完成的授课记录将被删除,且无法恢复。',
okText: '确认退出',
cancelText: '继续上课',
onOk: () => {
onOk: async () => {
if (!lessonId.value) {
router.back();
return;
}
try {
await teacherApi.abandonLesson(lessonId.value);
pauseTimer();
message.success('已退出上课');
router.back();
} catch (error: any) {
message.error(error?.message || error?.response?.data?.message || '退出失败');
throw error;
}
},
});
};

View File

@ -154,6 +154,16 @@ public class TeacherLessonController {
return Result.success();
}
@Operation(summary = "退出上课(删除未完成的课时记录)")
@Log(module = LogModule.LESSON, type = LogOperationType.DELETE, description = "教师退出上课并删除课时")
@PostMapping("/{id}/abandon")
public Result<Void> abandonLesson(@PathVariable Long id) {
Long teacherId = SecurityUtils.getCurrentUserId();
Long tenantId = SecurityUtils.getCurrentTenantId();
lessonService.abandonLessonByTeacher(id, teacherId, tenantId);
return Result.success();
}
@Operation(summary = "获取今日课程")
@GetMapping("/today")
public Result<List<LessonResponse>> getTodayLessons() {

View File

@ -36,6 +36,11 @@ public interface LessonService extends com.baomidou.mybatisplus.extension.servic
void cancelLesson(Long id);
/**
* 教师退出上课删除未完成的课时记录已完成并回退课程包使用次数与取消逻辑一致已取消状态不再重复扣减
*/
void abandonLessonByTeacher(Long lessonId, Long teacherId, Long tenantId);
List<Lesson> getTodayLessons(Long tenantId);
/**

View File

@ -167,7 +167,7 @@ public class LessonServiceImpl extends ServiceImpl<LessonMapper, Lesson>
if (endDate != null) {
wrapper.le(Lesson::getLessonDate, endDate);
}
wrapper.orderByAsc(Lesson::getLessonDate, Lesson::getStartTime);
wrapper.orderByDesc(Lesson::getCreatedAt, Lesson::getUpdatedAt);
return lessonMapper.selectPage(page, wrapper);
}
@ -221,6 +221,33 @@ public class LessonServiceImpl extends ServiceImpl<LessonMapper, Lesson>
}
}
@Override
@Transactional
public void abandonLessonByTeacher(Long lessonId, Long teacherId, Long tenantId) {
Lesson lesson = getLessonById(lessonId);
if (!tenantId.equals(lesson.getTenantId())) {
throw new BusinessException(ErrorCode.FORBIDDEN, "无权操作该课时");
}
if (!teacherId.equals(lesson.getTeacherId())) {
throw new BusinessException(ErrorCode.FORBIDDEN, "无权操作该课时");
}
String st = lesson.getStatus();
if (LessonStatus.COMPLETED.getCode().equals(st)) {
throw new BusinessException(ErrorCode.BAD_REQUEST, "已完成的课程不可删除");
}
studentRecordMapper.delete(
new LambdaQueryWrapper<StudentRecord>().eq(StudentRecord::getLessonId, lessonId));
lessonFeedbackMapper.delete(
new LambdaQueryWrapper<LessonFeedback>().eq(LessonFeedback::getLessonId, lessonId));
// cancelLesson 一致仅当尚未处于已取消时回退使用次数避免重复扣减
if (lesson.getCourseId() != null && !LessonStatus.CANCELLED.getCode().equals(st)) {
coursePackageMapper.decrementUsageCount(lesson.getCourseId());
log.info("退出上课删除课时,课程包使用次数 -1: courseId={}", lesson.getCourseId());
}
lessonMapper.deleteById(lessonId);
log.info("教师退出上课,已删除课时记录 lessonId={}", lessonId);
}
@Override
public List<Lesson> getTodayLessons(Long tenantId) {
return lessonMapper.selectList(