Browse Source

merge from release_v4.1.2

deason 3 năm trước cách đây
mục cha
commit
a9d6637be7
15 tập tin đã thay đổi với 431 bổ sung356 xóa
  1. 5 4
      examcloud-core-oe-admin-api-provider/src/main/java/cn/com/qmth/examcloud/core/oe/admin/api/controller/ExamAuditController.java
  2. 37 37
      examcloud-core-oe-admin-api-provider/src/main/java/cn/com/qmth/examcloud/core/oe/admin/api/controller/ExamRecordController.java
  3. 2 1
      examcloud-core-oe-admin-api-provider/src/main/java/cn/com/qmth/examcloud/core/oe/admin/api/controller/ExamScoreController.java
  4. 3 2
      examcloud-core-oe-admin-api-provider/src/main/java/cn/com/qmth/examcloud/core/oe/admin/api/controller/ExamStudentController.java
  5. 12 7
      examcloud-core-oe-admin-api-provider/src/main/java/cn/com/qmth/examcloud/core/oe/admin/api/provider/SyncExamDataCloudServiceProvider.java
  6. 10 0
      examcloud-core-oe-admin-service/src/main/java/cn/com/qmth/examcloud/core/oe/admin/service/bean/OnHandExamInfo.java
  7. 56 43
      examcloud-core-oe-admin-service/src/main/java/cn/com/qmth/examcloud/core/oe/admin/service/bean/examrecord/ExamRecordInfo.java
  8. 5 3
      examcloud-core-oe-admin-service/src/main/java/cn/com/qmth/examcloud/core/oe/admin/service/bean/exporttask/ExportTask.java
  9. 28 24
      examcloud-core-oe-admin-service/src/main/java/cn/com/qmth/examcloud/core/oe/admin/service/impl/ExamRecordQuestionsServiceImpl.java
  10. 261 231
      examcloud-core-oe-admin-service/src/main/java/cn/com/qmth/examcloud/core/oe/admin/service/impl/ExamRecordServiceImpl.java
  11. 6 2
      examcloud-core-oe-admin-service/src/main/java/cn/com/qmth/examcloud/core/oe/admin/service/impl/ExamStudentServiceImpl.java
  12. 2 1
      examcloud-core-oe-admin-service/src/main/java/cn/com/qmth/examcloud/core/oe/admin/service/impl/OfflineExamServiceImpl.java
  13. 1 0
      examcloud-core-oe-admin-starter/pom.xml
  14. 2 1
      examcloud-core-oe-admin-starter/src/main/java/cn/com/qmth/examcloud/core/oe/admin/stater/config/SwaggerConfig.java
  15. 1 0
      examcloud-core-oe-admin-starter/src/main/resources/log4j2.xml

+ 5 - 4
examcloud-core-oe-admin-api-provider/src/main/java/cn/com/qmth/examcloud/core/oe/admin/api/controller/ExamAuditController.java

@@ -23,6 +23,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
 
+import cn.com.qmth.examcloud.api.commons.enums.AdminOperateType;
 import cn.com.qmth.examcloud.api.commons.enums.DataRuleType;
 import cn.com.qmth.examcloud.api.commons.security.bean.User;
 import cn.com.qmth.examcloud.commons.exception.StatusException;
@@ -102,7 +103,7 @@ public class ExamAuditController extends ControllerSupport {
         User user = getAccessUser();
         asyncExportService.exportExamAuditList(query, user);
         AsyncExportConcurrentUtil.checkOrStartJob();
-        ReportsUtil.report(new AdminOperateReport(user.getRootOrgId(), user.getUserId(), "监考已审-导出", "导出条件:" + query));
+        ReportsUtil.report(new AdminOperateReport(user.getRootOrgId(), user.getUserId(), AdminOperateType.TYPE13.getDesc(), "导出条件:" + query));
     }
 
     @DataRule(type = {DataRuleType.COURSE,DataRuleType.ORG})
@@ -167,7 +168,7 @@ public class ExamAuditController extends ControllerSupport {
         if (StringUtils.isNotEmpty(disciplineDetail)) {
             sb.append(" 详情描述:" + disciplineDetail);
         }
-        ReportsUtil.report(new AdminOperateReport(user.getRootOrgId(), user.getUserId(), "监考待审-审核", sb.toString()));
+        ReportsUtil.report(new AdminOperateReport(user.getRootOrgId(), user.getUserId(), AdminOperateType.TYPE14.getDesc(), sb.toString()));
     }
 
     @PostMapping(value = "/batch/audit")
@@ -194,7 +195,7 @@ public class ExamAuditController extends ControllerSupport {
             sb.append("审核状态:不通过");
         }
         sb.append(" 审核条数:" + examRecordDataIds.size());
-        ReportsUtil.report(new AdminOperateReport(user.getRootOrgId(), user.getUserId(), "监考待审-批量审核", sb.toString()));
+        ReportsUtil.report(new AdminOperateReport(user.getRootOrgId(), user.getUserId(), AdminOperateType.TYPE15.getDesc(), sb.toString()));
     }
 
     @PostMapping(value = "/redoAudit")
@@ -246,7 +247,7 @@ public class ExamAuditController extends ControllerSupport {
         if (StringUtils.isNotEmpty(redoAuditInfo.getDisciplineDetail())) {
             sb.append(" 详情描述:" + redoAuditInfo.getDisciplineDetail());
         }
-        ReportsUtil.report(new AdminOperateReport(user.getRootOrgId(), user.getUserId(), "考试明细-重审", sb.toString()));
+        ReportsUtil.report(new AdminOperateReport(user.getRootOrgId(), user.getUserId(), AdminOperateType.TYPE16.getDesc(), sb.toString()));
     }
 
 }

+ 37 - 37
examcloud-core-oe-admin-api-provider/src/main/java/cn/com/qmth/examcloud/core/oe/admin/api/controller/ExamRecordController.java

@@ -7,6 +7,7 @@
 
 package cn.com.qmth.examcloud.core.oe.admin.api.controller;
 
+import cn.com.qmth.examcloud.api.commons.enums.AdminOperateType;
 import cn.com.qmth.examcloud.api.commons.enums.DataRuleType;
 import cn.com.qmth.examcloud.api.commons.enums.ExamType;
 import cn.com.qmth.examcloud.api.commons.security.bean.User;
