package cn.com.qmth.scancentral.service.impl; import java.io.*; import java.math.BigDecimal; import java.util.*; import java.util.stream.Collectors; import javax.validation.constraints.NotNull; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.google.gson.Gson; import com.qmth.boot.core.collection.PageResult; import com.qmth.boot.core.concurrent.service.ConcurrentService; import com.qmth.boot.core.exception.ParameterException; import com.qmth.boot.core.exception.StatusException; import com.qmth.boot.core.retrofit.utils.SignatureInfo; import com.qmth.boot.tools.excel.ExcelReader; import com.qmth.boot.tools.excel.enums.ExcelType; import com.qmth.boot.tools.signature.SignatureType; import com.qmth.boot.tools.uuid.FastUUID; import cn.com.qmth.scancentral.bean.*; import cn.com.qmth.scancentral.bean.answersave.ArrayResult; import cn.com.qmth.scancentral.bean.answersave.BoolResult; import cn.com.qmth.scancentral.bean.answersave.StringResult; import cn.com.qmth.scancentral.bean.omredit.OmrEditDomain; import cn.com.qmth.scancentral.bean.omredit.OmrEditPaper; import cn.com.qmth.scancentral.bean.omredit.OmrFieldEditDomain; import cn.com.qmth.scancentral.bean.refix.AnswerRefixDomain; import cn.com.qmth.scancentral.bean.refix.PageRefixDomain; import cn.com.qmth.scancentral.bean.refix.PaperRefixDomain; import cn.com.qmth.scancentral.config.SysProperty; import cn.com.qmth.scancentral.dao.StudentDao; import cn.com.qmth.scancentral.entity.*; import cn.com.qmth.scancentral.enums.*; import cn.com.qmth.scancentral.exception.NotFoundExceptions; import cn.com.qmth.scancentral.exception.ParameterExceptions; import cn.com.qmth.scancentral.model.ManualAbsentImportDTO; import cn.com.qmth.scancentral.service.*; import cn.com.qmth.scancentral.support.TaskLock; import cn.com.qmth.scancentral.support.TaskLockUtil; import cn.com.qmth.scancentral.util.BatchGetDataUtil; import cn.com.qmth.scancentral.util.BatchSetDataUtil; import cn.com.qmth.scancentral.util.MD5Util; import cn.com.qmth.scancentral.util.PageUtil; import cn.com.qmth.scancentral.vo.*; import cn.com.qmth.scancentral.vo.answerquery.AnswerPageVo; import cn.com.qmth.scancentral.vo.answerquery.AnswerPaperVo; import cn.com.qmth.scancentral.vo.answerquery.AnswerQueryVo; import cn.com.qmth.scancentral.vo.answerquery.StudentPaperVo; import cn.com.qmth.scancentral.vo.assginedcheck.*; import cn.com.qmth.scancentral.vo.examroom.ExamRoomScannedQuery; import cn.com.qmth.scancentral.vo.examroom.ExamRoomScannedVo; import cn.com.qmth.scancentral.vo.paper.PaperCetVo; import cn.com.qmth.scancentral.vo.paper.PaperPageCetVo; import cn.com.qmth.scancentral.vo.student.*; import cn.com.qmth.scancentral.vo.studentimport.StudentCountVo; import cn.com.qmth.scancentral.vo.subject.SubjectScanProgressVo; import cn.com.qmth.scancentral.vo.task.TaskStatusVo; @Service public class StudentServiceImpl extends ServiceImpl implements StudentService { private static final Logger log = LoggerFactory.getLogger(StudentService.class); @Autowired private PaperService paperService; @Autowired private PaperPageService paperPageService; @Autowired private StudentPaperService studentPaperService; @Autowired private ExamService examService; @Autowired private SubjectService subjectService; @Autowired private BatchService batchService; @Autowired private AnswerCardService answerCardService; @Autowired private ConcurrentService concurrentService; @Autowired private OmrTaskService omrTaskService; @Autowired private OmrGroupService omrGroupService; @Autowired private QuestionService questionService; @Autowired private SysProperty sysProperty; @Autowired private ToolExportService toolExportService; @Autowired private SessionService sessionService; @Autowired private AnswerCardSubjectService answerCardSubjectService; @Autowired private AssignedCheckHistoryService assignedCheckHistoryService; @Autowired private UserService userService; @Autowired private FileService fileService; /** * 整体更新考生绑定的paper并刷新考生状态,若集合为空则表示考生无扫描结果,需要在外部调用处对考生上锁 * * @param id * @param studentPaperList */ @Override @Transactional // @Lockable(name = LockType.STUDENT, key = "#id") public void updateStudentAndPaper(@NotNull User user, @NotNull Long id, @NotNull List studentPaperList) { for (StudentPaperEntity studentPaper : studentPaperList) { studentPaper.setStudentId(id); } // 清空原有绑定关系 studentPaperService.removeByStudentId(id); // 保存绑定关系 studentPaperService.saveOrUpdateBatchByMultiId(studentPaperList); // 更新考生状态 updateStudentByPaper(user, id, true); } /** * 根据考生当前绑定的paper刷新考生状态,需要在外部调用处对考生上锁 * * @param id */ @Override @Transactional // @Lockable(name = LockType.STUDENT, key = "#id") public void updateStudentByPaper(@NotNull User user, @NotNull Long id, @NotNull boolean updateOmrTask) { StudentEntity student = baseMapper.selectById(id); if (student == null) { throw new ParameterException("找不到对应的考生"); } ExamEntity exam = examService.getById(student.getExamId()); // 重置状态 student.setIncomplete(false); student.setAssigned(false); student.setAssignedSuspect(false); student.setQuestionFilled(false); student.setSubjectiveFilled(false); student.setDevice(null); student.setCardNumber(null); student.setPaperType("#"); student.setOmrAbsent(false); student.setExamStatus(ExamStatus.OK); int paperCount = 0; List studentPaperList = studentPaperService.findByStudentId(id); int omrExamNumberCount = 0; for (StudentPaperEntity studentPaper : studentPaperList) { paperCount++; // 获取paper详情更新考生状态 PaperEntity paper = paperService.getById(studentPaper.getPaperId()); student.setAssigned(student.getAssigned() || paper.getAssigned()); student.setAssignedSuspect(student.getAssignedSuspect() || paper.getAssignedSuspect()); student.setQuestionFilled(student.getQuestionFilled() || paper.getQuestionFilled()); student.setSubjectiveFilled(student.getSubjectiveFilled() || paper.getSubjectiveFilled()); student.setCardNumber(paper.getCardNumber()); // 单独判断首张纸正面的识别结果 if (studentPaper.getPaperNumber() == 1) { // 根据识别结果更新考生属性 PaperPageEntity page = paperPageService.findPaperIdAndIndex(paper.getId(), 1); student.setPaperType(page.getPaperType() != null ? page.getPaperType().getResult() : "#"); student.setOmrAbsent(page.getAbsent() == null ? false : page.getAbsent().getResult()); student.setDevice(batchService.findByPaperId(paper.getId()).getDevice()); } // 计算识别位数 int paperExamNumberCount = paper.getOmrExamNumber().replace("#", "").length(); if (omrExamNumberCount < paperExamNumberCount) { omrExamNumberCount = paperExamNumberCount; } } // 更新考生状态 if (paperCount > 0) { AnswerCardEntity answerCard = answerCardService.findByExamAndNumber(student.getExamId(), student.getCardNumber()); student.setIncomplete(paperCount != answerCard.getPaperCount()); student.setStatus(ScanStatus.SCANNED); } else { student.setStatus(ScanStatus.UNEXIST); student.setExamStatus(null); } // 更新缺考校验状态 if (exam.getExamNumberFillCount() != null) { resetExamStatus(student, omrExamNumberCount, exam.getExamNumberFillCount()); } student.setFileUploadStatus(UploadStatus.WAITING_UPLOAD); student.setDataUploadStatus(UploadStatus.WAITING_UPLOAD); student.setUpdaterId(user.getId()); student.setUpdateTime(System.currentTimeMillis()); saveOrUpdate(student); // try { // SignatureInfo signatureInfo = new SignatureInfo(SignatureType.TOKEN, // user.getAccount(), // user.getMarkingCloudToken()); // apiClient.studentFileDelete(signatureInfo.toString(), // student.getExamId(), student.getExamNumber()); // } catch (RetrofitResponseError e) { // e.printStackTrace(); // if (e.getCode() == 401) { // throw AuthorizationException.SIGNATURE_INVALID; // } else { // throw e; // } // } if (updateOmrTask) { // 遍历固定任务分组 List gs = omrGroupService.findByExamIdAndFixed(student.getExamId(), true); if (CollectionUtils.isNotEmpty(gs)) { for (OmrGroupEntity g : gs) { concurrentService.getReadWriteLock(LockType.OMR_GROUP + "-" + g.getId()).readLock().lock(); omrTaskService.deleteByStudentIdAndGroupId(g.getId(), student.getId()); // 重新生成识别对照任务 omrTaskService.saveTask(g, student.getId()); concurrentService.getReadWriteLock(LockType.OMR_GROUP + "-" + g.getId()).readLock().unlock(); } } } } @Override public List listCampusByExamId(Long examId) { return baseMapper.listCampusByExamId(examId); } @Override public Integer getStudentAnswerCount(Long examId) { if (examId == null) { throw new ParameterException("examId不能为空"); } QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.lambda().eq(StudentEntity::getExamId, examId); queryWrapper.lambda().eq(StudentEntity::getCheckMark, true); return this.count(queryWrapper); } @Override public List listSiteByExamId(Long examId) { return baseMapper.listSiteByExamId(examId); } @Override public StudentVo findOne(StudentQuery query) { Long examId = query.getExamId(); String examNumber = query.getExamNumber(); String subjectCode = query.getSubjectCode(); if (StringUtils.isBlank(examNumber) || StringUtils.isBlank(subjectCode)) { throw new ParameterException("examNumber subjectCode不能都为空"); } QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.lambda().eq(StudentEntity::getExamId, examId); queryWrapper.lambda().eq(StudentEntity::getExamNumber, examNumber); queryWrapper.lambda().eq(StudentEntity::getSubjectCode, subjectCode); StudentEntity s = baseMapper.selectOne(queryWrapper); if (s == null) { throw new ParameterException("未找到考生"); } StudentVo vo = StudentVo.of(s); SubjectEntity sub = subjectService.findByExamIdAndCode(examId, s.getSubjectCode()); vo.setSubjectName(sub.getName()); return vo; } @Override public int getCountByExam(Long examId) { QueryWrapper wrapper = new QueryWrapper<>(); LambdaQueryWrapper lw = wrapper.lambda(); lw.eq(StudentEntity::getExamId, examId); return this.count(wrapper); } @Override public int getPackageCountByExam(Long examId) { return baseMapper.getPackageCountByExam(examId); } @Override public int getCountByExamAndScanStatus(Long examId, ScanStatus status) { QueryWrapper wrapper = new QueryWrapper<>(); LambdaQueryWrapper lw = wrapper.lambda(); lw.eq(StudentEntity::getExamId, examId); lw.eq(StudentEntity::getStatus, status); return this.count(wrapper); } @Override public List packageList(StudentQuery query) { List ret = new ArrayList<>(); StudentVo one = findOne(query); if (one != null) { List list = findByExamAndPackage(query.getExamId(), one.getPackageCode(), one.getSubjectCode()); if (CollectionUtils.isNotEmpty(list)) { for (StudentEntity e : list) { StudentVo vo = StudentVo.of(e); vo.setSubjectName(one.getSubjectName()); ret.add(vo); } } } return ret; } @Override public List findByExamAndPackage(Long examId, String packageCode, String subjectCode) { if (examId == null) { throw new ParameterException("examId 不能为空"); } if (StringUtils.isBlank(packageCode)) { throw new ParameterException("packageCode不能为空"); } QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.lambda().eq(StudentEntity::getExamId, examId); queryWrapper.lambda().eq(StudentEntity::getPackageCode, packageCode); if (StringUtils.isNotBlank(subjectCode)) { queryWrapper.lambda().eq(StudentEntity::getSubjectCode, subjectCode); } return this.list(queryWrapper); } @Override public int getAssignedCountByExam(Long examId) { QueryWrapper wrapper = new QueryWrapper<>(); LambdaQueryWrapper lw = wrapper.lambda(); lw.eq(StudentEntity::getExamId, examId); lw.eq(StudentEntity::getAssigned, true); return this.count(wrapper); } @Override public int getUnscannedCountByExam(Long examId) { QueryWrapper wrapper = new QueryWrapper<>(); LambdaQueryWrapper lw = wrapper.lambda(); lw.eq(StudentEntity::getExamId, examId); lw.ne(StudentEntity::getStatus, ScanStatus.SCANNED); return this.count(wrapper); } @Override public int getAbsentSuspectCountByExam(Long examId) { QueryWrapper wrapper = new QueryWrapper<>(); LambdaQueryWrapper lw = wrapper.lambda(); lw.eq(StudentEntity::getExamId, examId); lw.eq(StudentEntity::getAbsentSuspect, true); return this.count(wrapper); } @Override public int getIncompleteCountByExam(Long examId) { QueryWrapper wrapper = new QueryWrapper<>(); LambdaQueryWrapper lw = wrapper.lambda(); lw.eq(StudentEntity::getExamId, examId); lw.eq(StudentEntity::getIncomplete, true); return this.count(wrapper); } @Override public AbsentInfoVo absentInfo(Long examId, GroupType groupType, String groupName) { AbsentInfoVo vo = baseMapper.absentInfo(examId, groupType != null ? groupType.getFieldName() : null, StringUtils.trimToNull(groupName)); if (vo == null) { vo = new AbsentInfoVo(); } return vo; } // private Integer totalCount(Long examId) { // QueryWrapper wrapper = new QueryWrapper<>(); // LambdaQueryWrapper lw = wrapper.lambda(); // lw.eq(StudentEntity::getExamId, examId); // return this.count(wrapper); // } // // private Integer countByStatus(Long examId, ScanStatus st) { // QueryWrapper wrapper = new QueryWrapper<>(); // LambdaQueryWrapper lw = wrapper.lambda(); // lw.eq(StudentEntity::getExamId, examId); // lw.eq(StudentEntity::getStatus, st); // return this.count(wrapper); // } // // private Integer countByAbsentSuspect(Long examId) { // QueryWrapper wrapper = new QueryWrapper<>(); // LambdaQueryWrapper lw = wrapper.lambda(); // lw.eq(StudentEntity::getExamId, examId); // lw.eq(StudentEntity::getAbsentSuspect, true); // return this.count(wrapper); // } // // private Integer countByIncomplete(Long examId) { // QueryWrapper wrapper = new QueryWrapper<>(); // LambdaQueryWrapper lw = wrapper.lambda(); // lw.eq(StudentEntity::getExamId, examId); // lw.eq(StudentEntity::getIncomplete, true); // return this.count(wrapper); // } @Override public PageResult absentQuery(AbsentQueryDomain query) { IPage iPage = baseMapper.absentQueryPage(new Page<>(query.getPageNumber(), query.getPageSize()), query.getGroupType().getFieldName(), query); return PageUtil.of(iPage); } @Override public List absentSummary(AbsentQueryDomain query) { return baseMapper.absentQuerySummary(query.getGroupType().getFieldName(), query); } @Override public List absentExportList(AbsentQueryDomain query) { return baseMapper.absentExportList(new Page<>(query.getPageNumber(), query.getPageSize()), query.getGroupType().getFieldName(), query); } @Transactional @Override public AbsentManualImportVo absentManualImport(Long examId, MultipartFile multipartFile) { List list = null; try { list = ExcelReader.create(ExcelType.XLSX, multipartFile.getInputStream(), 0) .getObjectList(ManualAbsentImportDTO.class); } catch (IOException e) { throw new ParameterException("Excel解析出错", e); } catch (Exception e) { throw new ParameterException("Excel解析出错", e); } if (CollectionUtils.isEmpty(list)) { throw new ParameterException("Excel无内容"); } // if (10001 < lineList.size()) { // throw new ParameterException("数据行数不能超过10000"); // } int updateCount = 0; int ignoreCount = 0; int suspectCount = 0; for (ManualAbsentImportDTO data : list) { String examNumber = trimAndNullIfBlank(data.getExamNumber()); String subjectCode = trimAndNullIfBlank(data.getSubjectCode()); if (StringUtils.isBlank(examNumber)) { throw new ParameterException("examNumber不能为空"); } if (StringUtils.isBlank(subjectCode)) { throw new ParameterException("科目代码不能为空"); } StudentEntity student = this.findByExamAndSubjectCodeAndExamNumber(examId, subjectCode, examNumber); if (student == null) { throw new ParameterException("考生信息未找到:" + examNumber + ":" + subjectCode); } if (ScanStatus.MANUAL_ABSENT.equals(student.getStatus())) { ignoreCount++; } else if (ScanStatus.SCANNED.equals(student.getStatus())) { absentSuspectUpdate(student.getExamId(), student.getSubjectCode(), student.getExamNumber(), true); suspectCount++; } else { absentManualUpdate(student.getExamId(), student.getSubjectCode(), student.getExamNumber()); updateCount++; } } AbsentManualImportVo vo = new AbsentManualImportVo(); vo.setIgnoreCount(ignoreCount); vo.setUpdateCount(updateCount); vo.setSuspectCount(suspectCount); return vo; } private String trimAndNullIfBlank(String s) { if (StringUtils.isBlank(s)) { return null; } return s.trim(); } @Transactional @Override public UpdateTimeVo absentManualUpdate(Long examId, String subjectCode, String examNumber) { StudentEntity student = this.findByExamAndSubjectCodeAndExamNumber(examId, subjectCode, examNumber); if (student == null) { throw new ParameterException("考生未找到:" + examNumber); } if (student.getStatus() != ScanStatus.UNEXIST) { throw new ParameterException("考生不是未扫描状态:" + examNumber); } LambdaUpdateWrapper lw = new LambdaUpdateWrapper<>(); lw.set(StudentEntity::getStatus, ScanStatus.MANUAL_ABSENT); lw.set(StudentEntity::getDataUploadStatus, UploadStatus.WAITING_UPLOAD); lw.eq(StudentEntity::getId, student.getId()); lw.eq(StudentEntity::getStatus, ScanStatus.UNEXIST); update(lw); return UpdateTimeVo.create(); } @Transactional @Override public UpdateTimeVo absentSuspectUpdate(Long examId, String subjectCode, String examNumber, boolean enable) { StudentEntity student = this.findByExamAndSubjectCodeAndExamNumber(examId, subjectCode, examNumber); if (student == null) { throw new ParameterException("考生未找到:" + examNumber); } LambdaUpdateWrapper lw = new LambdaUpdateWrapper<>(); lw.set(StudentEntity::getAbsentSuspect, enable); lw.set(StudentEntity::getDataUploadStatus, UploadStatus.WAITING_UPLOAD); lw.eq(StudentEntity::getId, student.getId()); update(lw); return UpdateTimeVo.create(); } @Override public ScanAnswerInfoVo scanAnswerInfo(Long examId) { return baseMapper.getInfoCountByExam(examId); } @Override public List summary(AnswerQueryDomain query) { // 不分页查询考生准考证号 return baseMapper.querySummary(query); } @Override public List exportList(AnswerQueryDomain query) { // 分页查询考生导出信息 return baseMapper.exportList(new Page<>(query.getPageNumber(), query.getPageSize()), query); } @Override public List exportListK12(AnswerQueryDomain query) { // 分页查询考生导出信息 List list = baseMapper.exportList(new Page<>(query.getPageNumber(), query.getPageSize()), query); List ret = new ArrayList<>(); if (CollectionUtils.isNotEmpty(list)) { for (AnswerExportVo vo : list) { AnswerExportK12Vo kvo = new AnswerExportK12Vo(); BeanUtils.copyProperties(vo, kvo); ret.add(kvo); } } return ret; } @Override public PageResult query(AnswerQueryDomain query) { // 查询考生分页信息 IPage iPage = baseMapper.queryPage(new Page<>(query.getPageNumber(), query.getPageSize()), query); if (CollectionUtils.isNotEmpty(iPage.getRecords())) { Map map = new HashMap<>(); for (AnswerQueryVo vo : iPage.getRecords()) { List papers = new ArrayList<>(); vo.setPapers(papers); if (vo.getCardPaperCount() != null) { for (int i = 1; i <= vo.getCardPaperCount(); i++) { AnswerPaperVo pv = new AnswerPaperVo(); pv.setNumber(i); papers.add(pv); } } map.put(vo.getId(), vo); } // 根据考生id查找绑定paper List studentIds = iPage.getRecords().stream().map(p -> p.getId()).collect(Collectors.toList()); List paperList = new BatchGetDataUtil() { @Override public List getData(List paramList) { return paperService.listByStudentIds(paramList); } }.getDataForBatch(studentIds, 20); if (CollectionUtils.isNotEmpty(paperList)) { Map paperMap = new HashMap<>(); for (StudentPaperVo p : paperList) { AnswerQueryVo vo = map.get(p.getStudentId()); if (vo == null) { continue; } List papers = vo.getPapers(); if (papers == null) { continue; } if (papers.size() < p.getNumber()) { continue; } AnswerPaperVo pvo = papers.get(p.getNumber() - 1); pvo.setId(p.getPaperId()); pvo.setNumber(p.getNumber()); pvo.setAssigned(p.getAssigned()); paperMap.put(p.getPaperId(), pvo); } // 查找page List paperIds = paperList.stream().map(p -> p.getPaperId()).collect(Collectors.toList()); List paperPageList = new BatchGetDataUtil() { @Override public List getData(List paramList) { return paperPageService.listByPaperList(paramList); } }.getDataForBatch(paperIds, 20); if (CollectionUtils.isNotEmpty(paperPageList)) { for (PaperPageEntity p : paperPageList) { AnswerPaperVo pvo = paperMap.get(p.getPaperId()); if (pvo == null) { continue; } List pages = pvo.getPages(); if (pages == null) { pages = new ArrayList<>(); pvo.setPages(pages); } AnswerPageVo pageVo = new AnswerPageVo(); pageVo.setIndex(p.getPageIndex()); pageVo.setSheetUri(p.getSheetPath()); pageVo.setSliceUri(p.getSlicePath()); if (query.getWithOmrDetail() != null && query.getWithOmrDetail()) { pageVo.setAbsent(p.getAbsent()); pageVo.setBreach(p.getBreach()); pageVo.setPaperType(p.getPaperType()); pageVo.setQuestion(p.getQuestion()); pageVo.setSelective(p.getSelective()); pageVo.setRecogData(p.getRecogData()); } pages.add(pageVo); } } } } return PageUtil.of(iPage); } @Transactional @Override public void updateDataUploadStatus(@NotNull Long id, @NotNull UploadStatus status) { LambdaUpdateWrapper lw = new LambdaUpdateWrapper<>(); lw.set(StudentEntity::getDataUploadStatus, status); lw.eq(StudentEntity::getId, id); update(lw); } @Transactional @Override public void updateFileUploadStatus(@NotNull Long id, @NotNull UploadStatus status) { LambdaUpdateWrapper lw = new LambdaUpdateWrapper<>(); lw.set(StudentEntity::getFileUploadStatus, status); lw.eq(StudentEntity::getId, id); update(lw); } @Transactional @Override public void updateUploadStatus(@NotNull Long id, @NotNull UploadStatus fileUploadStatus, @NotNull UploadStatus dataUploadStatus) { LambdaUpdateWrapper lw = new LambdaUpdateWrapper<>(); lw.set(StudentEntity::getDataUploadStatus, dataUploadStatus); lw.set(StudentEntity::getFileUploadStatus, fileUploadStatus); lw.eq(StudentEntity::getId, id); update(lw); } @Transactional @Override public void updateOmrAbsent(@NotNull Long id, @NotNull Boolean omrAbsent) { LambdaUpdateWrapper lw = new LambdaUpdateWrapper<>(); lw.set(StudentEntity::getOmrAbsent, omrAbsent); lw.eq(StudentEntity::getId, id); update(lw); } @Transactional @Override public void deletetByExamIdAndUnCreateTime(Long examId, long createTime) { QueryWrapper wrapper = new QueryWrapper<>(); LambdaQueryWrapper lw = wrapper.lambda(); lw.eq(StudentEntity::getExamId, examId); lw.ne(StudentEntity::getCreateTime, createTime); this.baseMapper.delete(wrapper); } @Override public boolean existUploadData(Long schoolId) { return CollectionUtils.isNotEmpty(baseMapper.findToUpload(1, schoolId)) || CollectionUtils.isNotEmpty(baseMapper.findUploadError(1, schoolId)); } @Override public List findToUpload(int pageSize, Long schoolId) { if (pageSize <= 0) { pageSize = 100; } List result = baseMapper.findToUpload(pageSize, schoolId); if (CollectionUtils.isEmpty(result)) { result = baseMapper.findUploadError(pageSize, schoolId); } return result; } @Override public int getCountByExamAndCardNumber(Long examId, Integer number) { QueryWrapper wrapper = new QueryWrapper<>(); LambdaQueryWrapper lw = wrapper.lambda(); lw.eq(StudentEntity::getExamId, examId); lw.eq(StudentEntity::getCardNumber, number); return this.count(wrapper); } @Transactional @Override public int importStudent(List students) { List savelist = new ArrayList(); List updatelist = new ArrayList(); // Map> map =new HashMap>(); for (ImportStudentDomain domain : students) { // Map examMap =map.get(domain.getExamId()); // if(examMap ==null) { // examMap = new HashMap(); // List list2 = this.list(); // for (StudentEntity s : list2) { // examMap.put(s.getExamNumber(), s); // } // map.put(domain.getExamId(), examMap); // } // StudentEntity entity = examMap.get(domain.getExamNumber()); StudentEntity entity = this.findByExamAndSubjectCodeAndExamNumber(domain.getExamId(), domain.getSubjectCode(), domain.getExamNumber()); if (entity == null) { entity = this.findByExamAndSubjectCodeAndExamNumber(domain.getExamId(), domain.getSubjectCode(), domain.getExamNumber()); } if (entity == null) { entity = new StudentEntity(); entity.setStatus(ScanStatus.UNEXIST); entity.setImageCheckStatus(ImageCheckStatus.WAITING); entity.setAbsentSuspect(false); entity.setAssigned(false); entity.setIncomplete(false); entity.setOmrAbsent(false); entity.setQuestionFilled(false); entity.setSubjectiveFilled(false); entity.setPaperType("#"); entity.setCheckMark(false); entity.setAssignedSuspect(false); savelist.add(entity); } else { updatelist.add(entity); } entity.setExamId(domain.getExamId()); entity.setName(domain.getName()); entity.setSubjectCode(domain.getSubjectCode()); entity.setExamNumber(domain.getExamNumber()); entity.setPackageCode(domain.getPackageCode()); entity.setExamRoom(domain.getExamRoom()); entity.setExamSite(domain.getExamSite()); entity.setExamSiteName(domain.getExamSiteName()); entity.setSeatNumber(domain.getSeatNumber()); entity.setCampusName(domain.getCampusName()); entity.setCampusCode(domain.getCampusCode()); } if (savelist.size() > 0) { this.saveBatch(savelist); } if (updatelist.size() > 0) { this.updateBatchById(updatelist); } return students.size(); } @Override public StudentEntity findByExamAndSubjectCodeAndExamNumber(Long examId, String subjectCode, String examNumber) { if (examId == null) { throw new ParameterException("examId 不能为空"); } if (StringUtils.isBlank(subjectCode)) { throw new ParameterException("subjectCode不能为空"); } if (StringUtils.isBlank(examNumber)) { throw new ParameterException("examNumber"); } QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.lambda().eq(StudentEntity::getExamId, examId); queryWrapper.lambda().eq(StudentEntity::getSubjectCode, subjectCode); queryWrapper.lambda().eq(StudentEntity::getExamNumber, examNumber); return baseMapper.selectOne(queryWrapper); } @Override public int countByQuery(ImportStudentQueryVo query) { if (query.getExamId() == null) { throw new ParameterException("examId不能为空"); } return baseMapper.countByQuery(query); } @Override public int countCetMarking(ExportCetMarkingQueryVo query) { if (query.getExamId() == null) { throw new ParameterException("examId不能为空"); } return baseMapper.countCetMarking(query); } @Override public List findByQuery(ImportStudentQueryVo query) { if (query.getExamId() == null) { throw new ParameterException("examId不能为空"); } ExamEntity exam = examService.getById(query.getExamId()); if (exam == null) { throw new ParameterException("未找到考试"); } IPage iPage = baseMapper .listPageQuery(new Page(query.getPageNumber(), query.getPageSize()), query); if (query.getWithAnswer() != null && query.getWithAnswer()) { for (ImportStudentVo student : iPage.getRecords()) { List papers = studentPaperService.findByStudentId(student.getId()); List pageList = new ArrayList<>(); for (StudentPaperEntity sp : papers) { List pages = paperPageService.listByPaperId(sp.getPaperId()); pageList.addAll(pages); } List answers = new ArrayList(); for (PaperPageEntity p : pageList) { if (p.getPageIndex() == 1) { student.setPaperType(p.getPaperType() == null ? null : p.getPaperType().getResult()); } disposeQuestionMark(p.getQuestion()); if (p.getQuestion() != null && CollectionUtils.isNotEmpty(p.getQuestion().getResult())) { answers.addAll(p.getQuestion().getResult()); } } student.setAnswer(answers); } } return iPage.getRecords(); } private void disposeQuestionMark(ArrayResult ar) { if (ar != null && CollectionUtils.isNotEmpty(ar.getResult())) { for (int i = 0; i < ar.getResult().size(); i++) { ar.getResult().set(i, ar.getResult().get(i).replaceAll("\\?", "")); } } } @Override public int getOmrAbsentCountByExam(Long examId) { QueryWrapper wrapper = new QueryWrapper<>(); LambdaQueryWrapper lw = wrapper.lambda(); lw.eq(StudentEntity::getExamId, examId); lw.eq(StudentEntity::getOmrAbsent, true); return this.count(wrapper); } @Override public boolean existPictureCopyData() { List list = baseMapper.findToPictureCopy(1); return CollectionUtils.isNotEmpty(list); } @Override public List findToPictureCopy(int pageSize) { if (pageSize <= 0) { pageSize = 100; } return baseMapper.findToPictureCopy(pageSize); } @Override public Double getUploadProgress(Long examId) { // int total = getCountByExamAndScanStatus(examId, ScanStatus.SCANNED); // if (total == 0) { // return 0.0; // } int needUpload = baseMapper.getNeedUploadCount(examId); int uploaded = baseMapper.getUploadedCount(examId); int total = needUpload + uploaded; if (total == 0) { return 0.0; } BigDecimal totalB = new BigDecimal(total); BigDecimal uploadedB = new BigDecimal(uploaded); return uploadedB.divide(totalB, 2, BigDecimal.ROUND_HALF_UP).doubleValue(); } @Transactional @Override public void studentClean(Long examId, String subjectCode) { ExamEntity exam = examService.getById(examId); if (exam == null) { throw ParameterExceptions.EXAM_NOT_FOUND; } if (batchService.getCountByExam(examId) > 0) { throw new ParameterException("已开始扫描不能清空"); } LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(); wrapper.eq(StudentEntity::getExamId, examId); wrapper.eq(StudentEntity::getSubjectCode, subjectCode); baseMapper.delete(wrapper); subjectService.cleanByExamId(examId, subjectCode); } @Transactional @Override // @Lockable public PaperDeleteVo paperDelete(User user, PageDeleteDomain domain) { Integer paperNumber = domain.getPaperNumber(); StudentEntity student = this.findByExamAndSubjectCodeAndExamNumber(domain.getExamId(), domain.getSubjectCode(), domain.getExamNumber()); if (student == null) { throw new ParameterException("考生信息未找到"); } concurrentService.getReadWriteLock(LockType.STUDENT + "-" + student.getId()).writeLock().lock(); try { updateStudentAndPaper(user, student.getId(), removeStudentPaper(studentPaperService.findByStudentId(student.getId()), paperNumber)); updateAssignedCheckCount(student.getId(), true); PaperDeleteVo vo = new PaperDeleteVo(); vo.setPaperCount(studentPaperService.countByStudentId(student.getId())); vo.setUpdateTime(new Date().getTime()); return vo; } finally { concurrentService.getReadWriteLock(LockType.STUDENT + "-" + student.getId()).writeLock().unlock(); } } private List removeStudentPaper(List list, Integer paperNumber) { boolean find = false; List left = new ArrayList<>(); for (StudentPaperEntity entity : list) { if (entity.getPaperNumber().equals(paperNumber)) { find = true; } else { left.add(entity); } } if (!find) { throw new ParameterException("未找到该张扫描结果"); } else if (left.size() > 0 && paperNumber == 1) { throw new StatusException("需先删除其他张之后才能删除第一张"); } else { return left; } } @Transactional @Override // @Lockable public AnswerDeleteVo answerDelete(User user, AnswerDeleteDomain domain) { Long examId = domain.getExamId(); String examNumber = domain.getExamNumber(); StudentEntity student = this.findByExamAndSubjectCodeAndExamNumber(examId, domain.getSubjectCode(), examNumber); if (student == null) { throw new ParameterException("考生信息未找到"); } concurrentService.getReadWriteLock(LockType.STUDENT + "-" + student.getId()).writeLock().lock(); try { updateStudentAndPaper(user, student.getId(), new ArrayList<>()); updateAssignedCheckCount(student.getId(), true); AnswerDeleteVo vo = new AnswerDeleteVo(); vo.setStatus(ScanStatus.UNEXIST); vo.setUpdateTime(new Date().getTime()); return vo; } finally { concurrentService.getReadWriteLock(LockType.STUDENT + "-" + student.getId()).writeLock().unlock(); } } @Transactional @Override // @Lockable public AnswerRefixVo answerRefix(User user, AnswerRefixDomain domain) { StudentEntity student = this.findByExamAndSubjectCodeAndExamNumber(domain.getExamId(), domain.getSubjectCode(), domain.getExamNumber()); if (student == null) { throw new ParameterException("考生信息未找到"); } AnswerCardEntity answerCard = answerCardService.findByExamAndNumber(domain.getExamId(), domain.getCardNumber()); if (answerCard == null) { throw new ParameterException("卡格式信息未找到"); } boolean allowSubject = answerCardSubjectService.checkSubject(answerCard.getExamId(), answerCard.getNumber(), student.getSubjectCode()); if (!allowSubject) { throw new ParameterException("卡格式与考生科目不匹配"); } // if (domain.getPapers().size() != answerCard.getPaperCount()) { // throw new ParameterException("卡格式张数不一致"); // } ExamEntity exam = examService.getById(student.getExamId()); List paperTypeBarcodeContents = exam.getPaperTypeBarcodeContent(); SubjectEntity subject = subjectService.findByExamIdAndCode(student.getExamId(), student.getSubjectCode()); if (subject.getPaperTypeBarcodeContent() != null && !subject.getPaperTypeBarcodeContent().isEmpty()) { paperTypeBarcodeContents = subject.getPaperTypeBarcodeContent(); } concurrentService.getReadWriteLock(LockType.STUDENT + "-" + student.getId()).writeLock().lock(); try { List studentPaperList = studentPaperService.findByStudentId(student.getId()); for (StudentPaperEntity studentPaper : studentPaperList) { PaperRefixDomain paperDomain = domain.findPaperDomain(studentPaper.getPaperNumber(), studentPaper.getPaperId()); if (paperDomain == null) { throw new ParameterException("与考生当前paper不一致,paperNumber=" + studentPaper.getPaperNumber()); } PaperEntity paper = paperService.getById(paperDomain.getId()); if (paper == null) { throw new ParameterException("考生当前paper不存在,paperId=" + paperDomain.getId()); } paper.setCardNumber(answerCard.getNumber()); paper.setMismatch(paperDomain.getMismatch()); List pages = new ArrayList<>(); for (PageRefixDomain pageDomain : paperDomain.getPages()) { PaperPageEntity page = paperPageService.findPaperIdAndIndex(paper.getId(), pageDomain.getIndex()); if (page == null) { throw new ParameterException("与考生当前page不一致,pageIndex=" + pageDomain.getIndex()); } pages.add(pageDomain.update(page, paperTypeBarcodeContents)); } paperService.savePaperAndPages(paper, pages); } updateStudentByPaper(user, student.getId(), true); return AnswerRefixVo.create(); } finally { concurrentService.getReadWriteLock(LockType.STUDENT + "-" + student.getId()).writeLock().unlock(); } } @Transactional @Override public UpdateTimeVo omrEdit(User user, OmrEditDomain domain) { StudentEntity student = this.findByExamAndSubjectCodeAndExamNumber(domain.getExamId(), domain.getSubjectCode(), domain.getExamNumber()); if (student == null) { throw new ParameterException("考生信息未找到"); } concurrentService.getReadWriteLock(LockType.STUDENT + "-" + student.getId()).writeLock().lock(); try { for (OmrEditPaper paperEdit : domain.getPapers()) { StudentPaperEntity sp = studentPaperService.findByStudentIdAndPaperNumber(student.getId(), paperEdit.getNumber()); if (sp == null) { throw new ParameterException("未找到绑定扫描结果"); } PaperEntity paperEntity = paperService.getById(sp.getPaperId()); if (paperEntity == null) { throw new ParameterException("未找到paper信息结果"); } paperEntity.setUpdaterId(user.getId()); paperEntity.setUpdateTime(System.currentTimeMillis()); List pages = paperPageService.listByPaperId(paperEntity.getId()); for (PaperPageEntity pageEntity : pages) { paperEdit.updatePage(pageEntity); } paperService.savePaperAndPages(paperEntity, pages); } updateStudentByPaper(user, student.getId(), false); return UpdateTimeVo.create(); } finally { concurrentService.getReadWriteLock(LockType.STUDENT + "-" + student.getId()).writeLock().unlock(); } } @Transactional @Override public UpdateTimeVo omrFieldEdit(User user, OmrFieldEditDomain domain) { StudentEntity student = this.findByExamAndSubjectCodeAndExamNumber(domain.getExamId(), domain.getSubjectCode(), domain.getExamNumber()); if (student == null) { throw new ParameterException("考生信息未找到"); } concurrentService.getReadWriteLock(LockType.STUDENT + "-" + student.getId()).writeLock().lock(); try { StudentPaperEntity sp = studentPaperService.findByStudentIdAndPaperNumber(student.getId(), domain.getPaperNumber()); if (sp == null) { throw new ParameterException("未找到绑定扫描结果"); } PaperEntity paperEntity = paperService.getById(sp.getPaperId()); if (paperEntity == null) { throw new ParameterException("未找到paper信息结果"); } paperEntity.setUpdaterId(user.getId()); paperEntity.setUpdateTime(System.currentTimeMillis()); List pages = paperPageService.listByPaperId(paperEntity.getId()); boolean pageIndexValid = false; for (PaperPageEntity pageEntity : pages) { if (pageEntity.getPageIndex().equals(domain.getPageIndex())) { pageIndexValid = true; Gson gson = new Gson(); if (OmrField.ABSENT.equals(domain.getField())) { pageEntity.setAbsent(gson.fromJson(domain.getValue().toString(), BoolResult.class)); } else if (OmrField.BREACH.equals(domain.getField())) { pageEntity.setBreach(gson.fromJson(domain.getValue().toString(), BoolResult.class)); } else if (OmrField.PAPER_TYPE.equals(domain.getField())) { pageEntity.setPaperType(gson.fromJson(domain.getValue().toString(), StringResult.class)); } else if (OmrField.QUESTION.equals(domain.getField())) { pageEntity.setQuestion(gson.fromJson(domain.getValue().toString(), ArrayResult.class)); } else if (OmrField.SELECTIVE.equals(domain.getField())) { pageEntity.setSelective(gson.fromJson(domain.getValue().toString(), ArrayResult.class)); } else { throw new ParameterException("field值错误"); } } } if (!pageIndexValid) { throw new ParameterException("未找到page信息结果"); } paperService.savePaperAndPages(paperEntity, pages); updateStudentByPaper(user, student.getId(), false); return UpdateTimeVo.create(); } finally { concurrentService.getReadWriteLock(LockType.STUDENT + "-" + student.getId()).writeLock().unlock(); } } @Transactional @Override public Integer importCetAbsent(List students) { List list = new ArrayList(); for (ImportCetAbsentDomain domain : students) { if (domain.getExamId() == null) { throw new StatusException("考试id不能为空"); } if (domain.getExamNumber() == null) { throw new StatusException("准考证号不能为空"); } // if (domain.getAbsent() == null) { // throw new StatusException("缺考信息不能为空"); // } StudentEntity entity = this.findByExamAndSubjectCodeAndExamNumber(domain.getExamId(), domain.getSubjectCode(), domain.getExamNumber()); if (entity == null) { throw new StatusException("未找到考生"); } entity.setBreachCode(domain.getBreachCode()); // entity.setExamStatus(domain.getAbsent() ? ExamStatus.ABSENT : // null); list.add(entity); } this.updateBatchById(list); return list.size(); } @Override public List exportCetData(ExportCetMarkingQueryVo query) { if (query.getExamId() == null) { throw new ParameterException("examId不能为空"); } ExamEntity exam = examService.getById(query.getExamId()); if (exam == null) { throw new ParameterException("未找到考试"); } if (CollectionUtils.isEmpty(exam.getPaperTypeBarcodeContent())) { throw new ParameterException("该考试条码值未设置"); } if (!ExamMode.CET.equals(exam.getMode())) { throw new ParameterException("该考试不是CET"); } IPage iPage = baseMapper .listCetMarkingPage(new Page(query.getPageNumber(), query.getPageSize()), query); if (CollectionUtils.isNotEmpty(iPage.getRecords())) { String imageTransferDir = sysProperty.getTransferDir(); Map> structs = new HashMap<>(); Map cardMap = new HashMap<>(); new BatchSetDataUtil() { @Override protected void setData(List dataList) { List ids = dataList.stream().map(e -> e.getId()).collect(Collectors.toList()); List totalpages = paperPageService.listByStudentIds(ids); List totalpapers = paperService.findByStudentIds(ids); Map> totalpagesmap = ofPage(totalpages); Map> totalpapersmap = ofPaper(totalpapers); for (ExportCetVo vo : dataList) { disposeStudent(vo, exam, totalpagesmap.get(vo.getId()), totalpapersmap.get(vo.getId()), imageTransferDir, structs, cardMap); } } }.setDataForBatch(iPage.getRecords(), 200); } return iPage.getRecords(); } private void disposeStudent(ExportCetVo student, ExamEntity exam, List pages, List papers, String imageTransferDir, Map> structs, Map cardMap) { int subject = Integer.valueOf(student.getSubjectCode()); if (subject > 2) { if (student.getExamStatus().equals(ExamStatus.ABSENT)) { student.setPaperType("000000"); } else { student.setPaperType("888888"); } } else { if (StringUtils.isBlank(student.getPaperType()) || "#".equals(student.getPaperType())) { student.setPaperType("000000"); } else if ("?".equals(student.getPaperType()) || !exam.getPaperTypeBarcodeContent().contains(student.getPaperType())) { student.setPaperType("999999"); } } Map pmap = new HashMap<>(); for (PaperCetVo v : papers) { pmap.put(v.getId(), v); } student.setAnswer(getCetAnswer(structs, pages, student.getSubjectCode())); AnswerCardEntity card = getCard(cardMap, student.getExamId(), student.getCardNumber()); Set sliceSet = new LinkedHashSet<>(); setCardStatus(student, card, pages, pmap); int index = 0; for (PaperPageCetVo p : pages) { if (CollectionUtils.isNotEmpty(p.getSlicePath())) { for (int i = 0; i < p.getSlicePath().size(); i++) { String sliceName = card.getSliceName().get(index); sliceSet.add(sliceName); index++; } } } // 获取图片大小 List sliceImageInfo = new ArrayList(); student.setSliceImageInfo(sliceImageInfo); for (String sliceName : sliceSet) { String mirrorSlicePath = toolExportService.getCetSliceUri(student.getExamId(), student.getExamNumber(), sliceName); File targetSliceFile = new File(imageTransferDir + "/" + mirrorSlicePath); sliceImageInfo.add(sliceName + "-" + targetSliceFile.length()); } } private Map> ofPage(List list) { Map> map = new HashMap<>(); for (PaperPageCetVo p : list) { List tem = map.get(p.getStudentId()); if (tem == null) { tem = new ArrayList<>(); map.put(p.getStudentId(), tem); } tem.add(p); } return map; } private Map> ofPaper(List list) { Map> map = new HashMap<>(); for (PaperCetVo p : list) { List tem = map.get(p.getStudentId()); if (tem == null) { tem = new ArrayList<>(); map.put(p.getStudentId(), tem); } tem.add(p); } return map; } private AnswerCardEntity getCard(Map cardMap, Long examId, Integer cardNumber) { AnswerCardEntity card = cardMap.get(cardNumber); if (card == null) { card = answerCardService.findByExamAndNumber(examId, cardNumber); cardMap.put(cardNumber, card); } return card; } private void setCardStatus(ExportCetVo student, AnswerCardEntity card, List pages, Map pmap) { int subject = Integer.valueOf(student.getSubjectCode()); if (subject > 2) { setCardStatusSmall(student, card, pages, pmap); } else { setCardStatusCet(student, card, pages, pmap); } } private void setCardStatusSmall(ExportCetVo student, AnswerCardEntity card, List pages, Map pmap) { PaperPageCetVo p = pages.get(0); if (ExamStatus.ABSENT.equals(student.getExamStatus())) { if (pmap.get(p.getPaperId()).getQuestionFilled()) { student.setCardFirst(1); } else { student.setCardFirst(0); } } else { student.setCardFirst(0); } student.setCardSecond(0); } private void setCardStatusCet(ExportCetVo student, AnswerCardEntity card, List pages, Map pmap) { if (card.getPaperCount() == 1) { PaperPageCetVo p = pages.get(0); if (ExamStatus.ABSENT.equals(student.getExamStatus())) { if (pmap.get(p.getPaperId()).getQuestionFilled()) { student.setCardFirst(1); } else if (isPaperTypeValid(p.getPaperType())) { student.setCardFirst(7); } else if (isPaperTypeEmpty(p.getPaperType())) { student.setCardFirst(0); } else { student.setCardFirst(7); } } else { if (isPaperTypeValid(p.getPaperType())) { student.setCardFirst(0); } else { student.setCardFirst(7); } } student.setCardSecond(0); } else { PaperPageCetVo fp = pages.get(0); PaperPageCetVo sp; if (card.getSinglePage()) { sp = pages.get(1); } else { sp = pages.get(2); } if (ExamStatus.ABSENT.equals(student.getExamStatus())) { if (pmap.get(fp.getPaperId()).getQuestionFilled()) { student.setCardFirst(1); } else if (isPaperTypeValid(fp.getPaperType())) { student.setCardFirst(7); } else if (isPaperTypeEmpty(fp.getPaperType())) { student.setCardFirst(0); } else { student.setCardFirst(7); } } else { if (isPaperTypeValid(fp.getPaperType())) { student.setCardFirst(0); } else { student.setCardFirst(7); } } if (ExamStatus.ABSENT.equals(student.getExamStatus())) { if (pmap.get(sp.getPaperId()).getQuestionFilled()) { student.setCardSecond(1); } else if (isPaperTypeValid(fp.getPaperType())) { student.setCardSecond(7); } else if (isPaperTypeEmpty(fp.getPaperType())) { student.setCardSecond(0); } else { student.setCardSecond(7); } } else { if (isPaperTypeValid(fp.getPaperType())) { student.setCardSecond(0); } else { student.setCardSecond(7); } } } } private boolean isPaperTypeEmpty(StringResult sr) { if (sr == null) { return true; } if (StringUtils.isBlank(sr.getResult())) { return true; } if ("#".equals(sr.getResult())) { return true; } return false; } private boolean isPaperTypeValid(StringResult sr) { if (sr == null) { return false; } if (StringUtils.isBlank(sr.getResult())) { return false; } if ("#".equals(sr.getResult()) || "?".equals(sr.getResult())) { return false; } return true; } private String getCetAnswer(Map> structs, List pages, String subjectCode) { List answers = new ArrayList(); List struct = structs.get(subjectCode); if (struct == null) { struct = questionService.findBySubjectCode(subjectCode); if (struct == null) { throw new ParameterException("科目:" + subjectCode + " 未上传试卷结构"); } structs.put(subjectCode, struct); } for (PaperPageCetVo page : pages) { disposeQuestionMark(page.getQuestion()); try { if (page.getQuestion() != null && CollectionUtils.isNotEmpty(page.getQuestion().getResult())) { answers.addAll(page.getQuestion().getResult()); } } catch (Exception e) { throw e; } } for (int i = 0; i < answers.size(); i++) { if ("#".equals(answers.get(i))) { answers.set(i, "."); } if (answers.get(i).length() > 1) { answers.set(i, ">"); } } int subject = Integer.valueOf(subjectCode); if (subject < 3) {// CET4 CET6 return StringUtils.join(answers, ""); } else {// 小语种 List tem = new ArrayList(); int index = 0; for (QuestionEntity s : struct) { if (s.getObjective()) { if (index >= answers.size()) { throw new ParameterException("科目:" + subjectCode + " 试卷结构和题卡客观题数量不一致"); } tem.add(answers.get(index)); index++; } else { tem.add("."); } } return StringUtils.join(tem, ""); } } @Transactional @Override public void updateCheckMark(Long studentId, Boolean tag) { LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper<>(); updateWrapper.set(StudentEntity::getCheckMark, tag); updateWrapper.eq(StudentEntity::getId, studentId); this.update(updateWrapper); } @Transactional @Override public void pictureCopy(StudentUploadVo vo) { concurrentService.getReadWriteLock(LockType.STUDENT + "-" + vo.getId()).writeLock().lock(); StudentEntity se = this.getById(vo.getId()); try { if (UploadStatus.WAITING_UPLOAD.equals(se.getFileUploadStatus())) { toolExportService.studentFileCopy(se.getId(), vo.getImageTransferMode()); this.updateFileUploadStatus(se.getId(), UploadStatus.UPLOADED); } } catch (Exception e) { this.updateFileUploadStatus(se.getId(), UploadStatus.ERROR); log.error("转存文件出错.studentId:" + se.getId(), e); } finally { concurrentService.getReadWriteLock(LockType.STUDENT + "-" + vo.getId()).writeLock().unlock(); } } @Transactional @Override public void uploadData(StudentUploadVo vo) { SchoolSession ss = sessionService.getSchoolSession(vo.getSchoolId()); if (ss == null) { return; } // log.info("markingcloud file upload: account={}, token={}", // ss.getAccount(), ss.getMarkingCloudToken()); SignatureInfo signatureInfo = new SignatureInfo(SignatureType.TOKEN, ss.getAccount(), ss.getMarkingCloudToken()); StudentEntity se = this.getById(vo.getId()); if (se == null) { return; } concurrentService.getReadWriteLock(LockType.STUDENT + "-" + vo.getId()).writeLock().lock(); try { if (se.getFileUploadStatus() == UploadStatus.WAITING_UPLOAD || se.getFileUploadStatus() == UploadStatus.ERROR) { log.info("开始上传文件,examId={}, examNumber={}", vo.getExamId(), vo.getExamNumber()); try { uploadFile(signatureInfo, se); this.updateFileUploadStatus(se.getId(), UploadStatus.UPLOADED); } catch (Exception e) { log.error("文件上传出错,examId=" + vo.getExamId() + ", examNumber=" + vo.getExamNumber(), e); this.updateFileUploadStatus(se.getId(), UploadStatus.ERROR); // 文件上传出错直接返回 return; } } if (se.getDataUploadStatus() == UploadStatus.WAITING_UPLOAD || se.getDataUploadStatus() == UploadStatus.ERROR) { log.info("开始上传数据,examId={}, examNumber={}", vo.getExamId(), vo.getExamNumber()); try { uploadData(signatureInfo, se); this.updateDataUploadStatus(se.getId(), UploadStatus.UPLOADED); } catch (Exception e) { log.error("数据上传出错,examId=" + vo.getExamId() + ", examNumber=" + vo.getExamNumber(), e); this.updateDataUploadStatus(se.getId(), UploadStatus.ERROR); } } } finally { concurrentService.getReadWriteLock(LockType.STUDENT + "-" + vo.getId()).writeLock().unlock(); } } private void uploadFile(SignatureInfo signatureInfo, StudentEntity student) throws Exception { // List sps = // studentPaperService.findByStudentId(student.getId()); // if (CollectionUtils.isEmpty(sps)) { // return; // } // List sheets = new ArrayList<>(); // List slices = new ArrayList<>(); // for (StudentPaperEntity sp : sps) { // List pages = // paperPageService.listByPaperId(sp.getPaperId()); // if (CollectionUtils.isNotEmpty(sps)) { // for (PaperPageEntity page : pages) { // sheets.add(page.getSheetPath()); // if (CollectionUtils.isNotEmpty(page.getSlicePath())) { // slices.addAll(page.getSlicePath()); // } // } // } // } // if (CollectionUtils.isNotEmpty(sheets)) { // int index = 0; // for (String s : sheets) { // index++; // FileUploadResponse res = markingcloudApiClient // .sheetFileUpload(signatureInfo, student.getExamId(), // student.getExamNumber(), index, // filePropertyService.getById(s).getMd5(), // UploadFile.build("file", getFileName(s), // IOUtils.toByteArray(fileStore.read(s)))); // if (res == null || !res.getSuccess()) { // throw new StatusException( // "sheet上传失败,Success:false.examId=" + student.getExamId() + // ",examNumber=" + student // .getExamNumber()); // } // } // } // if (CollectionUtils.isNotEmpty(slices)) { // int index = 0; // for (String s : slices) { // index++; // FileUploadResponse res = markingcloudApiClient // .sliceFileUpload(signatureInfo, student.getExamId(), // student.getExamNumber(), index, // filePropertyService.getById(s).getMd5(), // UploadFile.build("file", getFileName(s), // IOUtils.toByteArray(fileStore.read(s)))); // if (res == null || !res.getSuccess()) { // throw new StatusException( // "slice上传失败,Success:false.examId=" + student.getExamId() + // ",examNumber=" + student // .getExamNumber()); // } // } // } } private void uploadData(SignatureInfo signatureInfo, StudentEntity student) { // ExamEntity exam = examService.getById(student.getExamId()); // List sps = // studentPaperService.findByStudentId(student.getId()); // List sheets = new ArrayList<>(); // List slices = new ArrayList<>(); // List pageList = new ArrayList<>(); // if (CollectionUtils.isNotEmpty(sps)) { // for (StudentPaperEntity sp : sps) { // List pages = // paperPageService.listByPaperId(sp.getPaperId()); // if (CollectionUtils.isNotEmpty(sps)) { // pageList.addAll(pages); // for (PaperPageEntity page : pages) { // sheets.add(page.getSheetPath()); // if (CollectionUtils.isNotEmpty(page.getSlicePath())) { // slices.addAll(page.getSlicePath()); // } // } // } // } // } // //未扫描或者没有paper,需要删除考生原有上传状态 // if (student.getStatus().equals(ScanStatus.UNEXIST) || // CollectionUtils.isEmpty(sheets)) { // markingcloudApiClient.studentFileDelete(signatureInfo, exam.getId(), // student.getExamNumber()); // } // //有扫描结果,正常上传考生状态 // else { // DataUploadDto dto = new DataUploadDto(); // dto.setSheetCount(sheets.size()); // dto.setSliceCount(slices.size()); // dto.setExamNumber(student.getExamNumber()); // dto.setManual(student.getAssigned()); // dto.setAbsent(student.getOmrAbsent()); // dto.setCardNumber(student.getCardNumber()); // List answers = new ArrayList(); // int pageIndex = 0; // for (PaperPageEntity p : pageList) { // pageIndex++; // if (pageIndex == 1) { // dto.setPaperType(getPaperType(exam.getPaperTypeBarcodeContent(), // p.getPaperType())); // BatchPaperEntity bp = // batchPaperService.findByPaperId(p.getPaperId()); // dto.setBatchCode(bp != null ? bp.getBatchId().toString() : ""); // } // disposeQuestionMark(p.getQuestion()); // if (p.getQuestion() != null && // CollectionUtils.isNotEmpty(p.getQuestion().getResult())) { // answers.addAll(p.getQuestion().getResult()); // } // } // dto.setAnswers(StringUtils.join(answers, ",")); // List res = markingcloudApiClient // .dataUpload(signatureInfo, student.getExamId(), // Collections.singletonList(dto)); // if (CollectionUtils.isEmpty(res) || // StringUtils.isBlank(res.get(0).getExamNumber())) { // throw new StatusException( // "数据上传失败,Success:false.examId=" + student.getExamId() + ",examNumber=" // + student // .getExamNumber()); // } // } } // private String getFileName(String path) { // if (StringUtils.isBlank(path)) { // throw new StatusException("文件路径有误:" + (path == null ? "" : path)); // } // return path.substring(path.lastIndexOf("//") + 1); // } // private String getPaperType(List list, StringResult sr) { // String pt = sr != null ? sr.getResult() : null; // if (StringUtils.isBlank(pt)) { // return "#"; // } // if (OmrType.BARCODE == sr.getType()) { // if (CollectionUtils.isEmpty(list)) { // if (pt.length() > 1) { // return "#"; // } // pt = pt.toUpperCase(); // int pAscii = (int) pt.charAt(0); // if (pAscii >= 65 && pAscii <= 90) { // return pt; // } else { // return "#"; // } // } else { // int index = list.indexOf(pt); // if (index == -1) { // return "#"; // } // return String.valueOf((char) (index + 65)); // } // } else if (OmrType.FILL_AREA == sr.getType()) { // if (pt.length() > 1) { // return "#"; // } // pt = pt.toUpperCase(); // int pAscii = (int) pt.charAt(0); // if (pAscii >= 65 && pAscii <= 90) { // return pt; // } else { // return "#"; // } // } else { // return "#"; // } // } @Override @Transactional public void resetExamStatus(Long examId, Integer examNumberFillCount) { QueryWrapper wrapper = new QueryWrapper<>(); LambdaQueryWrapper lw = wrapper.lambda(); lw.eq(StudentEntity::getExamId, examId); List list = this.list(wrapper); for (StudentEntity student : list) { concurrentService.getReadWriteLock(LockType.STUDENT + "-" + student.getId()).writeLock().lock(); try { List studentPaperList = studentPaperService.findByStudentId(student.getId()); int omrExamNumberCount = 0; for (StudentPaperEntity studentPaper : studentPaperList) { PaperEntity paper = paperService.getById(studentPaper.getPaperId()); int paperExamNumberCount = paper.getOmrExamNumber().replace("#", "").length(); if (omrExamNumberCount < paperExamNumberCount) { omrExamNumberCount = paperExamNumberCount; } } resetExamStatus(student, omrExamNumberCount, examNumberFillCount); saveOrUpdate(student); } finally { concurrentService.getReadWriteLock(LockType.STUDENT + "-" + student.getId()).writeLock().unlock(); } } examService.updateExamNumberFillCount(examId, examNumberFillCount); } private void resetExamStatus(StudentEntity student, Integer omrExamNumberCount, Integer examNumberFillCount) { if (ScanStatus.UNEXIST.equals(student.getStatus())) { student.setExamStatus(null); } else if (!student.getQuestionFilled() && student.getSubjectiveFilled()) { student.setExamStatus(ExamStatus.UNCHECK); } else if (!student.getQuestionFilled() && !student.getSubjectiveFilled() && omrExamNumberCount >= examNumberFillCount) { student.setExamStatus(ExamStatus.UNCHECK); } else if (!student.getQuestionFilled() && !student.getSubjectiveFilled() && omrExamNumberCount < examNumberFillCount) { student.setExamStatus(ExamStatus.ABSENT); } else { student.setExamStatus(ExamStatus.OK); } } @Override @Transactional public void updateExamStatus(Long id, ExamStatus examStatus) { LambdaUpdateWrapper lw = new LambdaUpdateWrapper<>(); lw.set(StudentEntity::getExamStatus, examStatus); lw.eq(StudentEntity::getId, id); this.update(lw); } @Override public ImportResult importExamStatus(Long examId, ExamStatusCheckMode mode, InputStream inputStream) throws IOException { try { ImportResult ret = new ImportResult(); List failRecords = new ArrayList<>(); ret.setErrMsg(failRecords); Map examNumbers = new HashMap<>(); Map absentMap = new HashMap<>(); LineNumberReader lineNumberReader = new LineNumberReader(new InputStreamReader(inputStream)); // 获取字符串总长度 String line; int i = 0; while ((line = lineNumberReader.readLine()) != null) { i++; if (i == 1) { continue;// 第一行标题 } // 已读字符串长度 StringBuilder msg = new StringBuilder(); String[] str = line.split(","); if (str.length != 2) { msg.append(" 无法解析,请检查分隔符和数据"); failRecords.add(newError(i, msg.toString())); continue; } String examNumber = str[0]; String absent = str[1]; String subjectCode = str[3]; if (StringUtils.isBlank(examNumber)) { examNumber = null; msg.append(" 准考证号不能为空"); } else if (examNumber.length() < 15) { examNumber = null; msg.append(" 准考证号不能小于15位"); } if (StringUtils.isBlank(absent)) { msg.append(" 缺考标识不能为空"); } else if (!absent.equals("0") && !absent.equals("1")) { msg.append(" 缺考标识只能为0或1"); } if (examNumber != null) { if (examNumbers.containsKey(examNumber)) { msg.append(" 准考证号有重复"); } else { StudentEntity student = this.findByExamAndSubjectCodeAndExamNumber(examId, subjectCode, examNumber); if (student == null) { msg.append(" 准考证号不存在"); } else { examNumbers.put(examNumber, student); absentMap.put(examNumber, absent.equals("1")); } } } if (msg.length() > 0) { failRecords.add(newError(i, msg.toString())); continue; } } if (CollectionUtils.isNotEmpty(failRecords)) { return ret; } if (ExamStatusCheckMode.OVERRIDE.equals(mode)) { for (StudentEntity student : examNumbers.values()) { concurrentService.getReadWriteLock(LockType.STUDENT + "-" + student.getId()).writeLock().lock(); try { if (absentMap.get(student.getExamNumber())) { student.setExamStatus(ExamStatus.ABSENT); } else { student.setExamStatus(ExamStatus.OK); } saveOrUpdate(student); } finally { concurrentService.getReadWriteLock(LockType.STUDENT + "-" + student.getId()).writeLock() .unlock(); } } } if (ExamStatusCheckMode.COMPARE.equals(mode)) { for (StudentEntity student : examNumbers.values()) { concurrentService.getReadWriteLock(LockType.STUDENT + "-" + student.getId()).writeLock().lock(); try { if (absentMap.get(student.getExamNumber()) && !ExamStatus.ABSENT.equals(student.getExamStatus())) { student.setExamStatus(ExamStatus.UNCHECK); } if (!absentMap.get(student.getExamNumber()) && !ExamStatus.OK.equals(student.getExamStatus())) { student.setExamStatus(ExamStatus.UNCHECK); } saveOrUpdate(student); } finally { concurrentService.getReadWriteLock(LockType.STUDENT + "-" + student.getId()).writeLock() .unlock(); } } } return ret; } finally { if (inputStream != null) { inputStream.close(); } } } private String newError(int lineNum, String msg) { return "第" + lineNum + "行 " + msg; } @Override @Transactional public void updateAssignedCheckCount(Long id, boolean deleteHistory) { if (deleteHistory) { assignedCheckHistoryService.deleteByStudentId(id); } this.baseMapper.updateAssignedCheckCount(id); } @Override public int getCountByExamAndAssignedCheckCount(Long examId, int assignedCheckCount, OP op) { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.eq(StudentEntity::getExamId, examId); wrapper.eq(StudentEntity::getAssigned, true); if (OP.EQ == op) { wrapper.eq(StudentEntity::getAssignedCheckCount, assignedCheckCount); } else if (OP.GT == op) { wrapper.gt(StudentEntity::getAssignedCheckCount, assignedCheckCount); } else if (OP.GE == op) { wrapper.ge(StudentEntity::getAssignedCheckCount, assignedCheckCount); } else if (OP.LE == op) { wrapper.le(StudentEntity::getAssignedCheckCount, assignedCheckCount); } else if (OP.LT == op) { wrapper.lt(StudentEntity::getAssignedCheckCount, assignedCheckCount); } return this.count(wrapper); } @Override public int countByExamIdAndExamStatus(Long examId, ExamStatus examStatus) { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.eq(StudentEntity::getExamId, examId); wrapper.eq(StudentEntity::getExamStatus, examStatus); return this.count(wrapper); } @Override public List exportAssignedCheckPage(AssignedQueryDomain query) { List ret = this.baseMapper.exportAssignedCheckPage( new Page(query.getPageNumber(), query.getPageSize()), query); return ret; } @Override public PageResult queryAssignedCheckPage(AssignedQueryDomain query) { // 查询考生分页信息 IPage iPage = baseMapper .queryAssignedCheckPage(new Page<>(query.getPageNumber(), query.getPageSize()), query); if (CollectionUtils.isNotEmpty(iPage.getRecords()) && query.getWithPaper()) { Map map = new HashMap<>(); for (AnswerQueryVo vo : iPage.getRecords()) { List papers = new ArrayList<>(); vo.setPapers(papers); if (vo.getAuditorId() != null) { UserEntity au = userService.getById(vo.getAuditorId()); vo.setAuditorName(au.getLoginName()); } // if (vo.getCardPaperCount() != null) { // for (int i = 1; i <= vo.getCardPaperCount(); i++) { // AnswerPaperVo pv = new AnswerPaperVo(); // pv.setNumber(i); // papers.add(pv); // } // } map.put(vo.getId(), vo); } // 根据考生id查找绑定paper List studentIds = iPage.getRecords().stream().map(p -> p.getId()).collect(Collectors.toList()); List paperList = new BatchGetDataUtil() { @Override public List getData(List paramList) { return paperService.listByStudentIds(paramList); } }.getDataForBatch(studentIds, 20); if (CollectionUtils.isNotEmpty(paperList)) { Map paperMap = new HashMap<>(); for (StudentPaperVo p : paperList) { AnswerQueryVo vo = map.get(p.getStudentId()); if (vo == null) { continue; } List papers = vo.getPapers(); if (papers == null) { continue; } // if (papers.size() < p.getNumber()) { // continue; // } if (!p.getAssigned()) { continue; } // AnswerPaperVo pvo = papers.get(p.getNumber() - 1); AnswerPaperVo pvo = new AnswerPaperVo(); pvo.setId(p.getPaperId()); pvo.setNumber(p.getNumber()); pvo.setAssigned(p.getAssigned()); pvo.setAssignedSuspect(p.getAssignedSuspect()); papers.add(pvo); paperMap.put(p.getPaperId(), pvo); } // 查找page List paperIds = paperList.stream().map(p -> p.getPaperId()).collect(Collectors.toList()); List paperPageList = new BatchGetDataUtil() { @Override public List getData(List paramList) { return paperPageService.listByPaperList(paramList); } }.getDataForBatch(paperIds, 20); if (CollectionUtils.isNotEmpty(paperPageList)) { for (PaperPageEntity p : paperPageList) { AnswerPaperVo pvo = paperMap.get(p.getPaperId()); if (pvo == null) { continue; } List pages = pvo.getPages(); if (pages == null) { pages = new ArrayList<>(); pvo.setPages(pages); } AnswerPageVo pageVo = new AnswerPageVo(); pageVo.setIndex(p.getPageIndex()); pageVo.setSheetUri(p.getSheetPath()); pageVo.setSliceUri(p.getSlicePath()); pages.add(pageVo); } } } } else { for (AnswerQueryVo vo : iPage.getRecords()) { if (vo.getAuditorId() != null) { UserEntity au = userService.getById(vo.getAuditorId()); vo.setAuditorName(au.getLoginName()); } } } return PageUtil.of(iPage); } @Override public boolean apply(StudentEntity t, String account) { TaskLock taskLock = TaskLockUtil.getAssignedCheckTask(t.getExamId().toString()); boolean lock = taskLock.add(t.getId(), account); // 上锁失败直接返回 if (!lock) { return false; } // 重复校验任务状态 if (t.getAssignedCheckCount() == 0) { return true; } else { taskLock.remove(t.getId()); return false; } } @Override public boolean hasAppliedAssignedCheckTask(StudentEntity t, String account) { TaskLock taskLock = TaskLockUtil.getAssignedCheckTask(t.getExamId().toString()); return taskLock.exist(t.getId(), account); } @Override public TaskStatusVo getAssignedCheckTaskStatus(Long examId, User user) { TaskStatusVo status = new TaskStatusVo(); if (Role.AUDITOR.equals(user.getRole())) { status.setFinishCount(assignedCheckHistoryService.getCountByUserId(user.getId(), examId)); status.setTodoCount(this.getCountByExamAndAssignedCheckCount(examId, 0, OP.EQ)); } else { status.setFinishCount(this.getCountByExamAndAssignedCheckCount(examId, 2, OP.GE)); status.setTodoCount(this.getCountByExamAndAssignedCheckCount(examId, 1, OP.EQ)); } return status; } @Override public void releaseAssignedCheckTaskByUser(Long examId, String account) { TaskLock taskLock = TaskLockUtil.getAssignedCheckTask(examId.toString()); taskLock.clear(account); } @Override public AssignedTaskSaveVo submitAssignedCheckTask(AssginedTaskResult result, User user) { StudentEntity student = getById(result.getId()); if (student == null) { throw new ParameterException("考生信息未找到"); } if (student.getAssignedCheckCount() == 0 && !this.hasAppliedAssignedCheckTask(student, user.getAccount())) { throw new ParameterException("任务非本人领取"); } concurrentService.getReadWriteLock(LockType.STUDENT + "-" + student.getId()).writeLock().lock(); try { assignedCheckHistoryService.save(user.getId(), student.getId(), student.getExamId()); for (AssignedTaskResultPaper paper : result.getPapers()) { paperService.updatePaperAssignedSuspect(student.getId(), paper.getNumber(), paper.getAssignedSuspect()); } updateStudentByPaper(user, student.getId(), false); updateAssignedCheckCount(student.getId(), false); } finally { concurrentService.getReadWriteLock(LockType.STUDENT + "-" + student.getId()).writeLock().unlock(); } AssignedTaskSaveVo vo = new AssignedTaskSaveVo(); vo.setId(student.getId()); vo.setStatus(this.getAssignedCheckTaskStatus(student.getExamId(), user)); return vo; } @Override public List getAssignedCheckTaskHistory(Long id, Long pageSize, User user) { StudentEntity student = this.getById(id); List result = this.baseMapper.getAssignedCheckTaskHistory(id, pageSize, user.getId(), student.getExamId()); for (AnswerQueryVo t : result) { t = toTaskVo(t); } return result; } @Override public AnswerQueryVo getAssignedCheckTask(Long examId, String account) { int retry = 0; AnswerQueryVo task = null; while (task == null) { List list = this.findUnCheck(examId, retry * 20, 20, 0); if (list.isEmpty()) { break; } for (AnswerQueryVo t : list) { StudentEntity student = this.getById(t.getId()); if (this.apply(student, account)) { task = toTaskVo(t); break; } } if (task == null) { retry++; } } if (task == null) { throw NotFoundExceptions.NO_STUDENT_ANSWER_TASK; } return task; } private List findUnCheck(Long examId, int pageNumber, int pageSize, int checkCount) { return this.baseMapper.findUnCheck(examId, pageNumber, pageSize, checkCount); } private AnswerQueryVo toTaskVo(AnswerQueryVo t) { List papers = new ArrayList<>(); t.setPapers(papers); // if (t.getCardPaperCount() != null) { // for (int i = 1; i <= t.getCardPaperCount(); i++) { // AnswerPaperVo pv = new AnswerPaperVo(); // pv.setNumber(i); // papers.add(pv); // } // } List studentIds = new ArrayList<>(); studentIds.add(t.getId()); List paperList = new BatchGetDataUtil() { @Override public List getData(List paramList) { return paperService.listByStudentIds(paramList); } }.getDataForBatch(studentIds, 20); if (CollectionUtils.isNotEmpty(paperList)) { Map paperMap = new HashMap<>(); for (StudentPaperVo p : paperList) { AnswerQueryVo vo = t; if (vo == null) { continue; } // if (papers.size() < p.getNumber()) { // continue; // } if (!p.getAssigned()) { continue; } AnswerPaperVo pvo = new AnswerPaperVo(); pvo.setId(p.getPaperId()); pvo.setNumber(p.getNumber()); pvo.setAssigned(p.getAssigned()); pvo.setAssignedSuspect(p.getAssignedSuspect()); papers.add(pvo); paperMap.put(p.getPaperId(), pvo); } // 查找page List paperIds = paperList.stream().map(p -> p.getPaperId()).collect(Collectors.toList()); List paperPageList = new BatchGetDataUtil() { @Override public List getData(List paramList) { return paperPageService.listByPaperList(paramList); } }.getDataForBatch(paperIds, 20); if (CollectionUtils.isNotEmpty(paperPageList)) { for (PaperPageEntity p : paperPageList) { AnswerPaperVo pvo = paperMap.get(p.getPaperId()); if (pvo == null) { continue; } List pages = pvo.getPages(); if (pages == null) { pages = new ArrayList<>(); pvo.setPages(pages); } AnswerPageVo pageVo = new AnswerPageVo(); pageVo.setIndex(p.getPageIndex()); pageVo.setSheetUri(p.getSheetPath()); pageVo.setSliceUri(p.getSlicePath()); pages.add(pageVo); } } } return t; } @Override public StudentAnswerVo studentAnswer(Long batchId, Long studentId) { if (batchId == null) { throw new ParameterException("batchId不能为空"); } if (studentId == null) { throw new ParameterException("studentId不能为空"); } StudentAnswerVo ret = new StudentAnswerVo(); ret.setStudentId(studentId); ret.setPapers(new ArrayList<>()); List paperList = paperService.listByBatchIdAndStudentId(batchId, studentId); if (CollectionUtils.isNotEmpty(paperList)) { Map paperMap = new HashMap<>(); for (StudentPaperVo p : paperList) { AnswerPaperVo pvo = new AnswerPaperVo(); pvo.setId(p.getPaperId()); pvo.setNumber(p.getNumber()); pvo.setAssigned(p.getAssigned()); pvo.setPages(new ArrayList<>()); ret.getPapers().add(pvo); paperMap.put(p.getPaperId(), pvo); } // 查找page List paperIds = paperList.stream().map(p -> p.getPaperId()).collect(Collectors.toList()); List paperPageList = paperPageService.listByPaperList(paperIds); if (CollectionUtils.isNotEmpty(paperPageList)) { for (PaperPageEntity p : paperPageList) { AnswerPaperVo pvo = paperMap.get(p.getPaperId()); if (pvo == null) { continue; } AnswerPageVo pageVo = new AnswerPageVo(); pageVo.setIndex(p.getPageIndex()); pageVo.setSheetUri(p.getSheetPath()); pageVo.setSliceUri(p.getSlicePath()); pageVo.setAbsent(p.getAbsent()); pageVo.setBreach(p.getBreach()); pageVo.setPaperType(p.getPaperType()); pageVo.setQuestion(p.getQuestion()); pageVo.setSelective(p.getSelective()); pageVo.setRecogData(p.getRecogData()); pvo.getPages().add(pageVo); } } } return ret; } @Override public List scanProgress(Long examId, String subjectCode) { return this.baseMapper.scanProgress(examId, subjectCode); } @Override public PageResult examRoomScannedPage(ExamRoomScannedQuery query) { // 查询考生分页信息 IPage iPage = baseMapper .examRoomScannedPage(new Page<>(query.getPageNumber(), query.getPageSize()), query); if (CollectionUtils.isNotEmpty(iPage.getRecords())) { for (ExamRoomScannedVo vo : iPage.getRecords()) { if (vo.getScannedCount() == null || vo.getScannedCount() == 0) { vo.setScanned("未扫描"); } else { vo.setScanned("已扫描"); } } } return PageUtil.of(iPage); } @Override public List examRoomScannedList(ExamRoomScannedQuery query) { return examRoomScannedPage(query).getResult(); } @Override public PageResult studentPage(StudentPageQuery query) { // 查询考生分页信息 IPage iPage = baseMapper.studentPage(new Page<>(query.getPageNumber(), query.getPageSize()), query); if (CollectionUtils.isNotEmpty(iPage.getRecords())) { for (StudentPageVo vo : iPage.getRecords()) { if (ScanStatus.SCANNED.equals(vo.getStatus())) { vo.setScanned("已扫描"); } else { vo.setScanned("未扫描"); } } } return PageUtil.of(iPage); } @Override public List studentList(StudentPageQuery query) { return studentPage(query).getResult(); } @Override public List studentExportList(AnswerQueryDomain query) { return baseMapper.studentExport(new Page<>(query.getPageNumber(), query.getPageSize()), query).getRecords(); } @Override public List studentExamRoomExportList(AnswerQueryDomain query) { return baseMapper.studentExamRoomExport(new Page<>(query.getPageNumber(), query.getPageSize()), query) .getRecords(); } @Override public ImportBreachResult breachImport(Long examId, String subjectCode, MultipartFile file) { // 暂存临时文件 File temDir = new File("temp/" + FastUUID.get() + "/"); try { temDir.mkdirs(); File excel = new File(temDir.getAbsolutePath() + "/breach.txt"); try { file.transferTo(excel); } catch (Exception e) { throw new RuntimeException("系统错误", e); } // 校验Excel ImportBreachResult ret = null; InputStream in = null; try { in = new FileInputStream(excel); ret = breachImportCheck(examId, subjectCode, in); } catch (IOException e) { throw new RuntimeException("系统错误", e); } finally { if (in != null) { try { in.close(); } catch (IOException e) { } } } // 根据校验结果上传文件 if (ret != null && ret.getSuccess()) { InputStream excelIn = null; try { String md5 = MD5Util.md5Hex(excel); excelIn = new FileInputStream(excel); fileService.uploadBreach(excelIn, md5, examId, subjectCode); } catch (IOException e) { throw new RuntimeException("系统错误", e); } finally { if (excelIn != null) { try { excelIn.close(); } catch (IOException e) { } } } File info = new File(temDir.getAbsolutePath() + "/breach-info.txt"); InputStream infoIn = null; try { FileUtils.write(info, ret.getBreachCount().toString(), "utf-8"); String md5 = MD5Util.md5Hex(info); infoIn = new FileInputStream(info); fileService.uploadBreachInfo(infoIn, md5, examId, subjectCode); } catch (IOException e) { throw new RuntimeException("系统错误", e); } finally { if (infoIn != null) { try { infoIn.close(); } catch (IOException e) { } } } } return ret; } finally { try { FileUtils.deleteDirectory(temDir); } catch (IOException e) { throw new RuntimeException("系统错误", e); } } } private ImportBreachResult breachImportCheck(Long examId, String subjectCode, InputStream in) { List lineList = null; try { lineList = IOUtils.readLines(in, "UTF-8"); } catch (IOException e) { throw new StatusException("读取文件出错", e); } ImportBreachResult ret = new ImportBreachResult(); List failRecords = new ArrayList<>(); ret.setErrMsg(failRecords); Set examNumberSet = new HashSet<>(); for (int i = 0; i < lineList.size(); i++) { String lineString = lineList.get(i); if (StringUtils.isBlank(lineString)) { continue; } StringBuilder msg = new StringBuilder(); String[] line = lineString.split(","); if (line.length != 3) { msg.append(" 格式错误"); } else { String examNumber = trimAndNullIfBlank(line[0]); if (StringUtils.isBlank(examNumber)) { msg.append(" 准考证号不能为空"); } else { StudentEntity s = findByExamAndSubjectCodeAndExamNumber(examId, subjectCode, examNumber); if (s == null) { msg.append(" 准考证号未找到"); } else { if (examNumberSet.contains(examNumber)) { msg.append(" 准考证号重复"); } else { examNumberSet.add(examNumber); } } } String breach = trimAndNullIfBlank(line[1]); if (StringUtils.isNotBlank(breach)) { ret.setBreachCount(ret.getBreachCount() + 1); } } if (msg.length() > 0) { failRecords.add(errorMsg(i + 2, msg.toString())); } } if (CollectionUtils.isNotEmpty(failRecords)) { ret.setSuccess(false); return ret; } ret.setSuccess(true); return ret; } private String errorMsg(int lineNum, String msg) { return "第" + lineNum + "行 " + msg; } @Override public ImportBreachResult custStatusImport(Long examId, String subjectCode, MultipartFile file) { // 暂存临时文件 File temDir = new File("temp/" + FastUUID.get() + "/"); try { temDir.mkdirs(); File excel = new File(temDir.getAbsolutePath() + "/cust-status.txt"); try { file.transferTo(excel); } catch (Exception e) { throw new RuntimeException("系统错误", e); } // 校验Excel ImportBreachResult ret = null; InputStream in = null; try { in = new FileInputStream(excel); ret = custStatusImportCheck(examId, subjectCode, in); } catch (IOException e) { throw new RuntimeException("系统错误", e); } finally { if (in != null) { try { in.close(); } catch (IOException e) { } } } // 根据校验结果上传文件 if (ret != null && ret.getSuccess()) { InputStream excelIn = null; try { String md5 = MD5Util.md5Hex(excel); excelIn = new FileInputStream(excel); fileService.uploadCustStatus(in, md5, examId, subjectCode); } catch (IOException e) { throw new RuntimeException("系统错误", e); } finally { if (excelIn != null) { try { excelIn.close(); } catch (IOException e) { } } } File info = new File(temDir.getAbsolutePath() + "/cust-status-info.txt"); InputStream infoIn = null; try { FileUtils.write(info, ret.getBreachCount().toString(), "utf-8"); String md5 = MD5Util.md5Hex(info); infoIn = new FileInputStream(info); fileService.uploadCustStatusInfo(infoIn, md5, examId, subjectCode); } catch (IOException e) { throw new RuntimeException("系统错误", e); } finally { if (infoIn != null) { try { infoIn.close(); } catch (IOException e) { } } } } return ret; } finally { try { FileUtils.deleteDirectory(temDir); } catch (IOException e) { throw new RuntimeException("系统错误", e); } } } private ImportBreachResult custStatusImportCheck(Long examId, String subjectCode, InputStream in) { List lineList = null; try { lineList = IOUtils.readLines(in, "UTF-8"); } catch (IOException e) { throw new StatusException("读取文件出错", e); } ImportBreachResult ret = new ImportBreachResult(); List failRecords = new ArrayList<>(); ret.setErrMsg(failRecords); Set examNumberSet = new HashSet<>(); for (int i = 0; i < lineList.size(); i++) { String lineString = lineList.get(i); if (StringUtils.isBlank(lineString)) { continue; } StringBuilder msg = new StringBuilder(); String[] line = lineString.split(","); if (line.length != 3) { msg.append(" 格式错误"); } else { String examNumber = trimAndNullIfBlank(line[0]); if (StringUtils.isBlank(examNumber)) { msg.append(" 准考证号不能为空"); } else { StudentEntity s = findByExamAndSubjectCodeAndExamNumber(examId, subjectCode, examNumber); if (s == null) { msg.append(" 准考证号未找到"); } else { if (examNumberSet.contains(examNumber)) { msg.append(" 准考证号重复"); } else { examNumberSet.add(examNumber); } } } String breach = trimAndNullIfBlank(line[1]); if (StringUtils.isNotBlank(breach)) { ret.setBreachCount(ret.getBreachCount() + 1); } } if (msg.length() > 0) { failRecords.add(errorMsg(i + 2, msg.toString())); } } if (CollectionUtils.isNotEmpty(failRecords)) { ret.setSuccess(false); return ret; } ret.setSuccess(true); return ret; } @Override public List countStudent(Long examId) { if (examId == null) { throw new ParameterException("examId不能为空"); } return baseMapper.countStudent(examId); } @Override public List exportAssignedCheck(Long examId, String subjectCode) { return baseMapper.exportAssignedCheck(examId, subjectCode); } @Override public void resetAssignedCheck(Long examId, String subjectCode) { QueryWrapper wrapper = new QueryWrapper<>(); LambdaQueryWrapper lw = wrapper.lambda(); lw.eq(StudentEntity::getExamId, examId); lw.eq(StudentEntity::getSubjectCode, subjectCode); lw.eq(StudentEntity::getAssigned, true); lw.eq(StudentEntity::getAssignedSuspect, true); lw.gt(StudentEntity::getAssignedCheckCount, 1); List list = this.list(wrapper); for (StudentEntity student : list) { concurrentService.getReadWriteLock(LockType.STUDENT + "-" + student.getId()).writeLock().lock(); try { student.setAbsentSuspect(false); student.setAssignedCheckCount(1); saveOrUpdate(student); // assignedCheckHistoryService.deleteByStudentId(student.getId(),Role.AUDITOR); } finally { concurrentService.getReadWriteLock(LockType.STUDENT + "-" + student.getId()).writeLock().unlock(); } } } @Transactional @Override public void updateImageCheckStatus(Long id, ImageCheckStatus status) { LambdaUpdateWrapper lw = new LambdaUpdateWrapper<>(); lw.set(StudentEntity::getImageCheckStatus, status); lw.eq(StudentEntity::getId, id); update(lw); } }