StudentServiceImpl.java 110 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629
  1. package cn.com.qmth.scancentral.service.impl;
  2. import java.io.File;
  3. import java.io.FileInputStream;
  4. import java.io.IOException;
  5. import java.io.InputStream;
  6. import java.math.BigDecimal;
  7. import java.util.ArrayList;
  8. import java.util.Arrays;
  9. import java.util.Date;
  10. import java.util.HashMap;
  11. import java.util.HashSet;
  12. import java.util.LinkedHashSet;
  13. import java.util.List;
  14. import java.util.Map;
  15. import java.util.Set;
  16. import java.util.concurrent.ExecutorService;
  17. import java.util.concurrent.LinkedBlockingQueue;
  18. import java.util.concurrent.ThreadPoolExecutor;
  19. import java.util.concurrent.TimeUnit;
  20. import java.util.stream.Collectors;
  21. import javax.validation.constraints.NotNull;
  22. import org.apache.commons.collections4.CollectionUtils;
  23. import org.apache.commons.io.FileUtils;
  24. import org.apache.commons.io.IOUtils;
  25. import org.apache.commons.lang3.StringUtils;
  26. import org.slf4j.Logger;
  27. import org.slf4j.LoggerFactory;
  28. import org.springframework.beans.BeanUtils;
  29. import org.springframework.beans.factory.annotation.Autowired;
  30. import org.springframework.stereotype.Service;
  31. import org.springframework.transaction.annotation.Transactional;
  32. import org.springframework.web.multipart.MultipartFile;
  33. import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
  34. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
  35. import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
  36. import com.baomidou.mybatisplus.core.metadata.IPage;
  37. import com.baomidou.mybatisplus.core.toolkit.Wrappers;
  38. import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
  39. import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
  40. import com.google.gson.Gson;
  41. import com.qmth.boot.core.collection.PageResult;
  42. import com.qmth.boot.core.concurrent.service.ConcurrentService;
  43. import com.qmth.boot.core.exception.ParameterException;
  44. import com.qmth.boot.core.exception.StatusException;
  45. import com.qmth.boot.tools.excel.ExcelReader;
  46. import com.qmth.boot.tools.excel.enums.ExcelType;
  47. import com.qmth.boot.tools.uuid.FastUUID;
  48. import cn.com.qmth.scancentral.bean.AbsentQueryDomain;
  49. import cn.com.qmth.scancentral.bean.AnswerDeleteDomain;
  50. import cn.com.qmth.scancentral.bean.AnswerQueryDomain;
  51. import cn.com.qmth.scancentral.bean.AssignedQueryDomain;
  52. import cn.com.qmth.scancentral.bean.ImportCetAbsentDomain;
  53. import cn.com.qmth.scancentral.bean.ImportStudentDomain;
  54. import cn.com.qmth.scancentral.bean.PageDeleteDomain;
  55. import cn.com.qmth.scancentral.bean.User;
  56. import cn.com.qmth.scancentral.bean.answersave.ArrayResult;
  57. import cn.com.qmth.scancentral.bean.answersave.BoolResult;
  58. import cn.com.qmth.scancentral.bean.answersave.StringResult;
  59. import cn.com.qmth.scancentral.bean.omredit.OmrEditDomain;
  60. import cn.com.qmth.scancentral.bean.omredit.OmrEditPaper;
  61. import cn.com.qmth.scancentral.bean.omredit.OmrFieldEditDomain;
  62. import cn.com.qmth.scancentral.bean.refix.AnswerRefixDomain;
  63. import cn.com.qmth.scancentral.bean.refix.PageRefixDomain;
  64. import cn.com.qmth.scancentral.bean.refix.PaperRefixDomain;
  65. import cn.com.qmth.scancentral.config.SysProperty;
  66. import cn.com.qmth.scancentral.consumer.BreachImportConsumer;
  67. import cn.com.qmth.scancentral.consumer.CustStatusImportConsumer;
  68. import cn.com.qmth.scancentral.dao.StudentDao;
  69. import cn.com.qmth.scancentral.entity.AnswerCardEntity;
  70. import cn.com.qmth.scancentral.entity.ExamEntity;
  71. import cn.com.qmth.scancentral.entity.OmrGroupEntity;
  72. import cn.com.qmth.scancentral.entity.PaperEntity;
  73. import cn.com.qmth.scancentral.entity.PaperPageEntity;
  74. import cn.com.qmth.scancentral.entity.QuestionEntity;
  75. import cn.com.qmth.scancentral.entity.StudentEntity;
  76. import cn.com.qmth.scancentral.entity.StudentPaperEntity;
  77. import cn.com.qmth.scancentral.entity.SubjectEntity;
  78. import cn.com.qmth.scancentral.entity.UserEntity;
  79. import cn.com.qmth.scancentral.enums.AsyncTaskStatus;
  80. import cn.com.qmth.scancentral.enums.ExamMode;
  81. import cn.com.qmth.scancentral.enums.ExamStatus;
  82. import cn.com.qmth.scancentral.enums.ExamStatusCheckMode;
  83. import cn.com.qmth.scancentral.enums.GroupType;
  84. import cn.com.qmth.scancentral.enums.ImageCheckStatus;
  85. import cn.com.qmth.scancentral.enums.LockType;
  86. import cn.com.qmth.scancentral.enums.OP;
  87. import cn.com.qmth.scancentral.enums.OmrField;
  88. import cn.com.qmth.scancentral.enums.Role;
  89. import cn.com.qmth.scancentral.enums.ScanStatus;
  90. import cn.com.qmth.scancentral.enums.UploadStatus;
  91. import cn.com.qmth.scancentral.exception.NotFoundExceptions;
  92. import cn.com.qmth.scancentral.exception.ParameterExceptions;
  93. import cn.com.qmth.scancentral.model.ManualAbsentImportDTO;
  94. import cn.com.qmth.scancentral.service.AnswerCardService;
  95. import cn.com.qmth.scancentral.service.AnswerCardSubjectService;
  96. import cn.com.qmth.scancentral.service.AssignedCheckHistoryService;
  97. import cn.com.qmth.scancentral.service.AsyncTaskService;
  98. import cn.com.qmth.scancentral.service.BatchService;
  99. import cn.com.qmth.scancentral.service.ExamService;
  100. import cn.com.qmth.scancentral.service.FileService;
  101. import cn.com.qmth.scancentral.service.OmrGroupService;
  102. import cn.com.qmth.scancentral.service.OmrTaskService;
  103. import cn.com.qmth.scancentral.service.PaperPageService;
  104. import cn.com.qmth.scancentral.service.PaperService;
  105. import cn.com.qmth.scancentral.service.QuestionService;
  106. import cn.com.qmth.scancentral.service.StudentPaperService;
  107. import cn.com.qmth.scancentral.service.StudentService;
  108. import cn.com.qmth.scancentral.service.SubjectService;
  109. import cn.com.qmth.scancentral.service.ToolExportService;
  110. import cn.com.qmth.scancentral.service.UserService;
  111. import cn.com.qmth.scancentral.support.SpringContextHolder;
  112. import cn.com.qmth.scancentral.support.TaskLock;
  113. import cn.com.qmth.scancentral.support.TaskLockUtil;
  114. import cn.com.qmth.scancentral.util.BatchGetDataUtil;
  115. import cn.com.qmth.scancentral.util.BatchSetDataUtil;
  116. import cn.com.qmth.scancentral.util.MD5Util;
  117. import cn.com.qmth.scancentral.util.PageUtil;
  118. import cn.com.qmth.scancentral.vo.AbsentInfoVo;
  119. import cn.com.qmth.scancentral.vo.AbsentManualImportVo;
  120. import cn.com.qmth.scancentral.vo.AbsentQueryVo;
  121. import cn.com.qmth.scancentral.vo.AnswerDeleteVo;
  122. import cn.com.qmth.scancentral.vo.AnswerExportK12Vo;
  123. import cn.com.qmth.scancentral.vo.AnswerExportVo;
  124. import cn.com.qmth.scancentral.vo.AnswerRefixVo;
  125. import cn.com.qmth.scancentral.vo.ExportCetMarkingQueryVo;
  126. import cn.com.qmth.scancentral.vo.ExportCetVo;
  127. import cn.com.qmth.scancentral.vo.ImportStudentQueryVo;
  128. import cn.com.qmth.scancentral.vo.ImportStudentVo;
  129. import cn.com.qmth.scancentral.vo.PaperDeleteVo;
  130. import cn.com.qmth.scancentral.vo.ScanAnswerInfoVo;
  131. import cn.com.qmth.scancentral.vo.StudentUploadVo;
  132. import cn.com.qmth.scancentral.vo.UpdateTimeVo;
  133. import cn.com.qmth.scancentral.vo.answerquery.AnswerPageVo;
  134. import cn.com.qmth.scancentral.vo.answerquery.AnswerPaperVo;
  135. import cn.com.qmth.scancentral.vo.answerquery.AnswerQueryParam;
  136. import cn.com.qmth.scancentral.vo.answerquery.AnswerQueryVo;
  137. import cn.com.qmth.scancentral.vo.answerquery.StudentPaperVo;
  138. import cn.com.qmth.scancentral.vo.assginedcheck.AssginedTaskResult;
  139. import cn.com.qmth.scancentral.vo.assginedcheck.AssignedCheckExamRoomExport;
  140. import cn.com.qmth.scancentral.vo.assginedcheck.AssignedCheckExport;
  141. import cn.com.qmth.scancentral.vo.assginedcheck.AssignedTaskSaveVo;
  142. import cn.com.qmth.scancentral.vo.asynctask.BreachAndStatusImportTaskVo;
  143. import cn.com.qmth.scancentral.vo.asynctask.ExamStatusImportTaskVo;
  144. import cn.com.qmth.scancentral.vo.asynctask.ExamStatusResetTaskVo;
  145. import cn.com.qmth.scancentral.vo.examroom.ExamRoomScannedQuery;
  146. import cn.com.qmth.scancentral.vo.examroom.ExamRoomScannedVo;
  147. import cn.com.qmth.scancentral.vo.paper.PaperCetVo;
  148. import cn.com.qmth.scancentral.vo.paper.PaperPageCetVo;
  149. import cn.com.qmth.scancentral.vo.student.StudentAnswerVo;
  150. import cn.com.qmth.scancentral.vo.student.StudentExamRoomVo;
  151. import cn.com.qmth.scancentral.vo.student.StudentPageQuery;
  152. import cn.com.qmth.scancentral.vo.student.StudentPageVo;
  153. import cn.com.qmth.scancentral.vo.student.StudentQuery;
  154. import cn.com.qmth.scancentral.vo.student.StudentVo;
  155. import cn.com.qmth.scancentral.vo.studentimport.StudentCountVo;
  156. import cn.com.qmth.scancentral.vo.subject.SubjectScanProgressVo;
  157. import cn.com.qmth.scancentral.vo.subject.TaskIdVo;
  158. import cn.com.qmth.scancentral.vo.task.TaskStatusVo;
  159. @Service
  160. public class StudentServiceImpl extends ServiceImpl<StudentDao, StudentEntity> implements StudentService {
  161. private static final Logger log = LoggerFactory.getLogger(StudentService.class);
  162. private static ExecutorService exec;
  163. @Autowired
  164. private AsyncTaskService asyncTaskService;
  165. @Autowired
  166. private PaperService paperService;
  167. @Autowired
  168. private PaperPageService paperPageService;
  169. @Autowired
  170. private StudentPaperService studentPaperService;
  171. @Autowired
  172. private ExamService examService;
  173. @Autowired
  174. private SubjectService subjectService;
  175. @Autowired
  176. private BatchService batchService;
  177. @Autowired
  178. private AnswerCardService answerCardService;
  179. @Autowired
  180. private ConcurrentService concurrentService;
  181. @Autowired
  182. private OmrTaskService omrTaskService;
  183. @Autowired
  184. private OmrGroupService omrGroupService;
  185. @Autowired
  186. private QuestionService questionService;
  187. @Autowired
  188. private SysProperty sysProperty;
  189. @Autowired
  190. private ToolExportService toolExportService;
  191. @Autowired
  192. private AnswerCardSubjectService answerCardSubjectService;
  193. @Autowired
  194. private AssignedCheckHistoryService assignedCheckHistoryService;
  195. @Autowired
  196. private UserService userService;
  197. @Autowired
  198. private FileService fileService;
  199. static {
  200. int threadCount = 5;
  201. exec = new ThreadPoolExecutor(threadCount, threadCount, 0L, TimeUnit.SECONDS,
  202. new LinkedBlockingQueue<>(threadCount * 2), r -> {
  203. Thread t = new Thread(r);
  204. return t;
  205. }, (r, executor) -> {
  206. if (!executor.isShutdown()) {
  207. try {
  208. executor.getQueue().put(r);
  209. } catch (InterruptedException e) {
  210. throw new RuntimeException(e);
  211. }
  212. }
  213. });
  214. }
  215. /**
  216. * 整体更新考生绑定的paper并刷新考生状态,若集合为空则表示考生无扫描结果,需要在外部调用处对考生上锁
  217. *
  218. * @param id
  219. * @param studentPaperList
  220. */
  221. @Override
  222. @Transactional
  223. // @Lockable(name = LockType.STUDENT, key = "#id")
  224. public void updateStudentAndPaper(@NotNull User user, @NotNull Long id,
  225. @NotNull List<StudentPaperEntity> studentPaperList) {
  226. for (StudentPaperEntity studentPaper : studentPaperList) {
  227. studentPaper.setStudentId(id);
  228. }
  229. // 清空原有绑定关系
  230. studentPaperService.removeByStudentId(id);
  231. // 保存绑定关系
  232. studentPaperService.saveOrUpdateBatchByMultiId(studentPaperList);
  233. // 更新考生状态
  234. updateStudentByPaper(user, id, true);
  235. }
  236. /**
  237. * 根据考生当前绑定的paper刷新考生状态,需要在外部调用处对考生上锁
  238. *
  239. * @param id
  240. */
  241. @Override
  242. @Transactional
  243. // @Lockable(name = LockType.STUDENT, key = "#id")
  244. public void updateStudentByPaper(@NotNull User user, @NotNull Long id, @NotNull boolean updateOmrTask) {
  245. StudentEntity student = baseMapper.selectById(id);
  246. if (student == null) {
  247. throw new ParameterException("找不到对应的考生");
  248. }
  249. ExamEntity exam = examService.getById(student.getExamId());
  250. // 重置状态
  251. student.setIncomplete(false);
  252. student.setAssigned(false);
  253. student.setAssignedSuspect(false);
  254. student.setQuestionFilled(false);
  255. student.setSubjectiveFilled(false);
  256. student.setDevice(null);
  257. student.setCardNumber(null);
  258. student.setPaperType("#");
  259. student.setOmrAbsent(false);
  260. student.setExamStatus(ExamStatus.OK);
  261. int paperCount = 0;
  262. List<StudentPaperEntity> studentPaperList = studentPaperService.findByStudentId(id);
  263. int omrExamNumberCount = 0;
  264. for (StudentPaperEntity studentPaper : studentPaperList) {
  265. paperCount++;
  266. // 获取paper详情更新考生状态
  267. PaperEntity paper = paperService.getById(studentPaper.getPaperId());
  268. student.setAssigned(student.getAssigned() || paper.getAssigned());
  269. // student.setAssignedSuspect(student.getAssignedSuspect() ||
  270. // paper.getAssignedSuspect());
  271. student.setQuestionFilled(student.getQuestionFilled() || paper.getQuestionFilled());
  272. student.setSubjectiveFilled(student.getSubjectiveFilled() || paper.getSubjectiveFilled());
  273. student.setCardNumber(paper.getCardNumber());
  274. // 单独判断首张纸正面的识别结果
  275. if (studentPaper.getPaperNumber() == 1) {
  276. // 根据识别结果更新考生属性
  277. PaperPageEntity page = paperPageService.findPaperIdAndIndex(paper.getId(), 1);
  278. student.setPaperType(page.getPaperType() != null ? page.getPaperType().getResult() : "#");
  279. student.setOmrAbsent(page.getAbsent() == null ? false : page.getAbsent().getResult());
  280. student.setDevice(batchService.findByPaperId(paper.getId()).getDevice());
  281. }
  282. // 计算识别位数
  283. int paperExamNumberCount = paper.getOmrExamNumber().replace("#", "").length();
  284. if (omrExamNumberCount < paperExamNumberCount) {
  285. omrExamNumberCount = paperExamNumberCount;
  286. }
  287. }
  288. // 更新考生状态
  289. if (paperCount > 0) {
  290. AnswerCardEntity answerCard = answerCardService.findByExamAndNumber(student.getExamId(),
  291. student.getCardNumber());
  292. student.setIncomplete(paperCount != answerCard.getPaperCount());
  293. student.setStatus(ScanStatus.SCANNED);
  294. } else {
  295. student.setStatus(ScanStatus.UNEXIST);
  296. student.setExamStatus(null);
  297. }
  298. // 更新缺考校验状态
  299. if (exam.getExamNumberFillCount() != null) {
  300. resetExamStatus(student, omrExamNumberCount, exam.getExamNumberFillCount());
  301. }
  302. student.setFileUploadStatus(UploadStatus.WAITING_UPLOAD);
  303. student.setImageCheckStatus(ImageCheckStatus.WAITING);
  304. student.setDataUploadStatus(UploadStatus.WAITING_UPLOAD);
  305. student.setUpdaterId(user.getId());
  306. student.setUpdateTime(System.currentTimeMillis());
  307. saveOrUpdate(student);
  308. // try {
  309. // SignatureInfo signatureInfo = new SignatureInfo(SignatureType.TOKEN,
  310. // user.getAccount(),
  311. // user.getMarkingCloudToken());
  312. // apiClient.studentFileDelete(signatureInfo.toString(),
  313. // student.getExamId(), student.getExamNumber());
  314. // } catch (RetrofitResponseError e) {
  315. // e.printStackTrace();
  316. // if (e.getCode() == 401) {
  317. // throw AuthorizationException.SIGNATURE_INVALID;
  318. // } else {
  319. // throw e;
  320. // }
  321. // }
  322. if (updateOmrTask) {
  323. // 遍历固定任务分组
  324. List<OmrGroupEntity> gs = omrGroupService.findByExamIdAndSubjectCode(student.getExamId(),
  325. student.getSubjectCode());
  326. if (CollectionUtils.isNotEmpty(gs)) {
  327. for (OmrGroupEntity g : gs) {
  328. concurrentService.getReadWriteLock(LockType.OMR_GROUP + "-" + g.getId()).readLock().lock();
  329. omrTaskService.deleteByStudentIdAndGroupId(g.getId(), student.getId());
  330. // 默认分组重新生成识别对照任务,其他任务不生成
  331. if (g.getFixed()) {
  332. omrTaskService.saveTask(g, student.getId());
  333. }
  334. concurrentService.getReadWriteLock(LockType.OMR_GROUP + "-" + g.getId()).readLock().unlock();
  335. }
  336. }
  337. }
  338. }
  339. @Override
  340. public Integer getStudentAnswerCount(Long examId) {
  341. if (examId == null) {
  342. throw new ParameterException("examId不能为空");
  343. }
  344. QueryWrapper<StudentEntity> queryWrapper = new QueryWrapper<>();
  345. queryWrapper.lambda().eq(StudentEntity::getExamId, examId);
  346. queryWrapper.lambda().eq(StudentEntity::getCheckMark, true);
  347. return this.count(queryWrapper);
  348. }
  349. @Override
  350. public StudentVo findOne(StudentQuery query) {
  351. Long examId = query.getExamId();
  352. String examNumber = query.getExamNumber();
  353. String subjectCode = query.getSubjectCode();
  354. if (StringUtils.isBlank(examNumber) || StringUtils.isBlank(subjectCode)) {
  355. throw new ParameterException("examNumber subjectCode不能都为空");
  356. }
  357. QueryWrapper<StudentEntity> queryWrapper = new QueryWrapper<>();
  358. queryWrapper.lambda().eq(StudentEntity::getExamId, examId);
  359. queryWrapper.lambda().eq(StudentEntity::getExamNumber, examNumber);
  360. queryWrapper.lambda().eq(StudentEntity::getSubjectCode, subjectCode);
  361. StudentEntity s = baseMapper.selectOne(queryWrapper);
  362. if (s == null) {
  363. throw new ParameterException("未找到考生");
  364. }
  365. StudentVo vo = StudentVo.of(s);
  366. SubjectEntity sub = subjectService.findByExamIdAndCode(examId, s.getSubjectCode());
  367. vo.setSubjectName(sub.getName());
  368. return vo;
  369. }
  370. @Override
  371. public int getCountByExam(Long examId) {
  372. QueryWrapper<StudentEntity> wrapper = new QueryWrapper<>();
  373. LambdaQueryWrapper<StudentEntity> lw = wrapper.lambda();
  374. lw.eq(StudentEntity::getExamId, examId);
  375. return this.count(wrapper);
  376. }
  377. @Override
  378. public int getPackageCountByExam(Long examId) {
  379. return baseMapper.getPackageCountByExam(examId);
  380. }
  381. @Override
  382. public int getCountByExamAndScanStatus(Long examId, ScanStatus status) {
  383. QueryWrapper<StudentEntity> wrapper = new QueryWrapper<>();
  384. LambdaQueryWrapper<StudentEntity> lw = wrapper.lambda();
  385. lw.eq(StudentEntity::getExamId, examId);
  386. lw.eq(StudentEntity::getStatus, status);
  387. return this.count(wrapper);
  388. }
  389. @Override
  390. public List<StudentVo> packageList(StudentQuery query) {
  391. List<StudentVo> ret = new ArrayList<>();
  392. StudentVo one = findOne(query);
  393. if (one != null) {
  394. List<StudentEntity> list = findByExamAndPackage(query.getExamId(), one.getPackageCode(),
  395. one.getSubjectCode());
  396. if (CollectionUtils.isNotEmpty(list)) {
  397. for (StudentEntity e : list) {
  398. StudentVo vo = StudentVo.of(e);
  399. vo.setSubjectName(one.getSubjectName());
  400. ret.add(vo);
  401. }
  402. }
  403. }
  404. return ret;
  405. }
  406. @Override
  407. public List<StudentEntity> findByExamAndPackage(Long examId, String packageCode, String subjectCode) {
  408. if (examId == null) {
  409. throw new ParameterException("examId 不能为空");
  410. }
  411. if (StringUtils.isBlank(packageCode)) {
  412. throw new ParameterException("packageCode不能为空");
  413. }
  414. QueryWrapper<StudentEntity> queryWrapper = new QueryWrapper<>();
  415. queryWrapper.lambda().eq(StudentEntity::getExamId, examId);
  416. queryWrapper.lambda().eq(StudentEntity::getPackageCode, packageCode);
  417. if (StringUtils.isNotBlank(subjectCode)) {
  418. queryWrapper.lambda().eq(StudentEntity::getSubjectCode, subjectCode);
  419. }
  420. return this.list(queryWrapper);
  421. }
  422. @Override
  423. public int getAssignedCountByExam(Long examId) {
  424. QueryWrapper<StudentEntity> wrapper = new QueryWrapper<>();
  425. LambdaQueryWrapper<StudentEntity> lw = wrapper.lambda();
  426. lw.eq(StudentEntity::getExamId, examId);
  427. lw.eq(StudentEntity::getAssigned, true);
  428. return this.count(wrapper);
  429. }
  430. @Override
  431. public int getUnscannedCountByExam(Long examId) {
  432. QueryWrapper<StudentEntity> wrapper = new QueryWrapper<>();
  433. LambdaQueryWrapper<StudentEntity> lw = wrapper.lambda();
  434. lw.eq(StudentEntity::getExamId, examId);
  435. lw.ne(StudentEntity::getStatus, ScanStatus.SCANNED);
  436. return this.count(wrapper);
  437. }
  438. @Override
  439. public int getAbsentSuspectCountByExam(Long examId) {
  440. QueryWrapper<StudentEntity> wrapper = new QueryWrapper<>();
  441. LambdaQueryWrapper<StudentEntity> lw = wrapper.lambda();
  442. lw.eq(StudentEntity::getExamId, examId);
  443. lw.eq(StudentEntity::getAbsentSuspect, true);
  444. return this.count(wrapper);
  445. }
  446. @Override
  447. public int getIncompleteCountByExam(Long examId) {
  448. QueryWrapper<StudentEntity> wrapper = new QueryWrapper<>();
  449. LambdaQueryWrapper<StudentEntity> lw = wrapper.lambda();
  450. lw.eq(StudentEntity::getExamId, examId);
  451. lw.eq(StudentEntity::getIncomplete, true);
  452. return this.count(wrapper);
  453. }
  454. @Override
  455. public AbsentInfoVo absentInfo(Long examId, GroupType groupType, String groupName) {
  456. AbsentInfoVo vo = baseMapper.absentInfo(examId, groupType != null ? groupType.getFieldName() : null,
  457. StringUtils.trimToNull(groupName));
  458. if (vo == null) {
  459. vo = new AbsentInfoVo();
  460. }
  461. return vo;
  462. }
  463. // private Integer totalCount(Long examId) {
  464. // QueryWrapper<StudentEntity> wrapper = new QueryWrapper<>();
  465. // LambdaQueryWrapper<StudentEntity> lw = wrapper.lambda();
  466. // lw.eq(StudentEntity::getExamId, examId);
  467. // return this.count(wrapper);
  468. // }
  469. //
  470. // private Integer countByStatus(Long examId, ScanStatus st) {
  471. // QueryWrapper<StudentEntity> wrapper = new QueryWrapper<>();
  472. // LambdaQueryWrapper<StudentEntity> lw = wrapper.lambda();
  473. // lw.eq(StudentEntity::getExamId, examId);
  474. // lw.eq(StudentEntity::getStatus, st);
  475. // return this.count(wrapper);
  476. // }
  477. //
  478. // private Integer countByAbsentSuspect(Long examId) {
  479. // QueryWrapper<StudentEntity> wrapper = new QueryWrapper<>();
  480. // LambdaQueryWrapper<StudentEntity> lw = wrapper.lambda();
  481. // lw.eq(StudentEntity::getExamId, examId);
  482. // lw.eq(StudentEntity::getAbsentSuspect, true);
  483. // return this.count(wrapper);
  484. // }
  485. //
  486. // private Integer countByIncomplete(Long examId) {
  487. // QueryWrapper<StudentEntity> wrapper = new QueryWrapper<>();
  488. // LambdaQueryWrapper<StudentEntity> lw = wrapper.lambda();
  489. // lw.eq(StudentEntity::getExamId, examId);
  490. // lw.eq(StudentEntity::getIncomplete, true);
  491. // return this.count(wrapper);
  492. // }
  493. @Override
  494. public PageResult<AbsentQueryVo> absentQuery(AbsentQueryDomain query) {
  495. IPage<AbsentQueryVo> iPage = baseMapper.absentQueryPage(new Page<>(query.getPageNumber(), query.getPageSize()),
  496. query.getGroupType().getFieldName(), query);
  497. return PageUtil.of(iPage);
  498. }
  499. @Override
  500. public List<String> absentSummary(AbsentQueryDomain query) {
  501. return baseMapper.absentQuerySummary(query.getGroupType().getFieldName(), query);
  502. }
  503. @Override
  504. public List<AbsentQueryVo> absentExportList(AbsentQueryDomain query) {
  505. return baseMapper.absentExportList(new Page<>(query.getPageNumber(), query.getPageSize()),
  506. query.getGroupType().getFieldName(), query);
  507. }
  508. @Transactional
  509. @Override
  510. public AbsentManualImportVo absentManualImport(Long examId, MultipartFile multipartFile) {
  511. List<ManualAbsentImportDTO> list = null;
  512. try {
  513. list = ExcelReader.create(ExcelType.XLSX, multipartFile.getInputStream(), 0)
  514. .getObjectList(ManualAbsentImportDTO.class);
  515. } catch (IOException e) {
  516. throw new ParameterException("Excel解析出错", e);
  517. } catch (Exception e) {
  518. throw new ParameterException("Excel解析出错", e);
  519. }
  520. if (CollectionUtils.isEmpty(list)) {
  521. throw new ParameterException("Excel无内容");
  522. }
  523. // if (10001 < lineList.size()) {
  524. // throw new ParameterException("数据行数不能超过10000");
  525. // }
  526. int updateCount = 0;
  527. int ignoreCount = 0;
  528. int suspectCount = 0;
  529. for (ManualAbsentImportDTO data : list) {
  530. String examNumber = trimAndNullIfBlank(data.getExamNumber());
  531. String subjectCode = trimAndNullIfBlank(data.getSubjectCode());
  532. if (StringUtils.isBlank(examNumber)) {
  533. throw new ParameterException("examNumber不能为空");
  534. }
  535. if (StringUtils.isBlank(subjectCode)) {
  536. throw new ParameterException("科目代码不能为空");
  537. }
  538. StudentEntity student = this.findByExamAndSubjectCodeAndExamNumber(examId, subjectCode, examNumber);
  539. if (student == null) {
  540. throw new ParameterException("考生信息未找到:" + examNumber + ":" + subjectCode);
  541. }
  542. if (ScanStatus.MANUAL_ABSENT.equals(student.getStatus())) {
  543. ignoreCount++;
  544. } else if (ScanStatus.SCANNED.equals(student.getStatus())) {
  545. absentSuspectUpdate(student.getExamId(), student.getSubjectCode(), student.getExamNumber(), true);
  546. suspectCount++;
  547. } else {
  548. absentManualUpdate(student.getExamId(), student.getSubjectCode(), student.getExamNumber());
  549. updateCount++;
  550. }
  551. }
  552. AbsentManualImportVo vo = new AbsentManualImportVo();
  553. vo.setIgnoreCount(ignoreCount);
  554. vo.setUpdateCount(updateCount);
  555. vo.setSuspectCount(suspectCount);
  556. return vo;
  557. }
  558. private String trimAndNullIfBlank(String s) {
  559. if (StringUtils.isBlank(s)) {
  560. return null;
  561. }
  562. return s.trim();
  563. }
  564. @Transactional
  565. @Override
  566. public UpdateTimeVo absentManualUpdate(Long examId, String subjectCode, String examNumber) {
  567. StudentEntity student = this.findByExamAndSubjectCodeAndExamNumber(examId, subjectCode, examNumber);
  568. if (student == null) {
  569. throw new ParameterException("考生未找到:" + examNumber);
  570. }
  571. if (student.getStatus() != ScanStatus.UNEXIST) {
  572. throw new ParameterException("考生不是未扫描状态:" + examNumber);
  573. }
  574. LambdaUpdateWrapper<StudentEntity> lw = new LambdaUpdateWrapper<>();
  575. lw.set(StudentEntity::getStatus, ScanStatus.MANUAL_ABSENT);
  576. lw.set(StudentEntity::getDataUploadStatus, UploadStatus.WAITING_UPLOAD);
  577. lw.eq(StudentEntity::getId, student.getId());
  578. lw.eq(StudentEntity::getStatus, ScanStatus.UNEXIST);
  579. update(lw);
  580. return UpdateTimeVo.create();
  581. }
  582. @Transactional
  583. @Override
  584. public UpdateTimeVo absentSuspectUpdate(Long examId, String subjectCode, String examNumber, boolean enable) {
  585. StudentEntity student = this.findByExamAndSubjectCodeAndExamNumber(examId, subjectCode, examNumber);
  586. if (student == null) {
  587. throw new ParameterException("考生未找到:" + examNumber);
  588. }
  589. LambdaUpdateWrapper<StudentEntity> lw = new LambdaUpdateWrapper<>();
  590. lw.set(StudentEntity::getAbsentSuspect, enable);
  591. lw.set(StudentEntity::getDataUploadStatus, UploadStatus.WAITING_UPLOAD);
  592. lw.eq(StudentEntity::getId, student.getId());
  593. update(lw);
  594. return UpdateTimeVo.create();
  595. }
  596. @Override
  597. public ScanAnswerInfoVo scanAnswerInfo(Long examId) {
  598. return baseMapper.getInfoCountByExam(examId);
  599. }
  600. @Override
  601. public List<String> summary(AnswerQueryDomain query) {
  602. // 不分页查询考生准考证号
  603. return baseMapper.querySummary(query);
  604. }
  605. @Override
  606. public List<AnswerExportVo> exportList(AnswerQueryDomain query) {
  607. // 分页查询考生导出信息
  608. return baseMapper.exportList(new Page<>(query.getPageNumber(), query.getPageSize()), query);
  609. }
  610. @Override
  611. public List<AnswerExportK12Vo> exportListK12(AnswerQueryDomain query) {
  612. // 分页查询考生导出信息
  613. List<AnswerExportVo> list = baseMapper.exportList(new Page<>(query.getPageNumber(), query.getPageSize()),
  614. query);
  615. List<AnswerExportK12Vo> ret = new ArrayList<>();
  616. if (CollectionUtils.isNotEmpty(list)) {
  617. for (AnswerExportVo vo : list) {
  618. AnswerExportK12Vo kvo = new AnswerExportK12Vo();
  619. BeanUtils.copyProperties(vo, kvo);
  620. ret.add(kvo);
  621. }
  622. }
  623. return ret;
  624. }
  625. @Override
  626. public PageResult<AnswerQueryVo> query(AnswerQueryParam query) {
  627. // 查询考生分页信息
  628. IPage<AnswerQueryVo> iPage = baseMapper.queryPage(new Page<>(query.getPageNumber(), query.getPageSize()),
  629. query);
  630. if (CollectionUtils.isNotEmpty(iPage.getRecords())) {
  631. Map<Long, AnswerQueryVo> map = new HashMap<>();
  632. for (AnswerQueryVo vo : iPage.getRecords()) {
  633. List<AnswerPaperVo> papers = new ArrayList<>();
  634. vo.setPapers(papers);
  635. if (vo.getCardPaperCount() != null) {
  636. for (int i = 1; i <= vo.getCardPaperCount(); i++) {
  637. AnswerPaperVo pv = new AnswerPaperVo();
  638. pv.setNumber(i);
  639. papers.add(pv);
  640. }
  641. }
  642. map.put(vo.getId(), vo);
  643. }
  644. // 根据考生id查找绑定paper
  645. List<Long> studentIds = iPage.getRecords().stream().map(p -> p.getId()).collect(Collectors.toList());
  646. List<StudentPaperVo> paperList = new BatchGetDataUtil<StudentPaperVo, Long>() {
  647. @Override
  648. public List<StudentPaperVo> getData(List<Long> paramList) {
  649. return paperService.listByStudentIds(paramList);
  650. }
  651. }.getDataForBatch(studentIds, 20);
  652. if (CollectionUtils.isNotEmpty(paperList)) {
  653. Map<Long, AnswerPaperVo> paperMap = new HashMap<>();
  654. for (StudentPaperVo p : paperList) {
  655. AnswerQueryVo vo = map.get(p.getStudentId());
  656. if (vo == null) {
  657. continue;
  658. }
  659. List<AnswerPaperVo> papers = vo.getPapers();
  660. if (papers == null) {
  661. continue;
  662. }
  663. if (papers.size() < p.getNumber()) {
  664. continue;
  665. }
  666. AnswerPaperVo pvo = papers.get(p.getNumber() - 1);
  667. pvo.setId(p.getPaperId());
  668. pvo.setNumber(p.getNumber());
  669. pvo.setAssigned(p.getAssigned());
  670. paperMap.put(p.getPaperId(), pvo);
  671. }
  672. // 查找page
  673. List<Long> paperIds = paperList.stream().map(p -> p.getPaperId()).collect(Collectors.toList());
  674. List<PaperPageEntity> paperPageList = new BatchGetDataUtil<PaperPageEntity, Long>() {
  675. @Override
  676. public List<PaperPageEntity> getData(List<Long> paramList) {
  677. return paperPageService.listByPaperList(paramList);
  678. }
  679. }.getDataForBatch(paperIds, 20);
  680. if (CollectionUtils.isNotEmpty(paperPageList)) {
  681. for (PaperPageEntity p : paperPageList) {
  682. AnswerPaperVo pvo = paperMap.get(p.getPaperId());
  683. if (pvo == null) {
  684. continue;
  685. }
  686. List<AnswerPageVo> pages = pvo.getPages();
  687. if (pages == null) {
  688. pages = new ArrayList<>();
  689. pvo.setPages(pages);
  690. }
  691. AnswerPageVo pageVo = new AnswerPageVo();
  692. pageVo.setIndex(p.getPageIndex());
  693. pageVo.setSheetUri(p.getSheetPath());
  694. pageVo.setSliceUri(p.getSlicePath());
  695. if (query.getWithOmrDetail() != null && query.getWithOmrDetail()) {
  696. pageVo.setAbsent(p.getAbsent());
  697. pageVo.setBreach(p.getBreach());
  698. pageVo.setPaperType(p.getPaperType());
  699. pageVo.setQuestion(p.getQuestion());
  700. pageVo.setSelective(p.getSelective());
  701. pageVo.setRecogData(p.getRecogData());
  702. }
  703. pages.add(pageVo);
  704. }
  705. }
  706. }
  707. }
  708. return PageUtil.of(iPage);
  709. }
  710. @Transactional
  711. @Override
  712. public void updateDataUploadStatus(@NotNull Long id, @NotNull UploadStatus status) {
  713. LambdaUpdateWrapper<StudentEntity> lw = new LambdaUpdateWrapper<>();
  714. lw.set(StudentEntity::getDataUploadStatus, status);
  715. lw.eq(StudentEntity::getId, id);
  716. update(lw);
  717. }
  718. @Transactional
  719. @Override
  720. public void updateFileUploadStatus(@NotNull Long id, @NotNull UploadStatus status) {
  721. LambdaUpdateWrapper<StudentEntity> lw = new LambdaUpdateWrapper<>();
  722. lw.set(StudentEntity::getFileUploadStatus, status);
  723. lw.eq(StudentEntity::getId, id);
  724. update(lw);
  725. }
  726. @Transactional
  727. @Override
  728. public void updateUploadStatus(@NotNull Long id, @NotNull UploadStatus fileUploadStatus,
  729. @NotNull UploadStatus dataUploadStatus) {
  730. LambdaUpdateWrapper<StudentEntity> lw = new LambdaUpdateWrapper<>();
  731. lw.set(StudentEntity::getDataUploadStatus, dataUploadStatus);
  732. lw.set(StudentEntity::getFileUploadStatus, fileUploadStatus);
  733. lw.eq(StudentEntity::getId, id);
  734. update(lw);
  735. }
  736. @Transactional
  737. @Override
  738. public void updateOmrAbsent(@NotNull Long id, @NotNull Boolean omrAbsent) {
  739. LambdaUpdateWrapper<StudentEntity> lw = new LambdaUpdateWrapper<>();
  740. lw.set(StudentEntity::getOmrAbsent, omrAbsent);
  741. lw.eq(StudentEntity::getId, id);
  742. update(lw);
  743. }
  744. @Transactional
  745. @Override
  746. public void deletetByExamIdAndUnCreateTime(Long examId, long createTime) {
  747. QueryWrapper<StudentEntity> wrapper = new QueryWrapper<>();
  748. LambdaQueryWrapper<StudentEntity> lw = wrapper.lambda();
  749. lw.eq(StudentEntity::getExamId, examId);
  750. lw.ne(StudentEntity::getCreateTime, createTime);
  751. this.baseMapper.delete(wrapper);
  752. }
  753. @Override
  754. public boolean existUploadData() {
  755. return CollectionUtils.isNotEmpty(baseMapper.findToUpload(1))
  756. || CollectionUtils.isNotEmpty(baseMapper.findUploadError(1));
  757. }
  758. @Override
  759. public List<StudentUploadVo> findToUpload(int pageSize) {
  760. if (pageSize <= 0) {
  761. pageSize = 100;
  762. }
  763. List<StudentUploadVo> result = baseMapper.findToUpload(pageSize);
  764. if (CollectionUtils.isEmpty(result)) {
  765. result = baseMapper.findUploadError(pageSize);
  766. }
  767. return result;
  768. }
  769. @Override
  770. public int getCountByExamAndCardNumber(Long examId, Integer number) {
  771. QueryWrapper<StudentEntity> wrapper = new QueryWrapper<>();
  772. LambdaQueryWrapper<StudentEntity> lw = wrapper.lambda();
  773. lw.eq(StudentEntity::getExamId, examId);
  774. lw.eq(StudentEntity::getCardNumber, number);
  775. return this.count(wrapper);
  776. }
  777. @Transactional
  778. @Override
  779. public int importStudent(List<ImportStudentDomain> students) {
  780. List<StudentEntity> savelist = new ArrayList<StudentEntity>();
  781. List<StudentEntity> updatelist = new ArrayList<StudentEntity>();
  782. // Map<Long,Map<String, StudentEntity>> map =new HashMap<Long,
  783. // Map<String,StudentEntity>>();
  784. for (ImportStudentDomain domain : students) {
  785. // Map<String, StudentEntity> examMap =map.get(domain.getExamId());
  786. // if(examMap ==null) {
  787. // examMap = new HashMap<String, StudentEntity>();
  788. // List<StudentEntity> list2 = this.list();
  789. // for (StudentEntity s : list2) {
  790. // examMap.put(s.getExamNumber(), s);
  791. // }
  792. // map.put(domain.getExamId(), examMap);
  793. // }
  794. // StudentEntity entity = examMap.get(domain.getExamNumber());
  795. StudentEntity entity = this.findByExamAndSubjectCodeAndExamNumber(domain.getExamId(),
  796. domain.getSubjectCode(), domain.getExamNumber());
  797. if (entity == null) {
  798. entity = this.findByExamAndSubjectCodeAndExamNumber(domain.getExamId(), domain.getSubjectCode(),
  799. domain.getExamNumber());
  800. }
  801. if (entity == null) {
  802. entity = new StudentEntity();
  803. entity.setStatus(ScanStatus.UNEXIST);
  804. entity.setImageCheckStatus(ImageCheckStatus.WAITING);
  805. entity.setAbsentSuspect(false);
  806. entity.setAssigned(false);
  807. entity.setIncomplete(false);
  808. entity.setOmrAbsent(false);
  809. entity.setQuestionFilled(false);
  810. entity.setSubjectiveFilled(false);
  811. entity.setPaperType("#");
  812. entity.setCheckMark(false);
  813. entity.setAssignedSuspect(false);
  814. savelist.add(entity);
  815. } else {
  816. updatelist.add(entity);
  817. }
  818. entity.setExamId(domain.getExamId());
  819. entity.setName(domain.getName());
  820. entity.setSubjectCode(domain.getSubjectCode());
  821. entity.setExamNumber(domain.getExamNumber());
  822. entity.setPackageCode(domain.getPackageCode());
  823. entity.setExamRoom(domain.getExamRoom());
  824. entity.setProvince(domain.getProvince());
  825. entity.setExamSite(domain.getExamSite());
  826. entity.setExamSiteName(domain.getExamSiteName());
  827. entity.setSeatNumber(domain.getSeatNumber());
  828. entity.setCampusName(domain.getCampusName());
  829. entity.setCampusCode(domain.getCampusCode());
  830. }
  831. if (savelist.size() > 0) {
  832. this.saveBatch(savelist);
  833. }
  834. if (updatelist.size() > 0) {
  835. this.updateBatchById(updatelist);
  836. }
  837. return students.size();
  838. }
  839. @Override
  840. public StudentEntity findByExamAndSubjectCodeAndExamNumber(Long examId, String subjectCode, String examNumber) {
  841. if (examId == null) {
  842. throw new ParameterException("examId 不能为空");
  843. }
  844. if (StringUtils.isBlank(subjectCode)) {
  845. throw new ParameterException("subjectCode不能为空");
  846. }
  847. if (StringUtils.isBlank(examNumber)) {
  848. throw new ParameterException("examNumber");
  849. }
  850. QueryWrapper<StudentEntity> queryWrapper = new QueryWrapper<>();
  851. queryWrapper.lambda().eq(StudentEntity::getExamId, examId);
  852. queryWrapper.lambda().eq(StudentEntity::getSubjectCode, subjectCode);
  853. queryWrapper.lambda().eq(StudentEntity::getExamNumber, examNumber);
  854. return baseMapper.selectOne(queryWrapper);
  855. }
  856. @Override
  857. public int countByQuery(ImportStudentQueryVo query) {
  858. if (query.getExamId() == null) {
  859. throw new ParameterException("examId不能为空");
  860. }
  861. return baseMapper.countByQuery(query);
  862. }
  863. @Override
  864. public int countCetMarking(ExportCetMarkingQueryVo query) {
  865. if (query.getExamId() == null) {
  866. throw new ParameterException("examId不能为空");
  867. }
  868. return baseMapper.countCetMarking(query);
  869. }
  870. @Override
  871. public List<ImportStudentVo> findByQuery(ImportStudentQueryVo query) {
  872. if (query.getExamId() == null) {
  873. throw new ParameterException("examId不能为空");
  874. }
  875. ExamEntity exam = examService.getById(query.getExamId());
  876. if (exam == null) {
  877. throw new ParameterException("未找到考试");
  878. }
  879. IPage<ImportStudentVo> iPage = baseMapper
  880. .listPageQuery(new Page<ImportStudentVo>(query.getPageNumber(), query.getPageSize()), query);
  881. if (query.getWithAnswer() != null && query.getWithAnswer()) {
  882. for (ImportStudentVo student : iPage.getRecords()) {
  883. List<StudentPaperEntity> papers = studentPaperService.findByStudentId(student.getId());
  884. List<PaperPageEntity> pageList = new ArrayList<>();
  885. for (StudentPaperEntity sp : papers) {
  886. List<PaperPageEntity> pages = paperPageService.listByPaperId(sp.getPaperId());
  887. pageList.addAll(pages);
  888. }
  889. List<String> answers = new ArrayList<String>();
  890. for (PaperPageEntity p : pageList) {
  891. if (p.getPageIndex() == 1) {
  892. student.setPaperType(p.getPaperType() == null ? null : p.getPaperType().getResult());
  893. }
  894. disposeQuestionMark(p.getQuestion());
  895. if (p.getQuestion() != null && CollectionUtils.isNotEmpty(p.getQuestion().getResult())) {
  896. answers.addAll(p.getQuestion().getResult());
  897. }
  898. }
  899. student.setAnswer(answers);
  900. }
  901. }
  902. return iPage.getRecords();
  903. }
  904. private void disposeQuestionMark(ArrayResult ar) {
  905. if (ar != null && CollectionUtils.isNotEmpty(ar.getResult())) {
  906. for (int i = 0; i < ar.getResult().size(); i++) {
  907. ar.getResult().set(i, ar.getResult().get(i).replaceAll("\\?", ""));
  908. }
  909. }
  910. }
  911. @Override
  912. public int getOmrAbsentCountByExam(Long examId) {
  913. QueryWrapper<StudentEntity> wrapper = new QueryWrapper<>();
  914. LambdaQueryWrapper<StudentEntity> lw = wrapper.lambda();
  915. lw.eq(StudentEntity::getExamId, examId);
  916. lw.eq(StudentEntity::getOmrAbsent, true);
  917. return this.count(wrapper);
  918. }
  919. @Override
  920. public boolean existPictureCopyData() {
  921. List<StudentUploadVo> list = baseMapper.findToPictureCopy(1);
  922. return CollectionUtils.isNotEmpty(list);
  923. }
  924. @Override
  925. public List<StudentUploadVo> findToPictureCopy(int pageSize) {
  926. if (pageSize <= 0) {
  927. pageSize = 100;
  928. }
  929. return baseMapper.findToPictureCopy(pageSize);
  930. }
  931. @Override
  932. public Double getUploadProgress(Long examId) {
  933. // int total = getCountByExamAndScanStatus(examId, ScanStatus.SCANNED);
  934. // if (total == 0) {
  935. // return 0.0;
  936. // }
  937. int needUpload = baseMapper.getNeedUploadCount(examId);
  938. int uploaded = baseMapper.getUploadedCount(examId);
  939. int total = needUpload + uploaded;
  940. if (total == 0) {
  941. return 0.0;
  942. }
  943. BigDecimal totalB = new BigDecimal(total);
  944. BigDecimal uploadedB = new BigDecimal(uploaded);
  945. return uploadedB.divide(totalB, 2, BigDecimal.ROUND_HALF_UP).doubleValue();
  946. }
  947. @Transactional
  948. @Override
  949. public void studentClean(Long examId, String subjectCode) {
  950. ExamEntity exam = examService.getById(examId);
  951. if (exam == null) {
  952. throw ParameterExceptions.EXAM_NOT_FOUND;
  953. }
  954. if (batchService.getCountByExam(examId) > 0) {
  955. throw new ParameterException("已开始扫描不能清空");
  956. }
  957. LambdaQueryWrapper<StudentEntity> wrapper = Wrappers.lambdaQuery();
  958. wrapper.eq(StudentEntity::getExamId, examId);
  959. wrapper.eq(StudentEntity::getSubjectCode, subjectCode);
  960. baseMapper.delete(wrapper);
  961. }
  962. @Transactional
  963. @Override
  964. // @Lockable
  965. public PaperDeleteVo paperDelete(User user, PageDeleteDomain domain) {
  966. Integer paperNumber = domain.getPaperNumber();
  967. StudentEntity student = this.findByExamAndSubjectCodeAndExamNumber(domain.getExamId(), domain.getSubjectCode(),
  968. domain.getExamNumber());
  969. if (student == null) {
  970. throw new ParameterException("考生信息未找到");
  971. }
  972. concurrentService.getReadWriteLock(LockType.STUDENT + "-" + student.getId()).writeLock().lock();
  973. try {
  974. updateStudentAndPaper(user, student.getId(),
  975. removeStudentPaper(studentPaperService.findByStudentId(student.getId()), paperNumber));
  976. updateAssignedCheckCount(student.getId(), true);
  977. PaperDeleteVo vo = new PaperDeleteVo();
  978. vo.setPaperCount(studentPaperService.countByStudentId(student.getId()));
  979. vo.setUpdateTime(new Date().getTime());
  980. return vo;
  981. } finally {
  982. concurrentService.getReadWriteLock(LockType.STUDENT + "-" + student.getId()).writeLock().unlock();
  983. }
  984. }
  985. private List<StudentPaperEntity> removeStudentPaper(List<StudentPaperEntity> list, Integer paperNumber) {
  986. boolean find = false;
  987. List<StudentPaperEntity> left = new ArrayList<>();
  988. for (StudentPaperEntity entity : list) {
  989. if (entity.getPaperNumber().equals(paperNumber)) {
  990. find = true;
  991. } else {
  992. left.add(entity);
  993. }
  994. }
  995. if (!find) {
  996. throw new ParameterException("未找到该张扫描结果");
  997. } else if (left.size() > 0 && paperNumber == 1) {
  998. throw new StatusException("需先删除其他张之后才能删除第一张");
  999. } else {
  1000. return left;
  1001. }
  1002. }
  1003. @Transactional
  1004. @Override
  1005. // @Lockable
  1006. public AnswerDeleteVo answerDelete(User user, AnswerDeleteDomain domain) {
  1007. Long examId = domain.getExamId();
  1008. String examNumber = domain.getExamNumber();
  1009. StudentEntity student = this.findByExamAndSubjectCodeAndExamNumber(examId, domain.getSubjectCode(), examNumber);
  1010. if (student == null) {
  1011. throw new ParameterException("考生信息未找到");
  1012. }
  1013. concurrentService.getReadWriteLock(LockType.STUDENT + "-" + student.getId()).writeLock().lock();
  1014. try {
  1015. updateStudentAndPaper(user, student.getId(), new ArrayList<>());
  1016. updateAssignedCheckCount(student.getId(), true);
  1017. AnswerDeleteVo vo = new AnswerDeleteVo();
  1018. vo.setStatus(ScanStatus.UNEXIST);
  1019. vo.setUpdateTime(new Date().getTime());
  1020. return vo;
  1021. } finally {
  1022. concurrentService.getReadWriteLock(LockType.STUDENT + "-" + student.getId()).writeLock().unlock();
  1023. }
  1024. }
  1025. @Transactional
  1026. @Override
  1027. // @Lockable
  1028. public AnswerRefixVo answerRefix(User user, AnswerRefixDomain domain) {
  1029. StudentEntity student = this.findByExamAndSubjectCodeAndExamNumber(domain.getExamId(), domain.getSubjectCode(),
  1030. domain.getExamNumber());
  1031. if (student == null) {
  1032. throw new ParameterException("考生信息未找到");
  1033. }
  1034. AnswerCardEntity answerCard = answerCardService.findByExamAndNumber(domain.getExamId(), domain.getCardNumber());
  1035. if (answerCard == null) {
  1036. throw new ParameterException("卡格式信息未找到");
  1037. }
  1038. boolean allowSubject = answerCardSubjectService.checkSubject(answerCard.getExamId(), answerCard.getNumber(),
  1039. student.getSubjectCode());
  1040. if (!allowSubject) {
  1041. throw new ParameterException("卡格式与考生科目不匹配");
  1042. }
  1043. // if (domain.getPapers().size() != answerCard.getPaperCount()) {
  1044. // throw new ParameterException("卡格式张数不一致");
  1045. // }
  1046. ExamEntity exam = examService.getById(student.getExamId());
  1047. List<String> paperTypeBarcodeContents = exam.getPaperTypeBarcodeContent();
  1048. SubjectEntity subject = subjectService.findByExamIdAndCode(student.getExamId(), student.getSubjectCode());
  1049. if (subject.getPaperTypeBarcodeContent() != null && !subject.getPaperTypeBarcodeContent().isEmpty()) {
  1050. paperTypeBarcodeContents = subject.getPaperTypeBarcodeContent();
  1051. }
  1052. concurrentService.getReadWriteLock(LockType.STUDENT + "-" + student.getId()).writeLock().lock();
  1053. try {
  1054. List<StudentPaperEntity> studentPaperList = studentPaperService.findByStudentId(student.getId());
  1055. for (StudentPaperEntity studentPaper : studentPaperList) {
  1056. PaperRefixDomain paperDomain = domain.findPaperDomain(studentPaper.getPaperNumber(),
  1057. studentPaper.getPaperId());
  1058. if (paperDomain == null) {
  1059. throw new ParameterException("与考生当前paper不一致,paperNumber=" + studentPaper.getPaperNumber());
  1060. }
  1061. PaperEntity paper = paperService.getById(paperDomain.getId());
  1062. if (paper == null) {
  1063. throw new ParameterException("考生当前paper不存在,paperId=" + paperDomain.getId());
  1064. }
  1065. paper.setCardNumber(answerCard.getNumber());
  1066. paper.setMismatch(paperDomain.getMismatch());
  1067. List<PaperPageEntity> pages = new ArrayList<>();
  1068. for (PageRefixDomain pageDomain : paperDomain.getPages()) {
  1069. PaperPageEntity page = paperPageService.findPaperIdAndIndex(paper.getId(), pageDomain.getIndex());
  1070. if (page == null) {
  1071. throw new ParameterException("与考生当前page不一致,pageIndex=" + pageDomain.getIndex());
  1072. }
  1073. pages.add(pageDomain.update(page, paperTypeBarcodeContents));
  1074. }
  1075. paperService.savePaperAndPages(paper, pages);
  1076. }
  1077. updateStudentByPaper(user, student.getId(), true);
  1078. return AnswerRefixVo.create();
  1079. } finally {
  1080. concurrentService.getReadWriteLock(LockType.STUDENT + "-" + student.getId()).writeLock().unlock();
  1081. }
  1082. }
  1083. @Transactional
  1084. @Override
  1085. public UpdateTimeVo omrEdit(User user, OmrEditDomain domain) {
  1086. StudentEntity student = this.findByExamAndSubjectCodeAndExamNumber(domain.getExamId(), domain.getSubjectCode(),
  1087. domain.getExamNumber());
  1088. if (student == null) {
  1089. throw new ParameterException("考生信息未找到");
  1090. }
  1091. concurrentService.getReadWriteLock(LockType.STUDENT + "-" + student.getId()).writeLock().lock();
  1092. try {
  1093. for (OmrEditPaper paperEdit : domain.getPapers()) {
  1094. StudentPaperEntity sp = studentPaperService.findByStudentIdAndPaperNumber(student.getId(),
  1095. paperEdit.getNumber());
  1096. if (sp == null) {
  1097. throw new ParameterException("未找到绑定扫描结果");
  1098. }
  1099. PaperEntity paperEntity = paperService.getById(sp.getPaperId());
  1100. if (paperEntity == null) {
  1101. throw new ParameterException("未找到paper信息结果");
  1102. }
  1103. paperEntity.setUpdaterId(user.getId());
  1104. paperEntity.setUpdateTime(System.currentTimeMillis());
  1105. List<PaperPageEntity> pages = paperPageService.listByPaperId(paperEntity.getId());
  1106. for (PaperPageEntity pageEntity : pages) {
  1107. paperEdit.updatePage(pageEntity);
  1108. }
  1109. paperService.savePaperAndPages(paperEntity, pages);
  1110. }
  1111. updateStudentByPaper(user, student.getId(), false);
  1112. return UpdateTimeVo.create();
  1113. } finally {
  1114. concurrentService.getReadWriteLock(LockType.STUDENT + "-" + student.getId()).writeLock().unlock();
  1115. }
  1116. }
  1117. @Transactional
  1118. @Override
  1119. public UpdateTimeVo omrFieldEdit(User user, OmrFieldEditDomain domain) {
  1120. StudentEntity student = this.findByExamAndSubjectCodeAndExamNumber(domain.getExamId(), domain.getSubjectCode(),
  1121. domain.getExamNumber());
  1122. if (student == null) {
  1123. throw new ParameterException("考生信息未找到");
  1124. }
  1125. concurrentService.getReadWriteLock(LockType.STUDENT + "-" + student.getId()).writeLock().lock();
  1126. try {
  1127. StudentPaperEntity sp = studentPaperService.findByStudentIdAndPaperNumber(student.getId(),
  1128. domain.getPaperNumber());
  1129. if (sp == null) {
  1130. throw new ParameterException("未找到绑定扫描结果");
  1131. }
  1132. PaperEntity paperEntity = paperService.getById(sp.getPaperId());
  1133. if (paperEntity == null) {
  1134. throw new ParameterException("未找到paper信息结果");
  1135. }
  1136. paperEntity.setUpdaterId(user.getId());
  1137. paperEntity.setUpdateTime(System.currentTimeMillis());
  1138. List<PaperPageEntity> pages = paperPageService.listByPaperId(paperEntity.getId());
  1139. boolean pageIndexValid = false;
  1140. for (PaperPageEntity pageEntity : pages) {
  1141. if (pageEntity.getPageIndex().equals(domain.getPageIndex())) {
  1142. pageIndexValid = true;
  1143. Gson gson = new Gson();
  1144. if (StringUtils.isBlank(domain.getValue().toString())) {
  1145. throw new ParameterException("field值为空");
  1146. }
  1147. if (OmrField.ABSENT.equals(domain.getField())) {
  1148. pageEntity.setAbsent(gson.fromJson(domain.getValue().toString(), BoolResult.class));
  1149. } else if (OmrField.BREACH.equals(domain.getField())) {
  1150. pageEntity.setBreach(gson.fromJson(domain.getValue().toString(), BoolResult.class));
  1151. } else if (OmrField.PAPER_TYPE.equals(domain.getField())) {
  1152. pageEntity.setPaperType(gson.fromJson(domain.getValue().toString(), StringResult.class));
  1153. } else if (OmrField.QUESTION.equals(domain.getField())) {
  1154. pageEntity.setQuestion(gson.fromJson(domain.getValue().toString(), ArrayResult.class));
  1155. } else if (OmrField.SELECTIVE.equals(domain.getField())) {
  1156. pageEntity.setSelective(gson.fromJson(domain.getValue().toString(), ArrayResult.class));
  1157. } else {
  1158. throw new ParameterException("field值错误");
  1159. }
  1160. }
  1161. }
  1162. if (!pageIndexValid) {
  1163. throw new ParameterException("未找到page信息结果");
  1164. }
  1165. paperService.savePaperAndPages(paperEntity, pages);
  1166. updateStudentByPaper(user, student.getId(), false);
  1167. return UpdateTimeVo.create();
  1168. } finally {
  1169. concurrentService.getReadWriteLock(LockType.STUDENT + "-" + student.getId()).writeLock().unlock();
  1170. }
  1171. }
  1172. @Transactional
  1173. @Override
  1174. public Integer importCetAbsent(List<ImportCetAbsentDomain> students) {
  1175. List<StudentEntity> list = new ArrayList<StudentEntity>();
  1176. for (ImportCetAbsentDomain domain : students) {
  1177. if (domain.getExamId() == null) {
  1178. throw new StatusException("考试id不能为空");
  1179. }
  1180. if (domain.getExamNumber() == null) {
  1181. throw new StatusException("准考证号不能为空");
  1182. }
  1183. // if (domain.getAbsent() == null) {
  1184. // throw new StatusException("缺考信息不能为空");
  1185. // }
  1186. StudentEntity entity = this.findByExamAndSubjectCodeAndExamNumber(domain.getExamId(),
  1187. domain.getSubjectCode(), domain.getExamNumber());
  1188. if (entity == null) {
  1189. throw new StatusException("未找到考生");
  1190. }
  1191. entity.setBreachCode(domain.getBreachCode());
  1192. // entity.setExamStatus(domain.getAbsent() ? ExamStatus.ABSENT :
  1193. // null);
  1194. list.add(entity);
  1195. }
  1196. this.updateBatchById(list);
  1197. return list.size();
  1198. }
  1199. @Override
  1200. public List<ExportCetVo> exportCetData(ExportCetMarkingQueryVo query) {
  1201. if (query.getExamId() == null) {
  1202. throw new ParameterException("examId不能为空");
  1203. }
  1204. ExamEntity exam = examService.getById(query.getExamId());
  1205. if (exam == null) {
  1206. throw new ParameterException("未找到考试");
  1207. }
  1208. if (CollectionUtils.isEmpty(exam.getPaperTypeBarcodeContent())) {
  1209. throw new ParameterException("该考试条码值未设置");
  1210. }
  1211. if (!ExamMode.CET.equals(exam.getMode())) {
  1212. throw new ParameterException("该考试不是CET");
  1213. }
  1214. IPage<ExportCetVo> iPage = baseMapper
  1215. .listCetMarkingPage(new Page<ExportCetVo>(query.getPageNumber(), query.getPageSize()), query);
  1216. if (CollectionUtils.isNotEmpty(iPage.getRecords())) {
  1217. String imageTransferDir = sysProperty.getTransferDir();
  1218. Map<String, List<QuestionEntity>> structs = new HashMap<>();
  1219. Map<Integer, AnswerCardEntity> cardMap = new HashMap<>();
  1220. new BatchSetDataUtil<ExportCetVo>() {
  1221. @Override
  1222. protected void setData(List<ExportCetVo> dataList) {
  1223. List<Long> ids = dataList.stream().map(e -> e.getId()).collect(Collectors.toList());
  1224. List<PaperPageCetVo> totalpages = paperPageService.listByStudentIds(ids);
  1225. List<PaperCetVo> totalpapers = paperService.findByStudentIds(ids);
  1226. Map<Long, List<PaperPageCetVo>> totalpagesmap = ofPage(totalpages);
  1227. Map<Long, List<PaperCetVo>> totalpapersmap = ofPaper(totalpapers);
  1228. for (ExportCetVo vo : dataList) {
  1229. disposeStudent(vo, exam, totalpagesmap.get(vo.getId()), totalpapersmap.get(vo.getId()),
  1230. imageTransferDir, structs, cardMap);
  1231. }
  1232. }
  1233. }.setDataForBatch(iPage.getRecords(), 200);
  1234. }
  1235. return iPage.getRecords();
  1236. }
  1237. private void disposeStudent(ExportCetVo student, ExamEntity exam, List<PaperPageCetVo> pages,
  1238. List<PaperCetVo> papers, String imageTransferDir, Map<String, List<QuestionEntity>> structs,
  1239. Map<Integer, AnswerCardEntity> cardMap) {
  1240. int subject = Integer.valueOf(student.getSubjectCode());
  1241. if (subject > 2) {
  1242. if (student.getExamStatus().equals(ExamStatus.ABSENT)) {
  1243. student.setPaperType("000000");
  1244. } else {
  1245. student.setPaperType("888888");
  1246. }
  1247. } else {
  1248. if (StringUtils.isBlank(student.getPaperType()) || "#".equals(student.getPaperType())) {
  1249. student.setPaperType("000000");
  1250. } else if ("?".equals(student.getPaperType())
  1251. || !exam.getPaperTypeBarcodeContent().contains(student.getPaperType())) {
  1252. student.setPaperType("999999");
  1253. }
  1254. }
  1255. Map<Long, PaperCetVo> pmap = new HashMap<>();
  1256. for (PaperCetVo v : papers) {
  1257. pmap.put(v.getId(), v);
  1258. }
  1259. student.setAnswer(getCetAnswer(structs, pages, student.getSubjectCode()));
  1260. AnswerCardEntity card = getCard(cardMap, student.getExamId(), student.getCardNumber());
  1261. Set<String> sliceSet = new LinkedHashSet<>();
  1262. setCardStatus(student, card, pages, pmap);
  1263. int index = 0;
  1264. for (PaperPageCetVo p : pages) {
  1265. if (CollectionUtils.isNotEmpty(p.getSlicePath())) {
  1266. for (int i = 0; i < p.getSlicePath().size(); i++) {
  1267. String sliceName = card.getSliceName().get(index);
  1268. sliceSet.add(sliceName);
  1269. index++;
  1270. }
  1271. }
  1272. }
  1273. // 获取图片大小
  1274. List<String> sliceImageInfo = new ArrayList<String>();
  1275. student.setSliceImageInfo(sliceImageInfo);
  1276. for (String sliceName : sliceSet) {
  1277. String mirrorSlicePath = toolExportService.getCetSliceUri(student.getExamId(), student.getExamNumber(),
  1278. sliceName);
  1279. File targetSliceFile = new File(imageTransferDir + "/" + mirrorSlicePath);
  1280. sliceImageInfo.add(sliceName + "-" + targetSliceFile.length());
  1281. }
  1282. }
  1283. private Map<Long, List<PaperPageCetVo>> ofPage(List<PaperPageCetVo> list) {
  1284. Map<Long, List<PaperPageCetVo>> map = new HashMap<>();
  1285. for (PaperPageCetVo p : list) {
  1286. List<PaperPageCetVo> tem = map.get(p.getStudentId());
  1287. if (tem == null) {
  1288. tem = new ArrayList<>();
  1289. map.put(p.getStudentId(), tem);
  1290. }
  1291. tem.add(p);
  1292. }
  1293. return map;
  1294. }
  1295. private Map<Long, List<PaperCetVo>> ofPaper(List<PaperCetVo> list) {
  1296. Map<Long, List<PaperCetVo>> map = new HashMap<>();
  1297. for (PaperCetVo p : list) {
  1298. List<PaperCetVo> tem = map.get(p.getStudentId());
  1299. if (tem == null) {
  1300. tem = new ArrayList<>();
  1301. map.put(p.getStudentId(), tem);
  1302. }
  1303. tem.add(p);
  1304. }
  1305. return map;
  1306. }
  1307. private AnswerCardEntity getCard(Map<Integer, AnswerCardEntity> cardMap, Long examId, Integer cardNumber) {
  1308. AnswerCardEntity card = cardMap.get(cardNumber);
  1309. if (card == null) {
  1310. card = answerCardService.findByExamAndNumber(examId, cardNumber);
  1311. cardMap.put(cardNumber, card);
  1312. }
  1313. return card;
  1314. }
  1315. private void setCardStatus(ExportCetVo student, AnswerCardEntity card, List<PaperPageCetVo> pages,
  1316. Map<Long, PaperCetVo> pmap) {
  1317. int subject = Integer.valueOf(student.getSubjectCode());
  1318. if (subject > 2) {
  1319. setCardStatusSmall(student, card, pages, pmap);
  1320. } else {
  1321. setCardStatusCet(student, card, pages, pmap);
  1322. }
  1323. }
  1324. private void setCardStatusSmall(ExportCetVo student, AnswerCardEntity card, List<PaperPageCetVo> pages,
  1325. Map<Long, PaperCetVo> pmap) {
  1326. PaperPageCetVo p = pages.get(0);
  1327. if (ExamStatus.ABSENT.equals(student.getExamStatus())) {
  1328. if (pmap.get(p.getPaperId()).getQuestionFilled()) {
  1329. student.setCardFirst(1);
  1330. } else {
  1331. student.setCardFirst(0);
  1332. }
  1333. } else {
  1334. student.setCardFirst(0);
  1335. }
  1336. student.setCardSecond(0);
  1337. }
  1338. private void setCardStatusCet(ExportCetVo student, AnswerCardEntity card, List<PaperPageCetVo> pages,
  1339. Map<Long, PaperCetVo> pmap) {
  1340. if (card.getPaperCount() == 1) {
  1341. PaperPageCetVo p = pages.get(0);
  1342. if (ExamStatus.ABSENT.equals(student.getExamStatus())) {
  1343. if (pmap.get(p.getPaperId()).getQuestionFilled()) {
  1344. student.setCardFirst(1);
  1345. } else if (isPaperTypeValid(p.getPaperType())) {
  1346. student.setCardFirst(7);
  1347. } else if (isPaperTypeEmpty(p.getPaperType())) {
  1348. student.setCardFirst(0);
  1349. } else {
  1350. student.setCardFirst(7);
  1351. }
  1352. } else {
  1353. if (isPaperTypeValid(p.getPaperType())) {
  1354. student.setCardFirst(0);
  1355. } else {
  1356. student.setCardFirst(7);
  1357. }
  1358. }
  1359. student.setCardSecond(0);
  1360. } else {
  1361. PaperPageCetVo fp = pages.get(0);
  1362. PaperPageCetVo sp;
  1363. if (card.getSinglePage()) {
  1364. sp = pages.get(1);
  1365. } else {
  1366. sp = pages.get(2);
  1367. }
  1368. if (ExamStatus.ABSENT.equals(student.getExamStatus())) {
  1369. if (pmap.get(fp.getPaperId()).getQuestionFilled()) {
  1370. student.setCardFirst(1);
  1371. } else if (isPaperTypeValid(fp.getPaperType())) {
  1372. student.setCardFirst(7);
  1373. } else if (isPaperTypeEmpty(fp.getPaperType())) {
  1374. student.setCardFirst(0);
  1375. } else {
  1376. student.setCardFirst(7);
  1377. }
  1378. } else {
  1379. if (isPaperTypeValid(fp.getPaperType())) {
  1380. student.setCardFirst(0);
  1381. } else {
  1382. student.setCardFirst(7);
  1383. }
  1384. }
  1385. if (ExamStatus.ABSENT.equals(student.getExamStatus())) {
  1386. if (pmap.get(sp.getPaperId()).getQuestionFilled()) {
  1387. student.setCardSecond(1);
  1388. } else if (isPaperTypeValid(fp.getPaperType())) {
  1389. student.setCardSecond(7);
  1390. } else if (isPaperTypeEmpty(fp.getPaperType())) {
  1391. student.setCardSecond(0);
  1392. } else {
  1393. student.setCardSecond(7);
  1394. }
  1395. } else {
  1396. if (isPaperTypeValid(fp.getPaperType())) {
  1397. student.setCardSecond(0);
  1398. } else {
  1399. student.setCardSecond(7);
  1400. }
  1401. }
  1402. }
  1403. }
  1404. private boolean isPaperTypeEmpty(StringResult sr) {
  1405. if (sr == null) {
  1406. return true;
  1407. }
  1408. if (StringUtils.isBlank(sr.getResult())) {
  1409. return true;
  1410. }
  1411. if ("#".equals(sr.getResult())) {
  1412. return true;
  1413. }
  1414. return false;
  1415. }
  1416. private boolean isPaperTypeValid(StringResult sr) {
  1417. if (sr == null) {
  1418. return false;
  1419. }
  1420. if (StringUtils.isBlank(sr.getResult())) {
  1421. return false;
  1422. }
  1423. if ("#".equals(sr.getResult()) || "?".equals(sr.getResult())) {
  1424. return false;
  1425. }
  1426. return true;
  1427. }
  1428. private String getCetAnswer(Map<String, List<QuestionEntity>> structs, List<PaperPageCetVo> pages,
  1429. String subjectCode) {
  1430. List<String> answers = new ArrayList<String>();
  1431. List<QuestionEntity> struct = structs.get(subjectCode);
  1432. if (struct == null) {
  1433. struct = questionService.findBySubjectCode(subjectCode);
  1434. if (struct == null) {
  1435. throw new ParameterException("科目:" + subjectCode + " 未上传试卷结构");
  1436. }
  1437. structs.put(subjectCode, struct);
  1438. }
  1439. for (PaperPageCetVo page : pages) {
  1440. disposeQuestionMark(page.getQuestion());
  1441. try {
  1442. if (page.getQuestion() != null && CollectionUtils.isNotEmpty(page.getQuestion().getResult())) {
  1443. answers.addAll(page.getQuestion().getResult());
  1444. }
  1445. } catch (Exception e) {
  1446. throw e;
  1447. }
  1448. }
  1449. for (int i = 0; i < answers.size(); i++) {
  1450. if ("#".equals(answers.get(i))) {
  1451. answers.set(i, ".");
  1452. }
  1453. if (answers.get(i).length() > 1) {
  1454. answers.set(i, ">");
  1455. }
  1456. }
  1457. int subject = Integer.valueOf(subjectCode);
  1458. if (subject < 3) {// CET4 CET6
  1459. return StringUtils.join(answers, "");
  1460. } else {// 小语种
  1461. List<String> tem = new ArrayList<String>();
  1462. int index = 0;
  1463. for (QuestionEntity s : struct) {
  1464. if (s.getObjective()) {
  1465. if (index >= answers.size()) {
  1466. throw new ParameterException("科目:" + subjectCode + " 试卷结构和题卡客观题数量不一致");
  1467. }
  1468. tem.add(answers.get(index));
  1469. index++;
  1470. } else {
  1471. tem.add(".");
  1472. }
  1473. }
  1474. return StringUtils.join(tem, "");
  1475. }
  1476. }
  1477. @Transactional
  1478. @Override
  1479. public void updateCheckMark(Long studentId, Boolean tag) {
  1480. LambdaUpdateWrapper<StudentEntity> updateWrapper = new LambdaUpdateWrapper<>();
  1481. updateWrapper.set(StudentEntity::getCheckMark, tag);
  1482. updateWrapper.eq(StudentEntity::getId, studentId);
  1483. this.update(updateWrapper);
  1484. }
  1485. @Transactional
  1486. @Override
  1487. public void pictureCopy(StudentUploadVo vo) {
  1488. concurrentService.getReadWriteLock(LockType.STUDENT + "-" + vo.getId()).writeLock().lock();
  1489. StudentEntity se = this.getById(vo.getId());
  1490. try {
  1491. if (UploadStatus.WAITING_UPLOAD.equals(se.getFileUploadStatus())) {
  1492. toolExportService.studentFileCopy(se.getId(), vo.getMode());
  1493. this.updateFileUploadStatus(se.getId(), UploadStatus.UPLOADED);
  1494. }
  1495. } catch (Exception e) {
  1496. this.updateFileUploadStatus(se.getId(), UploadStatus.ERROR);
  1497. log.error("转存文件出错.studentId:" + se.getId(), e);
  1498. } finally {
  1499. concurrentService.getReadWriteLock(LockType.STUDENT + "-" + vo.getId()).writeLock().unlock();
  1500. }
  1501. }
  1502. @Override
  1503. @Transactional
  1504. public void resetExamStatus(ExamStatusResetTaskVo vo) {
  1505. Long examId = vo.getExamId();
  1506. Integer examNumberFillCount = vo.getExamNumberFillCount();
  1507. QueryWrapper<StudentEntity> wrapper = new QueryWrapper<>();
  1508. LambdaQueryWrapper<StudentEntity> lw = wrapper.lambda();
  1509. lw.eq(StudentEntity::getExamId, examId);
  1510. List<StudentEntity> list = this.list(wrapper);
  1511. for (StudentEntity student : list) {
  1512. concurrentService.getReadWriteLock(LockType.STUDENT + "-" + student.getId()).writeLock().lock();
  1513. try {
  1514. List<StudentPaperEntity> studentPaperList = studentPaperService.findByStudentId(student.getId());
  1515. int omrExamNumberCount = 0;
  1516. for (StudentPaperEntity studentPaper : studentPaperList) {
  1517. PaperEntity paper = paperService.getById(studentPaper.getPaperId());
  1518. int paperExamNumberCount = paper.getOmrExamNumber().replace("#", "").length();
  1519. if (omrExamNumberCount < paperExamNumberCount) {
  1520. omrExamNumberCount = paperExamNumberCount;
  1521. }
  1522. }
  1523. resetExamStatus(student, omrExamNumberCount, examNumberFillCount);
  1524. saveOrUpdate(student);
  1525. } finally {
  1526. concurrentService.getReadWriteLock(LockType.STUDENT + "-" + student.getId()).writeLock().unlock();
  1527. }
  1528. vo.setProgressCount(vo.getProgressCount() + 1);
  1529. }
  1530. examService.updateExamNumberFillCount(examId, examNumberFillCount);
  1531. }
  1532. private void resetExamStatus(StudentEntity student, Integer omrExamNumberCount, Integer examNumberFillCount) {
  1533. if (ScanStatus.UNEXIST.equals(student.getStatus())) {
  1534. student.setExamStatus(null);
  1535. } else {
  1536. // 客观题有作答,不缺考
  1537. if (student.getQuestionFilled()) {
  1538. student.setExamStatus(ExamStatus.OK);
  1539. } else {
  1540. if (student.getSubjectiveFilled()) {
  1541. // 客观题未作答,主观题有作答,待确认1
  1542. student.setExamStatus(ExamStatus.UNCHECK1);
  1543. } else {
  1544. // 客观题未作答,主观题未作答,填涂大于10位
  1545. if (omrExamNumberCount >= examNumberFillCount) {
  1546. if (!"#".equals(student.getPaperType())) {
  1547. // 客观题未作答,主观题未作答,填涂大于10位,有卷型,待校验2
  1548. student.setExamStatus(ExamStatus.UNCHECK2);
  1549. } else {
  1550. // 客观题未作答,主观题未作答,填涂大于10位,无卷型,缺考
  1551. student.setExamStatus(ExamStatus.ABSENT);
  1552. }
  1553. } else {
  1554. // 客观题未作答,主观题未作答,填涂小于10位,缺考
  1555. student.setExamStatus(ExamStatus.ABSENT);
  1556. }
  1557. }
  1558. }
  1559. }
  1560. }
  1561. @Override
  1562. @Transactional
  1563. public void updateExamStatus(Long id, ExamStatus examStatus) {
  1564. LambdaUpdateWrapper<StudentEntity> lw = new LambdaUpdateWrapper<>();
  1565. lw.set(StudentEntity::getExamStatus, examStatus);
  1566. lw.eq(StudentEntity::getId, id);
  1567. this.update(lw);
  1568. }
  1569. @Override
  1570. public void importExamStatus(ExamStatusImportTaskVo vo) {
  1571. Map<String, StudentEntity> examNumbers = new HashMap<>();
  1572. Map<String, Boolean> absentMap = new HashMap<>();
  1573. InputStream in = null;
  1574. try {
  1575. in = new FileInputStream(vo.getFile());
  1576. examStatusImportCheck(vo, in, examNumbers, absentMap);
  1577. } catch (ParameterException e) {
  1578. vo.setErrMsg(e.getMessage());
  1579. vo.setStatus(AsyncTaskStatus.FAILED);
  1580. throw e;
  1581. } catch (Exception e) {
  1582. vo.setErrMsg("系统错误");
  1583. vo.setStatus(AsyncTaskStatus.FAILED);
  1584. throw new ParameterException("系统错误", e);
  1585. } finally {
  1586. if (in != null) {
  1587. try {
  1588. in.close();
  1589. } catch (IOException e) {
  1590. }
  1591. }
  1592. }
  1593. if (ExamStatusCheckMode.OVERRIDE.equals(vo.getMode())) {
  1594. for (StudentEntity student : examNumbers.values()) {
  1595. concurrentService.getReadWriteLock(LockType.STUDENT + "-" + student.getId()).writeLock().lock();
  1596. try {
  1597. if (absentMap.get(student.getExamNumber())) {
  1598. student.setExamStatus(ExamStatus.ABSENT);
  1599. } else {
  1600. student.setExamStatus(ExamStatus.OK);
  1601. }
  1602. saveOrUpdate(student);
  1603. vo.setProgressCount(vo.getProgressCount() + 1);
  1604. } finally {
  1605. concurrentService.getReadWriteLock(LockType.STUDENT + "-" + student.getId()).writeLock().unlock();
  1606. }
  1607. }
  1608. }
  1609. if (ExamStatusCheckMode.COMPARE.equals(vo.getMode())) {
  1610. for (StudentEntity student : examNumbers.values()) {
  1611. concurrentService.getReadWriteLock(LockType.STUDENT + "-" + student.getId()).writeLock().lock();
  1612. try {
  1613. if (absentMap.get(student.getExamNumber()) && !ExamStatus.ABSENT.equals(student.getExamStatus())) {
  1614. student.setExamStatus(ExamStatus.UNCHECK3);
  1615. }
  1616. if (!absentMap.get(student.getExamNumber()) && !ExamStatus.OK.equals(student.getExamStatus())) {
  1617. student.setExamStatus(ExamStatus.UNCHECK3);
  1618. }
  1619. saveOrUpdate(student);
  1620. vo.setProgressCount(vo.getProgressCount() + 1);
  1621. } finally {
  1622. concurrentService.getReadWriteLock(LockType.STUDENT + "-" + student.getId()).writeLock().unlock();
  1623. }
  1624. }
  1625. }
  1626. }
  1627. private void examStatusImportCheck(ExamStatusImportTaskVo vo, InputStream in,
  1628. Map<String, StudentEntity> examNumbers, Map<String, Boolean> absentMap) {
  1629. List<String> lineList = null;
  1630. try {
  1631. lineList = IOUtils.readLines(in, "UTF-8");
  1632. } catch (IOException e) {
  1633. throw new ParameterException("读取文件出错", e);
  1634. }
  1635. for (int i = 1; i < lineList.size(); i++) {
  1636. String line = lineList.get(i);
  1637. if (StringUtils.isBlank(line)) {
  1638. continue;
  1639. }
  1640. // 已读字符串长度
  1641. StringBuilder msg = new StringBuilder();
  1642. String[] str = line.split(",");
  1643. if (str.length != 3) {
  1644. msg.append(" 无法解析,请检查分隔符和数据");
  1645. throw new ParameterException(newError(i + 1, msg.toString()));
  1646. }
  1647. String examNumber = str[0];
  1648. String absent = str[1];
  1649. String subjectCode = str[2];
  1650. if (StringUtils.isBlank(subjectCode) || !vo.getSubjectCode().equals(subjectCode)) {
  1651. msg.append(" 科目代码不正确");
  1652. }
  1653. if (StringUtils.isBlank(examNumber)) {
  1654. examNumber = null;
  1655. msg.append(" 准考证号不能为空");
  1656. } else if (examNumber.length() < 15) {
  1657. examNumber = null;
  1658. msg.append(" 准考证号不能小于15位");
  1659. }
  1660. if (StringUtils.isBlank(absent)) {
  1661. msg.append(" 缺考标识不能为空");
  1662. } else if (!absent.equals("0") && !absent.equals("1")) {
  1663. msg.append(" 缺考标识只能为0或1");
  1664. }
  1665. if (examNumber != null) {
  1666. if (examNumbers.containsKey(examNumber)) {
  1667. msg.append(" 准考证号有重复");
  1668. } else {
  1669. StudentEntity student = this.findByExamAndSubjectCodeAndExamNumber(vo.getExamId(), subjectCode,
  1670. examNumber);
  1671. if (student == null) {
  1672. msg.append(" 准考证号不存在");
  1673. } else {
  1674. examNumbers.put(examNumber, student);
  1675. absentMap.put(examNumber, absent.equals("1"));
  1676. }
  1677. }
  1678. }
  1679. if (msg.length() > 0) {
  1680. throw new ParameterException(newError(i + 1, msg.toString()));
  1681. }
  1682. }
  1683. }
  1684. private String newError(int lineNum, String msg) {
  1685. return "第" + lineNum + "行 " + msg;
  1686. }
  1687. @Override
  1688. @Transactional
  1689. public void updateAssignedCheckCount(Long id, boolean deleteHistory) {
  1690. if (deleteHistory) {
  1691. assignedCheckHistoryService.deleteByStudentId(id);
  1692. }
  1693. this.baseMapper.updateAssignedCheckCount(id);
  1694. }
  1695. @Override
  1696. public int getCountByExamAndAssignedCheckCount(Long examId, String subjectCode, int assignedCheckCount, OP op) {
  1697. LambdaQueryWrapper<StudentEntity> wrapper = new LambdaQueryWrapper<>();
  1698. wrapper.eq(StudentEntity::getExamId, examId);
  1699. if (subjectCode != null) {
  1700. wrapper.eq(StudentEntity::getSubjectCode, subjectCode);
  1701. }
  1702. wrapper.eq(StudentEntity::getAssigned, true);
  1703. if (OP.EQ == op) {
  1704. wrapper.eq(StudentEntity::getAssignedCheckCount, assignedCheckCount);
  1705. } else if (OP.GT == op) {
  1706. wrapper.gt(StudentEntity::getAssignedCheckCount, assignedCheckCount);
  1707. } else if (OP.GE == op) {
  1708. wrapper.ge(StudentEntity::getAssignedCheckCount, assignedCheckCount);
  1709. } else if (OP.LE == op) {
  1710. wrapper.le(StudentEntity::getAssignedCheckCount, assignedCheckCount);
  1711. } else if (OP.LT == op) {
  1712. wrapper.lt(StudentEntity::getAssignedCheckCount, assignedCheckCount);
  1713. }
  1714. return this.count(wrapper);
  1715. }
  1716. @Override
  1717. public int countByExamIdAndExamStatus(Long examId, ExamStatus... examStatus) {
  1718. LambdaQueryWrapper<StudentEntity> wrapper = new LambdaQueryWrapper<>();
  1719. wrapper.eq(StudentEntity::getExamId, examId);
  1720. wrapper.in(StudentEntity::getExamStatus, Arrays.asList(examStatus));
  1721. return this.count(wrapper);
  1722. }
  1723. @Override
  1724. public List<AssignedCheckExport> exportAssignedCheckPage(AssignedQueryDomain query) {
  1725. List<AssignedCheckExport> ret = this.baseMapper.exportAssignedCheckPage(
  1726. new Page<AssignedCheckExport>(query.getPageNumber(), query.getPageSize()), query);
  1727. return ret;
  1728. }
  1729. @Override
  1730. public PageResult<AnswerQueryVo> queryAssignedCheckPage(AssignedQueryDomain query) {
  1731. // 查询考生分页信息
  1732. IPage<AnswerQueryVo> iPage = baseMapper
  1733. .queryAssignedCheckPage(new Page<>(query.getPageNumber(), query.getPageSize()), query);
  1734. if (CollectionUtils.isNotEmpty(iPage.getRecords()) && query.getWithPaper()) {
  1735. Map<Long, AnswerQueryVo> map = new HashMap<>();
  1736. for (AnswerQueryVo vo : iPage.getRecords()) {
  1737. List<AnswerPaperVo> papers = new ArrayList<>();
  1738. vo.setPapers(papers);
  1739. if (vo.getAuditorId() != null) {
  1740. UserEntity au = userService.getById(vo.getAuditorId());
  1741. vo.setAuditorName(au.getLoginName());
  1742. }
  1743. // if (vo.getCardPaperCount() != null) {
  1744. // for (int i = 1; i <= vo.getCardPaperCount(); i++) {
  1745. // AnswerPaperVo pv = new AnswerPaperVo();
  1746. // pv.setNumber(i);
  1747. // papers.add(pv);
  1748. // }
  1749. // }
  1750. map.put(vo.getId(), vo);
  1751. }
  1752. // 根据考生id查找绑定paper
  1753. List<Long> studentIds = iPage.getRecords().stream().map(p -> p.getId()).collect(Collectors.toList());
  1754. List<StudentPaperVo> paperList = new BatchGetDataUtil<StudentPaperVo, Long>() {
  1755. @Override
  1756. public List<StudentPaperVo> getData(List<Long> paramList) {
  1757. return paperService.listByStudentIds(paramList);
  1758. }
  1759. }.getDataForBatch(studentIds, 20);
  1760. if (CollectionUtils.isNotEmpty(paperList)) {
  1761. Map<Long, AnswerPaperVo> paperMap = new HashMap<>();
  1762. for (StudentPaperVo p : paperList) {
  1763. AnswerQueryVo vo = map.get(p.getStudentId());
  1764. if (vo == null) {
  1765. continue;
  1766. }
  1767. List<AnswerPaperVo> papers = vo.getPapers();
  1768. if (papers == null) {
  1769. continue;
  1770. }
  1771. // if (papers.size() < p.getNumber()) {
  1772. // continue;
  1773. // }
  1774. if (!p.getAssigned()) {
  1775. continue;
  1776. }
  1777. // AnswerPaperVo pvo = papers.get(p.getNumber() - 1);
  1778. AnswerPaperVo pvo = new AnswerPaperVo();
  1779. pvo.setId(p.getPaperId());
  1780. pvo.setNumber(p.getNumber());
  1781. pvo.setAssigned(p.getAssigned());
  1782. // pvo.setAssignedSuspect(p.getAssignedSuspect());
  1783. papers.add(pvo);
  1784. paperMap.put(p.getPaperId(), pvo);
  1785. }
  1786. // 查找page
  1787. List<Long> paperIds = paperList.stream().map(p -> p.getPaperId()).collect(Collectors.toList());
  1788. List<PaperPageEntity> paperPageList = new BatchGetDataUtil<PaperPageEntity, Long>() {
  1789. @Override
  1790. public List<PaperPageEntity> getData(List<Long> paramList) {
  1791. return paperPageService.listByPaperList(paramList);
  1792. }
  1793. }.getDataForBatch(paperIds, 20);
  1794. if (CollectionUtils.isNotEmpty(paperPageList)) {
  1795. for (PaperPageEntity p : paperPageList) {
  1796. AnswerPaperVo pvo = paperMap.get(p.getPaperId());
  1797. if (pvo == null) {
  1798. continue;
  1799. }
  1800. List<AnswerPageVo> pages = pvo.getPages();
  1801. if (pages == null) {
  1802. pages = new ArrayList<>();
  1803. pvo.setPages(pages);
  1804. }
  1805. AnswerPageVo pageVo = new AnswerPageVo();
  1806. pageVo.setIndex(p.getPageIndex());
  1807. pageVo.setSheetUri(p.getSheetPath());
  1808. pageVo.setSliceUri(p.getSlicePath());
  1809. pages.add(pageVo);
  1810. }
  1811. }
  1812. }
  1813. } else {
  1814. for (AnswerQueryVo vo : iPage.getRecords()) {
  1815. if (vo.getAuditorId() != null) {
  1816. UserEntity au = userService.getById(vo.getAuditorId());
  1817. vo.setAuditorName(au.getLoginName());
  1818. }
  1819. }
  1820. }
  1821. return PageUtil.of(iPage);
  1822. }
  1823. @Override
  1824. public boolean apply(StudentEntity t, String account) {
  1825. TaskLock taskLock = TaskLockUtil.getAssignedCheckTask(t.getExamId() + "_" + t.getSubjectCode());
  1826. boolean lock = taskLock.add(t.getId(), account);
  1827. // 上锁失败直接返回
  1828. if (!lock) {
  1829. return false;
  1830. }
  1831. // 重复校验任务状态
  1832. if (t.getAssignedCheckCount() == 0 || t.getAssignedCheckCount() == 1) {
  1833. return true;
  1834. } else {
  1835. taskLock.remove(t.getId());
  1836. return false;
  1837. }
  1838. }
  1839. @Override
  1840. public boolean hasAppliedAssignedCheckTask(StudentEntity t, String account) {
  1841. TaskLock taskLock = TaskLockUtil.getAssignedCheckTask(t.getExamId() + "_" + t.getSubjectCode());
  1842. return taskLock.exist(t.getId(), account);
  1843. }
  1844. @Override
  1845. public TaskStatusVo getAssignedCheckTaskStatus(Long examId, String subjectCode, User user) {
  1846. TaskStatusVo status = new TaskStatusVo();
  1847. if (Role.AUDITOR.equals(user.getRole())) {
  1848. status.setFinishCount(assignedCheckHistoryService.getCountByUserId(user.getId(), examId, subjectCode));
  1849. status.setTodoCount(this.getCountByExamAndAssignedCheckCount(examId, subjectCode, 0, OP.EQ));
  1850. } else {
  1851. status.setFinishCount(this.getCountByExamAndAssignedCheckCount(examId, subjectCode, 2, OP.GE));
  1852. status.setTodoCount(this.getCountByExamAndAssignedCheckCount(examId, subjectCode, 1, OP.EQ));
  1853. }
  1854. return status;
  1855. }
  1856. @Override
  1857. public void releaseAssignedCheckTaskByUser(Long examId, String subjectCode, String account) {
  1858. TaskLock taskLock = TaskLockUtil.getAssignedCheckTask(examId + "_" + subjectCode);
  1859. taskLock.clear(account);
  1860. }
  1861. @Override
  1862. @Transactional
  1863. public AssignedTaskSaveVo submitAssignedCheckTask(AssginedTaskResult result, User user) {
  1864. StudentEntity student = getById(result.getId());
  1865. if (student == null) {
  1866. throw new ParameterException("考生信息未找到");
  1867. }
  1868. if (student.getAssignedCheckCount() == 0 && !this.hasAppliedAssignedCheckTask(student, user.getAccount())) {
  1869. throw new ParameterException("任务非本人领取");
  1870. }
  1871. concurrentService.getReadWriteLock(LockType.STUDENT + "-" + student.getId()).writeLock().lock();
  1872. try {
  1873. assignedCheckHistoryService.save(user.getId(), student.getId(), student.getExamId());
  1874. // for (AssignedTaskResultPaper paper : result.getPapers()) {
  1875. // paperService.updatePaperAssignedSuspect(student.getId(),
  1876. // paper.getNumber(), result.getAssignedSuspect());
  1877. // }
  1878. // updateStudentByPaper(user, student.getId(), false);
  1879. student.setAssignedSuspect(result.getAssignedSuspect());
  1880. saveOrUpdate(student);
  1881. updateAssignedCheckCount(student.getId(), false);
  1882. } finally {
  1883. concurrentService.getReadWriteLock(LockType.STUDENT + "-" + student.getId()).writeLock().unlock();
  1884. }
  1885. AssignedTaskSaveVo vo = new AssignedTaskSaveVo();
  1886. vo.setId(student.getId());
  1887. vo.setStatus(this.getAssignedCheckTaskStatus(student.getExamId(), student.getSubjectCode(), user));
  1888. return vo;
  1889. }
  1890. @Override
  1891. public PageResult<AnswerQueryVo> getAssignedCheckTaskHistory(Long examId, String subjectCode, Long pageNumber,
  1892. Long pageSize, User user) {
  1893. IPage<AnswerQueryVo> result = this.baseMapper.getAssignedCheckTaskHistory(new Page<>(pageNumber, pageSize),
  1894. examId, subjectCode, user.getId());
  1895. for (AnswerQueryVo t : result.getRecords()) {
  1896. t = toTaskVo(t);
  1897. }
  1898. return PageUtil.of(result);
  1899. }
  1900. @Override
  1901. public AnswerQueryVo getAssignedCheckTask(Long examId, String subjectCode, User user) {
  1902. int retry = 1;
  1903. AnswerQueryVo task = null;
  1904. int checkCount = 0;
  1905. if (Role.AUDITOR.equals(user.getRole())) {
  1906. checkCount = 0;
  1907. } else {
  1908. checkCount = 1;
  1909. }
  1910. while (task == null) {
  1911. IPage<AnswerQueryVo> list = this.findUnCheck(examId, subjectCode, checkCount, retry, 20);
  1912. if (list.getRecords().isEmpty()) {
  1913. break;
  1914. }
  1915. for (AnswerQueryVo t : list.getRecords()) {
  1916. StudentEntity student = this.getById(t.getId());
  1917. if (this.apply(student, user.getAccount())) {
  1918. task = toTaskVo(t);
  1919. break;
  1920. }
  1921. }
  1922. if (task == null) {
  1923. retry++;
  1924. }
  1925. }
  1926. if (task == null) {
  1927. throw NotFoundExceptions.NO_CHECK_ASSIGNED_TASK;
  1928. }
  1929. return task;
  1930. }
  1931. private IPage<AnswerQueryVo> findUnCheck(Long examId, String subjectCode, int checkCount, int pageNumber,
  1932. int pageSize) {
  1933. return this.baseMapper.findUnCheck(new Page<>(pageNumber, pageSize), examId, subjectCode, checkCount);
  1934. }
  1935. private AnswerQueryVo toTaskVo(AnswerQueryVo t) {
  1936. List<AnswerPaperVo> papers = new ArrayList<>();
  1937. t.setPapers(papers);
  1938. // if (t.getCardPaperCount() != null) {
  1939. // for (int i = 1; i <= t.getCardPaperCount(); i++) {
  1940. // AnswerPaperVo pv = new AnswerPaperVo();
  1941. // pv.setNumber(i);
  1942. // papers.add(pv);
  1943. // }
  1944. // }
  1945. List<Long> studentIds = new ArrayList<>();
  1946. studentIds.add(t.getId());
  1947. List<StudentPaperVo> paperList = new BatchGetDataUtil<StudentPaperVo, Long>() {
  1948. @Override
  1949. public List<StudentPaperVo> getData(List<Long> paramList) {
  1950. return paperService.listByStudentIds(paramList);
  1951. }
  1952. }.getDataForBatch(studentIds, 20);
  1953. if (CollectionUtils.isNotEmpty(paperList)) {
  1954. Map<Long, AnswerPaperVo> paperMap = new HashMap<>();
  1955. for (StudentPaperVo p : paperList) {
  1956. AnswerQueryVo vo = t;
  1957. if (vo == null) {
  1958. continue;
  1959. }
  1960. // if (papers.size() < p.getNumber()) {
  1961. // continue;
  1962. // }
  1963. if (!p.getAssigned()) {
  1964. continue;
  1965. }
  1966. AnswerPaperVo pvo = new AnswerPaperVo();
  1967. pvo.setId(p.getPaperId());
  1968. pvo.setNumber(p.getNumber());
  1969. pvo.setAssigned(p.getAssigned());
  1970. // pvo.setAssignedSuspect(p.getAssignedSuspect());
  1971. papers.add(pvo);
  1972. paperMap.put(p.getPaperId(), pvo);
  1973. }
  1974. // 查找page
  1975. List<Long> paperIds = paperList.stream().map(p -> p.getPaperId()).collect(Collectors.toList());
  1976. List<PaperPageEntity> paperPageList = new BatchGetDataUtil<PaperPageEntity, Long>() {
  1977. @Override
  1978. public List<PaperPageEntity> getData(List<Long> paramList) {
  1979. return paperPageService.listByPaperList(paramList);
  1980. }
  1981. }.getDataForBatch(paperIds, 20);
  1982. if (CollectionUtils.isNotEmpty(paperPageList)) {
  1983. for (PaperPageEntity p : paperPageList) {
  1984. AnswerPaperVo pvo = paperMap.get(p.getPaperId());
  1985. if (pvo == null) {
  1986. continue;
  1987. }
  1988. List<AnswerPageVo> pages = pvo.getPages();
  1989. if (pages == null) {
  1990. pages = new ArrayList<>();
  1991. pvo.setPages(pages);
  1992. }
  1993. AnswerPageVo pageVo = new AnswerPageVo();
  1994. pageVo.setIndex(p.getPageIndex());
  1995. pageVo.setSheetUri(p.getSheetPath());
  1996. pageVo.setSliceUri(p.getSlicePath());
  1997. pages.add(pageVo);
  1998. }
  1999. }
  2000. }
  2001. return t;
  2002. }
  2003. @Override
  2004. public StudentAnswerVo studentAnswer(Long batchId, Long studentId) {
  2005. if (batchId == null) {
  2006. throw new ParameterException("batchId不能为空");
  2007. }
  2008. if (studentId == null) {
  2009. throw new ParameterException("studentId不能为空");
  2010. }
  2011. StudentAnswerVo ret = this.baseMapper.getStudentVo(studentId);
  2012. if (ret == null) {
  2013. throw new ParameterException("未找到考生信息");
  2014. }
  2015. ret.setPapers(new ArrayList<>());
  2016. List<StudentPaperVo> paperList = paperService.listByBatchIdAndStudentId(batchId, studentId);
  2017. if (CollectionUtils.isNotEmpty(paperList)) {
  2018. Map<Long, AnswerPaperVo> paperMap = new HashMap<>();
  2019. for (StudentPaperVo p : paperList) {
  2020. AnswerPaperVo pvo = new AnswerPaperVo();
  2021. pvo.setId(p.getPaperId());
  2022. pvo.setNumber(p.getNumber());
  2023. pvo.setAssigned(p.getAssigned());
  2024. pvo.setPages(new ArrayList<>());
  2025. ret.getPapers().add(pvo);
  2026. paperMap.put(p.getPaperId(), pvo);
  2027. }
  2028. // 查找page
  2029. List<Long> paperIds = paperList.stream().map(p -> p.getPaperId()).collect(Collectors.toList());
  2030. List<PaperPageEntity> paperPageList = paperPageService.listByPaperList(paperIds);
  2031. if (CollectionUtils.isNotEmpty(paperPageList)) {
  2032. for (PaperPageEntity p : paperPageList) {
  2033. AnswerPaperVo pvo = paperMap.get(p.getPaperId());
  2034. if (pvo == null) {
  2035. continue;
  2036. }
  2037. AnswerPageVo pageVo = new AnswerPageVo();
  2038. pageVo.setIndex(p.getPageIndex());
  2039. pageVo.setSheetUri(p.getSheetPath());
  2040. pageVo.setSliceUri(p.getSlicePath());
  2041. pageVo.setAbsent(p.getAbsent());
  2042. pageVo.setBreach(p.getBreach());
  2043. pageVo.setPaperType(p.getPaperType());
  2044. pageVo.setQuestion(p.getQuestion());
  2045. pageVo.setSelective(p.getSelective());
  2046. pageVo.setRecogData(p.getRecogData());
  2047. pvo.getPages().add(pageVo);
  2048. }
  2049. }
  2050. }
  2051. return ret;
  2052. }
  2053. @Override
  2054. public List<SubjectScanProgressVo> scanProgress(Long examId, String subjectCode) {
  2055. return this.baseMapper.scanProgress(examId, subjectCode);
  2056. }
  2057. @Override
  2058. public PageResult<ExamRoomScannedVo> examRoomScannedPage(ExamRoomScannedQuery query) {
  2059. // 查询考生分页信息
  2060. IPage<ExamRoomScannedVo> iPage = baseMapper
  2061. .examRoomScannedPage(new Page<>(query.getPageNumber(), query.getPageSize()), query);
  2062. if (CollectionUtils.isNotEmpty(iPage.getRecords())) {
  2063. for (ExamRoomScannedVo vo : iPage.getRecords()) {
  2064. if (!vo.getScanned()) {
  2065. vo.setScannedText("未扫描");
  2066. } else {
  2067. vo.setScannedText("已扫描");
  2068. }
  2069. vo.setExamSite(vo.getExamSite() + "-" + vo.getExamSiteName());
  2070. }
  2071. }
  2072. return PageUtil.of(iPage);
  2073. }
  2074. @Override
  2075. public List<ExamRoomScannedVo> examRoomScannedList(ExamRoomScannedQuery query) {
  2076. return examRoomScannedPage(query).getResult();
  2077. }
  2078. @Override
  2079. public PageResult<StudentPageVo> studentPage(StudentPageQuery query) {
  2080. // 查询考生分页信息
  2081. IPage<StudentPageVo> iPage = baseMapper.studentPage(new Page<>(query.getPageNumber(), query.getPageSize()),
  2082. query);
  2083. if (CollectionUtils.isNotEmpty(iPage.getRecords())) {
  2084. for (StudentPageVo vo : iPage.getRecords()) {
  2085. if (ScanStatus.SCANNED.equals(vo.getStatus())) {
  2086. vo.setScanned("已扫描");
  2087. } else {
  2088. vo.setScanned("未扫描");
  2089. }
  2090. }
  2091. }
  2092. return PageUtil.of(iPage);
  2093. }
  2094. @Override
  2095. public List<StudentPageVo> studentList(StudentPageQuery query) {
  2096. return studentPage(query).getResult();
  2097. }
  2098. @Override
  2099. public List<StudentVo> studentExportList(AnswerQueryDomain query) {
  2100. return baseMapper.studentExport(new Page<>(query.getPageNumber(), query.getPageSize()), query).getRecords();
  2101. }
  2102. @Override
  2103. public List<StudentExamRoomVo> studentExamRoomExportList(AnswerQueryDomain query) {
  2104. return baseMapper.studentExamRoomExport(new Page<>(query.getPageNumber(), query.getPageSize()), query)
  2105. .getRecords();
  2106. }
  2107. @Override
  2108. public TaskIdVo breachImport(Long examId, String subjectCode, MultipartFile file) {
  2109. if (!file.getOriginalFilename().toLowerCase().endsWith(".txt")) {
  2110. throw new ParameterException("只能是txt文件");
  2111. }
  2112. String taskId = FastUUID.get();
  2113. // 暂存临时文件
  2114. File temDir = new File("temp/" + taskId + "/");
  2115. temDir.mkdirs();
  2116. File txt = new File(temDir.getAbsolutePath() + "/breach.txt");
  2117. try {
  2118. file.transferTo(txt);
  2119. List<String> list = FileUtils.readLines(txt, "utf-8");
  2120. if (CollectionUtils.isEmpty(list) || list.size() <= 1) {
  2121. throw new ParameterException("文件内容为空");
  2122. }
  2123. BreachAndStatusImportTaskVo vo = new BreachAndStatusImportTaskVo();
  2124. vo.setTaskId(taskId);
  2125. vo.setTotalCount(list.size() - 1);
  2126. vo.setExamId(examId);
  2127. vo.setSubjectCode(subjectCode);
  2128. vo.setStatus(AsyncTaskStatus.RUNNING);
  2129. vo.setProgress(0.0);
  2130. vo.setTempDir(temDir);
  2131. vo.setFile(txt);
  2132. BreachImportConsumer com = SpringContextHolder.getBean(BreachImportConsumer.class);
  2133. com.setVo(vo);
  2134. exec.execute(com);
  2135. asyncTaskService.addTask(vo);
  2136. return TaskIdVo.create(vo.getTaskId());
  2137. } catch (ParameterException e) {
  2138. throw e;
  2139. } catch (Exception e) {
  2140. throw new RuntimeException("系统错误", e);
  2141. }
  2142. }
  2143. @Override
  2144. public void breachImportDispose(BreachAndStatusImportTaskVo vo) {
  2145. InputStream in = null;
  2146. try {
  2147. in = new FileInputStream(vo.getFile());
  2148. breachImportCheck(vo, in);
  2149. } catch (ParameterException e) {
  2150. vo.setErrMsg(e.getMessage());
  2151. vo.setStatus(AsyncTaskStatus.FAILED);
  2152. throw e;
  2153. } catch (Exception e) {
  2154. vo.setErrMsg("系统错误");
  2155. vo.setStatus(AsyncTaskStatus.FAILED);
  2156. throw new ParameterException("系统错误", e);
  2157. } finally {
  2158. if (in != null) {
  2159. try {
  2160. in.close();
  2161. } catch (IOException e) {
  2162. }
  2163. }
  2164. }
  2165. // 根据校验结果上传文件
  2166. InputStream excelIn = null;
  2167. try {
  2168. String md5 = MD5Util.md5Hex(vo.getFile());
  2169. excelIn = new FileInputStream(vo.getFile());
  2170. fileService.uploadBreach(excelIn, md5, vo.getExamId(), vo.getSubjectCode());
  2171. } catch (IOException e) {
  2172. vo.setErrMsg("系统错误");
  2173. vo.setStatus(AsyncTaskStatus.FAILED);
  2174. throw new ParameterException("系统错误", e);
  2175. } finally {
  2176. if (excelIn != null) {
  2177. try {
  2178. excelIn.close();
  2179. } catch (IOException e) {
  2180. }
  2181. }
  2182. }
  2183. File info = new File(vo.getTempDir().getAbsolutePath() + "/breach-info.txt");
  2184. InputStream infoIn = null;
  2185. try {
  2186. FileUtils.write(info, vo.getProgressCount() + "", "utf-8");
  2187. String md5 = MD5Util.md5Hex(info);
  2188. infoIn = new FileInputStream(info);
  2189. fileService.uploadBreachInfo(infoIn, md5, vo.getExamId(), vo.getSubjectCode());
  2190. } catch (IOException e) {
  2191. vo.setErrMsg("系统错误");
  2192. vo.setStatus(AsyncTaskStatus.FAILED);
  2193. throw new ParameterException("系统错误", e);
  2194. } finally {
  2195. if (infoIn != null) {
  2196. try {
  2197. infoIn.close();
  2198. } catch (IOException e) {
  2199. }
  2200. }
  2201. }
  2202. vo.setTotalCount(vo.getProgressCount());
  2203. vo.setStatus(AsyncTaskStatus.SUCCESS);
  2204. }
  2205. private void breachImportCheck(BreachAndStatusImportTaskVo vo, InputStream in) {
  2206. List<String> lineList = null;
  2207. try {
  2208. lineList = IOUtils.readLines(in, "UTF-8");
  2209. } catch (IOException e) {
  2210. throw new ParameterException("读取文件出错", e);
  2211. }
  2212. Set<String> examNumberSet = new HashSet<>();
  2213. for (int i = 1; i < lineList.size(); i++) {
  2214. String lineString = lineList.get(i);
  2215. if (StringUtils.isBlank(lineString)) {
  2216. continue;
  2217. }
  2218. StringBuilder msg = new StringBuilder();
  2219. String[] line = lineString.split(",");
  2220. if (line.length != 4) {
  2221. msg.append(" 格式错误");
  2222. } else {
  2223. String subjectCode = trimAndNullIfBlank(line[0]);
  2224. if (StringUtils.isBlank(subjectCode)) {
  2225. throw new ParameterException(errorMsg(i + 1, " 科目代码不能为空"));
  2226. }
  2227. String examNumber = trimAndNullIfBlank(line[1]);
  2228. if (StringUtils.isBlank(examNumber)) {
  2229. msg.append(" 准考证号不能为空");
  2230. } else {
  2231. StudentEntity s = findByExamAndSubjectCodeAndExamNumber(vo.getExamId(), vo.getSubjectCode(),
  2232. examNumber);
  2233. if (s == null) {
  2234. msg.append(" 准考证号未找到");
  2235. } else {
  2236. if (examNumberSet.contains(examNumber)) {
  2237. msg.append(" 准考证号重复");
  2238. } else {
  2239. examNumberSet.add(examNumber);
  2240. }
  2241. }
  2242. }
  2243. String breach = trimAndNullIfBlank(line[3]);
  2244. if (StringUtils.isBlank(breach)) {
  2245. msg.append(" 违纪不能为空");
  2246. } else {
  2247. vo.setProgressCount(vo.getProgressCount() + 1);
  2248. }
  2249. }
  2250. if (msg.length() > 0) {
  2251. throw new ParameterException(errorMsg(i + 1, msg.toString()));
  2252. }
  2253. }
  2254. }
  2255. private String errorMsg(int lineNum, String msg) {
  2256. return "第" + lineNum + "行 " + msg;
  2257. }
  2258. @Override
  2259. public TaskIdVo custStatusImport(Long examId, String subjectCode, MultipartFile file) {
  2260. if (!file.getOriginalFilename().toLowerCase().endsWith(".txt")) {
  2261. throw new ParameterException("只能是txt文件");
  2262. }
  2263. String taskId = FastUUID.get();
  2264. // 暂存临时文件
  2265. File temDir = new File("temp/" + taskId + "/");
  2266. temDir.mkdirs();
  2267. File txt = new File(temDir.getAbsolutePath() + "/cust-status.txt");
  2268. try {
  2269. file.transferTo(txt);
  2270. List<String> list = FileUtils.readLines(txt, "utf-8");
  2271. if (CollectionUtils.isEmpty(list) || list.size() <= 1) {
  2272. throw new ParameterException("文件内容为空");
  2273. }
  2274. BreachAndStatusImportTaskVo vo = new BreachAndStatusImportTaskVo();
  2275. vo.setTaskId(taskId);
  2276. vo.setTotalCount(list.size() - 1);
  2277. vo.setExamId(examId);
  2278. vo.setSubjectCode(subjectCode);
  2279. vo.setStatus(AsyncTaskStatus.RUNNING);
  2280. vo.setProgress(0.0);
  2281. vo.setTempDir(temDir);
  2282. vo.setFile(txt);
  2283. CustStatusImportConsumer com = SpringContextHolder.getBean(CustStatusImportConsumer.class);
  2284. com.setVo(vo);
  2285. exec.execute(com);
  2286. asyncTaskService.addTask(vo);
  2287. return TaskIdVo.create(vo.getTaskId());
  2288. } catch (ParameterException e) {
  2289. throw e;
  2290. } catch (Exception e) {
  2291. throw new RuntimeException("系统错误", e);
  2292. }
  2293. }
  2294. @Override
  2295. public void custStatusImportDispose(BreachAndStatusImportTaskVo vo) {
  2296. InputStream in = null;
  2297. try {
  2298. in = new FileInputStream(vo.getFile());
  2299. custStatusImportCheck(vo, in);
  2300. } catch (ParameterException e) {
  2301. vo.setErrMsg(e.getMessage());
  2302. vo.setStatus(AsyncTaskStatus.FAILED);
  2303. throw e;
  2304. } catch (Exception e) {
  2305. vo.setErrMsg("系统错误");
  2306. vo.setStatus(AsyncTaskStatus.FAILED);
  2307. throw new ParameterException("系统错误", e);
  2308. } finally {
  2309. if (in != null) {
  2310. try {
  2311. in.close();
  2312. } catch (IOException e) {
  2313. }
  2314. }
  2315. }
  2316. // 根据校验结果上传文件
  2317. InputStream excelIn = null;
  2318. try {
  2319. String md5 = MD5Util.md5Hex(vo.getFile());
  2320. excelIn = new FileInputStream(vo.getFile());
  2321. fileService.uploadCustStatus(excelIn, md5, vo.getExamId(), vo.getSubjectCode());
  2322. } catch (IOException e) {
  2323. vo.setErrMsg("系统错误");
  2324. vo.setStatus(AsyncTaskStatus.FAILED);
  2325. throw new ParameterException("系统错误", e);
  2326. } finally {
  2327. if (excelIn != null) {
  2328. try {
  2329. excelIn.close();
  2330. } catch (IOException e) {
  2331. }
  2332. }
  2333. }
  2334. File info = new File(vo.getTempDir().getAbsolutePath() + "/cust-status-info.txt");
  2335. InputStream infoIn = null;
  2336. try {
  2337. FileUtils.write(info, vo.getProgressCount() + "", "utf-8");
  2338. String md5 = MD5Util.md5Hex(info);
  2339. infoIn = new FileInputStream(info);
  2340. fileService.uploadCustStatusInfo(infoIn, md5, vo.getExamId(), vo.getSubjectCode());
  2341. } catch (IOException e) {
  2342. vo.setErrMsg("系统错误");
  2343. vo.setStatus(AsyncTaskStatus.FAILED);
  2344. throw new ParameterException("系统错误", e);
  2345. } finally {
  2346. if (infoIn != null) {
  2347. try {
  2348. infoIn.close();
  2349. } catch (IOException e) {
  2350. }
  2351. }
  2352. }
  2353. vo.setTotalCount(vo.getProgressCount());
  2354. vo.setStatus(AsyncTaskStatus.SUCCESS);
  2355. }
  2356. private void custStatusImportCheck(BreachAndStatusImportTaskVo vo, InputStream in) {
  2357. List<String> lineList = null;
  2358. try {
  2359. lineList = IOUtils.readLines(in, "UTF-8");
  2360. } catch (IOException e) {
  2361. throw new ParameterException("读取文件出错", e);
  2362. }
  2363. Set<String> examNumberSet = new HashSet<>();
  2364. for (int i = 1; i < lineList.size(); i++) {
  2365. String lineString = lineList.get(i);
  2366. if (StringUtils.isBlank(lineString)) {
  2367. continue;
  2368. }
  2369. StringBuilder msg = new StringBuilder();
  2370. String[] line = lineString.split(",");
  2371. if (line.length != 4) {
  2372. msg.append(" 格式错误");
  2373. } else {
  2374. String subjectCode = trimAndNullIfBlank(line[0]);
  2375. if (StringUtils.isBlank(subjectCode)) {
  2376. throw new ParameterException(errorMsg(i + 1, " 科目代码不能为空"));
  2377. }
  2378. String examNumber = trimAndNullIfBlank(line[1]);
  2379. if (StringUtils.isBlank(examNumber)) {
  2380. msg.append(" 准考证号不能为空");
  2381. } else {
  2382. StudentEntity s = findByExamAndSubjectCodeAndExamNumber(vo.getExamId(), vo.getSubjectCode(),
  2383. examNumber);
  2384. if (s == null) {
  2385. msg.append(" 准考证号未找到");
  2386. } else {
  2387. if (examNumberSet.contains(examNumber)) {
  2388. msg.append(" 准考证号重复");
  2389. } else {
  2390. examNumberSet.add(examNumber);
  2391. }
  2392. }
  2393. }
  2394. String breach = trimAndNullIfBlank(line[3]);
  2395. if (StringUtils.isBlank(breach)) {
  2396. msg.append(" 考生状态不能为空");
  2397. } else {
  2398. vo.setProgressCount(vo.getProgressCount() + 1);
  2399. }
  2400. }
  2401. if (msg.length() > 0) {
  2402. throw new ParameterException(errorMsg(i + 1, msg.toString()));
  2403. }
  2404. }
  2405. }
  2406. @Override
  2407. public List<StudentCountVo> countStudent(Long examId) {
  2408. if (examId == null) {
  2409. throw new ParameterException("examId不能为空");
  2410. }
  2411. return baseMapper.countStudent(examId);
  2412. }
  2413. @Override
  2414. public List<AssignedCheckExamRoomExport> exportAssignedCheck(Long examId, String subjectCode) {
  2415. return baseMapper.exportAssignedCheck(examId, subjectCode);
  2416. }
  2417. @Override
  2418. public void resetAssignedCheck(Long examId, String subjectCode) {
  2419. TaskLock taskLock = TaskLockUtil.getAssignedCheckTask(examId + "_" + subjectCode);
  2420. taskLock.clear();
  2421. QueryWrapper<StudentEntity> wrapper = new QueryWrapper<>();
  2422. LambdaQueryWrapper<StudentEntity> lw = wrapper.lambda();
  2423. lw.eq(StudentEntity::getExamId, examId);
  2424. lw.eq(StudentEntity::getSubjectCode, subjectCode);
  2425. lw.eq(StudentEntity::getAssigned, true);
  2426. lw.gt(StudentEntity::getAssignedCheckCount, 1);
  2427. List<StudentEntity> list = this.list(wrapper);
  2428. for (StudentEntity student : list) {
  2429. concurrentService.getReadWriteLock(LockType.STUDENT + "-" + student.getId()).writeLock().lock();
  2430. try {
  2431. student.setAbsentSuspect(false);
  2432. student.setAssignedCheckCount(1);
  2433. saveOrUpdate(student);
  2434. assignedCheckHistoryService.deleteByStudentIdAndUserRole(student.getId(), Role.SCHOOL_ADMIN);
  2435. } finally {
  2436. concurrentService.getReadWriteLock(LockType.STUDENT + "-" + student.getId()).writeLock().unlock();
  2437. }
  2438. }
  2439. }
  2440. @Transactional
  2441. @Override
  2442. public void updateImageCheckStatus(Long id, ImageCheckStatus status) {
  2443. LambdaUpdateWrapper<StudentEntity> lw = new LambdaUpdateWrapper<>();
  2444. lw.set(StudentEntity::getImageCheckStatus, status);
  2445. lw.eq(StudentEntity::getId, id);
  2446. update(lw);
  2447. }
  2448. @Override
  2449. public boolean existUncheck(Long examId, String subjectCode) {
  2450. List<ExamStatus> st = new ArrayList<>();
  2451. st.add(ExamStatus.UNCHECK1);
  2452. st.add(ExamStatus.UNCHECK2);
  2453. st.add(ExamStatus.UNCHECK3);
  2454. LambdaQueryWrapper<StudentEntity> wrapper = new LambdaQueryWrapper<>();
  2455. wrapper.eq(StudentEntity::getExamId, examId);
  2456. wrapper.eq(StudentEntity::getSubjectCode, subjectCode);
  2457. wrapper.in(StudentEntity::getExamStatus, st);
  2458. wrapper.last("LIMIT 1");
  2459. return this.getOne(wrapper) != null;
  2460. }
  2461. }