|
@@ -0,0 +1,193 @@
|
|
|
+package cn.com.qmth.scancloud.tools.service.impl;
|
|
|
+
|
|
|
+import java.io.File;
|
|
|
+import java.io.IOException;
|
|
|
+import java.util.ArrayList;
|
|
|
+import java.util.HashSet;
|
|
|
+import java.util.List;
|
|
|
+import java.util.Set;
|
|
|
+import java.util.regex.Pattern;
|
|
|
+
|
|
|
+import org.apache.commons.collections4.CollectionUtils;
|
|
|
+import org.apache.commons.io.LineIterator;
|
|
|
+import org.apache.commons.lang3.StringUtils;
|
|
|
+import org.slf4j.Logger;
|
|
|
+import org.slf4j.LoggerFactory;
|
|
|
+
|
|
|
+import cn.com.qmth.scancloud.tools.config.SysProperty;
|
|
|
+import cn.com.qmth.scancloud.tools.enums.TaskType;
|
|
|
+import cn.com.qmth.scancloud.tools.model.ExamStudent;
|
|
|
+import cn.com.qmth.scancloud.tools.service.AbstractTask;
|
|
|
+import cn.com.qmth.scancloud.tools.service.CommonService;
|
|
|
+import cn.com.qmth.scancloud.tools.utils.FileHelper;
|
|
|
+import cn.com.qmth.scancloud.tools.utils.HttpHelper;
|
|
|
+import cn.com.qmth.scancloud.tools.utils.JsonHelper;
|
|
|
+import cn.com.qmth.scancloud.tools.utils.StatusException;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 考生导入
|
|
|
+ */
|
|
|
+public class ExamStudentImportTask extends AbstractTask {
|
|
|
+
|
|
|
+ private static final Logger log = LoggerFactory.getLogger(ExamStudentImportTask.class);
|
|
|
+ private static Pattern examNumberRex = Pattern.compile("^[0-9]{15}$");
|
|
|
+ @Override
|
|
|
+ protected String getTaskName() {
|
|
|
+ return TaskType.EXAM_STUDENT_IMPORT.getTitle();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ protected void execute() {
|
|
|
+ Long examId = SysProperty.EXAM_ID;
|
|
|
+ if (examId == null) {
|
|
|
+ throw new StatusException("【scan.tool.examId】未配置!");
|
|
|
+ }
|
|
|
+
|
|
|
+ if (CommonService.findExam(examId) == null) {
|
|
|
+ throw new StatusException("当前考试不存在!examId = " + examId);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!SysProperty.DATA_FILE.endsWith(".txt")) {
|
|
|
+ throw new StatusException("导入模板目前仅支持后缀名为“.txt”的文件!");
|
|
|
+ }
|
|
|
+
|
|
|
+ int total = 0;
|
|
|
+ List<ExamStudent> list = new ArrayList<>();
|
|
|
+ Set<String> subjectCodes = new HashSet<>();
|
|
|
+ Set<String> examNumbers = new HashSet<>();
|
|
|
+
|
|
|
+ File file = new File(SysProperty.DATA_FILE);
|
|
|
+ try (LineIterator lines = FileHelper.readLines(file);) {
|
|
|
+ while (lines.hasNext()) {
|
|
|
+ String line = lines.nextLine();
|
|
|
+
|
|
|
+ ExamStudent data = this.parseValues(total, line, examNumbers);
|
|
|
+ if (data != null) {
|
|
|
+ data.setExamId(examId);
|
|
|
+ list.add(data);
|
|
|
+
|
|
|
+ subjectCodes.add(data.getSubjectCode());
|
|
|
+
|
|
|
+ // 同个考试下考生的“准考证号”值唯一
|
|
|
+ examNumbers.add(data.getExamNumber());
|
|
|
+ }
|
|
|
+
|
|
|
+ total++;
|
|
|
+ }
|
|
|
+ } catch (IOException e) {
|
|
|
+ log.error(e.getMessage(), e);
|
|
|
+ }
|
|
|
+
|
|
|
+ log.info("导入文件全部行数共 {} 行,实际有效数据共 {} 条!", total, list.size());
|
|
|
+ if (CollectionUtils.isEmpty(list)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 校验所有科目代码
|
|
|
+ boolean allExist = true;
|
|
|
+ for (String subjectCode : subjectCodes) {
|
|
|
+ if (CommonService.findCourse(examId, subjectCode) == null) {
|
|
|
+ log.warn("科目不存在! examId={} subjectCode={}", examId, subjectCode);
|
|
|
+ allExist = false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (!allExist) {
|
|
|
+ throw new StatusException("科目信息有误!");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 分批保存
|
|
|
+ int batchSize = 5000;
|
|
|
+ List<ExamStudent> batchList = new ArrayList<>();
|
|
|
+ String url = SysProperty.SCAN_SERVER_URL + "/api/tool/import/exam/student";
|
|
|
+ for (int n = 0; n < list.size(); n++) {
|
|
|
+ batchList.add(list.get(n));
|
|
|
+
|
|
|
+ if (batchList.size() % batchSize == 0) {
|
|
|
+ String json = JsonHelper.toJson(batchList);
|
|
|
+ String result = HttpHelper.post(url, json);
|
|
|
+ batchList.clear();
|
|
|
+
|
|
|
+ float rate = (n + 1) * 100f / list.size();
|
|
|
+ log.info("已处理数:{} 进度:{}% {}", n + 1, rate, result);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (CollectionUtils.isNotEmpty(batchList)) {
|
|
|
+ String json = JsonHelper.toJson(batchList);
|
|
|
+ String result = HttpHelper.post(url, json);
|
|
|
+ log.info("已处理数:{} 进度:100% {}", list.size(), result);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private ExamStudent parseValues(int index, String line, Set<String> examNumbers) {
|
|
|
+ if (StringUtils.isBlank(line)) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ line = StringUtils.deleteWhitespace(line);
|
|
|
+ String[] values = StringUtils.splitByWholeSeparatorPreserveAllTokens(line, SysProperty.TEMPLATE_SEPARATOR);
|
|
|
+
|
|
|
+ try {
|
|
|
+
|
|
|
+ // 默认模板:科目代码|科目名称|准考证号|考生姓名|考生编号|卷袋号|座位号|学习中心|考场|考点
|
|
|
+ String examNumber = values[0].trim();
|
|
|
+ String name = values[1].trim();
|
|
|
+ String examSiteName = values[2].trim();
|
|
|
+
|
|
|
+ if (StringUtils.isEmpty(examNumber)) {
|
|
|
+ throw new StatusException(String.format("【第%s行】“准考证号”字段不能为空! %s", index + 1, line));
|
|
|
+ }
|
|
|
+ if (StringUtils.isEmpty(name)) {
|
|
|
+ throw new StatusException(String.format("【第%s行】“考生姓名”字段不能为空! %s", index + 1, line));
|
|
|
+ }
|
|
|
+ if (StringUtils.isEmpty(examSiteName)) {
|
|
|
+ throw new StatusException(String.format("【第%s行】“考点名称”字段不能为空! %s", index + 1, line));
|
|
|
+ }
|
|
|
+ if (examNumbers.contains(examNumber)) {
|
|
|
+ throw new StatusException(String.format("【第%s行】考生信息存在重复! %s", index + 1, line));
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ checkExamNumber(examNumber);
|
|
|
+ } catch (StatusException e) {
|
|
|
+ throw new StatusException(String.format("【第%s行】%s! %s", index + 1,e.getMessage(), line));
|
|
|
+ }
|
|
|
+
|
|
|
+ ExamStudent data = new ExamStudent();
|
|
|
+ data.setExamNumber(examNumber);
|
|
|
+ data.setName(name);
|
|
|
+ data.setExamSite(examNumber.substring(0, 5));
|
|
|
+ data.setExamSiteName(examSiteName);
|
|
|
+ data.setCampusCode(examNumber.substring(0, 6));
|
|
|
+ data.setCampusName(examSiteName+examNumber.substring(5, 6));
|
|
|
+ data.setExamRoom(examNumber.substring(0, 6)+examNumber.substring(10, 13));
|
|
|
+ data.setSeatNumber(examNumber.substring(13, 15));
|
|
|
+ data.setPackageCode(data.getExamRoom());
|
|
|
+ data.setSubjectCode(examNumber.substring(9, 10));
|
|
|
+ data.setStudentCode(examNumber);
|
|
|
+
|
|
|
+ return data;
|
|
|
+ } catch (ArrayIndexOutOfBoundsException e) {
|
|
|
+ log.error("【第{}行】内容格式错误! {} {}", index + 1, line, e.toString());
|
|
|
+ throw new StatusException("数据内容有误!");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void checkExamNumber(String examNumber) {
|
|
|
+ if(!examNumberRex.matcher(examNumber).find()) {
|
|
|
+ throw new StatusException("准考证号不是15位数字");
|
|
|
+ }
|
|
|
+ String year=examNumber.substring(6, 8);
|
|
|
+ if(!year.equals(SysProperty.YEAR)) {
|
|
|
+ throw new StatusException("年度不正确");
|
|
|
+ }
|
|
|
+ String yearHalf=examNumber.substring(8, 9);
|
|
|
+ if(!yearHalf.equals(SysProperty.YEAR_HALF)) {
|
|
|
+ throw new StatusException("考次不正确");
|
|
|
+ }
|
|
|
+ int subjectCode=Integer.valueOf(examNumber.substring(9, 10));
|
|
|
+ if(subjectCode<1||subjectCode>6) {
|
|
|
+ throw new StatusException("语种不正确");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+}
|