|
|
@@ -6,15 +6,11 @@ import cn.reghao.jutil.jdk.result.Result;
|
|
|
import cn.reghao.tnb.common.auth.UserContext;
|
|
|
import cn.reghao.tnb.common.db.KeyValue;
|
|
|
import cn.reghao.tnb.content.app.exam.db.mapper.*;
|
|
|
-import cn.reghao.tnb.content.app.exam.model.constant.PaperViewType;
|
|
|
-import cn.reghao.tnb.content.app.exam.model.constant.QuestionType;
|
|
|
import cn.reghao.tnb.content.app.exam.model.dto.PaperAddDto;
|
|
|
-import cn.reghao.tnb.content.app.exam.model.dto.UserResult;
|
|
|
import cn.reghao.tnb.content.app.exam.model.po.*;
|
|
|
import cn.reghao.tnb.content.app.exam.model.query.ExamQuery;
|
|
|
import cn.reghao.tnb.content.app.exam.model.query.PaperQuery;
|
|
|
import cn.reghao.tnb.content.app.exam.model.vo.*;
|
|
|
-import cn.reghao.tnb.content.app.util.redis.ds.RedisHash;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
|
@@ -33,23 +29,17 @@ public class PaperService {
|
|
|
private final PaperQuestionMapper paperQuestionMapper;
|
|
|
private final QuestionMapper questionMapper;
|
|
|
private final QuestionOptionMapper questionOptionMapper;
|
|
|
- private final RedisHash redisHash;
|
|
|
- private String keyPrefix = "tnb:exam:result";
|
|
|
- private PaperResultMapper paperResultMapper;
|
|
|
- private PaperAnswerMapper paperAnswerMapper;
|
|
|
- private ExamUserMapper examUserMapper;
|
|
|
+ private final PaperResultMapper paperResultMapper;
|
|
|
+ private final ExamUserMapper examUserMapper;
|
|
|
|
|
|
public PaperService(PaperMapper paperMapper, PaperQuestionMapper paperQuestionMapper,
|
|
|
QuestionMapper questionMapper, QuestionOptionMapper questionOptionMapper,
|
|
|
- RedisHash redisHash, PaperResultMapper paperResultMapper,
|
|
|
- PaperAnswerMapper paperAnswerMapper, ExamUserMapper examUserMapper) {
|
|
|
+ PaperResultMapper paperResultMapper, ExamUserMapper examUserMapper) {
|
|
|
this.paperMapper = paperMapper;
|
|
|
this.paperQuestionMapper = paperQuestionMapper;
|
|
|
this.questionMapper = questionMapper;
|
|
|
this.questionOptionMapper = questionOptionMapper;
|
|
|
- this.redisHash = redisHash;
|
|
|
this.paperResultMapper = paperResultMapper;
|
|
|
- this.paperAnswerMapper = paperAnswerMapper;
|
|
|
this.examUserMapper = examUserMapper;
|
|
|
}
|
|
|
|
|
|
@@ -187,160 +177,7 @@ public class PaperService {
|
|
|
return questionInfo;
|
|
|
}
|
|
|
|
|
|
- public PaperDetail getPaperDetail(int paperId, int viewType, long userId) {
|
|
|
- long loginUser = UserContext.getUser();
|
|
|
- ExamUser examUser = examUserMapper.findExamUser(paperId, loginUser);
|
|
|
- if (examUser == null) {
|
|
|
- // 用户没有访问试卷的权限
|
|
|
- return new PaperDetail(paperId, 1);
|
|
|
- }
|
|
|
-
|
|
|
- Paper paper = paperMapper.findById(paperId);
|
|
|
- int role = examUser.getRole();
|
|
|
-
|
|
|
- Map<Long, QuestionAnswer> paperAnswers;
|
|
|
- if (viewType == PaperViewType.PaperPreview.getCode()) {
|
|
|
- if (role > 1) {
|
|
|
- // 用户只有做题的权限
|
|
|
- return new PaperDetail(paperId, 3);
|
|
|
- }
|
|
|
-
|
|
|
- paperAnswers = getPaperAnswersFromCorrect(paperId);
|
|
|
- } else if (viewType == PaperViewType.PaperExam.getCode()) {
|
|
|
- if (role == 1) {
|
|
|
- // 用户只有管理的权限
|
|
|
- return new PaperDetail(paperId, 2);
|
|
|
- }
|
|
|
-
|
|
|
- paperAnswers = getPaperAnswersFromCache(paperId, loginUser);
|
|
|
- } else if (viewType == PaperViewType.PaperMark.getCode()) {
|
|
|
- int markType = paper.getMarkType();
|
|
|
- if (markType == 2) {
|
|
|
- // 自己批改
|
|
|
- if (role > 1) {
|
|
|
- // 试卷由用户自己批改
|
|
|
- return new PaperDetail(paperId, 4);
|
|
|
- }
|
|
|
- } else if (markType == 3) {
|
|
|
- // 他人批改
|
|
|
- if (role > 1) {
|
|
|
- // 用户只有做题的权限
|
|
|
- return new PaperDetail(paperId, 3);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // 批改试卷不需要客观题
|
|
|
- paperAnswers = getPaperAnswersFromResult(paperId, loginUser, false);
|
|
|
- } else if (viewType == PaperViewType.PaperResult.getCode()) {
|
|
|
- if (role == 1) {
|
|
|
- // 用户只有管理的权限
|
|
|
- return new PaperDetail(paperId, 2);
|
|
|
- }
|
|
|
-
|
|
|
- paperAnswers = getPaperAnswersFromResult(paperId, loginUser, true);
|
|
|
- } else {
|
|
|
- // 试卷访问类型 viewType 未知
|
|
|
- return new PaperDetail(paperId, 5);
|
|
|
- }
|
|
|
-
|
|
|
- int paperStatus = 6;
|
|
|
- Set<Integer> questionTypes = paperAnswers.values().stream()
|
|
|
- .collect(Collectors.groupingBy(QuestionAnswer::getQuestionType))
|
|
|
- .keySet();
|
|
|
- Map<Integer, List<QuestionInfo>> questionMap = getPaperQuestions(paperId).stream()
|
|
|
- .filter(questionInfo -> {
|
|
|
- int questionType = questionInfo.getQuestionType();
|
|
|
- return questionTypes.contains(questionType);
|
|
|
- })
|
|
|
- .collect(Collectors.groupingBy(QuestionInfo::getQuestionType));
|
|
|
- UserResult userResult = new UserResult(paperId, paperAnswers);
|
|
|
- return new PaperDetail(paper, paperStatus, questionMap, userResult);
|
|
|
- }
|
|
|
-
|
|
|
- public void cacheUserAnswers(UserResult userResult) {
|
|
|
- long loginUser = UserContext.getUser();
|
|
|
- int paperId = userResult.getPaperId();
|
|
|
- String key = String.format("%s:%s:%s", keyPrefix, paperId, loginUser);
|
|
|
-
|
|
|
- List<QuestionAnswer> submitUserAnswers = userResult.getSubmitUserAnswers();
|
|
|
- for (QuestionAnswer userAnswer : submitUserAnswers) {
|
|
|
- long questionId = userAnswer.getQuestionId();
|
|
|
- redisHash.hset(key, ""+questionId, userAnswer);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- private Map<Long, QuestionAnswer> getPaperAnswersFromCache(int paperId, long userId) {
|
|
|
- Map<Long, QuestionAnswer> map = new HashMap<>();
|
|
|
- String key = String.format("%s:%s:%s", keyPrefix, paperId, userId);
|
|
|
- redisHash.hgetall(key).forEach((k, v) -> {
|
|
|
- QuestionAnswer questionAnswer = (QuestionAnswer) v;
|
|
|
- long questionId = questionAnswer.getQuestionId();
|
|
|
- Object[] submitAnswer = questionAnswer.getSubmitAnswer();
|
|
|
- int questionType = questionAnswer.getQuestionType();
|
|
|
- if (questionType == QuestionType.QUESTION1.getCode()) {
|
|
|
- if (submitAnswer[0] instanceof String) {
|
|
|
- Object[] submitAnswer1 = new Object[] {Integer.parseInt((String) submitAnswer[0])};
|
|
|
- questionAnswer.setSubmitAnswer(submitAnswer1);
|
|
|
- }
|
|
|
- }
|
|
|
- map.put(questionId, questionAnswer);
|
|
|
- });
|
|
|
- if (!map.isEmpty()) {
|
|
|
- return map;
|
|
|
- }
|
|
|
-
|
|
|
- return getEmptyPaperAnswers(paperId);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 获取空白的试卷答案
|
|
|
- *
|
|
|
- * @param
|
|
|
- * @return
|
|
|
- * @date 2025-08-10 18:08:71
|
|
|
- */
|
|
|
- private Map<Long, QuestionAnswer> getEmptyPaperAnswers(int paperId) {
|
|
|
- Map<Long, QuestionAnswer> map = new HashMap<>();
|
|
|
- List<QuestionInfo> questions = getPaperQuestions(paperId);
|
|
|
- for (QuestionInfo questionInfo : questions) {
|
|
|
- QuestionAnswer questionAnswer = new QuestionAnswer(questionInfo);
|
|
|
- long questionId = questionInfo.getQuestionId();
|
|
|
- int type = questionInfo.getQuestionType();
|
|
|
- List<QuestionOption> questionOptionList = questionOptionMapper.findByQuestionId(questionId);
|
|
|
- long count = questionOptionList.stream().filter(QuestionOption::getCorrect).count();
|
|
|
- List<Object> list = new ArrayList<>();
|
|
|
- for (int i = 0; i < count; i++) {
|
|
|
- if (type == QuestionType.QUESTION1.getCode() || type == QuestionType.QUESTION3.getCode()) {
|
|
|
- // 单选题和判断题前端使用 radio, 需要 int 类型来表示选中的 radio
|
|
|
- list.add(-1);
|
|
|
- } else if (type == QuestionType.QUESTION2.getCode()) {
|
|
|
- // 多选题前端使用 checkbox, 使用 string[] 来表示选中的 checkbox
|
|
|
- // 空数组表示没有选中
|
|
|
- } else {
|
|
|
- // 填空题和简答题使用空字符串占位
|
|
|
- list.add("");
|
|
|
- }
|
|
|
- questionAnswer.setSubmitAnswer(list.toArray(new Object[0]));
|
|
|
- }
|
|
|
-
|
|
|
- map.putIfAbsent(questionId, questionAnswer);
|
|
|
- }
|
|
|
-
|
|
|
- return map;
|
|
|
- }
|
|
|
-
|
|
|
- private Map<Long, QuestionAnswer> getPaperAnswersFromResult(int paperId, long userId, boolean hasObjective) {
|
|
|
- PaperResult paperResult = getPaperResult(paperId, userId);
|
|
|
- if (paperResult == null) {
|
|
|
- log.error("userId:{} 的试卷 paperId:{} 结果不存在", userId, paperId);
|
|
|
- return getEmptyPaperAnswers(paperId);
|
|
|
- }
|
|
|
-
|
|
|
- int resultId = paperResult.getId();
|
|
|
- return getPaperAnswersFromResult0(paperId, resultId, hasObjective);
|
|
|
- }
|
|
|
-
|
|
|
- private PaperResult getPaperResult(int paperId, long userId) {
|
|
|
+ public PaperResult getPaperResult(int paperId, long userId) {
|
|
|
ExamQuery examQuery = new ExamQuery.Builder()
|
|
|
.loginUser(userId)
|
|
|
.paperId(paperId)
|
|
|
@@ -350,106 +187,6 @@ public class PaperService {
|
|
|
return list.isEmpty() ? null : list.get(0);
|
|
|
}
|
|
|
|
|
|
- private Map<Long, QuestionAnswer> getPaperAnswersFromResult0(int paperId, int resultId, boolean hasObjective) {
|
|
|
- Map<Long, QuestionAnswer> map = new HashMap<>();
|
|
|
- List<PaperAnswer> paperAnswerList = paperAnswerMapper.findByResultId(resultId);
|
|
|
- paperAnswerList.forEach(paperAnswer -> {
|
|
|
- long questionId = paperAnswer.getQuestionId();
|
|
|
- int questionType = paperAnswer.getQuestionType();
|
|
|
- if (questionType <= QuestionType.QUESTION3.getCode() && !hasObjective) {
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- PaperQuestion paperQuestion = paperQuestionMapper.findPaperQuestion(paperId, questionId);
|
|
|
- int correctScore = paperQuestion.getScore();
|
|
|
- QuestionAnswer questionAnswer = new QuestionAnswer(paperAnswer, correctScore);
|
|
|
-
|
|
|
- setSubmitAnswer(paperAnswer, questionAnswer);
|
|
|
- setCorrectAnswer(questionAnswer);
|
|
|
- map.put(questionId, questionAnswer);
|
|
|
- });
|
|
|
-
|
|
|
- return map;
|
|
|
- }
|
|
|
-
|
|
|
- private void setCorrectAnswer(QuestionAnswer questionAnswer) {
|
|
|
- long questionId = questionAnswer.getQuestionId();
|
|
|
- List<QuestionOption> list = questionOptionMapper.findByQuestionId(questionId);
|
|
|
- List<Object> correctAnswers = list.stream()
|
|
|
- .filter(QuestionOption::getCorrect)
|
|
|
- .map(QuestionOption::getContent)
|
|
|
- .collect(Collectors.toList());
|
|
|
- questionAnswer.setCorrectAnswer(correctAnswers.toArray(new Object[0]));
|
|
|
- }
|
|
|
-
|
|
|
- private void setSubmitAnswer(PaperAnswer paperAnswer, QuestionAnswer questionAnswer) {
|
|
|
- int type = paperAnswer.getQuestionType();
|
|
|
- String submitAnswer = paperAnswer.getAnswer();
|
|
|
- List<Object> submitAnswerList;
|
|
|
- if (type == QuestionType.QUESTION1.getCode() || type == QuestionType.QUESTION3.getCode()) {
|
|
|
- // 单选题和判断题前端使用 radio, 需要 int 类型来表示选中的 radio
|
|
|
- submitAnswerList = List.of(Integer.parseInt(submitAnswer));
|
|
|
- } else if (type == QuestionType.QUESTION2.getCode()) {
|
|
|
- // 多选题前端使用 checkbox, 使用 string[] 来表示选中的 checkbox
|
|
|
- String[] answerArr = submitAnswer.split(",");
|
|
|
- submitAnswerList = List.of(answerArr);
|
|
|
- } else if (type == QuestionType.QUESTION4.getCode()) {
|
|
|
- // 填空题
|
|
|
- String[] answerArr = submitAnswer.split(",");
|
|
|
- submitAnswerList = List.of(answerArr);
|
|
|
- } else if (type == QuestionType.QUESTION5.getCode()) {
|
|
|
- // 问答题
|
|
|
- submitAnswerList = List.of(submitAnswer);
|
|
|
- } else if (type == QuestionType.QUESTION6.getCode()) {
|
|
|
- // 组合题
|
|
|
- submitAnswerList = List.of(submitAnswer);
|
|
|
- } else {
|
|
|
- submitAnswerList = List.of(submitAnswer);
|
|
|
- }
|
|
|
- questionAnswer.setSubmitAnswer(submitAnswerList.toArray(new Object[0]));
|
|
|
- }
|
|
|
-
|
|
|
- private Map<Long, QuestionAnswer> getPaperAnswersFromCorrect(int paperId) {
|
|
|
- Map<Long, QuestionAnswer> map = new HashMap<>();
|
|
|
- List<PaperQuestion> paperQuestions = paperQuestionMapper.findByPaperId(paperId);
|
|
|
- Map<Long, PaperQuestion> paperQuestionMap = paperQuestions.stream()
|
|
|
- .collect(Collectors.toMap(PaperQuestion::getQuestionId, k -> k));
|
|
|
- //List<Long> questionIds = paperQuestions.stream().map(PaperQuestion::getQuestionId).collect(Collectors.toList());
|
|
|
- List<Long> questionIds = new ArrayList<>(paperQuestionMap.keySet());
|
|
|
-
|
|
|
- List<Question> questions = questionMapper.findByQuestionIds(questionIds);
|
|
|
- questions.forEach(question -> {
|
|
|
- long questionId = question.getQuestionId();
|
|
|
- int type = question.getType();
|
|
|
- int correctScore = paperQuestionMap.get(questionId).getScore();
|
|
|
- QuestionAnswer questionAnswer = new QuestionAnswer(question, correctScore);
|
|
|
-
|
|
|
- List<QuestionOption> list = questionOptionMapper.findByQuestionId(questionId);
|
|
|
- // 正确答案
|
|
|
- List<Object> correctAnswerList;
|
|
|
- if (type == QuestionType.QUESTION1.getCode() || type == QuestionType.QUESTION3.getCode()) {
|
|
|
- correctAnswerList = list.stream()
|
|
|
- .filter(QuestionOption::getCorrect)
|
|
|
- .map(QuestionOption::getPos)
|
|
|
- .collect(Collectors.toList());
|
|
|
- } else if (type == QuestionType.QUESTION2.getCode()) {
|
|
|
- correctAnswerList = list.stream()
|
|
|
- .filter(QuestionOption::getCorrect)
|
|
|
- .map(QuestionOption::getPos)
|
|
|
- .collect(Collectors.toList());
|
|
|
- } else {
|
|
|
- correctAnswerList = list.stream()
|
|
|
- .filter(QuestionOption::getCorrect)
|
|
|
- .map(QuestionOption::getContent)
|
|
|
- .collect(Collectors.toList());
|
|
|
- }
|
|
|
-
|
|
|
- questionAnswer.setCorrectAnswer(correctAnswerList.toArray(new Object[0]));
|
|
|
- map.put(questionId, questionAnswer);
|
|
|
- });
|
|
|
- return map;
|
|
|
- }
|
|
|
-
|
|
|
public List<KeyValue> getKeyValues() {
|
|
|
PaperQuery paperQuery = new PaperQuery.Builder().pageSize(10).build();
|
|
|
Page page = paperQuery.getPage();
|