Selaa lähdekoodia

完成分析导出,试题编辑

ting.yin 3 vuotta sitten
vanhempi
commit
318d92710f
23 muutettua tiedostoa jossa 920 lisäystä ja 119 poistoa
  1. 2 1
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/file/enums/FileType.java
  2. 1 1
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/file/enums/FormatType.java
  3. 9 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/file/service/FileService.java
  4. 21 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/file/service/impl/FileServiceImpl.java
  5. 16 15
      stmms-web/src/main/java/cn/com/qmth/stmms/admin/exam/AnswerCheckController.java
  6. 1 1
      stmms-web/src/main/java/cn/com/qmth/stmms/admin/exam/CheckStudentController.java
  7. 138 11
      stmms-web/src/main/java/cn/com/qmth/stmms/admin/exam/PaperController.java
  8. 104 53
      stmms-web/src/main/java/cn/com/qmth/stmms/admin/report/ReportSubjectRangeController.java
  9. 281 1
      stmms-web/src/main/java/cn/com/qmth/stmms/admin/thread/ScoreReportThread.java
  10. 12 0
      stmms-web/src/main/java/cn/com/qmth/stmms/common/controller/BaseController.java
  11. 26 0
      stmms-web/src/main/java/cn/com/qmth/stmms/mark/MarkController.java
  12. 2 5
      stmms-web/src/main/webapp/WEB-INF/views/modules/exam/checkAnswer.jsp
  13. 17 3
      stmms-web/src/main/webapp/WEB-INF/views/modules/exam/paperDetail.jsp
  14. 131 0
      stmms-web/src/main/webapp/WEB-INF/views/modules/exam/questionAdd.jsp
  15. 96 9
      stmms-web/src/main/webapp/WEB-INF/views/modules/exam/questionEdit.jsp
  16. 34 5
      stmms-web/src/main/webapp/WEB-INF/views/modules/mark/subjectSelect.jsp
  17. 2 2
      stmms-web/src/main/webapp/WEB-INF/views/modules/report/reportSubjectClass.jsp
  18. 2 2
      stmms-web/src/main/webapp/WEB-INF/views/modules/report/reportSubjectCollege.jsp
  19. 2 2
      stmms-web/src/main/webapp/WEB-INF/views/modules/report/reportSubjectGroup.jsp
  20. 2 2
      stmms-web/src/main/webapp/WEB-INF/views/modules/report/reportSubjectQuestion.jsp
  21. 17 2
      stmms-web/src/main/webapp/WEB-INF/views/modules/report/reportSubjectRange.jsp
  22. 2 2
      stmms-web/src/main/webapp/WEB-INF/views/modules/report/reportSubjectTeacher.jsp
  23. 2 2
      stmms-web/src/main/webapp/WEB-INF/views/modules/report/reportSubjectTeacherClass.jsp

+ 2 - 1
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/file/enums/FileType.java

@@ -7,7 +7,8 @@ public enum FileType {
 
     SHEET("原图", "sheet/%d/%s/%s-%d.%s"), SLICE("裁切图", "slice/%d/%s/%s-%d.%s"), JSON("作答内容", "json/%d/%s/%s.%s"), PACKAGE(
             "签到表", "package/%d/%s/%d.%s"), PAPER("试卷", "paper/%d/%s.%s"), ANSWER("标答", "answer/%d/%s.%s"), CARD("题卡",
-            "card/%d/%s.%s"), EXCHANGE("文件", "exchange/%s"), ANSWER_CARD("题卡", "card/answer/%d/%s.%s");
+            "card/%d/%s.%s"), EXCHANGE("文件", "exchange/%s"), ANSWER_CARD("题卡", "card/answer/%d/%s.%s"), REPORT("报表",
+            "report/%d/%s/%s.%s");
 
     private String name;
 

+ 1 - 1
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/file/enums/FormatType.java