@@ -70,18 +71,17 @@ public class ExamRecordController extends ControllerSupport {
 
     @Autowired
     private ExamRecordFileAnswerRepo examRecordFileAnswerRepo;
-    
+
     @Autowired
     private ExamProcessRecordService examProcessRecordService;
-    
-    
 
-    @DataRule(type = {DataRuleType.COURSE,DataRuleType.ORG})
+
+    @DataRule(type = {DataRuleType.COURSE, DataRuleType.ORG})
     @PostMapping("/waiting/audit/list")
     @ApiOperation(value = "查询“监考待审”列表(分页)")
     public Page<ExamRecordInfo> getExamRecordWaitingAuditList(@RequestBody ExamRecordQuery query) {
-    	UserDataRules uds=new UserDataRules(getUserDataRule(DataRuleType.ORG), getUserDataRule(DataRuleType.COURSE));
-        Page<ExamRecordInfo> examRecordWaitingAuditList = examRecordService.getExamRecordWaitingAuditList(uds,query);
+        UserDataRules uds = new UserDataRules(getUserDataRule(DataRuleType.ORG), getUserDataRule(DataRuleType.COURSE));
+        Page<ExamRecordInfo> examRecordWaitingAuditList = examRecordService.getExamRecordWaitingAuditList(uds, query);
         examRecordWaitingAuditList.getContent().forEach(p -> {
             p.setIdentityNumber(IdentityNumberHelper.conceal(p.getRootOrgId(), p.getIdentityNumber()));
         });
@@ -100,29 +100,29 @@ public class ExamRecordController extends ControllerSupport {
         return examRecordWaitingAuditList;
     }
 
-    @DataRule(type = {DataRuleType.COURSE,DataRuleType.ORG})
+    @DataRule(type = {DataRuleType.COURSE, DataRuleType.ORG})
     @PostMapping("/waiting/audit/next")
     @ApiOperation(value = "查询“监考待审”下一条记录")
     public Long getExamRecordWaitingAuditNextId(@RequestBody ExamRecordQuery query,
                                                 @RequestParam Long examRecordDataId, String next) {
-    	UserDataRules uds=new UserDataRules(getUserDataRule(DataRuleType.ORG), getUserDataRule(DataRuleType.COURSE));
-        return examRecordService.getExamRecordWaitingAuditNextId(uds,query, examRecordDataId, next);
+        UserDataRules uds = new UserDataRules(getUserDataRule(DataRuleType.ORG), getUserDataRule(DataRuleType.COURSE));
+        return examRecordService.getExamRecordWaitingAuditNextId(uds, query, examRecordDataId, next);
     }
 
-    @DataRule(type = {DataRuleType.COURSE,DataRuleType.ORG})
+    @DataRule(type = {DataRuleType.COURSE, DataRuleType.ORG})
     @PostMapping("/detail/check")
     @ApiOperation(value = "查询“考试明细” 是否存在待审数据")
     public Long existsWarnExamRecordDetail(@RequestBody ExamRecordQuery query) {
-    	UserDataRules uds=new UserDataRules(getUserDataRule(DataRuleType.ORG), getUserDataRule(DataRuleType.COURSE));
-        return examRecordService.existsWarnExamRecordDetail(uds,query);
+        UserDataRules uds = new UserDataRules(getUserDataRule(DataRuleType.ORG), getUserDataRule(DataRuleType.COURSE));
+        return examRecordService.existsWarnExamRecordDetail(uds, query);
     }
 
-    @DataRule(type = {DataRuleType.COURSE,DataRuleType.ORG})
+    @DataRule(type = {DataRuleType.COURSE, DataRuleType.ORG})
     @PostMapping("/detail/list")
     @ApiOperation(value = "查询“考试明细”列表(分页)")
     public Page<ExamRecordInfo> getExamRecordDetailList(@RequestBody ExamRecordQuery query) {
-    	UserDataRules uds=new UserDataRules(getUserDataRule(DataRuleType.ORG), getUserDataRule(DataRuleType.COURSE));
-        Page<ExamRecordInfo> examRecordInfoPage = examRecordService.getExamRecordDetailListForPage(uds,query);
+        UserDataRules uds = new UserDataRules(getUserDataRule(DataRuleType.ORG), getUserDataRule(DataRuleType.COURSE));
+        Page<ExamRecordInfo> examRecordInfoPage = examRecordService.getExamRecordDetailListForPage(uds, query);
         List<ExamRecordInfo> examRecordInfoList = examRecordInfoPage.getContent();
         if (examRecordInfoList != null && examRecordInfoList.size() > 0) {
             String examType = examRecordInfoList.get(0).getExamType();
@@ -166,27 +166,27 @@ public class ExamRecordController extends ControllerSupport {
         return resultList;
     }
 
-//    @Naked
-//    @GetMapping("/detail/list/export")
-//    @ApiOperation(value = "导出“考试明细”列表(Excel)", notes = "参数示例:query={\"pageNo\":1,\"pageSize\":10,\"examId\":123, ...}")
-//    public void exportExamRecordDetailList(@RequestParam String query, HttpServletResponse response) throws Exception {
-//        ExamRecordQuery newQuery = new JsonMapper().parseJson(query, ExamRecordQuery.class);
-//        Check.isNull(newQuery, "请求参数不能为空!");
-//        Check.isNull(newQuery.getExamId(), "请先选择考试批次!");
-//
-//        List<ExamRecordInfo> examRecordInfoList = examRecordService.getExamRecordDetailList(newQuery);
-//        if (examRecordInfoList != null && examRecordInfoList.size() > 0) {
-//            String examType = examRecordInfoList.get(0).getExamType();
-//
-//            for (ExamRecordInfo examRecordInfo : examRecordInfoList) {
-//                if (ExamType.ONLINE.name().equals(examType) || ExamType.ONLINE_HOMEWORK.name().equals(examType)) {
-//                    examRecordInfo.setVirtualCameraNames(examCaptureService.getVirtualCameraNames(examRecordInfo.getDataId()));
-//                }
-//            }
-//        }
-//
-//        ExportUtils.exportEXCEL("考试明细列表", ExamRecordInfo.class, examRecordInfoList, response);
-//    }
+    //    @Naked
+    //    @GetMapping("/detail/list/export")
+    //    @ApiOperation(value = "导出“考试明细”列表(Excel)", notes = "参数示例:query={\"pageNo\":1,\"pageSize\":10,\"examId\":123, ...}")
+    //    public void exportExamRecordDetailList(@RequestParam String query, HttpServletResponse response) throws Exception {
+    //        ExamRecordQuery newQuery = new JsonMapper().parseJson(query, ExamRecordQuery.class);
+    //        Check.isNull(newQuery, "请求参数不能为空!");
+    //        Check.isNull(newQuery.getExamId(), "请先选择考试批次!");
+    //
+    //        List<ExamRecordInfo> examRecordInfoList = examRecordService.getExamRecordDetailList(newQuery);
+    //        if (examRecordInfoList != null && examRecordInfoList.size() > 0) {
+    //            String examType = examRecordInfoList.get(0).getExamType();
+    //
+    //            for (ExamRecordInfo examRecordInfo : examRecordInfoList) {
+    //                if (ExamType.ONLINE.name().equals(examType) || ExamType.ONLINE_HOMEWORK.name().equals(examType)) {
+    //                    examRecordInfo.setVirtualCameraNames(examCaptureService.getVirtualCameraNames(examRecordInfo.getDataId()));
+    //                }
+    //            }
+    //        }
+    //
+    //        ExportUtils.exportEXCEL("考试明细列表", ExamRecordInfo.class, examRecordInfoList, response);
+    //    }
 
     @GetMapping("/detail/list/export/async")
     @ApiOperation(value = "导出“考试明细”列表(异步)", notes = "参数示例:query={\"rootOrgId\":0,\"examId\":1}")
@@ -194,7 +194,7 @@ public class ExamRecordController extends ControllerSupport {
         User user = getAccessUser();
         asyncExportService.exportExamRecordDetails(query, user);
         AsyncExportConcurrentUtil.checkOrStartJob();
-        ReportsUtil.report(new AdminOperateReport(user.getRootOrgId(), user.getUserId(), "考试明细-导出", "导出条件:" + query));
+        ReportsUtil.report(new AdminOperateReport(user.getRootOrgId(), user.getUserId(), AdminOperateType.TYPE17.getDesc(), "导出条件:" + query));
     }
 
     @PostMapping(value = "/refresh/capture/statistic")

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

@@ -1,5 +1,6 @@
 package cn.com.qmth.examcloud.core.oe.admin.api.controller;
 
+import cn.com.qmth.examcloud.api.commons.enums.AdminOperateType;
 import cn.com.qmth.examcloud.api.commons.enums.DataRuleType;
 import cn.com.qmth.examcloud.api.commons.security.bean.User;
 import cn.com.qmth.examcloud.core.oe.admin.service.AsyncExportService;
@@ -70,7 +71,7 @@ public class ExamScoreController extends ControllerSupport {
         User user = getAccessUser();
         asyncExportService.exportExamScoreStatistics(query, user);
         AsyncExportConcurrentUtil.checkOrStartJob();
-        ReportsUtil.report(new AdminOperateReport(user.getRootOrgId(), user.getUserId(), "成绩统计-导出", "导出条件:" + query));
+        ReportsUtil.report(new AdminOperateReport(user.getRootOrgId(), user.getUserId(), AdminOperateType.TYPE18.getDesc(), "导出条件:" + query));
     }
 
     @ApiOperation(value = "根据examStudentId获取客观分信息")

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

@@ -26,6 +26,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
 
+import cn.com.qmth.examcloud.api.commons.enums.AdminOperateType;
 import cn.com.qmth.examcloud.api.commons.enums.DataRuleType;
 import cn.com.qmth.examcloud.api.commons.security.bean.User;
 import cn.com.qmth.examcloud.api.commons.security.bean.UserDataRule;
@@ -141,7 +142,7 @@ public class ExamStudentController extends ControllerSupport {
         User user = getAccessUser();
         asyncExportService.exportExamScheduling(query, user);
         AsyncExportConcurrentUtil.checkOrStartJob();
-        ReportsUtil.report(new AdminOperateReport(user.getRootOrgId(), user.getUserId(), "考试进度详情-导出", "导出条件:" + query));
+        ReportsUtil.report(new AdminOperateReport(user.getRootOrgId(), user.getUserId(), AdminOperateType.TYPE19.getDesc(), "导出条件:" + query));
     }
 
     @DataRule(type = {DataRuleType.COURSE,DataRuleType.ORG})
@@ -208,7 +209,7 @@ public class ExamStudentController extends ControllerSupport {
         if (StringUtils.isNotEmpty(reexamineDetail)) {
             sb.append(" 详情描述:" + reexamineDetail);
         }
-        ReportsUtil.report(new AdminOperateReport(user.getRootOrgId(), user.getUserId(), "设置重考-设置重考", sb.toString()));
+        ReportsUtil.report(new AdminOperateReport(user.getRootOrgId(), user.getUserId(), AdminOperateType.TYPE20.getDesc(), sb.toString()));
     }
 
     @PostMapping("/statistic/by/finished")

+ 12 - 7
examcloud-core-oe-admin-api-provider/src/main/java/cn/com/qmth/examcloud/core/oe/admin/api/provider/SyncExamDataCloudServiceProvider.java

@@ -751,10 +751,10 @@ public class SyncExamDataCloudServiceProvider extends ControllerSupport implemen
         		JSONObject jsonObject = (JSONObject) jsonArray.get(i);
         		ExamCaptureCameraInfoEntity ci=new ExamCaptureCameraInfoEntity();
         		ci.setExamRecordDataId(examCaptureEntity.getExamRecordDataId());
-        		ci.setDetail(getVal(jsonObject, "detail"));
-        		ci.setName(getVal(jsonObject, "name"));
-        		ci.setPid(getVal(jsonObject, "pid"));
-        		ci.setVid(getVal(jsonObject, "vid"));
+        		ci.setDetail(getVal(jsonObject, "detail",500));
+        		ci.setName(getVal(jsonObject, "name",100));
+        		ci.setPid(getVal(jsonObject, "pid",100));
+        		ci.setVid(getVal(jsonObject, "vid",100));
         		if (jsonObject.isNull("pid") || StringUtils.isBlank(jsonObject.getString("pid"))
         				||jsonObject.isNull("vid") || StringUtils.isBlank(jsonObject.getString("vid"))) {
         			ci.setVirtualCamera(true);
@@ -777,14 +777,19 @@ public class SyncExamDataCloudServiceProvider extends ControllerSupport implemen
         }
     }
     
-    private String getVal(JSONObject jsonObject,String name) throws JSONException {
+    private String getVal(JSONObject jsonObject,String name,int length) throws JSONException {
     	if (jsonObject.isNull(name) || StringUtils.isBlank(jsonObject.getString(name))) {
     		return "";
     	}else {
-    		return jsonObject.getString(name);
+    		String content=jsonObject.getString(name);
+    		if(content.length()>length) {
+    			return content.substring(0, length);
+    		}else {
+    			return content;
+    		}
     	}
     }
-
+    
     private ExamCaptureEntity copyExamCaptureFrom(ExamCaptureBean examCapture, Long examRecordDataId) {
         ExamCaptureEntity entity = new ExamCaptureEntity();
         entity.setExamRecordDataId(examRecordDataId);

+ 10 - 0
examcloud-core-oe-admin-service/src/main/java/cn/com/qmth/examcloud/core/oe/admin/service/bean/OnHandExamInfo.java

@@ -18,6 +18,8 @@ public class OnHandExamInfo implements JsonSerializable {
 
     private String examName;//批次名称
 
+    private String examType;//考试类型
+
     private String studentName;//考生名称
 
     private String studentCode;//考生学号
@@ -255,6 +257,14 @@ public class OnHandExamInfo implements JsonSerializable {
         this.examName = examName;
     }
 
+    public String getExamType() {
+        return examType;
+    }
+
+    public void setExamType(String examType) {
+        this.examType = examType;
+    }
+
     public Long getOrgId() {
         return orgId;
     }

+ 56 - 43
examcloud-core-oe-admin-service/src/main/java/cn/com/qmth/examcloud/core/oe/admin/service/bean/examrecord/ExamRecordInfo.java

@@ -190,6 +190,11 @@ public class ExamRecordInfo implements JsonSerializable {
      */
     private Boolean isAudit;
 
+    /**
+     * 是否显示重审按钮
+     */
+    private Boolean showReAudit;
+
     /**
      * 是否违纪
      */
@@ -355,22 +360,22 @@ public class ExamRecordInfo implements JsonSerializable {
     private String auditUserName;
 
     private Boolean hasVirtual;
-    
+
     @ExcelProperty(name = "切屏次数", width = 30, index = 34)
     private Integer switchScreenCount;
-    
+
     @ExcelProperty(name = "场次", width = 30, index = 35)
     private String examStage;
-    
+
     private Long examStageId;
-    
+
     private Integer examStageOrder;
-    
+
     /**
      * 场次开始时间
      */
     private Date stageStartTime;
-    
+
     /**
      * 场次结束时间
      */
@@ -776,6 +781,14 @@ public class ExamRecordInfo implements JsonSerializable {
         this.isAudit = isAudit;
     }
 
+    public Boolean getShowReAudit() {
+        return showReAudit;
+    }
+
+    public void setShowReAudit(Boolean showReAudit) {
+        this.showReAudit = showReAudit;
+    }
+
     public Boolean getIsReexamine() {
         return isReexamine;
     }
@@ -874,53 +887,53 @@ public class ExamRecordInfo implements JsonSerializable {
         this.hasVirtual = hasVirtual;
     }
 
-	public Integer getSwitchScreenCount() {
-		return switchScreenCount;
-	}
+    public Integer getSwitchScreenCount() {
+        return switchScreenCount;
+    }
 
-	public void setSwitchScreenCount(Integer switchScreenCount) {
-		this.switchScreenCount = switchScreenCount;
-	}
+    public void setSwitchScreenCount(Integer switchScreenCount) {
+        this.switchScreenCount = switchScreenCount;
+    }
 
-	public Integer getExamStageOrder() {
-		return examStageOrder;
-	}
+    public Integer getExamStageOrder() {
+        return examStageOrder;
+    }
 
-	public void setExamStageOrder(Integer examStageOrder) {
-		this.examStageOrder = examStageOrder;
-	}
+    public void setExamStageOrder(Integer examStageOrder) {
+        this.examStageOrder = examStageOrder;
+    }
 
-	public String getExamStage() {
-		return examStage;
-	}
+    public String getExamStage() {
+        return examStage;
+    }
 
-	public void setExamStage(String examStage) {
-		this.examStage = examStage;
-	}
+    public void setExamStage(String examStage) {
+        this.examStage = examStage;
+    }
 
-	public Long getExamStageId() {
-		return examStageId;
-	}
+    public Long getExamStageId() {
+        return examStageId;
+    }
 
-	public void setExamStageId(Long examStageId) {
-		this.examStageId = examStageId;
-	}
+    public void setExamStageId(Long examStageId) {
+        this.examStageId = examStageId;
+    }
+
+    public Date getStageStartTime() {
+        return stageStartTime;
+    }
 
-	public Date getStageStartTime() {
-		return stageStartTime;
-	}
+    public void setStageStartTime(Date stageStartTime) {
+        this.stageStartTime = stageStartTime;
+    }
 
-	public void setStageStartTime(Date stageStartTime) {
-		this.stageStartTime = stageStartTime;
-	}
+    public Date getStageEndTime() {
+        return stageEndTime;
+    }
 
-	public Date getStageEndTime() {
-		return stageEndTime;
-	}
+    public void setStageEndTime(Date stageEndTime) {
+        this.stageEndTime = stageEndTime;
+    }
 
-	public void setStageEndTime(Date stageEndTime) {
-		this.stageEndTime = stageEndTime;
-	}
 
-    
 }

+ 5 - 3
examcloud-core-oe-admin-service/src/main/java/cn/com/qmth/examcloud/core/oe/admin/service/bean/exporttask/ExportTask.java

@@ -31,7 +31,6 @@ public class ExportTask extends Thread {
     public void run() {
         for (; ; ) {
             try {
-                log.info("ExportTask start");
                 ExportTaskEntity et = exportTaskService.findExportTaskToDispose();
                 if (et == null) {
                     log.info("ExportTask sleep 30s");
@@ -42,7 +41,8 @@ public class ExportTask extends Thread {
                 String cacheLock = "$_CACHE_LOCK:OE_EXPORT_TASK:" + et.getId();
                 Boolean lock = redisClient.setIfAbsent(cacheLock, cacheLock, cacheLockTimeout);
                 if (!lock) {
-                    log.info("ExportTask lock... " + cacheLock);
+                    log.warn("ExportTask lock... " + cacheLock);
+                    Util.sleep(10);
                     continue;
                 }
 
@@ -61,9 +61,11 @@ public class ExportTask extends Thread {
                 } finally {
                     redisClient.delete(cacheLock);
                 }
-                log.info("ExportTask end");
+
+                log.info("ExportTask end, taskId = {}", et.getId());
             } catch (Exception e) {
                 log.error("ExportTask error " + e.getMessage(), e);
+                Util.sleep(30);
             }
         }
     }

+ 28 - 24
examcloud-core-oe-admin-service/src/main/java/cn/com/qmth/examcloud/core/oe/admin/service/impl/ExamRecordQuestionsServiceImpl.java

@@ -52,17 +52,8 @@ public class ExamRecordQuestionsServiceImpl implements ExamRecordQuestionsServic
 
     @Override
     public List<ExamQuestionEntity> querySubjectiveAnswerList(Long examRecordDataId) {
-        ExamRecordDataEntity examRecordData = GlobalHelper.getEntity(examRecordDataRepo, examRecordDataId, ExamRecordDataEntity.class);
-
-        ExamRecordQuestionsEntity examRecordQuestionsEntity;
-        if (StringUtils.isNotEmpty(examRecordData.getExamRecordQuestionsId())) {
-            examRecordQuestionsEntity = GlobalHelper.getEntity(examRecordQuestionsRepo, examRecordData.getExamRecordQuestionsId(), ExamRecordQuestionsEntity.class);
-        } else {
-            examRecordQuestionsEntity = getExamRecordQuestionsAndFixExamRecordDataIfNecessary(examRecordData);
-        }
-
+        ExamRecordQuestionsEntity examRecordQuestionsEntity = getExamRecordQuestionsAndFixExamRecordDataIfNecessary(examRecordDataId);
         List<ExamQuestionEntity> examRecordQuestionList = examRecordQuestionsEntity.getExamQuestionEntities();
-
         return examRecordQuestionList.stream().filter((obj -> {
             return !QuestionTypeUtil.isObjectiveQuestion(obj.getQuestionType());
         })).collect(Collectors.toList());
@@ -71,11 +62,11 @@ public class ExamRecordQuestionsServiceImpl implements ExamRecordQuestionsServic
     @Override
     public void saveSubjectiveQuestionScore(Long examRecordDataId, List<SubjectiveQuestionScoreInfo> subjectiveQuestionScoreInfoList) {
         ExamRecordDataEntity examRecordData = GlobalHelper.getEntity(examRecordDataRepo, examRecordDataId, ExamRecordDataEntity.class);
+
         if (ExamType.ONLINE == examRecordData.getExamType() || ExamType.ONLINE_HOMEWORK == examRecordData.getExamType()) {
-            ExamRecordQuestionsEntity examRecordQuestionsEntity =
-                    getExamRecordQuestionsAndFixExamRecordDataIfNecessary(examRecordDataId);
-            List<ExamQuestionEntity> examRecordQuestionList = examRecordQuestionsEntity.getExamQuestionEntities();
+            ExamRecordQuestionsEntity examRecordQuestionsEntity = getExamRecordQuestionsAndFixExamRecordDataIfNecessary(examRecordData);
 
+            List<ExamQuestionEntity> examRecordQuestionList = examRecordQuestionsEntity.getExamQuestionEntities();
             for (SubjectiveQuestionScoreInfo scoreInfo : subjectiveQuestionScoreInfoList) {
                 for (ExamQuestionEntity examQuestionEntity : examRecordQuestionList) {
                     if (scoreInfo.getQuestionId().equals(examQuestionEntity.getQuestionId())
@@ -85,8 +76,10 @@ public class ExamRecordQuestionsServiceImpl implements ExamRecordQuestionsServic
                     }
                 }
             }
+
             examRecordQuestionsRepo.save(examRecordQuestionsEntity);
         }
+
         //计算主观题总得分
         double totalSubjectiveScore = 0D;
         for (SubjectiveQuestionScoreInfo scoreInfo : subjectiveQuestionScoreInfoList) {
@@ -171,29 +164,40 @@ public class ExamRecordQuestionsServiceImpl implements ExamRecordQuestionsServic
         if (examRecordData == null) {
             throw new StatusException("201101", "examRecordData参数不允许为空");
         }
+
         Long examRecordDataId = examRecordData.getId();
         String examRecordQuestionId = examRecordData.getExamRecordQuestionsId();
 
-        //如果考试作答记录id不为空,则根据id查询考试作答记录
+        ExamRecordQuestionsEntity examRecordQuestions;
         if (StringUtils.isNotEmpty(examRecordQuestionId)) {
-            return GlobalHelper.getEntity(examRecordQuestionsRepo, examRecordQuestionId,
-                    ExamRecordQuestionsEntity.class);
-        }
-        //如果考试作答记录id为空,则根据考试记录id获取考试作答记录,并将考试作答记录id保存至examRecordData表中
-        else {
-            ExamRecordQuestionsEntity examRecordQuestionsEntity = examRecordQuestionsRepo.findByExamRecordDataId(examRecordDataId);
+            //如果考试作答记录id不为空,则根据id查询考试作答记录
+            examRecordQuestions = GlobalHelper.getEntity(examRecordQuestionsRepo, examRecordQuestionId, ExamRecordQuestionsEntity.class);
+        } else {
+            //如果考试作答记录id为空,则根据考试记录id获取考试作答记录,并将考试作答记录id保存至examRecordData表中
+            examRecordQuestions = examRecordQuestionsRepo.findByExamRecordDataId(examRecordDataId);
 
             //将考试作答记录id保存至examRecordData表中,目的:纠正历史数据
-            examRecordDataRepo.updateExamRecordDataQuestionIdById(examRecordQuestionsEntity.getId(), examRecordData.getId());
-            return examRecordQuestionsEntity;
+            examRecordDataRepo.updateExamRecordDataQuestionIdById(examRecordQuestions.getId(), examRecordData.getId());
         }
+
+        // List<ExamQuestionEntity> examQuestions = examRecordQuestions.getExamQuestionEntities();
+        // for (ExamQuestionEntity examQuestion : examQuestions) {
+        //     if (QuestionType.SINGLE_CHOICE == examQuestion.getQuestionType() ||
+        //             QuestionType.MULTIPLE_CHOICE == examQuestion.getQuestionType()) {
+        //         // 选择题 - 转换为新答案格式(兼容旧格式)
+        //         examQuestion.setCorrectAnswer(QuestionOptionHelper.parseNumbers(examQuestion.getCorrectAnswer()));
+        //         examQuestion.setStudentAnswer(QuestionOptionHelper.parseNumbers(examQuestion.getStudentAnswer()));
+        //     }
+        // }
+
+        return examRecordQuestions;
     }
 
     @Override
     public ExamRecordQuestionsEntity getExamRecordQuestionsAndFixExamRecordDataIfNecessary(Long examRecordDataId) {
         Check.isNull(examRecordDataId, "examRecordDataId不能为空");
-        ExamRecordDataEntity examRecordData = GlobalHelper.getEntity(examRecordDataRepo,
-                examRecordDataId, ExamRecordDataEntity.class);
+
+        ExamRecordDataEntity examRecordData = GlobalHelper.getEntity(examRecordDataRepo, examRecordDataId, ExamRecordDataEntity.class);
         return getExamRecordQuestionsAndFixExamRecordDataIfNecessary(examRecordData);
     }
 

+ 261 - 231
examcloud-core-oe-admin-service/src/main/java/cn/com/qmth/examcloud/core/oe/admin/service/impl/ExamRecordServiceImpl.java

@@ -10,6 +10,7 @@ package cn.com.qmth.examcloud.core.oe.admin.service.impl;
 import cn.com.qmth.examcloud.api.commons.enums.ExamType;
 import cn.com.qmth.examcloud.commons.exception.StatusException;
 import cn.com.qmth.examcloud.commons.util.DateUtil;
+import cn.com.qmth.examcloud.commons.util.StringUtil;
 import cn.com.qmth.examcloud.core.basic.api.StudentCloudService;
 import cn.com.qmth.examcloud.core.basic.api.bean.StudentBean;
 import cn.com.qmth.examcloud.core.basic.api.request.GetStudentListByIdsReq;
@@ -18,12 +19,7 @@ import cn.com.qmth.examcloud.core.oe.admin.base.jpa.SqlWrapper;
 import cn.com.qmth.examcloud.core.oe.admin.base.utils.BatchSetDataUtil;
 import cn.com.qmth.examcloud.core.oe.admin.base.utils.Check;
 import cn.com.qmth.examcloud.core.oe.admin.base.utils.DateUtils;
-import cn.com.qmth.examcloud.core.oe.admin.dao.ExamCaptureCameraInfoRepo;
-import cn.com.qmth.examcloud.core.oe.admin.dao.ExamCaptureRepo;
-import cn.com.qmth.examcloud.core.oe.admin.dao.ExamProcessRecordRepo;
-import cn.com.qmth.examcloud.core.oe.admin.dao.ExamRecordDataRepo;
-import cn.com.qmth.examcloud.core.oe.admin.dao.ExamRecordQuestionsRepo;
-import cn.com.qmth.examcloud.core.oe.admin.dao.ExamScoreRepo;
+import cn.com.qmth.examcloud.core.oe.admin.dao.*;
 import cn.com.qmth.examcloud.core.oe.admin.dao.entity.*;
 import cn.com.qmth.examcloud.core.oe.admin.dao.enums.*;
 import cn.com.qmth.examcloud.core.oe.admin.service.ExamRecordService;
@@ -37,11 +33,7 @@ import cn.com.qmth.examcloud.core.oe.admin.service.bean.examrecord.ExamRecordQue
 import cn.com.qmth.examcloud.core.oe.admin.service.bean.examrecord.ExamStudentQuestionScoreInfo;
 import cn.com.qmth.examcloud.core.oe.admin.service.bean.examstudent.ExamStudentInfo;
 import cn.com.qmth.examcloud.support.cache.CacheHelper;
-import cn.com.qmth.examcloud.support.cache.bean.CourseCacheBean;
-import cn.com.qmth.examcloud.support.cache.bean.ExamSettingsCacheBean;
-import cn.com.qmth.examcloud.support.cache.bean.ExamStageCacheBean;
-import cn.com.qmth.examcloud.support.cache.bean.OrgCacheBean;
-import cn.com.qmth.examcloud.support.cache.bean.StudentCacheBean;
+import cn.com.qmth.examcloud.support.cache.bean.*;
 import cn.com.qmth.examcloud.support.enums.ExamProperties;
 import cn.com.qmth.examcloud.support.helper.ExamCacheTransferHelper;
 import cn.com.qmth.examcloud.support.helper.FaceBiopsyHelper;
@@ -96,18 +88,18 @@ public class ExamRecordServiceImpl implements ExamRecordService {
     @Autowired
     private ExamRecordEntityConvert examRecordEntityConvert;
 
-//    @Autowired
-//    private LocalCacheService localCacheService;
+    //    @Autowired
+    //    private LocalCacheService localCacheService;
 
     @Autowired
     private StudentCloudService studentCloudService;
 
     @Autowired
     private ExamCaptureRepo examCaptureRepo;
-    
+
     @Autowired
     private ExamCaptureCameraInfoRepo examCaptureCameraInfoRepo;
-    
+
     @Autowired
     private ExamProcessRecordRepo examProcessRecordRepo;
 
@@ -210,7 +202,7 @@ public class ExamRecordServiceImpl implements ExamRecordService {
             "record_data.switch_screen_count switchScreenCount," +
             "record_data.exam_stage_id examStageId," +
             "audit.audit_user_name audit_user_name ";
-            
+
     private static final String EXAM_RECORD_FROM_SQL = " from ec_oe_exam_record_data record_data " +
             " LEFT JOIN ec_oe_exam_process_record AS process ON record_data.id = process.exam_record_data_id " +
             " LEFT JOIN ec_oe_exam_audit AS audit ON record_data.id = audit.exam_record_data_id " +
@@ -231,65 +223,82 @@ public class ExamRecordServiceImpl implements ExamRecordService {
     private ExamRecordQuestionsRepo examRecordQuestionsRepo;
 
     @Override
-    public Page<ExamRecordInfo> getExamRecordDetailListForPage(UserDataRules uds,ExamRecordQuery query) {
+    public Page<ExamRecordInfo> getExamRecordDetailListForPage(UserDataRules uds, ExamRecordQuery query) {
         Check.isNull(query, "查询参数不能为空!");
         Check.isNull(query.getExamId(), "请先选择考试批次!");
         query.addRecordStatus(ExamRecordStatus.EXAM_END.name());
         query.addRecordStatus(ExamRecordStatus.EXAM_OVERDUE.name());
-        return this.loadData(_getExamRecordDetailListForPage(uds,query), query.getExamId());
+
+        Page<ExamRecordInfo> page = _getExamRecordDetailListForPage(uds, query);
+        return this.loadData(page, query.getExamId());
+    }
+
+    /**
+     * 考试 是否开启身份检测
+     */
+    private boolean isFaceEnable(Long examId) {
+        ExamPropertyCacheBean examProperty = CacheHelper.getExamProperty(examId, ExamProperties.IS_FACE_ENABLE.name());
+        String examValue = examProperty.getValue();
+        if (StringUtils.isBlank(examValue)) {
+            return false;
+        }
+        if (StringUtil.isTrue(examValue)) {
+            return true;
+        }
+        return false;
     }
 
     @Override
-    public Page<ExamRecordInfo> getExamRecordWaitingAuditList(UserDataRules uds,ExamRecordQuery query) {
+    public Page<ExamRecordInfo> getExamRecordWaitingAuditList(UserDataRules uds, ExamRecordQuery query) {
         Check.isNull(query, "查询参数不能为空!");
         Check.isNull(query.getExamId(), "请先选择考试批次!");
         //默认条件
         query.setIsAudit(false);
         query.addRecordStatus(ExamRecordStatus.EXAM_END.name());
         query.addRecordStatus(ExamRecordStatus.EXAM_OVERDUE.name());
-        return this.getExamRecordList(uds,query);
+        return this.getExamRecordList(uds, query);
     }
 
-//    @Override
-//    public List<ExamRecordInfo> getExamRecordWaitingAudit(ExamRecordQuery query) {
-//        Check.isNull(query, "查询参数不能为空!");
-//        //默认条件
-//        query.setIsAudit(false);
-//        query.addRecordStatus(ExamRecordStatus.EXAM_END.name());
-//        query.addRecordStatus(ExamRecordStatus.EXAM_OVERDUE.name());
-//
-//        //查询条件
-//        StringBuilder sqlBuilder = new StringBuilder();
-//        //待审核(按原先的sql,多了一个ip字段)
-//        sqlBuilder.append(EXAM_RECORD_SQL);
-//        sqlBuilder.append(buildExamRecordCommonSelectCondition(query));
-//        if (query.getIsWarn() != null) {
-//            //只查有异常未审核
-//            if (query.getIsWarn()) {
-//                sqlBuilder.append(" and record_data.is_warn  = 1 and record_data.is_audit = 0 ");
-//            } else {
-//                sqlBuilder.append(" and record_data.is_warn  = 0 ");
-//            }
-//        } else {
-//            sqlBuilder.append(" and ((record_data.is_warn = 0) OR (record_data.is_warn  = 1 and record_data.is_audit = 0))");
-//        }
-//        sqlBuilder.append(" and record_data.is_illegality = 0");
-//        //查询分页记录
-//        sqlBuilder.append(" group by record_data.id ");
-//
-//        sqlBuilder.append(" order by record_data.id desc");
-//        List<ExamRecordDataEntity> entities = jdbcTemplate.query(sqlBuilder.toString(), (rs, rowNum) -> getExamRecordDataEntityByResultSet(rs));
-//
-//        return examRecordEntityConvert.ofList(entities);
-//    }
+    //    @Override
+    //    public List<ExamRecordInfo> getExamRecordWaitingAudit(ExamRecordQuery query) {
+    //        Check.isNull(query, "查询参数不能为空!");
+    //        //默认条件
+    //        query.setIsAudit(false);
+    //        query.addRecordStatus(ExamRecordStatus.EXAM_END.name());
+    //        query.addRecordStatus(ExamRecordStatus.EXAM_OVERDUE.name());
+    //
+    //        //查询条件
+    //        StringBuilder sqlBuilder = new StringBuilder();
+    //        //待审核(按原先的sql,多了一个ip字段)
+    //        sqlBuilder.append(EXAM_RECORD_SQL);
+    //        sqlBuilder.append(buildExamRecordCommonSelectCondition(query));
+    //        if (query.getIsWarn() != null) {
+    //            //只查有异常未审核
+    //            if (query.getIsWarn()) {
+    //                sqlBuilder.append(" and record_data.is_warn  = 1 and record_data.is_audit = 0 ");
+    //            } else {
+    //                sqlBuilder.append(" and record_data.is_warn  = 0 ");
+    //            }
+    //        } else {
+    //            sqlBuilder.append(" and ((record_data.is_warn = 0) OR (record_data.is_warn  = 1 and record_data.is_audit = 0))");
+    //        }
+    //        sqlBuilder.append(" and record_data.is_illegality = 0");
+    //        //查询分页记录
+    //        sqlBuilder.append(" group by record_data.id ");
+    //
+    //        sqlBuilder.append(" order by record_data.id desc");
+    //        List<ExamRecordDataEntity> entities = jdbcTemplate.query(sqlBuilder.toString(), (rs, rowNum) -> getExamRecordDataEntityByResultSet(rs));
+    //
+    //        return examRecordEntityConvert.ofList(entities);
+    //    }
 
     @Override
-    public Long getExamRecordWaitingAuditNextId(UserDataRules uds,ExamRecordQuery query, Long examRecordDataId, String next) {
-    	//****注意按ID倒序排列的****,上一条,下一条
-    	if(uds.getCourseRule().assertEmptyQueryResult()||uds.getOrgRule().assertEmptyQueryResult()) {
-    		return null;
-    	}
-    	Check.isNull(query, "查询参数不能为空!");
+    public Long getExamRecordWaitingAuditNextId(UserDataRules uds, ExamRecordQuery query, Long examRecordDataId, String next) {
+        //****注意按ID倒序排列的****,上一条,下一条
+        if (uds.getCourseRule().assertEmptyQueryResult() || uds.getOrgRule().assertEmptyQueryResult()) {
+            return null;
+        }
+        Check.isNull(query, "查询参数不能为空!");
         Check.isNull(query.getExamId(), "请先选择考试批次!");
         Check.isBlank(next, "[next]参数不能为空!");
         //默认条件
@@ -300,11 +309,11 @@ public class ExamRecordServiceImpl implements ExamRecordService {
         //查询条件
         StringBuilder sqlBuilder = new StringBuilder();
         if ("1".equals(next)) {//下一条
-        	sqlBuilder.append("select max(record_data.id) id from ec_oe_exam_record_data record_data where 1 = 1 ");
+            sqlBuilder.append("select max(record_data.id) id from ec_oe_exam_record_data record_data where 1 = 1 ");
         } else if ("0".equals(next)) {//上一条
-        	sqlBuilder.append("select min(record_data.id) id from ec_oe_exam_record_data record_data where 1 = 1 ");
+            sqlBuilder.append("select min(record_data.id) id from ec_oe_exam_record_data record_data where 1 = 1 ");
         }
-        sqlBuilder.append(buildExamRecordCommonSelectCondition(uds,query));
+        sqlBuilder.append(buildExamRecordCommonSelectCondition(uds, query));
         if (query.getIsWarn() != null) {
             //只查有异常未审核
             if (query.getIsWarn()) {
@@ -320,7 +329,7 @@ public class ExamRecordServiceImpl implements ExamRecordService {
             sqlBuilder.append(" and record_data.id < ");
             sqlBuilder.append(examRecordDataId);
         } else if ("0".equals(next)) {//上一条
-        	sqlBuilder.append(" and record_data.id > ");
+            sqlBuilder.append(" and record_data.id > ");
             sqlBuilder.append(examRecordDataId);
         }
         List<Long> ids = jdbcTemplate.query(sqlBuilder.toString(), (rs, rowNum) -> rs.getLong("id"));
@@ -333,50 +342,52 @@ public class ExamRecordServiceImpl implements ExamRecordService {
      * @param query
      * @return
      */
-    private Page<ExamRecordInfo> _getExamRecordDetailListForPage(UserDataRules uds,ExamRecordQuery query) {
+    private Page<ExamRecordInfo> _getExamRecordDetailListForPage(UserDataRules uds, ExamRecordQuery query) {
         Check.isNull(query, "查询参数不能为空!");
         Check.isNull(query.getExamId(), "请先选择考试批次!");
         //查询条件
         StringBuilder sqlBuilder = new StringBuilder();
         sqlBuilder.append(EXAM_RECORD_FROM_SQL);
-        sqlBuilder.append(buildExamRecordCommonSelectCondition(uds,query));
+        sqlBuilder.append(buildExamRecordCommonSelectCondition(uds, query));
         sqlBuilder.append(" and ((record_data.is_warn = 0) OR (record_data.is_warn  = 1 and record_data.is_audit = 1))");
         sqlBuilder.append(" group by record_data.id ");
         //分页条件
         int currentNum = (query.getPageNo() - 1) * query.getPageSize();
         List<ExamRecordDataEntity> examRecordDataList = jdbcTemplate.query(
-        		EXAM_RECORD_HEAD_SQL+sqlBuilder.toString()+" order by record_data.id desc limit " + currentNum + "," + query.getPageSize(), 
-        		new RowMapper<ExamRecordDataEntity>() {
-            @Override
-            public ExamRecordDataEntity mapRow(ResultSet rs, int rowNum) throws SQLException {
-                return getExamRecordDataEntityByResultSet(rs);
-            }
-        });
+                EXAM_RECORD_HEAD_SQL + sqlBuilder.toString() + " order by record_data.id desc limit " + currentNum + "," + query.getPageSize(),
+                new RowMapper<ExamRecordDataEntity>() {
+                    @Override
+                    public ExamRecordDataEntity mapRow(ResultSet rs, int rowNum) throws SQLException {
+                        return getExamRecordDataEntityByResultSet(rs);
+                    }
+                });
         //查询总数
-//        long total = countExamRecordDetailListForPage(query);
-        long total=jdbcTemplate.queryForObject("SELECT count(1) FROM (SELECT record_data.id "+sqlBuilder.toString()+") temtb", Long.class);
+        //        long total = countExamRecordDetailListForPage(query);
+        long total = jdbcTemplate.queryForObject("SELECT count(1) FROM (SELECT record_data.id " + sqlBuilder.toString() + ") temtb", Long.class);
         Pageable pageable = PageRequest.of(query.getPageNo() - 1, query.getPageSize());
         Page<ExamRecordDataEntity> page = new PageImpl<ExamRecordDataEntity>(examRecordDataList, pageable, total);
-        Page<ExamRecordInfo> ret=examRecordEntityConvert.of(page);
+        Page<ExamRecordInfo> ret = examRecordEntityConvert.of(page);
         fillStage(ret.getContent());
         return ret;
     }
+
     private void fillStage(List<ExamRecordInfo> list) {
-    	if(CollectionUtils.isEmpty(list)) {
-    		return;
-    	}
-    	for(ExamRecordInfo info:list) {
-    		if(info.getExamStageId()!=null) {
-    			ExamStageCacheBean stage=CacheHelper.getExamStage(info.getExamId(), info.getExamStageId());
-    			info.setExamStageOrder(stage.getStageOrder());
-    			info.setStageStartTime(stage.getStartTime());
-    			info.setStageEndTime(stage.getEndTime());
-    			info.setExamStage(stage.getStageOrder() + "("
-						+ DateUtil.format(stage.getStartTime(), DateUtil.DatePatterns.CHINA_DEFAULT) + "至"
-						+ DateUtil.format(stage.getEndTime(), DateUtil.DatePatterns.CHINA_DEFAULT) + ")");
-    		}
-    	}
+        if (CollectionUtils.isEmpty(list)) {
+            return;
+        }
+        for (ExamRecordInfo info : list) {
+            if (info.getExamStageId() != null) {
+                ExamStageCacheBean stage = CacheHelper.getExamStage(info.getExamId(), info.getExamStageId());
+                info.setExamStageOrder(stage.getStageOrder());
+                info.setStageStartTime(stage.getStartTime());
+                info.setStageEndTime(stage.getEndTime());
+                info.setExamStage(stage.getStageOrder() + "("
+                        + DateUtil.format(stage.getStartTime(), DateUtil.DatePatterns.CHINA_DEFAULT) + "至"
+                        + DateUtil.format(stage.getEndTime(), DateUtil.DatePatterns.CHINA_DEFAULT) + ")");
+            }
+        }
     }
+
     private ExamRecordDataEntity getExamRecordDataEntityByResultSet(ResultSet rs) throws SQLException {
         ExamRecordDataEntity examRecordData = new ExamRecordDataEntity();
         examRecordData.setId(rs.getLong("id"));
@@ -402,23 +413,23 @@ public class ExamRecordServiceImpl implements ExamRecordService {
         examRecordData.setBaiduFaceLivenessSuccessPercent(rs.getDouble("baidu_face_liveness_success_percent"));
         examRecordData.setAuditUserName(rs.getString("audit_user_name"));
         examRecordData.setSwitchScreenCount(rs.getInt("switchScreenCount"));
-        if(rs.getString("examStageId")!=null) {
-        	examRecordData.setExamStageId(rs.getLong("examStageId"));
+        if (rs.getString("examStageId") != null) {
+            examRecordData.setExamStageId(rs.getLong("examStageId"));
         }
 
         return examRecordData;
     }
 
-//    private long countExamRecordDetailListForPage(ExamRecordQuery query) {
-//        StringBuilder sqlBuilder = new StringBuilder();
-//        sqlBuilder.append("select count(distinct record_data.id) from ec_oe_exam_record_data record_data " +
-//        		" LEFT JOIN ec_oe_exam_process_record AS process ON record_data.id = process.exam_record_data_id " +
-//                " LEFT JOIN ec_oe_exam_audit AS audit ON record_data.id = audit.exam_record_data_id where 1=1 ");
-//        sqlBuilder.append(buildExamRecordCommonSelectCondition(query));
-//        sqlBuilder.append(" and ((record_data.is_warn = 0) OR (record_data.is_warn  = 1 and record_data.is_audit = 1))");
-//        sqlBuilder.append(" group by record_data.id ");
-//        return jdbcTemplate.queryForObject(sqlBuilder.toString(), Long.class);
-//    }
+    //    private long countExamRecordDetailListForPage(ExamRecordQuery query) {
+    //        StringBuilder sqlBuilder = new StringBuilder();
+    //        sqlBuilder.append("select count(distinct record_data.id) from ec_oe_exam_record_data record_data " +
+    //        		" LEFT JOIN ec_oe_exam_process_record AS process ON record_data.id = process.exam_record_data_id " +
+    //                " LEFT JOIN ec_oe_exam_audit AS audit ON record_data.id = audit.exam_record_data_id where 1=1 ");
+    //        sqlBuilder.append(buildExamRecordCommonSelectCondition(query));
+    //        sqlBuilder.append(" and ((record_data.is_warn = 0) OR (record_data.is_warn  = 1 and record_data.is_audit = 1))");
+    //        sqlBuilder.append(" group by record_data.id ");
+    //        return jdbcTemplate.queryForObject(sqlBuilder.toString(), Long.class);
+    //    }
 
     /**
      * 构建查询 考试明细sql语句
@@ -426,13 +437,13 @@ public class ExamRecordServiceImpl implements ExamRecordService {
      * @param query
      * @return
      */
-    private StringBuilder buildExamRecordCommonSelectCondition(UserDataRules uds,ExamRecordQuery query) {
+    private StringBuilder buildExamRecordCommonSelectCondition(UserDataRules uds, ExamRecordQuery query) {
         StringBuilder sql = new StringBuilder();
         if (query.getSwitchScreenCountStart() != null) {
-        	sql.append(" and record_data.switch_screen_count >= " +query.getSwitchScreenCountStart());
+            sql.append(" and record_data.switch_screen_count >= " + query.getSwitchScreenCountStart());
         }
         if (query.getSwitchScreenCountEnd() != null) {
-        	sql.append(" and record_data.switch_screen_count <= " +query.getSwitchScreenCountEnd());
+            sql.append(" and record_data.switch_screen_count <= " + query.getSwitchScreenCountEnd());
         }
         if (query.getExamRecordDataId() != null) {
             sql.append(" and record_data.id = " + query.getExamRecordDataId());
@@ -519,31 +530,31 @@ public class ExamRecordServiceImpl implements ExamRecordService {
         //是否有虚拟设备
         if (query.getHasVirtual() != null) {
             if (query.getHasVirtual()) {
-            	sql.append(" AND EXISTS( ");
-    			sql.append(" select 1 from ec_oe_exam_capture_camera_info v where record_data.id = v.exam_record_data_id and v.virtual_camera=1 ");
-    			sql.append(" ) ");
+                sql.append(" AND EXISTS( ");
+                sql.append(" select 1 from ec_oe_exam_capture_camera_info v where record_data.id = v.exam_record_data_id and v.virtual_camera=1 ");
+                sql.append(" ) ");
             } else {
-            	sql.append(" AND NOT EXISTS( ");
-    			sql.append(" select 1 from ec_oe_exam_capture_camera_info v where record_data.id = v.exam_record_data_id and v.virtual_camera=1 ");
-    			sql.append(" ) ");
+                sql.append(" AND NOT EXISTS( ");
+                sql.append(" select 1 from ec_oe_exam_capture_camera_info v where record_data.id = v.exam_record_data_id and v.virtual_camera=1 ");
+                sql.append(" ) ");
             }
         }
         if (StringUtils.isNotBlank(query.getVirtualName())) {
-        	sql.append(" AND EXISTS( ");
-			sql.append(" select 1 from ec_oe_exam_capture_camera_info ci where record_data.id = ci.exam_record_data_id ");
-			sql.append(" and ci.virtual_camera=1 and ci.name='"+query.getVirtualName()+"' ");
-			sql.append(" ) ");
+            sql.append(" AND EXISTS( ");
+            sql.append(" select 1 from ec_oe_exam_capture_camera_info ci where record_data.id = ci.exam_record_data_id ");
+            sql.append(" and ci.virtual_camera=1 and ci.name='" + query.getVirtualName() + "' ");
+            sql.append(" ) ");
         }
-        
+
         //ip
         if (StringUtils.isNotBlank(query.getIp())) {
-        	sql.append(" and process.source_ip='"+query.getIp()+"' ");
+            sql.append(" and process.source_ip='" + query.getIp() + "' ");
         }
-        if(uds.getOrgRule().assertNeedQueryRefIds()) {
-            sql.append(" and record_data.org_id in (" + StringUtils.join(uds.getOrgRule().getRefIds(), ",")+") ");
+        if (uds.getOrgRule().assertNeedQueryRefIds()) {
+            sql.append(" and record_data.org_id in (" + StringUtils.join(uds.getOrgRule().getRefIds(), ",") + ") ");
         }
-        if(uds.getCourseRule().assertNeedQueryRefIds()) {
-            sql.append(" and record_data.course_id in (" + StringUtils.join(uds.getCourseRule().getRefIds(), ",")+") ");
+        if (uds.getCourseRule().assertNeedQueryRefIds()) {
+            sql.append(" and record_data.course_id in (" + StringUtils.join(uds.getCourseRule().getRefIds(), ",") + ") ");
         }
         return sql;
     }
@@ -553,16 +564,16 @@ public class ExamRecordServiceImpl implements ExamRecordService {
      * 查询无异常的数据和有异常未审核的数据
      */
     @Override
-    public Page<ExamRecordInfo> getExamRecordList(UserDataRules uds,ExamRecordQuery query) {
-    	if(uds.getCourseRule().assertEmptyQueryResult()||uds.getOrgRule().assertEmptyQueryResult()) {
-    		return Page.empty();
-    	}
+    public Page<ExamRecordInfo> getExamRecordList(UserDataRules uds, ExamRecordQuery query) {
+        if (uds.getCourseRule().assertEmptyQueryResult() || uds.getOrgRule().assertEmptyQueryResult()) {
+            return Page.empty();
+        }
         Check.isNull(query, "查询参数不能为空!");
         //查询条件
         StringBuilder sqlBuilder = new StringBuilder();
         //待审核(按原先的sql,多了一个ip字段)
         sqlBuilder.append(EXAM_RECORD_FROM_SQL);
-        sqlBuilder.append(buildExamRecordCommonSelectCondition(uds,query));
+        sqlBuilder.append(buildExamRecordCommonSelectCondition(uds, query));
         if (query.getIsWarn() != null) {
             //只查有异常未审核
             if (query.getIsWarn()) {
@@ -576,20 +587,20 @@ public class ExamRecordServiceImpl implements ExamRecordService {
         sqlBuilder.append(" and record_data.is_illegality = 0");
         //查询分页记录
         sqlBuilder.append(" group by record_data.id ");
-//        sqlBuilder.append(" order by record_data.id desc");
+        //        sqlBuilder.append(" order by record_data.id desc");
         //分页条件
         int currentNum = (query.getPageNo() - 1) * query.getPageSize();
-//        sqlBuilder.append(" limit " + currentNum + "," + query.getPageSize());
+        //        sqlBuilder.append(" limit " + currentNum + "," + query.getPageSize());
         List<ExamRecordDataEntity> examRecordDataList = jdbcTemplate.query(
-        		EXAM_RECORD_HEAD_SQL+sqlBuilder.toString()+" order by record_data.id desc limit " + currentNum + "," + query.getPageSize(), new RowMapper<ExamRecordDataEntity>() {
-            @Override
-            public ExamRecordDataEntity mapRow(ResultSet rs, int rowNum) throws SQLException {
-                return getExamRecordDataEntityByResultSet(rs);
-            }
-        });
+                EXAM_RECORD_HEAD_SQL + sqlBuilder.toString() + " order by record_data.id desc limit " + currentNum + "," + query.getPageSize(), new RowMapper<ExamRecordDataEntity>() {
+                    @Override
+                    public ExamRecordDataEntity mapRow(ResultSet rs, int rowNum) throws SQLException {
+                        return getExamRecordDataEntityByResultSet(rs);
+                    }
+                });
         //查询总数
-//        long total = countExamRecordListForPage(query);
-        long total=jdbcTemplate.queryForObject("SELECT count(1) FROM (SELECT record_data.id "+sqlBuilder.toString()+") temtb", Long.class);
+        //        long total = countExamRecordListForPage(query);
+        long total = jdbcTemplate.queryForObject("SELECT count(1) FROM (SELECT record_data.id " + sqlBuilder.toString() + ") temtb", Long.class);
         Pageable pageable = PageRequest.of(query.getPageNo() - 1, query.getPageSize());
 
         Page<ExamRecordDataEntity> page = new PageImpl<ExamRecordDataEntity>(examRecordDataList, pageable, total);
@@ -600,25 +611,24 @@ public class ExamRecordServiceImpl implements ExamRecordService {
      * 监考待审:数量查询
      * 查询无异常的数据和有异常未审核的数据
      */
-//    private long countExamRecordListForPage(ExamRecordQuery query) {
-//        StringBuilder sqlBuilder = new StringBuilder();
-//        sqlBuilder.append("select count(record_data.id) from ec_oe_exam_record_data record_data where 1=1");
-//        sqlBuilder.append(buildExamRecordCommonSelectCondition(query));
-//        if (query.getIsWarn() != null) {
-//            if (query.getIsWarn()) {
-//                sqlBuilder.append(" and record_data.is_warn  = 1 and record_data.is_audit = 0 ");
-//            } else {
-//                sqlBuilder.append(" and record_data.is_warn  = 0 ");
-//            }
-//        } else {
-//            sqlBuilder.append(" and ((record_data.is_warn = 0) OR (record_data.is_warn  = 1 and record_data.is_audit = 0))");
-//        }
-//        sqlBuilder.append(" and record_data.is_illegality = 0");
-//        return jdbcTemplate.queryForObject(sqlBuilder.toString(), Long.class);
-//    }
-
+    //    private long countExamRecordListForPage(ExamRecordQuery query) {
+    //        StringBuilder sqlBuilder = new StringBuilder();
+    //        sqlBuilder.append("select count(record_data.id) from ec_oe_exam_record_data record_data where 1=1");
+    //        sqlBuilder.append(buildExamRecordCommonSelectCondition(query));
+    //        if (query.getIsWarn() != null) {
+    //            if (query.getIsWarn()) {
+    //                sqlBuilder.append(" and record_data.is_warn  = 1 and record_data.is_audit = 0 ");
+    //            } else {
+    //                sqlBuilder.append(" and record_data.is_warn  = 0 ");
+    //            }
+    //        } else {
+    //            sqlBuilder.append(" and ((record_data.is_warn = 0) OR (record_data.is_warn  = 1 and record_data.is_audit = 0))");
+    //        }
+    //        sqlBuilder.append(" and record_data.is_illegality = 0");
+    //        return jdbcTemplate.queryForObject(sqlBuilder.toString(), Long.class);
+    //    }
     @SuppressWarnings("unchecked")
-	@Override
+    @Override
     public List<Long> getExamRecordingStudentIds(Long examId) {
         Check.isNull(examId, "考试ID不能为空!");
 
@@ -647,12 +657,23 @@ public class ExamRecordServiceImpl implements ExamRecordService {
     }
 
     private Page<ExamRecordInfo> loadData(Page<ExamRecordInfo> page, Long examId) {
-        if (page == null || page.getContent() == null) {
+        if (CollectionUtils.isEmpty(page.getContent())) {
             return page;
         }
 
+        //获取考试名称
+        ExamSettingsCacheBean examBean = ExamCacheTransferHelper.getDefaultCachedExam(examId);
+
+        //考试 是否开启身份检测
+        final boolean faceEnable;
+        if (ExamType.ONLINE.name().equals(examBean.getExamType())) {
+            faceEnable = this.isFaceEnable(examId);
+        } else {
+            faceEnable = false;
+        }
+
         //缓存
-        Map<String, Object> cahcheMap = new HashMap<String, Object>();
+        Map<String, Object> cahcheMap = new HashMap<>();
 
         page.getContent().forEach(e -> {
             ExamStudentInfo examStudent = examStudentService.getExamStudentInfo(e.getExamStudentId());
@@ -674,8 +695,6 @@ public class ExamRecordServiceImpl implements ExamRecordService {
                 e.setOrgName(orgBean.getName());
             }
 
-            //获取考试名称
-            ExamSettingsCacheBean examBean = ExamCacheTransferHelper.getDefaultCachedExam(examId);
             e.setExamName(examBean.getName());
             Map<String, String> data = this.getPaperScore(e.getDataId());
             //试卷总分
@@ -684,7 +703,10 @@ public class ExamRecordServiceImpl implements ExamRecordService {
             e.setObjectiveTotalScore(data.get("objectiveTotalScore"));
             //主观题总分
             e.setSubjectiveTotalScore(data.get("subjectiveTotalScore"));
+
+            e.setShowReAudit(faceEnable);
         });
+
         return page;
     }
 
@@ -712,20 +734,20 @@ public class ExamRecordServiceImpl implements ExamRecordService {
     }
 
     @Override
-    public Long existsWarnExamRecordDetail(UserDataRules uds,ExamRecordQuery query) {
-    	if(uds.getCourseRule().assertEmptyQueryResult()||uds.getOrgRule().assertEmptyQueryResult()) {
-    		return 0L;
-    	}
+    public Long existsWarnExamRecordDetail(UserDataRules uds, ExamRecordQuery query) {
+        if (uds.getCourseRule().assertEmptyQueryResult() || uds.getOrgRule().assertEmptyQueryResult()) {
+            return 0L;
+        }
         StringBuilder sqlBuilder = new StringBuilder();
         sqlBuilder.append("select count(record_data.id) from ec_oe_exam_record_data record_data "
                 + " where 1=1 ");
-        sqlBuilder.append(buildExamRecordCommonSelectCondition(uds,query));
+        sqlBuilder.append(buildExamRecordCommonSelectCondition(uds, query));
         sqlBuilder.append(" and record_data.is_warn = 1 and record_data.is_audit = 0");
         return jdbcTemplate.queryForObject(sqlBuilder.toString(), Long.class);
     }
 
     @Override
-    public List<ExamRecordInfo> getExamRecordDetailListForAsync(UserDataRules uds,ExamRecordQuery query) {
+    public List<ExamRecordInfo> getExamRecordDetailListForAsync(UserDataRules uds, ExamRecordQuery query) {
         Check.isNull(query, "查询参数不能为空!");
         query.addRecordStatus(ExamRecordStatus.EXAM_END.name());
         query.addRecordStatus(ExamRecordStatus.EXAM_OVERDUE.name());
@@ -734,11 +756,11 @@ public class ExamRecordServiceImpl implements ExamRecordService {
         int pageNo = 1;
         int pageSize = 200;
         for (; ; ) {
-            List<ExamRecordInfo> tem = getExamRecordDetailPageForExport(uds,query, pageNo,pageSize);
+            List<ExamRecordInfo> tem = getExamRecordDetailPageForExport(uds, query, pageNo, pageSize);
             if (tem == null || tem.size() == 0) {
                 break;
             } else {
-            	pageNo++;
+                pageNo++;
                 examRecordDataList.addAll(tem);
             }
         }
@@ -829,7 +851,7 @@ public class ExamRecordServiceImpl implements ExamRecordService {
             public void setData(List<ExamRecordInfo> dataList) {
                 List<Long> ids = dataList.stream().map(dto -> dto.getId()).distinct().collect(Collectors.toList());
                 Map<Long, Set<String>> map = new HashMap<>();
-                List<ExamCaptureCameraInfoEntity> examCaptureList = examCaptureCameraInfoRepo.findByExamRecordDataIdInAndVirtualCamera(ids,true);
+                List<ExamCaptureCameraInfoEntity> examCaptureList = examCaptureCameraInfoRepo.findByExamRecordDataIdInAndVirtualCamera(ids, true);
                 if (examCaptureList != null && examCaptureList.size() > 0) {
                     for (ExamCaptureCameraInfoEntity examCapture : examCaptureList) {
                         Set<String> virtualCameraNames = map.get(examCapture.getExamRecordDataId());
@@ -851,7 +873,7 @@ public class ExamRecordServiceImpl implements ExamRecordService {
         };
         tool.setDataForBatch(examRecordDataList, 100);
     }
-    
+
     private void setIps(List<ExamRecordInfo> examRecordDataList) {
         BatchSetDataUtil<ExamRecordInfo> tool = new BatchSetDataUtil<ExamRecordInfo>() {
             @Override
@@ -863,7 +885,7 @@ public class ExamRecordServiceImpl implements ExamRecordService {
                     for (ExamProcessRecordEntity ep : list) {
                         Set<String> ips = map.get(ep.getExamRecordDataId());
                         if (ips == null) {
-                        	ips = new HashSet<String>();
+                            ips = new HashSet<String>();
                             map.put(ep.getExamRecordDataId(), ips);
                         }
                         String ip = ep.getSourceIp();
@@ -947,10 +969,10 @@ public class ExamRecordServiceImpl implements ExamRecordService {
 
     }
 
-    private List<ExamRecordInfo> getExamRecordDetailPageForExport(UserDataRules uds,ExamRecordQuery query,int pageNo, int pageSize) {
+    private List<ExamRecordInfo> getExamRecordDetailPageForExport(UserDataRules uds, ExamRecordQuery query, int pageNo, int pageSize) {
         StringBuilder sqlBuilder = new StringBuilder();
         sqlBuilder.append(EXAM_RECORD_EXPORT_SQL);
-        sqlBuilder.append(buildExamRecordCommonSelectCondition(uds,query));
+        sqlBuilder.append(buildExamRecordCommonSelectCondition(uds, query));
         sqlBuilder.append(" and ((record_data.is_warn = 0) OR (record_data.is_warn  = 1 and record_data.is_audit = 1))");
         sqlBuilder.append(" group by record_data.id ");
         //根据ip查询
@@ -965,68 +987,68 @@ public class ExamRecordServiceImpl implements ExamRecordService {
         return ret;
     }
 
-//    @Override
-//    public List<ExamRecordInfo> getExamRecordDetailList(ExamRecordQuery query) {
-//        Check.isNull(query, "查询参数不能为空!");
-//        query.addRecordStatus(ExamRecordStatus.EXAM_END.name());
-//        query.addRecordStatus(ExamRecordStatus.EXAM_OVERDUE.name());
-//
-//        StringBuilder sqlBuilder = new StringBuilder();
-//        sqlBuilder.append(EXAM_RECORD_SQL);
-//        sqlBuilder.append(buildExamRecordCommonSelectCondition(query));
-//        sqlBuilder.append(" and ((record_data.is_warn = 0) OR (record_data.is_warn  = 1 and record_data.is_audit = 1))");
-//        sqlBuilder.append(" group by record_data.id ");
-//        //根据ip查询
-//        /*if (StringUtils.isNoneBlank(query.getIp())) {
-//            sqlBuilder.append(" having ip like '%"+query.getIp()+"%' ");
-//        }*/
-//        sqlBuilder.append(" order by record_data.id desc");
-//
-//        List<ExamRecordDataEntity> examRecordDataList = jdbcTemplate.query(sqlBuilder.toString(), new RowMapper<ExamRecordDataEntity>() {
-//            @Override
-//            public ExamRecordDataEntity mapRow(ResultSet rs, int rowNum) throws SQLException {
-//                return getExamRecordDataEntityByResultSet(rs);
-//            }
-//        });
-//
-//        List<ExamRecordInfo> examRecordInfoList = examRecordEntityConvert.of(examRecordDataList);
-//        return this.loadExamRecordDetailData(examRecordInfoList, query.getExamId());
-//    }
-
-//    private List<ExamRecordInfo> loadExamRecordDetailData(List<ExamRecordInfo> list, Long examId) {
-//        if (list == null || list.size() == 0) {
-//            return new ArrayList<ExamRecordInfo>();
-//        }
-//        //缓存
-//        Map<String, Object> cahcheMap = new HashMap<String, Object>();
-//
-//        list.forEach(examRecordInfo -> {
-//            //获取考试名称
-//            ExamSettingsCacheBean examBean = ExamCacheTransferHelper.getDefaultCachedExam(examId);
-//            examRecordInfo.setExamName(examBean.getName());
-//
-//            ExamStudentInfo examStudent = (ExamStudentInfo) cahcheMap.get("examStudentinfo_" + examRecordInfo.getExamStudentId());
-//            if (examStudent == null) {
-//                examStudent = examStudentService.getExamStudentInfo(examRecordInfo.getExamStudentId());
-//                cahcheMap.put("examStudentinfo_" + examRecordInfo.getExamStudentId(), examStudent);
-//            }
-//
-//            String photoNumber = localCacheService.getStudentPhotoNumber(cahcheMap, examRecordInfo.getStudentId());
-//            examRecordInfo.setPhone(photoNumber);//电话号码
-//            if (examStudent != null) {
-//                examRecordInfo.setSpecialtyName(examStudent.getSpecialtyName());
-//                examRecordInfo.setGrade(examStudent.getGrade());
-//            }
-//            Map<String, String> data = this.getPaperScore(examRecordInfo.getDataId());
-//            //试卷总分
-//            examRecordInfo.setPaperTotalScore(data.get("paperTotalScore"));
-//            //客观题总分
-//            examRecordInfo.setObjectiveTotalScore(data.get("objectiveTotalScore"));
-//            //主观题总分
-//            examRecordInfo.setSubjectiveTotalScore(data.get("subjectiveTotalScore"));
-//        });
-//        return list;
-//    }
+    //    @Override
+    //    public List<ExamRecordInfo> getExamRecordDetailList(ExamRecordQuery query) {
+    //        Check.isNull(query, "查询参数不能为空!");
+    //        query.addRecordStatus(ExamRecordStatus.EXAM_END.name());
+    //        query.addRecordStatus(ExamRecordStatus.EXAM_OVERDUE.name());
+    //
+    //        StringBuilder sqlBuilder = new StringBuilder();
+    //        sqlBuilder.append(EXAM_RECORD_SQL);
+    //        sqlBuilder.append(buildExamRecordCommonSelectCondition(query));
+    //        sqlBuilder.append(" and ((record_data.is_warn = 0) OR (record_data.is_warn  = 1 and record_data.is_audit = 1))");
+    //        sqlBuilder.append(" group by record_data.id ");
+    //        //根据ip查询
+    //        /*if (StringUtils.isNoneBlank(query.getIp())) {
+    //            sqlBuilder.append(" having ip like '%"+query.getIp()+"%' ");
+    //        }*/
+    //        sqlBuilder.append(" order by record_data.id desc");
+    //
+    //        List<ExamRecordDataEntity> examRecordDataList = jdbcTemplate.query(sqlBuilder.toString(), new RowMapper<ExamRecordDataEntity>() {
+    //            @Override
+    //            public ExamRecordDataEntity mapRow(ResultSet rs, int rowNum) throws SQLException {
+    //                return getExamRecordDataEntityByResultSet(rs);
+    //            }
+    //        });
+    //
+    //        List<ExamRecordInfo> examRecordInfoList = examRecordEntityConvert.of(examRecordDataList);
+    //        return this.loadExamRecordDetailData(examRecordInfoList, query.getExamId());
+    //    }
+
+    //    private List<ExamRecordInfo> loadExamRecordDetailData(List<ExamRecordInfo> list, Long examId) {
+    //        if (list == null || list.size() == 0) {
+    //            return new ArrayList<ExamRecordInfo>();
+    //        }
+    //        //缓存
+    //        Map<String, Object> cahcheMap = new HashMap<String, Object>();
+    //
+    //        list.forEach(examRecordInfo -> {
+    //            //获取考试名称
+    //            ExamSettingsCacheBean examBean = ExamCacheTransferHelper.getDefaultCachedExam(examId);
+    //            examRecordInfo.setExamName(examBean.getName());
+    //
+    //            ExamStudentInfo examStudent = (ExamStudentInfo) cahcheMap.get("examStudentinfo_" + examRecordInfo.getExamStudentId());
+    //            if (examStudent == null) {
+    //                examStudent = examStudentService.getExamStudentInfo(examRecordInfo.getExamStudentId());
+    //                cahcheMap.put("examStudentinfo_" + examRecordInfo.getExamStudentId(), examStudent);
+    //            }
+    //
+    //            String photoNumber = localCacheService.getStudentPhotoNumber(cahcheMap, examRecordInfo.getStudentId());
+    //            examRecordInfo.setPhone(photoNumber);//电话号码
+    //            if (examStudent != null) {
+    //                examRecordInfo.setSpecialtyName(examStudent.getSpecialtyName());
+    //                examRecordInfo.setGrade(examStudent.getGrade());
+    //            }
+    //            Map<String, String> data = this.getPaperScore(examRecordInfo.getDataId());
+    //            //试卷总分
+    //            examRecordInfo.setPaperTotalScore(data.get("paperTotalScore"));
+    //            //客观题总分
+    //            examRecordInfo.setObjectiveTotalScore(data.get("objectiveTotalScore"));
+    //            //主观题总分
+    //            examRecordInfo.setSubjectiveTotalScore(data.get("subjectiveTotalScore"));
+    //        });
+    //        return list;
+    //    }
 
     @Override
     public List<ExamStudentQuestionScoreInfo> getExamStudentQuestionScoreList(Long examId, String courseCode) {
@@ -1145,6 +1167,14 @@ public class ExamRecordServiceImpl implements ExamRecordService {
         examStudentQuestionScoreInfo.setOrder(qa.getOrder());
         examStudentQuestionScoreInfo.setStudentScore(qa.getStudentScore());
         examStudentQuestionScoreInfo.setStudentAnswer(qa.getStudentAnswer());
+
+        // if (QuestionType.SINGLE_CHOICE == qa.getQuestionType() || QuestionType.MULTIPLE_CHOICE == qa.getQuestionType()) {
+        //     // 选择题 - 转换为新答案格式(兼容旧格式)
+        //     examStudentQuestionScoreInfo.setStudentAnswer(QuestionOptionHelper.parseNumbers(qa.getStudentAnswer()));
+        // } else {
+        //     examStudentQuestionScoreInfo.setStudentAnswer(qa.getStudentAnswer());
+        // }
+
         return examStudentQuestionScoreInfo;
     }
 

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

@@ -311,7 +311,7 @@ public class ExamStudentServiceImpl implements ExamStudentService {
         fillStage(examStudentInfoList);
         return new PageImpl<>(examStudentInfoList, pageable, totalSize);
     }
-    
+
     private void fillStage(List<ExamStudentInfo> list) {
     	if(CollectionUtils.isEmpty(list)) {
     		return;
@@ -401,6 +401,8 @@ public class ExamStudentServiceImpl implements ExamStudentService {
             } else {
                 info.setExamCycleEnabled(false);
             }
+
+            info.setExamType(examType.name());
         }
 
         return examStudentDtoList;
@@ -673,7 +675,7 @@ public class ExamStudentServiceImpl implements ExamStudentService {
         if(rs.getString("exam_stage_id")!=null) {
         	examStudentEntity.setExamStageId(rs.getLong("exam_stage_id"));
         }
-        
+
         return examStudentEntity;
     }
 
@@ -1235,6 +1237,8 @@ public class ExamStudentServiceImpl implements ExamStudentService {
             }else {
             	info.setShowUndertaking(false);
             }
+
+            info.setExamType(examType.name());
         }
 
         return examStudentDtoList;

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

@@ -1,5 +1,6 @@
 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.ExamSpecialSettingsType;
 import cn.com.qmth.examcloud.api.commons.enums.ExamType;
 import cn.com.qmth.examcloud.commons.exception.StatusException;
@@ -376,7 +377,7 @@ public class OfflineExamServiceImpl implements OfflineExamService {
         //更新考试记录状态,交卷(上传)时间
         examRecordDataRepo.updateExamRecordStatusById(examRecordDataId, ExamRecordStatus.EXAM_END, new Date());
 
-        ReportsUtil.report(new AdminOperateReport(examRecordData.getRootOrgId(), userId, "考试进度详情-上传作答",
+        ReportsUtil.report(new AdminOperateReport(examRecordData.getRootOrgId(), userId, AdminOperateType.TYPE21.getDesc(),
                 "考试记录ID:" + examRecordDataId + " 考生ID:" + examRecordData.getExamStudentId()));
     }
 

+ 1 - 0
examcloud-core-oe-admin-starter/pom.xml

@@ -55,6 +55,7 @@
                 <artifactId>maven-assembly-plugin</artifactId>
                 <configuration>
                     <finalName>examcloud-core-oe-admin</finalName>
+                    <skipAssembly>${skipAssembly}</skipAssembly>
                     <descriptors>
                         <descriptor>assembly.xml</descriptor>
                     </descriptors>

+ 2 - 1
examcloud-core-oe-admin-starter/src/main/java/cn/com/qmth/examcloud/core/oe/admin/stater/config/SwaggerConfig.java

@@ -25,6 +25,7 @@ public class SwaggerConfig {
         List<Parameter> parameters = new ArrayList<>();
         parameters.add(new ParameterBuilder().name("key").modelRef(new ModelRef("String")).parameterType("header").required(false).build());
         parameters.add(new ParameterBuilder().name("token").modelRef(new ModelRef("String")).parameterType("header").required(false).build());
+        parameters.add(new ParameterBuilder().name("timestamp").modelRef(new ModelRef("String")).parameterType("header").required(false).build());
 
         return new Docket(DocumentationType.SWAGGER_2)
                 .groupName("default")
@@ -33,7 +34,7 @@ public class SwaggerConfig {
                 .useDefaultResponseMessages(false)
                 .select()
                 // .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
-                .apis(RequestHandlerSelectors.basePackage("cn.com.qmth.examcloud.core.oe.admin.api.controller.client"))
+                .apis(RequestHandlerSelectors.basePackage("cn.com.qmth.examcloud.core.oe.admin.api.controller"))
                 .paths(PathSelectors.any())
                 .build();
     }

+ 1 - 0
examcloud-core-oe-admin-starter/src/main/resources/log4j2.xml

@@ -36,6 +36,7 @@
 
     <Loggers>
         <logger name="springfox.documentation" level="WARN"/>
+        <logger name="org.mongodb.driver" level="WARN"/>
         <logger name="org.springframework" level="WARN"/>
         <logger name="org.hibernate" level="WARN"/>
         <logger name="org.apache" level="WARN"/>