1
0
ting.yin 2 gadi atpakaļ
vecāks
revīzija
a5fafd7a9c

+ 4 - 2
stmms-web/src/main/java/cn/com/qmth/stmms/admin/exam/PaperController.java

@@ -704,8 +704,10 @@ public class PaperController extends BaseExamController {
                 subjectSet.add(subjectCode);
             }
             if (!subjectSet.isEmpty()) {
-                ScoreReportThread thread = new ScoreReportThread(exam.getId(), subjectSet, lockService, studentService,
-                        questionService, reportService, examService, subjectService, fileService, examLock,
+                Map<Integer, Set<String>> map = new HashMap<Integer, Set<String>>();
+                map.put(exam.getId(), subjectSet);
+                ScoreReportThread thread = new ScoreReportThread(map, lockService, studentService, questionService,
+                        groupService, reportService, examService, subjectService, fileService, examLock,
                         reportSubjectQuestionService, reportSubjectClassService, reportSubjectTeacherService,
                         reportSubjectCollegeService, reportSubjectGroupService, reportSubjectService);
                 taskExecutor.submit(thread);

+ 10 - 2
stmms-web/src/main/java/cn/com/qmth/stmms/admin/report/ReportSubjectRangeController.java

@@ -2,8 +2,10 @@ package cn.com.qmth.stmms.admin.report;
 
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 
 import javax.servlet.http.HttpServletRequest;
@@ -32,6 +34,7 @@ import cn.com.qmth.stmms.biz.exam.service.ExamQuestionService;
 import cn.com.qmth.stmms.biz.exam.service.ExamService;
 import cn.com.qmth.stmms.biz.exam.service.ExamStudentService;
 import cn.com.qmth.stmms.biz.exam.service.ExamSubjectService;
+import cn.com.qmth.stmms.biz.exam.service.MarkGroupService;
 import cn.com.qmth.stmms.biz.file.enums.FormatType;
 import cn.com.qmth.stmms.biz.file.service.FileService;
 import cn.com.qmth.stmms.biz.lock.LockService;
@@ -86,6 +89,9 @@ public class ReportSubjectRangeController extends BaseExamController {
     @Autowired
     private ExamStudentService studentService;
 
+    @Autowired
+    private MarkGroupService groupService;
+
     @Autowired
     private ExamService examService;
 
@@ -196,8 +202,10 @@ public class ReportSubjectRangeController extends BaseExamController {
             subjectSet.add(subjectCode);
         }
         if (!subjectSet.isEmpty()) {
-            ScoreReportThread thread = new ScoreReportThread(examId, subjectSet, lockService, studentService,
-                    questionService, reportService, examService, subjectService, fileService, false,
+            Map<Integer, Set<String>> map = new HashMap<Integer, Set<String>>();
+            map.put(examId, subjectSet);
+            ScoreReportThread thread = new ScoreReportThread(map, lockService, studentService, questionService,
+                    groupService, reportService, examService, subjectService, fileService, false,
                     reportSubjectQuestionService, reportSubjectClassService, reportSubjectTeacherService,
                     reportSubjectCollegeService, reportSubjectGroupService, reportSubjectService);
             taskExecutor.submit(thread);

+ 24 - 341
stmms-web/src/main/java/cn/com/qmth/stmms/admin/thread/ScoreReportJob.java

@@ -1,20 +1,11 @@
 package cn.com.qmth.stmms.admin.thread;
 
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.math.BigDecimal;
-import java.math.RoundingMode;
-import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
-import net.sf.json.JSONArray;
-import net.sf.json.JSONObject;
-
-import org.apache.commons.io.output.ByteArrayOutputStream;
-import org.apache.commons.lang.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -23,28 +14,15 @@ import org.springframework.core.task.AsyncTaskExecutor;
 import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.stereotype.Component;
 
-import com.qmth.boot.tools.codec.CodecUtils;
-
-import cn.com.qmth.stmms.admin.dto.ReportSubjectRangeDTO;
-import cn.com.qmth.stmms.biz.exam.model.Exam;
-import cn.com.qmth.stmms.biz.exam.model.ExamQuestion;
-import cn.com.qmth.stmms.biz.exam.model.ExamStudent;
 import cn.com.qmth.stmms.biz.exam.model.ExamSubject;
+import cn.com.qmth.stmms.biz.exam.model.MarkGroup;
 import cn.com.qmth.stmms.biz.exam.service.ExamQuestionService;
 import cn.com.qmth.stmms.biz.exam.service.ExamService;
 import cn.com.qmth.stmms.biz.exam.service.ExamStudentService;
 import cn.com.qmth.stmms.biz.exam.service.ExamSubjectService;
 import cn.com.qmth.stmms.biz.exam.service.MarkGroupService;
-import cn.com.qmth.stmms.biz.file.enums.FormatType;
 import cn.com.qmth.stmms.biz.file.service.FileService;
 import cn.com.qmth.stmms.biz.lock.LockService;
-import cn.com.qmth.stmms.biz.report.model.ReportSubject;
-import cn.com.qmth.stmms.biz.report.model.ReportSubjectClass;
-import cn.com.qmth.stmms.biz.report.model.ReportSubjectCollege;
-import cn.com.qmth.stmms.biz.report.model.ReportSubjectGroup;
-import cn.com.qmth.stmms.biz.report.model.ReportSubjectQuestion;
-import cn.com.qmth.stmms.biz.report.model.ReportSubjectTeacher;
-import cn.com.qmth.stmms.biz.report.query.ReportSubjectQuery;
 import cn.com.qmth.stmms.biz.report.service.ReportService;
 import cn.com.qmth.stmms.biz.report.service.ReportSubjectClassService;
 import cn.com.qmth.stmms.biz.report.service.ReportSubjectCollegeService;
@@ -52,12 +30,8 @@ import cn.com.qmth.stmms.biz.report.service.ReportSubjectGroupService;
 import cn.com.qmth.stmms.biz.report.service.ReportSubjectQuestionService;
 import cn.com.qmth.stmms.biz.report.service.ReportSubjectService;
 import cn.com.qmth.stmms.biz.report.service.ReportSubjectTeacherService;
-import cn.com.qmth.stmms.biz.report.utils.ReportContext;
-import cn.com.qmth.stmms.common.enums.ExamStatus;
 import cn.com.qmth.stmms.common.enums.LockType;
 import cn.com.qmth.stmms.common.enums.MarkStatus;
-import cn.com.qmth.stmms.common.enums.SubjectiveStatus;
-import cn.com.qmth.stmms.common.utils.ExportExcel;
 
 /**
  * 统计定时任务
@@ -83,10 +57,6 @@ public class ScoreReportJob {
     @Autowired
     private FileService fileService;
 
-    @Qualifier("task-executor")
-    @Autowired
-    private AsyncTaskExecutor taskExecutor;
-
     @Autowired
     private LockService lockService;
 
@@ -114,330 +84,43 @@ public class ScoreReportJob {
     @Autowired
     private ReportSubjectService reportSubjectService;
 
-    private ReportContext context;
-
-    private Map<String, List<ExamQuestion>> objectiveMap;
-
-    private Map<String, List<ExamQuestion>> subjectiveMap;
-
-    private Map<String, ExamSubject> subjectMap;
+    @Qualifier("task-executor")
+    @Autowired
+    private AsyncTaskExecutor taskExecutor;
 
     /**
      * 定时更新成绩分析报告
      */
-    @Scheduled(fixedDelay = 60 * 1000, initialDelay = 30 * 60 * 1000)
+    @Scheduled(fixedDelay = 1 * 60 * 1000, initialDelay = 30 * 60 * 1000)
     public void updateReport() {
         log.info("start auto-update report");
         try {
+            Map<Integer, Set<String>> map = new HashMap<Integer, Set<String>>();
             List<Integer> examIds = groupService.findExamIdByStatus(MarkStatus.FORMAL);
             for (Integer examId : examIds) {
-                Exam exam = examService.findById(examId);
-                if (ExamStatus.FINISH.equals(exam.getStatus())) {
-                    continue;
+                List<ExamSubject> list = subjectService.list(examId);
+                Set<String> set = new HashSet<>();
+                for (ExamSubject subject : list) {
+                    List<MarkGroup> groups = groupService.findByExamAndSubjectAndStatus(subject.getExamId(),
+                            subject.getCode(), MarkStatus.TRIAL);
+                    if (!groups.isEmpty()
+                            && !lockService.isLocked(LockType.SCORE_CALCULATE, subject.getExamId(), subject.getCode())) {
+                        set.add(subject.getCode());
+                    }
+                }
+                if (!set.isEmpty()) {
+                    map.put(examId, set);
                 }
-                updateReportByExam(examId);
             }
+            ScoreReportThread thread = new ScoreReportThread(map, lockService, studentService, questionService,
+                    groupService, reportService, examService, subjectService, fileService, false,
+                    reportSubjectQuestionService, reportSubjectClassService, reportSubjectTeacherService,
+                    reportSubjectCollegeService, reportSubjectGroupService, reportSubjectService);
+            taskExecutor.submit(thread);
         } catch (Exception e) {
             log.error("auto-update report error", e);
         } finally {
             log.info("finish auto-update report");
         }
     }
-
-    private void updateReportByExam(Integer examId) {
-        // 获取主观题总分大于0的科目
-        List<ExamSubject> subjects = subjectService.list(examId, 0);
-        Set<String> subjectSet = new HashSet<String>();
-        for (ExamSubject subject : subjects) {
-            if (!lockService.isLocked(LockType.SCORE_CALCULATE, subject.getExamId(), subject.getCode())) {
-                subjectSet.add(subject.getCode());
-            }
-        }
-
-        // 获取考试信息并判断状态
-        Exam exam = examService.findById(examId);
-        if (exam == null || exam.getStatus() != ExamStatus.START) {
-            log.info("report exception for examId=" + examId + ", exam is null or status error");
-            return;
-        }
-        log.info("start report for examId=" + examId + ", subjectCode count=" + subjectSet.size());
-
-        lockService.trylock(LockType.SCORE_CALCULATE, examId);
-        for (String subjectCode : subjectSet) {
-            // 尝试上锁,失败直接跳过
-            if (!lockService.trylock(LockType.SCORE_CALCULATE, examId, subjectCode)) {
-                log.warn("report locked for examId=" + examId + ", subjectCode=" + subjectCode);
-                continue;
-            }
-            try {
-                log.info("start report for examId=" + examId + ", subjectCode=" + subjectCode);
-                // 删除原有统计数据
-                reportService.deleteData(examId, subjectCode);
-                context = new ReportContext(exam);
-                int pageNumber = 1;
-                int pageSize = 1000;
-                List<ExamStudent> list = studentService.findByExamIdAndSubjectCode(examId, subjectCode, pageNumber,
-                        pageSize);
-                while (list != null && list.size() > 0) {
-                    for (ExamStudent student : list) {
-                        // 统计
-                        statistic(student);
-                    }
-                    pageNumber++;
-                    list = studentService.findByExamIdAndSubjectCode(examId, subjectCode, pageNumber, pageSize);
-                }
-                // 结束统计
-                context.save();
-                // 生成文件
-                reoprtExcel(examId, subjectCode);
-            } catch (Exception e) {
-                log.error("report exception for examId=" + examId + ", subjectCode=" + subjectCode, e);
-            } finally {
-                lockService.unlock(LockType.SCORE_CALCULATE, examId, subjectCode);
-                log.info("finish report for examId=" + examId + ", subjectCode=" + subjectCode);
-            }
-        }
-        lockService.unlock(LockType.SCORE_CALCULATE, examId);
-    }
-
-    private void statistic(ExamStudent student) {
-        if (SubjectiveStatus.MARKED.equals(student.getSubjectiveStatus())
-                || SubjectiveStatus.INSPECTED.equals(student.getSubjectiveStatus())) {
-            student.setSubject(findExamSubject(student.getExamId(), student.getSubjectCode()));
-            student.setObjectiveQuestionList(findQuestionList(student.getExamId(), student.getSubjectCode(),
-                    student.getPaperType(), true));
-            student.setSubjectiveQuestionList(findQuestionList(student.getExamId(), student.getSubjectCode(),
-                    student.getPaperType(), false));
-            context.process(student);
-        }
-    }
-
-    private List<ExamQuestion> findQuestionList(int examId, String subjectCode, String paperType, boolean objective) {
-        if (objective) {
-            String key = subjectCode + "_" + StringUtils.trimToEmpty(paperType);
-            List<ExamQuestion> list = objectiveMap.get(key);
-            if (list == null) {
-                list = questionService.findByExamAndSubjectAndObjectiveAndPaperType(examId, subjectCode, true,
-                        paperType);
-                objectiveMap.put(key, list);
-            }
-            return list;
-        } else {
-            List<ExamQuestion> list = subjectiveMap.get(subjectCode);
-            if (list == null) {
-                list = questionService.findByExamAndSubjectAndObjective(examId, subjectCode, false);
-                subjectiveMap.put(subjectCode, list);
-            }
-            return list;
-        }
-    }
-
-    private ExamSubject findExamSubject(int examId, String subjectCode) {
-        ExamSubject subject = subjectMap.get(subjectCode);
-        if (subject == null) {
-            subject = subjectService.find(examId, subjectCode);
-            subjectMap.put(subjectCode, subject);
-        }
-        return subject;
-    }
-
-    private void reoprtExcel(int examId, String subjectCode) throws IOException, Exception {
-        uploadRange(examId, subjectCode, findExamSubject(examId, subjectCode).getName(), "课程分段统计");
-        uploadCollege(examId, subjectCode, findExamSubject(examId, subjectCode).getName(), "学院分析");
-        uploadClass(examId, subjectCode, findExamSubject(examId, subjectCode).getName(), "班级分析");
-        uploadTeacher(examId, subjectCode, findExamSubject(examId, subjectCode).getName(), "任课老师统计");
-        uploadQuestion(examId, subjectCode, findExamSubject(examId, subjectCode).getName(), true, "客观题分析");
-        uploadQuestion(examId, subjectCode, findExamSubject(examId, subjectCode).getName(), false, "主观题分析");
-        uploadGroup(examId, subjectCode, findExamSubject(examId, subjectCode).getName(), "分组统计分析");
-    }
-
-    private void uploadGroup(int examId, String subjectCode, String subjectName, String name) throws IOException,
-            Exception {
-        ReportSubjectQuery query = new ReportSubjectQuery();
-        query.setExamId(examId);
-        query.setSubjectCode(subjectCode);
-        query.setPageNumber(1);
-        query.setPageSize(Integer.MAX_VALUE);
-        List<ReportSubjectGroup> list = reportSubjectGroupService.findByQuery(query);
-        for (ReportSubjectGroup r : list) {
-            r.setAvgScore(new BigDecimal(r.getAvgScore()).setScale(2, RoundingMode.HALF_UP).doubleValue());
-            r.setScoreRate(new BigDecimal(r.getScoreRate()).setScale(2, RoundingMode.HALF_UP).doubleValue());
-            r.setStdev(new BigDecimal(r.getStdev()).setScale(2, RoundingMode.HALF_UP).doubleValue());
-            r.setCoefficient(new BigDecimal(r.getCoefficient()).setScale(2, RoundingMode.HALF_UP).doubleValue());
-        }
-        ByteArrayOutputStream os = new ByteArrayOutputStream();
-        new ExportExcel(name, ReportSubjectGroup.class).setDataList(list).write(os);
-        os.flush();
-        byte[] value = os.toByteArray();
-        String md5 = CodecUtils.toHexString(CodecUtils.md5(value));
-        fileService.uploadReport(new ByteArrayInputStream(value), md5, examId, subjectCode + "-" + subjectName, name,
-                FormatType.XLSX);
-    }
-
-    private void uploadQuestion(int examId, String subjectCode, String subjectName, boolean objective, String name)
-            throws IOException, Exception {
-        ReportSubjectQuery query = new ReportSubjectQuery();
-        query.setExamId(examId);
-        query.setSubjectCode(subjectCode);
-        query.setObjective(objective);
-        query.setPageNumber(1);
-        query.setPageSize(Integer.MAX_VALUE);
-        List<ReportSubjectQuestion> list = reportSubjectQuestionService.findByQuery(query);
-        for (ReportSubjectQuestion r : list) {
-            r.setAvgScore(new BigDecimal(r.getAvgScore()).setScale(2, RoundingMode.HALF_UP).doubleValue());
-            r.setStdev(new BigDecimal(r.getStdev()).setScale(2, RoundingMode.HALF_UP).doubleValue());
-            r.setScoreRate(new BigDecimal(r.getScoreRate()).setScale(2, RoundingMode.HALF_UP).doubleValue());
-            r.setFullScoreRate(new BigDecimal(r.getFullScoreRate()).setScale(2, RoundingMode.HALF_UP).doubleValue());
-        }
-        ByteArrayOutputStream os = new ByteArrayOutputStream();
-        new ExportExcel(name, ReportSubjectQuestion.class).setDataList(list).write(os);
-        os.flush();
-        byte[] value = os.toByteArray();
-        String md5 = CodecUtils.toHexString(CodecUtils.md5(value));
-        fileService.uploadReport(new ByteArrayInputStream(value), md5, examId, subjectCode + "-" + subjectName, name,
-                FormatType.XLSX);
-    }
-
-    private void uploadTeacher(int examId, String subjectCode, String subjectName, String name) throws IOException,
-            Exception {
-        ReportSubjectQuery query = new ReportSubjectQuery();
-        query.setExamId(examId);
-        query.setSubjectCode(subjectCode);
-        query.setPageNumber(1);
-        query.setPageSize(Integer.MAX_VALUE);
-        List<ReportSubjectTeacher> list = reportSubjectTeacherService.findByQuery(query);
-        for (ReportSubjectTeacher r : list) {
-            r.setAvgScore(new BigDecimal(r.getAvgScore()).setScale(2, RoundingMode.HALF_UP).doubleValue());
-            r.setExcellentRate(new BigDecimal(r.getExcellentRate()).setScale(2, RoundingMode.HALF_UP).doubleValue());
-            r.setPassRate(new BigDecimal(r.getPassRate()).setScale(2, RoundingMode.HALF_UP).doubleValue());
-            r.setRelativeAvgScore(new BigDecimal(r.getRelativeAvgScore()).setScale(2, RoundingMode.HALF_UP)
-                    .doubleValue());
-        }
-        ByteArrayOutputStream os = new ByteArrayOutputStream();
-        new ExportExcel(name, ReportSubjectTeacher.class).setDataList(list).write(os);
-        os.flush();
-        byte[] value = os.toByteArray();
-        String md5 = CodecUtils.toHexString(CodecUtils.md5(value));
-        fileService.uploadReport(new ByteArrayInputStream(value), md5, examId, subjectCode + "-" + subjectName, name,
-                FormatType.XLSX);
-    }
-
-    private void uploadClass(int examId, String subjectCode, String subjectName, String name) throws IOException,
-            Exception {
-        ReportSubjectQuery query = new ReportSubjectQuery();
-        query.setExamId(examId);
-        query.setSubjectCode(subjectCode);
-        query.setPageNumber(1);
-        query.setPageSize(Integer.MAX_VALUE);
-        List<ReportSubjectClass> list = reportSubjectClassService.findByQuery(query);
-        for (ReportSubjectClass r : list) {
-            r.setAvgScore(new BigDecimal(r.getAvgScore()).setScale(2, RoundingMode.HALF_UP).doubleValue());
-            r.setExcellentRate(new BigDecimal(r.getExcellentRate()).setScale(2, RoundingMode.HALF_UP).doubleValue());
-            r.setPassRate(new BigDecimal(r.getPassRate()).setScale(2, RoundingMode.HALF_UP).doubleValue());
-        }
-        ByteArrayOutputStream os = new ByteArrayOutputStream();
-        new ExportExcel(name, ReportSubjectClass.class).setDataList(list).write(os);
-        os.flush();
-        byte[] value = os.toByteArray();
-        String md5 = CodecUtils.toHexString(CodecUtils.md5(value));
-        fileService.uploadReport(new ByteArrayInputStream(value), md5, examId, subjectCode + "-" + subjectName, name,
-                FormatType.XLSX);
-    }
-
-    private void uploadCollege(int examId, String subjectCode, String subjectName, String name) throws IOException,
-            Exception {
-        ReportSubjectQuery query = new ReportSubjectQuery();
-        query.setExamId(examId);
-        query.setSubjectCode(subjectCode);
-        query.setPageNumber(1);
-        query.setPageSize(Integer.MAX_VALUE);
-        List<ReportSubjectCollege> list = reportSubjectCollegeService.findByQuery(query);
-        for (ReportSubjectCollege r : list) {
-            r.setAvgScore(new BigDecimal(r.getAvgScore()).setScale(2, RoundingMode.HALF_UP).doubleValue());
-            r.setExcellentRate(new BigDecimal(r.getExcellentRate()).setScale(2, RoundingMode.HALF_UP).doubleValue());
-            r.setPassRate(new BigDecimal(r.getPassRate()).setScale(2, RoundingMode.HALF_UP).doubleValue());
-        }
-        ByteArrayOutputStream os = new ByteArrayOutputStream();
-        new ExportExcel(name, ReportSubjectCollege.class).setDataList(list).write(os);
-        os.flush();
-        byte[] value = os.toByteArray();
-        String md5 = CodecUtils.toHexString(CodecUtils.md5(value));
-        fileService.uploadReport(new ByteArrayInputStream(value), md5, examId, subjectCode + "-" + subjectName, name,
-                FormatType.XLSX);
-    }
-
-    private void uploadRange(int examId, String subjectCode, String subjectName, String name) throws IOException,
-            Exception {
-        List<ReportSubjectRangeDTO> list = new ArrayList<ReportSubjectRangeDTO>();
-        ReportSubject subject = reportSubjectService.findOne(examId, subjectCode);
-        if (subject != null) {
-            JSONArray array = getScoreRange(subject.getScoreRange(), subject.getTotalScore(),
-                    subject.getRealityCount(), 10);
-            for (int i = 0; i < array.size(); i++) {
-                JSONObject jsonObject = array.getJSONObject(i);
-                String score = jsonObject.getInt("score") + "-";
-                Integer rangeCount = jsonObject.getInt("rangeCount");
-                Double rangeRate = jsonObject.getDouble("rangeRate");
-                list.add(new ReportSubjectRangeDTO(score, rangeCount, rangeRate));
-            }
-        }
-        ByteArrayOutputStream os = new ByteArrayOutputStream();
-        new ExportExcel(name, ReportSubjectRangeDTO.class).setDataList(list).write(os);
-        os.flush();
-        byte[] value = os.toByteArray();
-        String md5 = CodecUtils.toHexString(CodecUtils.md5(value));
-        fileService.uploadReport(new ByteArrayInputStream(value), md5, examId, subjectCode + "-" + subjectName, name,
-                FormatType.XLSX);
-    }
-
-    private JSONArray getScoreRange(String scoreRange, double totalScore, Integer totalCount, int range) {
-        JSONArray result = new JSONArray();
-        JSONObject jsonObject = JSONObject.fromObject(scoreRange);
-        int rangeCount = 0;
-        int sumCount = 0;
-        int total = (int) Math.ceil(totalScore / range);
-        for (int i = total; i >= 0; i--) {
-            int start = i * range;
-            int end = (i - 1) * range + 1;
-            if (start > totalScore) {
-                start = (int) Math.ceil(totalScore);
-            }
-            if (end < 0) {
-                end = 0;
-            }
-            rangeCount = getSumCount(jsonObject, start, end);
-            sumCount = sumCount + rangeCount;
-            result.add(getRangeJson(totalCount, rangeCount, sumCount, i * range));
-        }
-        return result;
-    }
-
-    private int getSumCount(JSONObject jsonObject, int start, int end) {
-        int sumCount = 0;
-        int currentCount = 0;
-        if (start < end) {
-            for (int i = start; i <= end; i++) {
-                currentCount = jsonObject.getInt(String.valueOf(i));
-                sumCount = sumCount + currentCount;
-            }
-        } else if (start >= end) {
-            for (int i = end; i <= start; i++) {
-                currentCount = jsonObject.getInt(String.valueOf(i));
-                sumCount = sumCount + currentCount;
-            }
-        } else {
-            sumCount = jsonObject.getInt(String.valueOf(start));
-        }
-        return sumCount;
-    }
-
-    private JSONObject getRangeJson(Integer totalCount, int rangeCount, int sumCount, int score) {
-        JSONObject value = new JSONObject();
-        value.accumulate("score", score);
-        value.accumulate("rangeCount", rangeCount);
-        value.accumulate("rangeRate", rangeCount * 100.0 / totalCount);
-        value.accumulate("sumCount", sumCount);
-        value.accumulate("sumRate", sumCount * 100.0 / totalCount);
-        return value;
-    }
 }

+ 45 - 20
stmms-web/src/main/java/cn/com/qmth/stmms/admin/thread/ScoreReportThread.java

@@ -25,10 +25,12 @@ import cn.com.qmth.stmms.biz.exam.model.Exam;
 import cn.com.qmth.stmms.biz.exam.model.ExamQuestion;
 import cn.com.qmth.stmms.biz.exam.model.ExamStudent;
 import cn.com.qmth.stmms.biz.exam.model.ExamSubject;
+import cn.com.qmth.stmms.biz.exam.model.MarkGroup;
 import cn.com.qmth.stmms.biz.exam.service.ExamQuestionService;
 import cn.com.qmth.stmms.biz.exam.service.ExamService;
 import cn.com.qmth.stmms.biz.exam.service.ExamStudentService;
 import cn.com.qmth.stmms.biz.exam.service.ExamSubjectService;
+import cn.com.qmth.stmms.biz.exam.service.MarkGroupService;
 import cn.com.qmth.stmms.biz.file.enums.FormatType;
 import cn.com.qmth.stmms.biz.file.service.FileService;
 import cn.com.qmth.stmms.biz.lock.LockService;
@@ -49,6 +51,7 @@ import cn.com.qmth.stmms.biz.report.service.ReportSubjectTeacherService;
 import cn.com.qmth.stmms.biz.report.utils.ReportContext;
 import cn.com.qmth.stmms.common.enums.ExamStatus;
 import cn.com.qmth.stmms.common.enums.LockType;
+import cn.com.qmth.stmms.common.enums.MarkStatus;
 import cn.com.qmth.stmms.common.enums.SubjectiveStatus;
 import cn.com.qmth.stmms.common.utils.ExportExcel;
 
@@ -62,9 +65,9 @@ public class ScoreReportThread implements Runnable {
 
     private ExamQuestionService questionService;
 
-    private int examId;
+    private MarkGroupService groupService;
 
-    private Set<String> subjectCodeSet;
+    private Map<Integer, Set<String>> exams;
 
     private LockService lockService;
 
@@ -104,22 +107,22 @@ public class ScoreReportThread implements Runnable {
 
     private boolean examLock;
 
-    public ScoreReportThread(int examId, Set<String> subjectCodeSet, LockService lockService,
-            ExamStudentService studentService, ExamQuestionService questionService, ReportService reportService,
-            ExamService examService, ExamSubjectService subjectService, FileService fileService, boolean examLock,
-            ReportSubjectQuestionService reportSubjectQuestionService,
+    public ScoreReportThread(Map<Integer, Set<String>> exams, LockService lockService,
+            ExamStudentService studentService, ExamQuestionService questionService, MarkGroupService groupService,
+            ReportService reportService, ExamService examService, ExamSubjectService subjectService,
+            FileService fileService, boolean examLock, ReportSubjectQuestionService reportSubjectQuestionService,
             ReportSubjectClassService reportSubjectClassService,
             ReportSubjectTeacherService reportSubjectTeacherService,
             ReportSubjectCollegeService reportSubjectCollegeService,
             ReportSubjectGroupService reportSubjectGroupService, ReportSubjectService reportSubjectService) {
-        this.examId = examId;
-        this.subjectCodeSet = subjectCodeSet != null ? subjectCodeSet : new HashSet<>();
+        this.exams = exams != null ? exams : new HashMap<Integer, Set<String>>();
         this.lockService = lockService;
         this.studentService = studentService;
         this.questionService = questionService;
         this.reportService = reportService;
         this.examService = examService;
         this.subjectService = subjectService;
+        this.groupService = groupService;
         this.fileService = fileService;
         this.examLock = examLock;
         this.reportSubjectClassService = reportSubjectClassService;
@@ -136,11 +139,31 @@ public class ScoreReportThread implements Runnable {
     @Override
     public void run() {
         // 获取考试信息并判断状态
+        if (exams != null && !exams.isEmpty()) {
+            for (Integer examId : exams.keySet()) {
+                reportExam(examId, exams.get(examId));
+            }
+        }
+    }
+
+    private void reportExam(int examId, Set<String> subjectCodeSet) {
         Exam exam = examService.findById(examId);
         if (exam == null || exam.getStatus() != ExamStatus.START) {
             log.info("report exception for examId=" + examId + ", exam is null or status error");
             return;
         }
+        if (subjectCodeSet == null) {
+            subjectCodeSet = new HashSet<String>();
+            List<ExamSubject> list = subjectService.list(exam.getId());
+            for (ExamSubject subject : list) {
+                List<MarkGroup> groups = groupService.findByExamAndSubjectAndStatus(examId, subject.getCode(),
+                        MarkStatus.FORMAL, MarkStatus.TRIAL);
+                if (groups != null && !groups.isEmpty()
+                        && !lockService.isLocked(LockType.SCORE_CALCULATE, subject.getExamId(), subject.getCode())) {
+                    subjectCodeSet.add(subject.getCode());
+                }
+            }
+        }
         log.info("start report for examId=" + examId + ", subjectCode count=" + subjectCodeSet.size());
 
         if (examLock) {
@@ -188,14 +211,16 @@ public class ScoreReportThread implements Runnable {
     private void statistic(ExamStudent student) {
         if (SubjectiveStatus.MARKED.equals(student.getSubjectiveStatus())
                 || SubjectiveStatus.INSPECTED.equals(student.getSubjectiveStatus())) {
-            student.setSubject(findExamSubject(student.getSubjectCode()));
-            student.setObjectiveQuestionList(findQuestionList(student.getSubjectCode(), student.getPaperType(), true));
-            student.setSubjectiveQuestionList(findQuestionList(student.getSubjectCode(), student.getPaperType(), false));
+            student.setSubject(findExamSubject(student.getExamId(), student.getSubjectCode()));
+            student.setObjectiveQuestionList(findQuestionList(student.getExamId(), student.getSubjectCode(),
+                    student.getPaperType(), true));
+            student.setSubjectiveQuestionList(findQuestionList(student.getExamId(), student.getSubjectCode(),
+                    student.getPaperType(), false));
             context.process(student);
         }
     }
 
-    private List<ExamQuestion> findQuestionList(String subjectCode, String paperType, boolean objective) {
+    private List<ExamQuestion> findQuestionList(int examId, String subjectCode, String paperType, boolean objective) {
         if (objective) {
             String key = subjectCode + "_" + StringUtils.trimToEmpty(paperType);
             List<ExamQuestion> list = objectiveMap.get(key);
@@ -215,7 +240,7 @@ public class ScoreReportThread implements Runnable {
         }
     }
 
-    private ExamSubject findExamSubject(String subjectCode) {
+    private ExamSubject findExamSubject(int examId, String subjectCode) {
         ExamSubject subject = subjectMap.get(subjectCode);
         if (subject == null) {
             subject = subjectService.find(examId, subjectCode);
@@ -225,13 +250,13 @@ public class ScoreReportThread implements Runnable {
     }
 
     private void reoprtExcel(int examId, String subjectCode) throws IOException, Exception {
-        uploadRange(examId, subjectCode, findExamSubject(subjectCode).getName(), "课程分段统计");
-        uploadCollege(examId, subjectCode, findExamSubject(subjectCode).getName(), "学院分析");
-        uploadClass(examId, subjectCode, findExamSubject(subjectCode).getName(), "班级分析");
-        uploadTeacher(examId, subjectCode, findExamSubject(subjectCode).getName(), "任课老师统计");
-        uploadQuestion(examId, subjectCode, findExamSubject(subjectCode).getName(), true, "客观题分析");
-        uploadQuestion(examId, subjectCode, findExamSubject(subjectCode).getName(), false, "主观题分析");
-        uploadGroup(examId, subjectCode, findExamSubject(subjectCode).getName(), "分组统计分析");
+        uploadRange(examId, subjectCode, findExamSubject(examId, subjectCode).getName(), "课程分段统计");
+        uploadCollege(examId, subjectCode, findExamSubject(examId, subjectCode).getName(), "学院分析");
+        uploadClass(examId, subjectCode, findExamSubject(examId, subjectCode).getName(), "班级分析");
+        uploadTeacher(examId, subjectCode, findExamSubject(examId, subjectCode).getName(), "任课老师统计");
+        uploadQuestion(examId, subjectCode, findExamSubject(examId, subjectCode).getName(), true, "客观题分析");
+        uploadQuestion(examId, subjectCode, findExamSubject(examId, subjectCode).getName(), false, "主观题分析");
+        uploadGroup(examId, subjectCode, findExamSubject(examId, subjectCode).getName(), "分组统计分析");
     }
 
     private void uploadGroup(int examId, String subjectCode, String subjectName, String name) throws IOException,