From 49274de68ad0c7f83cab9f2a5c8336d01ad66b12 Mon Sep 17 00:00:00 2001 From: zhanglei Date: Mon, 24 Aug 2026 15:06:50 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E6=95=99=E5=9F=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/ClassCourseController.java | 15 +++ .../qinan/cedu/model/dto/ClassStudentDTO.java | 4 + .../cedu/model/entity/ClassStudentDO.java | 3 + .../qinan/cedu/model/vo/ClassCourseVO.java | 17 +++ .../model/vo/ClassStudentExamRecordVO.java | 6 + .../qinan/cedu/model/vo/ClassStudentVO.java | 4 + .../model/vo/ExamStatisticsAndRecordVO.java | 26 +++++ .../cedu/service/ClassCourseService.java | 6 + .../service/impl/ClassCourseServiceImpl.java | 104 +++++++++++++++++- safety-cedu-service/src/班级管理.sql | 1 + 10 files changed, 183 insertions(+), 3 deletions(-) create mode 100644 safety-cedu-service/src/main/java/org/qinan/cedu/model/vo/ExamStatisticsAndRecordVO.java diff --git a/safety-cedu-service/src/main/java/org/qinan/cedu/controller/ClassCourseController.java b/safety-cedu-service/src/main/java/org/qinan/cedu/controller/ClassCourseController.java index 57a08238..14e85650 100644 --- a/safety-cedu-service/src/main/java/org/qinan/cedu/controller/ClassCourseController.java +++ b/safety-cedu-service/src/main/java/org/qinan/cedu/controller/ClassCourseController.java @@ -7,6 +7,7 @@ import io.swagger.annotations.ApiParam; import org.qinan.cedu.model.dto.ClassCourseDTO; import org.qinan.cedu.model.query.ClassCoursePageQuery; import org.qinan.cedu.model.vo.ClassCourseVO; +import org.qinan.cedu.model.vo.ExamStatisticsAndRecordVO; import org.qinan.cedu.service.ClassCourseService; import org.qinan.safetyeval.client.dto.PageResponse; import org.qinan.safetyeval.client.dto.SingleResponse; @@ -67,4 +68,18 @@ public class ClassCourseController { IPage page = classCourseService.pageQuery(query); return PageResponse.of(page.getRecords(), page.getTotal()); } + + @ApiOperation("我的课程") + @GetMapping("/myCoursePage") + public SingleResponse> myCoursePage() { + List list = classCourseService.myCoursePage(); + return SingleResponse.success(list); + } + + @ApiOperation("成绩查询") + @GetMapping("/scoreQuery") + public SingleResponse scoreQuery() { + ExamStatisticsAndRecordVO examStatisticsAndRecordVO = classCourseService.scoreQuery(); + return SingleResponse.success(examStatisticsAndRecordVO); + } } diff --git a/safety-cedu-service/src/main/java/org/qinan/cedu/model/dto/ClassStudentDTO.java b/safety-cedu-service/src/main/java/org/qinan/cedu/model/dto/ClassStudentDTO.java index 14493ef7..5fbed03d 100644 --- a/safety-cedu-service/src/main/java/org/qinan/cedu/model/dto/ClassStudentDTO.java +++ b/safety-cedu-service/src/main/java/org/qinan/cedu/model/dto/ClassStudentDTO.java @@ -1,5 +1,6 @@ package org.qinan.cedu.model.dto; +import com.baomidou.mybatisplus.annotation.TableField; import com.fasterxml.jackson.annotation.JsonFormat; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @@ -55,4 +56,7 @@ public class ClassStudentDTO { @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") private LocalDateTime entryTime; + @TableField("student_id") + private String studentId; + } diff --git a/safety-cedu-service/src/main/java/org/qinan/cedu/model/entity/ClassStudentDO.java b/safety-cedu-service/src/main/java/org/qinan/cedu/model/entity/ClassStudentDO.java index 215b452f..95d75313 100644 --- a/safety-cedu-service/src/main/java/org/qinan/cedu/model/entity/ClassStudentDO.java +++ b/safety-cedu-service/src/main/java/org/qinan/cedu/model/entity/ClassStudentDO.java @@ -63,4 +63,7 @@ public class ClassStudentDO extends BaseEntity { @TableField("entry_time") private LocalDateTime entryTime; + @TableField("student_id") + private String studentId; + } diff --git a/safety-cedu-service/src/main/java/org/qinan/cedu/model/vo/ClassCourseVO.java b/safety-cedu-service/src/main/java/org/qinan/cedu/model/vo/ClassCourseVO.java index bea9ae98..e9250d57 100644 --- a/safety-cedu-service/src/main/java/org/qinan/cedu/model/vo/ClassCourseVO.java +++ b/safety-cedu-service/src/main/java/org/qinan/cedu/model/vo/ClassCourseVO.java @@ -1,10 +1,13 @@ package org.qinan.cedu.model.vo; +import com.fasterxml.jackson.annotation.JsonFormat; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import lombok.EqualsAndHashCode; +import org.springframework.format.annotation.DateTimeFormat; import java.math.BigDecimal; +import java.time.LocalDateTime; import java.util.List; /** @@ -38,4 +41,18 @@ public class ClassCourseVO extends BaseVO { @ApiModelProperty("已完成学员数") private Long completedCount; + + @ApiModelProperty("app: 学员完成状态: 0未完成,1未学习,2完成") + private Integer completed; + + @ApiModelProperty("培训结束日期") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime endDate; + + @ApiModelProperty("app: 班级名称") + private String className; + + @ApiModelProperty("归属课件") + private List coursewareList; } diff --git a/safety-cedu-service/src/main/java/org/qinan/cedu/model/vo/ClassStudentExamRecordVO.java b/safety-cedu-service/src/main/java/org/qinan/cedu/model/vo/ClassStudentExamRecordVO.java index 71b19aa5..e12a9c8b 100644 --- a/safety-cedu-service/src/main/java/org/qinan/cedu/model/vo/ClassStudentExamRecordVO.java +++ b/safety-cedu-service/src/main/java/org/qinan/cedu/model/vo/ClassStudentExamRecordVO.java @@ -53,4 +53,10 @@ public class ClassStudentExamRecordVO extends BaseVO { @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") private LocalDateTime endTime; + + @ApiModelProperty("app: 班级名称") + private String className; + + @ApiModelProperty("app: 考试时长分钟") + private Integer examDurationMinutes; } diff --git a/safety-cedu-service/src/main/java/org/qinan/cedu/model/vo/ClassStudentVO.java b/safety-cedu-service/src/main/java/org/qinan/cedu/model/vo/ClassStudentVO.java index e41ed636..fe8dc034 100644 --- a/safety-cedu-service/src/main/java/org/qinan/cedu/model/vo/ClassStudentVO.java +++ b/safety-cedu-service/src/main/java/org/qinan/cedu/model/vo/ClassStudentVO.java @@ -1,5 +1,6 @@ package org.qinan.cedu.model.vo; +import com.baomidou.mybatisplus.annotation.TableField; import com.fasterxml.jackson.annotation.JsonFormat; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @@ -54,4 +55,7 @@ public class ClassStudentVO extends BaseVO { @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") private LocalDateTime entryTime; + @TableField("student_id") + private String studentId; + } diff --git a/safety-cedu-service/src/main/java/org/qinan/cedu/model/vo/ExamStatisticsAndRecordVO.java b/safety-cedu-service/src/main/java/org/qinan/cedu/model/vo/ExamStatisticsAndRecordVO.java new file mode 100644 index 00000000..547d2481 --- /dev/null +++ b/safety-cedu-service/src/main/java/org/qinan/cedu/model/vo/ExamStatisticsAndRecordVO.java @@ -0,0 +1,26 @@ +package org.qinan.cedu.model.vo; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.List; + +/** + * 学员考试统计和记录 + * @TableName class_student_exam_record + */ +@Data +public class ExamStatisticsAndRecordVO { + // 参加考试次数 + @ApiModelProperty("参加考试次数") + private int totalExams; + // 合格次数 + @ApiModelProperty("合格次数") + private int passedExams; + // 不合格次数 + @ApiModelProperty("不合格次数") + private int failedExams; + + @ApiModelProperty("考试记录") + private List classStudentExamRecordVO; +} diff --git a/safety-cedu-service/src/main/java/org/qinan/cedu/service/ClassCourseService.java b/safety-cedu-service/src/main/java/org/qinan/cedu/service/ClassCourseService.java index 6d310534..ee888bf2 100644 --- a/safety-cedu-service/src/main/java/org/qinan/cedu/service/ClassCourseService.java +++ b/safety-cedu-service/src/main/java/org/qinan/cedu/service/ClassCourseService.java @@ -6,6 +6,7 @@ import org.qinan.cedu.model.dto.ClassCourseDTO; import org.qinan.cedu.model.entity.ClassCourseDO; import org.qinan.cedu.model.query.ClassCoursePageQuery; import org.qinan.cedu.model.vo.ClassCourseVO; +import org.qinan.cedu.model.vo.ExamStatisticsAndRecordVO; import java.util.List; @@ -31,4 +32,9 @@ public interface ClassCourseService extends IService { boolean updateCourse(ClassCourseDTO dto); boolean deleteById(Long id); + + List myCoursePage(); + + ExamStatisticsAndRecordVO scoreQuery(); + } diff --git a/safety-cedu-service/src/main/java/org/qinan/cedu/service/impl/ClassCourseServiceImpl.java b/safety-cedu-service/src/main/java/org/qinan/cedu/service/impl/ClassCourseServiceImpl.java index b2cad044..a8431642 100644 --- a/safety-cedu-service/src/main/java/org/qinan/cedu/service/impl/ClassCourseServiceImpl.java +++ b/safety-cedu-service/src/main/java/org/qinan/cedu/service/impl/ClassCourseServiceImpl.java @@ -1,25 +1,33 @@ package org.qinan.cedu.service.impl; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import org.qinan.cedu.convertor.ClassCourseConvertor; +import org.qinan.cedu.convertor.ClassStudentExamRecordConvertor; +import org.qinan.cedu.convertor.CourseRelCoursewareConvertor; +import org.qinan.cedu.convertor.CoursewareManagementConvertor; import org.qinan.cedu.enums.DeleteEnum; -import org.qinan.cedu.mapper.ClassCourseMapper; -import org.qinan.cedu.mapper.ClassStudentLearningRecordMapper; +import org.qinan.cedu.mapper.*; import org.qinan.cedu.model.dto.ClassCourseDTO; -import org.qinan.cedu.model.entity.ClassCourseDO; +import org.qinan.cedu.model.entity.*; import org.qinan.cedu.model.query.ClassCoursePageQuery; import org.qinan.cedu.model.vo.ClassCourseVO; +import org.qinan.cedu.model.vo.ClassStudentExamRecordVO; import org.qinan.cedu.model.vo.CourseStudentStatVO; +import org.qinan.cedu.model.vo.ExamStatisticsAndRecordVO; import org.qinan.cedu.service.ClassCourseService; +import org.qinan.safetyeval.infrastructure.adapter.auth.AuthUserContextAdapter; import org.qinan.safetyeval.infrastructure.support.InsertFieldDefaults; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; +import java.time.Duration; import java.time.LocalDateTime; +import java.util.Collections; import java.util.List; import java.util.Map; import java.util.function.Function; @@ -37,6 +45,22 @@ public class ClassCourseServiceImpl extends ServiceImpl pageQuery(ClassCoursePageQuery query) { @@ -127,4 +151,78 @@ public class ClassCourseServiceImpl extends ServiceImpl 0; } + + @Override + public List myCoursePage() { + List classId = classStudentMapper.selectList(new LambdaQueryWrapper() + .eq(ClassStudentDO::getStudentId, AuthUserContextAdapter.getCurrentUserId())) + .stream().map(ClassStudentDO::getClassId).distinct().collect(Collectors.toList()); + List classCourseDOS = baseMapper.selectList(new LambdaQueryWrapper() + .eq(ClassCourseDO::getClassId, CollectionUtils.isEmpty(classId) ? Collections.singletonList(0L) : classId) + .eq(ClassCourseDO::getDeleteEnum, DeleteEnum.FALSE.getCode())); + //查询班级 + Map collectClassMap = classManagementMapper.selectList(new LambdaQueryWrapper() + .in(ClassManagementDO::getId, CollectionUtils.isEmpty(classId) ? Collections.singletonList(0L) : classId)) + .stream().collect(Collectors.toMap(ClassManagementDO::getId, Function.identity())); + return classCourseDOS.stream().map(item -> { + ClassCourseVO classCourseVO = classCourseConvertor.convertEToVo(item); + List classStudentLearningRecordDOS = learningRecordMapper.selectList(new LambdaQueryWrapper() + .eq(ClassStudentLearningRecordDO::getStudentId, AuthUserContextAdapter.getCurrentUserId()) + .eq(ClassStudentLearningRecordDO::getCourseId, item.getId()) + .eq(ClassStudentLearningRecordDO::getClassId, item.getClassId())); + // getStudyStatus()都为2就是完成, 否则为未完成 + int completed = classStudentLearningRecordDOS.stream().allMatch(record -> record.getStudyStatus() != null && record.getStudyStatus() == 2) ? 2 : 0; + ClassManagementDO classManagementDO = collectClassMap.get(item.getClassId()); + if (classManagementDO != null) { + classCourseVO.setClassName(classManagementDO.getClassName()); + LocalDateTime endDate = classManagementDO.getEndDate(); + if (classManagementDO.getDelayTime() != null && classManagementDO.getDelayTime().isAfter(endDate)) { + endDate = classManagementDO.getDelayTime(); + } + classCourseVO.setEndDate(endDate); + } + if (completed == 0) { + LocalDateTime endDate = classCourseVO.getEndDate(); + if (LocalDateTime.now().isBefore(endDate)) { + classCourseVO.setCompleted(1); + } + } + classCourseVO.setCompleted(completed); + // 查询课件 + classCourseVO.setCoursewareList(coursewareManagementMapper.selectBatchIds(item.getCoursewareId()) + .stream().map(coursewareManagementConvertor::convertEToVo).collect(Collectors.toList())); + return classCourseVO; + }).collect(Collectors.toList()); + } + + @Override + public ExamStatisticsAndRecordVO scoreQuery() { + ExamStatisticsAndRecordVO examStatisticsAndRecordVO = new ExamStatisticsAndRecordVO(); + List classId = classStudentMapper.selectList(new LambdaQueryWrapper() + .eq(ClassStudentDO::getStudentId, AuthUserContextAdapter.getCurrentUserId())) + .stream().map(ClassStudentDO::getClassId).distinct().collect(Collectors.toList()); + List classStudentExamRecordDOS = classStudentExamRecordMapper.selectList(new LambdaQueryWrapper() + .eq(ClassStudentExamRecordDO::getStudentId, AuthUserContextAdapter.getCurrentUserId()) + .in(ClassStudentExamRecordDO::getClassId, CollectionUtils.isEmpty(classId) ? Collections.singletonList(0L) : classId)); + //查询班级 + Map collectClassMap = classManagementMapper.selectList(new LambdaQueryWrapper() + .in(ClassManagementDO::getId, CollectionUtils.isEmpty(classId) ? Collections.singletonList(0L) : classId)) + .stream().collect(Collectors.toMap(ClassManagementDO::getId, Function.identity())); + examStatisticsAndRecordVO.setClassStudentExamRecordVO(classStudentExamRecordDOS.stream().map(item -> { + ClassStudentExamRecordVO classStudentExamRecordVO = classStudentExamRecordConvertor.convertEToVo(item); + ClassManagementDO classManagementDO = collectClassMap.get(item.getClassId()); + if (classManagementDO != null) { + classStudentExamRecordVO.setClassName(classManagementDO.getClassName()); + } + // 结束时间 - 开始时间 = 时长 + Duration duration = Duration.between(item.getStartTime(), item.getEndTime()); + classStudentExamRecordVO.setExamDurationMinutes((int) duration.toMinutes()); + return classStudentExamRecordVO; + }).collect(Collectors.toList())); + // 设置: 参加考试次数, 合格次数, 不合格次数 @ApiModelProperty("是否通过(0-未通过,1-通过)")passed + examStatisticsAndRecordVO.setTotalExams(classStudentExamRecordDOS.size()); + examStatisticsAndRecordVO.setPassedExams((int) classStudentExamRecordDOS.stream().filter(record -> record.getPassed() != null && record.getPassed() == 1).count()); + examStatisticsAndRecordVO.setFailedExams((int) classStudentExamRecordDOS.stream().filter(record -> record.getPassed() != null && record.getPassed() == 0).count()); + return examStatisticsAndRecordVO; + } } diff --git a/safety-cedu-service/src/班级管理.sql b/safety-cedu-service/src/班级管理.sql index 94ad02ef..bea6796a 100644 --- a/safety-cedu-service/src/班级管理.sql +++ b/safety-cedu-service/src/班级管理.sql @@ -80,6 +80,7 @@ create table class_student study_status int default 0 null comment '学习状态:0-未学习,1-学习中,2-已学完,3-已完成', exam_status int default 0 null comment '考试状态:0-不考试,1-待考试,2-考试未通过,3-考试通过,4-未参加', entry_time datetime null comment '入班时间', + student_id varchar(20) null comment '学员(来源id)', delete_enum varchar(32) null comment '删除标识true false', remarks varchar(255) null comment '备注', create_name varchar(50) null comment '创建人姓名',