feat: 题目解析和错题回顾
This commit is contained in:
@@ -119,4 +119,9 @@ public class ExamPaperQuestionDetailVo implements Serializable {
|
||||
* 题库题目逻辑删除标记(hot_question_bank.is_deleted)
|
||||
*/
|
||||
private Long questionIsDeleted;
|
||||
|
||||
/**
|
||||
* 题目解析
|
||||
*/
|
||||
private String caseDesc;
|
||||
}
|
||||
|
||||
@@ -84,6 +84,10 @@ public class HotExamPaperQuestionServiceImpl implements IHotExamPaperQuestionSer
|
||||
lqw.eq(bo.getQuestionId() != null, HotExamPaperQuestion::getQuestionId, bo.getQuestionId());
|
||||
lqw.eq(bo.getSortOrder() != null, HotExamPaperQuestion::getSortOrder, bo.getSortOrder());
|
||||
lqw.eq(bo.getScore() != null, HotExamPaperQuestion::getScore, bo.getScore());
|
||||
// 修复试卷试题顺序问题
|
||||
lqw.orderByAsc(HotExamPaperQuestion::getQuestionType)
|
||||
.orderByAsc(HotExamPaperQuestion::getSortOrder)
|
||||
.orderByAsc(HotExamPaperQuestion::getId);
|
||||
return lqw;
|
||||
}
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ public class HotQuestionBankImportVo implements Serializable {
|
||||
@ExcelDictFormat(readConverterExp = "1=普通,2=困难,3=极难")
|
||||
private Long difficulty;
|
||||
|
||||
@ExcelProperty(value = "案例描述", index = 11)
|
||||
@ExcelProperty(value = "解析", index = 11)
|
||||
private String caseDesc;
|
||||
|
||||
@ExcelProperty(value = "题型分类", index = 12, converter = ExcelDictConvert.class)
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.hotwj.platform.securityManagement.trainingAnswer.controller;
|
||||
import com.hotwj.platform.securityManagement.trainingAnswer.domain.bo.SubmitTrainingAnswerBo;
|
||||
import com.hotwj.platform.securityManagement.trainingAnswer.domain.bo.TrainingAnswerRecordBo;
|
||||
import com.hotwj.platform.securityManagement.trainingAnswer.domain.vo.HotTrainingAnswerRecordVo;
|
||||
import com.hotwj.platform.securityManagement.trainingAnswer.domain.vo.HotTrainingWrongQuestionReviewVo;
|
||||
import com.hotwj.platform.securityManagement.trainingAnswer.service.IHotTrainingAnswerRecordService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
@@ -12,6 +13,7 @@ import jakarta.validation.constraints.NotEmpty;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.dromara.common.core.domain.R;
|
||||
import org.dromara.common.core.utils.StringUtils;
|
||||
import org.dromara.common.core.validate.AddGroup;
|
||||
import org.dromara.common.core.validate.EditGroup;
|
||||
import org.dromara.common.excel.utils.ExcelUtil;
|
||||
@@ -20,6 +22,7 @@ import org.dromara.common.log.annotation.Log;
|
||||
import org.dromara.common.log.enums.BusinessType;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.common.satoken.utils.LoginHelper;
|
||||
import org.dromara.common.web.core.BaseController;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
@@ -138,4 +141,16 @@ public class HotTrainingAnswerRecordController extends BaseController {
|
||||
public R<Void> submit(@RequestBody @Validated(AddGroup.class) SubmitTrainingAnswerBo bo) {
|
||||
return toAjax(hotTrainingAnswerRecordService.submitWithSignature(bo));
|
||||
}
|
||||
|
||||
@GetMapping("/wrongQuestion/review")
|
||||
@Operation(summary = "查询错题回顾(当前用户)")
|
||||
public R<List<HotTrainingWrongQuestionReviewVo>> wrongQuestionReview(TrainingAnswerRecordBo bo) {
|
||||
Long companyId = LoginHelper.getCompanyId();
|
||||
String userId = LoginHelper.getBusinessUserId();
|
||||
if (StringUtils.isBlank(userId)) {
|
||||
userId = LoginHelper.getUserIdStr();
|
||||
}
|
||||
List<HotTrainingWrongQuestionReviewVo> result = hotTrainingAnswerRecordService.queryWrongQuestionReview(companyId, userId, bo);
|
||||
return R.ok(result);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,6 +130,16 @@ public class HotTrainingAnswerRecord extends BaseEntity {
|
||||
*/
|
||||
private Date answerTime;
|
||||
|
||||
/**
|
||||
* 错误次数
|
||||
*/
|
||||
private Integer errorCount;
|
||||
|
||||
/**
|
||||
* 错误答案,逗号拼接
|
||||
*/
|
||||
private String errorAnswers;
|
||||
|
||||
/**
|
||||
* 0=正常, 1=已删除
|
||||
*/
|
||||
|
||||
@@ -73,6 +73,10 @@ public class TrainingAnswerRecordBo extends BaseEntity {
|
||||
|
||||
private Date answerTime;
|
||||
|
||||
private Integer errorCount;
|
||||
|
||||
private String errorAnswers;
|
||||
|
||||
private Long isDeleted;
|
||||
|
||||
}
|
||||
|
||||
@@ -216,5 +216,7 @@ public class HotTrainingAnswerRecordVo implements Serializable {
|
||||
|
||||
private Boolean passed;
|
||||
|
||||
private Integer errorCount;
|
||||
|
||||
private String errorAnswers;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.hotwj.platform.securityManagement.trainingAnswer.domain.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
public class HotTrainingWrongQuestionReviewVo implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private Long questionId;
|
||||
private String questionType;
|
||||
private String questionDesc;
|
||||
private String imageUrl;
|
||||
|
||||
private String optionA;
|
||||
private String optionB;
|
||||
private String optionC;
|
||||
private String optionD;
|
||||
private String optionE;
|
||||
private String optionF;
|
||||
|
||||
private String correctAnswers;
|
||||
private String analysis;
|
||||
|
||||
private Integer errorCount;
|
||||
|
||||
}
|
||||
@@ -1,7 +1,10 @@
|
||||
package com.hotwj.platform.securityManagement.trainingAnswer.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.hotwj.platform.securityManagement.trainingAnswer.domain.HotTrainingAnswerRecord;
|
||||
import com.hotwj.platform.securityManagement.trainingAnswer.domain.bo.TrainingAnswerRecordBo;
|
||||
import com.hotwj.platform.securityManagement.trainingAnswer.domain.vo.HotTrainingAnswerRecordVo;
|
||||
import com.hotwj.platform.securityManagement.trainingAnswer.domain.vo.HotTrainingWrongQuestionReviewVo;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
|
||||
@@ -27,4 +30,8 @@ public interface HotTrainingAnswerRecordMapper extends BaseMapperPlus<HotTrainin
|
||||
@Param("userId") String userId
|
||||
);
|
||||
|
||||
java.util.List<HotTrainingWrongQuestionReviewVo> selectWrongQuestionReviewList(@Param("companyId") Long companyId,
|
||||
@Param("userId") String userId,
|
||||
@Param("bo") TrainingAnswerRecordBo bo);
|
||||
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.hotwj.platform.securityManagement.trainingAnswer.service;
|
||||
import com.hotwj.platform.securityManagement.trainingAnswer.domain.bo.TrainingAnswerRecordBo;
|
||||
import com.hotwj.platform.securityManagement.trainingAnswer.domain.bo.SubmitTrainingAnswerBo;
|
||||
import com.hotwj.platform.securityManagement.trainingAnswer.domain.vo.HotTrainingAnswerRecordVo;
|
||||
import com.hotwj.platform.securityManagement.trainingAnswer.domain.vo.HotTrainingWrongQuestionReviewVo;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
|
||||
@@ -84,4 +85,6 @@ public interface IHotTrainingAnswerRecordService {
|
||||
* @return 是否成功
|
||||
*/
|
||||
Boolean submitWithSignature(SubmitTrainingAnswerBo bo);
|
||||
|
||||
List<HotTrainingWrongQuestionReviewVo> queryWrongQuestionReview(Long companyId, String userId, TrainingAnswerRecordBo bo);
|
||||
}
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
package com.hotwj.platform.securityManagement.trainingAnswer.service.impl;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.hotwj.platform.config.examPaperQuestion.domain.vo.ExamPaperQuestionDetailVo;
|
||||
import com.hotwj.platform.config.examPaperQuestion.mapper.HotExamPaperQuestionMapper;
|
||||
import com.hotwj.platform.flow.service.ISysFlowService;
|
||||
import com.hotwj.platform.integration.ocr.SignatureVerifyService;
|
||||
import com.hotwj.platform.noticeManagerment.systemNotification.domain.bo.HotSystemNotificationGroupBo;
|
||||
@@ -17,6 +20,7 @@ import com.hotwj.platform.securityManagement.trainingAnswer.domain.bo.SubmitTrai
|
||||
import com.hotwj.platform.securityManagement.trainingAnswer.domain.bo.TrainingAnswerRecordBo;
|
||||
import com.hotwj.platform.securityManagement.trainingAnswer.domain.enums.TrainingSceneType;
|
||||
import com.hotwj.platform.securityManagement.trainingAnswer.domain.vo.HotTrainingAnswerRecordVo;
|
||||
import com.hotwj.platform.securityManagement.trainingAnswer.domain.vo.HotTrainingWrongQuestionReviewVo;
|
||||
import com.hotwj.platform.securityManagement.trainingAnswer.mapper.HotTrainingAnswerRecordMapper;
|
||||
import com.hotwj.platform.securityManagement.trainingAnswer.service.IHotTrainingAnswerRecordService;
|
||||
import com.hotwj.platform.securityManagement.trainingAudit.domain.HotTrainingAudit;
|
||||
@@ -64,6 +68,7 @@ public class HotTrainingAnswerRecordServiceImpl implements IHotTrainingAnswerRec
|
||||
private final TrainingProgressService trainingProgressService;
|
||||
private final HotTrainingAuditMapper trainingAuditMapper;
|
||||
private final SignatureVerifyService signatureVerifyService;
|
||||
private final HotExamPaperQuestionMapper examPaperQuestionMapper;
|
||||
|
||||
/**
|
||||
* 查询培训课程答题详情记录
|
||||
@@ -392,6 +397,69 @@ public class HotTrainingAnswerRecordServiceImpl implements IHotTrainingAnswerRec
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<HotTrainingWrongQuestionReviewVo> queryWrongQuestionReview(Long companyId, String userId, TrainingAnswerRecordBo bo) {
|
||||
if (companyId == null || StringUtils.isBlank(userId)) {
|
||||
return List.of();
|
||||
}
|
||||
// 1.查询试卷题目
|
||||
List<ExamPaperQuestionDetailVo> paperQuestions = loadPlanPaperQuestionList(bo);
|
||||
if (CollUtil.isEmpty(paperQuestions)) {
|
||||
return List.of();
|
||||
}
|
||||
|
||||
// 2.查询本次培训计划中错题信息
|
||||
List<HotTrainingWrongQuestionReviewVo> wrongList = baseMapper.selectWrongQuestionReviewList(companyId, userId, bo);
|
||||
if (CollUtil.isEmpty(wrongList)) {
|
||||
return List.of();
|
||||
}
|
||||
|
||||
// 3.组装返回给前端的错题信息
|
||||
Map<Long, HotTrainingWrongQuestionReviewVo> wrongByQuestionId = wrongList.stream()
|
||||
.filter(v -> v.getQuestionId() != null)
|
||||
.collect(Collectors.toMap(HotTrainingWrongQuestionReviewVo::getQuestionId, Function.identity(), (a, b) -> a));
|
||||
|
||||
List<HotTrainingWrongQuestionReviewVo> orderedWrong = new ArrayList<>();
|
||||
Set<Long> addedQuestionIds = new HashSet<>();
|
||||
for (ExamPaperQuestionDetailVo questionDetail : paperQuestions) {
|
||||
if (questionDetail == null || questionDetail.getQuestionId() == null) {
|
||||
continue;
|
||||
}
|
||||
Long questionId = questionDetail.getQuestionId();
|
||||
if (!addedQuestionIds.add(questionId)) {
|
||||
continue;
|
||||
}
|
||||
HotTrainingWrongQuestionReviewVo vo = wrongByQuestionId.get(questionId);
|
||||
if (vo == null) {
|
||||
continue;
|
||||
}
|
||||
vo.setQuestionType(questionDetail.getQuestionType());
|
||||
vo.setQuestionDesc(questionDetail.getQuestionDesc());
|
||||
vo.setImageUrl(questionDetail.getImageUrl());
|
||||
vo.setOptionA(questionDetail.getOptionA());
|
||||
vo.setOptionB(questionDetail.getOptionB());
|
||||
vo.setOptionC(questionDetail.getOptionC());
|
||||
vo.setOptionD(questionDetail.getOptionD());
|
||||
vo.setOptionE(questionDetail.getOptionE());
|
||||
vo.setOptionF(questionDetail.getOptionF());
|
||||
vo.setCorrectAnswers(questionDetail.getCorrectAnswers());
|
||||
vo.setAnalysis(questionDetail.getCaseDesc());
|
||||
orderedWrong.add(vo);
|
||||
}
|
||||
return orderedWrong;
|
||||
}
|
||||
|
||||
private List<ExamPaperQuestionDetailVo> loadPlanPaperQuestionList(TrainingAnswerRecordBo bo) {
|
||||
if (bo == null || bo.getExamId() == null) {
|
||||
return List.of();
|
||||
}
|
||||
List<ExamPaperQuestionDetailVo> list = examPaperQuestionMapper.selectPaperQuestionDetailList(bo.getExamId());
|
||||
if (CollUtil.isEmpty(list)) {
|
||||
return List.of();
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
private void clearPlanAuditRecord(SubmitTrainingAnswerBo bo) {
|
||||
if (bo.getCompanyId() == null || bo.getTrainingId() == null || StringUtils.isBlank(bo.getUserId())) {
|
||||
return;
|
||||
|
||||
@@ -26,7 +26,8 @@
|
||||
qb.option_f AS optionF,
|
||||
qb.correct_answers AS correctAnswers,
|
||||
qb.score AS questionScore,
|
||||
qb.is_deleted AS questionIsDeleted
|
||||
qb.is_deleted AS questionIsDeleted,
|
||||
qb.case_desc AS caseDesc
|
||||
FROM hot_exam_paper_question epq
|
||||
LEFT JOIN hot_question_bank qb ON qb.id = epq.question_id
|
||||
WHERE epq.paper_id = #{paperId}
|
||||
|
||||
@@ -136,4 +136,20 @@
|
||||
ORDER BY ar.question_order ASC, ar.id ASC
|
||||
</select>
|
||||
|
||||
<!-- 错题回顾 -->
|
||||
<select id="selectWrongQuestionReviewList"
|
||||
resultType="com.hotwj.platform.securityManagement.trainingAnswer.domain.vo.HotTrainingWrongQuestionReviewVo">
|
||||
SELECT ar.question_id AS questionId,
|
||||
count(ar.question_id) AS errorCount
|
||||
FROM hot_training_answer_record ar
|
||||
WHERE ar.is_deleted = 0
|
||||
AND ar.company_id = #{companyId}
|
||||
AND ar.user_id = #{userId}
|
||||
AND ar.scene_type = 'PLAN'
|
||||
AND ar.training_id = #{bo.trainingId}
|
||||
AND ar.exam_id = #{bo.examId}
|
||||
AND ar.error_answers IS NOT NULL
|
||||
AND ar.error_answers <> ''
|
||||
GROUP BY ar.question_id
|
||||
</select>
|
||||
</mapper>
|
||||
|
||||
Reference in New Issue
Block a user