|
@@ -1,30 +1,207 @@
|
|
|
package cn.com.qmth.scancentral.service.impl;
|
|
|
|
|
|
+import cn.com.qmth.scancentral.entity.ExamEntity;
|
|
|
+import cn.com.qmth.scancentral.service.ExamService;
|
|
|
import cn.com.qmth.scancentral.service.StudentImportService;
|
|
|
+import cn.com.qmth.scancentral.service.SubjectService;
|
|
|
+import cn.com.qmth.scancentral.util.FileUtil;
|
|
|
+import cn.com.qmth.scancentral.vo.studentimport.StudentImportInfo;
|
|
|
+import com.qmth.boot.tools.uuid.FastUUID;
|
|
|
+import org.apache.commons.io.FileUtils;
|
|
|
+import org.apache.commons.lang3.StringUtils;
|
|
|
import org.slf4j.Logger;
|
|
|
import org.slf4j.LoggerFactory;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.stereotype.Component;
|
|
|
import org.springframework.web.multipart.MultipartFile;
|
|
|
|
|
|
-import java.util.HashMap;
|
|
|
-import java.util.Map;
|
|
|
+import java.io.File;
|
|
|
+import java.io.IOException;
|
|
|
+import java.util.*;
|
|
|
+import java.util.regex.Pattern;
|
|
|
|
|
|
@Component
|
|
|
public class StudentImportServiceImpl implements StudentImportService {
|
|
|
|
|
|
private static final Logger log = LoggerFactory.getLogger(StudentImportServiceImpl.class);
|
|
|
|
|
|
- @Override
|
|
|
- public Long studentImport(Long examId, MultipartFile file) {
|
|
|
- return 1L;
|
|
|
- }
|
|
|
+ @Autowired
|
|
|
+ private ExamService examService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private SubjectService subjectService;
|
|
|
|
|
|
@Override
|
|
|
- public Map<String, Object> studentImportProgress(Long taskId) {
|
|
|
+ public Map<String, Object> studentImportProgress(String taskId) {
|
|
|
Map<String, Object> result = new HashMap<>();
|
|
|
result.put("progress", 100);
|
|
|
result.put("errFileUrl", "");
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
+ @Override
|
|
|
+ public String studentImport(Long examId, MultipartFile file) {
|
|
|
+ final String taskId = FastUUID.get();
|
|
|
+ final String tempDir = "temp/import_data/";
|
|
|
+ FileUtil.makeDirs(tempDir);
|
|
|
+ File logFile = new File(tempDir + taskId + ".log");
|
|
|
+
|
|
|
+ if (examId == null) {
|
|
|
+ this.writeLogFile(logFile, "【错误】考试ID不能为空");
|
|
|
+ return taskId;
|
|
|
+ }
|
|
|
+
|
|
|
+ ExamEntity exam = examService.getById(examId);
|
|
|
+ if (exam == null) {
|
|
|
+ this.writeLogFile(logFile, "【错误】当前考试不存在");
|
|
|
+ return taskId;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (exam.getYear() == null || exam.getYearHalf() == null) {
|
|
|
+ this.writeLogFile(logFile, "【错误】未设置考试年度或考次");
|
|
|
+ return taskId;
|
|
|
+ }
|
|
|
+
|
|
|
+ String fileSuffix = FileUtil.getFileSuffix(file.getOriginalFilename());
|
|
|
+ if (!".txt".equals(fileSuffix)) {
|
|
|
+ this.writeLogFile(logFile, "【错误】导入模板目前仅支持后缀名为“.txt”的文件");
|
|
|
+ return taskId;
|
|
|
+ }
|
|
|
+
|
|
|
+ List<String> lines;
|
|
|
+ try {
|
|
|
+ File dataFile = new File(tempDir + taskId + fileSuffix);
|
|
|
+ FileUtils.writeByteArrayToFile(dataFile, file.getBytes());
|
|
|
+ lines = FileUtil.readAllLines(dataFile);
|
|
|
+ log.warn("读取考生数据文件共{}行! taskId:{}", lines.size(), taskId);
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error(e.getMessage());
|
|
|
+ this.writeLogFile(logFile, "【错误】读取导入数据文件失败");
|
|
|
+ return taskId;
|
|
|
+ }
|
|
|
+
|
|
|
+ List<StudentImportInfo> list = new ArrayList<>();
|
|
|
+ List<String> errs = this.parseValues(lines, list, examId, exam.getYear(), exam.getYearHalf());
|
|
|
+ log.warn("解析考生数据共{}条! errCount:{} taskId:{}", list.size(), errs.size(), taskId);
|
|
|
+ if (!errs.isEmpty()) {
|
|
|
+ this.writeLogFile(logFile, StringUtils.join(errs, "\n"));
|
|
|
+ return taskId;
|
|
|
+ }
|
|
|
+
|
|
|
+ // todo insert
|
|
|
+ log.info("开始写入数据库...");
|
|
|
+
|
|
|
+ this.writeLogFile(logFile, "本次成功导入0条,失败0条");
|
|
|
+ return taskId;
|
|
|
+ }
|
|
|
+
|
|
|
+ private List<String> parseValues(List<String> lines, List<StudentImportInfo> list, Long examId, Integer yearConfig, Integer yearHalfConfig) {
|
|
|
+ Set<String> subjectCodes = new HashSet<>();
|
|
|
+ Set<String> examNumbers = new HashSet<>();
|
|
|
+ List<String> errs = new ArrayList<>();
|
|
|
+ Pattern examNumberPattern = Pattern.compile("^[0-9]{15}$");
|
|
|
+
|
|
|
+ for (int n = 1; n < lines.size(); n++) {
|
|
|
+ String line = lines.get(n);
|
|
|
+ if (StringUtils.isBlank(line)) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ line = StringUtils.deleteWhitespace(line);
|
|
|
+ String[] values = StringUtils.splitByWholeSeparatorPreserveAllTokens(line, ",");
|
|
|
+ if (values.length != 3) {
|
|
|
+ errs.add(String.format("【第%s行】数据格式不正确", n + 1));
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ boolean okData = true;
|
|
|
+ // 默认模板:准考证号,姓名,考点名称(标题行,数据从第二行读取)
|
|
|
+ String examNumber = values[0].trim();
|
|
|
+ String name = values[1].trim();
|
|
|
+ String examSiteName = values[2].trim();
|
|
|
+
|
|
|
+ if (StringUtils.isEmpty(examNumber)) {
|
|
|
+ okData = false;
|
|
|
+ errs.add(String.format("【第%s行】准考证号不能为空", n + 1));
|
|
|
+ }
|
|
|
+ if (StringUtils.isEmpty(name)) {
|
|
|
+ okData = false;
|
|
|
+ errs.add(String.format("【第%s行】姓名不能为空", n + 1));
|
|
|
+ }
|
|
|
+ if (StringUtils.isEmpty(examSiteName)) {
|
|
|
+ okData = false;
|
|
|
+ errs.add(String.format("【第%s行】考点名称不能为空", n + 1));
|
|
|
+ }
|
|
|
+ if (examNumbers.contains(examNumber)) {
|
|
|
+ okData = false;
|
|
|
+ errs.add(String.format("【第%s行】考生信息存在重复", n + 1));
|
|
|
+ }
|
|
|
+ examNumbers.add(examNumber);
|
|
|
+
|
|
|
+ if (!examNumberPattern.matcher(examNumber).find()) {
|
|
|
+ errs.add(String.format("【第%s行】准考证号不是15位数字", n + 1));
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ String year = examNumber.substring(6, 8);
|
|
|
+ if (!yearConfig.toString().equals(year)) {
|
|
|
+ okData = false;
|
|
|
+ errs.add(String.format("【第%s行】考试年度不正确", n + 1));
|
|
|
+ }
|
|
|
+
|
|
|
+ String yearHalf = examNumber.substring(8, 9);
|
|
|
+ if (!yearHalfConfig.toString().equals(yearHalf)) {
|
|
|
+ okData = false;
|
|
|
+ errs.add(String.format("【第%s行】考次不正确", n + 1));
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!okData) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ String subjectCode = examNumber.substring(9, 10);
|
|
|
+ String examSite = examNumber.substring(0, 5);
|
|
|
+ String campusCode = examNumber.substring(0, 6);
|
|
|
+ String examRoom = examNumber.substring(10, 13);
|
|
|
+ String seatNumber = examNumber.substring(13, 15);
|
|
|
+ subjectCodes.add(subjectCode);
|
|
|
+
|
|
|
+ StudentImportInfo data = new StudentImportInfo();
|
|
|
+ data.setExamId(examId);
|
|
|
+ data.setSubjectCode(subjectCode);
|
|
|
+ data.setExamNumber(examNumber);
|
|
|
+ data.setName(name);
|
|
|
+ data.setStudentCode(examNumber);
|
|
|
+ data.setExamSite(examSite);
|
|
|
+ data.setExamSiteName(examSiteName);
|
|
|
+ data.setCampusCode(campusCode);
|
|
|
+ data.setCampusName(examSiteName + examNumber.substring(5, 6));
|
|
|
+ data.setExamRoom(campusCode + examRoom);
|
|
|
+ data.setPackageCode(campusCode + examRoom);
|
|
|
+ data.setSeatNumber(seatNumber);
|
|
|
+ list.add(data);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 校验所有科目代码
|
|
|
+ for (String subjectCode : subjectCodes) {
|
|
|
+ if (subjectService.findByExamIdAndCode(examId, subjectCode) == null) {
|
|
|
+ log.warn("科目不存在!examId:{} subjectCode:{}", examId, subjectCode);
|
|
|
+ errs.add(String.format("【错误】科目代码不存在!subjectCode:%s", subjectCode));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return errs;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void writeLogFile(File logFile, String content) {
|
|
|
+ if (StringUtils.isEmpty(content)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ FileUtils.writeStringToFile(logFile, "\n" + content, "UTF-8", true);
|
|
|
+ } catch (IOException e) {
|
|
|
+ log.error(e.getMessage(), e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
}
|