Kaynağa Gözat

update content-service exam module

reghao 7 ay önce
ebeveyn
işleme
2b63c151d6
22 değiştirilmiş dosya ile 228 ekleme ve 93 silme
  1. 3 3
      content/content-service/src/main/java/cn/reghao/tnb/content/app/exam/controller/ExamResultController.java
  2. 2 2
      content/content-service/src/main/java/cn/reghao/tnb/content/app/exam/controller/PaperController.java
  3. 18 0
      content/content-service/src/main/java/cn/reghao/tnb/content/app/exam/db/mapper/ExamUserMapper.java
  4. 1 0
      content/content-service/src/main/java/cn/reghao/tnb/content/app/exam/db/mapper/PaperQuestionMapper.java
  5. 1 1
      content/content-service/src/main/java/cn/reghao/tnb/content/app/exam/db/mapper/PaperResultMapper.java
  6. 7 7
      content/content-service/src/main/java/cn/reghao/tnb/content/app/exam/model/constant/PaperViewType.java
  7. 0 23
      content/content-service/src/main/java/cn/reghao/tnb/content/app/exam/model/dto/ExamMarkForm.java
  8. 1 1
      content/content-service/src/main/java/cn/reghao/tnb/content/app/exam/model/dto/PaperAddDto.java
  9. 1 1
      content/content-service/src/main/java/cn/reghao/tnb/content/app/exam/model/dto/UserResult.java
  10. 21 0
      content/content-service/src/main/java/cn/reghao/tnb/content/app/exam/model/po/ExamUser.java
  11. 4 2
      content/content-service/src/main/java/cn/reghao/tnb/content/app/exam/model/po/Paper.java
  12. 4 2
      content/content-service/src/main/java/cn/reghao/tnb/content/app/exam/model/po/PaperQuestion.java
  13. 0 1
      content/content-service/src/main/java/cn/reghao/tnb/content/app/exam/model/query/ExamQuery.java
  14. 12 2
      content/content-service/src/main/java/cn/reghao/tnb/content/app/exam/model/vo/QuestionAnswer.java
  15. 36 10
      content/content-service/src/main/java/cn/reghao/tnb/content/app/exam/service/ExamResultService.java
  16. 5 4
      content/content-service/src/main/java/cn/reghao/tnb/content/app/exam/service/ExamService.java
  17. 73 30
      content/content-service/src/main/java/cn/reghao/tnb/content/app/exam/service/PaperService.java
  18. 30 0
      content/content-service/src/main/resources/mapper/exam/ExamUserMapper.xml
  19. 2 2
      content/content-service/src/main/resources/mapper/exam/PaperMapper.xml
  20. 5 0
      content/content-service/src/main/resources/mapper/exam/PaperQuestionMapper.xml
  21. 1 1
      content/content-service/src/main/resources/mapper/exam/PaperResultMapper.xml
  22. 1 1
      content/content-service/src/test/java/cn/reghao/tnb/content/app/exam/service/ExamTest.java

+ 3 - 3
content/content-service/src/main/java/cn/reghao/tnb/content/app/exam/controller/ExamResultController.java

@@ -2,7 +2,7 @@ package cn.reghao.tnb.content.app.exam.controller;
 
 import cn.reghao.jutil.jdk.db.PageList;
 import cn.reghao.jutil.web.WebResult;
-import cn.reghao.tnb.content.app.exam.model.dto.ExamMarkForm;
+import cn.reghao.tnb.content.app.exam.model.dto.UserResult;
 import cn.reghao.tnb.content.app.exam.model.query.ExamQuery;
 import cn.reghao.tnb.content.app.exam.model.vo.ExamMark;
 import cn.reghao.tnb.content.app.exam.model.vo.ExamResult;