@@ -5,7 +5,7 @@ package cn.com.qmth.stmms.biz.file.enums;
  */
 public enum FormatType {
 
-    JPG, JSON, PDF, ZIP;
+    JPG, JSON, PDF, ZIP, XLSX;
 
     public String getExtName() {
         return toString().toLowerCase();

+ 9 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/file/service/FileService.java

@@ -35,6 +35,9 @@ public interface FileService {
 
     void uploadExchange(InputStream ins, String md5, String name) throws Exception;
 
+    void uploadReport(InputStream ins, String md5, int examId, String subjectCode, String name, FormatType type)
+            throws Exception;
+
     String getSheetUri(int examId, String examNumber, int index);
 
     List<String> getSheetUris(int examId, String examNumber, int start, int end);
@@ -71,4 +74,10 @@ public interface FileService {
 
     String getAnswerCardUri(int examId, int number);
 
+    String getReportUri(int examId, String subjectName, String reportTitle, FormatType type);
+
+    byte[] downloadReport(int examId, String subjectName, String reportTitle, FormatType type) throws Exception;
+
+    boolean reportExist(int examId, String subjectName, String reportTitle, FormatType type);
+
 }

+ 21 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/file/service/impl/FileServiceImpl.java

@@ -307,6 +307,27 @@ public class FileServiceImpl implements FileService, InitializingBean, Disposabl
         return FileType.ANSWER_CARD.getPath(examId, number, FormatType.JSON.getExtName());
     }
 
+    @Override
+    public void uploadReport(InputStream ins, String md5, int examId, String subjectCode, String name, FormatType type)
+            throws Exception {
+        store.write(getReportUri(examId, subjectCode, name, type), ins, md5);
+    }
+
+    @Override
+    public String getReportUri(int examId, String subjectName, String reportTitle, FormatType type) {
+        return FileType.REPORT.getPath(examId, subjectName, reportTitle, type.getExtName());
+    }
+
+    @Override
+    public byte[] downloadReport(int examId, String subjectName, String reportTitle, FormatType type) throws Exception {
+        return store.read(getReportUri(examId, subjectName, reportTitle, type));
+    }
+
+    @Override
+    public boolean reportExist(int examId, String subjectName, String reportTitle, FormatType type) {
+        return store.exist(getReportUri(examId, subjectName, reportTitle, type));
+    }
+
     public static void main(String[] args) throws Exception {
         FileServiceImpl service = new FileServiceImpl();
         // service.fileServerString = "123";

+ 16 - 15
stmms-web/src/main/java/cn/com/qmth/stmms/admin/exam/AnswerCheckController.java

@@ -75,9 +75,9 @@ public class AnswerCheckController extends BaseExamController {
         }
     }
 
-    @RequestMapping("/start")
+    @RequestMapping("/getSetting")
     @ResponseBody
-    public JSONObject start(HttpServletRequest request, ExamStudentSearchQuery query) {
+    public JSONObject getSetting(HttpServletRequest request, ExamStudentSearchQuery query) {
         int examId = getSessionExamId(request);
         JSONObject setting = new JSONObject();
         setting.accumulate("fileServer", fileService.getFileServer());
@@ -94,7 +94,7 @@ public class AnswerCheckController extends BaseExamController {
             query.setPageNumber(query.getPageNumber() + 1);
             query = studentService.findByQuery(query);
         }
-        setting.accumulate("ids", StringUtils.join(ids, ","));
+        setting.accumulate("studentIds", ids);
         return setting;
     }
 
@@ -146,17 +146,18 @@ public class AnswerCheckController extends BaseExamController {
         List<String> answers = student.getAnswerList();
         if (questions.isEmpty()) {
             // 未设置客观题或无客观题
-            int count = answers.size();
-            for (int i = 0; i < count; i++) {
-                JSONObject obj = new JSONObject();
-                obj.accumulate("mainNumber", 1);
-                obj.accumulate("subNumber", i + 1);
-                obj.accumulate("answer", answers.get(i));
-                obj.accumulate("exist", true);
-                obj.accumulate("multi", questions.get(i).getAnswer().length() > 1);
-                array.add(obj);
-            }
-            titles.put(1, "客观题");
+            // int count = answers.size();
+            // for (int i = 0; i < count; i++) {
+            // JSONObject obj = new JSONObject();
+            // obj.accumulate("mainNumber", 1);
+            // obj.accumulate("subNumber", i + 1);
+            // obj.accumulate("answer", answers.get(i));
+            // obj.accumulate("exist", true);
+            // obj.accumulate("multi", questions.get(i).getAnswer().length() >
+            // 1);
+            // array.add(obj);
+            // }
+            // titles.put(1, "客观题");
         } else {
             // 已设置客观题
             int questionCount = questions.size();
@@ -169,7 +170,7 @@ public class AnswerCheckController extends BaseExamController {
                 obj.accumulate("mainNumber", q != null ? q.getMainNumber() : 0);
                 obj.accumulate("subNumber", q != null ? q.getSubNumber() : 0);
                 obj.accumulate("answer", answer);
-                obj.accumulate("exist", q != null && q.getTotalScore() > 0);
+                // obj.accumulate("exist", q != null && q.getTotalScore() > 0);
                 // obj.accumulate("multi",
                 // q != null && (q.getMainTitle().contains("多选") ||
                 // q.getMainTitle().contains("多项选择")));

+ 1 - 1
stmms-web/src/main/java/cn/com/qmth/stmms/admin/exam/CheckStudentController.java

@@ -71,7 +71,7 @@ public class CheckStudentController extends BaseExamController {
         for (CheckStudent student : list) {
             ids.add(student.getStudentId());
         }
-        setting.accumulate("ids", ids);
+        setting.accumulate("studentIds", ids);
         return setting;
     }
 

+ 138 - 11
stmms-web/src/main/java/cn/com/qmth/stmms/admin/exam/PaperController.java

@@ -53,6 +53,12 @@ import cn.com.qmth.stmms.biz.file.service.FileService;
 import cn.com.qmth.stmms.biz.lock.LockService;
 import cn.com.qmth.stmms.biz.mark.service.MarkService;
 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;
+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.common.annotation.Logging;
 import cn.com.qmth.stmms.common.annotation.RoleRequire;
 import cn.com.qmth.stmms.common.domain.WebUser;
@@ -60,6 +66,7 @@ import cn.com.qmth.stmms.common.enums.LockType;
 import cn.com.qmth.stmms.common.enums.LogType;
 import cn.com.qmth.stmms.common.enums.ObjectivePolicy;
 import cn.com.qmth.stmms.common.enums.ObjectiveStatus;
+import cn.com.qmth.stmms.common.enums.QuestionType;
 import cn.com.qmth.stmms.common.enums.Role;
 import cn.com.qmth.stmms.common.enums.SubjectiveStatus;
 import cn.com.qmth.stmms.common.utils.ExportExcel;
@@ -70,6 +77,8 @@ import cn.com.qmth.stmms.common.utils.RequestUtils;
 @RequestMapping("/admin/exam/paper")
 public class PaperController extends BaseExamController {
 
+    private static final String NULL_PAPER_TYPE_PLACEHOLDER = "#";
+
     @Autowired
     private ExamSubjectService subjectService;
 
@@ -101,6 +110,24 @@ public class PaperController extends BaseExamController {
     @Autowired
     private MarkService markService;
 
+    @Autowired
+    private ReportSubjectQuestionService reportSubjectQuestionService;
+
+    @Autowired
+    private ReportSubjectClassService reportSubjectClassService;
+
+    @Autowired
+    private ReportSubjectTeacherService reportSubjectTeacherService;
+
+    @Autowired
+    private ReportSubjectCollegeService reportSubjectCollegeService;
+
+    @Autowired
+    private ReportSubjectGroupService reportSubjectGroupService;
+
+    @Autowired
+    private ReportSubjectService reportSubjectService;
+
     @Logging(menu = "试卷管理查询", type = LogType.QUERY)
     @RequestMapping
     public String list(Model model, HttpServletRequest request, ExamSubjectSearchQuery query,
@@ -138,24 +165,32 @@ public class PaperController extends BaseExamController {
     @RequestMapping("/detail")
     public String detail(Model model, HttpServletRequest request, @RequestParam String subjectCode,
             @RequestParam(required = false) Boolean objective, @RequestParam(required = false) Boolean upload,
-            ExamSubjectSearchQuery query) {
+            @RequestParam(required = false) Integer mainNumber, ExamSubjectSearchQuery query) {
         int examId = getSessionExamId(request);
         ExamSubject subject = subjectService.find(examId, subjectCode);
         if (subject != null) {
             List<ExamQuestion> list = new LinkedList<ExamQuestion>();
             if (objective == null || objective) {
-                List<ExamQuestion> objectiveList = questionService.findByExamAndSubjectAndObjective(examId,
-                        subjectCode, true);
+                List<ExamQuestion> objectiveList = mainNumber == null ? questionService
+                        .findByExamAndSubjectAndObjective(examId, subjectCode, true) : questionService
+                        .findByExamAndSubjectAndObjectiveAndMainNumber(examId, subjectCode, true, mainNumber);
                 list.addAll(objectiveList);
             }
             if (objective == null || !objective) {
-                List<ExamQuestion> subjectiveList = questionService.findByExamAndSubjectAndObjective(examId,
-                        subjectCode, false);
+                List<ExamQuestion> subjectiveList = mainNumber == null ? questionService
+                        .findByExamAndSubjectAndObjective(examId, subjectCode, false) : questionService
+                        .findByExamAndSubjectAndObjectiveAndMainNumber(examId, subjectCode, false, mainNumber);
                 list.addAll(subjectiveList);
             }
+
+            List<ExamQuestion> mainList = new LinkedList<ExamQuestion>();
+            mainList.addAll(questionService.findMainByExamAndSubjectAndObjective(examId, subjectCode, true));
+            mainList.addAll(questionService.findMainByExamAndSubjectAndObjective(examId, subjectCode, false));
             model.addAttribute("questionList", list);
+            model.addAttribute("mainList", mainList);
             model.addAttribute("subject", subject);
             model.addAttribute("objective", objective);
+            model.addAttribute("mainNumber", mainNumber);
             model.addAttribute("upload", upload);
             model.addAttribute("query", query);
             return "modules/exam/paperDetail";
@@ -434,17 +469,17 @@ public class PaperController extends BaseExamController {
         ExamQuestion examQuestion = questionService.findById(questionId);
         model.addAttribute("examQuestion", examQuestion);
         model.addAttribute("objectivePolicyList", ObjectivePolicy.values());
+        model.addAttribute("questionTypeList", QuestionType.values());
         model.addAttribute("query", query);
         model.addAttribute("upload", upload);
         return "modules/exam/questionEdit";
     }
 
-    @Logging(menu = "编辑题目判分策略", type = LogType.UPDATE)
+    @Logging(menu = "编辑题目", type = LogType.UPDATE)
     @RequestMapping(value = "/question-edit", method = RequestMethod.POST)
     @RoleRequire(Role.SCHOOL_ADMIN)
-    public String update(@RequestParam Integer id, @RequestParam ObjectivePolicy objectivePolicy,
-            ExamSubjectSearchQuery query, @RequestParam(required = false) Boolean upload) {
-        ExamQuestion question = questionService.updateObjectivePolicy(id, objectivePolicy);
+    public String update(@RequestParam Integer id, @RequestParam ExamQuestion question, ExamSubjectSearchQuery query,
+            @RequestParam(required = false) Boolean upload) {
         String u = upload == null ? "" : upload.toString();
         String t = query.getTotalScoreNotEqual() == null ? "" : query.getTotalScoreNotEqual().toString();
         return "redirect:/admin/exam/paper/detail?subjectCode=" + question.getSubjectCode() + "&pageNumber="
@@ -537,7 +572,10 @@ public class PaperController extends BaseExamController {
             }
             if (!subjectSet.isEmpty()) {
                 ScoreReportThread thread = new ScoreReportThread(exam.getId(), subjectSet, lockService, studentService,
-                        questionService, reportService, examService, subjectService, examLock);
+                        questionService, reportService, examService, subjectService, fileService, examLock,
+                        reportSubjectQuestionService, reportSubjectClassService, reportSubjectTeacherService,
+                        reportSubjectCollegeService, reportSubjectGroupService, reportSubjectService);
+
                 taskExecutor.submit(thread);
             }
         }
@@ -559,7 +597,7 @@ public class PaperController extends BaseExamController {
         return array;
     }
 
-    @Logging(menu = "删除题目", type = LogType.DELETE)
+    @Logging(menu = "批量删除题目", type = LogType.DELETE)
     @RequestMapping("/question/delete")
     @RoleRequire({ Role.SCHOOL_ADMIN, Role.SUBJECT_HEADER })
     public String delete(HttpServletRequest request, Model model, RedirectAttributes redirectAttributes,
@@ -576,4 +614,93 @@ public class PaperController extends BaseExamController {
                 + "&code=" + query.getCode() + "&category=" + query.getCategory() + "&level=" + query.getLevel()
                 + "&upload=" + u + "&totalScoreNotEqual=" + t;
     }
+
+    @RequestMapping(value = "/question/add", method = RequestMethod.GET)
+    @RoleRequire(Role.SCHOOL_ADMIN)
+    public String add(Model model, @RequestParam String subjectCode, ExamSubjectSearchQuery query,
+            @RequestParam(required = false) Boolean upload) {
+        model.addAttribute("examQuestion", new ExamQuestion());
+        model.addAttribute("objectivePolicyList", ObjectivePolicy.values());
+        model.addAttribute("questionTypeList", QuestionType.values());
+        model.addAttribute("query", query);
+        model.addAttribute("upload", upload);
+        model.addAttribute("subjectCode", subjectCode);
+        return "modules/exam/questionAdd";
+    }
+
+    @Logging(menu = "新增题目", type = LogType.ADD)
+    @RequestMapping(value = "/question/save", method = RequestMethod.POST)
+    @RoleRequire(Role.SCHOOL_ADMIN)
+    public String save(HttpServletRequest request, Model model, RedirectAttributes redirectAttributes,
+            ExamQuestion question, ExamSubjectSearchQuery query, @RequestParam(required = false) Boolean upload) {
+        int examId = getSessionExamId(request);
+        ExamQuestion old = questionService.findByExamAndSubjectAndObjectiveAndMainNumberAndSubNumber(examId,
+                question.getSubjectCode(), question.isObjective(), question.getMainNumber(), question.getSubNumber());
+        if (old != null) {
+            addMessage(redirectAttributes, "新增失败,题号已存在");
+            String u = upload == null ? "" : upload.toString();
+            String t = query.getTotalScoreNotEqual() == null ? "" : query.getTotalScoreNotEqual().toString();
+            return "redirect:/admin/exam/paper/detail?subjectCode=" + question.getSubjectCode() + "&pageNumber="
+                    + query.getPageNumber() + "&code=" + query.getCode() + "&category=" + query.getCategory()
+                    + "&level=" + query.getLevel() + "&upload=" + u + "&totalScoreNotEqual=" + t;
+        }
+        question.setExamId(examId);
+        if (question.getPaperType() == null) {
+            question.setPaperType(NULL_PAPER_TYPE_PLACEHOLDER);
+        }
+        if (question.isObjective()) {
+            question.setGroupNumber(0);
+        }
+        Map<Integer, String> titleMap = new HashMap<>();
+        List<ExamQuestion> current = questionService.findByExamAndSubjectAndObjective(examId,
+                question.getSubjectCode(), question.isObjective());
+        for (ExamQuestion q : current) {
+            titleMap.put(q.getMainNumber(), q.getMainTitle());
+        }
+        List<String> error = new LinkedList<String>();
+        if (validate(question, error, titleMap)) {
+            questionService.save(question);
+            subjectService.updateScore(examId, question.getSubjectCode(), question.isObjective(),
+                    question.getTotalScore());
+        }
+        if (error.size() > 0) {
+            addMessage(redirectAttributes, StringUtils.join(error, "<br\\>"));
+        }
+        String u = upload == null ? "" : upload.toString();
+        String t = query.getTotalScoreNotEqual() == null ? "" : query.getTotalScoreNotEqual().toString();
+        return "redirect:/admin/exam/paper/detail?subjectCode=" + question.getSubjectCode() + "&pageNumber="
+                + query.getPageNumber() + "&code=" + query.getCode() + "&category=" + query.getCategory() + "&level="
+                + query.getLevel() + "&upload=" + u + "&totalScoreNotEqual=" + t;
+    }
+
+    private boolean validate(ExamQuestion question, List<String> error, Map<Integer, String> titleMap) {
+        int score = (int) (question.getTotalScore() * 100);
+        if ((question.getTotalScore() * 100) - score > 0) {
+            error.add("有满分为小数超2位的记录");
+            return false;
+        }
+        if (question.isObjective() && StringUtils.isBlank(question.getAnswer())) {
+            error.add("有答案为空的记录");
+            return false;
+        }
+        if (question.isObjective() && question.getType() == null) {
+            error.add("有题型为空的记录");
+            return false;
+        }
+        if (QuestionType.TRUR_OR_FALSE.equals(question.getType())
+                && (!question.getAnswer().contains("A") && !question.getAnswer().contains("B"))) {
+            error.add("有判断题标答不为A或B的记录");
+            return false;
+        }
+        if (QuestionType.SINGLE.equals(question.getType()) && question.getAnswer().length() > 1) {
+            error.add("有单选题标答大于一个的记录");
+            return false;
+        }
+        String title = titleMap.get(question.getMainNumber());
+        if (title != null && !title.equals(question.getMainTitle())) {
+            error.add("有名称不一致的记录");
+            return false;
+        }
+        return true;
+    }
 }

+ 104 - 53
stmms-web/src/main/java/cn/com/qmth/stmms/admin/report/ReportSubjectRangeController.java

@@ -1,6 +1,7 @@
 package cn.com.qmth.stmms.admin.report;
 
-import java.util.ArrayList;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
@@ -23,27 +24,37 @@ import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.servlet.mvc.support.RedirectAttributes;
 
-import cn.com.qmth.stmms.admin.dto.ReportSubjectRangeDTO;
 import cn.com.qmth.stmms.admin.exam.BaseExamController;
 import cn.com.qmth.stmms.admin.thread.ScoreReportThread;
+import cn.com.qmth.stmms.biz.exam.model.Exam;
+import cn.com.qmth.stmms.biz.exam.model.ExamSubject;
 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.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.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;
+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.common.annotation.Logging;
 import cn.com.qmth.stmms.common.annotation.RoleRequire;
 import cn.com.qmth.stmms.common.domain.WebUser;
 import cn.com.qmth.stmms.common.enums.LockType;
 import cn.com.qmth.stmms.common.enums.LogType;
 import cn.com.qmth.stmms.common.enums.Role;
-import cn.com.qmth.stmms.common.utils.ExportExcel;
+import cn.com.qmth.stmms.common.utils.Encodes;
 import cn.com.qmth.stmms.common.utils.RequestUtils;
 
+import com.qmth.boot.tools.io.ZipWriter;
+
 /**
  * 课程分段统计
  *
@@ -81,6 +92,24 @@ public class ReportSubjectRangeController extends BaseExamController {
     @Autowired
     private ReportService reportService;
 
+    @Autowired
+    private FileService fileService;
+
+    @Autowired
+    private ReportSubjectQuestionService reportSubjectQuestionService;
+
+    @Autowired
+    private ReportSubjectClassService reportSubjectClassService;
+
+    @Autowired
+    private ReportSubjectTeacherService reportSubjectTeacherService;
+
+    @Autowired
+    private ReportSubjectCollegeService reportSubjectCollegeService;
+
+    @Autowired
+    private ReportSubjectGroupService reportSubjectGroupService;
+
     @Logging(menu = "课程分段统计", type = LogType.QUERY)
     @RequestMapping
     public String list(Model model, HttpServletRequest request, ReportSubjectQuery query) {
@@ -102,6 +131,78 @@ public class ReportSubjectRangeController extends BaseExamController {
         return "modules/report/reportSubjectRange";
     }
 
+    @Logging(menu = "课程统计导出", type = LogType.EXPORT)
+    @RequestMapping("/export")
+    public String export(ReportSubjectQuery query, HttpServletRequest request, HttpServletResponse response,
+            RedirectAttributes redirectAttributes, @RequestParam(required = false) Boolean all) {
+        int examId = getSessionExamId(request);
+        response.reset();
+        response.setContentType("application/octet-stream; charset=utf-8");
+        try {
+            ZipWriter writer = ZipWriter.create(response.getOutputStream());
+            if (all) {
+                Exam exam = examService.findById(examId);
+                response.setHeader("Content-Disposition",
+                        "attachment; filename=" + Encodes.urlEncode(exam.getName() + ".zip"));
+                List<ExamSubject> list = subjectService.list(examId);
+                for (ExamSubject subject : list) {
+                    String subjectName = subject.getCode() + "-" + subject.getName();
+                    addFileToZip(examId, writer, subjectName);
+                }
+            } else {
+                ExamSubject subject = subjectService.find(examId, query.getSubjectCode());
+                String subjectName = subject.getCode() + "-" + subject.getName();
+                response.setHeader("Content-Disposition",
+                        "attachment; filename=" + Encodes.urlEncode(subjectName + ".zip"));
+                addFileToZip(examId, writer, subjectName);
+            }
+            writer.close();
+            return null;
+        } catch (Exception e) {
+            addMessage(redirectAttributes, "导出分析失败!" + e.getMessage());
+            return "redirect:/admin/exam/reportSubjectRange";
+        }
+    }
+
+    private void addFileToZip(int examId, ZipWriter writer, String subjectName) throws Exception, IOException {
+        if (fileService.reportExist(examId, subjectName, "课程分段统计", FormatType.XLSX)) {
+            byte[] range = fileService.downloadReport(examId, subjectName, "课程分段统计", FormatType.XLSX);
+            writer.write(new ByteArrayInputStream(range), subjectName, "课程分段统计.xlsx");
+            byte[] college = fileService.downloadReport(examId, subjectName, "学院分析", FormatType.XLSX);
+            writer.write(new ByteArrayInputStream(college), subjectName, "学院分析.xlsx");
+            byte[] className = fileService.downloadReport(examId, subjectName, "班级分析", FormatType.XLSX);
+            writer.write(new ByteArrayInputStream(className), subjectName, "班级分析.xlsx");
+            byte[] teacher = fileService.downloadReport(examId, subjectName, "任课老师统计", FormatType.XLSX);
+            writer.write(new ByteArrayInputStream(teacher), subjectName, "任课老师统计.xlsx");
+            byte[] objective = fileService.downloadReport(examId, subjectName, "客观题分析", FormatType.XLSX);
+            writer.write(new ByteArrayInputStream(objective), subjectName, "客观题分析.xlsx");
+            byte[] subjective = fileService.downloadReport(examId, subjectName, "主观题分析", FormatType.XLSX);
+            writer.write(new ByteArrayInputStream(subjective), subjectName, "主观题分析.xlsx");
+            byte[] group = fileService.downloadReport(examId, subjectName, "分组统计分析", FormatType.XLSX);
+            writer.write(new ByteArrayInputStream(group), subjectName, "分组统计分析.xlsx");
+        }
+    }
+
+    @Logging(menu = "科目成绩分析计算", type = LogType.UPDATE)
+    @RequestMapping("/report")
+    @RoleRequire({ Role.SCHOOL_ADMIN, Role.SUBJECT_HEADER })
+    public String calculate(HttpServletRequest request, RedirectAttributes redirectAttributes,
+            @RequestParam String subjectCode) {
+        int examId = getSessionExamId(request);
+        Set<String> subjectSet = new HashSet<String>();
+        if (!lockService.isLocked(LockType.SCORE_CALCULATE, examId, subjectCode)) {
+            subjectSet.add(subjectCode);
+        }
+        if (!subjectSet.isEmpty()) {
+            ScoreReportThread thread = new ScoreReportThread(examId, subjectSet, lockService, studentService,
+                    questionService, reportService, examService, subjectService, fileService, false,
+                    reportSubjectQuestionService, reportSubjectClassService, reportSubjectTeacherService,
+                    reportSubjectCollegeService, reportSubjectGroupService, reportSubjectService);
+            taskExecutor.submit(thread);
+        }
+        return "redirect:/admin/exam/reportSubjectRange?subjectCode=" + subjectCode + "&range=" + 10;
+    }
+
     private JSONArray getScoreRange(String scoreRange, double totalScore, Integer totalCount, int range) {
         JSONArray result = new JSONArray();
         JSONObject jsonObject = JSONObject.fromObject(scoreRange);
@@ -152,54 +253,4 @@ public class ReportSubjectRangeController extends BaseExamController {
         value.accumulate("sumRate", sumCount * 100.0 / totalCount);
         return value;
     }
-
-    @Logging(menu = "课程分段统计导出", type = LogType.EXPORT)
-    @RequestMapping("/export")
-    public String export(ReportSubjectQuery query, HttpServletRequest request, HttpServletResponse response,
-            RedirectAttributes redirectAttributes) {
-        List<ReportSubjectRangeDTO> list = new ArrayList<ReportSubjectRangeDTO>();
-        int examId = getSessionExamId(request);
-        if (StringUtils.isNotBlank(query.getSubjectCode()) && query.getRange() != null) {
-            ReportSubject subject = reportSubjectService.findOne(examId, query.getSubjectCode());
-            if (subject != null && subject.getScoreRange() != null && subject.getTotalScore() != null
-                    && subject.getRealityCount() != null) {
-                JSONArray array = getScoreRange(subject.getScoreRange(), subject.getTotalScore(),
-                        subject.getRealityCount(), query.getRange());
-                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));
-                }
-            }
-        }
-        String fileName = "课程分段统计.xlsx";
-        try {
-            new ExportExcel("课程分段统计", ReportSubjectRangeDTO.class).setDataList(list).write(response, fileName)
-                    .dispose();
-            return null;
-        } catch (Exception e) {
-            addMessage(redirectAttributes, "导出成绩失败!" + e.getMessage());
-            return "redirect:/admin/exam/reportSubjectRange";
-        }
-    }
-
-    @Logging(menu = "科目成绩分析计算", type = LogType.UPDATE)
-    @RequestMapping("/report")
-    @RoleRequire({ Role.SCHOOL_ADMIN, Role.SUBJECT_HEADER })
-    public String calculate(HttpServletRequest request, RedirectAttributes redirectAttributes,
-            @RequestParam String subjectCode) {
-        int examId = getSessionExamId(request);
-        Set<String> subjectSet = new HashSet<String>();
-        if (!lockService.isLocked(LockType.SCORE_CALCULATE, examId, subjectCode)) {
-            subjectSet.add(subjectCode);
-        }
-        if (!subjectSet.isEmpty()) {
-            ScoreReportThread thread = new ScoreReportThread(examId, subjectSet, lockService, studentService,
-                    questionService, reportService, examService, subjectService, false);
-            taskExecutor.submit(thread);
-        }
-        return "redirect:/admin/exam/reportSubjectRange?subjectCode=" + subjectCode + "&range=" + 10;
-    }
 }

+ 281 - 1
stmms-web/src/main/java/cn/com/qmth/stmms/admin/thread/ScoreReportThread.java

@@ -1,15 +1,26 @@
 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;
 
+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;
@@ -18,12 +29,30 @@ 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.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;
+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.SubjectiveStatus;
+import cn.com.qmth.stmms.common.utils.ExportExcel;
+
+import com.qmth.boot.tools.codec.CodecUtils;
 
 public class ScoreReportThread implements Runnable {
 
@@ -51,13 +80,38 @@ public class ScoreReportThread implements Runnable {
 
     private ExamService examService;
 
+    private FileService fileService;
+
+    @Autowired
+    private ReportSubjectQuestionService reportSubjectQuestionService;
+
+    @Autowired
+    private ReportSubjectClassService reportSubjectClassService;
+
+    @Autowired
+    private ReportSubjectTeacherService reportSubjectTeacherService;
+
+    @Autowired
+    private ReportSubjectCollegeService reportSubjectCollegeService;
+
+    @Autowired
+    private ReportSubjectGroupService reportSubjectGroupService;
+
+    @Autowired
+    private ReportSubjectService reportSubjectService;
+
     private ReportContext context;
 
     private boolean examLock;
 
     public ScoreReportThread(int examId, Set<String> subjectCodeSet, LockService lockService,
             ExamStudentService studentService, ExamQuestionService questionService, ReportService reportService,
-            ExamService examService, ExamSubjectService subjectService, boolean examLock) {
+            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.lockService = lockService;
@@ -66,7 +120,14 @@ public class ScoreReportThread implements Runnable {
         this.reportService = reportService;
         this.examService = examService;
         this.subjectService = subjectService;
+        this.fileService = fileService;
         this.examLock = examLock;
+        this.reportSubjectClassService = reportSubjectClassService;
+        this.reportSubjectCollegeService = reportSubjectCollegeService;
+        this.reportSubjectGroupService = reportSubjectGroupService;
+        this.reportSubjectQuestionService = reportSubjectQuestionService;
+        this.reportSubjectService = reportSubjectService;
+        this.reportSubjectTeacherService = reportSubjectTeacherService;
         this.objectiveMap = new HashMap<>();
         this.subjectiveMap = new HashMap<>();
         this.subjectMap = new HashMap<>();
@@ -110,6 +171,8 @@ public class ScoreReportThread implements Runnable {
                 }
                 // 结束统计
                 context.save();
+                // 生成文件
+                reoprtExcel(examId, subjectCode);
             } catch (Exception e) {
                 log.error("report exception for examId=" + examId + ", subjectCode=" + subjectCode, e);
             } finally {
@@ -161,4 +224,221 @@ public class ScoreReportThread implements Runnable {
         return subject;
     }
 
+    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(), "分组统计分析");
+    }
+
+    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);
+        if (list.isEmpty()) {
+            return;
+        }
+        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());
+        }
+        if (list.isEmpty()) {
+            return;
+        }
+        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());
+        }
+        if (list.isEmpty()) {
+            return;
+        }
+        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());
+        }
+        if (list.isEmpty()) {
+            return;
+        }
+        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());
+        }
+        if (list.isEmpty()) {
+            return;
+        }
+        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());
+        }
+        if (list.isEmpty()) {
+            return;
+        }
+        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);
+        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));
+        }
+        if (list.isEmpty()) {
+            return;
+        }
+        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;
+    }
 }

+ 12 - 0
stmms-web/src/main/java/cn/com/qmth/stmms/common/controller/BaseController.java

@@ -295,6 +295,18 @@ public class BaseController {
                 }
             }
         });
+        // QuestionType 类型转换
+        binder.registerCustomEditor(QuestionType.class, new PropertyEditorSupport() {
+
+            @Override
+            public void setAsText(String text) {
+                try {
+                    setValue(QuestionType.findByValue(Integer.valueOf(text)));
+                } catch (Exception e) {
+                    setValue(null);
+                }
+            }
+        });
         binder.registerCustomEditor(Boolean.class, new CustomBooleanEditor(true));
     }
 

+ 26 - 0
stmms-web/src/main/java/cn/com/qmth/stmms/mark/MarkController.java

@@ -209,6 +209,32 @@ public class MarkController extends BaseController {
         return array;
     }
 
+    @RequestMapping(value = "/subject/group/query")
+    @ResponseBody
+    public JSONArray groupQuery(HttpServletRequest request, @RequestParam Integer examId,
+            @RequestParam String subjectCode) {
+        User user = RequestUtils.getWebUser(request).getUser();
+        List<Marker> list = markerService.findByExamAndSubjectAndUserIdAndEnable(examId, subjectCode, user.getId(),
+                true);
+        JSONArray array = new JSONArray();
+        for (Marker marker : list) {
+            MarkGroup group = groupService.findOne(examId, marker.getSubjectCode(), marker.getGroupNumber());
+            group.setQuestionList(questionService.findByExamAndSubjectAndObjectiveAndGroupNumber(examId,
+                    marker.getSubjectCode(), false, group.getNumber()));
+            if (group.getStatus() != MarkStatus.FINISH) {
+                JSONObject item = new JSONObject();
+                item.accumulate("id", marker.getId());
+                item.accumulate("title", group.getTitle());
+                item.accumulate("groupNumber", group.getNumber());
+                int percent = group.getLibraryCount() > 0 ? (int) (group.getMarkedCount() * 100.00 / group
+                        .getLibraryCount()) : 0;
+                item.accumulate("percent", percent);
+                array.add(item);
+            }
+        }
+        return array;
+    }
+
     @RequestMapping(value = "/subject-select", method = RequestMethod.POST)
     public ModelAndView select(HttpServletRequest request, HttpServletResponse response, @RequestParam Integer markerId) {
         WebUser user = RequestUtils.getWebUser(request);

+ 2 - 5
stmms-web/src/main/webapp/WEB-INF/views/modules/exam/checkAnswer.jsp

@@ -135,9 +135,6 @@ $('#count-button').click(function(){
     	alert("试卷类型仅支持英文或#!");
     	return;
     }
-    
-    
-    //alert($("#searchForm").serialize());
     $.post('${ctx}/admin/exam/check/answer/count', $("#searchForm").serialize(), function(result){
         //alert(result);
         $('#count').val(result);
@@ -150,8 +147,8 @@ $('#count-button').click(function(){
 });
 
 $('#start-button').click(function(){
-	var queryId=new Date().getTime()
-	sessionStorage.setItem(queryId, $("#searchForm").serialize());
+	var queryId=new Date().getTime();
+	localStorage.setItem(queryId, JSON.stringify($("#searchForm").serializeArray()));
 	$('#start-button').attr('href','${ctx}/web/admin/exam/check/answer/start?queryId='+queryId);
 });
 

+ 17 - 3
stmms-web/src/main/webapp/WEB-INF/views/modules/exam/paperDetail.jsp

@@ -16,16 +16,27 @@
 			<label>客观总分:<fmt:formatNumber pattern="###.###" value="${subject.objectiveScore}"/></label>
 			<label>主观总分:<fmt:formatNumber pattern="###.###" value="${subject.subjectiveScore}"/></label>
 			<label>试卷总分:<fmt:formatNumber pattern="###.###" value="${subject.totalScore}"/></label>
-			&nbsp;
+			&nbsp;<br/><br/>
+			<label>题型</label>
 			<select id="type-select" name="objective" class="input-small">
 				<option value="">不限</option>
 				<option value="true" <c:if test="${objective!=null && objective==true}">selected</c:if>>客观题</option>
 				<option value="false" <c:if test="${objective!=null && objective==false}">selected</c:if>>主观题</option>
 			</select>
+			&nbsp;
+			<label>大题</label>
+			<select id="main-select" name="mainNumber" class="input-large">
+				<option value="">不限</option>
+				<c:forEach items="${mainList}" var="question">
+					<option value="${question.mainNumber}" <c:if test="${question.mainNumber ==mainNumber }">selected</c:if>>${question.mainNumber}-${question.mainTitle}</option>
+				</c:forEach>
+			</select>
+			&nbsp;		
+			<a class="btn" type="button" href="${ctx}/admin/exam/paper/question/add?subjectCode=${subject.code }&pageNumber=${query.pageNumber}&code=${query.code }&category=${ query.category}&level=${query.level }&upload=${ upload}&totalScoreNotEqual=${  query.totalScoreNotEqual}">新增</a>
 			&nbsp;		
 			<input id="btnDelete" class="btn" type="button" value="删除" onclick="goDelete()"/>
 			&nbsp;		
-			<a class="btn" href="${ctx}/admin/exam/paper?pageNumber=${query.pageNumber}&code=${query.code }&category=${ query.category}&level=${query.level }&upload=${ upload}&totalScoreNotEqual=${  query.totalScoreNotEqual}"">返回</a>
+			<a class="btn" href="${ctx}/admin/exam/paper?pageNumber=${query.pageNumber}&code=${query.code }&category=${ query.category}&level=${query.level }&upload=${ upload}&totalScoreNotEqual=${  query.totalScoreNotEqual}">返回</a>
 		</div>
 	</form>
 	<form id="checkForm" action="${ctx}/admin/exam/paper/question/delete" method="post" class="breadcrumb form-search">
@@ -73,7 +84,7 @@
 				<td><c:if test="${!question.objective}">${question.groupNumber}</c:if>
 				</td>
 				<td>
-					<c:if test="${question.objective}"><a href="${ctx}/admin/exam/paper/question-edit/${question.id}?pageNumber=${query.pageNumber}&code=${query.code }&category=${ query.category}&level=${query.level }&upload=${ upload}&totalScoreNotEqual=${  query.totalScoreNotEqual}">编辑</a></c:if>
+					<c:if test="${question.groupNumber==null ||question.groupNumber==0}"><a href="${ctx}/admin/exam/paper/question-edit/${question.id}?pageNumber=${query.pageNumber}&code=${query.code }&category=${ query.category}&level=${query.level }&upload=${ upload}&totalScoreNotEqual=${  query.totalScoreNotEqual}">编辑</a></c:if>
 					<c:if test="${question.groupNumber==null ||question.groupNumber==0}"><a href="${ctx}/admin/exam/paper/question-delete/${question.id}?pageNumber=${query.pageNumber}&code=${query.code }&category=${ query.category}&level=${query.level }&upload=${ upload}&totalScoreNotEqual=${  query.totalScoreNotEqual}" class="delete-button">删除</a></c:if>
 				</td>
 			</tr>
@@ -85,6 +96,9 @@
 $('#type-select').change(function(){
 	$('#searchForm').submit();
 });
+$('#main-select').change(function(){
+	$('#searchForm').submit();
+});
 $('.delete-button').click(function () {
     return confirm('确定要删除吗?');
 });

+ 131 - 0
stmms-web/src/main/webapp/WEB-INF/views/modules/exam/questionAdd.jsp

@@ -0,0 +1,131 @@
+<%@ page contentType="text/html;charset=UTF-8" %>
+<%@ include file="/WEB-INF/views/include/taglib.jsp"%>
+<html>
+<head>
+	<title>考试管理</title>
+	<meta name="decorator" content="default"/>
+	<%@include file="/WEB-INF/views/include/head.jsp" %>
+	 <script type="text/javascript">
+        $(document).ready(function () {
+            $("#inputForm").validate({
+                submitHandler: function (form) {
+                    loading('正在提交,请稍等...');
+                    form.submit();
+                },
+                errorContainer: "#messageBox",
+                errorPlacement: function (error, element) {
+                    $("#messageBox").text("输入有误,请先更正。");
+                    if (element.is(":checkbox") || element.is(":radio") || element.parent().is(".input-append")) {
+                        error.appendTo(element.parent().parent());
+                    } else {
+                        error.insertAfter(element);
+                    }
+                }
+            });
+            $(".objectiveDiv").hide();
+            $("#objective").change(function () {
+                if ($("#objective").is(':checked')) {
+                    $(".objectiveDiv").show();
+                } else {
+                    $("#answer").attr("value", "");
+                    $("#paperType").attr("value", "");
+                    $(".objectiveDiv").hide();
+                }
+            });
+        });
+    </script>
+</head>
+<body>
+	<ul class="nav nav-tabs">
+		<li class="active"><a href="javascript:" onclick="history.go(-1);">试题列表</a></li>
+	</ul><br/>
+	<form id="inputForm" action="${ctx}/admin/exam/paper/question/save" method="post" class="form-horizontal">
+		<tags:message content="${message}"/>
+		<input type="hidden" id="pageNumber" name="pageNumber" value="${query.pageNumber }"/>
+	 	<input type="hidden" id="code" name="code" value="${query.code }"/>
+	 	<input type="hidden" id="category" name="category" value="${query.category }"/>
+	 	<input type="hidden" id="level" name="level" value="${query.level }"/>
+	 	<input type="hidden" id="upload" name="upload" value="${upload}"/>
+	 	<input type="hidden" id="totalScoreNotEqual" name="totalScoreNotEqual" value="${query.totalScoreNotEqual }"/>
+	 	
+	 	<input type="hidden" name="subjectCode" value="${subjectCode}"/>
+		<div class="control-group">
+			<label class="control-label">大题名称</label>
+			<div class="controls">
+			 <input name="mainTitle" value="${examQuestion.mainTitle }" type="text"  class="required"/>
+			</div>
+		</div>
+		<div class="control-group">
+			<label class="control-label">大题号</label>
+			<div class="controls">
+			 <input name="mainNumber" value="${examQuestion.mainNumber }" type="number" htmlEscape="false" max="100" min="1" class="required digits"/>
+			</div>
+		</div>
+		<div class="control-group">
+			<label class="control-label">小题号</label>
+			<div class="controls">
+			 <input name="subNumber" value="${examQuestion.subNumber }" type="number" htmlEscape="false" max="100" min="1" class="required digits"/>
+			</div>
+		</div>
+		<div class="control-group">
+			<label class="control-label">满分</label>
+			<div class="controls">
+			 <input name="totalScore" value="${examQuestion.totalScore }" type="number" htmlEscape="false"  maxlength="10" class="required digits"/>
+			</div>
+		</div>
+		<div class="control-group">
+	        <label class="control-label">是否客观题</label>
+	        <div class="controls">
+	            <input type="checkbox" id="objective" name="objective">是
+	        </div>
+    	</div>
+			<div class="control-group">
+	            <label class="control-label">间隔分</label>
+	            <div class="controls">
+	                <input type="text" name="intervalScore" class="required interval-score-input" htmlEscape="false" maxlength="10" class="required digits"
+	                       value="${examQuestion.intervalScore}"/>
+	            </div>
+	        </div>
+        <div class="objectiveDiv">
+        	<div class="control-group">
+				<label class="control-label">试卷类型</label>
+				<div class="controls">
+				 <input name="paperType" value="${examQuestion.paperType }" type="text" class="required"/>
+				</div>
+			</div>
+	        <div class="control-group">
+				<label class="control-label">题型</label>
+				<div class="controls">
+					<select class="input-small" name="type">
+	                <c:forEach items="${questionTypeList}" var="item">
+	                	 <option value="${item.value}" <c:if test="${item.value==examQuestion.type.value}">selected</c:if>>${item.name}</option>
+	                </c:forEach>
+	            </select>
+				</div>
+			</div>
+	        <div class="control-group">
+	            <label class="control-label">答案</label>
+	            <div class="controls">
+	                <input type="text" name="answer" htmlEscape="false" maxlength="10" class="required"
+	                       value="${examQuestion.answer}"/>
+	            </div>
+	        </div>
+			<div class="control-group">
+				<label class="control-label">判分策略</label>
+				<div class="controls">
+					<select class="input-small" name="objectivePolicy">
+	                <c:forEach items="${objectivePolicyList}" var="item">
+	                	 <option value="${item.value}" <c:if test="${item.value==examQuestion.objectivePolicy.value}">selected</c:if>>${item.name}</option>
+	                </c:forEach>
+	            </select>
+				</div>
+			</div>
+		</div>
+		<div class="form-actions">
+			<input id="btnSubmit" class="btn btn-primary" type="submit" value="保 存"/>
+			&nbsp;
+			<a href="javascript:" onclick="history.go(-1);"  class="btn"/>返回</a>
+		</div>
+	</form>
+</body>
+</html>

+ 96 - 9
stmms-web/src/main/webapp/WEB-INF/views/modules/exam/questionEdit.jsp

@@ -5,28 +5,115 @@
 	<title>考试管理</title>
 	<meta name="decorator" content="default"/>
 	<%@include file="/WEB-INF/views/include/head.jsp" %>
+	<script type="text/javascript">
+        $(document).ready(function () {
+            $("#inputForm").validate({
+                submitHandler: function (form) {
+                    loading('正在提交,请稍等...');
+                    form.submit();
+                },
+                errorContainer: "#messageBox",
+                errorPlacement: function (error, element) {
+                    $("#messageBox").text("输入有误,请先更正。");
+                    if (element.is(":checkbox") || element.is(":radio") || element.parent().is(".input-append")) {
+                        error.appendTo(element.parent().parent());
+                    } else {
+                        error.insertAfter(element);
+                    }
+                }
+            });
+            if ($("#objective").is(':checked')) {
+                $(".objectiveDiv").show();
+            }else{
+	            $(".objectiveDiv").hide();
+            }
+        });
+    </script>
 </head>
 <body>
-	<ul class="nav nav-tabs">
-		<li class="active"><a href="${ctx}/admin/exam/paper/detail?subjectCode=${examQuestion.subjectCode }">试题列表</a></li>
+<ul class="nav nav-tabs">
+		<li class="active"><a href="javascript:" onclick="history.go(-1);">试题列表</a></li>
 	</ul><br/>
 	<form id="inputForm" action="${ctx}/admin/exam/paper/question-edit" method="post" class="form-horizontal">
 		<tags:message content="${message}"/>
-		<input type="hidden"  name="id" value="${examQuestion.id }"/>
 		<input type="hidden" id="pageNumber" name="pageNumber" value="${query.pageNumber }"/>
 	 	<input type="hidden" id="code" name="code" value="${query.code }"/>
 	 	<input type="hidden" id="category" name="category" value="${query.category }"/>
 	 	<input type="hidden" id="level" name="level" value="${query.level }"/>
 	 	<input type="hidden" id="upload" name="upload" value="${upload}"/>
 	 	<input type="hidden" id="totalScoreNotEqual" name="totalScoreNotEqual" value="${query.totalScoreNotEqual }"/>
+	 	
+	 	<input type="hidden" name="id" value="${examQuestion.id}"/>
 		<div class="control-group">
-			<label class="control-label">判分策略</label>
+			<label class="control-label">大题名称</label>
 			<div class="controls">
-				<select class="input-small" name="objectivePolicy">
-                <c:forEach items="${objectivePolicyList}" var="item">
-                	 <option value="${item.value}" <c:if test="${item.value==examQuestion.objectivePolicy.value}">selected</c:if>>${item.name}</option>
-                </c:forEach>
-            </select>
+			 <input name="mainTitle" value="${examQuestion.mainTitle }" type="text"  class="required"/>
+			</div>
+		</div>
+		<div class="control-group">
+			<label class="control-label">大题号</label>
+			<div class="controls">
+			 <input name="mainNumber" value="${examQuestion.mainNumber }" type="number" htmlEscape="false" max="100" min="1" class="required digits"/>
+			</div>
+		</div>
+		<div class="control-group">
+			<label class="control-label">小题号</label>
+			<div class="controls">
+			 <input name="subNumber" value="${examQuestion.subNumber }" type="number" htmlEscape="false" max="100" min="1" class="required digits"/>
+			</div>
+		</div>
+		<div class="control-group">
+			<label class="control-label">满分</label>
+			<div class="controls">
+			 <input name="totalScore" value="${examQuestion.totalScore }" type="number" htmlEscape="false"  maxlength="10" class="required digits"/>
+			</div>
+		</div>
+		<div class="control-group">
+	        <label class="control-label">是否客观题</label>
+	        <div class="controls">
+	            <input type="checkbox" id="objective" name="objective" <c:if test="${examQuestion.objective }">checked</c:if> disabled>是
+	        </div>
+    	</div>
+			<div class="control-group">
+	            <label class="control-label">间隔分</label>
+	            <div class="controls">
+	                <input type="text" name="intervalScore" class="required interval-score-input" htmlEscape="false" maxlength="10" class="required digits"
+	                       value="${examQuestion.intervalScore}"/>
+	            </div>
+	        </div>
+        <div class="objectiveDiv">
+        	<div class="control-group">
+				<label class="control-label">试卷类型</label>
+				<div class="controls">
+				 <input name="paperType" value="${examQuestion.paperType }" type="text" class="required"/>
+				</div>
+			</div>
+	        <div class="control-group">
+				<label class="control-label">题型</label>
+				<div class="controls">
+					<select class="input-small" name="type">
+	                <c:forEach items="${questionTypeList}" var="item">
+	                	 <option value="${item.value}" <c:if test="${item.value==examQuestion.type.value}">selected</c:if>>${item.name}</option>
+	                </c:forEach>
+	            </select>
+				</div>
+			</div>
+	        <div class="control-group">
+	            <label class="control-label">答案</label>
+	            <div class="controls">
+	                <input type="text" name="answer" htmlEscape="false" maxlength="10" class="required"
+	                       value="${examQuestion.answer}"/>
+	            </div>
+	        </div>
+			<div class="control-group">
+				<label class="control-label">判分策略</label>
+				<div class="controls">
+					<select class="input-small" name="objectivePolicy">
+	                <c:forEach items="${objectivePolicyList}" var="item">
+	                	 <option value="${item.value}" <c:if test="${item.value==examQuestion.objectivePolicy.value}">selected</c:if>>${item.name}</option>
+	                </c:forEach>
+	            </select>
+				</div>
 			</div>
 		</div>
 		<div class="form-actions">

+ 34 - 5
stmms-web/src/main/webapp/WEB-INF/views/modules/mark/subjectSelect.jsp

@@ -28,17 +28,39 @@
 
             $('#exam-select').change(function () {
                 var examId = $(this).val();
+                $('#subject-select').empty();
+                if (examId == '') {
+                    $('#subject-select').val('').trigger('change');
+                    return;
+                }
+                $.post('${ctx}/mark/subject/query', {examId: examId}, function (result) {
+                    var parent = $('#subject-select');
+                    var first = '';
+                    for (var i = 0; i < result.length; i++) {
+                        var marker = result[i];
+                        $('<option value="' + marker.subjectCode + '">' + marker.subjectCode + '_' + marker.subjectName + '</option>').appendTo(parent);
+                        if (i == 0) {
+                            first = marker.id;
+                        }
+                    }
+                    parent.val(first).trigger('change');
+                });
+                $('.point').hide();
+            });
+            $('#subject-select').change(function () {
+            	var examId = $("#exam-select").val();
+                var subjectCode = $(this).val();
                 $('#marker-select').empty();
                 if (examId == '') {
                     $('#marker-select').val('').trigger('change');
                     return;
                 }
-                $.post('${ctx}/mark/subject/query', {examId: examId}, function (result) {
+                $.post('${ctx}/mark/subject/group/query', {examId: examId,subjectCode:subjectCode}, function (result) {
                     var parent = $('#marker-select');
                     var first = '';
                     for (var i = 0; i < result.length; i++) {
                         var marker = result[i];
-                        $('<option value="' + marker.id + '">' + marker.subjectCode + '_' + marker.subjectName + '</option>').appendTo(parent);
+                        $('<option value="' + marker.id + '">分组:' + marker.groupNumber + '-' + marker.title +' '+ marker.percent+'%</option>').appendTo(parent);
                         if (i == 0) {
                             first = marker.id;
                         }
@@ -47,7 +69,7 @@
                 });
                 $('.point').hide();
             });
-
+            
             $(document).ajaxError(function (evt, req, settings) {
                 if (req.status == 401) {
                     alert("账号已在其他地方登录!");
@@ -95,9 +117,16 @@
                         </select>
                     </div>
                     <div class="option">
-                        <select name="markerId" id="marker-select">
+                        <select name="subjectCode" id="subject-select">
                             <c:if test="${subject!=null}">
-                                <option value="">${subject.code}_${subject.name}</option>
+                                <option value="${subject.code}">${subject.code}_${subject.name}</option>
+                            </c:if>
+                        </select>
+                    </div>
+                    <div class="option">
+                        <select name="markerId" id="marker-select">
+                            <c:if test="${group!=null}">
+                                <option value="">分组:${group.groupNumber}-${group.title}&nbsp;${group.percent }%</option>
                             </c:if>
                         </select>
                     </div>

+ 2 - 2
stmms-web/src/main/webapp/WEB-INF/views/modules/report/reportSubjectClass.jsp

@@ -42,8 +42,8 @@
         &nbsp;
         <input id="btnSubmit" class="btn btn-primary" type="button" value="查询" onclick="goSearch()" data-i18n-value="report.class.search"/>
         &nbsp;
-		<input id="export-button" class="btn" type="button" value="导出" data-i18n-value="report.class.export"/>
-		 &nbsp;
+		<!-- <input id="export-button" class="btn" type="button" value="导出" data-i18n-value="report.class.export"/>
+		 &nbsp; -->
         <input class="btn btn-primary" type="button" value="查看统计图" onclick="viewClassEcharts()" data-i18n-value="report.class.chart"/>
     </div>
 </form>

+ 2 - 2
stmms-web/src/main/webapp/WEB-INF/views/modules/report/reportSubjectCollege.jsp

@@ -45,8 +45,8 @@
         &nbsp;
         <input id="btnSubmit" class="btn btn-primary" type="button" value="查询" onclick="goSearch()" data-i18n-value="report.college.search"/>
          &nbsp;
-		<input id="export-button" class="btn" type="button" value="导出" data-i18n-value="report.college.export"/>
-		 &nbsp;
+		<!-- <input id="export-button" class="btn" type="button" value="导出" data-i18n-value="report.college.export"/>
+		 &nbsp; -->
         <input class="btn btn-primary" type="button" value="查看统计图" onclick="viewCollegeEcharts()" data-i18n-value="report.college.chart"/>
     </div>
 </form>

+ 2 - 2
stmms-web/src/main/webapp/WEB-INF/views/modules/report/reportSubjectGroup.jsp

@@ -42,8 +42,8 @@
         &nbsp;
         <input id="btnSubmit" class="btn btn-primary" type="button" value="查询" onclick="goSearch()"  data-i18n-value="report.group.search"/>
 		&nbsp;
-		<input id="export-button" class="btn" type="button" value="导出"  data-i18n-value="report.group.export"/>
-		 &nbsp;
+		<!-- <input id="export-button" class="btn" type="button" value="导出"  data-i18n-value="report.group.export"/>
+		 &nbsp; -->
         <input class="btn btn-primary" type="button" value="查看统计图" onclick="viewGroupEcharts()"  data-i18n-value="report.group.chart"/>
     </div>
 </form>

+ 2 - 2
stmms-web/src/main/webapp/WEB-INF/views/modules/report/reportSubjectQuestion.jsp

@@ -51,8 +51,8 @@
         &nbsp;
         <input id="btnSubmit" class="btn btn-primary" type="button" value="查询" onclick="goSearch()"  data-i18n-value="report.question.search"/>		
         &nbsp;
-		<input id="export-button" class="btn" type="button" value="导出"  data-i18n-value="report.question.export"/>
-		 &nbsp;
+		<!-- <input id="export-button" class="btn" type="button" value="导出"  data-i18n-value="report.question.export"/>
+		 &nbsp; -->
         <input class="btn btn-primary" type="button" value="查看统计图" onclick="viewQuestionEcharts()" data-i18n-value="report.question.chart"/>
 
     </div>

+ 17 - 2
stmms-web/src/main/webapp/WEB-INF/views/modules/report/reportSubjectRange.jsp

@@ -46,10 +46,18 @@
         </select>
         <input id="btnSubmit" class="btn btn-primary" type="button" value="查询" onclick="goSearch()"  data-i18n-value="report.group.search"/>
 		&nbsp;
-		<input id="export-button" class="btn" type="button" value="导出"  data-i18n-value="report.group.export"/>
+		<div class="btn-group">
+				<a class="btn dropdown-toggle" data-toggle="dropdown" href="#">
+					导出<span class="caret"></span>
+				</a>
+				<ul class="dropdown-menu">
+					<li><a href="##" id="export-button">导出</a></li>
+					<li><a href="##"  id="exportAll-button">批量导出</a></li>
+				</ul>
+		</div>
 		<c:if test="${query.subjectCode!=null}">
 		&nbsp;
-		<a href="${ctx}/admin/exam/reportSubjectRange/report?subjectCode=${query.subjectCode}" class="btn" <c:if test="${locked}">disabled="disabled"</c:if>>分析计算</a>
+		<a href="${ctx}/admin/exam/reportSubjectRange/report?subjectCode=${query.subjectCode}" class="btn" <c:if test="${locked}">disabled="disabled"</c:if>>刷新</a>
 		</c:if>
 		&nbsp;
 		<a href="#" onclick="viewEcharts()" class="btn  btn-primary">查看统计图</a>
@@ -58,6 +66,7 @@
 	<form id="exportForm" action="${ctx}/admin/exam/reportSubjectRange/export" method="post" class="breadcrumb form-search hide">
         <input type="text" name="subjectCode" value="${query.subjectCode}"  class="input-small"/>
         <input type="text" name="range" value="${query.range}"  class="input-small"/>
+        <input type="hidden" id="all" name="all"/>
 	</form>
 <tags:message content="${message}"/>
 <table id="contentTable" class="table table-striped table-bordered table-condensed">
@@ -86,6 +95,12 @@ $("#export-button").click(function(){
         alert('请选择科目');
         return;
     }
+	$("#all").attr("value",false);
+	$("#exportForm").attr("action","${ctx}/admin/exam/reportSubjectRange/export");
+	$("#exportForm").submit();
+});
+$("#exportAll-button").click(function(){
+	$("#all").attr("value",true);
 	$("#exportForm").attr("action","${ctx}/admin/exam/reportSubjectRange/export");
 	$("#exportForm").submit();
 });

+ 2 - 2
stmms-web/src/main/webapp/WEB-INF/views/modules/report/reportSubjectTeacher.jsp

@@ -42,8 +42,8 @@
        &nbsp;
         <input id="btnSubmit" class="btn btn-primary" type="button" value="查询" onclick="goSearch()"  data-i18n-value="report.teacher.search"/>
 		&nbsp;
-		<input id="export-button" class="btn" type="button" value="导出"  data-i18n-value="report.teacher.export"/>
-		 &nbsp;
+		<!-- <input id="export-button" class="btn" type="button" value="导出"  data-i18n-value="report.teacher.export"/>
+		 &nbsp; -->
         <input class="btn btn-primary" type="button" value="查看统计图" onclick="viewTeacherEcharts()"  data-i18n-value="report.teacher.chart"/>
     </div>
 </form>

+ 2 - 2
stmms-web/src/main/webapp/WEB-INF/views/modules/report/reportSubjectTeacherClass.jsp

@@ -25,8 +25,8 @@
     <span data-i18n-text="report.teacher.name">任课老师</span>:${query.teacherName} &nbsp;&nbsp;
     <a href="#" class="btn btn-primary" onclick="viewTeacherClassEcharts()" data-i18n-text="report.teacher.chart">查看统计图</a>
     &nbsp;
-	<input id="export-button" class="btn" type="button" value="导出" data-i18n-value="report.teacher.export"/>
-	&nbsp;
+	<!-- <input id="export-button" class="btn" type="button" value="导出" data-i18n-value="report.teacher.export"/>
+	&nbsp; -->
     <a href="javascript:" onclick="history.go(-1);"  class="btn" data-i18n-text="report.teacher.return">返回</a>
 </form>
 <tags:message content="${message}"/>