浏览代码

update studentImport

deason 8 月之前
父节点
当前提交
5ef592850c

+ 37 - 9
src/main/java/cn/com/qmth/scancentral/controller/admin/StudentImportController.java

@@ -1,11 +1,14 @@
 package cn.com.qmth.scancentral.controller.admin;
 
 import cn.com.qmth.scancentral.controller.BaseController;
+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.StudentService;
+import cn.com.qmth.scancentral.util.FileUtil;
 import cn.com.qmth.scancentral.util.ResouceUtil;
 import cn.com.qmth.scancentral.vo.ResultVo;
+import cn.com.qmth.scancentral.vo.studentimport.ImportTaskVo;
 import cn.com.qmth.scancentral.vo.studentimport.StudentCountVo;
 import cn.com.qmth.scancentral.vo.studentimport.StudentImportConfigVo;
 import com.qmth.boot.api.annotation.Aac;
@@ -14,6 +17,9 @@ import com.qmth.boot.core.exception.StatusException;
 import com.qmth.boot.tools.uuid.FastUUID;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
+import org.apache.commons.io.FileUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.multipart.MultipartFile;
@@ -29,6 +35,8 @@ import java.util.Map;
 @Aac(strict = false, auth = true)
 public class StudentImportController extends BaseController {
 
+    private static final Logger log = LoggerFactory.getLogger(StudentImportController.class);
+
     @Autowired
     private StudentService studentService;
 
@@ -45,8 +53,35 @@ public class StudentImportController extends BaseController {
             throw new StatusException("有正在运行的考生导入任务,请稍后再试!");
         }
 
+        ExamEntity exam = examService.getById(examId);
+        if (exam == null) {
+            throw new StatusException("当前考试不存在!");
+        }
+
+        if (exam.getYear() == null || exam.getYearHalf() == null) {
+            throw new StatusException("未设置考试年度或考次!");
+        }
+
+        String fileSuffix = FileUtil.getFileSuffix(file.getOriginalFilename());
+        if (!".txt".equals(fileSuffix)) {
+            throw new StatusException("导入模板目前仅支持后缀名为“.txt”的文件!");
+        }
+
         final String taskId = FastUUID.get();
-        studentImportService.studentImport(taskId, examId, file.getOriginalFilename(), file.getBytes());
+        List<String> lines;
+        try {
+            final String tempDir = "temp/import_data/";
+            FileUtil.makeDirs(tempDir);
+            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(), e);
+            throw new StatusException("读取导入数据文件失败!");
+        }
+
+        studentImportService.studentImport(taskId, lines, examId, exam.getYear(), exam.getYearHalf());
 
         Map<String, Object> result = new HashMap<>();
         result.put("taskId", taskId);
