Explorar o código

Merge branch 'dev_v5.0.1' of http://git.qmth.com.cn/examcloud-backend/examcloud-core-oe-admin.git into dev_v5.0.1

xiatian %!s(int64=2) %!d(string=hai) anos
pai
achega
e700fbd901

+ 2 - 1
examcloud-core-oe-admin-api-provider/src/main/java/cn/com/qmth/examcloud/core/oe/admin/api/controller/ExamRecordPaperStructController.java

@@ -35,9 +35,10 @@ public class ExamRecordPaperStructController extends ControllerSupport {
     @GetMapping("/getExamRecordPaperStruct")
     public ExamRecordPaperStructEntity getExamRecordPaperStruct(@RequestParam Long examRecordDataId, @RequestParam(required = false) String fromCache) {
         if (fromCache != null) {
+            // 从临时表中获取 实际的考试记录ID
             examRecordDataId = examRecordDataSyncService.getExamRecordDataIdByCacheId(examRecordDataId);
             if (examRecordDataId == null) {
-                throw new StatusException("1001", "未找到数据");
+                throw new StatusException("1001", "未找到考试记录数据");
             }
         }
         return examRecordPaperStructService.getExamRecordPaperStruct(examRecordDataId);

+ 8 - 9
examcloud-core-oe-admin-service/src/main/java/cn/com/qmth/examcloud/core/oe/admin/service/ExamRecordDataService.java

@@ -15,18 +15,17 @@ import cn.com.qmth.examcloud.support.cache.bean.ExamSettingsCacheBean;
  */
 public interface ExamRecordDataService {
 
-
     /**
      * 创建离线考试记录
-     *
-     * @param fullyObjective
-     * @return
      */
-    ExamRecordDataEntity createOfflineExamRecordData(ExamStudentBean bean,
-                                                     ExamSettingsCacheBean examBean,
-                                                     CourseCacheBean courseBean,
-                                                     String basePaperId,
-                                                     String paperStructId, Boolean fullyObjective);
+    ExamRecordDataEntity createOfflineExamRecordData(
+            ExamStudentBean bean,
+            ExamSettingsCacheBean examBean,
+            CourseCacheBean courseBean,
+            String basePaperId,
+            Boolean fullyObjective,
+            boolean randomPaper,
+            double paperScore);
 
     Long getGetAwaitingAuditCount(Long rootOrgId, Long examId);
 

+ 15 - 6
examcloud-core-oe-admin-service/src/main/java/cn/com/qmth/examcloud/core/oe/admin/service/impl/ExamRecordDataServiceImpl.java

@@ -32,11 +32,14 @@ public class ExamRecordDataServiceImpl implements ExamRecordDataService {
     private ExamRecordDataRepo examRecordDataRepo;
 
     @Override
-    public ExamRecordDataEntity createOfflineExamRecordData(ExamStudentBean examStudent,
-                                                            ExamSettingsCacheBean examBean,
-                                                            CourseCacheBean courseBean,
-                                                            String basePaperId,
-                                                            String paperStructId, Boolean fullyObjective) {
+    public ExamRecordDataEntity createOfflineExamRecordData(
+            ExamStudentBean examStudent,
+            ExamSettingsCacheBean examBean,
+            CourseCacheBean courseBean,
+            String basePaperId,
+            Boolean fullyObjective,
+            boolean randomPaper,
+            double paperScore) {
         ExamRecordDataEntity examRecordDataEntity = new ExamRecordDataEntity();
         examRecordDataEntity.setExamId(examBean.getId());
         examRecordDataEntity.setExamType(ExamType.valueOf(examBean.getExamType()));
@@ -51,10 +54,16 @@ public class ExamRecordDataServiceImpl implements ExamRecordDataService {
 
         examRecordDataEntity.setCourseId(courseBean.getId());
         examRecordDataEntity.setCourseLevel(examStudent.getCourseLevel());
+
+        // 采用千人千卷规则时,ID实际为randomPaperId
         examRecordDataEntity.setBasePaperId(basePaperId);
+        // 是否采用千人千卷规则
+        examRecordDataEntity.setRandomPaper(randomPaper);
+        // 试卷总分
+        examRecordDataEntity.setPaperScore(paperScore);
 
         examRecordDataEntity.setPaperType(examStudent.getPaperType());
-        examRecordDataEntity.setPaperStructId(paperStructId);
+        // examRecordDataEntity.setPaperStructId(paperStructId);
 
         examRecordDataEntity.setInfoCollector(examStudent.getInfoCollector());
         examRecordDataEntity.setStartTime(new Date());

+ 16 - 41
examcloud-core-oe-admin-service/src/main/java/cn/com/qmth/examcloud/core/oe/admin/service/impl/ExamRecordPaperStructServiceImpl.java

@@ -1,7 +1,6 @@
 package cn.com.qmth.examcloud.core.oe.admin.service.impl;
 
 import cn.com.qmth.examcloud.commons.exception.StatusException;
-import cn.com.qmth.examcloud.core.oe.admin.base.Constants;
 import cn.com.qmth.examcloud.core.oe.admin.base.utils.Check;
 import cn.com.qmth.examcloud.core.oe.admin.base.utils.NewQuestionType;
 import cn.com.qmth.examcloud.core.oe.admin.base.utils.Sentence;
@@ -11,12 +10,11 @@ import cn.com.qmth.examcloud.core.oe.admin.dao.entity.ExamRecordDataEntity;
 import cn.com.qmth.examcloud.core.oe.admin.dao.entity.ExamRecordPaperStructEntity;
 import cn.com.qmth.examcloud.core.oe.admin.service.ExamRecordPaperStructService;
 import cn.com.qmth.examcloud.core.oe.admin.service.bean.ExamRecordQuestionsInfo;
-import cn.com.qmth.examcloud.support.cache.CacheHelper;
-import cn.com.qmth.examcloud.support.cache.bean.BasePaperCacheBean;
 import cn.com.qmth.examcloud.web.helpers.GlobalHelper;
 import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.data.mongodb.core.MongoTemplate;
 import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.stereotype.Service;
 
@@ -34,6 +32,8 @@ import java.util.Map;
 @Service("examRecordPaperStructService")
 public class ExamRecordPaperStructServiceImpl implements ExamRecordPaperStructService {
 
+    private static final Logger log = LoggerFactory.getLogger(ExamRecordPaperStructServiceImpl.class);
+
     @Autowired
     private ExamRecordDataRepo examRecordDataRepo;
 
@@ -43,54 +43,28 @@ public class ExamRecordPaperStructServiceImpl implements ExamRecordPaperStructSe
     @Autowired
     private JdbcTemplate jdbcTemplate;
 
-    @Autowired
-    private MongoTemplate mongoTemplate;
-
     @Override
     public ExamRecordPaperStructEntity getExamRecordPaperStruct(Long examRecordDataId) {
         Check.isNull(examRecordDataId, "examRecordDataId不能为空");
-
-        ExamRecordDataEntity examRecordDataEntity = GlobalHelper.getEntity(examRecordDataRepo, examRecordDataId, ExamRecordDataEntity.class);
-        if (examRecordDataEntity == null) {
+        ExamRecordDataEntity examRecordData = GlobalHelper.getEntity(examRecordDataRepo, examRecordDataId, ExamRecordDataEntity.class);
+        if (examRecordData == null) {
             throw new StatusException("400404", "未找到考试记录数据");
         }
 
-        String paperStructId = examRecordDataEntity.getPaperStructId();
-        ExamRecordPaperStructEntity examRecordPaperStruct = null;
+        String paperStructId = examRecordData.getPaperStructId();
         if (StringUtils.isBlank(paperStructId)) {
-            Map<String, Object> paperInfoMap = getPaperInfoFromOeExamQuestion(examRecordDataEntity.getId());
-            String paperId = paperInfoMap.get("paper_id").toString();
-            //从缓存中获取试卷结构
-            BasePaperCacheBean getBasePaperResp = CacheHelper.getBasePaper(paperId);
-
-            examRecordPaperStruct = new ExamRecordPaperStructEntity();
-            examRecordPaperStruct.setDefaultPaper(getBasePaperResp.getDefaultPaper());
-            //保存作答记录
-            List<ExamRecordQuestionsInfo> examRecordQuestionList = encapsulationExamQuestion(examRecordDataEntity);
-            if (examRecordQuestionList.size() > 0) {
-                mongoTemplate.insert(examRecordQuestionList, Constants.EXAM_RECORD_QUESTIONS);
-            }
-            //保存试卷结构
-            examRecordPaperStruct = examRecordPaperStructRepo.save(examRecordPaperStruct);
-            //保存考试记录
-            //经测试,从oe_exam_question中获取的paperId最准确
-            examRecordDataEntity.setBasePaperId(paperId);
-            examRecordDataEntity.setPaperType(paperInfoMap.get("paper_type").toString());
-            examRecordDataEntity.setPaperStructId(examRecordPaperStruct.getId());
-            examRecordDataRepo.save(examRecordDataEntity);
-            return examRecordPaperStruct;
+            log.warn("未找到考试试卷结构!paperStructId is null, basePaperId:{} examType:{} examRecordDataId:{}",
+                    examRecordData.getBasePaperId(), examRecordData.getExamType(), examRecordData.getId());
+            throw new StatusException("400404", "未找到考试试卷结构");
         } else {
-            examRecordPaperStruct = GlobalHelper.getEntity(examRecordPaperStructRepo, paperStructId, ExamRecordPaperStructEntity.class);
-            return examRecordPaperStruct;
+            return GlobalHelper.getEntity(examRecordPaperStructRepo, paperStructId, ExamRecordPaperStructEntity.class);
         }
     }
 
     /**
      * 使用examRecordId查询paperId
-     *
-     * @param examRecordId
-     * @return
      */
+    @Deprecated
     private Map<String, Object> getPaperInfoFromOeExamQuestion(Long examRecordId) {
         String sql = "select paper_id,paper_type from oe_exam_question where exam_record_id = " + examRecordId + " limit 1";
         Map<String, Object> examQuestionMap = jdbcTemplate.queryForMap(sql);
@@ -99,9 +73,8 @@ public class ExamRecordPaperStructServiceImpl implements ExamRecordPaperStructSe
 
     /**
      * 封装ExamQuestion
-     *
-     * @param examRecordDataEntity
      */
+    @Deprecated
     private List<ExamRecordQuestionsInfo> encapsulationExamQuestion(ExamRecordDataEntity examRecordDataEntity) {
         List<ExamRecordQuestionsInfo> examRecordQuestionList = new ArrayList<ExamRecordQuestionsInfo>();
         ExamRecordQuestionsInfo examRecordQuestion = new ExamRecordQuestionsInfo();
@@ -146,16 +119,18 @@ public class ExamRecordPaperStructServiceImpl implements ExamRecordPaperStructSe
         return examRecordQuestionList;
     }
 
+    @Deprecated
     private String selectOldRecordQuestionByExamRecordIdSql(Long examRecordId) {
         return new StringBuilder().append("SELECT ")
                 .append("id,exam_record_id,is_answered,is_multiple,is_nested_question,is_sign,orders,")
                 .append("main_number,sub_number,base_paper_id,paper_id,paper_name,paper_number,paper_type,")
                 .append("parent_question_id,question_id,question_type,score,stu_score,answer,stu_answer,create_at")
-                .append(" FROM ").append(Constants.OE_EXAM_QUESTION)
+                .append(" FROM oe_exam_question")
                 .append(" WHERE exam_record_id = ").append(examRecordId)
                 .append(" ORDER BY orders ASC").toString();
     }
 
+    @Deprecated
     private Float computeStudentScore(NewQuestionType questionType, Float questionScore, String correctAnswer, String studentAnswer) {
         //若为客观题重新计算考生试题得分
         if (questionType == null || !questionType.isObjective()) {

+ 31 - 4
examcloud-core-oe-admin-service/src/main/java/cn/com/qmth/examcloud/core/oe/admin/service/impl/OfflineExamServiceImpl.java

@@ -1,6 +1,7 @@
 package cn.com.qmth.examcloud.core.oe.admin.service.impl;
 
 import cn.com.qmth.examcloud.api.commons.enums.AdminOperateType;
+import cn.com.qmth.examcloud.api.commons.enums.CallType;
 import cn.com.qmth.examcloud.api.commons.enums.ExamSpecialSettingsType;
 import cn.com.qmth.examcloud.api.commons.enums.ExamType;
 import cn.com.qmth.examcloud.commons.exception.StatusException;
@@ -23,6 +24,8 @@ import cn.com.qmth.examcloud.core.oe.admin.service.bean.uploadfile.FileInfo;
 import cn.com.qmth.examcloud.core.questions.api.ExtractConfigCloudService;
 import cn.com.qmth.examcloud.core.questions.api.request.GetPaperReq;
 import cn.com.qmth.examcloud.core.questions.api.response.GetPaperResp;
+import cn.com.qmth.examcloud.question.commons.core.paper.DefaultPaper;
+import cn.com.qmth.examcloud.question.commons.core.paper.DefaultQuestionGroup;
 import cn.com.qmth.examcloud.reports.commons.bean.AdminOperateReport;
 import cn.com.qmth.examcloud.reports.commons.util.ReportsUtil;
 import cn.com.qmth.examcloud.support.cache.CacheHelper;
@@ -174,6 +177,16 @@ public class OfflineExamServiceImpl implements OfflineExamService {
         return resultList;
     }
 
+    private double parsePaperScore(DefaultPaper defaultPaper) {
+        double paperScore = 0d;
+        if (org.apache.commons.collections.CollectionUtils.isNotEmpty(defaultPaper.getQuestionGroupList())) {
+            for (DefaultQuestionGroup group : defaultPaper.getQuestionGroupList()) {
+                paperScore += group.getGroupScore();
+            }
+        }
+        return paperScore;
+    }
+
     @Override
     public void startOfflineExam(Long examStudentId) {
         Check.isNull(examStudentId, "examStudentId不能为空");
@@ -188,33 +201,47 @@ public class OfflineExamServiceImpl implements OfflineExamService {
         if (stuClientLoginLimit.getHasValue()) {
             stuClientLoginLimitBoolean = Boolean.parseBoolean(stuClientLoginLimit.getValue().toString());
         }
+
         if (stuClientLoginLimitBoolean) {
             throw new StatusException("1001", "系统维护中... ...");
         }
+
         List<ExamRecordDataEntity> examRecordList = examRecordDataRepo.findByExamStudentId(examStudentId);
         if (examRecordList != null && examRecordList.size() > 0) {
             throw new StatusException("1002", "已经存在examStudentId=" + examStudentId + "的离线考试记录");
         }
+
         //获取考生信息
         ExamStudentEntity examStudentEntity = examStudentRepo.findByExamStudentId(examStudentId);
         ExamStudentBean bean = of(examStudentEntity);
+
         //检查并获取课程信息
         CourseCacheBean courseBean = checkCourse(bean);
+
         //检查并获取考试信息
         ExamSettingsCacheBean examBean = checkExam(bean);
-        //获取题库试卷结构(由于存在随机抽卷,所以不能缓存 )
+
+        //获取题库试卷结构
         GetPaperReq getPaperReq = new GetPaperReq();
         getPaperReq.setExamId(examStudentEntity.getExamId());
         getPaperReq.setCourseCode(courseBean.getCode());
         getPaperReq.setGroupCode(examStudentEntity.getPaperType());
         GetPaperResp getPaperResp = extractConfigCloudService.getPaper(getPaperReq);
 
+        // 是否采用千人千卷规则 (目前离线考试不支持千卷模式,默认false)
+        boolean randomPaper = CallType.RANDOM_PAPER.name().equals(examBean.getCallType());
+
+        DefaultPaper defaultPaper = getPaperResp.getDefaultPaper();
+        double paperScore = this.parsePaperScore(defaultPaper);
+
         //生成考试记录
-        ExamRecordDataEntity examRecordData = examRecordDataService.createOfflineExamRecordData(bean,
-                examBean, courseBean, getPaperResp.getPaperId(),
-                null, getPaperResp.getDefaultPaper().getFullyObjective());
+        ExamRecordDataEntity examRecordData = examRecordDataService.createOfflineExamRecordData(
+                bean, examBean, courseBean, getPaperResp.getPaperId(), defaultPaper.getFullyObjective(),
+                randomPaper, paperScore);
+
         //生成分数
         examScoreService.createExamScoreWithOffline(examRecordData.getId());
+
         //更新考生
         examStudentRepo.updateExamStudentFinished(examStudentId);
     }