|
@@ -1,14 +1,17 @@
|
|
|
package cn.com.qmth.scancentral.service.impl;
|
|
|
|
|
|
import java.io.File;
|
|
|
+import java.io.FileInputStream;
|
|
|
import java.io.IOException;
|
|
|
import java.io.InputStream;
|
|
|
import java.io.InputStreamReader;
|
|
|
import java.io.LineNumberReader;
|
|
|
import java.math.BigDecimal;
|
|
|
import java.util.ArrayList;
|
|
|
+import java.util.Arrays;
|
|
|
import java.util.Date;
|
|
|
import java.util.HashMap;
|
|
|
+import java.util.HashSet;
|
|
|
import java.util.LinkedHashSet;
|
|
|
import java.util.List;
|
|
|
import java.util.Map;
|
|
@@ -18,6 +21,7 @@ import java.util.stream.Collectors;
|
|
|
import javax.validation.constraints.NotNull;
|
|
|
|
|
|
import org.apache.commons.collections4.CollectionUtils;
|
|
|
+import org.apache.commons.io.FileUtils;
|
|
|
import org.apache.commons.lang3.StringUtils;
|
|
|
import org.slf4j.Logger;
|
|
|
import org.slf4j.LoggerFactory;
|
|
@@ -43,6 +47,7 @@ import com.qmth.boot.tools.excel.ExcelReader;
|
|
|
import com.qmth.boot.tools.excel.enums.ExcelType;
|
|
|
import com.qmth.boot.tools.io.IOUtils;
|
|
|
import com.qmth.boot.tools.signature.SignatureType;
|
|
|
+import com.qmth.boot.tools.uuid.FastUUID;
|
|
|
|
|
|
import cn.com.qmth.scancentral.bean.AbsentQueryDomain;
|
|
|
import cn.com.qmth.scancentral.bean.AnswerDeleteDomain;
|
|
@@ -93,6 +98,7 @@ import cn.com.qmth.scancentral.service.AnswerCardSubjectService;
|
|
|
import cn.com.qmth.scancentral.service.AssignedCheckHistoryService;
|
|
|
import cn.com.qmth.scancentral.service.BatchService;
|
|
|
import cn.com.qmth.scancentral.service.ExamService;
|
|
|
+import cn.com.qmth.scancentral.service.FileService;
|
|
|
import cn.com.qmth.scancentral.service.OmrGroupService;
|
|
|
import cn.com.qmth.scancentral.service.OmrTaskService;
|
|
|
import cn.com.qmth.scancentral.service.PaperPageService;
|
|
@@ -108,6 +114,7 @@ import cn.com.qmth.scancentral.support.TaskLock;
|
|
|
import cn.com.qmth.scancentral.support.TaskLockUtil;
|
|
|
import cn.com.qmth.scancentral.util.BatchGetDataUtil;
|
|
|
import cn.com.qmth.scancentral.util.BatchSetDataUtil;
|
|
|
+import cn.com.qmth.scancentral.util.MD5Util;
|
|
|
import cn.com.qmth.scancentral.util.PageUtil;
|
|
|
import cn.com.qmth.scancentral.vo.AbsentInfoVo;
|
|
|
import cn.com.qmth.scancentral.vo.AbsentManualImportVo;
|
|
@@ -120,6 +127,7 @@ import cn.com.qmth.scancentral.vo.CampusVo;
|
|
|
import cn.com.qmth.scancentral.vo.ExamSiteVo;
|
|
|
import cn.com.qmth.scancentral.vo.ExportCetMarkingQueryVo;
|
|
|
import cn.com.qmth.scancentral.vo.ExportCetVo;
|
|
|
+import cn.com.qmth.scancentral.vo.ImportBreachResult;
|
|
|
import cn.com.qmth.scancentral.vo.ImportResult;
|
|
|
import cn.com.qmth.scancentral.vo.ImportStudentQueryVo;
|
|
|
import cn.com.qmth.scancentral.vo.ImportStudentVo;
|
|
@@ -151,6 +159,10 @@ import cn.com.qmth.scancentral.vo.task.TaskStatusVo;
|
|
|
@Service
|
|
|
public class StudentServiceImpl extends ServiceImpl<StudentDao, StudentEntity> implements StudentService {
|
|
|
|
|
|
+ private static final String[] BREACH_EXCEL_HEADER = new String[] { "准考证号", "违纪码" };
|
|
|
+
|
|
|
+ private static final String[] CUST_STATUS_EXCEL_HEADER = new String[] { "准考证号", "考生状态" };
|
|
|
+
|
|
|
private static final Logger log = LoggerFactory.getLogger(StudentService.class);
|
|
|
|
|
|
@Autowired
|
|
@@ -204,6 +216,9 @@ public class StudentServiceImpl extends ServiceImpl<StudentDao, StudentEntity> i
|
|
|
@Autowired
|
|
|
private UserService userService;
|
|
|
|
|
|
+ @Autowired
|
|
|
+ private FileService fileService;
|
|
|
+
|
|
|
|
|
|
* 整体更新考生绑定的paper并刷新考生状态,若集合为空则表示考生无扫描结果,需要在外部调用处对考生上锁
|
|
|
*
|
|
@@ -2376,4 +2391,265 @@ public class StudentServiceImpl extends ServiceImpl<StudentDao, StudentEntity> i
|
|
|
return baseMapper.studentExamRoomExport(new Page<>(query.getPageNumber(), query.getPageSize()), query)
|
|
|
.getRecords();
|
|
|
}
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public ImportBreachResult breachImport(Long examId, String subjectCode, MultipartFile file) {
|
|
|
+
|
|
|
+ File temDir = new File("temp/" + FastUUID.get() + "/");
|
|
|
+ try {
|
|
|
+ temDir.mkdirs();
|
|
|
+ File excel = new File(temDir.getAbsolutePath() + "/breach.xlsx");
|
|
|
+ try {
|
|
|
+ file.transferTo(excel);
|
|
|
+ } catch (Exception e) {
|
|
|
+ throw new RuntimeException("系统错误", e);
|
|
|
+ }
|
|
|
+
|
|
|
+ ImportBreachResult ret = null;
|
|
|
+ InputStream in = null;
|
|
|
+ try {
|
|
|
+ in = new FileInputStream(excel);
|
|
|
+ ret = breachImportCheck(examId, subjectCode, in);
|
|
|
+ } catch (IOException e) {
|
|
|
+ throw new RuntimeException("系统错误", e);
|
|
|
+ } finally {
|
|
|
+ if (in != null) {
|
|
|
+ try {
|
|
|
+ in.close();
|
|
|
+ } catch (IOException e) {
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (ret != null && ret.getSuccess()) {
|
|
|
+ InputStream excelIn = null;
|
|
|
+ try {
|
|
|
+ String md5 = MD5Util.md5Hex(excel);
|
|
|
+ excelIn = new FileInputStream(excel);
|
|
|
+ fileService.uploadBreach(excelIn, md5, examId, subjectCode);
|
|
|
+ } catch (IOException e) {
|
|
|
+ throw new RuntimeException("系统错误", e);
|
|
|
+ } finally {
|
|
|
+ if (excelIn != null) {
|
|
|
+ try {
|
|
|
+ excelIn.close();
|
|
|
+ } catch (IOException e) {
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ File info = new File(temDir.getAbsolutePath() + "/breach-info.txt");
|
|
|
+ InputStream infoIn = null;
|
|
|
+ try {
|
|
|
+ FileUtils.write(info, ret.getBreachCount().toString(), "utf-8");
|
|
|
+ String md5 = MD5Util.md5Hex(info);
|
|
|
+ infoIn = new FileInputStream(info);
|
|
|
+ fileService.uploadBreachInfo(infoIn, md5, examId, subjectCode);
|
|
|
+ } catch (IOException e) {
|
|
|
+ throw new RuntimeException("系统错误", e);
|
|
|
+ } finally {
|
|
|
+ if (infoIn != null) {
|
|
|
+ try {
|
|
|
+ infoIn.close();
|
|
|
+ } catch (IOException e) {
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return ret;
|
|
|
+ } finally {
|
|
|
+ try {
|
|
|
+ FileUtils.deleteDirectory(temDir);
|
|
|
+ } catch (IOException e) {
|
|
|
+ throw new RuntimeException("系统错误", e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private ImportBreachResult breachImportCheck(Long examId, String subjectCode, InputStream in) {
|
|
|
+ List<String[]> lineList = null;
|
|
|
+ ExcelReader reader = ExcelReader.create(ExcelType.XLSX, in, 0);
|
|
|
+ try {
|
|
|
+ lineList = reader.getDataArrayList();
|
|
|
+ } catch (Exception e) {
|
|
|
+ throw new ParameterException("Excel 解析失败");
|
|
|
+ }
|
|
|
+ if (!Arrays.equals(BREACH_EXCEL_HEADER, reader.getColumnNames())) {
|
|
|
+ throw new ParameterException("Excel表头错误");
|
|
|
+ }
|
|
|
+ if (CollectionUtils.isEmpty(lineList)) {
|
|
|
+ throw new ParameterException("Excel无内容");
|
|
|
+ }
|
|
|
+ if (500001 < lineList.size()) {
|
|
|
+ throw new ParameterException("数据行数不能超过500000");
|
|
|
+ }
|
|
|
+ ImportBreachResult ret = new ImportBreachResult();
|
|
|
+ List<String> failRecords = new ArrayList<>();
|
|
|
+ ret.setErrMsg(failRecords);
|
|
|
+ Set<String> examNumberSet = new HashSet<>();
|
|
|
+ for (int i = 0; i < lineList.size(); i++) {
|
|
|
+ String[] line = lineList.get(i);
|
|
|
+
|
|
|
+ StringBuilder msg = new StringBuilder();
|
|
|
+
|
|
|
+ String examNumber = trimAndNullIfBlank(line[0]);
|
|
|
+ if (StringUtils.isBlank(examNumber)) {
|
|
|
+ msg.append(" 准考证号不能为空");
|
|
|
+ } else {
|
|
|
+ StudentEntity s = findByExamAndSubjectCodeAndExamNumber(examId, subjectCode, examNumber);
|
|
|
+ if (s == null) {
|
|
|
+ msg.append(" 准考证号未找到");
|
|
|
+ } else {
|
|
|
+ if (examNumberSet.contains(examNumber)) {
|
|
|
+ msg.append(" 准考证号重复");
|
|
|
+ } else {
|
|
|
+ examNumberSet.add(examNumber);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ String breach = trimAndNullIfBlank(line[1]);
|
|
|
+ if (StringUtils.isNotBlank(breach)) {
|
|
|
+ ret.setBreachCount(ret.getBreachCount() + 1);
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ if (CollectionUtils.isNotEmpty(failRecords)) {
|
|
|
+ ret.setSuccess(false);
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+ ret.setSuccess(true);
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public ImportBreachResult custStatusImport(Long examId, String subjectCode, MultipartFile file) {
|
|
|
+
|
|
|
+ File temDir = new File("temp/" + FastUUID.get() + "/");
|
|
|
+ try {
|
|
|
+ temDir.mkdirs();
|
|
|
+ File excel = new File(temDir.getAbsolutePath() + "/cust-status.xlsx");
|
|
|
+ try {
|
|
|
+ file.transferTo(excel);
|
|
|
+ } catch (Exception e) {
|
|
|
+ throw new RuntimeException("系统错误", e);
|
|
|
+ }
|
|
|
+
|
|
|
+ ImportBreachResult ret = null;
|
|
|
+ InputStream in = null;
|
|
|
+ try {
|
|
|
+ in = new FileInputStream(excel);
|
|
|
+ ret = custStatusImportCheck(examId, subjectCode, in);
|
|
|
+ } catch (IOException e) {
|
|
|
+ throw new RuntimeException("系统错误", e);
|
|
|
+ } finally {
|
|
|
+ if (in != null) {
|
|
|
+ try {
|
|
|
+ in.close();
|
|
|
+ } catch (IOException e) {
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (ret != null && ret.getSuccess()) {
|
|
|
+ InputStream excelIn = null;
|
|
|
+ try {
|
|
|
+ String md5 = MD5Util.md5Hex(excel);
|
|
|
+ excelIn = new FileInputStream(excel);
|
|
|
+ fileService.uploadCustStatus(in, md5, examId, subjectCode);
|
|
|
+ } catch (IOException e) {
|
|
|
+ throw new RuntimeException("系统错误", e);
|
|
|
+ } finally {
|
|
|
+ if (excelIn != null) {
|
|
|
+ try {
|
|
|
+ excelIn.close();
|
|
|
+ } catch (IOException e) {
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ File info = new File(temDir.getAbsolutePath() + "/cust-status-info.txt");
|
|
|
+ InputStream infoIn = null;
|
|
|
+ try {
|
|
|
+ FileUtils.write(info, ret.getBreachCount().toString(), "utf-8");
|
|
|
+ String md5 = MD5Util.md5Hex(info);
|
|
|
+ infoIn = new FileInputStream(info);
|
|
|
+ fileService.uploadCustStatusInfo(infoIn, md5, examId, subjectCode);
|
|
|
+ } catch (IOException e) {
|
|
|
+ throw new RuntimeException("系统错误", e);
|
|
|
+ } finally {
|
|
|
+ if (infoIn != null) {
|
|
|
+ try {
|
|
|
+ infoIn.close();
|
|
|
+ } catch (IOException e) {
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return ret;
|
|
|
+ } finally {
|
|
|
+ try {
|
|
|
+ FileUtils.deleteDirectory(temDir);
|
|
|
+ } catch (IOException e) {
|
|
|
+ throw new RuntimeException("系统错误", e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private ImportBreachResult custStatusImportCheck(Long examId, String subjectCode, InputStream in) {
|
|
|
+ List<String[]> lineList = null;
|
|
|
+ ExcelReader reader = ExcelReader.create(ExcelType.XLSX, in, 0);
|
|
|
+ try {
|
|
|
+ lineList = reader.getDataArrayList();
|
|
|
+ } catch (Exception e) {
|
|
|
+ throw new ParameterException("Excel 解析失败");
|
|
|
+ }
|
|
|
+ if (!Arrays.equals(CUST_STATUS_EXCEL_HEADER, reader.getColumnNames())) {
|
|
|
+ throw new ParameterException("Excel表头错误");
|
|
|
+ }
|
|
|
+ if (CollectionUtils.isEmpty(lineList)) {
|
|
|
+ throw new ParameterException("Excel无内容");
|
|
|
+ }
|
|
|
+ if (500001 < lineList.size()) {
|
|
|
+ throw new ParameterException("数据行数不能超过500000");
|
|
|
+ }
|
|
|
+ ImportBreachResult ret = new ImportBreachResult();
|
|
|
+ List<String> failRecords = new ArrayList<>();
|
|
|
+ ret.setErrMsg(failRecords);
|
|
|
+ Set<String> examNumberSet = new HashSet<>();
|
|
|
+ for (int i = 0; i < lineList.size(); i++) {
|
|
|
+ String[] line = lineList.get(i);
|
|
|
+
|
|
|
+ StringBuilder msg = new StringBuilder();
|
|
|
+
|
|
|
+ String examNumber = trimAndNullIfBlank(line[0]);
|
|
|
+ if (StringUtils.isBlank(examNumber)) {
|
|
|
+ msg.append(" 准考证号不能为空");
|
|
|
+ } else {
|
|
|
+ StudentEntity s = findByExamAndSubjectCodeAndExamNumber(examId, subjectCode, examNumber);
|
|
|
+ if (s == null) {
|
|
|
+ msg.append(" 准考证号未找到");
|
|
|
+ } else {
|
|
|
+ if (examNumberSet.contains(examNumber)) {
|
|
|
+ msg.append(" 准考证号重复");
|
|
|
+ } else {
|
|
|
+ examNumberSet.add(examNumber);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ String breach = trimAndNullIfBlank(line[1]);
|
|
|
+ if (StringUtils.isNotBlank(breach)) {
|
|
|
+ ret.setBreachCount(ret.getBreachCount() + 1);
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ if (CollectionUtils.isNotEmpty(failRecords)) {
|
|
|
+ ret.setSuccess(false);
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+ ret.setSuccess(true);
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+
|
|
|
}
|