deason hace 2 años
padre
commit
ecf2a96eac

+ 852 - 844
examcloud-core-oe-admin-service/src/main/java/cn/com/qmth/examcloud/core/oe/admin/service/impl/ExamScoreServiceImpl.java

@@ -65,851 +65,859 @@ import java.util.stream.Collectors;
 @Service
 public class ExamScoreServiceImpl implements ExamScoreService {
 
-	private static final Logger log = LoggerFactory.getLogger(ExamScoreServiceImpl.class);
+    private static final Logger log = LoggerFactory.getLogger(ExamScoreServiceImpl.class);
+
     @Autowired
     private ExportTaskService exportTaskService;
-	@Autowired
-	private ExamScoreRepo examScoreRepo;
-
-	@Autowired
-	private ExamRecordDataRepo examRecordDataRepo;
-
-	@Autowired
-	private ExamRecordQuestionsRepo examRecordQuestionsRepo;
-
-	@Autowired
-	private ExamRecordForMarkingRepo examRecordForMarkingRepo;
-
-	@Autowired
-	private ExamRecordQuestionsService examRecordQuestionsService;
-
-	@Autowired
-	private ExamStudentService examStudentService;
-
-	@Autowired
-	private ExamRecordService examRecordService;
-
-	@Autowired
-	private GainBaseDataService gainBaseDataService;
-
-	@Autowired
-	private JdbcTemplate jdbcTemplate;
-
-	@Autowired
-	private RedisClient redisClient;
-
-	@Autowired
-	private ExamStudentFinalScoreService examStudentFinalScoreService;
-
-	@Override
-	public Page<ExamScoreInfo> getExamScoreList(UserDataRules uds, ExamScoreQuery query) {
-		Check.isNull(query, "查询参数不能为空!");
-		Check.isNull(query.getExamId(), "请先选择考试批次!");
-		Pageable pageable = SpecUtils.buildPageable(query.getPageNo(), query.getPageSize());
-
-		// 阅卷方式
-		String markingType = ExamCacheTransferHelper
-				.getDefaultCachedExamProperty(query.getExamId(), ExamProperties.MARKING_TYPE.name()).getValue();
-
-		// 获取考生列表
-		Page<ExamStudentInfo> page = examStudentService.getExamStudentListPage(uds, ExamScoreEntityConvert.of(query));
-		List<ExamStudentInfo> examStudentList = page.getContent();
-		if (examStudentList == null || examStudentList.size() == 0) {
-			return new PageImpl<ExamScoreInfo>(Lists.newArrayList(), pageable, page.getTotalElements());
-		}
-
-		// 封装成绩统计结果
-		List<ExamScoreInfo> examScoreList = new ArrayList<>();
-		examStudentList.forEach(examStudent -> {
-			// 获取考试信息
-			ExamSettingsCacheBean examBean = ExamCacheTransferHelper.getDefaultCachedExam(query.getExamId());
-			examScoreList.add(of(examStudent, examBean, markingType));
-		});
-		fillStage(examScoreList);
-		return new PageImpl<ExamScoreInfo>(examScoreList, pageable, page.getTotalElements());
-	}
-
-	private void fillStage(List<ExamScoreInfo> list) {
-		if (CollectionUtils.isEmpty(list)) {
-			return;
-		}
-		for (ExamScoreInfo 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 void fillStage(List<ExamScoreInfo> list,Long taskId) {
-		if (CollectionUtils.isEmpty(list)) {
-			return;
-		}
-		for (ExamScoreInfo info : list) {
-			exportTaskService.checkStopExportTaskById(taskId);
-			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 ExamScoreInfo of(ExamStudentInfo examStudent, ExamSettingsCacheBean examBean, String markingType) {
-		ExamScoreInfo examScore = new ExamScoreInfo();
-		examScore.setExamId(examStudent.getExamId());
-		examScore.setExamName(examBean.getName());
-		examScore.setStudentId(examStudent.getStudentId());
-		examScore.setStudentCode(examStudent.getStudentCode());
-		examScore.setStudentName(examStudent.getStudentName());
-		examScore.setIdentityNumber(examStudent.getIdentityNumber());
-
-		examScore.setCourseId(examStudent.getCourseId());
-		examScore.setCourseCode(examStudent.getCourseCode());
-		examScore.setCourseName(examStudent.getCourseName());
-		examScore.setCourseNameAndCode(examStudent.getCourseName() + "(" + examStudent.getCourseCode() + ")");
-		examScore.setCourseLevel(CourseLevel.getCourseLevelTitle(examStudent.getCourseLevel()));
-
-		examScore.setOrgId(examStudent.getOrgId());
-		examScore.setOrgCode(examStudent.getOrgCode());
-		examScore.setOrgName(examStudent.getOrgName());
-		examScore.setInfoCollector(examStudent.getInfoCollector());
-		examScore.setSpecialtyName(examStudent.getSpecialtyName());
-		examScore.setGrade(examStudent.getGrade());
-		examScore.setExamStageId(examStudent.getExamStageId());
-		Long examTimes = examBean.getExamTimes();
-		if (examTimes != null) {
-			Integer extraExamNum = examStudent.getExtraNum() == null ? 0 : examStudent.getExtraNum();
-			Integer usedNum = examStudent.getUsedNum() == null ? 0 : examStudent.getUsedNum();
-			Long leftExamTimes = (examTimes + extraExamNum - usedNum) < 0 ? 0 : (examTimes + extraExamNum - usedNum);
-			examScore.setLeftExamTimes(leftExamTimes);
-		}
-		return setCommomScoreInfo(examScore, examStudent.getFinished(), examStudent.getExamStudentId(), examBean,
-				markingType);
-	}
-
-	@Override
-	public List<ExamScoreInfo> exportExamScoreListForAsync(UserDataRules uds, ExamScoreQuery query) {
-		if (uds.getCourseRule().assertEmptyQueryResult() || uds.getOrgRule().assertEmptyQueryResult()) {
-			return Lists.newArrayList();
-		}
-		Check.isNull(query, "查询参数不能为空!");
-		Check.isNull(query.getExamId(), "请先选择考试批次!");
-
-		// 阅卷方式
-		String markingType = ExamCacheTransferHelper
-				.getDefaultCachedExamProperty(query.getExamId(), ExamProperties.MARKING_TYPE.name()).getValue();
-//        if (query.getStartLimit() != null && query.getEndLimit() != null) {
-//            return getExamStudentInfoListOfScoreExport(uds, query, markingType);
-//        } else {
-		List<ExamScoreInfo> examScoreInfoList = new ArrayList<ExamScoreInfo>();
-		List<Long> ids = getExamStudentInfoListOfScoreExportByPageOnlyId(uds, query, markingType);
-		if (CollectionUtils.isEmpty(ids)) {
-			return examScoreInfoList;
-		}
-		List<ExamStudentEntity> examStudentList=new BatchGetDataUtil<ExamStudentEntity, Long>() {
-
-			@Override
-			protected List<ExamStudentEntity> getData(List<Long> paramList) {
-				exportTaskService.checkStopExportTaskById(query.getTaskId());
-				return getExamStudentInfoListOfScoreExportByPage(uds, query, markingType,paramList);
-			}
-		}.getDataForBatch(ids, 1000);
-       
-		if(CollectionUtils.isEmpty(examStudentList)) {
-        	return examScoreInfoList;
-        }
-
-		// 缓存
-		for (ExamStudentEntity examStudent : examStudentList) {
-			exportTaskService.checkStopExportTaskById(query.getTaskId());
-			long courseId = examStudent.getCourseId();
-			CourseCacheBean courseBean = ExamCacheTransferHelper.getCachedCourse(courseId);
-
-			long orgId = examStudent.getOrgId();
-			OrgCacheBean orgBean = gainBaseDataService.getOrgBean(orgId);
-
-			examScoreInfoList.add(convertToExamScoreInfo(examStudent, courseBean, orgBean, markingType));
-		}
-		fillStage(examScoreInfoList,query.getTaskId());
-		return examScoreInfoList;
-//        }
-	}
-
-	private List<ExamStudentEntity> getExamStudentInfoListOfScoreExportByPage(UserDataRules uds, ExamScoreQuery query,
-			String markingType, List<Long> ids) {
-		// 查询条件
-		StringBuffer sql = new StringBuffer();
-		sql.append(
-				"select id,exam_student_id,exam_id,course_id,course_code,course_level,finished,student_id,student_code,student_name,identity_number"
-						+ ",info_collector,root_org_id,org_id,paper_type,used_num,extra_num"
-						+ ",specialty_code,specialty_name,grade,exam_stage_id from ec_oe_exam_student where id in ( ");
-		sql.append(StringUtils.join(ids, ","));
-		sql.append(" )");
-
-		List<ExamStudentEntity> examStudentList = jdbcTemplate.query(sql.toString(),
-				new RowMapper<ExamStudentEntity>() {
-					@Override
-					public ExamStudentEntity mapRow(ResultSet rs, int rowNum) throws SQLException {
-						return getExamStudentEntityByResultSet(rs);
-					}
-				});
-
-		return examStudentList;
-	}
-
-	private List<Long> getExamStudentInfoListOfScoreExportByPageOnlyId(UserDataRules uds, ExamScoreQuery query,
-			String markingType) {
-		// 查询条件
-		StringBuffer sql = new StringBuffer();
-		sql.append("select id from ec_oe_exam_student where 1=1 ");
-		if (query.getOrgId() != null) {
-			sql.append(" and org_id=" + query.getOrgId());
-		}
-		if (query.getExamId() != null) {
-			sql.append(" and exam_id=" + query.getExamId());
-		}
-		if (query.getExamStageId() != null) {
-			sql.append(" and exam_stage_id=" + query.getExamStageId());
-		}
-		if (StringUtils.isNotBlank(query.getStudentCode())) {
-			sql.append(" and student_code LIKE '" + query.getStudentCode() + "%'");
-		}
-		if (StringUtils.isNotBlank(query.getStudentName())) {
-			sql.append(" and student_name LIKE '" + query.getStudentName() + "%'");
-		}
-		if (StringUtils.isNotBlank(query.getIdentityNumber())) {
-			sql.append(" and identity_number LIKE '" + query.getIdentityNumber() + "%'");
-		}
-		if (query.getCourseId() != null) {
-			sql.append(" and course_id=" + query.getCourseId());
-		}
-		if (StringUtils.isNotBlank(query.getCourseLevel())) {
-			sql.append(" and course_level= '" + query.getCourseLevel() + "'");
-		}
-		if (query.getFinished() != null) {
-			sql.append(" and finished= " + query.getFinished());
-		}
-		if (uds.getOrgRule().assertNeedQueryRefIds()) {
-			sql.append(" and org_id in (" + StringUtils.join(uds.getOrgRule().getRefIds(), ",") + ") ");
-		}
-		if (uds.getCourseRule().assertNeedQueryRefIds()) {
-			sql.append(" and course_id in (" + StringUtils.join(uds.getCourseRule().getRefIds(), ",") + ") ");
-		}
-
-		List<Long> examStudentList = jdbcTemplate.queryForList(sql.toString(), Long.class);
-
-		return examStudentList;
-	}
-
-	// @Override
-	// public List<ExamScoreInfo> exportExamScoreList(ExamScoreQuery query) {
-	// Check.isNull(query, "查询参数不能为空!");
-	// Check.isNull(query.getExamId(), "请先选择考试批次!");
-	//
-	// //阅卷方式
-	// String markingType = ExamCacheTransferHelper.
-	// getDefaultCachedExamProperty(query.getExamId(),
-	// ExamProperties.MARKING_TYPE.name()).getValue();
-	// return getExamStudentInfoListOfScoreExport(query, markingType);
-	// }
-
-	@Override
-	public List<ExamScoreEntity> getAllExamScoreList(Long examId, String identityNumber, Long courseId) {
-		List<ExamRecordDataEntity> allExamRecordDataList = examRecordDataRepo
-				.findByExamIdAndIdentityNumberAndCourseId(examId, identityNumber, courseId);
-		if (allExamRecordDataList == null || allExamRecordDataList.isEmpty()) {
-			return null;
-		}
-
-		List<Long> examRecordDataIds = allExamRecordDataList.stream().map(p -> p.getId()).collect(Collectors.toList());
-		return examScoreRepo.findByExamRecordDataIdIn(examRecordDataIds);
-	}
-
-//    private List<ExamScoreInfo> getExamStudentInfoListOfScoreExport(UserDataRules uds, ExamScoreQuery query, String markingType) {
-//        Check.isNull(query, "查询参数不能为空!");
-//        //查询条件
-//        StringBuffer sql = new StringBuffer();
-//        sql.append("select id,exam_student_id,exam_id,course_id,course_code,course_level,finished,student_id,student_code,student_name,identity_number"
-//                + ",info_collector,root_org_id,org_id,paper_type,used_num,extra_num"
-//                + ",specialty_code,specialty_name,grade,exam_stage_id from ec_oe_exam_student where 1=1 ");
-//        if (query.getOrgId() != null) {
-//            sql.append(" and org_id=" + query.getOrgId());
-//        }
-//        if (query.getExamId() != null) {
-//            sql.append(" and exam_id=" + query.getExamId());
-//        }
-//        if (query.getExamStageId() != null) {
-//            sql.append(" and exam_stage_id=" + query.getExamStageId());
-//        }
-//        if (StringUtils.isNotBlank(query.getStudentCode())) {
-//            sql.append(" and student_code LIKE '" + query.getStudentCode() + "%'");
-//        }
-//        if (StringUtils.isNotBlank(query.getStudentName())) {
-//            sql.append(" and student_name LIKE '" + query.getStudentName() + "%'");
-//        }
-//        if (StringUtils.isNotBlank(query.getIdentityNumber())) {
-//            sql.append(" and identity_number LIKE '" + query.getIdentityNumber() + "%'");
-//        }
-//        if (query.getCourseId() != null) {
-//            sql.append(" and course_id=" + query.getCourseId());
-//        }
-//        if (StringUtils.isNotBlank(query.getCourseLevel())) {
-//            sql.append(" and course_level= '" + query.getCourseLevel() + "'");
-//        }
-//        if (query.getFinished() != null) {
-//            sql.append(" and finished= " + query.getFinished());
-//        }
-//        if (uds.getOrgRule().assertNeedQueryRefIds()) {
-//            sql.append(" and org_id in (" + StringUtils.join(uds.getOrgRule().getRefIds(), ",") + ") ");
-//        }
-//        if (uds.getCourseRule().assertNeedQueryRefIds()) {
-//            sql.append(" and course_id in (" + StringUtils.join(uds.getCourseRule().getRefIds(), ",") + ") ");
-//        }
-//        sql.append(" order by id");
-//
-//        if (query.getStartLimit() != null && query.getEndLimit() != null) {
-//            int offset = query.getEndLimit() - query.getStartLimit() + 1;
-//            sql.append(" limit " + (query.getStartLimit() - 1) + "," + offset);
-//        }
-//        List<ExamStudentEntity> examStudentList = jdbcTemplate.query(sql.toString(), new RowMapper<ExamStudentEntity>() {
-//            @Override
-//            public ExamStudentEntity mapRow(ResultSet rs, int rowNum) throws SQLException {
-//                return getExamStudentEntityByResultSet(rs);
-//            }
-//        });
-//
-//        List<ExamScoreInfo> examScoreInfoList = new ArrayList<ExamScoreInfo>();
-//        //缓存
-//        for (ExamStudentEntity examStudent : examStudentList) {
-//            long courseId = examStudent.getCourseId();
-//            CourseCacheBean courseBean = ExamCacheTransferHelper.getCachedCourse(courseId);
-//
-//            long orgId = examStudent.getOrgId();
-//            OrgCacheBean orgBean = gainBaseDataService.getOrgBean(orgId);
-//
-//            examScoreInfoList.add(convertToExamScoreInfo(examStudent, courseBean, orgBean, markingType));
-//        }
-//        fillStage(examScoreInfoList);
-//        return examScoreInfoList;
-//    }
-
-	private ExamScoreInfo convertToExamScoreInfo(ExamStudentEntity examStudent, CourseCacheBean courseBean,
-			OrgCacheBean orgBean, String markingType) {
-		if (examStudent == null) {
-			return null;
-		}
-		// 获取考试信息
-		ExamSettingsCacheBean examBean = ExamCacheTransferHelper.getCachedExam(examStudent.getExamId(),
-				examStudent.getStudentId(), examStudent.getExamStageId());
-		ExamScoreInfo examScore = new ExamScoreInfo();
-		examScore.setExamStageId(examStudent.getExamStageId());
-		examScore.setExamId(examStudent.getExamId());
-		examScore.setExamName(examBean.getName());
-		examScore.setStudentId(examStudent.getStudentId());
-		examScore.setStudentCode(examStudent.getStudentCode());
-		examScore.setStudentName(examStudent.getStudentName());
-		examScore.setIdentityNumber(examStudent.getIdentityNumber());
-		examScore.setInfoCollector(examStudent.getInfoCollector());
-
-		examScore.setCourseId(examStudent.getCourseId());
-		examScore.setCourseCode(examStudent.getCourseCode());
-		examScore.setCourseName(courseBean.getName());
-		examScore.setCourseNameAndCode(courseBean.getName() + "(" + courseBean.getCode() + ")");
-		examScore.setCourseLevel(CourseLevel.getCourseLevelTitle(examStudent.getCourseLevel()));
-
-		examScore.setOrgId(examStudent.getOrgId());
-		examScore.setOrgCode(orgBean.getCode());
-		examScore.setOrgName(orgBean.getName());
-
-		examScore.setSpecialtyName(examStudent.getSpecialtyName());
-		examScore.setGrade(examStudent.getGrade());
-
-		// 剩余考试次数=可考次数+可重考次数-已考次数
-		Long examTimes = examBean.getExamTimes();
-		if (examTimes != null) {
-			Integer extraExamNum = examStudent.getExtraNum() == null ? 0 : examStudent.getExtraNum();
-			Integer usedNum = examStudent.getUsedNum() == null ? 0 : examStudent.getUsedNum();
-			Long leftExamTimes = (examTimes + extraExamNum - usedNum) < 0 ? 0 : (examTimes + extraExamNum - usedNum);
-			examScore.setLeftExamTimes(leftExamTimes);
-		}
-
-		return setCommomScoreInfo(examScore, examStudent.getFinished(), examStudent.getExamStudentId(), examBean,
-				markingType);
-	}
-
-	private ExamScoreInfo setCommomScoreInfo(ExamScoreInfo examScoreInfo, Boolean finished, long examStudentId,
-			ExamSettingsCacheBean examBean, String markingType) {
-		// 查询考试记录
-		if (finished != null && finished) {
-			// 查询考试记录
-			List<ExamRecordDataEntity> examRecordList = examRecordService
-					.getExamRecordListByExamStudentId(examStudentId);
-			examScoreInfo.setIsFinished("是");// 是否完成考试
-			examScoreInfo.setIsAbsent("否");// 是否缺考
-			// 违纪次数
-			examScoreInfo.setDisciplineCount(disciplineCount(examRecordList));
-			// 提交次数
-			examScoreInfo.setSubmitCount(submitCount(examRecordList));
-
-			// 设置相关成绩(总分,主观分,客观分)
-			ExamStudentFinalScoreEntity finalExamScore = examStudentFinalScoreService
-					.getFinalEffectiveExamScore(examStudentId);
-			setFinalExamScore(examScoreInfo, finalExamScore);
-
-			if (finalExamScore != null) {
-				// 违纪未审核 存在最终分为空情况
-				examScoreInfo.setExamRecordDataId(finalExamScore.getExamRecordDataId());
-
-				if (!CollectionUtils.isEmpty(examRecordList)) {
-					for (ExamRecordDataEntity entity : examRecordList) {
-						if (Objects.equals(entity.getId(), finalExamScore.getExamRecordDataId())) {
-							examScoreInfo.setBasePaperId(entity.getBasePaperId());
-						}
-					}
-				}
-			}
-
-			// 需求调整20200923:将开考时间,改为最终成绩的更新时间
-			examScoreInfo.setStartTime(getExamStudentFinalScoreUpdateTime(finalExamScore));
-		} else {
-			examScoreInfo.setIsFinished("否");// 是否完成考试
-			examScoreInfo.setIsAbsent("是");// 是否缺考
-			examScoreInfo.setDisciplineCount("--");// 违纪次数
-			examScoreInfo.setSubmitCount("--"); // 提交次数
-			examScoreInfo.setObjectiveScore("--");// 主观分
-			examScoreInfo.setSubjectiveScore("--");// 客观分
-			examScoreInfo.setFinalExamScore("--");// 最终成绩
-			examScoreInfo.setStartTime("--");// 考试开始时间
-		}
-
-		return examScoreInfo;
-	}
-
-	/**
-	 * 给考生最终成绩赋值
-	 *
-	 * @param examScoreInfo 考试模型实体
-	 * @param examScore     考试数据实体
-	 */
-	private void setFinalExamScore(ExamScoreInfo examScoreInfo, final ExamStudentFinalScoreEntity examScore) {
-		if (examScore == null) {
-			examScoreInfo.setObjectiveScore("0");
-			examScoreInfo.setSubjectiveScore("0");
-			examScoreInfo.setFinalExamScore("0");
-		} else {
-			DecimalFormat decimalFormat = new DecimalFormat("#.##");
-			examScoreInfo.setObjectiveScore(
-					decimalFormat.format(null == examScore.getObjectiveScore() ? 0 : examScore.getObjectiveScore()));
-			examScoreInfo.setSubjectiveScore(
-					decimalFormat.format(null == examScore.getSubjectiveScore() ? 0 : examScore.getSubjectiveScore()));
-			examScoreInfo.setFinalExamScore(
-					decimalFormat.format(null == examScore.getTotalScore() ? 0 : examScore.getTotalScore()));
-		}
-	}
-
-	/**
-	 * 考试开始时间
-	 */
-	private String getExamStudentFinalScoreUpdateTime(ExamStudentFinalScoreEntity examScore) {
-		if (examScore == null || examScore.getUpdateTime() == null) {
-			return "";
-		}
-
-		return CommonUtil.getDateStrWithSecond(examScore.getUpdateTime());
-	}
-
-	/**
-	 * 违纪次数
-	 */
-	private String disciplineCount(List<ExamRecordDataEntity> examRecordList) {
-		Integer disciplineCount = 0;
-		if (examRecordList == null) {
-			return disciplineCount.toString();
-		}
-		for (ExamRecordDataEntity e : examRecordList) {
-			if (e.getIsIllegality() != null && e.getIsIllegality()) {
-				disciplineCount++;
-			}
-		}
-		return disciplineCount.toString();
-	}
-
-	/**
-	 * 正常交卷次数:无警告或者有警告,有审核,有正常提交时间
-	 */
-	private String submitCount(List<ExamRecordDataEntity> examRecordList) {
-		Integer submitCount = 0;
-		for (ExamRecordDataEntity e : examRecordList) {
-			if (e.getIsWarn() == null) {
-				e.setIsWarn(false);
-			}
-			if (e.getIsAudit() == null) {
-				e.setIsAudit(false);
-			}
-			if (e.getIsWarn() && !e.getIsAudit()) {
-				// ignore
-			} else {
-				if (e.getEndTime() != null) {
-					submitCount++;
-				}
-			}
-		}
-		return submitCount.toString();
-	}
-
-	private ExamStudentEntity getExamStudentEntityByResultSet(ResultSet rs) throws SQLException {
-		ExamStudentEntity examStudentEntity = new ExamStudentEntity();
-		examStudentEntity.setId(rs.getLong("id"));
-		examStudentEntity.setExamStudentId(rs.getLong("exam_student_id"));
-		examStudentEntity.setExamId(rs.getLong("exam_id"));
-		examStudentEntity.setCourseId(rs.getLong("course_id"));
-		examStudentEntity.setCourseCode(rs.getString("course_code"));
-		examStudentEntity.setCourseLevel(rs.getString("course_level"));
-		examStudentEntity.setFinished(rs.getBoolean("finished"));
-		examStudentEntity.setStudentId(rs.getLong("student_id"));
-		examStudentEntity.setStudentCode(rs.getString("student_code"));
-		examStudentEntity.setStudentName(rs.getString("student_name"));
-		examStudentEntity.setIdentityNumber(rs.getString("identity_number"));
-		examStudentEntity.setInfoCollector(rs.getString("info_collector"));
-		examStudentEntity.setRootOrgId(rs.getLong("root_org_id"));
-		examStudentEntity.setOrgId(rs.getLong("org_id"));
-		examStudentEntity.setPaperType(rs.getString("paper_type"));
-		examStudentEntity.setUsedNum(rs.getInt("used_num"));
-		examStudentEntity.setExtraNum(rs.getInt("extra_num"));
-		examStudentEntity.setSpecialtyCode(rs.getString("specialty_code"));
-		examStudentEntity.setSpecialtyName(rs.getString("specialty_name"));
-		examStudentEntity.setGrade(rs.getString("grade"));
-		if (rs.getString("exam_stage_id") != null) {
-			examStudentEntity.setExamStageId(rs.getLong("exam_stage_id"));
-		}
-		return examStudentEntity;
-	}
-
-	@Override
-	public void createExamScoreWithOffline(Long examRecordDataId) {
-		ExamScoreEntity examScoreEntity = new ExamScoreEntity();
-		examScoreEntity.setExamRecordDataId(examRecordDataId);
-		examScoreEntity.setObjectiveScore(0D);
-		examScoreEntity.setSubjectiveScore(0D);
-		examScoreEntity.setTotalScore(0D);
-		examScoreRepo.save(examScoreEntity);
-	}
-
-	@Override
-	public List<ObjectiveScoreInfo> queryObjectiveScoreList(Long examStudentId) {
-		Check.isNull(examStudentId, "examStudentId 不能为空");
-
-		List<ExamRecordDataEntity> examRecordDataList = examRecordDataRepo.findByExamStudentId(examStudentId);
-		// 过滤已完成的考试记录(包括违纪的)
-		examRecordDataList = examRecordDataList.stream().filter((o -> {
-			return o.getExamRecordStatus() == ExamRecordStatus.EXAM_END
-					|| o.getExamRecordStatus() == ExamRecordStatus.EXAM_OVERDUE
-					|| o.getExamRecordStatus() == ExamRecordStatus.EXAM_HAND_IN
-					|| o.getExamRecordStatus() == ExamRecordStatus.EXAM_AUTO_HAND_IN;
-		})).collect(Collectors.toList());
-
-		List<ObjectiveScoreInfo> objectiveScoreInfoList = new ArrayList<>();
-		for (ExamRecordDataEntity examRecordDataEntity : examRecordDataList) {
-			ObjectiveScoreInfo objectiveScoreInfo = new ObjectiveScoreInfo();
-			objectiveScoreInfo.setExamRecordDataId(examRecordDataEntity.getId());
-			objectiveScoreInfo.setExamOrder(examRecordDataEntity.getExamOrder());
-			objectiveScoreInfo.setStartTime(examRecordDataEntity.getStartTime());
-			objectiveScoreInfo.setEndTime(examRecordDataEntity.getEndTime());
-
-			// 如果考试没有结束,则只能返回部分数据
-			if (!isExamRecordEnded(examRecordDataEntity)) {
-				objectiveScoreInfo.setIsExamEnded(false);
-				objectiveScoreInfoList.add(objectiveScoreInfo);
-				continue;
-			} else {
-				objectiveScoreInfo.setIsExamEnded(true);
-			}
-
-			if (examRecordDataEntity.getIsIllegality() == null || !examRecordDataEntity.getIsIllegality()) {
-				if (examRecordDataEntity.getIsWarn() && !examRecordDataEntity.getIsAudit()) {
-					objectiveScoreInfo.setIsAuditing(true);
-				} else if (!examRecordDataEntity.getIsWarn()
-						|| (examRecordDataEntity.getIsWarn() && examRecordDataEntity.getIsAudit())) {
-					ExamScoreEntity examScore = examScoreRepo.findByExamRecordDataId(examRecordDataEntity.getId());
-					objectiveScoreInfo.setIsAuditing(false);
-					objectiveScoreInfo.setObjectiveScore(examScore.getObjectiveScore());
-				}
-				objectiveScoreInfo.setIsIllegality(false);
-			} else {
-				objectiveScoreInfo.setIsIllegality(true);
-			}
-			objectiveScoreInfoList.add(objectiveScoreInfo);
-		}
-
-		processObjectiveScoreList(examStudentId, objectiveScoreInfoList);
-
-		return objectiveScoreInfoList;
-	}
-
-	private void processObjectiveScoreList(Long examStudentId, List<ObjectiveScoreInfo> resultList) {
-		// 如果有未处理完成的考试记录,需要将未处理的考试记录数据添加到列表中
-		String examBossKey = RedisKeyHelper.getBuilder().examBossKey(examStudentId);
-		ExamBoss examBoss = redisClient.get(examBossKey, ExamBoss.class);
-		if (null != examBoss) {
-			// 未完全同步的考试记录id
-			List<Long> unSyncedExamRecordDataIds = examBoss.getExamRecordDataIds();
-			if (null != unSyncedExamRecordDataIds && !unSyncedExamRecordDataIds.isEmpty()) {
-				// 正序排列
-				unSyncedExamRecordDataIds.sort(Long::compareTo);
-
-				// 已考次数
-				Integer examUsedNum = 0;
-
-				for (Long examRecordDataId : unSyncedExamRecordDataIds) {
-					ExamRecordData examRecordData = redisClient
-							.get(RedisKeyHelper.getBuilder().examRecordDataKey(examRecordDataId), ExamRecordData.class);
-					if (null == examRecordData) {
-						throw new StatusException("100001", "考试记录的缓存数据有误");
-					}
-
-					// 考试中的数据不展示
-					if (cn.com.qmth.examcloud.support.enums.ExamRecordStatus.EXAM_ING == examRecordData
-							.getExamRecordStatus()) {
-						continue;
-					}
-
-					if (!resultList.isEmpty()) {
-						examUsedNum = resultList.get(resultList.size() - 1).getExamOrder();
-					}
-
-					ObjectiveScoreInfo cachedObjectiveScoreInfo = getCachedObjectiveScoreInfo(examRecordData);
-					cachedObjectiveScoreInfo.setExamOrder(
-							getExamOrder(examRecordData.getExamId(), examRecordData.getStudentId(), examUsedNum));
-
-					resultList.add(cachedObjectiveScoreInfo);
-				}
-			}
-		}
-	}
-
-	private ObjectiveScoreInfo getCachedObjectiveScoreInfo(final ExamRecordData examRecordData) {
-		ObjectiveScoreInfo objectiveScoreInfo = new ObjectiveScoreInfo();
-		objectiveScoreInfo.setExamRecordDataId(examRecordData.getId());
-		objectiveScoreInfo.setStartTime(examRecordData.getStartTime());
-		objectiveScoreInfo.setEndTime(examRecordData.getEndTime());
-
-		// 如果考试没有结束,则只能返回部分数据
-		if (!isExamRecordEnded(examRecordData)) {
-			objectiveScoreInfo.setIsExamEnded(false);
-			return objectiveScoreInfo;
-		} else {
-			objectiveScoreInfo.setIsExamEnded(true);
-		}
-
-		if (examRecordData.getIsIllegality() == null || !examRecordData.getIsIllegality()) {
-			if ((null != examRecordData.getIsWarn() && !examRecordData.getIsWarn())
-					|| (null != examRecordData.getIsWarn() && examRecordData.getIsWarn()
-							&& null != examRecordData.getIsAudit() && examRecordData.getIsAudit())) {
-				objectiveScoreInfo.setIsAuditing(true);
-
-				// 缓存中的分数是存储在临时考试记录表中的,所以需要从考试记录缓存中取
-				objectiveScoreInfo.setObjectiveScore(examRecordData.getObjectiveScore());
-			} else {
-				objectiveScoreInfo.setIsAuditing(false);
-			}
-
-			objectiveScoreInfo.setIsIllegality(false);
-		} else {
-			objectiveScoreInfo.setIsIllegality(true);
-		}
-
-		return objectiveScoreInfo;
-	}
-
-	/**
-	 * 计算考试次数
-	 *
-	 * @param examId      考试id
-	 * @param studentId   学生id
-	 * @param usedExamNum 已考次数
-	 * @return
-	 */
-	private Integer getExamOrder(Long examId, Long studentId, Integer usedExamNum) {
-		ExamSettingsCacheBean cachedExam = ExamCacheTransferHelper.getDefaultCachedExam(examId);
-		Integer canExamTimes = cachedExam.getExamTimes() == null ? 0 : cachedExam.getExamTimes().intValue();// 可考次数
-
-		// 超过可考次数,始终为可考次数+1
-		if (usedExamNum > canExamTimes) {
-			return canExamTimes + 1;
-		}
-
-		return usedExamNum + 1;
-	}
-
-	private boolean isExamRecordEnded(ExamRecordData examRecordData) {
-		// 如果考试记录状态为已处理,则直接返回true.
-		if (examRecordData.getExamRecordStatus() == cn.com.qmth.examcloud.support.enums.ExamRecordStatus.EXAM_END
-				|| examRecordData
-						.getExamRecordStatus() == cn.com.qmth.examcloud.support.enums.ExamRecordStatus.EXAM_OVERDUE
-				|| examRecordData
-						.getExamRecordStatus() == cn.com.qmth.examcloud.support.enums.ExamRecordStatus.EXAM_INVALID) {
-			return true;
-		}
-		return false;
-	}
-
-	private boolean isExamRecordEnded(ExamRecordDataEntity examRecordData) {
-		// 如果考试记录状态为已处理,则直接返回true.
-		if (examRecordData.getExamRecordStatus() == ExamRecordStatus.EXAM_END
-				|| examRecordData.getExamRecordStatus() == ExamRecordStatus.EXAM_OVERDUE
-				|| examRecordData.getExamRecordStatus() == ExamRecordStatus.EXAM_INVALID) {
-			return true;
-		}
-		return false;
-	}
-
-	@Override
-	public void updateCorrectAnswerAndReFixScore(Long examId, Long courseId, Long examStudentId) {
-		List<ExamRecordDataEntity> examRecordDataList = examRecordDataRepo
-				.findByExamIdAndCourseIdAndExamStudentId(examId, courseId, examStudentId);
-		if (CollectionUtils.isEmpty(examRecordDataList)) {
-			log.warn("updateCorrectAnswerAndReFixScore examRecordDataList is empty, examStudentId = {}", examStudentId);
-			return;
-		}
-
-		// Map<试题ID, 正确答案列表>
-		Map<String, List<String>> questionAnswerMaps = new HashMap<>();
-		boolean needUpdateFinalScore = false;
-
-		for (ExamRecordDataEntity examRecordData : examRecordDataList) {
-			if (ExamType.OFFLINE == examRecordData.getExamType()) {
-				// 离线考试,examRecordQuestions实际为空
-				continue;
-			}
-
-			ExamRecordQuestionsEntity examRecordQuestion = examRecordQuestionsService
-					.getExamRecordQuestionsAndFixExamRecordDataIfNecessary(examRecordData);
-			if (examRecordQuestion == null) {
-				log.warn("updateCorrectAnswerAndReFixScore examRecordQuestions is null, examRecordDataId = {}",
-						examRecordData.getId());
-				continue;
-			}
-
-			// 所有客观题的试题ID列表
-			List<ExamQuestionEntity> examQuestions = examRecordQuestion.getExamQuestionEntities();
-			Set<String> objectiveQuestionIds = examQuestions.stream()
-					.filter(e -> QuestionType.isObjective(e.getQuestionType())).map(ExamQuestionEntity::getQuestionId)
-					.collect(Collectors.toSet());
-
-			double objectiveScore = 0d; // 客观题得分
-			int totalObjective = 0; // 客观题总数
-			int totalRightObjective = 0; // 客观题作答正确数
-			boolean needUpdateExamRecordQuestions = false;
-
-			for (String curQuestionId : objectiveQuestionIds) {
-				// 按题号由小到大提取相同题ID的小题列表(注:套题的子题ID相同)
-				List<ExamQuestionEntity> questionUnits = examQuestions.stream()
-						.filter(e -> e.getQuestionId().equals(curQuestionId))
-						.sorted(Comparator.comparingInt(ExamQuestionEntity::getOrder)).collect(Collectors.toList());
-
-				for (ExamQuestionEntity e : questionUnits) {
-					if (QuestionType.isObjective(e.getQuestionType())) {
-						totalObjective++;
-					}
-				}
-
-				// 获取当前题的正确答案
-				List<String> rightAnswers;
-				if (questionAnswerMaps.containsKey(curQuestionId)) {
-					rightAnswers = questionAnswerMaps.get(curQuestionId);
-				} else {
-					QuestionAnswerCacheBean questionAnswer = CacheHelper.getQuestionAnswer(curQuestionId);
-					rightAnswers = questionAnswer.getRightAnswers();
-					questionAnswerMaps.put(curQuestionId, rightAnswers);
-				}
-
-				if (CollectionUtils.isEmpty(rightAnswers)) {
-					log.warn("updateCorrectAnswerAndReFixScore rightAnswers is empty, questionId = {}", curQuestionId);
-					continue;
-				}
-
-				if (questionUnits.size() != rightAnswers.size()) {
-					log.warn("updateCorrectAnswerAndReFixScore rightAnswers incorrect, questionId = {}", curQuestionId);
-					continue;
-				}
-
-				for (int i = 0; i < questionUnits.size(); i++) {
-					ExamQuestionEntity curQuestion = questionUnits.get(i);
-					if (!QuestionType.isObjective(curQuestion.getQuestionType())) {
-						// 跳过套题内主观题
-						continue;
-					}
-
-					// 答案不一致,则更新
-					String rightAnswer = rightAnswers.get(i);
-					if (rightAnswer != null && !rightAnswer.equals(curQuestion.getCorrectAnswer())) {
-						curQuestion.setCorrectAnswer(rightAnswer);
-						needUpdateExamRecordQuestions = true;
-					}
-
-					// 计算得分
-					String correctAnswer = curQuestion.getCorrectAnswer();
-					String studentAnswer = curQuestion.getStudentAnswer();
-					// if (correctAnswer != null &&
-					// QuestionOptionHelper.isEqualAnswer(correctAnswer, studentAnswer)) {
-					if (correctAnswer != null && correctAnswer.equals(studentAnswer)) {
-						objectiveScore += curQuestion.getQuestionScore();
-						totalRightObjective++;
-					}
-				}
-			}
-
-			if (needUpdateExamRecordQuestions) {
-				needUpdateFinalScore = true;
-
-				examRecordQuestionsRepo.save(examRecordQuestion);
-
-				ExamScoreEntity examScore = examScoreRepo.findByExamRecordDataId(examRecordData.getId());
-				if (examScore != null) {
-					double subjectiveScore = examScore.getSubjectiveScore() != null ? examScore.getSubjectiveScore()
-							: 0d;
-
-					double objectiveAccuracy = 0d;// 客观题正确率
-					if (totalObjective > 0) {
-						objectiveAccuracy = totalRightObjective * 100d / totalObjective;
-						objectiveAccuracy = Double.parseDouble(new DecimalFormat("#.00").format(objectiveAccuracy));
-					}
-
-					examScore.setObjectiveScore(objectiveScore);
-					examScore.setObjectiveAccuracy(objectiveAccuracy);
-					examScore.setTotalScore(objectiveScore + subjectiveScore);
-					examScoreRepo.save(examScore);
-				}
-
-				ExamRecordForMarkingEntity examRecordForMarking = examRecordForMarkingRepo
-						.findByExamRecordDataId(examRecordData.getId());
-				if (examRecordForMarking != null) {
-					examRecordForMarking.setObjectiveScore(objectiveScore);
-					examRecordForMarkingRepo.save(examRecordForMarking);
-				}
-
-				log.info("updateCorrectAnswerAndReFixScore examRecordQuestions examRecordDataId = {}",
-						examRecordData.getId());
-			}
-		}
-
-		if (needUpdateFinalScore) {
-			examStudentFinalScoreService.calcAndSaveFinalScore(examStudentId);
-			log.info("updateCorrectAnswerAndReFixScore finalScore examStudentId = {}", examStudentId);
-		}
-	}
+
+    @Autowired
+    private ExamScoreRepo examScoreRepo;
+
+    @Autowired
+    private ExamRecordDataRepo examRecordDataRepo;
+
+    @Autowired
+    private ExamRecordQuestionsRepo examRecordQuestionsRepo;
+
+    @Autowired
+    private ExamRecordForMarkingRepo examRecordForMarkingRepo;
+
+    @Autowired
+    private ExamRecordQuestionsService examRecordQuestionsService;
+
+    @Autowired
+    private ExamStudentService examStudentService;
+
+    @Autowired
+    private ExamRecordService examRecordService;
+
+    @Autowired
+    private GainBaseDataService gainBaseDataService;
+
+    @Autowired
+    private JdbcTemplate jdbcTemplate;
+
+    @Autowired
+    private RedisClient redisClient;
+
+    @Autowired
+    private ExamStudentFinalScoreService examStudentFinalScoreService;
+
+    @Override
+    public Page<ExamScoreInfo> getExamScoreList(UserDataRules uds, ExamScoreQuery query) {
+        Check.isNull(query, "查询参数不能为空!");
+        Check.isNull(query.getExamId(), "请先选择考试批次!");
+        Pageable pageable = SpecUtils.buildPageable(query.getPageNo(), query.getPageSize());
+
+        // 阅卷方式
+        String markingType = ExamCacheTransferHelper
+                .getDefaultCachedExamProperty(query.getExamId(), ExamProperties.MARKING_TYPE.name()).getValue();
+
+        // 获取考生列表
+        Page<ExamStudentInfo> page = examStudentService.getExamStudentListPage(uds, ExamScoreEntityConvert.of(query));
+        List<ExamStudentInfo> examStudentList = page.getContent();
+        if (examStudentList == null || examStudentList.size() == 0) {
+            return new PageImpl<ExamScoreInfo>(Lists.newArrayList(), pageable, page.getTotalElements());
+        }
+
+        // 封装成绩统计结果
+        List<ExamScoreInfo> examScoreList = new ArrayList<>();
+        examStudentList.forEach(examStudent -> {
+            // 获取考试信息
+            ExamSettingsCacheBean examBean = ExamCacheTransferHelper.getDefaultCachedExam(query.getExamId());
+            examScoreList.add(of(examStudent, examBean, markingType));
+        });
+        fillStage(examScoreList);
+        return new PageImpl<ExamScoreInfo>(examScoreList, pageable, page.getTotalElements());
+    }
+
+    private void fillStage(List<ExamScoreInfo> list) {
+        if (CollectionUtils.isEmpty(list)) {
+            return;
+        }
+        for (ExamScoreInfo 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 void fillStage(List<ExamScoreInfo> list, Long taskId) {
+        if (CollectionUtils.isEmpty(list)) {
+            return;
+        }
+        for (ExamScoreInfo info : list) {
+            exportTaskService.checkStopExportTaskById(taskId);
+            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 ExamScoreInfo of(ExamStudentInfo examStudent, ExamSettingsCacheBean examBean, String markingType) {
+        ExamScoreInfo examScore = new ExamScoreInfo();
+        examScore.setExamId(examStudent.getExamId());
+        examScore.setExamName(examBean.getName());
+        examScore.setStudentId(examStudent.getStudentId());
+        examScore.setStudentCode(examStudent.getStudentCode());
+        examScore.setStudentName(examStudent.getStudentName());
+        examScore.setIdentityNumber(examStudent.getIdentityNumber());
+
+        examScore.setCourseId(examStudent.getCourseId());
+        examScore.setCourseCode(examStudent.getCourseCode());
+        examScore.setCourseName(examStudent.getCourseName());
+        examScore.setCourseNameAndCode(examStudent.getCourseName() + "(" + examStudent.getCourseCode() + ")");
+        examScore.setCourseLevel(CourseLevel.getCourseLevelTitle(examStudent.getCourseLevel()));
+
+        examScore.setOrgId(examStudent.getOrgId());
+        examScore.setOrgCode(examStudent.getOrgCode());
+        examScore.setOrgName(examStudent.getOrgName());
+        examScore.setInfoCollector(examStudent.getInfoCollector());
+        examScore.setSpecialtyName(examStudent.getSpecialtyName());
+        examScore.setGrade(examStudent.getGrade());
+        examScore.setExamStageId(examStudent.getExamStageId());
+        Long examTimes = examBean.getExamTimes();
+        if (examTimes != null) {
+            Integer extraExamNum = examStudent.getExtraNum() == null ? 0 : examStudent.getExtraNum();
+            Integer usedNum = examStudent.getUsedNum() == null ? 0 : examStudent.getUsedNum();
+            Long leftExamTimes = (examTimes + extraExamNum - usedNum) < 0 ? 0 : (examTimes + extraExamNum - usedNum);
+            examScore.setLeftExamTimes(leftExamTimes);
+        }
+        return setCommomScoreInfo(examScore, examStudent.getFinished(), examStudent.getExamStudentId(), examBean,
+                markingType);
+    }
+
+    @Override
+    public List<ExamScoreInfo> exportExamScoreListForAsync(UserDataRules uds, ExamScoreQuery query) {
+        if (uds.getCourseRule().assertEmptyQueryResult() || uds.getOrgRule().assertEmptyQueryResult()) {
+            return Lists.newArrayList();
+        }
+        Check.isNull(query, "查询参数不能为空!");
+        Check.isNull(query.getExamId(), "请先选择考试批次!");
+
+        // 阅卷方式
+        String markingType = ExamCacheTransferHelper
+                .getDefaultCachedExamProperty(query.getExamId(), ExamProperties.MARKING_TYPE.name()).getValue();
+        //        if (query.getStartLimit() != null && query.getEndLimit() != null) {
+        //            return getExamStudentInfoListOfScoreExport(uds, query, markingType);
+        //        } else {
+        List<ExamScoreInfo> examScoreInfoList = new ArrayList<ExamScoreInfo>();
+        List<Long> ids = getExamStudentInfoListOfScoreExportByPageOnlyId(uds, query, markingType);
+        if (CollectionUtils.isEmpty(ids)) {
+            return examScoreInfoList;
+        }
+        List<ExamStudentEntity> examStudentList = new BatchGetDataUtil<ExamStudentEntity, Long>() {
+
+            @Override
+            protected List<ExamStudentEntity> getData(List<Long> paramList) {
+                exportTaskService.checkStopExportTaskById(query.getTaskId());
+                return getExamStudentInfoListOfScoreExportByPage(uds, query, markingType, paramList);
+            }
+        }.getDataForBatch(ids, 1000);
+
+        if (CollectionUtils.isEmpty(examStudentList)) {
+            return examScoreInfoList;
+        }
+
+        // 缓存
+        for (ExamStudentEntity examStudent : examStudentList) {
+            exportTaskService.checkStopExportTaskById(query.getTaskId());
+            long courseId = examStudent.getCourseId();
+            CourseCacheBean courseBean = ExamCacheTransferHelper.getCachedCourse(courseId);
+
+            long orgId = examStudent.getOrgId();
+            OrgCacheBean orgBean = gainBaseDataService.getOrgBean(orgId);
+
+            examScoreInfoList.add(convertToExamScoreInfo(examStudent, courseBean, orgBean, markingType));
+        }
+        fillStage(examScoreInfoList, query.getTaskId());
+        return examScoreInfoList;
+        //        }
+    }
+
+    private List<ExamStudentEntity> getExamStudentInfoListOfScoreExportByPage(UserDataRules uds, ExamScoreQuery query,
+                                                                              String markingType, List<Long> ids) {
+        // 查询条件
+        StringBuffer sql = new StringBuffer();
+        sql.append(
+                "select id,exam_student_id,exam_id,course_id,course_code,course_level,finished,student_id,student_code,student_name,identity_number"
+                        + ",info_collector,root_org_id,org_id,paper_type,used_num,extra_num"
+                        + ",specialty_code,specialty_name,grade,exam_stage_id from ec_oe_exam_student where id in ( ");
+        sql.append(StringUtils.join(ids, ","));
+        sql.append(" )");
+
+        List<ExamStudentEntity> examStudentList = jdbcTemplate.query(sql.toString(),
+                new RowMapper<ExamStudentEntity>() {
+                    @Override
+                    public ExamStudentEntity mapRow(ResultSet rs, int rowNum) throws SQLException {
+                        return getExamStudentEntityByResultSet(rs);
+                    }
+                });
+
+        return examStudentList;
+    }
+
+    private List<Long> getExamStudentInfoListOfScoreExportByPageOnlyId(UserDataRules uds, ExamScoreQuery query,
+                                                                       String markingType) {
+        // 查询条件
+        StringBuffer sql = new StringBuffer();
+        sql.append("select id from ec_oe_exam_student where 1=1 ");
+        if (query.getOrgId() != null) {
+            sql.append(" and org_id=" + query.getOrgId());
+        }
+        if (query.getExamId() != null) {
+            sql.append(" and exam_id=" + query.getExamId());
+        }
+        if (query.getExamStageId() != null) {
+            sql.append(" and exam_stage_id=" + query.getExamStageId());
+        }
+        if (StringUtils.isNotBlank(query.getStudentCode())) {
+            sql.append(" and student_code LIKE '" + query.getStudentCode() + "%'");
+        }
+        if (StringUtils.isNotBlank(query.getStudentName())) {
+            sql.append(" and student_name LIKE '" + query.getStudentName() + "%'");
+        }
+        if (StringUtils.isNotBlank(query.getIdentityNumber())) {
+            sql.append(" and identity_number LIKE '" + query.getIdentityNumber() + "%'");
+        }
+        if (query.getCourseId() != null) {
+            sql.append(" and course_id=" + query.getCourseId());
+        }
+        if (StringUtils.isNotBlank(query.getCourseLevel())) {
+            sql.append(" and course_level= '" + query.getCourseLevel() + "'");
+        }
+        if (query.getFinished() != null) {
+            sql.append(" and finished= " + query.getFinished());
+        }
+        if (uds.getOrgRule().assertNeedQueryRefIds()) {
+            sql.append(" and org_id in (" + StringUtils.join(uds.getOrgRule().getRefIds(), ",") + ") ");
+        }
+        if (uds.getCourseRule().assertNeedQueryRefIds()) {
+            sql.append(" and course_id in (" + StringUtils.join(uds.getCourseRule().getRefIds(), ",") + ") ");
+        }
+
+        List<Long> examStudentList = jdbcTemplate.queryForList(sql.toString(), Long.class);
+
+        return examStudentList;
+    }
+
+    // @Override
+    // public List<ExamScoreInfo> exportExamScoreList(ExamScoreQuery query) {
+    // Check.isNull(query, "查询参数不能为空!");
+    // Check.isNull(query.getExamId(), "请先选择考试批次!");
+    //
+    // //阅卷方式
+    // String markingType = ExamCacheTransferHelper.
+    // getDefaultCachedExamProperty(query.getExamId(),
+    // ExamProperties.MARKING_TYPE.name()).getValue();
+    // return getExamStudentInfoListOfScoreExport(query, markingType);
+    // }
+
+    @Override
+    public List<ExamScoreEntity> getAllExamScoreList(Long examId, String identityNumber, Long courseId) {
+        List<ExamRecordDataEntity> allExamRecordDataList = examRecordDataRepo
+                .findByExamIdAndIdentityNumberAndCourseId(examId, identityNumber, courseId);
+        if (allExamRecordDataList == null || allExamRecordDataList.isEmpty()) {
+            return null;
+        }
+
+        List<Long> examRecordDataIds = allExamRecordDataList.stream().map(p -> p.getId()).collect(Collectors.toList());
+        return examScoreRepo.findByExamRecordDataIdIn(examRecordDataIds);
+    }
+
+    //    private List<ExamScoreInfo> getExamStudentInfoListOfScoreExport(UserDataRules uds, ExamScoreQuery query, String markingType) {
+    //        Check.isNull(query, "查询参数不能为空!");
+    //        //查询条件
+    //        StringBuffer sql = new StringBuffer();
+    //        sql.append("select id,exam_student_id,exam_id,course_id,course_code,course_level,finished,student_id,student_code,student_name,identity_number"
+    //                + ",info_collector,root_org_id,org_id,paper_type,used_num,extra_num"
+    //                + ",specialty_code,specialty_name,grade,exam_stage_id from ec_oe_exam_student where 1=1 ");
+    //        if (query.getOrgId() != null) {
+    //            sql.append(" and org_id=" + query.getOrgId());
+    //        }
+    //        if (query.getExamId() != null) {
+    //            sql.append(" and exam_id=" + query.getExamId());
+    //        }
+    //        if (query.getExamStageId() != null) {
+    //            sql.append(" and exam_stage_id=" + query.getExamStageId());
+    //        }
+    //        if (StringUtils.isNotBlank(query.getStudentCode())) {
+    //            sql.append(" and student_code LIKE '" + query.getStudentCode() + "%'");
+    //        }
+    //        if (StringUtils.isNotBlank(query.getStudentName())) {
+    //            sql.append(" and student_name LIKE '" + query.getStudentName() + "%'");
+    //        }
+    //        if (StringUtils.isNotBlank(query.getIdentityNumber())) {
+    //            sql.append(" and identity_number LIKE '" + query.getIdentityNumber() + "%'");
+    //        }
+    //        if (query.getCourseId() != null) {
+    //            sql.append(" and course_id=" + query.getCourseId());
+    //        }
+    //        if (StringUtils.isNotBlank(query.getCourseLevel())) {
+    //            sql.append(" and course_level= '" + query.getCourseLevel() + "'");
+    //        }
+    //        if (query.getFinished() != null) {
+    //            sql.append(" and finished= " + query.getFinished());
+    //        }
+    //        if (uds.getOrgRule().assertNeedQueryRefIds()) {
+    //            sql.append(" and org_id in (" + StringUtils.join(uds.getOrgRule().getRefIds(), ",") + ") ");
+    //        }
+    //        if (uds.getCourseRule().assertNeedQueryRefIds()) {
+    //            sql.append(" and course_id in (" + StringUtils.join(uds.getCourseRule().getRefIds(), ",") + ") ");
+    //        }
+    //        sql.append(" order by id");
+    //
+    //        if (query.getStartLimit() != null && query.getEndLimit() != null) {
+    //            int offset = query.getEndLimit() - query.getStartLimit() + 1;
+    //            sql.append(" limit " + (query.getStartLimit() - 1) + "," + offset);
+    //        }
+    //        List<ExamStudentEntity> examStudentList = jdbcTemplate.query(sql.toString(), new RowMapper<ExamStudentEntity>() {
+    //            @Override
+    //            public ExamStudentEntity mapRow(ResultSet rs, int rowNum) throws SQLException {
+    //                return getExamStudentEntityByResultSet(rs);
+    //            }
+    //        });
+    //
+    //        List<ExamScoreInfo> examScoreInfoList = new ArrayList<ExamScoreInfo>();
+    //        //缓存
+    //        for (ExamStudentEntity examStudent : examStudentList) {
+    //            long courseId = examStudent.getCourseId();
+    //            CourseCacheBean courseBean = ExamCacheTransferHelper.getCachedCourse(courseId);
+    //
+    //            long orgId = examStudent.getOrgId();
+    //            OrgCacheBean orgBean = gainBaseDataService.getOrgBean(orgId);
+    //
+    //            examScoreInfoList.add(convertToExamScoreInfo(examStudent, courseBean, orgBean, markingType));
+    //        }
+    //        fillStage(examScoreInfoList);
+    //        return examScoreInfoList;
+    //    }
+
+    private ExamScoreInfo convertToExamScoreInfo(ExamStudentEntity examStudent, CourseCacheBean courseBean,
+                                                 OrgCacheBean orgBean, String markingType) {
+        if (examStudent == null) {
+            return null;
+        }
+        // 获取考试信息
+        ExamSettingsCacheBean examBean = ExamCacheTransferHelper.getCachedExam(examStudent.getExamId(),
+                examStudent.getStudentId(), examStudent.getExamStageId());
+        ExamScoreInfo examScore = new ExamScoreInfo();
+        examScore.setExamStageId(examStudent.getExamStageId());
+        examScore.setExamId(examStudent.getExamId());
+        examScore.setExamName(examBean.getName());
+        examScore.setStudentId(examStudent.getStudentId());
+        examScore.setStudentCode(examStudent.getStudentCode());
+        examScore.setStudentName(examStudent.getStudentName());
+        examScore.setIdentityNumber(examStudent.getIdentityNumber());
+        examScore.setInfoCollector(examStudent.getInfoCollector());
+
+        examScore.setCourseId(examStudent.getCourseId());
+        examScore.setCourseCode(examStudent.getCourseCode());
+        examScore.setCourseName(courseBean.getName());
+        examScore.setCourseNameAndCode(courseBean.getName() + "(" + courseBean.getCode() + ")");
+        examScore.setCourseLevel(CourseLevel.getCourseLevelTitle(examStudent.getCourseLevel()));
+
+        examScore.setOrgId(examStudent.getOrgId());
+        examScore.setOrgCode(orgBean.getCode());
+        examScore.setOrgName(orgBean.getName());
+
+        examScore.setSpecialtyName(examStudent.getSpecialtyName());
+        examScore.setGrade(examStudent.getGrade());
+
+        // 剩余考试次数=可考次数+可重考次数-已考次数
+        Long examTimes = examBean.getExamTimes();
+        if (examTimes != null) {
+            Integer extraExamNum = examStudent.getExtraNum() == null ? 0 : examStudent.getExtraNum();
+            Integer usedNum = examStudent.getUsedNum() == null ? 0 : examStudent.getUsedNum();
+            Long leftExamTimes = (examTimes + extraExamNum - usedNum) < 0 ? 0 : (examTimes + extraExamNum - usedNum);
+            examScore.setLeftExamTimes(leftExamTimes);
+        }
+
+        return setCommomScoreInfo(examScore, examStudent.getFinished(), examStudent.getExamStudentId(), examBean,
+                markingType);
+    }
+
+    private ExamScoreInfo setCommomScoreInfo(ExamScoreInfo examScoreInfo, Boolean finished, long examStudentId,
+                                             ExamSettingsCacheBean examBean, String markingType) {
+        // 查询考试记录
+        if (finished != null && finished) {
+            // 查询考试记录
+            List<ExamRecordDataEntity> examRecordList = examRecordService
+                    .getExamRecordListByExamStudentId(examStudentId);
+            examScoreInfo.setIsFinished("是");// 是否完成考试
+            examScoreInfo.setIsAbsent("否");// 是否缺考
+            // 违纪次数
+            examScoreInfo.setDisciplineCount(disciplineCount(examRecordList));
+            // 提交次数
+            examScoreInfo.setSubmitCount(submitCount(examRecordList));
+
+            // 设置相关成绩(总分,主观分,客观分)
+            ExamStudentFinalScoreEntity finalExamScore = examStudentFinalScoreService
+                    .getFinalEffectiveExamScore(examStudentId);
+            setFinalExamScore(examScoreInfo, finalExamScore);
+
+            if (finalExamScore != null) {
+                // 违纪未审核 存在最终分为空情况
+                examScoreInfo.setExamRecordDataId(finalExamScore.getExamRecordDataId());
+
+                if (!CollectionUtils.isEmpty(examRecordList)) {
+                    for (ExamRecordDataEntity entity : examRecordList) {
+                        if (Objects.equals(entity.getId(), finalExamScore.getExamRecordDataId())) {
+                            examScoreInfo.setBasePaperId(entity.getBasePaperId());
+                        }
+                    }
+                }
+            }
+
+            // 需求调整20200923:将开考时间,改为最终成绩的更新时间
+            examScoreInfo.setStartTime(getExamStudentFinalScoreUpdateTime(finalExamScore));
+        } else {
+            examScoreInfo.setIsFinished("否");// 是否完成考试
+            examScoreInfo.setIsAbsent("是");// 是否缺考
+            examScoreInfo.setDisciplineCount("--");// 违纪次数
+            examScoreInfo.setSubmitCount("--"); // 提交次数
+            examScoreInfo.setObjectiveScore("--");// 主观分
+            examScoreInfo.setSubjectiveScore("--");// 客观分
+            examScoreInfo.setFinalExamScore("--");// 最终成绩
+            examScoreInfo.setStartTime("--");// 考试开始时间
+        }
+
+        return examScoreInfo;
+    }
+
+    /**
+     * 给考生最终成绩赋值
+     *
+     * @param examScoreInfo 考试模型实体
+     * @param examScore     考试数据实体
+     */
+    private void setFinalExamScore(ExamScoreInfo examScoreInfo, final ExamStudentFinalScoreEntity examScore) {
+        if (examScore == null) {
+            examScoreInfo.setObjectiveScore("0");
+            examScoreInfo.setSubjectiveScore("0");
+            examScoreInfo.setFinalExamScore("0");
+        } else {
+            DecimalFormat decimalFormat = new DecimalFormat("#.##");
+            examScoreInfo.setObjectiveScore(
+                    decimalFormat.format(null == examScore.getObjectiveScore() ? 0 : examScore.getObjectiveScore()));
+            examScoreInfo.setSubjectiveScore(
+                    decimalFormat.format(null == examScore.getSubjectiveScore() ? 0 : examScore.getSubjectiveScore()));
+            examScoreInfo.setFinalExamScore(
+                    decimalFormat.format(null == examScore.getTotalScore() ? 0 : examScore.getTotalScore()));
+        }
+    }
+
+    /**
+     * 考试开始时间
+     */
+    private String getExamStudentFinalScoreUpdateTime(ExamStudentFinalScoreEntity examScore) {
+        if (examScore == null || examScore.getUpdateTime() == null) {
+            return "";
+        }
+
+        return CommonUtil.getDateStrWithSecond(examScore.getUpdateTime());
+    }
+
+    /**
+     * 违纪次数
+     */
+    private String disciplineCount(List<ExamRecordDataEntity> examRecordList) {
+        Integer disciplineCount = 0;
+        if (examRecordList == null) {
+            return disciplineCount.toString();
+        }
+        for (ExamRecordDataEntity e : examRecordList) {
+            if (e.getIsIllegality() != null && e.getIsIllegality()) {
+                disciplineCount++;
+            }
+        }
+        return disciplineCount.toString();
+    }
+
+    /**
+     * 正常交卷次数:无警告或者有警告,有审核,有正常提交时间
+     */
+    private String submitCount(List<ExamRecordDataEntity> examRecordList) {
+        Integer submitCount = 0;
+        for (ExamRecordDataEntity e : examRecordList) {
+            if (e.getIsWarn() == null) {
+                e.setIsWarn(false);
+            }
+            if (e.getIsAudit() == null) {
+                e.setIsAudit(false);
+            }
+            if (e.getIsWarn() && !e.getIsAudit()) {
+                // ignore
+            } else {
+                if (e.getEndTime() != null) {
+                    submitCount++;
+                }
+            }
+        }
+        return submitCount.toString();
+    }
+
+    private ExamStudentEntity getExamStudentEntityByResultSet(ResultSet rs) throws SQLException {
+        ExamStudentEntity examStudentEntity = new ExamStudentEntity();
+        examStudentEntity.setId(rs.getLong("id"));
+        examStudentEntity.setExamStudentId(rs.getLong("exam_student_id"));
+        examStudentEntity.setExamId(rs.getLong("exam_id"));
+        examStudentEntity.setCourseId(rs.getLong("course_id"));
+        examStudentEntity.setCourseCode(rs.getString("course_code"));
+        examStudentEntity.setCourseLevel(rs.getString("course_level"));
+        examStudentEntity.setFinished(rs.getBoolean("finished"));
+        examStudentEntity.setStudentId(rs.getLong("student_id"));
+        examStudentEntity.setStudentCode(rs.getString("student_code"));
+        examStudentEntity.setStudentName(rs.getString("student_name"));
+        examStudentEntity.setIdentityNumber(rs.getString("identity_number"));
+        examStudentEntity.setInfoCollector(rs.getString("info_collector"));
+        examStudentEntity.setRootOrgId(rs.getLong("root_org_id"));
+        examStudentEntity.setOrgId(rs.getLong("org_id"));
+        examStudentEntity.setPaperType(rs.getString("paper_type"));
+        examStudentEntity.setUsedNum(rs.getInt("used_num"));
+        examStudentEntity.setExtraNum(rs.getInt("extra_num"));
+        examStudentEntity.setSpecialtyCode(rs.getString("specialty_code"));
+        examStudentEntity.setSpecialtyName(rs.getString("specialty_name"));
+        examStudentEntity.setGrade(rs.getString("grade"));
+        if (rs.getString("exam_stage_id") != null) {
+            examStudentEntity.setExamStageId(rs.getLong("exam_stage_id"));
+        }
+        return examStudentEntity;
+    }
+
+    @Override
+    public void createExamScoreWithOffline(Long examRecordDataId) {
+        ExamScoreEntity examScoreEntity = new ExamScoreEntity();
+        examScoreEntity.setExamRecordDataId(examRecordDataId);
+        examScoreEntity.setObjectiveScore(0D);
+        examScoreEntity.setSubjectiveScore(0D);
+        examScoreEntity.setTotalScore(0D);
+        examScoreRepo.save(examScoreEntity);
+    }
+
+    @Override
+    public List<ObjectiveScoreInfo> queryObjectiveScoreList(Long examStudentId) {
+        Check.isNull(examStudentId, "examStudentId 不能为空");
+
+        List<ExamRecordDataEntity> examRecordDataList = examRecordDataRepo.findByExamStudentId(examStudentId);
+        // 过滤已完成的考试记录(包括违纪的)
+        examRecordDataList = examRecordDataList.stream().filter((o -> {
+            return o.getExamRecordStatus() == ExamRecordStatus.EXAM_END
+                    || o.getExamRecordStatus() == ExamRecordStatus.EXAM_OVERDUE
+                    || o.getExamRecordStatus() == ExamRecordStatus.EXAM_HAND_IN
+                    || o.getExamRecordStatus() == ExamRecordStatus.EXAM_AUTO_HAND_IN;
+        })).collect(Collectors.toList());
+
+        List<ObjectiveScoreInfo> objectiveScoreInfoList = new ArrayList<>();
+        for (ExamRecordDataEntity examRecordDataEntity : examRecordDataList) {
+            ObjectiveScoreInfo objectiveScoreInfo = new ObjectiveScoreInfo();
+            objectiveScoreInfo.setExamRecordDataId(examRecordDataEntity.getId());
+            objectiveScoreInfo.setExamOrder(examRecordDataEntity.getExamOrder());
+            objectiveScoreInfo.setStartTime(examRecordDataEntity.getStartTime());
+            objectiveScoreInfo.setEndTime(examRecordDataEntity.getEndTime());
+
+            // 如果考试没有结束,则只能返回部分数据
+            if (!isExamRecordEnded(examRecordDataEntity)) {
+                objectiveScoreInfo.setIsExamEnded(false);
+                objectiveScoreInfoList.add(objectiveScoreInfo);
+                continue;
+            } else {
+                objectiveScoreInfo.setIsExamEnded(true);
+            }
+
+            if (examRecordDataEntity.getIsIllegality() == null || !examRecordDataEntity.getIsIllegality()) {
+                if (examRecordDataEntity.getIsWarn() && !examRecordDataEntity.getIsAudit()) {
+                    objectiveScoreInfo.setIsAuditing(true);
+                } else if (!examRecordDataEntity.getIsWarn()
+                        || (examRecordDataEntity.getIsWarn() && examRecordDataEntity.getIsAudit())) {
+                    ExamScoreEntity examScore = examScoreRepo.findByExamRecordDataId(examRecordDataEntity.getId());
+                    objectiveScoreInfo.setIsAuditing(false);
+                    objectiveScoreInfo.setObjectiveScore(examScore.getObjectiveScore());
+                }
+                objectiveScoreInfo.setIsIllegality(false);
+            } else {
+                objectiveScoreInfo.setIsIllegality(true);
+            }
+            objectiveScoreInfoList.add(objectiveScoreInfo);
+        }
+
+        processObjectiveScoreList(examStudentId, objectiveScoreInfoList);
+
+        return objectiveScoreInfoList;
+    }
+
+    private void processObjectiveScoreList(Long examStudentId, List<ObjectiveScoreInfo> resultList) {
+        // 如果有未处理完成的考试记录,需要将未处理的考试记录数据添加到列表中
+        String examBossKey = RedisKeyHelper.getBuilder().examBossKey(examStudentId);
+        ExamBoss examBoss = redisClient.get(examBossKey, ExamBoss.class);
+        if (null != examBoss) {
+            // 未完全同步的考试记录id
+            List<Long> unSyncedExamRecordDataIds = examBoss.getExamRecordDataIds();
+            if (null != unSyncedExamRecordDataIds && !unSyncedExamRecordDataIds.isEmpty()) {
+                // 正序排列
+                unSyncedExamRecordDataIds.sort(Long::compareTo);
+
+                // 已考次数
+                Integer examUsedNum = 0;
+
+                for (Long examRecordDataId : unSyncedExamRecordDataIds) {
+                    ExamRecordData examRecordData = redisClient
+                            .get(RedisKeyHelper.getBuilder().examRecordDataKey(examRecordDataId), ExamRecordData.class);
+                    if (null == examRecordData) {
+                        throw new StatusException("100001", "考试记录的缓存数据有误");
+                    }
+
+                    // 考试中的数据不展示
+                    if (cn.com.qmth.examcloud.support.enums.ExamRecordStatus.EXAM_ING == examRecordData
+                            .getExamRecordStatus()) {
+                        continue;
+                    }
+
+                    if (!resultList.isEmpty()) {
+                        examUsedNum = resultList.get(resultList.size() - 1).getExamOrder();
+                    }
+
+                    ObjectiveScoreInfo cachedObjectiveScoreInfo = getCachedObjectiveScoreInfo(examRecordData);
+                    cachedObjectiveScoreInfo.setExamOrder(
+                            getExamOrder(examRecordData.getExamId(), examRecordData.getStudentId(), examUsedNum));
+
+                    resultList.add(cachedObjectiveScoreInfo);
+                }
+            }
+        }
+    }
+
+    private ObjectiveScoreInfo getCachedObjectiveScoreInfo(final ExamRecordData examRecordData) {
+        ObjectiveScoreInfo objectiveScoreInfo = new ObjectiveScoreInfo();
+        objectiveScoreInfo.setExamRecordDataId(examRecordData.getId());
+        objectiveScoreInfo.setStartTime(examRecordData.getStartTime());
+        objectiveScoreInfo.setEndTime(examRecordData.getEndTime());
+
+        // 如果考试没有结束,则只能返回部分数据
+        if (!isExamRecordEnded(examRecordData)) {
+            objectiveScoreInfo.setIsExamEnded(false);
+            return objectiveScoreInfo;
+        } else {
+            objectiveScoreInfo.setIsExamEnded(true);
+        }
+
+        if (examRecordData.getIsIllegality() == null || !examRecordData.getIsIllegality()) {
+            if ((null != examRecordData.getIsWarn() && !examRecordData.getIsWarn())
+                    || (null != examRecordData.getIsWarn() && examRecordData.getIsWarn()
+                    && null != examRecordData.getIsAudit() && examRecordData.getIsAudit())) {
+                objectiveScoreInfo.setIsAuditing(true);
+
+                // 缓存中的分数是存储在临时考试记录表中的,所以需要从考试记录缓存中取
+                objectiveScoreInfo.setObjectiveScore(examRecordData.getObjectiveScore());
+            } else {
+                objectiveScoreInfo.setIsAuditing(false);
+            }
+
+            objectiveScoreInfo.setIsIllegality(false);
+        } else {
+            objectiveScoreInfo.setIsIllegality(true);
+        }
+
+        return objectiveScoreInfo;
+    }
+
+    /**
+     * 计算考试次数
+     *
+     * @param examId      考试id
+     * @param studentId   学生id
+     * @param usedExamNum 已考次数
+     * @return
+     */
+    private Integer getExamOrder(Long examId, Long studentId, Integer usedExamNum) {
+        ExamSettingsCacheBean cachedExam = ExamCacheTransferHelper.getDefaultCachedExam(examId);
+        Integer canExamTimes = cachedExam.getExamTimes() == null ? 0 : cachedExam.getExamTimes().intValue();// 可考次数
+
+        // 超过可考次数,始终为可考次数+1
+        if (usedExamNum > canExamTimes) {
+            return canExamTimes + 1;
+        }
+
+        return usedExamNum + 1;
+    }
+
+    private boolean isExamRecordEnded(ExamRecordData examRecordData) {
+        // 如果考试记录状态为已处理,则直接返回true.
+        if (examRecordData.getExamRecordStatus() == cn.com.qmth.examcloud.support.enums.ExamRecordStatus.EXAM_END
+                || examRecordData
+                .getExamRecordStatus() == cn.com.qmth.examcloud.support.enums.ExamRecordStatus.EXAM_OVERDUE
+                || examRecordData
+                .getExamRecordStatus() == cn.com.qmth.examcloud.support.enums.ExamRecordStatus.EXAM_INVALID) {
+            return true;
+        }
+        return false;
+    }
+
+    private boolean isExamRecordEnded(ExamRecordDataEntity examRecordData) {
+        // 如果考试记录状态为已处理,则直接返回true.
+        if (examRecordData.getExamRecordStatus() == ExamRecordStatus.EXAM_END
+                || examRecordData.getExamRecordStatus() == ExamRecordStatus.EXAM_OVERDUE
+                || examRecordData.getExamRecordStatus() == ExamRecordStatus.EXAM_INVALID) {
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public void updateCorrectAnswerAndReFixScore(Long examId, Long courseId, Long examStudentId) {
+        List<ExamRecordDataEntity> examRecordDataList = examRecordDataRepo
+                .findByExamIdAndCourseIdAndExamStudentId(examId, courseId, examStudentId);
+        if (CollectionUtils.isEmpty(examRecordDataList)) {
+            log.warn("updateCorrectAnswerAndReFixScore examRecordDataList is empty, examStudentId = {}", examStudentId);
+            return;
+        }
+
+        // Map<试题ID, 正确答案列表>
+        Map<String, List<String>> questionAnswerMaps = new HashMap<>();
+        boolean needUpdateFinalScore = false;
+
+        for (ExamRecordDataEntity examRecordData : examRecordDataList) {
+            if (ExamType.OFFLINE == examRecordData.getExamType()) {
+                // 离线考试,examRecordQuestions实际为空
+                continue;
+            }
+
+            ExamRecordQuestionsEntity examRecordQuestion = examRecordQuestionsService
+                    .getExamRecordQuestionsAndFixExamRecordDataIfNecessary(examRecordData);
+            if (examRecordQuestion == null) {
+                log.warn("updateCorrectAnswerAndReFixScore examRecordQuestions is null, examRecordDataId = {}",
+                        examRecordData.getId());
+                continue;
+            }
+
+            // 所有客观题的试题ID列表
+            List<ExamQuestionEntity> examQuestions = examRecordQuestion.getExamQuestionEntities();
+            Set<String> objectiveQuestionIds = examQuestions.stream()
+                    .filter(e -> QuestionType.isObjective(e.getQuestionType())).map(ExamQuestionEntity::getQuestionId)
+                    .collect(Collectors.toSet());
+
+            double objectiveScore = 0d; // 客观题得分
+            int totalObjective = 0; // 客观题总数
+            int totalRightObjective = 0; // 客观题作答正确数
+            boolean needUpdateExamRecordQuestions = false;
+
+            for (String curQuestionId : objectiveQuestionIds) {
+                // 按题号由小到大提取相同题ID的小题列表(注:套题的子题ID相同)
+                List<ExamQuestionEntity> questionUnits = examQuestions.stream()
+                        .filter(e -> e.getQuestionId().equals(curQuestionId))
+                        .sorted(Comparator.comparingInt(ExamQuestionEntity::getOrder)).collect(Collectors.toList());
+
+                for (ExamQuestionEntity e : questionUnits) {
+                    if (QuestionType.isObjective(e.getQuestionType())) {
+                        totalObjective++;
+                    }
+                }
+
+                // 获取当前题的正确答案
+                List<String> rightAnswers;
+                if (questionAnswerMaps.containsKey(curQuestionId)) {
+                    rightAnswers = questionAnswerMaps.get(curQuestionId);
+                } else {
+                    QuestionAnswerCacheBean questionAnswer = CacheHelper.getQuestionAnswer(curQuestionId);
+                    rightAnswers = questionAnswer.getRightAnswers();
+                    questionAnswerMaps.put(curQuestionId, rightAnswers);
+                }
+
+                if (CollectionUtils.isEmpty(rightAnswers)) {
+                    log.warn("updateCorrectAnswerAndReFixScore rightAnswers is empty, questionId = {}", curQuestionId);
+                    continue;
+                }
+
+                if (questionUnits.size() != rightAnswers.size()) {
+                    log.warn("updateCorrectAnswerAndReFixScore rightAnswers incorrect, questionId = {}", curQuestionId);
+                    continue;
+                }
+
+                for (int i = 0; i < questionUnits.size(); i++) {
+                    ExamQuestionEntity curQuestion = questionUnits.get(i);
+                    if (!QuestionType.isObjective(curQuestion.getQuestionType())) {
+                        // 跳过套题内主观题
+                        continue;
+                    }
+
+                    // 答案不一致,则更新
+                    String rightAnswer = rightAnswers.get(i);
+                    if (rightAnswer != null && !rightAnswer.equals(curQuestion.getCorrectAnswer())) {
+                        curQuestion.setCorrectAnswer(rightAnswer);
+                        needUpdateExamRecordQuestions = true;
+                    }
+
+                    // 计算得分
+                    String correctAnswer = curQuestion.getCorrectAnswer();
+                    String studentAnswer = curQuestion.getStudentAnswer();
+                    // if (correctAnswer != null &&
+                    // QuestionOptionHelper.isEqualAnswer(correctAnswer, studentAnswer)) {
+                    if (correctAnswer != null && correctAnswer.equals(studentAnswer)) {
+                        Double questionScore = curQuestion.getQuestionScore();
+                        if (questionScore == null) {
+                            log.warn("[calcExamScore] questionScore is null, examRecordDataId:{} questionId:{}",
+                                    examRecordData.getId(), curQuestionId);
+                            questionScore = 0d;
+                        }
+
+                        objectiveScore += questionScore;
+                        totalRightObjective++;
+                    }
+                }
+            }
+
+            if (needUpdateExamRecordQuestions) {
+                needUpdateFinalScore = true;
+
+                examRecordQuestionsRepo.save(examRecordQuestion);
+
+                ExamScoreEntity examScore = examScoreRepo.findByExamRecordDataId(examRecordData.getId());
+                if (examScore != null) {
+                    double subjectiveScore = examScore.getSubjectiveScore() != null ? examScore.getSubjectiveScore() : 0d;
+
+                    double objectiveAccuracy = 0d;// 客观题正确率
+                    if (totalObjective > 0) {
+                        objectiveAccuracy = totalRightObjective * 100d / totalObjective;
+                        objectiveAccuracy = Double.parseDouble(new DecimalFormat("#.00").format(objectiveAccuracy));
+                    }
+
+                    examScore.setObjectiveScore(objectiveScore);
+                    examScore.setObjectiveAccuracy(objectiveAccuracy);
+                    examScore.setTotalScore(objectiveScore + subjectiveScore);
+                    examScoreRepo.save(examScore);
+                }
+
+                ExamRecordForMarkingEntity examRecordForMarking = examRecordForMarkingRepo
+                        .findByExamRecordDataId(examRecordData.getId());
+                if (examRecordForMarking != null) {
+                    examRecordForMarking.setObjectiveScore(objectiveScore);
+                    examRecordForMarkingRepo.save(examRecordForMarking);
+                }
+
+                log.info("updateCorrectAnswerAndReFixScore examRecordQuestions examRecordDataId = {}",
+                        examRecordData.getId());
+            }
+        }
+
+        if (needUpdateFinalScore) {
+            examStudentFinalScoreService.calcAndSaveFinalScore(examStudentId);
+            log.info("updateCorrectAnswerAndReFixScore finalScore examStudentId = {}", examStudentId);
+        }
+    }
 
 }