@@ -55,17 +90,10 @@ public class StudentImportController extends BaseController {
 
     @ApiOperation(value = "考生导入进度查询")
     @PostMapping("/import/progress")
-    public Map<String, Object> studentImportProgress(@RequestParam String taskId) {
+    public ImportTaskVo studentImportProgress(@RequestParam String taskId) {
         return studentImportService.studentImportProgress(taskId);
     }
 
-    @ApiOperation(value = "考生导入报告下载", hidden = true)
-    @GetMapping("/import/report/{taskId}")
-    public void importReport(@PathVariable String taskId) {
-        File logFile = studentImportService.studentImportReport(taskId);
-        super.exportFile("考生导入报告.txt", logFile);
-    }
-
     @ApiOperation(value = "查询科目考生数")
     @PostMapping("/count")
     public List<StudentCountVo> countStudent(@RequestParam Long examId) {

+ 6 - 7
src/main/java/cn/com/qmth/scancentral/service/StudentImportService.java

@@ -1,16 +1,15 @@
 package cn.com.qmth.scancentral.service;
 
-import java.io.File;
-import java.util.Map;
+import cn.com.qmth.scancentral.vo.studentimport.ImportTaskVo;
 
-public interface StudentImportService {
+import java.util.List;
 
-    void studentImport(String taskId, Long examId, String fileName, byte[] fileBytes);
+public interface StudentImportService {
 
-    Map<String, Object> studentImportProgress(String taskId);
+    boolean existRunningStudentImportTask();
 
-    File studentImportReport(String taskId);
+    void studentImport(String taskId, List<String> lines, Long examId, Integer yearConfig, Integer yearHalfConfig);
 
-    boolean existRunningStudentImportTask();
+    ImportTaskVo studentImportProgress(String taskId);
 
 }

+ 33 - 129
src/main/java/cn/com/qmth/scancentral/service/impl/StudentImportServiceImpl.java

@@ -1,12 +1,9 @@
 package cn.com.qmth.scancentral.service.impl;
 
 import cn.com.qmth.scancentral.bean.ImportStudentDomain;
-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.StudentService;
 import cn.com.qmth.scancentral.service.SubjectService;
-import cn.com.qmth.scancentral.util.FileUtil;
 import cn.com.qmth.scancentral.vo.studentimport.ImportTaskVo;
 import cn.com.qmth.scancentral.vo.studentimport.StudentImportInfo;
 import com.qmth.boot.core.exception.ParameterException;
@@ -31,9 +28,6 @@ public class StudentImportServiceImpl implements StudentImportService {
 
     private final static Map<String, ImportTaskVo> IMPORT_TASKS = new ConcurrentHashMap<>();
 
-    @Autowired
-    private ExamService examService;
-
     @Autowired
     private SubjectService subjectService;
 
@@ -41,43 +35,18 @@ public class StudentImportServiceImpl implements StudentImportService {
     private StudentService studentService;
 
     @Override
-    public Map<String, Object> studentImportProgress(String taskId) {
+    public ImportTaskVo studentImportProgress(String taskId) {
         ImportTaskVo task = IMPORT_TASKS.get(taskId);
         if (task == null) {
             throw new ParameterException("考生导入任务不存在");
         }
-
-        Map<String, Object> result = new HashMap<>();
-        result.put("progress", task.getProgress());
-        if (task.getProgress() == 100d) {
-            result.put("logFileUrl", "/api/admin/student/import/report/" + taskId);
-        }
-        return result;
-    }
-
-    @Override
-    public File studentImportReport(String taskId) {
-        ImportTaskVo task = IMPORT_TASKS.get(taskId);
-        if (task == null) {
-            throw new ParameterException("考生导入任务不存在");
-        }
-
-        if (task.getProgress() != 100d) {
-            throw new ParameterException("考生导入报告文件正在生成中");
-        }
-
-        File logFile = new File(task.getLogFilePath());
-        if (!logFile.exists()) {
-            throw new ParameterException("考生导入报告文件不存在");
-        }
-
-        return logFile;
+        return task;
     }
 
     @Override
     public boolean existRunningStudentImportTask() {
         for (ImportTaskVo task : IMPORT_TASKS.values()) {
-            if (task.getProgress() < 100d) {
+            if (task.getRunning()) {
                 return true;
             }
         }
@@ -86,73 +55,27 @@ public class StudentImportServiceImpl implements StudentImportService {
 
     @Async
     @Override
-    public void studentImport(String taskId, Long examId, String fileName, byte[] fileBytes) {
-        final String tempDir = "temp/import_data/";
-        FileUtil.makeDirs(tempDir);
-        File logFile = new File(tempDir + taskId + ".log");
-
+    public void studentImport(String taskId, List<String> lines, Long examId, Integer yearConfig, Integer yearHalfConfig) {
         ImportTaskVo task = new ImportTaskVo();
         task.setTaskId(taskId);
         task.setProgress(0d);
-        task.setLogFilePath(logFile.getAbsolutePath());
+        task.setRunning(true);
         IMPORT_TASKS.put(taskId, task);
 
-        int total = 0, finishCount = 0;
-
+        List<StudentImportInfo> list = new ArrayList<>();
         try {
-            ExamEntity exam = examService.getById(examId);
-            if (exam == null) {
-                this.writeLogFile(logFile, "【错误】当前考试不存在");
-                task.setProgress(100d);
-                return;
-            }
-
-            if (exam.getYear() == null || exam.getYearHalf() == null) {
-                this.writeLogFile(logFile, "【错误】未设置考试年度或考次");
-                task.setProgress(100d);
-                return;
-            }
-
-            String fileSuffix = FileUtil.getFileSuffix(fileName);
-            if (!".txt".equals(fileSuffix)) {
-                this.writeLogFile(logFile, "【错误】导入模板目前仅支持后缀名为“.txt”的文件");
-                task.setProgress(100d);
-                return;
-            }
-
-            List<String> lines;
-            try {
-                File dataFile = new File(tempDir + taskId + fileSuffix);
-                FileUtils.writeByteArrayToFile(dataFile, fileBytes);
-                lines = FileUtil.readAllLines(dataFile);
-                log.warn("读取考生数据文件共{}行! taskId:{}", lines.size(), taskId);
-            } catch (Exception e) {
-                log.error(e.getMessage());
-                this.writeLogFile(logFile, "【错误】读取导入数据文件失败");
-                task.setProgress(100d);
-                return;
-            }
-
-            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()) {
-                errs.add(String.format("本次解析考生数据共%s条,执行导入0条,请先处理文件内容错误!", list.size()));
-                this.writeLogFile(logFile, StringUtils.join(errs, "\n"));
-                task.setProgress(100d);
-                return;
-            }
-
-            if (list.isEmpty()) {
-                this.writeLogFile(logFile, "本次解析考生数据共0条,请填写有效的数据内容!");
-                task.setProgress(100d);
-                return;
-            }
-
-            log.info("执行导入数据库开始... {}", taskId);
-            this.writeLogFile(logFile, "执行导入数据库开始...");
+            this.parseValues(lines, list, examId, yearConfig, yearHalfConfig);
+            log.warn("【考生导入】解析考生数据,有效共{}条! taskId:{}", list.size(), taskId);
+        } catch (Exception e) {
+            log.error("【考生导入】解析考生数据错误! taskId:{} {}", taskId, e.getMessage());
+            task.setRunning(false);
+            task.setErrMsg(e.getMessage());
+            return;
+        }
 
-            total = list.size();
+        int total = list.size(), finishCount = 0;
+        try {
+            log.info("【考生导入】执行导入数据库开始... {}", taskId);
             long startTime = System.currentTimeMillis();
 
             int batchNum = 1000;
@@ -168,7 +91,7 @@ public class StudentImportServiceImpl implements StudentImportService {
 
                     double progress = finishCount * 100f / total;
                     long cost = (System.currentTimeMillis() - startTime) / 1000L;
-                    log.info("已导入:{}条 已耗时:{}秒 进度:{}%", finishCount, cost, progress);
+                    log.info("【考生导入】共{}条 已导入:{}条 已耗时:{}秒 进度:{}%", total, finishCount, cost, progress);
                     task.setProgress(progress);
                 }
             }
@@ -178,16 +101,14 @@ public class StudentImportServiceImpl implements StudentImportService {
                 finishCount = finishCount + batchList.size();
             }
 
+            task.setProgress(100d);
             long cost = (System.currentTimeMillis() - startTime) / 1000L;
-            log.info("已导入:{}条 已耗时:{}秒 进度:100% taskId:{}", finishCount, cost, taskId);
-            this.writeLogFile(logFile,
-                    String.format("本次解析考生数据共%s条,已导入%s条,未导入%s条!", total, finishCount, total - finishCount));
+            log.info("【考生导入】共{}条 已导入:{}条 已耗时:{}秒 进度:100% taskId:{}", total, finishCount, cost, taskId);
         } catch (Exception e) {
-            log.error("导入过程异常终止,已导入{}条,未导入{}条!taskId:{} err:{}", finishCount, total - finishCount, taskId,
-                    e.getMessage(), e);
-            this.writeLogFile(logFile, String.format("【错误】导入过程异常终止,已导入%s条,未导入%s条!", finishCount, total - finishCount));
+            task.setErrMsg(String.format("导入异常终止,已导入%s条,未导入%s条!", finishCount, total - finishCount));
+            log.error("【考生导入】导入异常终止,已导入{}条,未导入{}条!taskId:{} err:{}", finishCount, total - finishCount, taskId, e.getMessage(), e);
         } finally {
-            task.setProgress(100d);
+            task.setRunning(false);
         }
     }
 
@@ -208,11 +129,9 @@ public class StudentImportServiceImpl implements StudentImportService {
         return data;
     }
 
-    private List<String> parseValues(List<String> lines, List<StudentImportInfo> list, Long examId, Integer yearConfig,
-            Integer yearHalfConfig) {
+    private void 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++) {
@@ -224,53 +143,40 @@ public class StudentImportServiceImpl implements StudentImportService {
             line = StringUtils.deleteWhitespace(line);
             String[] values = StringUtils.splitByWholeSeparatorPreserveAllTokens(line, ",");
             if (values.length != 3) {
-                errs.add(String.format("【第%s行】数据格式不正确", n + 1));
-                continue;
+                throw new RuntimeException(String.format("【第%s行】数据格式不正确", n + 1));
             }
 
-            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));
+                throw new RuntimeException(String.format("【第%s行】准考证号不能为空", n + 1));
             }
             if (StringUtils.isEmpty(name)) {
-                okData = false;
-                errs.add(String.format("【第%s行】姓名不能为空", n + 1));
+                throw new RuntimeException(String.format("【第%s行】姓名不能为空", n + 1));
             }
             if (StringUtils.isEmpty(examSiteName)) {
-                okData = false;
-                errs.add(String.format("【第%s行】考点名称不能为空", n + 1));
+                throw new RuntimeException(String.format("【第%s行】考点名称不能为空", n + 1));
             }
             if (examNumbers.contains(examNumber)) {
-                okData = false;
-                errs.add(String.format("【第%s行】考生信息存在重复", n + 1));
+                throw new RuntimeException(String.format("【第%s行】考生信息存在重复", n + 1));
             }
             examNumbers.add(examNumber);
 
             if (!examNumberPattern.matcher(examNumber).find()) {
-                errs.add(String.format("【第%s行】准考证号不是15位数字", n + 1));
-                continue;
+                throw new RuntimeException(String.format("【第%s行】准考证号不是15位数字", n + 1));
             }
 
             String year = examNumber.substring(6, 8);
             if (!yearConfig.toString().equals(year)) {
-                okData = false;
-                errs.add(String.format("【第%s行】考试年度不正确", n + 1));
+                throw new RuntimeException(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;
+                throw new RuntimeException(String.format("【第%s行】考次不正确", n + 1));
             }
 
             String province = examNumber.substring(0, 3);
@@ -302,11 +208,9 @@ public class StudentImportServiceImpl implements StudentImportService {
         for (String subjectCode : subjectCodes) {
             if (subjectService.findByExamIdAndCode(examId, subjectCode) == null) {
                 log.warn("科目不存在!examId:{} subjectCode:{}", examId, subjectCode);
-                errs.add(String.format("【错误】科目代码不存在!subjectCode:%s", subjectCode));
+                throw new RuntimeException(String.format("科目代码【%s】不存在!", subjectCode));
             }
         }
-
-        return errs;
     }
 
     private void writeLogFile(File logFile, String content) {

+ 20 - 5
src/main/java/cn/com/qmth/scancentral/vo/studentimport/ImportTaskVo.java

@@ -1,12 +1,19 @@
 package cn.com.qmth.scancentral.vo.studentimport;
 
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import io.swagger.annotations.ApiModelProperty;
+
 public class ImportTaskVo {
 
+    @JsonIgnore
+    @ApiModelProperty(hidden = true)
     private String taskId;
 
     private Double progress;
 
-    private String logFilePath;
+    private Boolean running;
+
+    private String errMsg;
 
     public String getTaskId() {
         return taskId;
@@ -24,12 +31,20 @@ public class ImportTaskVo {
         this.progress = progress;
     }
 
-    public String getLogFilePath() {
-        return logFilePath;
+    public Boolean getRunning() {
+        return running;
+    }
+
+    public void setRunning(Boolean running) {
+        this.running = running;
+    }
+
+    public String getErrMsg() {
+        return errMsg;
     }
 
-    public void setLogFilePath(String logFilePath) {
-        this.logFilePath = logFilePath;
+    public void setErrMsg(String errMsg) {
+        this.errMsg = errMsg;
     }
 
 }