@@ -37,8 +37,8 @@ public class ExamResultController {
 
     @Operation(summary = "提交评卷结果", description = "N")
     @PostMapping(value = "/mark", produces = MediaType.APPLICATION_JSON_VALUE)
-    public String submitExamMark(@RequestBody @Validated ExamMarkForm examMarkForm) {
-        examResultService.markExamResult(examMarkForm);
+    public String submitExamMark(@RequestBody @Validated UserResult userResult) {
+        examResultService.markExamResult(userResult);
         return WebResult.success();
     }
 

+ 2 - 2
content/content-service/src/main/java/cn/reghao/tnb/content/app/exam/controller/PaperController.java

@@ -54,8 +54,8 @@ public class PaperController {
 
     @Operation(summary = "获取试卷详情", description = "N")
     @GetMapping(value = "/{paperId}", produces = MediaType.APPLICATION_JSON_VALUE)
-    public String getPaper(@PathVariable("paperId") Integer paperId, @RequestParam("status") int status) {
-        PaperDetail paperDetail = paperService.getPaperDetail(paperId, status);
+    public String getPaper(@PathVariable("paperId") Integer paperId, @RequestParam("viewType") int viewType) {
+        PaperDetail paperDetail = paperService.getPaperDetail(paperId, viewType);
         if (paperDetail == null) {
             return WebResult.notFound();
         }

+ 18 - 0
content/content-service/src/main/java/cn/reghao/tnb/content/app/exam/db/mapper/ExamUserMapper.java

@@ -0,0 +1,18 @@
+package cn.reghao.tnb.content.app.exam.db.mapper;
+
+import cn.reghao.jutil.jdk.db.BaseMapper;
+import cn.reghao.tnb.content.app.exam.model.po.ExamUser;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * @author reghao
+ * @date 2025-08-10 19:22:51
+ */
+@Mapper
+public interface ExamUserMapper extends BaseMapper<ExamUser> {
+    List<ExamUser> findByPaperId(int paperId);
+    ExamUser findExamUser(@Param("paperId") int paperId, @Param("userId") long userId);
+}

+ 1 - 0
content/content-service/src/main/java/cn/reghao/tnb/content/app/exam/db/mapper/PaperQuestionMapper.java

@@ -15,6 +15,7 @@ import java.util.List;
 public interface PaperQuestionMapper extends BaseMapper<PaperQuestion> {
     void deleteByPaperId(int paperId);
     List<PaperQuestion> findByPaperId(int paperId);
+    PaperQuestion findPaperQuestion(@Param("paperId") int paperId, @Param("questionId") long questionId);
     @Deprecated
     List<PaperQuestion> findByPaperIdAndPid(@Param("paperId") int paperId, @Param("pid") long pid);
 }

+ 1 - 1
content/content-service/src/main/java/cn/reghao/tnb/content/app/exam/db/mapper/PaperResultMapper.java

@@ -16,7 +16,7 @@ import java.util.List;
  */
 @Mapper
 public interface PaperResultMapper extends BaseMapper<PaperResult> {
-    void updateSetResultMarked(int resultId);
+    void updateSetResultMarked(@Param("resultId") int resultId, @Param("subjectiveScore") int subjectiveScore);
 
     List<PaperResult> findByPaperId(int paperId);
     int countByCriteria(ExamQuery examQuery);

+ 7 - 7
content/content-service/src/main/java/cn/reghao/tnb/content/app/exam/model/constant/PaperStatus.java → content/content-service/src/main/java/cn/reghao/tnb/content/app/exam/model/constant/PaperViewType.java

@@ -7,22 +7,22 @@ import java.util.Map;
  * @author reghao
  * @date 2024-09-02 11:19:11
  */
-public enum PaperStatus {
-    PaperPreview(1, "预览状态"),
-    PaperExam(2, "考试状态"),
-    PaperMark(3, "阅卷状态"),
-    PaperResult(4, "结果状态");
+public enum PaperViewType {
+    PaperPreview(1, "试卷预览"),
+    PaperExam(2, "考试预览"),
+    PaperMark(3, "阅卷预览"),
+    PaperResult(4, "结果预览");
 
     private final int code;
     private final String desc;
     private static Map<Integer, String> descMap = new HashMap<>();
     static {
-        for (PaperStatus eNumber : PaperStatus.values()) {
+        for (PaperViewType eNumber : PaperViewType.values()) {
             descMap.put(eNumber.code, eNumber.desc);
         }
     }
 
-    PaperStatus(Integer code, String desc) {
+    PaperViewType(Integer code, String desc) {
         this.code = code;
         this.desc = desc;
     }

+ 0 - 23
content/content-service/src/main/java/cn/reghao/tnb/content/app/exam/model/dto/ExamMarkForm.java

@@ -1,23 +0,0 @@
-package cn.reghao.tnb.content.app.exam.model.dto;
-
-import lombok.Getter;
-import lombok.Setter;
-
-import javax.validation.constraints.NotNull;
-import javax.validation.constraints.Size;
-import java.util.List;
-
-/**
- * @author reghao
- * @date 2024-08-29 14:58:48
- */
-@Setter
-@Getter
-public class ExamMarkForm {
-    @NotNull
-    private Integer paperId;
-    @NotNull
-    private Integer resultId;
-    @Size(min = 1, max = 100, message = "需要批改试题")
-    private List<ExamMarkResult> paperMarks;
-}

+ 1 - 1
content/content-service/src/main/java/cn/reghao/tnb/content/app/exam/model/dto/PaperAddDto.java

@@ -22,7 +22,7 @@ public class PaperAddDto {
     private String examName;
     private String examDesc;
     @Size(min = 1, max = 100, message = "一套试卷中的试题不能超过 100 道")
-    private List<PaperQuestion> questions;
+    private List<PaperQuestion> paperQuestions;
     @NotNull
     private Integer passScore;
     @NotNull

+ 1 - 1
content/content-service/src/main/java/cn/reghao/tnb/content/app/exam/model/dto/UserResult.java

@@ -25,7 +25,7 @@ public class UserResult {
     private Integer paperId;
     private Map<Long, QuestionAnswer> cachedUserAnswers;
     @Size(min = 1, max = 100)
-    private List<QuestionAnswer> userAnswers;
+    private List<QuestionAnswer> submitUserAnswers;
 
     public UserResult(int paperId, Map<Long, QuestionAnswer> questionAnswerMap) {
         this.paperId = paperId;

+ 21 - 0
content/content-service/src/main/java/cn/reghao/tnb/content/app/exam/model/po/ExamUser.java

@@ -0,0 +1,21 @@
+package cn.reghao.tnb.content.app.exam.model.po;
+
+import cn.reghao.jutil.jdk.db.BaseObject;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+/**
+ * @author reghao
+ * @date 2025-08-10 19:22:05
+ */
+@NoArgsConstructor
+@AllArgsConstructor
+@Getter
+@Setter
+public class ExamUser extends BaseObject<Integer> {
+    private Integer paperId;
+    private Long userId;
+    private Integer role;
+}

+ 4 - 2
content/content-service/src/main/java/cn/reghao/tnb/content/app/exam/model/po/Paper.java

@@ -21,6 +21,7 @@ import java.util.List;
 public class Paper extends BaseObject<Integer> {
     private Integer subjectId;
     private String name;
+    private Integer markType;
     private String description;
     private Integer duration;
     private Integer totalScore;
@@ -28,7 +29,7 @@ public class Paper extends BaseObject<Integer> {
     private LocalDateTime startTime;
     private LocalDateTime endTime;
     private String passcode;
-    private Integer status;
+    //private Integer status;
     private Boolean hasSubjective;
     private LocalDateTime createAt;
     private Long createBy;
@@ -37,6 +38,7 @@ public class Paper extends BaseObject<Integer> {
     public Paper(PaperAddDto paperAddDto) {
         this.subjectId = 1;
         this.name = paperAddDto.getExamName();
+        this.markType = 1;
         this.description = paperAddDto.getExamDesc();
         this.duration = paperAddDto.getExamDuration();
         this.totalScore = paperAddDto.getTotalScore();
@@ -44,7 +46,7 @@ public class Paper extends BaseObject<Integer> {
         this.startTime = LocalDateTime.ofInstant(paperAddDto.getStartTime().toInstant(), ZoneId.systemDefault());
         this.endTime = LocalDateTime.ofInstant(paperAddDto.getEndTime().toInstant(), ZoneId.systemDefault());
         this.passcode = paperAddDto.getExamPassword();
-        this.status = 1;
+        //this.status = 1;
         this.hasSubjective = false;
         this.createAt = LocalDateTime.now();
         this.createBy = UserContext.getUser();

+ 4 - 2
content/content-service/src/main/java/cn/reghao/tnb/content/app/exam/model/po/PaperQuestion.java

@@ -24,11 +24,13 @@ public class PaperQuestion extends BaseObject<Integer> {
     private Integer pos;
     @NotNull
     private Long questionId;
+    @NotNull
     private Integer type;
     @NotNull
     private Integer score;
-    //@Size(max = 20)
-    //private transient List<PaperQuestion> children = new ArrayList<>();
+    // 组合题
+    @Size(max = 20)
+    private transient List<PaperQuestion> children = new ArrayList<>();
 
     public PaperQuestion(int pos, Question question, int score) {
         this.questionId = question.getQuestionId();

+ 0 - 1
content/content-service/src/main/java/cn/reghao/tnb/content/app/exam/model/query/ExamQuery.java

@@ -21,7 +21,6 @@ public class ExamQuery {
     public ExamQuery() {
         this.pageNumber = 1;
         this.pageSize = 10;
-        this.marked = false;
     }
 
     private ExamQuery(Builder builder) {

+ 12 - 2
content/content-service/src/main/java/cn/reghao/tnb/content/app/exam/model/vo/QuestionAnswer.java

@@ -30,6 +30,10 @@ public class QuestionAnswer implements Serializable {
     private Object[] submitAnswer = {};
     @Size(min = 1, max = 20)
     private Object[] correctAnswer = {};
+    @NotNull
+    private Integer submitScore;
+    @NotNull
+    private Integer correctScore;
 
     private Long pid = 0L;
 
@@ -37,17 +41,23 @@ public class QuestionAnswer implements Serializable {
         this.questionId = questionInfo.getQuestionId();
         this.questionType = questionInfo.getQuestionType();
         this.pos = questionInfo.getPos();
+        this.submitScore = 0;
+        this.correctScore = questionInfo.getScore();
     }
 
-    public QuestionAnswer(PaperAnswer paperAnswer) {
+    public QuestionAnswer(PaperAnswer paperAnswer, int correctScore) {
         this.questionId = paperAnswer.getQuestionId();
         this.questionType = paperAnswer.getQuestionType();
         this.pos = paperAnswer.getPos();
+        this.submitScore = paperAnswer.getScore();
+        this.correctScore = correctScore;
     }
 
-    public QuestionAnswer(Question question) {
+    public QuestionAnswer(Question question, int correctScore) {
         this.questionId = question.getQuestionId();
         this.questionType = question.getType();
         this.pos = 1;
+        this.submitScore = 0;
+        this.correctScore = correctScore;
     }
 }

+ 36 - 10
content/content-service/src/main/java/cn/reghao/tnb/content/app/exam/service/ExamResultService.java

@@ -4,9 +4,10 @@ import cn.reghao.jutil.jdk.db.Page;
 import cn.reghao.jutil.jdk.db.PageList;
 import cn.reghao.tnb.account.api.dto.AccountInfo;
 import cn.reghao.tnb.account.api.iface.AccountQuery;
+import cn.reghao.tnb.common.auth.UserContext;
 import cn.reghao.tnb.content.app.exam.db.mapper.*;
 import cn.reghao.tnb.content.app.exam.model.constant.QuestionType;
-import cn.reghao.tnb.content.app.exam.model.dto.ExamMarkForm;
+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.vo.*;
@@ -66,15 +67,40 @@ public class ExamResultService {
     }
 
     @Transactional(rollbackFor = Exception.class)
-    public void markExamResult(ExamMarkForm examMarkForm) {
-        int resultId = examMarkForm.getResultId();
-        examMarkForm.getPaperMarks().forEach(examMarkResult -> {
-            long questionId = examMarkResult.getQuestionId();
-            String review = examMarkResult.getReview();
-            int score = examMarkResult.getScore();
-            paperAnswerMapper.updatePaperAnswer(resultId, questionId, review, score);
-        });
-        paperResultMapper.updateSetResultMarked(resultId);
+    public void markExamResult(UserResult userResult) {
+        int paperId = userResult.getPaperId();
+        long loginUser = UserContext.getUser();
+        PaperResult paperResult = getPaperResult(paperId, loginUser);
+        if (paperResult == null) {
+            return;
+        }
+
+        int totalSubjectiveScore = 0;
+        int resultId = paperResult.getId();
+        for (QuestionAnswer questionAnswer : userResult.getSubmitUserAnswers()) {
+            long questionId = questionAnswer.getQuestionId();
+            int questionType = questionAnswer.getQuestionType();
+            if (questionType <= QuestionType.QUESTION3.getCode()) {
+                continue;
+            }
+
+            String review = "";
+            int submitScore = questionAnswer.getSubmitScore();
+            paperAnswerMapper.updatePaperAnswer(resultId, questionId, review, submitScore);
+            totalSubjectiveScore += submitScore;
+        }
+
+        paperResultMapper.updateSetResultMarked(resultId, totalSubjectiveScore);
+    }
+
+    private PaperResult getPaperResult(int paperId, long userId) {
+        ExamQuery examQuery = new ExamQuery.Builder()
+                .loginUser(userId)
+                .paperId(paperId)
+                .build();
+        Page page = examQuery.getPage();
+        List<PaperResult> list = paperResultMapper.findPaperResultByPage(page, examQuery);
+        return list.isEmpty() ? null : list.get(0);
     }
 
     public PageList<ExamScore> getExamScoreList() {

+ 5 - 4
content/content-service/src/main/java/cn/reghao/tnb/content/app/exam/service/ExamService.java

@@ -40,17 +40,18 @@ public class ExamService {
     public int submitExamPaper(UserResult userResult) {
         int paperId = userResult.getPaperId();
         List<PaperQuestion> paperQuestions = paperQuestionMapper.findByPaperId(paperId);
+        // 客观题数量
         Long totalObjectiveQuestions = paperQuestions.stream()
                 .filter(paperQuestion -> {
                     int type = paperQuestion.getType();
-                    return type <= QuestionType.QUESTION5.getCode();
+                    return type <= QuestionType.QUESTION3.getCode();
                 }).count();
 
         Map<Long, Integer> scoreMap = paperQuestions.stream()
                 .collect(Collectors.toMap(PaperQuestion::getQuestionId, PaperQuestion::getScore));
 
         // pid -> List<QuestionAnswer>
-        Map<Long, List<QuestionAnswer>> group = userResult.getUserAnswers().stream()
+        Map<Long, List<QuestionAnswer>> group = userResult.getSubmitUserAnswers().stream()
                 .collect(Collectors.groupingBy(QuestionAnswer::getPid));
         List<PaperAnswer> paperAnswers = new ArrayList<>();
         for (Map.Entry<Long, List<QuestionAnswer>> entry : group.entrySet()) {
@@ -76,7 +77,7 @@ public class ExamService {
 
         boolean marked = totalObjectiveQuestions.intValue() == paperQuestions.size();
         PaperResult paperResult = new PaperResult(paperId, objectiveScore, marked);
-        int resultId = save(paperResult, paperAnswers);
+        int resultId = savePaperResult(paperResult, paperAnswers);
 
         long loginUser = UserContext.getUser();
         String keyPrefix = "tnb:exam:result";
@@ -86,7 +87,7 @@ public class ExamService {
     }
 
     @Transactional(rollbackFor = Exception.class)
-    public int save(PaperResult paperResult, List<PaperAnswer> paperAnswers) {
+    public int savePaperResult(PaperResult paperResult, List<PaperAnswer> paperAnswers) {
         paperResultMapper.save(paperResult);
         int resultId = paperResult.getId();
         paperAnswers.forEach(paperAnswer -> paperAnswer.setResultId(resultId));

+ 73 - 30
content/content-service/src/main/java/cn/reghao/tnb/content/app/exam/service/PaperService.java

@@ -3,11 +3,10 @@ package cn.reghao.tnb.content.app.exam.service;
 import cn.reghao.jutil.jdk.db.Page;
 import cn.reghao.jutil.jdk.db.PageList;
 import cn.reghao.jutil.jdk.result.Result;
-import cn.reghao.jutil.jdk.serializer.JsonConverter;
 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.PaperStatus;
+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;
@@ -16,6 +15,7 @@ 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;
 
@@ -26,6 +26,7 @@ import java.util.stream.Collectors;
  * @author reghao
  * @date 2024-08-27 17:21:01
  */
+@Slf4j
 @Service
 public class PaperService {
     private final PaperMapper paperMapper;
@@ -36,11 +37,12 @@ public class PaperService {
     private String keyPrefix = "tnb:exam:result";
     private PaperResultMapper paperResultMapper;
     private PaperAnswerMapper paperAnswerMapper;
+    private ExamUserMapper examUserMapper;
 
     public PaperService(PaperMapper paperMapper, PaperQuestionMapper paperQuestionMapper,
                         QuestionMapper questionMapper, QuestionOptionMapper questionOptionMapper,
                         RedisHash redisHash, PaperResultMapper paperResultMapper,
-                        PaperAnswerMapper paperAnswerMapper) {
+                        PaperAnswerMapper paperAnswerMapper, ExamUserMapper examUserMapper) {
         this.paperMapper = paperMapper;
         this.paperQuestionMapper = paperQuestionMapper;
         this.questionMapper = questionMapper;
@@ -48,11 +50,12 @@ public class PaperService {
         this.redisHash = redisHash;
         this.paperResultMapper = paperResultMapper;
         this.paperAnswerMapper = paperAnswerMapper;
+        this.examUserMapper = examUserMapper;
     }
 
     public Result createExamPaper(PaperAddDto paperAddDto) {
         Paper paper = new Paper(paperAddDto);
-        List<PaperQuestion> paperQuestions = paperAddDto.getQuestions();
+        List<PaperQuestion> paperQuestions = paperAddDto.getPaperQuestions();
         save(paper, paperQuestions);
         return Result.success();
     }
@@ -65,6 +68,7 @@ public class PaperService {
             paperQuestion.setPaperId(paperId);
         });
 
+        examUserMapper.saveAll(getExamUsers(paperId));
         /*List<PaperQuestion> list1 = list.stream()
                 .map(paperQuestion -> {
                     if (paperQuestion.getChildren().isEmpty()) {
@@ -81,13 +85,24 @@ public class PaperService {
                 .filter(Objects::nonNull)
                 .flatMap(Collection::stream)
                 .collect(Collectors.toList());*/
-
         paperQuestionMapper.saveAll(list);
         /*if (!list1.isEmpty()) {
             paperQuestionMapper.saveAll(list1);
         }*/
     }
 
+    private List<ExamUser> getExamUsers(int paperId) {
+        List<ExamUser> list = new ArrayList<>();
+        long start = 10001L;
+        long total = 100;
+        while (start < start + total) {
+            ExamUser examUser = new ExamUser(paperId, start, 1);
+            list.add(examUser);
+            start++;
+        }
+        return list;
+    }
+
     public Result deleteExamPaper(int paperId) {
         paperMapper.deleteById(paperId);
         return Result.success();
@@ -101,22 +116,21 @@ public class PaperService {
         List<PaperView> list1 = list.stream()
                 .map(paper -> {
                     int paperId = paper.getId();
-                    int paperType = paper.getStatus();
+                    int markType = paper.getMarkType();
                     PaperResult paperResult = getPaperResult(paperId, loginUser);
                     int status;
                     // 1. 试卷未完成
-                    // 2. 试卷已完成, 批改
-                    // 3. 试卷已完成, 自己批改
+                    // 2. 试卷已完成, 自己批改
+                    // 3. 试卷已完成, 他人批改
                     // 4. 试卷已完成, 已批改
                     if (paperResult == null) {
                         status = 1;
                     } else if (paperResult.getMarked()) {
-                        //status = paperResult.getMarked() ? 4 : 2;
                         status = 4;
-                    } else if (paperType == 2) {
-                        status = 3;
-                    } else {
+                    } else if (markType == 2) {
                         status = 2;
+                    } else {
+                        status = 3;
                     }
 
                     return new PaperView(paper, status);
@@ -173,26 +187,35 @@ public class PaperService {
         return questionInfo;
     }
 
-    public PaperDetail getPaperDetail(int paperId, int status) {
+    public PaperDetail getPaperDetail(int paperId, int viewType) {
         long loginUser = UserContext.getUser();
+        ExamUser examUser = examUserMapper.findExamUser(paperId, loginUser);
+        if (examUser == null) {
+            return null;
+        }
+
+        int paperStatus = 1;
+        Paper paper = paperMapper.findById(paperId);
+        int markType = paper.getMarkType();
+        int role = examUser.getRole();
+
         Map<Long, QuestionAnswer> paperAnswers;
-        if (status == PaperStatus.PaperPreview.getCode()) {
-            paperAnswers = getPaperAnswersFromResult(paperId, loginUser);
-        } else if (status == PaperStatus.PaperExam.getCode()) {
+        if (viewType == PaperViewType.PaperPreview.getCode()) {
+            paperAnswers = getPaperAnswersFromCorrect(paperId);
+        } else if (viewType == PaperViewType.PaperExam.getCode()) {
             paperAnswers = getPaperAnswersFromCache(paperId, loginUser);
-        } else if (status == PaperStatus.PaperMark.getCode()) {
+        } else if (viewType == PaperViewType.PaperMark.getCode()) {
             paperAnswers = getPaperAnswersFromResult(paperId, loginUser);
-        } else if (status == PaperStatus.PaperResult.getCode()) {
+        } else if (viewType == PaperViewType.PaperResult.getCode()) {
             paperAnswers = getPaperAnswersFromResult(paperId, loginUser);
         } else {
-            paperAnswers = getPaperAnswersFromResult(paperId, loginUser);
+            paperAnswers = getEmptyPaperAnswers(paperId);
         }
 
-        Paper paper = paperMapper.findById(paperId);
         Map<Integer, List<QuestionInfo>> questionMap = getPaperQuestions(paperId).stream()
                 .collect(Collectors.groupingBy(QuestionInfo::getQuestionType));
         UserResult userResult = new UserResult(paperId, paperAnswers);
-        return new PaperDetail(paper, status, questionMap, userResult);
+        return new PaperDetail(paper, paperStatus, questionMap, userResult);
     }
 
     public void cacheUserAnswers(UserResult userResult) {
@@ -200,8 +223,8 @@ public class PaperService {
         int paperId = userResult.getPaperId();
         String key = String.format("%s:%s:%s", keyPrefix, paperId, loginUser);
 
-        List<QuestionAnswer> userAnswers = userResult.getUserAnswers();
-        for (QuestionAnswer userAnswer : userAnswers) {
+        List<QuestionAnswer> submitUserAnswers = userResult.getSubmitUserAnswers();
+        for (QuestionAnswer userAnswer : submitUserAnswers) {
             long questionId = userAnswer.getQuestionId();
             redisHash.hset(key, ""+questionId, userAnswer);
         }
@@ -227,6 +250,18 @@ public class PaperService {
             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);
@@ -258,11 +293,12 @@ public class PaperService {
     private Map<Long, QuestionAnswer> getPaperAnswersFromResult(int paperId, long userId) {
         PaperResult paperResult = getPaperResult(paperId, userId);
         if (paperResult == null) {
-            return getPaperAnswersFromCorrect(paperId);
+            log.error("userId:{} 的试卷 paperId:{} 结果不存在", userId, paperId);
+            return getEmptyPaperAnswers(paperId);
         }
 
         int resultId = paperResult.getId();
-        return getPaperAnswersFromResult(resultId);
+        return getPaperAnswersFromResult0(paperId, resultId);
     }
 
     private PaperResult getPaperResult(int paperId, long userId) {
@@ -275,12 +311,15 @@ public class PaperService {
         return list.isEmpty() ? null : list.get(0);
     }
 
-    private Map<Long, QuestionAnswer> getPaperAnswersFromResult(int resultId) {
+    private Map<Long, QuestionAnswer> getPaperAnswersFromResult0(int paperId, int resultId) {
         Map<Long, QuestionAnswer> map = new HashMap<>();
         List<PaperAnswer> paperAnswerList = paperAnswerMapper.findByResultId(resultId);
         paperAnswerList.forEach(paperAnswer -> {
-            QuestionAnswer questionAnswer = new QuestionAnswer(paperAnswer);
             long questionId = paperAnswer.getQuestionId();
+            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);
@@ -314,16 +353,20 @@ public class PaperService {
         questionAnswer.setSubmitAnswer(submitAnswerList.toArray(new Object[0]));
     }
 
-    @Deprecated
     private Map<Long, QuestionAnswer> getPaperAnswersFromCorrect(int paperId) {
         Map<Long, QuestionAnswer> map = new HashMap<>();
         List<PaperQuestion> paperQuestions = paperQuestionMapper.findByPaperId(paperId);
-        List<Long> questionIds = paperQuestions.stream().map(PaperQuestion::getQuestionId).collect(Collectors.toList());
+        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 -> {
-            QuestionAnswer questionAnswer = new QuestionAnswer(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);
             // 正确答案

+ 30 - 0
content/content-service/src/main/resources/mapper/exam/ExamUserMapper.xml

@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+
+<mapper namespace="cn.reghao.tnb.content.app.exam.db.mapper.ExamUserMapper">
+    <insert id="save" useGeneratedKeys="true" keyProperty="id">
+        insert into exam_user
+        (`paper_id`,`user_id`,`role`)
+        values
+        (#{paperId},#{userId},#{role})
+    </insert>
+    <insert id="saveAll" useGeneratedKeys="true" keyProperty="id">
+        insert ignore into exam_user
+        (`paper_id`,`user_id`,`role`)
+        values
+        <foreach collection="list" item="item" index="index" separator=",">
+            (#{item.paperId},#{item.userId},#{item.role})
+        </foreach>
+    </insert>
+
+    <select id="findByPaperId" resultType="cn.reghao.tnb.content.app.exam.model.po.ExamUser">
+        select *
+        from exam_user
+        where paper_id=#{paperId}
+    </select>
+    <select id="findExamUser" resultType="cn.reghao.tnb.content.app.exam.model.po.ExamUser">
+        select *
+        from exam_user
+        where paper_id=#{paperId} and user_id=#{userId}
+    </select>
+</mapper>

+ 2 - 2
content/content-service/src/main/resources/mapper/exam/PaperMapper.xml

@@ -4,9 +4,9 @@
 <mapper namespace="cn.reghao.tnb.content.app.exam.db.mapper.PaperMapper">
     <insert id="save" useGeneratedKeys="true" keyProperty="id">
         insert into exam_paper
-        (`subject_id`,`name`,`description`,`duration`,`total_score`,`pass_score`,`start_time`,`end_time`,`passcode`,`status`,`has_subjective`,`create_at`,`create_by`)
+        (`subject_id`,`name`,`mark_type`,`description`,`duration`,`total_score`,`pass_score`,`start_time`,`end_time`,`passcode`,`status`,`has_subjective`,`create_at`,`create_by`)
         values 
-        (#{subjectId},#{name},#{description},#{duration},#{totalScore},#{passScore},#{endTime},#{startTime},#{passcode},#{status},#{hasSubjective},#{createAt},#{createBy})
+        (#{subjectId},#{name},#{markType},#{description},#{duration},#{totalScore},#{passScore},#{endTime},#{startTime},#{passcode},#{status},#{hasSubjective},#{createAt},#{createBy})
     </insert>
 
     <delete id="deleteById">

+ 5 - 0
content/content-service/src/main/resources/mapper/exam/PaperQuestionMapper.xml

@@ -27,6 +27,11 @@
         from exam_paper_question
         where paper_id=#{paperId}
     </select>
+    <select id="findPaperQuestion" resultType="cn.reghao.tnb.content.app.exam.model.po.PaperQuestion">
+        select *
+        from exam_paper_question
+        where paper_id=#{paperId} and question_id=#{questionId}
+    </select>
     <select id="findByPaperIdAndPid" resultType="cn.reghao.tnb.content.app.exam.model.po.PaperQuestion">
         select *
         from exam_paper_question

+ 1 - 1
content/content-service/src/main/resources/mapper/exam/PaperResultMapper.xml

@@ -19,7 +19,7 @@
 
     <update id="updateSetResultMarked">
         update exam_paper_result
-        set update_time=now(),`marked`=1
+        set update_time=now(),`marked`=1,subjective_score=#{subjectiveScore}
         where id=#{resultId}
     </update>
     

+ 1 - 1
content/content-service/src/test/java/cn/reghao/tnb/content/app/exam/service/ExamTest.java

@@ -454,7 +454,7 @@ public class ExamTest {
         paperAddDto.setExamDuration(90);
         paperAddDto.setStartTime(new Date());
         paperAddDto.setEndTime(new Date());
-        paperAddDto.setQuestions(paperQuestions);
+        paperAddDto.setPaperQuestions(paperQuestions);
         paperService.createExamPaper(paperAddDto);
     }