user paper exam

dev-tmp1
luotaiqian 2026-08-24 15:16:06 +08:00
parent 49274de68a
commit 9b4315dafb
9 changed files with 77 additions and 11 deletions

View File

@ -30,8 +30,8 @@ public class ClassStudentExamRecordDTO {
@ApiModelProperty("试卷名称") @ApiModelProperty("试卷名称")
private String paperName; private String paperName;
@ApiModelProperty("试卷id") @ApiModelProperty("考试试卷id")
private Long paperId; private Long paperExamId;
@ApiModelProperty("得分") @ApiModelProperty("得分")
private BigDecimal score; private BigDecimal score;

View File

@ -17,6 +17,9 @@ public class StartExamDTO {
@NotNull(message = "试卷id不能为空") @NotNull(message = "试卷id不能为空")
private Long paperId; private Long paperId;
@ApiModelProperty("班级id非空时生成班级学员考试记录")
private Long classId;
@ApiModelProperty("用户id") @ApiModelProperty("用户id")
private Long userId; private Long userId;
} }

View File

@ -34,8 +34,8 @@ public class ClassStudentExamRecordDO extends BaseEntity {
@TableField("paper_name") @TableField("paper_name")
private String paperName; private String paperName;
@TableField("paper_id") @TableField("paper_exam_id")
private Long paperId; private Long paperExamId;
@TableField("score") @TableField("score")
private BigDecimal score; private BigDecimal score;

View File

@ -17,8 +17,8 @@ public class ClassStudentExamRecordPageQuery extends BasePageQuery {
@ApiModelProperty("学员ID") @ApiModelProperty("学员ID")
private Long studentId; private Long studentId;
@ApiModelProperty("试卷id") @ApiModelProperty("考试试卷id")
private Long paperId; private Long paperExamId;
@ApiModelProperty("是否通过0-未通过1-通过)") @ApiModelProperty("是否通过0-未通过1-通过)")
private Integer passed; private Integer passed;

View File

@ -29,8 +29,8 @@ public class ClassStudentExamRecordVO extends BaseVO {
@ApiModelProperty("试卷名称") @ApiModelProperty("试卷名称")
private String paperName; private String paperName;
@ApiModelProperty("试卷id") @ApiModelProperty("考试试卷id")
private String paperId; private String paperExamId;
@ApiModelProperty("得分") @ApiModelProperty("得分")
private BigDecimal score; private BigDecimal score;

View File

@ -57,7 +57,7 @@ public interface PaperExamService extends IService<PaperExamDO> {
boolean deleteById(Long id); boolean deleteById(Long id);
/** /**
* * id
* *
* @param dto ididController * @param dto ididController
* @return * @return

View File

@ -33,7 +33,7 @@ public class ClassStudentExamRecordServiceImpl extends ServiceImpl<ClassStudentE
.eq(ClassStudentExamRecordDO::getDeleteEnum, DeleteEnum.FALSE.getCode()) .eq(ClassStudentExamRecordDO::getDeleteEnum, DeleteEnum.FALSE.getCode())
.eq(query.getClassId() != null, ClassStudentExamRecordDO::getClassId, query.getClassId()) .eq(query.getClassId() != null, ClassStudentExamRecordDO::getClassId, query.getClassId())
.eq(query.getStudentId() != null, ClassStudentExamRecordDO::getStudentId, query.getStudentId()) .eq(query.getStudentId() != null, ClassStudentExamRecordDO::getStudentId, query.getStudentId())
.eq(query.getPaperId() != null, ClassStudentExamRecordDO::getPaperId, query.getPaperId()) .eq(query.getPaperExamId() != null, ClassStudentExamRecordDO::getPaperExamId, query.getPaperExamId())
.eq(query.getPassed() != null, ClassStudentExamRecordDO::getPassed, query.getPassed()) .eq(query.getPassed() != null, ClassStudentExamRecordDO::getPassed, query.getPassed())
.orderByDesc(ClassStudentExamRecordDO::getCreateTime) .orderByDesc(ClassStudentExamRecordDO::getCreateTime)
.page(new Page<>(query.getCurrent(), query.getSize())) .page(new Page<>(query.getCurrent(), query.getSize()))

View File

@ -10,6 +10,7 @@ import org.qinan.cedu.convertor.PaperExamQuestionUserConvertor;
import org.qinan.cedu.enums.AnswerStatusEnum; import org.qinan.cedu.enums.AnswerStatusEnum;
import org.qinan.cedu.enums.DeleteEnum; import org.qinan.cedu.enums.DeleteEnum;
import org.qinan.cedu.enums.PaperExamStatusEnum; import org.qinan.cedu.enums.PaperExamStatusEnum;
import org.qinan.cedu.mapper.ClassStudentExamRecordMapper;
import org.qinan.cedu.mapper.PaperExamMapper; import org.qinan.cedu.mapper.PaperExamMapper;
import org.qinan.cedu.mapper.PaperExamQuestionUserMapper; import org.qinan.cedu.mapper.PaperExamQuestionUserMapper;
import org.qinan.cedu.mapper.PaperMapper; import org.qinan.cedu.mapper.PaperMapper;
@ -19,6 +20,7 @@ import org.qinan.cedu.model.dto.PaperExamDTO;
import org.qinan.cedu.model.dto.PaperExamPageQueryDTO; import org.qinan.cedu.model.dto.PaperExamPageQueryDTO;
import org.qinan.cedu.model.dto.StartExamDTO; import org.qinan.cedu.model.dto.StartExamDTO;
import org.qinan.cedu.model.dto.SubmitExamDTO; import org.qinan.cedu.model.dto.SubmitExamDTO;
import org.qinan.cedu.model.entity.ClassStudentExamRecordDO;
import org.qinan.cedu.model.entity.PaperDO; import org.qinan.cedu.model.entity.PaperDO;
import org.qinan.cedu.model.entity.PaperExamDO; import org.qinan.cedu.model.entity.PaperExamDO;
import org.qinan.cedu.model.entity.PaperExamQuestionUserDO; import org.qinan.cedu.model.entity.PaperExamQuestionUserDO;
@ -29,12 +31,14 @@ import org.qinan.cedu.model.vo.StartExamVO;
import org.qinan.cedu.service.PaperExamQuestionUserService; import org.qinan.cedu.service.PaperExamQuestionUserService;
import org.qinan.cedu.service.PaperExamService; import org.qinan.cedu.service.PaperExamService;
import org.qinan.safetyeval.domain.constant.BooleanQAEnum; import org.qinan.safetyeval.domain.constant.BooleanQAEnum;
import org.qinan.safetyeval.infrastructure.adapter.auth.AuthUserContextAdapter;
import org.qinan.safetyeval.infrastructure.support.InsertFieldDefaults; import org.qinan.safetyeval.infrastructure.support.InsertFieldDefaults;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
@ -61,6 +65,8 @@ public class PaperExamServiceImpl extends ServiceImpl<PaperExamMapper, PaperExam
private final PaperExamQuestionUserMapper paperExamQuestionUserMapper; private final PaperExamQuestionUserMapper paperExamQuestionUserMapper;
private final ClassStudentExamRecordMapper classStudentExamRecordMapper;
@Override @Override
public IPage<PaperExamVO> pageQuery(PaperExamPageQueryDTO query) { public IPage<PaperExamVO> pageQuery(PaperExamPageQueryDTO query) {
return this.lambdaQuery() return this.lambdaQuery()
@ -132,6 +138,8 @@ public class PaperExamServiceImpl extends ServiceImpl<PaperExamMapper, PaperExam
this.save(paperExam); this.save(paperExam);
// 生成并保存用户试题作答记录,同时回填作答记录信息到返回列表 // 生成并保存用户试题作答记录,同时回填作答记录信息到返回列表
saveQuestionUserList(paperExam, questionList); saveQuestionUserList(paperExam, questionList);
// 携带班级id时生成班级学员考试记录交卷时回填成绩
saveClassStudentExamRecord(paper, paperExam, dto.getClassId());
// 组装返回结果 // 组装返回结果
StartExamVO startExamVO = paperExamConvertor.convertEToStartExamVo(paperExam); StartExamVO startExamVO = paperExamConvertor.convertEToStartExamVo(paperExam);
startExamVO.setPaperType(paper.getPaperType()); startExamVO.setPaperType(paper.getPaperType());
@ -192,6 +200,61 @@ public class PaperExamServiceImpl extends ServiceImpl<PaperExamMapper, PaperExam
// paper_exam 表无 org_id 列更新前不填充机构id // paper_exam 表无 org_id 列更新前不填充机构id
InsertFieldDefaults.applyForUpdateIgnoreOrgId(paperExam); InsertFieldDefaults.applyForUpdateIgnoreOrgId(paperExam);
this.updateById(paperExam); this.updateById(paperExam);
// 回填班级学员考试记录的成绩数据开始考试未携带班级id时无记录跳过
finishClassStudentExamRecord(paperExam, examScore);
}
/**
* 0
*/
private void saveClassStudentExamRecord(PaperDO paper, PaperExamDO paperExam, Long classId) {
if (classId == null) {
return;
}
ClassStudentExamRecordDO examRecord = new ClassStudentExamRecordDO();
examRecord.setStudentId(paperExam.getUserId());
String studentName = AuthUserContextAdapter.getCurrentUserName();
examRecord.setStudentName(studentName == null ? "系统" : studentName);
examRecord.setClassId(classId);
examRecord.setPaperName(paper.getPaperName());
examRecord.setPaperExamId(paperExam.getId());
examRecord.setScore(BigDecimal.ZERO);
examRecord.setPassed(0);
examRecord.setWrongCount(0);
examRecord.setAccuracy(BigDecimal.ZERO);
examRecord.setStartTime(LocalDateTime.now());
InsertFieldDefaults.apply(examRecord);
classStudentExamRecordMapper.insert(examRecord);
}
/**
*
*/
private void finishClassStudentExamRecord(PaperExamDO paperExam, BigDecimal examScore) {
ClassStudentExamRecordDO examRecord = classStudentExamRecordMapper.selectOne(new LambdaQueryWrapper<ClassStudentExamRecordDO>()
.eq(ClassStudentExamRecordDO::getPaperExamId, paperExam.getId())
.eq(ClassStudentExamRecordDO::getDeleteEnum, DeleteEnum.FALSE.getCode())
.orderByDesc(ClassStudentExamRecordDO::getId)
.last("limit 1"));
if (examRecord == null) {
return;
}
// 统计总题数与答对题数,错误题数=总题数-答对题数(未作答按错误计),正确率=答对/总数*100
long total = paperExamQuestionUserService.count(new LambdaQueryWrapper<PaperExamQuestionUserDO>()
.eq(PaperExamQuestionUserDO::getPaperExamId, paperExam.getId())
.eq(PaperExamQuestionUserDO::getDeleteEnum, DeleteEnum.FALSE.getCode()));
long correct = paperExamQuestionUserService.count(new LambdaQueryWrapper<PaperExamQuestionUserDO>()
.eq(PaperExamQuestionUserDO::getPaperExamId, paperExam.getId())
.eq(PaperExamQuestionUserDO::getDeleteEnum, DeleteEnum.FALSE.getCode())
.eq(PaperExamQuestionUserDO::getRightStatus, BooleanQAEnum.TRUE.getValue()));
examRecord.setScore(examScore);
examRecord.setPassed(paperExam.getPassed());
examRecord.setWrongCount((int) (total - correct));
examRecord.setAccuracy(total == 0 ? BigDecimal.ZERO
: BigDecimal.valueOf(correct * 100).divide(BigDecimal.valueOf(total), 2, RoundingMode.HALF_UP));
examRecord.setEndTime(LocalDateTime.now());
InsertFieldDefaults.applyForUpdate(examRecord);
classStudentExamRecordMapper.updateById(examRecord);
} }
/** /**

View File

@ -106,7 +106,7 @@ create table class_student_exam_record
student_name varchar(20) not null comment '学员名称', student_name varchar(20) not null comment '学员名称',
class_id bigint not null comment '所属班级ID关联training_class.id', class_id bigint not null comment '所属班级ID关联training_class.id',
paper_name varchar(200) not null comment '试卷名称', paper_name varchar(200) not null comment '试卷名称',
paper_id bigint not null comment '试卷id', paper_exam_id bigint not null comment '考试试卷id关联paper_exam.id',
score decimal(10, 2) null comment '得分', score decimal(10, 2) null comment '得分',
passed tinyint(1) default 0 null comment '是否通过0-未通过1-通过)', passed tinyint(1) default 0 null comment '是否通过0-未通过1-通过)',
wrong_count int default 0 null comment '错误题数', wrong_count int default 0 null comment '错误题数',