Selaa lähdekoodia

Merge remote-tracking branch 'origin/dev_xuwenjin' into dev0415_yinting

Conflicts:
	stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/model/Exam.java
	stmms-web/src/main/java/cn/com/qmth/stmms/admin/exam/ScoreController.java
	stmms-web/src/main/java/cn/com/qmth/stmms/admin/thread/ScoreCalculateThread.java
ting.yin 6 vuotta sitten
vanhempi
commit
96fc4de437
58 muutettua tiedostoa jossa 5305 lisäystä ja 51 poistoa
  1. 13 10
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/dao/ExamQuestionDao.java
  2. 15 13
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/dao/ExamStudentDao.java
  3. 28 3
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/model/Exam.java
  4. 45 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/dao/ReportSubjectClassDao.java
  5. 43 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/dao/ReportSubjectCollegeDao.java
  6. 53 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/dao/ReportSubjectDao.java
  7. 27 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/dao/ReportSubjectGroupDao.java
  8. 19 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/dao/ReportSubjectQuestionDao.java
  9. 34 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/dao/ReportSubjectRangeDao.java
  10. 44 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/dao/ReportSubjectTeacherClassDao.java
  11. 43 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/dao/ReportSubjectTeacherDao.java
  12. 202 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/model/ReportSubject.java
  13. 186 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/model/ReportSubjectClass.java
  14. 174 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/model/ReportSubjectCollege.java
  15. 202 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/model/ReportSubjectGroup.java
  16. 171 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/model/ReportSubjectQuestion.java
  17. 282 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/model/ReportSubjectRange.java
  18. 215 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/model/ReportSubjectTeacher.java
  19. 228 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/model/ReportSubjectTeacherClass.java
  20. 62 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/query/ReportSubjectQuery.java
  21. 16 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/service/ReportService.java
  22. 22 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/service/ReportSubjectClassService.java
  23. 22 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/service/ReportSubjectCollegeService.java
  24. 28 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/service/ReportSubjectGroupService.java
  25. 24 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/service/ReportSubjectQuestionService.java
  26. 19 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/service/ReportSubjectRangeService.java
  27. 22 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/service/ReportSubjectService.java
  28. 22 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/service/ReportSubjectTeacherClassService.java
  29. 22 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/service/ReportSubjectTeacherService.java
  30. 125 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/service/impl/ReportServiceImpl.java
  31. 88 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/service/impl/ReportSubjectClassServiceImpl.java
  32. 83 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/service/impl/ReportSubjectCollegeServiceImpl.java
  33. 183 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/service/impl/ReportSubjectGroupServiceImpl.java
  34. 157 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/service/impl/ReportSubjectQuestionServiceImpl.java
  35. 99 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/service/impl/ReportSubjectRangeServiceImpl.java
  36. 88 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/service/impl/ReportSubjectServiceImpl.java
  37. 99 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/service/impl/ReportSubjectTeacherClassServiceImpl.java
  38. 97 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/service/impl/ReportSubjectTeacherServiceImpl.java
  39. 75 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/utils/DoubleUtil.java
  40. 19 14
      stmms-web/src/main/java/cn/com/qmth/stmms/admin/exam/ScoreController.java
  41. 52 0
      stmms-web/src/main/java/cn/com/qmth/stmms/admin/report/ReportSubjectClassController.java
  42. 52 0
      stmms-web/src/main/java/cn/com/qmth/stmms/admin/report/ReportSubjectCollegeController.java
  43. 51 0
      stmms-web/src/main/java/cn/com/qmth/stmms/admin/report/ReportSubjectController.java
  44. 50 0
      stmms-web/src/main/java/cn/com/qmth/stmms/admin/report/ReportSubjectGroupController.java
  45. 52 0
      stmms-web/src/main/java/cn/com/qmth/stmms/admin/report/ReportSubjectQuestionController.java
  46. 53 0
      stmms-web/src/main/java/cn/com/qmth/stmms/admin/report/ReportSubjectRangeController.java
  47. 60 0
      stmms-web/src/main/java/cn/com/qmth/stmms/admin/report/ReportSubjectTeacherClassController.java
  48. 52 0
      stmms-web/src/main/java/cn/com/qmth/stmms/admin/report/ReportSubjectTeacherController.java
  49. 42 10
      stmms-web/src/main/java/cn/com/qmth/stmms/admin/thread/ScoreCalculateThread.java
  50. 1 1
      stmms-web/src/main/webapp/WEB-INF/views/modules/exam/examIndex.jsp
  51. 86 0
      stmms-web/src/main/webapp/WEB-INF/views/modules/report/reportSubject.jsp
  52. 208 0
      stmms-web/src/main/webapp/WEB-INF/views/modules/report/reportSubjectClass.jsp
  53. 201 0
      stmms-web/src/main/webapp/WEB-INF/views/modules/report/reportSubjectCollege.jsp
  54. 199 0
      stmms-web/src/main/webapp/WEB-INF/views/modules/report/reportSubjectGroup.jsp
  55. 190 0
      stmms-web/src/main/webapp/WEB-INF/views/modules/report/reportSubjectQuestion.jsp
  56. 163 0
      stmms-web/src/main/webapp/WEB-INF/views/modules/report/reportSubjectRange.jsp
  57. 226 0
      stmms-web/src/main/webapp/WEB-INF/views/modules/report/reportSubjectTeacher.jsp
  58. 171 0
      stmms-web/src/main/webapp/WEB-INF/views/modules/report/reportSubjectTeacherClass.jsp

+ 13 - 10
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/dao/ExamQuestionDao.java

@@ -1,35 +1,38 @@
 package cn.com.qmth.stmms.biz.exam.dao;
 
-import java.util.List;
-
+import cn.com.qmth.stmms.biz.exam.model.ExamQuestion;
 import org.springframework.data.jpa.repository.JpaRepository;
 import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
 import org.springframework.data.jpa.repository.Modifying;
 import org.springframework.data.jpa.repository.Query;
 
-import cn.com.qmth.stmms.biz.exam.model.ExamQuestion;
+import java.util.List;
 
 public interface ExamQuestionDao extends JpaRepository<ExamQuestion, Integer>, JpaSpecificationExecutor<ExamQuestion> {
 
+
+    @Query("select sum(q.totalScore) as totalScore from ExamQuestion q where q.examId=?1 and q.subjectCode=?2 and q.mainNumber=?3")
+    public Double queryFullScoreByExamIdAndSubjectCodeAndMainNumber(Integer examId, String subjectCode, Integer mainNumber);
+
     @Query("select q from ExamQuestion q where q.examId=?1 and q.subjectCode=?2 and q.objective=?3 "
-            + "order by q.paperType, q.mainNumber, q.subNumber")
+            + "order by q.mainNumber, q.subNumber")
     public List<ExamQuestion> findByExamIdAndSubjectCodeAndObjective(Integer examId, String subjectCode,
-            boolean objective);
+                                                                     boolean objective);
 
     @Query("select q from ExamQuestion q where q.examId=?1 and q.subjectCode=?2 and q.objective=?3 "
             + "and q.paperType=?4 order by q.mainNumber, q.subNumber")
     public List<ExamQuestion> findByExamIdAndSubjectCodeAndObjectiveAndPaperType(Integer examId, String subjectCode,
-            boolean objective, String paperType);
+                                                                                 boolean objective, String paperType);
 
     @Query("select q from ExamQuestion q where q.examId=?1 and q.subjectCode=?2 and q.objective=?3 "
             + "and q.mainNumber=?4 order by q.subNumber")
     public List<ExamQuestion> findByExamIdAndSubjectCodeAndObjectiveAndMainNumber(Integer examId, String subjectCode,
-            boolean objective, Integer mainNumber);
+                                                                                  boolean objective, Integer mainNumber);
 
     @Query("select q from ExamQuestion q where q.examId=?1 and q.subjectCode=?2 and q.objective=?3 "
             + "and q.paperType=?4 and q.mainNumber=?5 order by q.subNumber")
     public List<ExamQuestion> findByExamIdAndSubjectCodeAndObjectiveAndPaperTypeAndMainNumber(Integer examId,
-            String subjectCode, boolean objective, String paperType, Integer mainNumber);
+                                                                                              String subjectCode, boolean objective, String paperType, Integer mainNumber);
 
     @Modifying
     @Query("delete from ExamQuestion q where q.examId=?1 and q.subjectCode=?2 and q.objective=?3")
@@ -38,12 +41,12 @@ public interface ExamQuestionDao extends JpaRepository<ExamQuestion, Integer>, J
     @Modifying
     @Query("delete from ExamQuestion q where q.examId=?1 and q.subjectCode=?2 and q.objective=?3 and q.mainNumber=?4")
     public void deleteByExamIdAndSubjectCodeAndObjectiveAndMainNumber(Integer examId, String subjectCode,
-            boolean objective, Integer mainNumber);
+                                                                      boolean objective, Integer mainNumber);
 
     @Modifying
     @Query("update ExamQuestion q set q.mainTitle=?5 where q.examId=?1 and q.subjectCode=?2 "
             + "and q.objective=?3 and q.mainNumber=?4")
     public void updateMainTitleByExamIdAndSubjectCodeAndObjectiveAndMainNumber(Integer examId, String subjectCode,
-            boolean objective, Integer mainNumber, String mainTitle);
+                                                                               boolean objective, Integer mainNumber, String mainTitle);
 
 }

+ 15 - 13
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/dao/ExamStudentDao.java

@@ -1,15 +1,14 @@
 package cn.com.qmth.stmms.biz.exam.dao;
 
-import java.util.Date;
-import java.util.List;
-
+import cn.com.qmth.stmms.biz.exam.model.ExamStudent;
 import org.springframework.data.domain.Pageable;
 import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
 import org.springframework.data.jpa.repository.Modifying;
 import org.springframework.data.jpa.repository.Query;
 import org.springframework.data.repository.PagingAndSortingRepository;
 
-import cn.com.qmth.stmms.biz.exam.model.ExamStudent;
+import java.util.Date;
+import java.util.List;
 
 public interface ExamStudentDao
         extends PagingAndSortingRepository<ExamStudent, Integer>, JpaSpecificationExecutor<ExamStudent> {
@@ -17,7 +16,7 @@ public interface ExamStudentDao
     public List<ExamStudent> findByExamId(int examId, Pageable pageable);
 
     public List<ExamStudent> findByExamIdAndUploadAndAbsent(int examId, boolean upload, boolean absent,
-            Pageable pageable);
+                                                            Pageable pageable);
 
     public List<ExamStudent> findByExamIdAndCampusName(int examId, String campusName, Pageable pageable);
 
@@ -63,7 +62,7 @@ public interface ExamStudentDao
     @Modifying
     @Query("update ExamStudent s set s.subjectName=?3, s.subjectLevel=?4, s.subjectCategory=?5 where s.examId=?1 and s.subjectCode=?2")
     public void updateSubjectInfo(int examId, String subjectCode, String subjectName, String subjectLevel,
-            String subjectCategory);
+                                  String subjectCategory);
 
     @Modifying
     @Query("update ExamStudent s set s.exception=?2 where s.id=?1")
@@ -81,7 +80,7 @@ public interface ExamStudentDao
     @Query("update ExamStudent s set s.sheetCount=?2, s.sliceCount=?3, s.answers=?4, s.batchCode=?5, s.paperType=?6,"
             + " s.absent=?7, s.upload=true, s.uploadTime=?8, s.objectiveScore=?9, s.objectiveScoreList=?10 where s.id=?1")
     public int updateScanInfo(Integer id, Integer sheetCount, Integer sliceCount, String answers, String batchCode,
-            String paperType, boolean absent, Date uploadTime, Double objectiveScore, String objectiveScoreList);
+                              String paperType, boolean absent, Date uploadTime, Double objectiveScore, String objectiveScoreList);
 
     @Modifying
     @Query("update ExamStudent s set s.manualAbsent=0 where s.examId=?1")
@@ -98,34 +97,37 @@ public interface ExamStudentDao
     public ExamStudent findByExamIdAndSubjectCodeAndStudentCode(Integer id, String subjectCode, String studentCode);
 
     public ExamStudent findBySchoolIdAndSubjectCodeAndStudentCodeAndRemark(Integer schoolId, String subjectCode,
-            String studentCode, String examSeqCode);
+                                                                           String studentCode, String examSeqCode);
 
     public List<ExamStudent> findByExamIdAndUploadTimeAfter(int examId, Date date);
 
     public List<ExamStudent> findByExamIdAndSubjectCodeAndUploadTimeAfter(int examId, String code, Date date,
-            Pageable page);
+                                                                          Pageable page);
 
     @Query("select count(s) from ExamStudent s where s.examId=?1 and s.subjectiveScoreList != null ")
     public long countByExamIdAndSubjectiveScoreListNotNull(Integer examId);
 
     public List<ExamStudent> findByExamIdAndSubjectCodeAndUploadTimeNotNull(int examId, String code);
 
+    public List<ExamStudent> findByExamIdAndSubjectCodeAndUploadTimeNotNullAndAbsent(int examId, String code, Boolean absent);
+
+
     @Query("select s from ExamStudent s where s.examId=?1 and s.subjectCode=?2 and s.absent=false and s.breach=false and s.uploadTime!=null "
             + "and not exists (select l.id from MarkLibrary l where l.studentId=s.id and l.groupNumber=?3)")
     public List<ExamStudent> findUnLibraryStudent(Integer examId, String subjectCode, Integer groupNumber,
-            Pageable page);
+                                                  Pageable page);
 
     @Query("select s from ExamStudent s where s.examId=?1 and s.subjectCode=?2 and s.absent=false and s.breach=false and s.uploadTime!=null and s.uploadTime>=?4 "
             + "and not exists (select l.id from MarkLibrary l where l.studentId=s.id and l.groupNumber=?3)")
     public List<ExamStudent> findUnLibraryStudent(Integer examId, String subjectCode, Integer groupNumber,
-            Date minUploadTime, Pageable page);
+                                                  Date minUploadTime, Pageable page);
 
     @Query("select s from ExamStudent s where s.examId=?1 and s.subjectCode=?2 and s.upload=true and s.absent=false and s.breach=false "
             + "and not exists (select l.id from TrialLibrary l where l.studentId=s.id and l.groupNumber=?3)")
     public List<ExamStudent> findUnTrialStudent(Integer examId, String subjectCode, Integer groupNumber, Pageable page);
 
     @Query("select s from ExamStudent s where s.examId=?1 and s.subjectCode=?2 and (s.absent=true or s.breach=true) and "
-            + " (exists (select l.id from MarkLibrary l where l.studentId=s.id) or exists (select t.id from TrialLibrary t where t.studentId=s.id)) ")
+            + "exists (select l.id from MarkLibrary l where l.studentId=s.id)")
     public List<ExamStudent> findAbsentOrBreachLibraryStudent(Integer examId, String subjectCode);
 
     @Query("select sum(case when ((case when s.objectiveScore is null then 0 else s.objectiveScore end) + (case when s.subjectiveScore is null then 0 else s.subjectiveScore end)) between 0 and 49.9 then 1 else 0 end),"
@@ -160,7 +162,7 @@ public interface ExamStudentDao
             + "sum(case when ((case when s.objectiveScore is null then 0 else s.objectiveScore end) + (case when s.subjectiveScore is null then 0 else s.subjectiveScore end)) between 60 and 100 then 1 else 0 end) "
             + " from ExamStudent s where s.examId=?1 and s.subjectCode=?2 and s.upload=?3  and s.absent=?4 and s.breach = ?5")
     public List<Object[]> statisticsByAbsentAndBreach(Integer examId, String code, Boolean upload, boolean absent,
-            boolean breach);
+                                                      boolean breach);
 
     @Query(value = "select s.id from eb_exam_student s where 1=1 and s.id in (select m.student_id from m_library m where 1=1 and m.marker_id in (select m.id from eb_marker m where 1=1 and m.login_name = ?1 ))", nativeQuery = true)
     public List<String[]> findIdsByMarkLogin(String markLogin);

+ 28 - 3
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/model/Exam.java

@@ -67,13 +67,25 @@ public class Exam implements Serializable {
 
     @Column(name = "creator_id")
     private Integer creatorId;
-    
+
     /**
      * 是否需要统分
      */
     @Column(name = "need_calculate", nullable = false)
     private boolean needCalculate;
 
+    /**
+     * 及格分数
+     */
+    @Column(name = "pass_score")
+    private Double passScore;
+
+    /**
+     * 优秀分数
+     */
+    @Column(name = "excellent_score")
+    private Double excellentScore;
+
     public Integer getId() {
         return id;
     }
@@ -166,14 +178,27 @@ public class Exam implements Serializable {
         return PictureConfigItem.parse(sliceConfig);
     }
 
-    
     public boolean isNeedCalculate() {
         return needCalculate;
     }
 
-    
     public void setNeedCalculate(boolean needCalculate) {
         this.needCalculate = needCalculate;
     }
 
+    public Double getPassScore() {
+        return passScore;
+    }
+
+    public void setPassScore(Double passScore) {
+        this.passScore = passScore;
+    }
+
+    public Double getExcellentScore() {
+        return excellentScore;
+    }
+
+    public void setExcellentScore(Double excellentScore) {
+        this.excellentScore = excellentScore;
+    }
 }

+ 45 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/dao/ReportSubjectClassDao.java

@@ -0,0 +1,45 @@
+package cn.com.qmth.stmms.biz.report.dao;
+
+import cn.com.qmth.stmms.biz.report.model.ReportSubjectClass;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.PagingAndSortingRepository;
+
+import java.util.List;
+
+/**
+ * 课程班级成绩分析 Dao
+ *
+ * @author xuwenjin
+ * @date 2019-04-16
+ */
+public interface ReportSubjectClassDao
+        extends PagingAndSortingRepository<ReportSubjectClass, Integer>, JpaSpecificationExecutor<ReportSubjectClass> {
+
+    void deleteByExamId(Integer exmaId);
+
+
+    /**
+     * 获取课程班级分析数据
+     *
+     * @param examId
+     * @param subjectCode
+     * @return List<Object [ ]>
+     */
+    @Query(value = "SELECT " +
+            "s.className," +
+            "avg( s.objectiveScore + s.subjectiveScore ) ," +
+            "max( s.objectiveScore + s.subjectiveScore ) ," +
+            "min( s.objectiveScore + s.subjectiveScore ) ," +
+            "sum( CASE WHEN ( s.objectiveScore + s.subjectiveScore ) >= e.passScore THEN 1 ELSE 0 END ) ," +
+            "sum( CASE WHEN ( s.objectiveScore + s.subjectiveScore ) >= e.excellentScore THEN 1 ELSE 0 END ) ," +
+            "count(s) " +
+            "FROM " +
+            "ExamStudent s ,Exam e " +
+            "where s.examId = e.id " +
+            "and " +
+            "s.examId = ?1 AND s.subjectCode = ?2 and s.className is not null and s.absent = false " +
+            "GROUP BY s.className")
+    List<Object[]> queryReportSubjectClassData(Integer examId, String subjectCode);
+
+}

+ 43 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/dao/ReportSubjectCollegeDao.java

@@ -0,0 +1,43 @@
+package cn.com.qmth.stmms.biz.report.dao;
+
+import cn.com.qmth.stmms.biz.report.model.ReportSubjectCollege;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.PagingAndSortingRepository;
+
+import java.util.List;
+
+/**
+ * 课程学院分析 Dao
+ *
+ * @author xuwenjin
+ * @date 2019-04-15
+ */
+public interface ReportSubjectCollegeDao
+        extends PagingAndSortingRepository<ReportSubjectCollege, Integer>, JpaSpecificationExecutor<ReportSubjectCollege> {
+
+    void deleteByExamId(Integer exmaId);
+
+
+    /**
+     * 获取课程学院分析数据
+     *
+     * @param examId
+     * @param subjectCode
+     * @return List<Object [ ]>
+     */
+    @Query(value = "SELECT " +
+            "s.college," +
+            "max( s.objectiveScore + s.subjectiveScore ) ," +
+            "min( s.objectiveScore + s.subjectiveScore) ," +
+            "avg( s.objectiveScore + s.subjectiveScore ) ," +
+            "sum( CASE WHEN ( s.objectiveScore + s.subjectiveScore ) >= e.passScore THEN 1 ELSE 0 END ) ," +
+            "sum( CASE WHEN ( s.objectiveScore + s.subjectiveScore ) >= e.excellentScore THEN 1 ELSE 0 END ) ," +
+            "count(s) FROM " +
+            "ExamStudent s , Exam e where  s.examId = e.id " +
+            "and " +
+            "s.examId = ?1 and s.subjectCode = ?2  and s.college is not null and s.absent = false " +
+            "GROUP BY s.college")
+    List<Object[]> queryReportSubjectCollegeData(Integer examId, String subjectCode);
+
+}

+ 53 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/dao/ReportSubjectDao.java

@@ -0,0 +1,53 @@
+package cn.com.qmth.stmms.biz.report.dao;
+
+import cn.com.qmth.stmms.biz.report.model.ReportSubject;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.PagingAndSortingRepository;
+
+import java.util.List;
+
+/**
+ * 课程总量分析 Dao
+ *
+ * @author xuwenjin
+ * @date 2019-04-12
+ */
+public interface ReportSubjectDao
+        extends PagingAndSortingRepository<ReportSubject, Integer>, JpaSpecificationExecutor<ReportSubject> {
+
+    void deleteByExamId(Integer exmaId);
+
+    /**
+     * 查询考试数据
+     *
+     * @param examId
+     * @return
+     */
+    @Query(value = "SELECT  s.examId," +
+            "s.subjectCode," +
+            "s.subjectName," +
+            "count(s) ," +
+            "sum( CASE WHEN s.absent = true THEN 1 ELSE 0 END ) ," +
+            "sum( CASE WHEN s.breach = true THEN 1 ELSE 0 END ) ," +
+            "count(s) - sum( CASE WHEN s.absent = true THEN 1 ELSE 0 END )  ," +
+            "max(s.objectiveScore + s.subjectiveScore) ," +
+            "min(s.objectiveScore + s.subjectiveScore) ," +
+            "avg(s.objectiveScore + s.subjectiveScore) ," +
+            "sum( CASE WHEN (s.objectiveScore + s.subjectiveScore) >= e.passScore  THEN 1 ELSE 0 END )  " +
+            "FROM " +
+            "ExamStudent s , Exam e where s.examId = e.id " +
+            "and s.examId = ?1  GROUP BY s.subjectCode, s.subjectName")
+    List<Object[]> queryReportSubjectData(Integer examId);
+
+    /**
+     * 查询课程平均分
+     *
+     * @param examId
+     * @param subjectCode
+     */
+    @Query(value = "select avg(s.objectiveScore + s.subjectiveScore) " +
+            "from ExamStudent s where s.examId = ?1 and s.subjectCode = ?2 ")
+    Double querySubjectAvgScore(Integer examId, String subjectCode);
+
+}

+ 27 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/dao/ReportSubjectGroupDao.java

@@ -0,0 +1,27 @@
+package cn.com.qmth.stmms.biz.report.dao;
+
+import cn.com.qmth.stmms.biz.report.model.ReportSubjectGroup;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.PagingAndSortingRepository;
+
+import java.util.List;
+
+/**
+ * 大题成绩分析 Dao
+ *
+ * @author xuwenjin
+ * @date 2019-04-18
+ */
+public interface ReportSubjectGroupDao
+        extends PagingAndSortingRepository<ReportSubjectGroup, Integer>, JpaSpecificationExecutor<ReportSubjectGroup> {
+
+    void deleteByExamId(Integer exmaId);
+
+    @Query("select q.mainNumber,q.mainTitle,count(q.mainNumber) as subNumber from ExamQuestion q where q.examId=?1 and q.subjectCode=?2 and q.objective=?3 group by q.mainNumber,q.mainTitle  "
+            + "order by q.mainNumber")
+    public List<Object[]> countGroupByMainNum(Integer examId, String subjectCode,
+                                              boolean objective);
+
+
+}

+ 19 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/dao/ReportSubjectQuestionDao.java

@@ -0,0 +1,19 @@
+package cn.com.qmth.stmms.biz.report.dao;
+
+import cn.com.qmth.stmms.biz.report.model.ReportSubjectQuestion;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+import org.springframework.data.repository.PagingAndSortingRepository;
+
+/**
+ * 客、主观题分析 Dao
+ *
+ * @author xuwenjin
+ * @date 2019-04-17
+ */
+public interface ReportSubjectQuestionDao
+        extends PagingAndSortingRepository<ReportSubjectQuestion, Integer>, JpaSpecificationExecutor<ReportSubjectQuestion> {
+
+    void deleteByExamId(Integer exmaId);
+
+
+}

+ 34 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/dao/ReportSubjectRangeDao.java

@@ -0,0 +1,34 @@
+package cn.com.qmth.stmms.biz.report.dao;
+
+import cn.com.qmth.stmms.biz.report.model.ReportSubjectRange;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.PagingAndSortingRepository;
+
+import java.util.List;
+
+/**
+ * 课程分段统计 Dao
+ *
+ * @author xuwenjin
+ * @date 2019-04-19
+ */
+public interface ReportSubjectRangeDao
+        extends PagingAndSortingRepository<ReportSubjectRange, Integer>, JpaSpecificationExecutor<ReportSubjectRange> {
+
+    void deleteByExamId(Integer exmaId);
+
+    @Query("select s.subjectCode,s.subjectName,s.subjectLevel,"
+            + "sum(case when ((case when s.objectiveScore is null then 0 else s.objectiveScore end) + (case when s.subjectiveScore is null then 0 else s.subjectiveScore end)) between 0 and 49.9 then 1 else 0 end),"
+            + "sum(case when ((case when s.objectiveScore is null then 0 else s.objectiveScore end) + (case when s.subjectiveScore is null then 0 else s.subjectiveScore end)) between 50 and 59.9 then 1 else 0 end) ,"
+            + "sum(case when ((case when s.objectiveScore is null then 0 else s.objectiveScore end) + (case when s.subjectiveScore is null then 0 else s.subjectiveScore end)) between 60 and 69.9 then 1 else 0 end) ,"
+            + "sum(case when ((case when s.objectiveScore is null then 0 else s.objectiveScore end) + (case when s.subjectiveScore is null then 0 else s.subjectiveScore end)) between 70 and 79.9 then 1 else 0 end) ,"
+            + "sum(case when ((case when s.objectiveScore is null then 0 else s.objectiveScore end) + (case when s.subjectiveScore is null then 0 else s.subjectiveScore end)) between 80 and 89.9 then 1 else 0 end) ,"
+            + "sum(case when ((case when s.objectiveScore is null then 0 else s.objectiveScore end) + (case when s.subjectiveScore is null then 0 else s.subjectiveScore end)) between 90 and 100 then 1 else 0 end),"
+            + "sum(case when ((case when s.objectiveScore is null then 0 else s.objectiveScore end) + (case when s.subjectiveScore is null then 0 else s.subjectiveScore end)) between 0 and 59.9 then 1 else 0 end), "
+            + "sum(case when ((case when s.objectiveScore is null then 0 else s.objectiveScore end) + (case when s.subjectiveScore is null then 0 else s.subjectiveScore end)) between 60 and 100 then 1 else 0 end), "
+            + "count(s)  from ExamStudent s where s.examId=?1 and s.upload=true  and s.absent=false  group by s.subjectCode,s.subjectName,s.subjectLevel")
+    public List<Object[]> queryRangeSubjectByExamId(Integer examId);
+
+
+}

+ 44 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/dao/ReportSubjectTeacherClassDao.java

@@ -0,0 +1,44 @@
+package cn.com.qmth.stmms.biz.report.dao;
+
+import cn.com.qmth.stmms.biz.report.model.ReportSubjectTeacherClass;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.PagingAndSortingRepository;
+
+import java.util.List;
+
+/**
+ * 课程老师班级成绩分析 Dao
+ *
+ * @author xuwenjin
+ * @date 2019-04-17
+ */
+public interface ReportSubjectTeacherClassDao
+        extends PagingAndSortingRepository<ReportSubjectTeacherClass, Integer>, JpaSpecificationExecutor<ReportSubjectTeacherClass> {
+
+    void deleteByExamId(Integer exmaId);
+
+
+    /**
+     * 获取课程老师班级成绩 分析数据
+     *
+     * @param examId
+     * @param subjectCode
+     */
+    @Query(value = "SELECT " +
+            "s.teacher," +
+            "s.className," +
+            "count(s) - sum( CASE WHEN s.absent = true THEN 1 ELSE 0 END ) ," +
+            "sum( CASE WHEN ( s.objectiveScore + s.subjectiveScore ) >= e.passScore THEN 1 ELSE 0 END ) ," +
+            "sum( CASE WHEN ( s.objectiveScore + s.subjectiveScore ) >= e.excellentScore THEN 1 ELSE 0 END ) ," +
+            "max( s.objectiveScore + s.subjectiveScore ) ," +
+            "min( s.objectiveScore + s.subjectiveScore ) ," +
+            "avg(s.objectiveScore + s.subjectiveScore ) " +
+            "FROM ExamStudent s , Exam e " +
+            "where s.examId = e.id " +
+            "and s.examId = ?1 " +
+            "AND s.subjectCode = ?2  and s.teacher is not null and s.className is not null " +
+            "GROUP BY s.teacher,s.className")
+    List<Object[]> queryReportSubjectTeacherClassData(Integer examId, String subjectCode);
+
+}

+ 43 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/dao/ReportSubjectTeacherDao.java

@@ -0,0 +1,43 @@
+package cn.com.qmth.stmms.biz.report.dao;
+
+import cn.com.qmth.stmms.biz.report.model.ReportSubjectTeacher;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.PagingAndSortingRepository;
+
+import java.util.List;
+
+/**
+ * 课程老师成绩分析 Dao
+ *
+ * @author xuwenjin
+ * @date 2019-04-16
+ */
+public interface ReportSubjectTeacherDao
+        extends PagingAndSortingRepository<ReportSubjectTeacher, Integer>, JpaSpecificationExecutor<ReportSubjectTeacher> {
+
+    void deleteByExamId(Integer exmaId);
+
+
+    /**
+     * 获取课程老师分析数据
+     *
+     * @param examId      考试Id
+     * @param subjectCode 课程编码
+     */
+    @Query(value = "SELECT " +
+            "s.teacher," +
+            "count(s) - sum( CASE WHEN s.absent = true THEN 1 ELSE 0 END ) ," +
+            "sum( CASE WHEN ( s.objectiveScore + s.subjectiveScore ) >= e.passScore THEN 1 ELSE 0 END ) ," +
+            "sum( CASE WHEN ( s.objectiveScore + s.subjectiveScore ) >= e.excellentScore THEN 1 ELSE 0 END ) ," +
+            "max( s.objectiveScore + s.subjectiveScore ) ," +
+            "min( s.objectiveScore + s.subjectiveScore ) ," +
+            "avg( s.objectiveScore + s.subjectiveScore ) " +
+            "FROM ExamStudent s , Exam e " +
+            "where s.examId = e.id " +
+            "and s.examId = ?1 " +
+            "AND s.subjectCode = ?2  and s.teacher is not null " +
+            "GROUP BY s.teacher")
+    List<Object[]> queryReportSubjectTeacherData(Integer examId, String subjectCode);
+
+}

+ 202 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/model/ReportSubject.java

@@ -0,0 +1,202 @@
+package cn.com.qmth.stmms.biz.report.model;
+
+import javax.persistence.*;
+import java.io.Serializable;
+
+/**
+ * 课程总量分析
+ * 
+ * @author xuwenjin
+ * @date 2019-04-11
+ *
+ */
+@Entity
+@Table(name = "s_basic_subject")
+public class ReportSubject implements Serializable {
+
+	private static final long serialVersionUID = -1596478079357284914L;
+
+	/**
+	 * 主键
+	 */
+	@Id
+	@GeneratedValue
+	private Integer id;
+
+	/**
+	 * 考试id
+	 */
+	@Column(name = "exam_id")
+	private Integer examId;
+
+	/**
+	 * 课程编号
+	 */
+	@Column(name = "subject_code")
+	private String subjectCode;
+
+	/**
+	 * 课程名称
+	 */
+	@Column(name = "subject_name")
+	private String subjectName;
+
+	/**
+	 * 最高分
+	 */
+	@Column(name = "max_score")
+	private Double maxScore;
+
+	/**
+	 * 最低分
+	 */
+	@Column(name = "min_score")
+	private Double minScore;
+
+	/**
+	 * 平均分
+	 */
+	@Column(name = "avg_score")
+	private Double avgScore;
+
+	/**
+	 * 报考人数
+	 */
+	@Column(name = "total_count")
+	private Integer totalCount;
+
+	/**
+	 * 及格人数
+	 */
+	@Column(name = "pass_count")
+	private Integer passCount;
+
+	/**
+	 * 及格率
+	 */
+	@Column(name = "pass_rate")
+	private Double passRate;
+
+	/**
+	 * 缺考人数
+	 */
+	@Column(name = "absent_count")
+	private Integer absentCount;
+
+	/**
+	 * 违纪人数
+	 */
+	@Column(name = "breach_count")
+	private Integer breachCount;
+
+	/**
+	 * 实考人数
+	 */
+	@Column(name = "reality_count")
+	private Integer realityCount;
+
+	public Integer getId() {
+		return id;
+	}
+
+	public void setId(Integer id) {
+		this.id = id;
+	}
+
+	public Integer getExamId() {
+		return examId;
+	}
+
+	public void setExamId(Integer examId) {
+		this.examId = examId;
+	}
+
+	public String getSubjectCode() {
+		return subjectCode;
+	}
+
+	public void setSubjectCode(String subjectCode) {
+		this.subjectCode = subjectCode;
+	}
+
+	public String getSubjectName() {
+		return subjectName;
+	}
+
+	public void setSubjectName(String subjectName) {
+		this.subjectName = subjectName;
+	}
+
+	public Double getMaxScore() {
+		return maxScore;
+	}
+
+	public void setMaxScore(Double maxScore) {
+		this.maxScore = maxScore;
+	}
+
+	public Double getMinScore() {
+		return minScore;
+	}
+
+	public void setMinScore(Double minScore) {
+		this.minScore = minScore;
+	}
+
+	public Double getAvgScore() {
+		return avgScore;
+	}
+
+	public void setAvgScore(Double avgScore) {
+		this.avgScore = avgScore;
+	}
+
+	public Integer getTotalCount() {
+		return totalCount;
+	}
+
+	public void setTotalCount(Integer totalCount) {
+		this.totalCount = totalCount;
+	}
+
+	public Integer getPassCount() {
+		return passCount;
+	}
+
+	public void setPassCount(Integer passCount) {
+		this.passCount = passCount;
+	}
+
+	public Double getPassRate() {
+		return passRate;
+	}
+
+	public void setPassRate(Double passRate) {
+		this.passRate = passRate;
+	}
+
+	public Integer getAbsentCount() {
+		return absentCount;
+	}
+
+	public void setAbsentCount(Integer absentCount) {
+		this.absentCount = absentCount;
+	}
+
+	public Integer getBreachCount() {
+		return breachCount;
+	}
+
+	public void setBreachCount(Integer breachCount) {
+		this.breachCount = breachCount;
+	}
+
+	public Integer getRealityCount() {
+		return realityCount;
+	}
+
+	public void setRealityCount(Integer realityCount) {
+		this.realityCount = realityCount;
+	}
+
+}

+ 186 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/model/ReportSubjectClass.java

@@ -0,0 +1,186 @@
+package cn.com.qmth.stmms.biz.report.model;
+
+import javax.persistence.*;
+import java.io.Serializable;
+
+/**
+ * 课程班级成绩分析
+ *
+ * @author xuwenjin
+ * @date 2019-04-12
+ */
+@Entity
+@Table(name = "s_basic_subject_class")
+public class ReportSubjectClass implements Serializable {
+
+    private static final long serialVersionUID = 1932022687226092788L;
+
+    /**
+     * 主键
+     */
+    @Id
+    @GeneratedValue
+    private Integer id;
+
+    /**
+     * 考试id
+     */
+    @Column(name = "exam_id")
+    private Integer examId;
+
+    /**
+     * 课程编号
+     */
+    @Column(name = "subject_code")
+    private String subjectCode;
+
+    /**
+     * 课程名称
+     */
+    @Column(name = "subject_name")
+    private String subjectName;
+
+    /**
+     * 班级
+     */
+    @Column(name = "class_name")
+    private String className;
+
+    /**
+     * 最高分
+     */
+    @Column(name = "max_score")
+    private Double maxScore;
+
+    /**
+     * 最低分
+     */
+    @Column(name = "min_score")
+    private Double minScore;
+    /**
+     * 及格人数
+     */
+    @Column(name = "pass_count")
+    private int passCount;
+
+    /**
+     * 及格率
+     */
+    @Column(name = "pass_rate")
+    private Double passRate;
+
+    /**
+     * 优秀数
+     */
+    @Column(name = "excellent_count")
+    private int excellentCount;
+
+    /**
+     * 优秀率
+     */
+    @Column(name = "excellent_rate")
+    private Double excellentRate;
+
+    /**
+     * 平均分
+     */
+    @Column(name = "avg_score")
+    private Double avgScore;
+
+    public Integer getId() {
+        return id;
+    }
+
+    public void setId(Integer id) {
+        this.id = id;
+    }
+
+    public Integer getExamId() {
+        return examId;
+    }
+
+    public void setExamId(Integer examId) {
+        this.examId = examId;
+    }
+
+    public String getSubjectCode() {
+        return subjectCode;
+    }
+
+    public void setSubjectCode(String subjectCode) {
+        this.subjectCode = subjectCode;
+    }
+
+    public String getSubjectName() {
+        return subjectName;
+    }
+
+    public void setSubjectName(String subjectName) {
+        this.subjectName = subjectName;
+    }
+
+    public String getClassName() {
+        return className;
+    }
+
+    public void setClassName(String className) {
+        this.className = className;
+    }
+
+    public Double getMaxScore() {
+        return maxScore;
+    }
+
+    public void setMaxScore(Double maxScore) {
+        this.maxScore = maxScore;
+    }
+
+    public Double getMinScore() {
+        return minScore;
+    }
+
+    public void setMinScore(Double minScore) {
+        this.minScore = minScore;
+    }
+
+    public int getPassCount() {
+        return passCount;
+    }
+
+    public void setPassCount(int passCount) {
+        this.passCount = passCount;
+    }
+
+    public Double getPassRate() {
+        return passRate;
+    }
+
+    public void setPassRate(Double passRate) {
+        this.passRate = passRate;
+    }
+
+    public int getExcellentCount() {
+        return excellentCount;
+    }
+
+    public void setExcellentCount(int excellentCount) {
+        this.excellentCount = excellentCount;
+    }
+
+    public Double getExcellentRate() {
+        return excellentRate;
+    }
+
+    public void setExcellentRate(Double excellentRate) {
+        this.excellentRate = excellentRate;
+    }
+
+    public Double getAvgScore() {
+        return avgScore;
+    }
+
+    public void setAvgScore(Double avgScore) {
+        this.avgScore = avgScore;
+    }
+
+}

+ 174 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/model/ReportSubjectCollege.java

@@ -0,0 +1,174 @@
+package cn.com.qmth.stmms.biz.report.model;
+
+import javax.persistence.*;
+import java.io.Serializable;
+
+/**
+ * 课程学院分析
+ *
+ * @author xuwenjin
+ * @date 2019-04-11
+ */
+@Entity
+@Table(name = "s_basic_subject_college")
+public class ReportSubjectCollege implements Serializable {
+
+    private static final long serialVersionUID = 3030910032864476591L;
+
+    /**
+     * 主键
+     */
+    @Id
+    @GeneratedValue
+    private Integer id;
+
+    /**
+     * 考试id
+     */
+    @Column(name = "exam_id")
+    private Integer examId;
+
+    /**
+     * 课程编号
+     */
+    @Column(name = "subject_code")
+    private String subjectCode;
+
+    /**
+     * 课程名称
+     */
+    @Column(name = "subject_name")
+    private String subjectName;
+
+    /**
+     * 学院名称
+     */
+    @Column(name = "college_name")
+    private String collegeName;
+
+    /**
+     * 最高分
+     */
+    @Column(name = "max_score")
+    private Double maxScore;
+
+    /**
+     * 最低分
+     */
+    @Column(name = "min_score")
+    private Double minScore;
+
+    /**
+     * 平均分
+     */
+    @Column(name = "avg_score")
+    private Double avgScore;
+
+    /**
+     * 及格率
+     */
+    @Column(name = "pass_rate")
+    private Double passRate;
+
+
+    /**
+     * 及格数
+     */
+    @Column(name = "pass_count")
+    private Integer passCount;
+
+    /**
+     * 优秀率
+     */
+    @Column(name = "excellent_rate")
+    private Double excellentRate;
+
+
+    public Integer getId() {
+        return id;
+    }
+
+    public void setId(Integer id) {
+        this.id = id;
+    }
+
+    public Integer getExamId() {
+        return examId;
+    }
+
+    public void setExamId(Integer examId) {
+        this.examId = examId;
+    }
+
+    public String getSubjectCode() {
+        return subjectCode;
+    }
+
+    public void setSubjectCode(String subjectCode) {
+        this.subjectCode = subjectCode;
+    }
+
+    public String getSubjectName() {
+        return subjectName;
+    }
+
+    public void setSubjectName(String subjectName) {
+        this.subjectName = subjectName;
+    }
+
+    public String getCollegeName() {
+        return collegeName;
+    }
+
+    public void setCollegeName(String collegeName) {
+        this.collegeName = collegeName;
+    }
+
+    public Double getMaxScore() {
+        return maxScore;
+    }
+
+    public void setMaxScore(Double maxScore) {
+        this.maxScore = maxScore;
+    }
+
+    public Double getMinScore() {
+        return minScore;
+    }
+
+    public void setMinScore(Double minScore) {
+        this.minScore = minScore;
+    }
+
+    public Double getAvgScore() {
+        return avgScore;
+    }
+
+    public void setAvgScore(Double avgScore) {
+        this.avgScore = avgScore;
+    }
+
+    public Integer getPassCount() {
+        return passCount;
+    }
+
+    public void setPassCount(Integer passCount) {
+        this.passCount = passCount;
+    }
+
+    public Double getPassRate() {
+        return passRate;
+    }
+
+    public void setPassRate(Double passRate) {
+        this.passRate = passRate;
+    }
+
+    public Double getExcellentRate() {
+        return excellentRate;
+    }
+
+    public void setExcellentRate(Double excellentRate) {
+        this.excellentRate = excellentRate;
+    }
+}

+ 202 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/model/ReportSubjectGroup.java

@@ -0,0 +1,202 @@
+package cn.com.qmth.stmms.biz.report.model;
+
+import javax.persistence.*;
+import java.io.Serializable;
+
+/**
+ * 大题维度分析
+ * 
+ * @author xuwenjin
+ * @date 2019-04-12
+ *
+ */
+@Entity
+@Table(name = "s_basic_group")
+public class ReportSubjectGroup implements Serializable {
+
+	private static final long serialVersionUID = 3619846310455325739L;
+
+	/**
+	 * 主键
+	 */
+	@Id
+	@GeneratedValue
+	private Integer id;
+
+	/**
+	 * 考试id
+	 */
+	@Column(name = "exam_id")
+	private Integer examId;
+
+	/**
+	 * 课程编号
+	 */
+	@Column(name = "subject_code")
+	private String subjectCode;
+
+	/**
+	 * 课程名称
+	 */
+	@Column(name = "subject_name")
+	private String subjectName;
+
+	/**
+	 * 大题型
+	 */
+	@Column(name = "group_name")
+	private String groupName;
+
+	/**
+	 * 最高分
+	 */
+	@Column(name = "max_score")
+	private Double maxScore;
+
+	/**
+	 * 最低分
+	 */
+	@Column(name = "min_score")
+	private Double minScore;
+
+	/**
+	 * 平均分
+	 */
+	@Column(name = "avg_score")
+	private Double avgScore;
+
+	/**
+	 * 满分
+	 */
+	@Column(name = "total_score")
+	private Double totalScore;
+
+	/**
+	 * 标准差
+	 */
+	@Column(name = "sd")
+	private Double SD;
+
+	/**
+	 * 差异系数
+	 */
+	@Column(name = "cv")
+	private Double CV;
+
+	/**
+	 * 零分人数
+	 */
+	@Column(name = "zero_count")
+	private Integer zeroCount;
+
+	/**
+	 * 满分人数
+	 */
+	@Column(name = "full_count")
+	private Integer fullCount;
+
+	public Integer getId() {
+		return id;
+	}
+
+	public void setId(Integer id) {
+		this.id = id;
+	}
+
+	public Integer getExamId() {
+		return examId;
+	}
+
+	public void setExamId(Integer examId) {
+		this.examId = examId;
+	}
+
+	public String getSubjectCode() {
+		return subjectCode;
+	}
+
+	public void setSubjectCode(String subjectCode) {
+		this.subjectCode = subjectCode;
+	}
+
+	public String getSubjectName() {
+		return subjectName;
+	}
+
+	public void setSubjectName(String subjectName) {
+		this.subjectName = subjectName;
+	}
+
+	public String getGroupName() {
+		return groupName;
+	}
+
+	public void setGroupName(String groupName) {
+		this.groupName = groupName;
+	}
+
+	public Double getMaxScore() {
+		return maxScore;
+	}
+
+	public void setMaxScore(Double maxScore) {
+		this.maxScore = maxScore;
+	}
+
+	public Double getMinScore() {
+		return minScore;
+	}
+
+	public void setMinScore(Double minScore) {
+		this.minScore = minScore;
+	}
+
+	public Double getAvgScore() {
+		return avgScore;
+	}
+
+	public void setAvgScore(Double avgScore) {
+		this.avgScore = avgScore;
+	}
+
+	public Double getTotalScore() {
+		return totalScore;
+	}
+
+	public void setTotalScore(Double totalScore) {
+		this.totalScore = totalScore;
+	}
+
+	public Double getSD() {
+		return SD;
+	}
+
+	public void setSD(Double sD) {
+		SD = sD;
+	}
+
+	public Double getCV() {
+		return CV;
+	}
+
+	public void setCV(Double cV) {
+		CV = cV;
+	}
+
+	public Integer getZeroCount() {
+		return zeroCount;
+	}
+
+	public void setZeroCount(Integer zeroCount) {
+		this.zeroCount = zeroCount;
+	}
+
+	public Integer getFullCount() {
+		return fullCount;
+	}
+
+	public void setFullCount(Integer fullCount) {
+		this.fullCount = fullCount;
+	}
+
+}

+ 171 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/model/ReportSubjectQuestion.java

@@ -0,0 +1,171 @@
+package cn.com.qmth.stmms.biz.report.model;
+
+import javax.persistence.*;
+import java.io.Serializable;
+
+/**
+ * 客观 主观题 成绩分析
+ *
+ * @author xuwenjin
+ * @date 2019-04-12
+ */
+@Entity
+@Table(name = "s_basic_question")
+public class ReportSubjectQuestion implements Serializable {
+
+    private static final long serialVersionUID = 6724909968773149817L;
+
+    /**
+     * 主键
+     */
+    @Id
+    @GeneratedValue
+    private Integer id;
+
+    /**
+     * 考试id
+     */
+    @Column(name = "exam_id")
+    private Integer examId;
+
+    /**
+     * 课程编号
+     */
+    @Column(name = "subject_code")
+    private String subjectCode;
+
+    /**
+     * 课程名称
+     */
+    @Column(name = "subject_name")
+    private String subjectName;
+    /**
+     * 题目名称
+     */
+    @Column(name = "question_Name", length = 128)
+    private String questionName;
+
+    /**
+     * 总分
+     */
+    @Column(name = "total_score")
+    private Double totalScore;
+
+    /**
+     * 平均分
+     */
+    @Column(name = "avg_score")
+    private Double avgScore;
+
+    /**
+     * 标准差
+     */
+    @Column(name = "sd")
+    private Double sd;
+
+    /**
+     * 得分率
+     */
+    @Column(name = "score_rate")
+    private Double scoreRate;
+
+    /**
+     * 满分率
+     */
+    @Column(name = "full_score_rate")
+    private Double fullScoreRate;
+
+    /**
+     * 是否客观
+     */
+    @Column(name = "objective")
+    private Boolean objective;
+
+    public Integer getId() {
+        return id;
+    }
+
+    public void setId(Integer id) {
+        this.id = id;
+    }
+
+    public Integer getExamId() {
+        return examId;
+    }
+
+    public void setExamId(Integer examId) {
+        this.examId = examId;
+    }
+
+    public String getSubjectCode() {
+        return subjectCode;
+    }
+
+    public void setSubjectCode(String subjectCode) {
+        this.subjectCode = subjectCode;
+    }
+
+    public String getSubjectName() {
+        return subjectName;
+    }
+
+    public void setSubjectName(String subjectName) {
+        this.subjectName = subjectName;
+    }
+
+    public String getQuestionName() {
+        return questionName;
+    }
+
+    public void setQuestionName(String questionName) {
+        this.questionName = questionName;
+    }
+
+    public Double getTotalScore() {
+        return totalScore;
+    }
+
+    public void setTotalScore(Double totalScore) {
+        this.totalScore = totalScore;
+    }
+
+    public Double getAvgScore() {
+        return avgScore;
+    }
+
+    public void setAvgScore(Double avgScore) {
+        this.avgScore = avgScore;
+    }
+
+    public Double getSd() {
+        return sd;
+    }
+
+    public void setSd(Double sd) {
+        this.sd = sd;
+    }
+
+    public Double getScoreRate() {
+        return scoreRate;
+    }
+
+    public void setScoreRate(Double scoreRate) {
+        this.scoreRate = scoreRate;
+    }
+
+    public Double getFullScoreRate() {
+        return fullScoreRate;
+    }
+
+    public void setFullScoreRate(Double fullScoreRate) {
+        this.fullScoreRate = fullScoreRate;
+    }
+
+    public Boolean getObjective() {
+        return objective;
+    }
+
+    public void setObjective(Boolean objective) {
+        this.objective = objective;
+    }
+}

+ 282 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/model/ReportSubjectRange.java

@@ -0,0 +1,282 @@
+package cn.com.qmth.stmms.biz.report.model;
+
+import javax.persistence.*;
+import java.io.Serializable;
+
+/**
+ * 分段统计
+ *
+ * @author xuwenjin
+ * @date 2019-04-19
+ */
+@Entity
+@Table(name = "s_range_subject")
+public class ReportSubjectRange implements Serializable {
+
+    private static final long serialVersionUID = -6460526419770818333L;
+
+    /**
+     * 主键
+     */
+    @Id
+    @GeneratedValue
+    private Integer id;
+
+    /**
+     * 考试id
+     */
+    @Column(name = "exam_id")
+    private Integer examId;
+
+    /**
+     * 课程编号
+     */
+    @Column(name = "subject_code")
+    private String subjectCode;
+
+    /**
+     * 科目名称
+     */
+    @Column(name = "subject_name")
+    private String subjectName;
+
+    /**
+     * 层次
+     */
+    @Column(name = "subject_level")
+    private String level;
+
+    /**
+     * 0-49数量
+     */
+    private Integer count0_49;
+
+    /**
+     * 0-49占比
+     */
+    private double percent0_49;
+
+    private Integer count50_59;
+
+    private double percent50_59;
+
+    private Integer count60_69;
+
+    private double percent60_69;
+
+    private Integer count70_79;
+
+    private double percent70_79;
+
+    private Integer count80_89;
+
+    private double percent80_89;
+
+    private Integer count90_100;
+
+    private double percent90_100;
+
+    /**
+     * 小于60数量
+     */
+    private Integer lt60;
+
+    /**
+     * 小于60占比
+     */
+    private double percent_lt60;
+
+    /**
+     * 大于等于60数量
+     */
+    private Integer mte60;
+
+    /**
+     * 大于等于60占比
+     */
+    private double percent_mte60;
+
+    /**
+     * 总数
+     */
+    private Integer totalCount;
+
+
+    public String getSubjectName() {
+        return subjectName;
+    }
+
+    public void setSubjectName(String subjectName) {
+        this.subjectName = subjectName;
+    }
+
+    public String getLevel() {
+        return level;
+    }
+
+    public void setLevel(String level) {
+        this.level = level;
+    }
+
+    public Integer getCount0_49() {
+        return count0_49;
+    }
+
+    public void setCount0_49(Integer count0_49) {
+        this.count0_49 = count0_49;
+    }
+
+    public double getPercent0_49() {
+        return percent0_49;
+    }
+
+    public void setPercent0_49(double percent0_49) {
+        this.percent0_49 = percent0_49;
+    }
+
+    public Integer getCount50_59() {
+        return count50_59;
+    }
+
+    public void setCount50_59(Integer count50_59) {
+        this.count50_59 = count50_59;
+    }
+
+    public double getPercent50_59() {
+        return percent50_59;
+    }
+
+    public void setPercent50_59(double percent50_59) {
+        this.percent50_59 = percent50_59;
+    }
+
+    public Integer getCount60_69() {
+        return count60_69;
+    }
+
+    public void setCount60_69(Integer count60_69) {
+        this.count60_69 = count60_69;
+    }
+
+    public double getPercent60_69() {
+        return percent60_69;
+    }
+
+    public void setPercent60_69(double percent60_69) {
+        this.percent60_69 = percent60_69;
+    }
+
+    public Integer getCount70_79() {
+        return count70_79;
+    }
+
+    public void setCount70_79(Integer count70_79) {
+        this.count70_79 = count70_79;
+    }
+
+    public double getPercent70_79() {
+        return percent70_79;
+    }
+
+    public void setPercent70_79(double percent70_79) {
+        this.percent70_79 = percent70_79;
+    }
+
+    public Integer getCount80_89() {
+        return count80_89;
+    }
+
+    public void setCount80_89(Integer count80_89) {
+        this.count80_89 = count80_89;
+    }
+
+    public double getPercent80_89() {
+        return percent80_89;
+    }
+
+    public void setPercent80_89(double percent80_89) {
+        this.percent80_89 = percent80_89;
+    }
+
+    public Integer getCount90_100() {
+        return count90_100;
+    }
+
+    public void setCount90_100(Integer count90_100) {
+        this.count90_100 = count90_100;
+    }
+
+    public double getPercent90_100() {
+        return percent90_100;
+    }
+
+    public void setPercent90_100(double percent90_100) {
+        this.percent90_100 = percent90_100;
+    }
+
+    public Integer getLt60() {
+        return lt60;
+    }
+
+    public void setLt60(Integer lt60) {
+        this.lt60 = lt60;
+    }
+
+
+    public Integer getMte60() {
+        return mte60;
+    }
+
+    public void setMte60(Integer mte60) {
+        this.mte60 = mte60;
+    }
+
+    public double getPercent_lt60() {
+        return percent_lt60;
+    }
+
+    public void setPercent_lt60(double percent_lt60) {
+        this.percent_lt60 = percent_lt60;
+    }
+
+    public double getPercent_mte60() {
+        return percent_mte60;
+    }
+
+    public void setPercent_mte60(double percent_mte60) {
+        this.percent_mte60 = percent_mte60;
+    }
+
+    public Integer getTotalCount() {
+        return totalCount;
+    }
+
+    public void setTotalCount(Integer totalCount) {
+        this.totalCount = totalCount;
+    }
+
+
+    public Integer getId() {
+        return id;
+    }
+
+    public void setId(Integer id) {
+        this.id = id;
+    }
+
+    public Integer getExamId() {
+        return examId;
+    }
+
+    public void setExamId(Integer examId) {
+        this.examId = examId;
+    }
+
+    public String getSubjectCode() {
+        return subjectCode;
+    }
+
+    public void setSubjectCode(String subjectCode) {
+        this.subjectCode = subjectCode;
+    }
+}

+ 215 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/model/ReportSubjectTeacher.java

@@ -0,0 +1,215 @@
+package cn.com.qmth.stmms.biz.report.model;
+
+import javax.persistence.*;
+import java.io.Serializable;
+
+/**
+ * 课程任课老师成绩分析
+ * 
+ * @author xuwenjin
+ * @date 2019-04-12
+ *
+ */
+@Entity
+@Table(name = "s_basic_subject_teacher")
+public class ReportSubjectTeacher implements Serializable {
+
+	private static final long serialVersionUID = -8747256777581891978L;
+
+	/**
+	 * 主键
+	 */
+	@Id
+	@GeneratedValue
+	private Integer id;
+
+	/**
+	 * 考试id
+	 */
+	@Column(name = "exam_id")
+	private Integer examId;
+
+	/**
+	 * 课程编号
+	 */
+	@Column(name = "subject_code")
+	private String subjectCode;
+
+	/**
+	 * 课程名称
+	 */
+	@Column(name = "subject_name")
+	private String subjectName;
+
+	/**
+	 * 教师
+	 */
+	@Column(name = "teacher_name")
+	private String teacherName;
+
+	/**
+	 * 实考人数
+	 */
+	@Column(name = "reality_count")
+	private int realityCount;
+
+	/**
+	 * 最高分
+	 */
+	@Column(name = "max_score")
+	private Double maxScore;
+
+	/**
+	 * 最低分
+	 */
+	@Column(name = "min_score")
+	private Double minScore;
+	/**
+	 * 及格人数
+	 */
+	@Column(name = "pass_count")
+	private int passCount;
+
+	/**
+	 * 及格率
+	 */
+	@Column(name = "pass_rate")
+	private Double passRate;
+
+	/**
+	 * 优秀数
+	 */
+	@Column(name = "excellent_count")
+	private int excellentCount;
+
+	/**
+	 * 优秀率
+	 */
+	@Column(name = "excellent_rate")
+	private Double excellentRate;
+
+	/**
+	 * 平均分
+	 */
+	@Column(name = "avg_score")
+	private Double avgScore;
+
+	/**
+	 * 相对平均分
+	 */
+	@Column(name = "relative_avg_score")
+	private Double relativeAvgScore;
+
+	public Integer getId() {
+		return id;
+	}
+
+	public void setId(Integer id) {
+		this.id = id;
+	}
+
+	public Integer getExamId() {
+		return examId;
+	}
+
+	public void setExamId(Integer examId) {
+		this.examId = examId;
+	}
+
+	public String getSubjectCode() {
+		return subjectCode;
+	}
+
+	public void setSubjectCode(String subjectCode) {
+		this.subjectCode = subjectCode;
+	}
+
+	public String getSubjectName() {
+		return subjectName;
+	}
+
+	public void setSubjectName(String subjectName) {
+		this.subjectName = subjectName;
+	}
+
+	public String getTeacherName() {
+		return teacherName;
+	}
+
+	public void setTeacherName(String teacherName) {
+		this.teacherName = teacherName;
+	}
+
+	public int getRealityCount() {
+		return realityCount;
+	}
+
+	public void setRealityCount(int realityCount) {
+		this.realityCount = realityCount;
+	}
+
+	public Double getMaxScore() {
+		return maxScore;
+	}
+
+	public void setMaxScore(Double maxScore) {
+		this.maxScore = maxScore;
+	}
+
+	public Double getMinScore() {
+		return minScore;
+	}
+
+	public void setMinScore(Double minScore) {
+		this.minScore = minScore;
+	}
+
+	public int getPassCount() {
+		return passCount;
+	}
+
+	public void setPassCount(int passCount) {
+		this.passCount = passCount;
+	}
+
+	public Double getPassRate() {
+		return passRate;
+	}
+
+	public void setPassRate(Double passRate) {
+		this.passRate = passRate;
+	}
+
+	public int getExcellentCount() {
+		return excellentCount;
+	}
+
+	public void setExcellentCount(int excellentCount) {
+		this.excellentCount = excellentCount;
+	}
+
+	public Double getExcellentRate() {
+		return excellentRate;
+	}
+
+	public void setExcellentRate(Double excellentRate) {
+		this.excellentRate = excellentRate;
+	}
+
+	public Double getAvgScore() {
+		return avgScore;
+	}
+
+	public void setAvgScore(Double avgScore) {
+		this.avgScore = avgScore;
+	}
+
+	public Double getRelativeAvgScore() {
+		return relativeAvgScore;
+	}
+
+	public void setRelativeAvgScore(Double relativeAvgScore) {
+		this.relativeAvgScore = relativeAvgScore;
+	}
+
+}

+ 228 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/model/ReportSubjectTeacherClass.java

@@ -0,0 +1,228 @@
+package cn.com.qmth.stmms.biz.report.model;
+
+import javax.persistence.*;
+import java.io.Serializable;
+
+/**
+ * 课程任课老师班级成绩分析
+ *
+ * @author xuwenjin
+ * @date 2019-04-12
+ */
+@Entity
+@Table(name = "s_basic_subject_teacher_class")
+public class ReportSubjectTeacherClass implements Serializable {
+
+    private static final long serialVersionUID = 711106040799843384L;
+
+    /**
+     * 主键
+     */
+    @Id
+    @GeneratedValue
+    private Integer id;
+
+    /**
+     * 考试id
+     */
+    @Column(name = "exam_id")
+    private Integer examId;
+
+    /**
+     * 课程编号
+     */
+    @Column(name = "subject_code")
+    private String subjectCode;
+
+    /**
+     * 课程名称
+     */
+    @Column(name = "subject_name")
+    private String subjectName;
+
+    /**
+     * 教师
+     */
+    @Column(name = "teacher_name")
+    private String teacherName;
+
+    /**
+     * 班级
+     */
+    @Column(name = "class_name")
+    private String className;
+
+    /**
+     * 实考人数
+     */
+    @Column(name = "reality_count")
+    private int realityCount;
+
+    /**
+     * 最高分
+     */
+    @Column(name = "max_score")
+    private Double maxScore;
+
+    /**
+     * 最低分
+     */
+    @Column(name = "min_score")
+    private Double minScore;
+    /**
+     * 及格人数
+     */
+    @Column(name = "pass_count")
+    private int passCount;
+
+    /**
+     * 及格率
+     */
+    @Column(name = "pass_rate")
+    private Double passRate;
+
+    /**
+     * 优秀数
+     */
+    @Column(name = "excellent_count")
+    private int excellentCount;
+
+    /**
+     * 优秀率
+     */
+    @Column(name = "excellent_rate")
+    private Double excellentRate;
+
+    /**
+     * 平均分
+     */
+    @Column(name = "avg_score")
+    private Double avgScore;
+
+    /**
+     * 相对平均分
+     */
+    @Column(name = "relative_avg_score")
+    private Double relativeAvgScore;
+
+    public Integer getId() {
+        return id;
+    }
+
+    public void setId(Integer id) {
+        this.id = id;
+    }
+
+    public Integer getExamId() {
+        return examId;
+    }
+
+    public void setExamId(Integer examId) {
+        this.examId = examId;
+    }
+
+    public String getSubjectCode() {
+        return subjectCode;
+    }
+
+    public void setSubjectCode(String subjectCode) {
+        this.subjectCode = subjectCode;
+    }
+
+    public String getSubjectName() {
+        return subjectName;
+    }
+
+    public void setSubjectName(String subjectName) {
+        this.subjectName = subjectName;
+    }
+
+    public String getTeacherName() {
+        return teacherName;
+    }
+
+    public void setTeacherName(String teacherName) {
+        this.teacherName = teacherName;
+    }
+
+    public String getClassName() {
+        return className;
+    }
+
+    public void setClassName(String className) {
+        this.className = className;
+    }
+
+    public int getRealityCount() {
+        return realityCount;
+    }
+
+    public void setRealityCount(int realityCount) {
+        this.realityCount = realityCount;
+    }
+
+    public Double getMaxScore() {
+        return maxScore;
+    }
+
+    public void setMaxScore(Double maxScore) {
+        this.maxScore = maxScore;
+    }
+
+    public Double getMinScore() {
+        return minScore;
+    }
+
+    public void setMinScore(Double minScore) {
+        this.minScore = minScore;
+    }
+
+    public int getPassCount() {
+        return passCount;
+    }
+
+    public void setPassCount(int passCount) {
+        this.passCount = passCount;
+    }
+
+    public Double getPassRate() {
+        return passRate;
+    }
+
+    public void setPassRate(Double passRate) {
+        this.passRate = passRate;
+    }
+
+    public int getExcellentCount() {
+        return excellentCount;
+    }
+
+    public void setExcellentCount(int excellentCount) {
+        this.excellentCount = excellentCount;
+    }
+
+    public Double getExcellentRate() {
+        return excellentRate;
+    }
+
+    public void setExcellentRate(Double excellentRate) {
+        this.excellentRate = excellentRate;
+    }
+
+    public Double getAvgScore() {
+        return avgScore;
+    }
+
+    public void setAvgScore(Double avgScore) {
+        this.avgScore = avgScore;
+    }
+
+    public Double getRelativeAvgScore() {
+        return relativeAvgScore;
+    }
+
+    public void setRelativeAvgScore(Double relativeAvgScore) {
+        this.relativeAvgScore = relativeAvgScore;
+    }
+
+}

+ 62 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/query/ReportSubjectQuery.java

@@ -0,0 +1,62 @@
+package cn.com.qmth.stmms.biz.report.query;
+
+import cn.com.qmth.stmms.biz.common.BaseQuery;
+
+/**
+ * 课程报表查询query
+ *
+ * @author xuwenjin
+ * @Date 2019-04-12 18:01
+ */
+public class ReportSubjectQuery extends BaseQuery {
+
+    private Integer examId;
+
+    private String subjectCode;
+
+    private String teacherName;
+
+    private String className;
+
+    private Boolean objective;
+
+    public Integer getExamId() {
+        return examId;
+    }
+
+    public void setExamId(Integer examId) {
+        this.examId = examId;
+    }
+
+    public String getSubjectCode() {
+        return subjectCode;
+    }
+
+    public void setSubjectCode(String subjectCode) {
+        this.subjectCode = subjectCode;
+    }
+
+    public String getTeacherName() {
+        return teacherName;
+    }
+
+    public void setTeacherName(String teacherName) {
+        this.teacherName = teacherName;
+    }
+
+    public String getClassName() {
+        return className;
+    }
+
+    public void setClassName(String className) {
+        this.className = className;
+    }
+
+    public Boolean getObjective() {
+        return objective;
+    }
+
+    public void setObjective(Boolean objective) {
+        this.objective = objective;
+    }
+}

+ 16 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/service/ReportService.java

@@ -0,0 +1,16 @@
+package cn.com.qmth.stmms.biz.report.service;
+
+/**
+ * 报表服务 service
+ *
+ * @author xuwenjin
+ * @date 2019-04-22
+ */
+public interface ReportService {
+
+    /**
+     * 生成报表表数据
+     */
+    void generateReportData(Integer examId);
+
+}

+ 22 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/service/ReportSubjectClassService.java

@@ -0,0 +1,22 @@
+package cn.com.qmth.stmms.biz.report.service;
+
+import cn.com.qmth.stmms.biz.report.model.ReportSubjectClass;
+import cn.com.qmth.stmms.biz.report.query.ReportSubjectQuery;
+
+import java.util.List;
+
+/**
+ * 课程班级成绩分析
+ *
+ * @author xuwenjin
+ * @date 2019-04-16
+ */
+public interface ReportSubjectClassService {
+
+    void deleteByExamId(Integer examId);
+
+    List<ReportSubjectClass> findByQuery(ReportSubjectQuery query);
+
+    void saveReportSubjectClassData(Integer examId, String subjectCode);
+
+}

+ 22 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/service/ReportSubjectCollegeService.java

@@ -0,0 +1,22 @@
+package cn.com.qmth.stmms.biz.report.service;
+
+import cn.com.qmth.stmms.biz.report.model.ReportSubjectCollege;
+import cn.com.qmth.stmms.biz.report.query.ReportSubjectQuery;
+
+import java.util.List;
+
+/**
+ * 课程学院分析 service 接口
+ *
+ * @author xuwenjin
+ * @Date 2019-04-16
+ */
+public interface ReportSubjectCollegeService {
+
+    void deleteByExamId(Integer examId);
+
+    List<ReportSubjectCollege> findByQuery(ReportSubjectQuery query);
+
+    void saveReportSubjectCollegeData(Integer examId, String subjectCode);
+
+}

+ 28 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/service/ReportSubjectGroupService.java

@@ -0,0 +1,28 @@
+package cn.com.qmth.stmms.biz.report.service;
+
+import cn.com.qmth.stmms.biz.report.model.ReportSubjectGroup;
+import cn.com.qmth.stmms.biz.report.query.ReportSubjectQuery;
+
+import java.util.List;
+
+/**
+ * 大题统计分析 service 接口
+ *
+ * @author xuwenjin
+ * @Date 2019-04-18
+ */
+public interface ReportSubjectGroupService {
+
+    void deleteByExamId(Integer examId);
+
+    List<ReportSubjectGroup> findByQuery(ReportSubjectQuery query);
+
+    /**
+     * 保存大题统计分析
+     *
+     * @param examId      考试Id
+     * @param subjectCode 科目Code
+     */
+    void saveReportSubjectGroupData(Integer examId, String subjectCode);
+
+}

+ 24 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/service/ReportSubjectQuestionService.java

@@ -0,0 +1,24 @@
+package cn.com.qmth.stmms.biz.report.service;
+
+import cn.com.qmth.stmms.biz.report.model.ReportSubjectQuestion;
+import cn.com.qmth.stmms.biz.report.query.ReportSubjectQuery;
+
+import java.util.List;
+
+/**
+ * 客、主观题分析 service 接口
+ *
+ * @author xuwenjin
+ * @Date 2019-04-17
+ */
+public interface ReportSubjectQuestionService {
+
+    ReportSubjectQuestion save(ReportSubjectQuestion ReportSubjectQuestion);
+
+    void deleteByExamId(Integer examId);
+
+    List<ReportSubjectQuestion> findByQuery(ReportSubjectQuery query);
+
+    void saveReportSubjectObjectiveQuestionData(Integer examId, String subjectCode, Boolean objective);
+
+}

+ 19 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/service/ReportSubjectRangeService.java

@@ -0,0 +1,19 @@
+package cn.com.qmth.stmms.biz.report.service;
+
+import cn.com.qmth.stmms.biz.report.query.ReportSubjectQuery;
+
+/**
+ * 课程分段统计 service 接口
+ *
+ * @author xuwenjin
+ * @Date 2019-04-19
+ */
+public interface ReportSubjectRangeService {
+
+    void deleteByExamId(Integer examId);
+
+    ReportSubjectQuery findByQuery(ReportSubjectQuery query);
+
+    void saveReportRangeSubjectData(Integer examId);
+
+}

+ 22 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/service/ReportSubjectService.java

@@ -0,0 +1,22 @@
+package cn.com.qmth.stmms.biz.report.service;
+
+import cn.com.qmth.stmms.biz.report.model.ReportSubject;
+import cn.com.qmth.stmms.biz.report.query.ReportSubjectQuery;
+
+/**
+ * 课程总量统计 service 接口
+ *
+ * @Date 2019-04-12 17:12
+ * @Created by xuwenjin
+ */
+public interface ReportSubjectService {
+
+    ReportSubject save(ReportSubject reportSubject);
+
+    void deleteByExamId(Integer examId);
+
+    ReportSubjectQuery findByQuery(ReportSubjectQuery query);
+
+    void saveReportSubjectData(Integer examId);
+
+}

+ 22 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/service/ReportSubjectTeacherClassService.java

@@ -0,0 +1,22 @@
+package cn.com.qmth.stmms.biz.report.service;
+
+import cn.com.qmth.stmms.biz.report.model.ReportSubjectTeacherClass;
+import cn.com.qmth.stmms.biz.report.query.ReportSubjectQuery;
+
+import java.util.List;
+
+/**
+ * 课程教师班级 成绩分析
+ *
+ * @author xuwenjin
+ * @date 2019-04-17
+ */
+public interface ReportSubjectTeacherClassService {
+
+    void deleteByExamId(Integer examId);
+
+    List<ReportSubjectTeacherClass> findByQuery(ReportSubjectQuery query);
+
+    void saveReportSubjectTeacherClassData(Integer examId, String subjectCode);
+
+}

+ 22 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/service/ReportSubjectTeacherService.java

@@ -0,0 +1,22 @@
+package cn.com.qmth.stmms.biz.report.service;
+
+import cn.com.qmth.stmms.biz.report.model.ReportSubjectTeacher;
+import cn.com.qmth.stmms.biz.report.query.ReportSubjectQuery;
+
+import java.util.List;
+
+/**
+ * 课程教师成绩分析
+ *
+ * @author xuwenjin
+ * @date 2019-04-16 16:51
+ */
+public interface ReportSubjectTeacherService {
+
+    void deleteByExamId(Integer examId);
+
+    List<ReportSubjectTeacher> findByQuery(ReportSubjectQuery query);
+
+    void saveReportSubjectTeacherData(Integer examId, String subjectCode);
+
+}

+ 125 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/service/impl/ReportServiceImpl.java

@@ -0,0 +1,125 @@
+package cn.com.qmth.stmms.biz.report.service.impl;
+
+import cn.com.qmth.stmms.biz.exam.model.ExamSubject;
+import cn.com.qmth.stmms.biz.exam.service.ExamSubjectService;
+import cn.com.qmth.stmms.biz.report.service.*;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+
+/**
+ * 报表服务 service 实现
+ *
+ * @author xuwenjin
+ * @Date 2019-04-22
+ */
+@Component
+public class ReportServiceImpl implements ReportService {
+
+    @Autowired
+    private ReportSubjectService reportSubjectService;
+
+    @Autowired
+    private ReportSubjectRangeService reportSubjectRangeService;
+
+    @Autowired
+    private ReportSubjectCollegeService reportSubjectCollegeService;
+
+    @Autowired
+    private ReportSubjectTeacherService reportSubjectTeacherService;
+
+    @Autowired
+    private ReportSubjectTeacherClassService reportSubjectTeacherClassService;
+
+    @Autowired
+    private ReportSubjectClassService reportSubjectClassService;
+
+    @Autowired
+    private ReportSubjectQuestionService reportSubjectQuestionService;
+
+    @Autowired
+    private ReportSubjectGroupService reportSubjectGroupService;
+
+    @Autowired
+    private ExamSubjectService examSubjectService;
+
+
+    /**
+     * 生成报表数据
+     *
+     * @param examId 考试id
+     */
+    @Override
+    public void generateReportData(Integer examId) {
+
+        deleteData(examId);
+
+        saveData(examId);
+
+    }
+
+    /**
+     * 删除数据
+     *
+     * @param examId
+     */
+    private void deleteData(Integer examId) {
+
+        reportSubjectService.deleteByExamId(examId);
+
+        reportSubjectRangeService.deleteByExamId(examId);
+
+        reportSubjectCollegeService.deleteByExamId(examId);
+
+        reportSubjectTeacherService.deleteByExamId(examId);
+
+        reportSubjectTeacherClassService.deleteByExamId(examId);
+
+        reportSubjectClassService.deleteByExamId(examId);
+
+        reportSubjectQuestionService.deleteByExamId(examId);
+
+        reportSubjectGroupService.deleteByExamId(examId);
+
+    }
+
+    /**
+     * 重新生成数据
+     *
+     * @param examId
+     */
+    private void saveData(Integer examId) {
+        List<ExamSubject> examSubjects = examSubjectService.list(examId);
+
+        //保存课程总量统计分析
+        reportSubjectService.saveReportSubjectData(examId);
+
+        //保存课程分段统计
+        reportSubjectRangeService.saveReportRangeSubjectData(examId);
+
+        for (ExamSubject subject : examSubjects) {
+            String subjectCode = subject.getCode();
+            //保存学院成绩分析
+            reportSubjectCollegeService.saveReportSubjectCollegeData(examId, subjectCode);
+
+            //保存课程任课老师成绩分析
+            reportSubjectTeacherService.saveReportSubjectTeacherData(examId, subjectCode);
+
+            //保存任课老师班级成绩分析
+            reportSubjectTeacherClassService.saveReportSubjectTeacherClassData(examId, subjectCode);
+
+            //保存成班级成绩分析
+            reportSubjectClassService.saveReportSubjectClassData(examId, subjectCode);
+
+            //保存客观题成绩分析
+            reportSubjectQuestionService.saveReportSubjectObjectiveQuestionData(examId, subjectCode, true);
+
+            //保存主观题成绩分析
+            reportSubjectQuestionService.saveReportSubjectObjectiveQuestionData(examId, subjectCode, false);
+
+            //保存大题型成绩分析
+            reportSubjectGroupService.saveReportSubjectGroupData(examId, subjectCode);
+        }
+    }
+}

+ 88 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/service/impl/ReportSubjectClassServiceImpl.java

@@ -0,0 +1,88 @@
+package cn.com.qmth.stmms.biz.report.service.impl;
+
+import cn.com.qmth.stmms.biz.common.BaseQueryService;
+import cn.com.qmth.stmms.biz.exam.dao.ExamSubjectDao;
+import cn.com.qmth.stmms.biz.exam.model.ExamSubject;
+import cn.com.qmth.stmms.biz.report.dao.ReportSubjectClassDao;
+import cn.com.qmth.stmms.biz.report.model.ReportSubjectClass;
+import cn.com.qmth.stmms.biz.report.query.ReportSubjectQuery;
+import cn.com.qmth.stmms.biz.report.service.ReportSubjectClassService;
+import cn.com.qmth.stmms.biz.utils.DoubleUtil;
+import org.apache.commons.lang.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.jpa.domain.Specification;
+import org.springframework.stereotype.Service;
+
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.criteria.Predicate;
+import javax.persistence.criteria.Root;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * 课程班级分析 service实现
+ *
+ * @author xuwenjin
+ * @date 2019-04-16
+ */
+@Service
+public class ReportSubjectClassServiceImpl extends BaseQueryService<ReportSubjectClass> implements ReportSubjectClassService {
+
+    @Autowired
+    private ReportSubjectClassDao reportSubjectClassDao;
+
+    @Autowired
+    private ExamSubjectDao examSubjectDao;
+
+
+    @Override
+    public void deleteByExamId(Integer examId) {
+        reportSubjectClassDao.deleteByExamId(examId);
+    }
+
+    @Override
+    public List<ReportSubjectClass> findByQuery(final ReportSubjectQuery query) {
+        List<ReportSubjectClass> result = reportSubjectClassDao.findAll(new Specification<ReportSubjectClass>() {
+            @Override
+            public Predicate toPredicate(Root<ReportSubjectClass> root, CriteriaQuery<?> cQuery, CriteriaBuilder cb) {
+                List<Predicate> predicates = new LinkedList<Predicate>();
+
+                if (query.getExamId() != null) {
+                    predicates.add(cb.equal(root.get("examId"), query.getExamId()));
+                }
+                if (query.getSubjectCode() != null) {
+                    predicates.add(cb.equal(root.get("subjectCode"), query.getSubjectCode()));
+                }
+                if (StringUtils.isNotBlank(query.getClassName())) {
+                    predicates.add(cb.equal(root.get("className"), query.getClassName()));
+                }
+                return predicates.isEmpty() ? cb.conjunction()
+                        : cb.and(predicates.toArray(new Predicate[predicates.size()]));
+            }
+        });
+        return result;
+    }
+
+    @Override
+    public void saveReportSubjectClassData(Integer examId, String subjectCode) {
+        ExamSubject examSubject = examSubjectDao.findByExamIdAndCode(examId, subjectCode);
+        List<Object[]> reportSubjecCollegetList = reportSubjectClassDao.queryReportSubjectClassData(examId, subjectCode);
+        for (Object[] rs : reportSubjecCollegetList) {
+            ReportSubjectClass subject = new ReportSubjectClass();
+            subject.setExamId(examId);
+            subject.setSubjectCode(subjectCode);
+            subject.setSubjectName(examSubject.getName());
+            subject.setClassName(rs[0].toString());
+            subject.setAvgScore(DoubleUtil.format(Double.parseDouble(rs[1].toString()), "0.00"));
+            subject.setMaxScore(Double.parseDouble(rs[2].toString()));
+            subject.setMinScore(Double.parseDouble(rs[3].toString()));
+            subject.setPassCount(Integer.parseInt(rs[4].toString()));
+            subject.setPassRate(DoubleUtil.div(subject.getPassCount(), Integer.parseInt(rs[6].toString()), 2));
+            subject.setExcellentCount(Integer.parseInt(rs[5].toString()));
+            subject.setExcellentRate(DoubleUtil.div(subject.getExcellentCount(), Integer.parseInt(rs[6].toString()), 2));
+            reportSubjectClassDao.save(subject);
+        }
+    }
+
+}

+ 83 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/service/impl/ReportSubjectCollegeServiceImpl.java

@@ -0,0 +1,83 @@
+package cn.com.qmth.stmms.biz.report.service.impl;
+
+import cn.com.qmth.stmms.biz.common.BaseQueryService;
+import cn.com.qmth.stmms.biz.exam.dao.ExamSubjectDao;
+import cn.com.qmth.stmms.biz.exam.model.ExamSubject;
+import cn.com.qmth.stmms.biz.report.dao.ReportSubjectCollegeDao;
+import cn.com.qmth.stmms.biz.report.model.ReportSubjectCollege;
+import cn.com.qmth.stmms.biz.report.query.ReportSubjectQuery;
+import cn.com.qmth.stmms.biz.report.service.ReportSubjectCollegeService;
+import cn.com.qmth.stmms.biz.utils.DoubleUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.jpa.domain.Specification;
+import org.springframework.stereotype.Service;
+
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.criteria.Predicate;
+import javax.persistence.criteria.Root;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * 课程学院分析 service实现
+ *
+ * @author xuwenjin
+ * @date 2019-04-16 09:43
+ */
+@Service
+public class ReportSubjectCollegeServiceImpl extends BaseQueryService<ReportSubjectCollege> implements ReportSubjectCollegeService {
+
+    @Autowired
+    private ReportSubjectCollegeDao reportSubjectCollegeDao;
+
+    @Autowired
+    private ExamSubjectDao examSubjectDao;
+
+
+    @Override
+    public void deleteByExamId(Integer examId) {
+        reportSubjectCollegeDao.deleteByExamId(examId);
+    }
+
+    @Override
+    public List<ReportSubjectCollege> findByQuery(final ReportSubjectQuery query) {
+        List<ReportSubjectCollege> result = reportSubjectCollegeDao.findAll(new Specification<ReportSubjectCollege>() {
+
+            @Override
+            public Predicate toPredicate(Root<ReportSubjectCollege> root, CriteriaQuery<?> cQuery, CriteriaBuilder cb) {
+                List<Predicate> predicates = new LinkedList<Predicate>();
+                if (query.getExamId() != null) {
+                    predicates.add(cb.equal(root.get("examId"), query.getExamId()));
+                }
+                if (query.getSubjectCode() != null) {
+                    predicates.add(cb.equal(root.get("subjectCode"), query.getSubjectCode()));
+                }
+                return predicates.isEmpty() ? cb.conjunction()
+                        : cb.and(predicates.toArray(new Predicate[predicates.size()]));
+            }
+        });
+        return result;
+    }
+
+    @Override
+    public void saveReportSubjectCollegeData(Integer examId, String subjectCode) {
+        ExamSubject examSubject = examSubjectDao.findByExamIdAndCode(examId, subjectCode);
+        List<Object[]> reportSubjecCollegetList = reportSubjectCollegeDao.queryReportSubjectCollegeData(examId, subjectCode);
+        for (Object[] rs : reportSubjecCollegetList) {
+            ReportSubjectCollege subject = new ReportSubjectCollege();
+            subject.setExamId(examId);
+            subject.setSubjectCode(subjectCode);
+            subject.setSubjectName(examSubject.getName());
+            subject.setCollegeName(rs[0].toString());
+            subject.setMaxScore(Double.parseDouble(rs[1].toString()));
+            subject.setMinScore(Double.parseDouble(rs[2].toString()));
+            subject.setAvgScore(DoubleUtil.format(Double.parseDouble(rs[3].toString()), "0.000000"));
+            subject.setPassCount(Integer.parseInt(rs[4].toString()));
+            subject.setPassRate(DoubleUtil.div(Double.parseDouble(rs[4].toString()),Integer.parseInt(rs[6].toString()),6));
+            subject.setExcellentRate(DoubleUtil.div(Double.parseDouble(rs[5].toString()),Integer.parseInt(rs[6].toString()),6));
+            reportSubjectCollegeDao.save(subject);
+        }
+    }
+
+}

+ 183 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/service/impl/ReportSubjectGroupServiceImpl.java

@@ -0,0 +1,183 @@
+package cn.com.qmth.stmms.biz.report.service.impl;
+
+import cn.com.qmth.stmms.biz.common.BaseQueryService;
+import cn.com.qmth.stmms.biz.exam.dao.ExamQuestionDao;
+import cn.com.qmth.stmms.biz.exam.dao.ExamStudentDao;
+import cn.com.qmth.stmms.biz.exam.dao.ExamSubjectDao;
+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.report.dao.ReportSubjectGroupDao;
+import cn.com.qmth.stmms.biz.report.model.ReportSubjectGroup;
+import cn.com.qmth.stmms.biz.report.query.ReportSubjectQuery;
+import cn.com.qmth.stmms.biz.report.service.ReportSubjectGroupService;
+import cn.com.qmth.stmms.biz.utils.DoubleUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.jpa.domain.Specification;
+import org.springframework.stereotype.Service;
+
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.criteria.Predicate;
+import javax.persistence.criteria.Root;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * 大题型统计分析 service 实现
+ *
+ * @author xuwenjin
+ * @Date 2019-04-18
+ */
+@Service
+public class ReportSubjectGroupServiceImpl extends BaseQueryService<ReportSubjectGroup> implements ReportSubjectGroupService {
+
+    @Autowired
+    private ReportSubjectGroupDao reportSubjectGroupDao;
+
+    @Autowired
+    private ExamStudentDao examStudentDao;
+
+    @Autowired
+    private ExamQuestionDao examQuestionDao;
+
+    @Autowired
+    private ExamSubjectDao examSubjectDao;
+
+
+    @Override
+    public void deleteByExamId(Integer examId) {
+        reportSubjectGroupDao.deleteByExamId(examId);
+
+    }
+
+    @Override
+    public List<ReportSubjectGroup> findByQuery(final ReportSubjectQuery query) {
+        List<ReportSubjectGroup> result = reportSubjectGroupDao.findAll(new Specification<ReportSubjectGroup>() {
+            @Override
+            public Predicate toPredicate(Root<ReportSubjectGroup> root, CriteriaQuery<?> cQuery, CriteriaBuilder cb) {
+                List<Predicate> predicates = new LinkedList<Predicate>();
+                if (query.getExamId() != null) {
+                    predicates.add(cb.equal(root.get("examId"), query.getExamId()));
+                }
+                if (query.getSubjectCode() != null) {
+                    predicates.add(cb.equal(root.get("subjectCode"), query.getSubjectCode()));
+                }
+                return predicates.isEmpty() ? cb.conjunction()
+                        : cb.and(predicates.toArray(new Predicate[predicates.size()]));
+            }
+        });
+        return result;
+    }
+
+    @Override
+    public void saveReportSubjectGroupData(Integer examId, String subjectCode) {
+        //保存主观题统计分析
+        saveReportSubjectGroupData(examId, subjectCode, true);
+        //保存客观题统计分析
+        saveReportSubjectGroupData(examId, subjectCode, false);
+    }
+
+    /**
+     * 保存题型统计分析
+     *
+     * @param examId      考试Id
+     * @param subjectCode 科目Code
+     * @param objective   客观题,主观题
+     */
+    private void saveReportSubjectGroupData(Integer examId, String subjectCode, Boolean objective) {
+        ExamSubject subject = examSubjectDao.findByExamIdAndCode(examId, subjectCode);
+        List<Object[]> questionGroups = reportSubjectGroupDao.countGroupByMainNum(examId, subjectCode, objective);
+        List<ExamStudent> examStudentList = examStudentDao.findByExamIdAndSubjectCodeAndUploadTimeNotNullAndAbsent(examId, subjectCode, false);
+        Integer studentCount = examStudentList.size();
+        Integer begin = 0;
+        for (int i = 0; i < questionGroups.size(); i++) {
+            Object[] obj = questionGroups.get(i);
+            ExamQuestion question = new ExamQuestion();
+            question.setMainNumber(Integer.parseInt(obj[0].toString()));
+            question.setMainTitle(obj[1].toString());
+            question.setSubNumber(Integer.parseInt(obj[2].toString()));
+            //满分
+            Double fullScore = examQuestionDao.queryFullScoreByExamIdAndSubjectCodeAndMainNumber(examId, subjectCode, question.getMainNumber());
+            Integer questionCount = question.getSubNumber();
+            Double[] totalScoreArray = new Double[studentCount];
+            //题型 总分
+            Double totalScore = 0d;
+            //0分人数
+            Integer zeroScoreCount = 0;
+            //满分人数
+            Integer fullScoreCount = 0;
+            //方差
+            Double variance = 0d;
+            for (int j = 0; j < studentCount; j++) {
+                ExamStudent student = examStudentList.get(j);
+                String[] answers;
+                if (objective) {
+                    answers = student.getObjectiveScoreList().split(";");
+                } else {
+                    answers = student.getSubjectiveScoreList().split(";");
+                }
+                Double score = 0d;
+                for (int k = begin; k < begin + questionCount; k++) {
+                    Double s = 0d;
+                    if (objective) {
+                        s = Double.parseDouble(answers[k].split(":")[1]);
+                    } else {
+                        s = Double.parseDouble(answers[k]);
+                    }
+                    score = DoubleUtil.sum(score, s);
+                }
+                if (score.doubleValue() == 0) {
+                    zeroScoreCount++;
+                }
+                if (score.doubleValue() == fullScore.doubleValue()) {
+                    fullScoreCount++;
+                }
+                totalScoreArray[j] = score;
+                totalScore = DoubleUtil.sum(totalScore, score);
+            }
+            //最大分
+            Double maxScore = Collections.max(Arrays.asList(totalScoreArray));
+            //最小分
+            Double minScore = Collections.min(Arrays.asList(totalScoreArray));
+            //平均分
+            Double avgScore = DoubleUtil.div(totalScore, studentCount, 2);
+            //计算方差
+            for (int j = 0; j < studentCount; j++) {
+                ExamStudent student = examStudentList.get(j);
+                String[] objectiveAnswers = student.getObjectiveScoreList().split(";");
+                Double score = 0d;
+                for (int k = begin; k < begin + questionCount; k++) {
+                    Double s = Double.parseDouble(objectiveAnswers[i].split(":")[1]);
+                    score = DoubleUtil.sum(score, s);
+                }
+                variance = DoubleUtil.sum(variance, DoubleUtil.mul(DoubleUtil.sub(score, avgScore), DoubleUtil.sub(score, avgScore)));
+            }
+            //标准差
+            Double sd = DoubleUtil.format(Math.sqrt(variance / studentCount), "0.000000");
+            //差异系数
+            Double cv = DoubleUtil.mul(DoubleUtil.div(sd, avgScore, 4), 100);
+            ReportSubjectGroup reportSubjectGroup = new ReportSubjectGroup();
+            reportSubjectGroup.setExamId(examId);
+            reportSubjectGroup.setSubjectCode(subjectCode);
+            reportSubjectGroup.setSubjectName(subject.getName());
+            reportSubjectGroup.setGroupName(question.getMainTitle());
+            reportSubjectGroup.setMaxScore(maxScore);
+            reportSubjectGroup.setMinScore(minScore);
+            reportSubjectGroup.setAvgScore(avgScore);
+            reportSubjectGroup.setTotalScore(fullScore);
+            reportSubjectGroup.setSD(sd);
+            reportSubjectGroup.setCV(cv);
+            reportSubjectGroup.setZeroCount(zeroScoreCount);
+            reportSubjectGroup.setFullCount(fullScoreCount);
+
+            begin += questionCount;
+            reportSubjectGroupDao.save(reportSubjectGroup);
+        }
+
+    }
+
+
+}

+ 157 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/service/impl/ReportSubjectQuestionServiceImpl.java

@@ -0,0 +1,157 @@
+package cn.com.qmth.stmms.biz.report.service.impl;
+
+import cn.com.qmth.stmms.biz.common.BaseQueryService;
+import cn.com.qmth.stmms.biz.exam.dao.ExamQuestionDao;
+import cn.com.qmth.stmms.biz.exam.dao.ExamStudentDao;
+import cn.com.qmth.stmms.biz.exam.model.ExamQuestion;
+import cn.com.qmth.stmms.biz.exam.model.ExamStudent;
+import cn.com.qmth.stmms.biz.report.dao.ReportSubjectQuestionDao;
+import cn.com.qmth.stmms.biz.report.model.ReportSubjectQuestion;
+import cn.com.qmth.stmms.biz.report.query.ReportSubjectQuery;
+import cn.com.qmth.stmms.biz.report.service.ReportSubjectQuestionService;
+import cn.com.qmth.stmms.biz.utils.DoubleUtil;
+import org.apache.commons.lang.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.jpa.domain.Specification;
+import org.springframework.stereotype.Service;
+
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.criteria.Predicate;
+import javax.persistence.criteria.Root;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * 客、主观题分析 service 实现
+ *
+ * @author xuwenjin
+ * @Date 2019-04-17
+ */
+@Service
+public class ReportSubjectQuestionServiceImpl extends BaseQueryService<ReportSubjectQuestion> implements ReportSubjectQuestionService {
+
+    @Autowired
+    private ReportSubjectQuestionDao reportSubjectQuestionDao;
+
+    @Autowired
+    private ExamStudentDao examStudentDao;
+
+    @Autowired
+    private ExamQuestionDao examQuestionDao;
+
+    @Override
+    public ReportSubjectQuestion save(ReportSubjectQuestion reportSubjectQuestion) {
+        return reportSubjectQuestionDao.save(reportSubjectQuestion);
+    }
+
+    @Override
+    public void deleteByExamId(Integer examId) {
+        reportSubjectQuestionDao.deleteByExamId(examId);
+
+    }
+
+    @Override
+    public List<ReportSubjectQuestion> findByQuery(final ReportSubjectQuery query) {
+        List<ReportSubjectQuestion> result = reportSubjectQuestionDao.findAll(new Specification<ReportSubjectQuestion>() {
+            @Override
+            public Predicate toPredicate(Root<ReportSubjectQuestion> root, CriteriaQuery<?> cQuery, CriteriaBuilder cb) {
+                List<Predicate> predicates = new LinkedList<Predicate>();
+                if (query.getExamId() != null) {
+                    predicates.add(cb.equal(root.get("examId"), query.getExamId()));
+                }
+                if (query.getSubjectCode() != null) {
+                    predicates.add(cb.equal(root.get("subjectCode"), query.getSubjectCode()));
+                }
+                predicates.add(cb.equal(root.get("objective"), query.getObjective()));
+                return predicates.isEmpty() ? cb.conjunction()
+                        : cb.and(predicates.toArray(new Predicate[predicates.size()]));
+            }
+        });
+        return result;
+    }
+
+    @Override
+    public void saveReportSubjectObjectiveQuestionData(Integer examId, String subjectCode, Boolean objective) {
+
+        List<ExamQuestion> examQuestionObjectiveList = examQuestionDao.findByExamIdAndSubjectCodeAndObjective(examId, subjectCode, objective);
+
+        List<ExamStudent> examStudentList = examStudentDao.findByExamIdAndSubjectCodeAndUploadTimeNotNullAndAbsent(examId, subjectCode, false);
+
+        Integer studentCount = examStudentList.size();
+
+        for (int i = 0; i < examQuestionObjectiveList.size(); i++) {
+            ExamQuestion question = examQuestionObjectiveList.get(i);
+            if (question.getTotalScore().doubleValue() > 0) {
+                ReportSubjectQuestion reportSubjectQuestion = new ReportSubjectQuestion();
+                //得分人数
+                Integer scoreCount = 0;
+                //满分人数
+                Integer fullScoreCount = 0;
+                //考生题目得分汇总
+                Double sumScore = 0d;
+                //题目总分汇总
+                Double questionSumScore = DoubleUtil.mul(question.getTotalScore(), studentCount);
+                //方差
+                Double variance = 0d;
+
+                for (int j = 0; j < studentCount; j++) {
+                    ExamStudent student = examStudentList.get(j);
+                    Double score = 0d;
+                    if (objective) {
+                        if (StringUtils.isNotBlank(student.getObjectiveScoreList())) {
+                            //客观题
+                            String[] objectiveAnswers = student.getObjectiveScoreList().split(";");
+                            score = Double.parseDouble(objectiveAnswers[i].split(":")[1]);
+                        }
+                    } else {
+                        if (StringUtils.isNotBlank(student.getSubjectiveScoreList())) {
+                            //主观题
+                            String[] subjectiveAnswers = student.getSubjectiveScoreList().split(";");
+                            score = Double.parseDouble(subjectiveAnswers[i]);
+                        }
+                    }
+                    sumScore = DoubleUtil.sum(sumScore, score);
+                    if (score > 0) {
+                        scoreCount++;
+                    }
+                    if (score.doubleValue() == question.getTotalScore().doubleValue()) {
+                        fullScoreCount++;
+                    }
+                }
+                Double avgScore = DoubleUtil.div(sumScore, examStudentList.size(), 6);
+                for (int j = 0; j < studentCount; j++) {
+                    ExamStudent student = examStudentList.get(j);
+                    Double score = 0d;
+                    if (objective) {
+                        if (StringUtils.isNotBlank(student.getObjectiveScoreList())) {
+                            //客观题
+                            String[] objectiveAnswers = student.getObjectiveScoreList().split(";");
+                            score = Double.parseDouble(objectiveAnswers[i].split(":")[1]);
+                        }
+                    } else {
+                        if (StringUtils.isNotBlank(student.getSubjectiveScoreList())) {
+                            //主观题
+                            String[] subjectiveAnswers = student.getSubjectiveScoreList().split(";");
+                            score = Double.parseDouble(subjectiveAnswers[i]);
+                        }
+                    }
+                    variance = DoubleUtil.sum(variance, DoubleUtil.mul(DoubleUtil.sub(score, avgScore), DoubleUtil.sub(score, avgScore)));
+                }
+                reportSubjectQuestion.setExamId(examId);
+                reportSubjectQuestion.setSubjectCode(subjectCode);
+                reportSubjectQuestion.setObjective(objective);
+                reportSubjectQuestion.setQuestionName(question.getMainTitle() + "_" + (i + 1));
+                reportSubjectQuestion.setTotalScore(question.getTotalScore());
+                reportSubjectQuestion.setAvgScore(avgScore);
+                reportSubjectQuestion.setScoreRate(DoubleUtil.div(scoreCount, studentCount, 6));
+                reportSubjectQuestion.setSd(DoubleUtil.format(Math.sqrt(variance / studentCount), "0.000000"));
+                reportSubjectQuestion.setFullScoreRate(DoubleUtil.div(fullScoreCount, studentCount, 6));
+                reportSubjectQuestionDao.save(reportSubjectQuestion);
+            }
+        }
+
+    }
+
+
+}

+ 99 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/service/impl/ReportSubjectRangeServiceImpl.java

@@ -0,0 +1,99 @@
+package cn.com.qmth.stmms.biz.report.service.impl;
+
+import cn.com.qmth.stmms.biz.common.BaseQueryService;
+import cn.com.qmth.stmms.biz.report.dao.ReportSubjectRangeDao;
+import cn.com.qmth.stmms.biz.report.model.ReportSubjectRange;
+import cn.com.qmth.stmms.biz.report.query.ReportSubjectQuery;
+import cn.com.qmth.stmms.biz.report.service.ReportSubjectRangeService;
+import cn.com.qmth.stmms.biz.utils.DoubleUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Page;
+import org.springframework.data.jpa.domain.Specification;
+import org.springframework.stereotype.Service;
+
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.criteria.Predicate;
+import javax.persistence.criteria.Root;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * 课程分段统计 service 实现
+ *
+ * @author xuwenjin
+ * @Date 2019-04-19
+ */
+@Service
+public class ReportSubjectRangeServiceImpl extends BaseQueryService<ReportSubjectRange> implements ReportSubjectRangeService {
+
+    @Autowired
+    private ReportSubjectRangeDao reportSubjectRangetDao;
+
+
+    @Override
+    public void deleteByExamId(Integer examId) {
+        reportSubjectRangetDao.deleteByExamId(examId);
+    }
+
+    @Override
+    public ReportSubjectQuery findByQuery(final ReportSubjectQuery query) {
+        checkQuery(query);
+        Page<ReportSubjectRange> result = reportSubjectRangetDao.findAll(new Specification<ReportSubjectRange>() {
+
+            @Override
+            public Predicate toPredicate(Root<ReportSubjectRange> root, CriteriaQuery<?> cQuery, CriteriaBuilder cb) {
+                List<Predicate> predicates = new LinkedList<Predicate>();
+
+                if (query.getExamId() != null) {
+                    predicates.add(cb.equal(root.get("examId"), query.getExamId()));
+                }
+                if (query.getSubjectCode() != null) {
+                    predicates.add(cb.equal(root.get("subjectCode"), query.getSubjectCode()));
+                }
+                return predicates.isEmpty() ? cb.conjunction()
+                        : cb.and(predicates.toArray(new Predicate[predicates.size()]));
+            }
+        }, query);
+        fillResult(result, query);
+
+        return query;
+    }
+
+    /**
+     * 保存 课程分段统计
+     *
+     * @param examId 考试Id
+     */
+    @Override
+    public void saveReportRangeSubjectData(Integer examId) {
+        List<Object[]> datas = reportSubjectRangetDao.queryRangeSubjectByExamId(examId);
+        for (Object[] obj : datas) {
+            ReportSubjectRange subjectRange = new ReportSubjectRange();
+            subjectRange.setExamId(examId);
+            subjectRange.setSubjectCode(obj[0].toString());
+            subjectRange.setSubjectName(obj[1].toString());
+            subjectRange.setLevel(obj[2]!= null?obj[2].toString():"");
+            subjectRange.setCount0_49(Integer.parseInt(obj[3].toString()));
+            subjectRange.setCount50_59(Integer.parseInt(obj[4].toString()));
+            subjectRange.setCount60_69(Integer.parseInt(obj[5].toString()));
+            subjectRange.setCount70_79(Integer.parseInt(obj[6].toString()));
+            subjectRange.setCount80_89(Integer.parseInt(obj[7].toString()));
+            subjectRange.setCount90_100(Integer.parseInt(obj[8].toString()));
+            subjectRange.setLt60(Integer.parseInt(obj[9].toString()));
+            subjectRange.setMte60(Integer.parseInt(obj[10].toString()));
+            subjectRange.setTotalCount(Integer.parseInt(obj[11].toString()));
+            subjectRange.setPercent0_49(DoubleUtil.format(DoubleUtil.div(subjectRange.getCount0_49(), subjectRange.getTotalCount(), 4) * 100,"0.00"));
+            subjectRange.setPercent50_59(DoubleUtil.format(DoubleUtil.div(subjectRange.getCount50_59(), subjectRange.getTotalCount(), 4) * 100,"0.00"));
+            subjectRange.setPercent60_69(DoubleUtil.format(DoubleUtil.div(subjectRange.getCount60_69(), subjectRange.getTotalCount(), 4) * 100,"0.00"));
+            subjectRange.setPercent70_79(DoubleUtil.format(DoubleUtil.div(subjectRange.getCount70_79(), subjectRange.getTotalCount(), 4) * 100,"0.00"));
+            subjectRange.setPercent80_89(DoubleUtil.format(DoubleUtil.div(subjectRange.getCount80_89(), subjectRange.getTotalCount(), 4) * 100,"0.00"));
+            subjectRange.setPercent90_100(DoubleUtil.format(DoubleUtil.div(subjectRange.getCount90_100(), subjectRange.getTotalCount(), 4) * 100,"0.00"));
+            subjectRange.setPercent_lt60(DoubleUtil.format(DoubleUtil.div(subjectRange.getLt60(), subjectRange.getTotalCount(), 4) * 100,"0.00"));
+            subjectRange.setPercent_mte60(DoubleUtil.format(DoubleUtil.div(subjectRange.getMte60(), subjectRange.getTotalCount(), 4) * 100,"0.00"));
+            reportSubjectRangetDao.save(subjectRange);
+        }
+    }
+
+
+}

+ 88 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/service/impl/ReportSubjectServiceImpl.java

@@ -0,0 +1,88 @@
+package cn.com.qmth.stmms.biz.report.service.impl;
+
+import cn.com.qmth.stmms.biz.common.BaseQueryService;
+import cn.com.qmth.stmms.biz.report.dao.ReportSubjectDao;
+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.ReportSubjectService;
+import cn.com.qmth.stmms.biz.utils.DoubleUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Page;
+import org.springframework.data.jpa.domain.Specification;
+import org.springframework.stereotype.Service;
+
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.criteria.Predicate;
+import javax.persistence.criteria.Root;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * 课程总量统计service
+ *
+ * @author xuwenjin
+ * @Date 2019-04-12 18:10
+ */
+@Service
+public class ReportSubjectServiceImpl extends BaseQueryService<ReportSubject> implements ReportSubjectService {
+
+    @Autowired
+    private ReportSubjectDao reportSubjectDao;
+
+    @Override
+    public ReportSubject save(ReportSubject reportSubject) {
+        return reportSubjectDao.save(reportSubject);
+    }
+
+    @Override
+    public void deleteByExamId(Integer examId) {
+        reportSubjectDao.deleteByExamId(examId);
+    }
+
+    @Override
+    public ReportSubjectQuery findByQuery(final ReportSubjectQuery query) {
+        checkQuery(query);
+        Page<ReportSubject> result = reportSubjectDao.findAll(new Specification<ReportSubject>() {
+
+            @Override
+            public Predicate toPredicate(Root<ReportSubject> root, CriteriaQuery<?> cQuery, CriteriaBuilder cb) {
+                List<Predicate> predicates = new LinkedList<Predicate>();
+
+                if (query.getExamId() != null) {
+                    predicates.add(cb.equal(root.get("examId"), query.getExamId()));
+                }
+                if (query.getSubjectCode() != null) {
+                    predicates.add(cb.equal(root.get("subjectCode"), query.getSubjectCode()));
+                }
+                return predicates.isEmpty() ? cb.conjunction()
+                        : cb.and(predicates.toArray(new Predicate[predicates.size()]));
+            }
+        }, query);
+        fillResult(result, query);
+
+        return query;
+    }
+
+    @Override
+    public void saveReportSubjectData(Integer examId) {
+        List<Object[]> reportSubjectList = reportSubjectDao.queryReportSubjectData(examId);
+        for (Object[] rs : reportSubjectList) {
+            ReportSubject subject = new ReportSubject();
+            subject.setExamId(Integer.parseInt(rs[0].toString()));
+            subject.setSubjectCode(rs[1].toString());
+            subject.setSubjectName(rs[2].toString());
+            subject.setTotalCount(Integer.parseInt(rs[3].toString()));
+            subject.setAbsentCount(Integer.parseInt(rs[4].toString()));
+            subject.setBreachCount(Integer.parseInt(rs[5].toString()));
+            subject.setRealityCount(Integer.parseInt(rs[6].toString()));
+            subject.setMaxScore(Double.parseDouble(rs[7].toString()));
+            subject.setMinScore(Double.parseDouble(rs[8].toString()));
+            subject.setAvgScore(DoubleUtil.format(Double.parseDouble(rs[9].toString()),"0.00"));
+            subject.setPassCount(Integer.parseInt(rs[10].toString()));
+            subject.setPassRate(DoubleUtil.div(Integer.parseInt(rs[10].toString()), Integer.parseInt(rs[6].toString()), 2));
+            reportSubjectDao.save(subject);
+        }
+    }
+
+}

+ 99 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/service/impl/ReportSubjectTeacherClassServiceImpl.java

@@ -0,0 +1,99 @@
+package cn.com.qmth.stmms.biz.report.service.impl;
+
+import cn.com.qmth.stmms.biz.common.BaseQueryService;
+import cn.com.qmth.stmms.biz.exam.dao.ExamSubjectDao;
+import cn.com.qmth.stmms.biz.exam.model.ExamSubject;
+import cn.com.qmth.stmms.biz.report.dao.ReportSubjectDao;
+import cn.com.qmth.stmms.biz.report.dao.ReportSubjectTeacherClassDao;
+import cn.com.qmth.stmms.biz.report.model.ReportSubjectTeacherClass;
+import cn.com.qmth.stmms.biz.report.query.ReportSubjectQuery;
+import cn.com.qmth.stmms.biz.report.service.ReportSubjectTeacherClassService;
+import cn.com.qmth.stmms.biz.utils.DoubleUtil;
+import org.apache.commons.lang.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.jpa.domain.Specification;
+import org.springframework.stereotype.Service;
+
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.criteria.Predicate;
+import javax.persistence.criteria.Root;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * 课程老师班级成绩 分析service实现
+ *
+ * @author xuwenjin
+ * @date 2019-04-17
+ */
+@Service
+public class ReportSubjectTeacherClassServiceImpl extends BaseQueryService<ReportSubjectTeacherClass> implements ReportSubjectTeacherClassService {
+
+    @Autowired
+    private ReportSubjectTeacherClassDao reportSubjectTeacherClassDao;
+
+    @Autowired
+    private ReportSubjectDao reportSubjectDao;
+
+    @Autowired
+    private ExamSubjectDao examSubjectDao;
+
+
+    @Override
+    public void deleteByExamId(Integer examId) {
+        reportSubjectTeacherClassDao.deleteByExamId(examId);
+    }
+
+    @Override
+    public List<ReportSubjectTeacherClass> findByQuery(final ReportSubjectQuery query) {
+        List<ReportSubjectTeacherClass> result = reportSubjectTeacherClassDao.findAll(new Specification<ReportSubjectTeacherClass>() {
+
+            @Override
+            public Predicate toPredicate(Root<ReportSubjectTeacherClass> root, CriteriaQuery<?> cQuery, CriteriaBuilder cb) {
+                List<Predicate> predicates = new LinkedList<Predicate>();
+
+                if (query.getExamId() != null) {
+                    predicates.add(cb.equal(root.get("examId"), query.getExamId()));
+                }
+                if (query.getSubjectCode() != null) {
+                    predicates.add(cb.equal(root.get("subjectCode"), query.getSubjectCode()));
+                }
+                if (StringUtils.isNotBlank(query.getTeacherName())) {
+                    predicates.add(cb.equal(root.get("teacherName"), query.getTeacherName()));
+                }
+                return predicates.isEmpty() ? cb.conjunction()
+                        : cb.and(predicates.toArray(new Predicate[predicates.size()]));
+            }
+        });
+
+        return result;
+    }
+
+    @Override
+    public void saveReportSubjectTeacherClassData(Integer examId, String subjectCode) {
+        ExamSubject examSubject = examSubjectDao.findByExamIdAndCode(examId, subjectCode);
+        List<Object[]> reportSubjectTeacherClassList = reportSubjectTeacherClassDao.queryReportSubjectTeacherClassData(examId, subjectCode);
+        Double subjectAvgScore = reportSubjectDao.querySubjectAvgScore(examId, subjectCode);
+        for (Object[] rs : reportSubjectTeacherClassList) {
+            ReportSubjectTeacherClass teacherClass = new ReportSubjectTeacherClass();
+            teacherClass.setExamId(examId);
+            teacherClass.setSubjectCode(subjectCode);
+            teacherClass.setSubjectName(examSubject.getName());
+            teacherClass.setTeacherName(rs[0].toString());
+            teacherClass.setClassName(rs[1].toString());
+            teacherClass.setRealityCount(Integer.parseInt(rs[2].toString()));
+            teacherClass.setPassCount(Integer.parseInt(rs[3].toString()));
+            teacherClass.setExcellentCount(Integer.parseInt(rs[4].toString()));
+            teacherClass.setMaxScore(Double.parseDouble(rs[5].toString()));
+            teacherClass.setMinScore(Double.parseDouble(rs[6].toString()));
+            teacherClass.setPassRate(DoubleUtil.div(teacherClass.getPassCount(), teacherClass.getRealityCount(), 2));
+            teacherClass.setExcellentRate(DoubleUtil.div(teacherClass.getExcellentCount(), teacherClass.getRealityCount(), 2));
+            teacherClass.setAvgScore(DoubleUtil.format(Double.parseDouble(rs[7].toString()),"0.00"));
+            teacherClass.setRelativeAvgScore(Double.parseDouble(String.format("%.2f",
+                    Double.parseDouble(rs[7].toString()) - subjectAvgScore)));
+            reportSubjectTeacherClassDao.save(teacherClass);
+        }
+    }
+
+}

+ 97 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/service/impl/ReportSubjectTeacherServiceImpl.java

@@ -0,0 +1,97 @@
+package cn.com.qmth.stmms.biz.report.service.impl;
+
+import cn.com.qmth.stmms.biz.common.BaseQueryService;
+import cn.com.qmth.stmms.biz.exam.dao.ExamSubjectDao;
+import cn.com.qmth.stmms.biz.exam.model.ExamSubject;
+import cn.com.qmth.stmms.biz.report.dao.ReportSubjectDao;
+import cn.com.qmth.stmms.biz.report.dao.ReportSubjectTeacherDao;
+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.ReportSubjectTeacherService;
+import cn.com.qmth.stmms.biz.utils.DoubleUtil;
+import org.apache.commons.lang.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.jpa.domain.Specification;
+import org.springframework.stereotype.Service;
+
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.criteria.Predicate;
+import javax.persistence.criteria.Root;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * 课程学院分析 service实现
+ *
+ * @author xuwenjin
+ * @date 2019-04-16 09:43
+ */
+@Service
+public class ReportSubjectTeacherServiceImpl extends BaseQueryService<ReportSubjectTeacher> implements ReportSubjectTeacherService {
+
+    @Autowired
+    private ReportSubjectTeacherDao reportSubjectTeacherDao;
+
+    @Autowired
+    private ReportSubjectDao reportSubjectDao;
+
+    @Autowired
+    private ExamSubjectDao examSubjectDao;
+
+
+    @Override
+    public void deleteByExamId(Integer examId) {
+        reportSubjectTeacherDao.deleteByExamId(examId);
+    }
+
+    @Override
+    public List<ReportSubjectTeacher> findByQuery(final ReportSubjectQuery query) {
+        List<ReportSubjectTeacher> result = reportSubjectTeacherDao.findAll(new Specification<ReportSubjectTeacher>() {
+
+            @Override
+            public Predicate toPredicate(Root<ReportSubjectTeacher> root, CriteriaQuery<?> cQuery, CriteriaBuilder cb) {
+                List<Predicate> predicates = new LinkedList<Predicate>();
+
+                if (query.getExamId() != null) {
+                    predicates.add(cb.equal(root.get("examId"), query.getExamId()));
+                }
+                if (query.getSubjectCode() != null) {
+                    predicates.add(cb.equal(root.get("subjectCode"), query.getSubjectCode()));
+                }
+                if (StringUtils.isNotBlank(query.getTeacherName())) {
+                    predicates.add(cb.equal(root.get("teacherName"), query.getTeacherName()));
+                }
+                return predicates.isEmpty() ? cb.conjunction()
+                        : cb.and(predicates.toArray(new Predicate[predicates.size()]));
+            }
+        });
+        return result;
+    }
+
+    @Override
+    public void saveReportSubjectTeacherData(Integer examId, String subjectCode) {
+        ExamSubject examSubject = examSubjectDao.findByExamIdAndCode(examId, subjectCode);
+        List<Object[]> reportSubjectTeacherList = reportSubjectTeacherDao.queryReportSubjectTeacherData(examId, subjectCode);
+        Double subjectAvgScore = reportSubjectDao.querySubjectAvgScore(examId, subjectCode);
+        for (Object[] rs : reportSubjectTeacherList) {
+            ReportSubjectTeacher subject = new ReportSubjectTeacher();
+            subject.setExamId(examId);
+            subject.setSubjectCode(subjectCode);
+            subject.setSubjectName(examSubject.getName());
+            subject.setTeacherName(rs[0].toString());
+            subject.setRealityCount(Integer.parseInt(rs[1].toString()));
+            subject.setPassCount(Integer.parseInt(rs[2].toString()));
+            subject.setExcellentCount(Integer.parseInt(rs[3].toString()));
+            subject.setMaxScore(Double.parseDouble(rs[4].toString()));
+            subject.setMinScore(Double.parseDouble(rs[5].toString()));
+            subject.setPassRate(DoubleUtil.div(subject.getPassCount(), subject.getRealityCount(), 2));
+            subject.setExcellentRate(DoubleUtil.div(subject.getExcellentCount(), subject.getRealityCount(), 2));
+            subject.setAvgScore(DoubleUtil.format(Double.parseDouble(rs[6].toString()),"0.00000"));
+            subject.setRelativeAvgScore(Double.parseDouble(String.format("%.2f",
+                    Double.parseDouble(rs[6].toString()) - subjectAvgScore)));
+            reportSubjectTeacherDao.save(subject);
+        }
+    }
+
+}

+ 75 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/utils/DoubleUtil.java

@@ -0,0 +1,75 @@
+package cn.com.qmth.stmms.biz.utils;
+
+import java.math.BigDecimal;
+import java.text.DecimalFormat;
+
+/**
+ * Double 帮助类
+ *
+ * @author xuwenjin
+ * @date 2019-04-17 18:42
+ */
+public class DoubleUtil {
+    /**
+     * double 相加
+     *
+     * @param d1
+     * @param d2
+     * @return
+     */
+    public static double sum(double d1, double d2) {
+        BigDecimal bd1 = new BigDecimal(Double.toString(d1));
+        BigDecimal bd2 = new BigDecimal(Double.toString(d2));
+        return bd1.add(bd2).doubleValue();
+    }
+
+
+    /**
+     * double 相减
+     *
+     * @param d1
+     * @param d2
+     * @return
+     */
+    public static double sub(double d1, double d2) {
+        BigDecimal bd1 = new BigDecimal(Double.toString(d1));
+        BigDecimal bd2 = new BigDecimal(Double.toString(d2));
+        return bd1.subtract(bd2).doubleValue();
+    }
+
+    /**
+     * double 乘法
+     *
+     * @param d1
+     * @param d2
+     * @return
+     */
+    public static double mul(double d1, double d2) {
+        BigDecimal bd1 = new BigDecimal(Double.toString(d1));
+        BigDecimal bd2 = new BigDecimal(Double.toString(d2));
+        return bd1.multiply(bd2).doubleValue();
+    }
+
+
+    /**
+     * double 除法
+     *
+     * @param d1
+     * @param d2
+     * @param scale 四舍五入 小数点位数
+     * @return
+     */
+    public static double div(double d1, double d2, int scale) {
+        //  当然在此之前,你要判断分母是否为0,    
+        //  为0你可以根据实际需求做相应的处理 
+        BigDecimal bd1 = new BigDecimal(Double.toString(d1));
+        BigDecimal bd2 = new BigDecimal(Double.toString(d2));
+        return bd1.divide(bd2, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
+    }
+
+    public static double format(double d1,String format){
+        DecimalFormat formatter = new DecimalFormat(format);
+        return Double.parseDouble(formatter.format(d1));
+    }
+
+}

+ 19 - 14
stmms-web/src/main/java/cn/com/qmth/stmms/admin/exam/ScoreController.java

@@ -39,6 +39,7 @@ import cn.com.qmth.stmms.biz.exam.service.MarkGroupService;
 import cn.com.qmth.stmms.biz.exam.service.ScoreRateService;
 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.utils.ScoreItem;
 import cn.com.qmth.stmms.common.auth.annotation.RoleRequire;
 import cn.com.qmth.stmms.common.domain.WebUser;
@@ -79,13 +80,16 @@ public class ScoreController extends BaseExamController {
 
     @Autowired
     private LockService lockService;
-    
+
     @Autowired
     private CheckStudentService checkStudentService;
-    
+
     @Autowired
     private ExamService examService;
 
+    @Autowired
+    private ReportService reportService;
+
     @Value("${sheet.image.server}")
     private String imageServer;
 
@@ -122,10 +126,10 @@ public class ScoreController extends BaseExamController {
             buildAnswerUrl(student);
         }
         String exporMmessage = enableExport(examId);
-        if(exporMmessage!=null){
+        if (exporMmessage != null) {
             view.addObject("exporMmessage", exporMmessage);
             view.addObject("enableExport", false);
-        }else{
+        } else {
             view.addObject("enableExport", true);
         }
         view.addObject("query", query);
@@ -198,8 +202,9 @@ public class ScoreController extends BaseExamController {
     public ModelAndView calculate(HttpServletRequest request) {
         int examId = getSessionExamId(request);
         if (lockService.trylock(LockType.EXAM, examId)) {
-            ScoreCalculateThread thread = new ScoreCalculateThread(examId, lockService, studentService, questionService,
-                    subjectService, scoreRateService, markService, groupService,checkStudentService);
+            ScoreCalculateThread thread = new ScoreCalculateThread(examId, lockService, studentService,
+                    questionService, subjectService, scoreRateService, markService, groupService, checkStudentService,
+                    reportService);
             taskExecutor.submit(thread);
         }
         return new ModelAndView("redirect:/admin/exam/score");
@@ -211,8 +216,8 @@ public class ScoreController extends BaseExamController {
         WebUser wu = RequestUtils.getWebUser(request);
         int examId = getSessionExamId(request);
         String exporMmessage = enableExport(examId);
-        if(exporMmessage!=null){
-            addMessage(redirectAttributes, "评卷未结束不能导出成绩 "+exporMmessage);
+        if (exporMmessage != null) {
+            addMessage(redirectAttributes, "评卷未结束不能导出成绩 " + exporMmessage);
             return "redirect:/admin/exam/score";
         }
         String subjectCode = RequestUtils.getSession(request).getParameter("subjectCode");
@@ -321,15 +326,15 @@ public class ScoreController extends BaseExamController {
         String message = null;
         Exam exam = examService.findById(examId);
         long totalCount = studentService.countByExamId(examId);
-        long uploadCount = studentService.countByExamIdAndUpload(examId,true);
-        long manualAbsentCount = studentService.countByExamIdAndManualAbsent(examId,true);
-        if(exam.isNeedCalculate()){
+        long uploadCount = studentService.countByExamIdAndUpload(examId, true);
+        long manualAbsentCount = studentService.countByExamIdAndManualAbsent(examId, true);
+        if (exam.isNeedCalculate()) {
             message = "该考试需要统分";
-        }else if(uploadCount+manualAbsentCount!=totalCount){
+        } else if (uploadCount + manualAbsentCount != totalCount) {
             message = "已上传和人工指定缺考总数不等于总人数";
-        }else if(groupService.countByExamAndStatus(examId, MarkStatus.TRIAL, MarkStatus.FORMAL) != 0){
+        } else if (groupService.countByExamAndStatus(examId, MarkStatus.TRIAL, MarkStatus.FORMAL) != 0) {
             message = "有科目未评卷完成";
-        }else if(checkStudentService.countByExamIdAndChecked(examId,false)!=0){
+        } else if (checkStudentService.countByExamIdAndChecked(examId, false) != 0) {
             message = "人工确认未完成";
         }
         return message;

+ 52 - 0
stmms-web/src/main/java/cn/com/qmth/stmms/admin/report/ReportSubjectClassController.java

@@ -0,0 +1,52 @@
+package cn.com.qmth.stmms.admin.report;
+
+import cn.com.qmth.stmms.admin.exam.BaseExamController;
+import cn.com.qmth.stmms.biz.report.model.ReportSubjectClass;
+import cn.com.qmth.stmms.biz.report.query.ReportSubjectQuery;
+import cn.com.qmth.stmms.biz.report.service.ReportSubjectClassService;
+import cn.com.qmth.stmms.common.domain.WebUser;
+import cn.com.qmth.stmms.common.utils.RequestUtils;
+import org.apache.commons.lang.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.List;
+
+/**
+ * 课程班级ß成绩分析
+ *
+ * @author xuwenjin
+ * @date 2019-04-16
+ */
+@Controller
+@RequestMapping("/admin/exam/reportSubjectClass")
+public class ReportSubjectClassController extends BaseExamController {
+
+    protected static Logger log = LoggerFactory.getLogger(ReportSubjectClassController.class);
+
+    @Autowired
+    private ReportSubjectClassService reportSubjectClassService;
+
+
+    @RequestMapping
+    public String list(Model model, HttpServletRequest request, ReportSubjectQuery query) {
+        WebUser webuser = RequestUtils.getWebUser(request);
+        int examId = getSessionExamId(request);
+//        reportSubjectClassService.saveReportSubjectClassData(1, "1118802");
+        query.setExamId(examId);
+        if (StringUtils.isNotBlank(query.getSubjectCode())) {
+            List<ReportSubjectClass> reportSubjectClassList = reportSubjectClassService.findByQuery(query);
+            model.addAttribute("list", reportSubjectClassList);
+        }
+        model.addAttribute("subjectList", getExamSubject(examId, webuser));
+        model.addAttribute("query", query);
+        return "modules/report/reportSubjectClass";
+    }
+
+
+}

+ 52 - 0
stmms-web/src/main/java/cn/com/qmth/stmms/admin/report/ReportSubjectCollegeController.java

@@ -0,0 +1,52 @@
+package cn.com.qmth.stmms.admin.report;
+
+import cn.com.qmth.stmms.admin.exam.BaseExamController;
+import cn.com.qmth.stmms.biz.report.model.ReportSubjectCollege;
+import cn.com.qmth.stmms.biz.report.query.ReportSubjectQuery;
+import cn.com.qmth.stmms.biz.report.service.ReportSubjectCollegeService;
+import cn.com.qmth.stmms.common.domain.WebUser;
+import cn.com.qmth.stmms.common.utils.RequestUtils;
+import org.apache.commons.lang.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.List;
+
+/**
+ * 课程学院成绩分析
+ *
+ * @author xuwenjin
+ * @date 2019-04-16 10:05
+ */
+@Controller
+@RequestMapping("/admin/exam/reportSubjectCollege")
+public class ReportSubjectCollegeController extends BaseExamController {
+
+    protected static Logger log = LoggerFactory.getLogger(ReportSubjectCollegeController.class);
+
+    @Autowired
+    private ReportSubjectCollegeService reportSubjectCollegeService;
+
+
+    @RequestMapping
+    public String list(Model model, HttpServletRequest request, ReportSubjectQuery query) {
+        WebUser webuser = RequestUtils.getWebUser(request);
+        int examId = getSessionExamId(request);
+//        reportSubjectCollegeService.saveReportSubjectCollegeData(1,"1118802");
+        query.setExamId(examId);
+        if (StringUtils.isNotBlank(query.getSubjectCode())) {
+            List<ReportSubjectCollege> reportSubjectColleges = reportSubjectCollegeService.findByQuery(query);
+            model.addAttribute("list", reportSubjectColleges);
+        }
+        model.addAttribute("subjectList", getExamSubject(examId, webuser));
+        model.addAttribute("query", query);
+        return "modules/report/reportSubjectCollege";
+    }
+
+
+}

+ 51 - 0
stmms-web/src/main/java/cn/com/qmth/stmms/admin/report/ReportSubjectController.java

@@ -0,0 +1,51 @@
+package cn.com.qmth.stmms.admin.report;
+
+import cn.com.qmth.stmms.admin.exam.BaseExamController;
+import cn.com.qmth.stmms.biz.report.query.ReportSubjectQuery;
+import cn.com.qmth.stmms.biz.report.service.ReportSubjectService;
+import cn.com.qmth.stmms.common.domain.WebUser;
+import cn.com.qmth.stmms.common.utils.Paginator;
+import cn.com.qmth.stmms.common.utils.RequestUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * 课程总量统计
+ *
+ * @author xuwenjin
+ * @date 2019-04-12 17:05
+ */
+@Controller
+@RequestMapping("/admin/exam/reportSubject")
+public class ReportSubjectController extends BaseExamController {
+
+    protected static Logger log = LoggerFactory.getLogger(ReportSubjectController.class);
+
+    @Autowired
+    private ReportSubjectService reportSubjectService;
+
+
+    @RequestMapping
+    public String list(Model model, HttpServletRequest request, ReportSubjectQuery query) {
+        WebUser webuser = RequestUtils.getWebUser(request);
+        int examId = getSessionExamId(request);
+//        reportSubjectService.saveReportSubjectData(examId);
+        query = reportSubjectService.findByQuery(query);
+        if (query.getCurrentCount() > 0) {
+            model.addAttribute("list", query.getResult());
+            model.addAttribute("paginator",
+                    new Paginator(query.getPageNumber(), query.getPageSize(), (int) query.getTotalCount()));
+        }
+        model.addAttribute("subjectList", getExamSubject(examId, webuser));
+        model.addAttribute("query", query);
+        return "modules/report/reportSubject";
+    }
+
+
+}

+ 50 - 0
stmms-web/src/main/java/cn/com/qmth/stmms/admin/report/ReportSubjectGroupController.java

@@ -0,0 +1,50 @@
+package cn.com.qmth.stmms.admin.report;
+
+import cn.com.qmth.stmms.admin.exam.BaseExamController;
+import cn.com.qmth.stmms.biz.report.model.ReportSubjectGroup;
+import cn.com.qmth.stmms.biz.report.query.ReportSubjectQuery;
+import cn.com.qmth.stmms.biz.report.service.ReportSubjectGroupService;
+import cn.com.qmth.stmms.common.domain.WebUser;
+import cn.com.qmth.stmms.common.utils.RequestUtils;
+import org.apache.commons.lang.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.List;
+
+/**
+ * 大题统计分析
+ *
+ * @author xuwenjin
+ * @date 2019-04-19
+ */
+@Controller
+@RequestMapping("/admin/exam/reportSubjectGroup")
+public class ReportSubjectGroupController extends BaseExamController {
+
+    protected static Logger log = LoggerFactory.getLogger(ReportSubjectGroupController.class);
+
+    @Autowired
+    private ReportSubjectGroupService reportSubjectGroupService;
+
+    @RequestMapping
+    public String list(Model model, HttpServletRequest request, ReportSubjectQuery query) {
+        WebUser webuser = RequestUtils.getWebUser(request);
+        int examId = getSessionExamId(request);
+        reportSubjectGroupService.saveReportSubjectGroupData(1, "1118802");
+        query.setExamId(examId);
+        if (StringUtils.isNotBlank(query.getSubjectCode())) {
+            List<ReportSubjectGroup> groups = reportSubjectGroupService.findByQuery(query);
+            model.addAttribute("list", groups);
+        }
+        model.addAttribute("subjectList", getExamSubject(examId, webuser));
+        model.addAttribute("query", query);
+        return "modules/report/reportSubjectGroup";
+    }
+
+}

+ 52 - 0
stmms-web/src/main/java/cn/com/qmth/stmms/admin/report/ReportSubjectQuestionController.java

@@ -0,0 +1,52 @@
+package cn.com.qmth.stmms.admin.report;
+
+import cn.com.qmth.stmms.admin.exam.BaseExamController;
+import cn.com.qmth.stmms.biz.report.model.ReportSubjectQuestion;
+import cn.com.qmth.stmms.biz.report.query.ReportSubjectQuery;
+import cn.com.qmth.stmms.biz.report.service.ReportSubjectQuestionService;
+import cn.com.qmth.stmms.common.domain.WebUser;
+import cn.com.qmth.stmms.common.utils.RequestUtils;
+import org.apache.commons.lang.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.List;
+
+/**
+ * 客、主观题 成绩分析
+ *
+ * @author xuwenjin
+ * @date 2019-04-18
+ */
+@Controller
+@RequestMapping("/admin/exam/reportSubjectQuestion")
+public class ReportSubjectQuestionController extends BaseExamController {
+
+    protected static Logger log = LoggerFactory.getLogger(ReportSubjectQuestionController.class);
+
+    @Autowired
+    private ReportSubjectQuestionService reportSubjectQuestionService;
+
+
+    @RequestMapping
+    public String list(Model model, HttpServletRequest request, ReportSubjectQuery query) {
+        WebUser webuser = RequestUtils.getWebUser(request);
+        int examId = getSessionExamId(request);
+//        reportSubjectQuestionService.saveReportSubjectObjectiveQuestionData(1, "1118802", query.getObjective());
+        query.setExamId(examId);
+        if (StringUtils.isNotBlank(query.getSubjectCode())) {
+            List<ReportSubjectQuestion> questions = reportSubjectQuestionService.findByQuery(query);
+            model.addAttribute("list", questions);
+        }
+        model.addAttribute("subjectList", getExamSubject(examId, webuser));
+        model.addAttribute("query", query);
+        return "modules/report/reportSubjectQuestion";
+    }
+
+
+}

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

@@ -0,0 +1,53 @@
+package cn.com.qmth.stmms.admin.report;
+
+import cn.com.qmth.stmms.admin.exam.BaseExamController;
+import cn.com.qmth.stmms.biz.report.query.ReportSubjectQuery;
+import cn.com.qmth.stmms.biz.report.service.ReportSubjectRangeService;
+import cn.com.qmth.stmms.biz.user.model.User;
+import cn.com.qmth.stmms.common.domain.WebUser;
+import cn.com.qmth.stmms.common.utils.Paginator;
+import cn.com.qmth.stmms.common.utils.RequestUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * 课程总量统计
+ *
+ * @author xuwenjin
+ * @date 2019-04-12 17:05
+ */
+@Controller
+@RequestMapping("/admin/exam/reportSubjectRange")
+public class ReportSubjectRangeController extends BaseExamController {
+
+    protected static Logger log = LoggerFactory.getLogger(ReportSubjectRangeController.class);
+
+    @Autowired
+    private ReportSubjectRangeService reportSubjectRangeService;
+
+
+    @RequestMapping
+    public String list(Model model, HttpServletRequest request, ReportSubjectQuery query) {
+        WebUser webuser = RequestUtils.getWebUser(request);
+        int examId = getSessionExamId(request);
+//        reportSubjectRangeService.saveReportRangeSubjectData(1);
+        User user = RequestUtils.getWebUser(request).getUser();
+        query = reportSubjectRangeService.findByQuery(query);
+        if (query.getCurrentCount() > 0) {
+            model.addAttribute("list", query.getResult());
+            model.addAttribute("paginator",
+                    new Paginator(query.getPageNumber(), query.getPageSize(), (int) query.getTotalCount()));
+        }
+        model.addAttribute("subjectList", getExamSubject(examId, webuser));
+        model.addAttribute("query", query);
+        return "modules/report/reportSubjectRange";
+    }
+
+
+}

+ 60 - 0
stmms-web/src/main/java/cn/com/qmth/stmms/admin/report/ReportSubjectTeacherClassController.java

@@ -0,0 +1,60 @@
+package cn.com.qmth.stmms.admin.report;
+
+import cn.com.qmth.stmms.admin.exam.BaseExamController;
+import cn.com.qmth.stmms.biz.exam.model.ExamSubject;
+import cn.com.qmth.stmms.biz.exam.service.ExamSubjectService;
+import cn.com.qmth.stmms.biz.report.model.ReportSubjectTeacherClass;
+import cn.com.qmth.stmms.biz.report.query.ReportSubjectQuery;
+import cn.com.qmth.stmms.biz.report.service.ReportSubjectTeacherClassService;
+import cn.com.qmth.stmms.common.domain.WebUser;
+import cn.com.qmth.stmms.common.utils.RequestUtils;
+import org.apache.commons.lang.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.List;
+
+/**
+ * 课程老师班级 成绩分析
+ *
+ * @author xuwenjin
+ * @date 2019-04-17
+ */
+@Controller
+@RequestMapping("/admin/exam/reportSubjectTeacherClass")
+public class ReportSubjectTeacherClassController extends BaseExamController {
+
+    protected static Logger log = LoggerFactory.getLogger(ReportSubjectTeacherClassController.class);
+
+    @Autowired
+    private ReportSubjectTeacherClassService reportSubjectTeacherClassService;
+
+    @Autowired
+    private ExamSubjectService subjectService;
+
+
+    @RequestMapping
+    public String list(Model model, HttpServletRequest request, ReportSubjectQuery query) {
+        WebUser webuser = RequestUtils.getWebUser(request);
+        int examId = getSessionExamId(request);
+//        reportSubjectTeacherClassService.saveReportSubjectTeacherClassData(1,"1118802");
+        query.setExamId(examId);
+        if (StringUtils.isNotBlank(query.getSubjectCode()) && StringUtils.isNotBlank(query.getTeacherName())) {
+            List<ReportSubjectTeacherClass> reportSubjectTeacherClasses = reportSubjectTeacherClassService.findByQuery(query);
+            model.addAttribute("list", reportSubjectTeacherClasses);
+            ExamSubject subject = subjectService.find(examId,query.getSubjectCode());
+            model.addAttribute("subjectName", subject.getCode()+"-"+subject.getName());
+        }
+
+        model.addAttribute("subjectList", getExamSubject(examId, webuser));
+        model.addAttribute("query", query);
+        return "modules/report/reportSubjectTeacherClass";
+    }
+
+
+}

+ 52 - 0
stmms-web/src/main/java/cn/com/qmth/stmms/admin/report/ReportSubjectTeacherController.java

@@ -0,0 +1,52 @@
+package cn.com.qmth.stmms.admin.report;
+
+import cn.com.qmth.stmms.admin.exam.BaseExamController;
+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.ReportSubjectTeacherService;
+import cn.com.qmth.stmms.common.domain.WebUser;
+import cn.com.qmth.stmms.common.utils.RequestUtils;
+import org.apache.commons.lang.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.List;
+
+/**
+ * 课程老师成绩分析
+ *
+ * @author xuwenjin
+ * @date 2019-04-16 17:26
+ */
+@Controller
+@RequestMapping("/admin/exam/reportSubjectTeacher")
+public class ReportSubjectTeacherController extends BaseExamController {
+
+    protected static Logger log = LoggerFactory.getLogger(ReportSubjectTeacherController.class);
+
+    @Autowired
+    private ReportSubjectTeacherService reportSubjectTeacherService;
+
+
+    @RequestMapping
+    public String list(Model model, HttpServletRequest request, ReportSubjectQuery query) {
+        WebUser webuser = RequestUtils.getWebUser(request);
+        int examId = getSessionExamId(request);
+//        reportSubjectTeacherService.saveReportSubjectTeacherData(1,"1118802");
+        query.setExamId(examId);
+        if (StringUtils.isNotBlank(query.getSubjectCode())) {
+            List<ReportSubjectTeacher> reportSubjectTeacherList = reportSubjectTeacherService.findByQuery(query);
+            model.addAttribute("list", reportSubjectTeacherList);
+        }
+        model.addAttribute("subjectList", getExamSubject(examId, webuser));
+        model.addAttribute("query", query);
+        return "modules/report/reportSubjectTeacher";
+    }
+
+
+}

+ 42 - 10
stmms-web/src/main/java/cn/com/qmth/stmms/admin/thread/ScoreCalculateThread.java

@@ -25,6 +25,7 @@ import cn.com.qmth.stmms.biz.exam.service.MarkGroupService;
 import cn.com.qmth.stmms.biz.exam.service.ScoreRateService;
 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.utils.ScoreCalculateUtil;
 import cn.com.qmth.stmms.biz.utils.ScoreInfo;
 import cn.com.qmth.stmms.biz.utils.ScoreItem;
@@ -51,6 +52,8 @@ public class ScoreCalculateThread implements Runnable {
 
     private LockService lockService;
 
+    private ReportService reportService;
+
     private Map<String, List<ExamQuestion>> objectiveMap;
 
     private Map<String, List<ExamQuestion>> subjectiveMap;
@@ -58,12 +61,13 @@ public class ScoreCalculateThread implements Runnable {
     private Map<String, Set<String>> campusNameMap;
 
     private Map<String, Double> scoreRateMap;
-    
+
     private CheckStudentService checkStudentService;
 
     public ScoreCalculateThread(int examId, LockService lockService, ExamStudentService studentService,
             ExamQuestionService questionService, ExamSubjectService subjectService, ScoreRateService scoreRateService,
-            MarkService markService, MarkGroupService groupService,CheckStudentService checkStudentService) {
+            MarkService markService, MarkGroupService groupService, CheckStudentService checkStudentService,
+            ReportService reportService) {
         this.examId = examId;
         this.lockService = lockService;
         this.studentService = studentService;
@@ -73,6 +77,7 @@ public class ScoreCalculateThread implements Runnable {
         this.markService = markService;
         this.groupService = groupService;
         this.checkStudentService = checkStudentService;
+        this.reportService = reportService;
         this.objectiveMap = new HashMap<String, List<ExamQuestion>>();
         this.subjectiveMap = new HashMap<String, List<ExamQuestion>>();
         this.scoreRateMap = new HashMap<String, Double>();
@@ -103,13 +108,39 @@ public class ScoreCalculateThread implements Runnable {
             if (total == finish) {
                 statistics();
             }
-            
-            //统计识别缺考的试卷
-            List<ExamStudent> students = studentService.findByExamIdAndUploadAndAbsent(examId, true, true, 1, Integer.MAX_VALUE);
+
+            // 统计识别缺考的试卷
+            List<ExamStudent> students = studentService.findByExamIdAndUploadAndAbsent(examId, true, true, 1,
+                    Integer.MAX_VALUE);
             for (ExamStudent examStudent : students) {
-                CheckStudent student = new CheckStudent(examStudent.getId(),examId,examStudent.getSubjectCode(),CheckType.SCAN_ABSENT);
+                CheckStudent student = new CheckStudent(examStudent.getId(), examId, examStudent.getSubjectCode(),
+                        CheckType.SCAN_ABSENT);
                 checkStudentService.save(student);
             }
+            // int pageNumber = 1;
+            // int pageSize = 1000;
+            // List<ExamStudent> list =
+            // studentService.findByExamIdAndUploadAndAbsent(examId, true,
+            // false, pageNumber,
+            // pageSize);
+            // while (list != null && list.size() > 0) {
+            // for (ExamStudent student : list) {
+            // calculate(student);
+            // }
+            //
+            // pageNumber++;
+            // list = studentService.findByExamIdAndUploadAndAbsent(examId,
+            // true, false, pageNumber, pageSize);
+            // }
+            //
+            // // 统计各科目下每题得分率,主观题评卷完成才统计
+            // double total = groupService.sumLibraryCount(examId);
+            // double finish = groupService.sumMarkedCount(examId);
+            // if (total == finish) {
+            // statistics();
+            // }
+            // 生成报表数据
+            reportService.generateReportData(examId);
         } catch (Exception e) {
             log.error("calculate exception for examId=" + examId, e);
         } finally {
@@ -175,10 +206,11 @@ public class ScoreCalculateThread implements Runnable {
             // 主观题得分统计
             // 需要重新从数据库读取一遍考生信息
             statistics(studentService.findById(student.getId()));
-            
-            //客观题0分主观题有分的考生
-            if(student.getObjectiveScore()==0 && student.getSubjectiveScore()!=0){
-                CheckStudent cs = new CheckStudent(student.getId(),examId,student.getSubjectCode(),CheckType.EXCEPTION);
+
+            // 客观题0分主观题有分的考生
+            if (student.getObjectiveScore() == 0 && student.getSubjectiveScore() != 0) {
+                CheckStudent cs = new CheckStudent(student.getId(), examId, student.getSubjectCode(),
+                        CheckType.EXCEPTION);
                 checkStudentService.save(cs);
             }
         } catch (Exception e) {

+ 1 - 1
stmms-web/src/main/webapp/WEB-INF/views/modules/exam/examIndex.jsp

@@ -95,7 +95,7 @@
 											<li><a href="${ctx}/admin/exam/scan" target="mainFrame" ><i class="icon-print"></i>扫描进度</a></li>
 											<li><a href="${ctx}/admin/exam/mark" target="mainFrame" ><i class="icon-pencil"></i>评卷管理</a></li>
 											<li><a href="${ctx}/admin/exam/score" target="mainFrame" ><i class="icon-search"></i>成绩查询</a></li>
-											<li><a href="${ctx}/admin/exam/statistics" target="mainFrame" ><i class="icon-align-center"></i>成绩分析</a></li>		
+											<li><a href="${ctx}/admin/exam/reportSubjectRange" target="mainFrame" ><i class="icon-search"></i>报表统计</a></li>
 											<li><a href="${ctx}/admin/exam/tag" target="mainFrame" ><i class="icon-tag"></i>标记试卷</a></li>	
 											<li><a href="${ctx}/admin/exam/check/answer" target="mainFrame" ><i class="icon-check"></i>数据检查</a></li>			
 											</c:if>

+ 86 - 0
stmms-web/src/main/webapp/WEB-INF/views/modules/report/reportSubject.jsp

@@ -0,0 +1,86 @@
+<%@ 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" %>
+	<%@include file="/WEB-INF/views/include/dialog.jsp" %>
+	<style type="text/css">.sort{color:#0663A2;cursor:pointer;}</style>
+</head>
+<body>
+	<ul class="nav nav-tabs">
+		<li><a href="${ctx}/admin/exam/reportSubjectRange">课程分段统计</a></li>
+		<li class="active"><a href="${ctx}/admin/exam/reportSubject">课程总量统计表</a></li>
+	</ul>
+	<form id="searchForm"  action="${ctx}/admin/exam/reportSubject" method="post" class="breadcrumb form-search">
+		<input id="pageNumber" name="pageNumber" type="hidden"/>
+		<input id="pageSize" name="pageSize" type="hidden"/>
+		<div>
+			<label>科目:</label>
+			<select class="input-large" id="subjectCode" name="subjectCode">
+				<option value="">请选择</option>
+				<c:forEach items="${subjectList }" var="subject">
+					<option value="${subject.code }" <c:if test="${query.subjectCode eq subject.code }">selected</c:if>>${subject.code}-${subject.name}</option>
+				</c:forEach>
+			</select>
+			&nbsp;
+			<input id="btnSubmit" class="btn btn-primary" type="button" value="查询" onclick="goSearch()"/>
+		</div>
+	</form>
+	<tags:message content="${message}"/>
+	<table id="contentTable" class="table table-striped table-bordered table-condensed">
+		<thead>
+			<tr>
+				<th>课程</th>
+				<th>报考人数</th>
+				<th>缺考</th>
+				<th>违纪</th>
+				<th>实考人数</th>
+				<th>平均分</th>
+				<th>最高分</th>
+				<th>最低分</th>
+				<th>及格人数</th>
+				<th>及格率(%)</th>
+			</tr>
+		</thead>
+		<tbody>
+		<c:forEach items="${list}" var="reportSubject">
+			<tr>
+				<td><a href="${ctx}/admin/exam/reportSubjectCollege?subjectCode=${reportSubject.subjectCode}">${reportSubject.subjectCode}-${reportSubject.subjectName}</a></td>
+				<td>${reportSubject.totalCount}</td>
+				<td>${reportSubject.absentCount}</td>
+				<td>${reportSubject.breachCount}</td>
+				<td>${reportSubject.realityCount}</td>
+				<td>${reportSubject.avgScore}</td>
+				<td>${reportSubject.maxScore}</td>
+				<td>${reportSubject.minScore}</td>
+				<td>${reportSubject.passCount}</td>
+				<td>${reportSubject.passRate}</td>
+			</tr>
+		</c:forEach>
+		</tbody>
+	</table>
+	<div class="pagination">${query}</div>
+<script type="text/javascript">
+function page(n,s){
+	$("#pageNumber").val(n);
+	$("#pageSize").val(s);
+	$("#searchForm").submit();
+	return false;
+}
+function goSearch(){
+	$("#pageNumber").val(1);
+	$("#pageSize").val('${query.pageSize}');
+	$("#searchForm").submit();
+	return false;
+}
+$(document).keydown(function(event) {
+	if(event.keyCode == 13 || event.keyCode== 108){
+		goSearch();
+		return false;
+	}
+});
+</script>	
+</body>
+</html>

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

@@ -0,0 +1,208 @@
+<%@ 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" %>
+    <%@include file="/WEB-INF/views/include/dialog.jsp" %>
+    <link rel="stylesheet" type="text/css" href="${ctxStatic}/jBox/Source/jBox.css">
+    <script type="text/javascript" src="${ctxStatic}/jBox/Source/jBox.min.js"></script>
+    <script type="text/javascript" src="${ctxStatic}/echarts/echarts.min.js"></script>
+    <style type="text/css">.sort {
+        color: #0663A2;
+        cursor: pointer;
+    }</style>
+</head>
+<body>
+<ul class="nav nav-tabs">
+
+    <li><a href="${ctx}/admin/exam/reportSubjectCollege?subjectCode=${query.subjectCode}">课程学院分析表</a></li>
+    <li><a href="${ctx}/admin/exam/reportSubjectTeacher?subjectCode=${query.subjectCode}">课程任课老师分析表</a></li>
+    <li class="active"><a href="${ctx}/admin/exam/reportSubjectClass?subjectCode=${query.subjectCode}">课程班级分析表</a></li>
+    <li><a href="${ctx}/admin/exam/reportSubjectQuestion?subjectCode=${query.subjectCode}&objective=true">客观题分析表</a>
+    </li>
+    <li><a href="${ctx}/admin/exam/reportSubjectQuestion?subjectCode=${query.subjectCode}&objective=false">主观题分析表</a>
+    </li>
+    <li><a href="${ctx}/admin/exam/reportSubjectGroup?subjectCode=${query.subjectCode}">大题统计分析表</a></li>
+</ul>
+<form id="searchForm" action="${ctx}/admin/exam/reportSubjectClass" method="post" class="breadcrumb form-search">
+    <input id="pageNumber" name="pageNumber" type="hidden"/>
+    <input id="pageSize" name="pageSize" type="hidden"/>
+    <div>
+        <label>科目:</label>
+        <select class="input-large" id="subjectCode" name="subjectCode">
+            <option value="">请选择</option>
+            <c:forEach items="${subjectList }" var="subject">
+                <option value="${subject.code }"
+                        <c:if test="${query.subjectCode eq subject.code }">selected</c:if>>${subject.code}-${subject.name}</option>
+            </c:forEach>
+        </select>
+        <label>班级:</label>
+        <input type="text" name="className" value="${query.className}" maxlength="10" class="input-small"/>
+        &nbsp;
+        <input id="btnSubmit" class="btn btn-primary" type="button" value="查询" onclick="goSearch()"/>
+        <input class="btn btn-primary" type="button" value="查看统计图" onclick="viewClassEcharts()"/>
+    </div>
+</form>
+<tags:message content="${message}"/>
+<table id="contentTable" class="table table-striped table-bordered table-condensed">
+    <thead>
+    <tr>
+        <th>班级</th>
+        <th>平均分</th>
+        <th>最高分</th>
+        <th>最低分</th>
+        <th>及格数</th>
+        <th>及格率</th>
+        <th>及格数</th>
+        <th>优秀率</th>
+    </tr>
+    </thead>
+    <tbody>
+    <c:forEach items="${list}" var="reportSubjectClass">
+        <tr>
+            <td>${reportSubjectClass.className}</td>
+            <td>${reportSubjectClass.avgScore}</td>
+            <td>${reportSubjectClass.maxScore}</td>
+            <td>${reportSubjectClass.minScore}</td>
+            <td>${reportSubjectClass.passCount}</td>
+            <td>${reportSubjectClass.passRate}</td>
+            <td>${reportSubjectClass.excellentCount}</td>
+            <td>${reportSubjectClass.excellentRate}</td>
+        </tr>
+    </c:forEach>
+    </tbody>
+</table>
+<script type="text/javascript">
+
+    function viewClassEcharts() {
+        var classs = new Array();
+        var avgScores = new Array();
+        var maxScores = new Array();
+        var minScores = new Array();
+        var passRates = new Array();
+        var excellentRates = new Array();
+
+        $('tbody tr').each(function (i) {
+            $(this).children('td').each(function (j) {
+                if(j == 0){
+                    classs.push($(this).text());
+                } else if(j == 1){
+                    avgScores.push($(this).text());
+                } else if(j == 2){
+                    maxScores.push($(this).text());
+                } else if(j == 3){
+                    minScores.push($(this).text());
+                } else if(j == 5){
+                    passRates.push($(this).text()*100);
+                } else if(j == 7){
+                    excellentRates.push($(this).text()*100);
+                }
+            });
+        });
+
+        var title = '';
+
+        var imageModal = new jBox('Modal');
+        imageModal.setWidth($(window).width() * 0.9);
+        imageModal.setHeight($(window).height() * 0.85);
+        imageModal.setTitle('课程班级成绩分析');
+        imageModal.setContent($('#echart-view-content'));
+        imageModal.open();
+
+        var myChart = echarts.init(document.getElementById('echart-content'));
+
+        // 指定图表的配置项和数据
+        var option = {
+            title: {
+                text: '课程班级成绩分析'
+                // textAlign:'center'
+            },
+            tooltip: {},
+            legend: {
+                data: ['平均分','最高分','最低分','及格率','优秀率']
+            },
+            dataZoom: [{
+                type: 'slider',
+                show: true,
+                xAxisIndex: [0],
+                left: '9%',
+                bottom: -5,
+                start: 10,
+                end: 90 //初始化滚动条
+            }],
+            xAxis: {
+                axisLabel: {
+                    interval:0,
+                    rotate:40
+                },
+                data: classs
+            },
+            yAxis: [
+                {
+                    type: 'value'
+                },
+                {
+                    type: 'value'
+                }
+            ],
+            series: [{
+                name: '平均分',
+                type: 'bar',
+                data: avgScores
+            },{
+                name: '最高分',
+                type: 'bar',
+                data: maxScores
+            },{
+                name: '最低分',
+                type: 'bar',
+                data: minScores
+            },{
+                name: '及格率',
+                type: 'line',
+                yAxisIndex : 1,
+                data: passRates
+            },{
+                name: '优秀率',
+                type: 'line',
+                yAxisIndex : 1,
+                data: excellentRates
+            }]
+        };
+        // 使用刚指定的配置项和数据显示图表。
+        myChart.setOption(option);
+    }
+
+
+    function page(n, s) {
+        $("#pageNumber").val(n);
+        $("#pageSize").val(s);
+        $("#searchForm").submit();
+        return false;
+    }
+
+    function goSearch() {
+        $("#pageNumber").val(1);
+        $("#pageSize").val('${query.pageSize}');
+        if ($("#subjectCode").val() == null || $("#subjectCode").val() == '') {
+            alert('请选择科目');
+            return;
+        }
+        $("#searchForm").submit();
+        return false;
+    }
+
+    $(document).keydown(function (event) {
+        if (event.keyCode == 13 || event.keyCode == 108) {
+            goSearch();
+            return false;
+        }
+    });
+</script>
+<div id="echart-view-content" class="container-fluid" style="display:none" align="center">
+    <div id="echart-content" style="width: 100%;height:520px;"/>
+</div>
+</body>
+</html>

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

@@ -0,0 +1,201 @@
+<%@ 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" %>
+    <%@include file="/WEB-INF/views/include/dialog.jsp" %>
+    <link rel="stylesheet" type="text/css" href="${ctxStatic}/jBox/Source/jBox.css">
+    <script type="text/javascript" src="${ctxStatic}/jBox/Source/jBox.min.js"></script>
+    <script type="text/javascript" src="${ctxStatic}/echarts/echarts.min.js"></script>
+    <style type="text/css">.sort {
+        color: #0663A2;
+        cursor: pointer;
+    }</style>
+</head>
+<body>
+<ul class="nav nav-tabs">
+
+    <li class="active"><a href="${ctx}/admin/exam/reportSubjectCollege?subjectCode=${query.subjectCode}">课程学院分析表</a>
+    </li>
+    <li><a href="${ctx}/admin/exam/reportSubjectTeacher?subjectCode=${query.subjectCode}">课程任课老师分析表</a>
+    </li>
+    <li><a href="${ctx}/admin/exam/reportSubjectClass?subjectCode=${query.subjectCode}">课程班级分析表</a></li>
+    <li><a href="${ctx}/admin/exam/reportSubjectQuestion?subjectCode=${query.subjectCode}&objective=true">客观题分析表</a>
+    </li>
+    <li><a href="${ctx}/admin/exam/reportSubjectQuestion?subjectCode=${query.subjectCode}&objective=false">主观题分析表</a>
+    </li>
+    <li><a href="${ctx}/admin/exam/reportSubjectGroup?subjectCode=${query.subjectCode}">大题统计分析表</a></li>
+</ul>
+<form id="searchForm" action="${ctx}/admin/exam/reportSubjectCollege" method="post" class="breadcrumb form-search">
+    <input id="pageNumber" name="pageNumber" type="hidden"/>
+    <input id="pageSize" name="pageSize" type="hidden"/>
+    <div>
+        <label>科目:</label>
+        <select class="input-large" id="subjectCode" name="subjectCode">
+            <option value="">请选择</option>
+            <c:forEach items="${subjectList }" var="subject">
+                <option value="${subject.code }"
+                        <c:if test="${query.subjectCode eq subject.code }">selected</c:if>>${subject.code}-${subject.name}</option>
+            </c:forEach>
+        </select>
+        &nbsp;
+        <input id="btnSubmit" class="btn btn-primary" type="button" value="查询" onclick="goSearch()"/>
+        <input class="btn btn-primary" type="button" value="查看统计图" onclick="viewCollegeEcharts()"/>
+    </div>
+</form>
+<tags:message content="${message}"/>
+<table id="contentTable" class="table table-striped table-bordered table-condensed">
+    <thead>
+    <tr>
+        <th>学生院系</th>
+        <th>平均分</th>
+        <th>最高分</th>
+        <th>最低分</th>
+        <th>及格数</th>
+        <th>及格率</th>
+        <th>优秀率</th>
+    </tr>
+    </thead>
+    <tbody>
+    <c:forEach items="${list}" var="reportSubjectCollege">
+        <tr>
+            <td>${reportSubjectCollege.collegeName}</td>
+            <td>${reportSubjectCollege.avgScore}</td>
+            <td>${reportSubjectCollege.maxScore}</td>
+            <td>${reportSubjectCollege.minScore}</td>
+            <td>${reportSubjectCollege.passCount}</td>
+            <td>${reportSubjectCollege.passRate}</td>
+            <td>${reportSubjectCollege.excellentRate}</td>
+        </tr>
+    </c:forEach>
+    </tbody>
+</table>
+<script type="text/javascript">
+
+    function viewCollegeEcharts() {
+        var colleges = new Array();
+        var avgScores = new Array();
+        var maxScores = new Array();
+        var minScores = new Array();
+        var passRates = new Array();
+        var excellentRates = new Array();
+
+        $('tbody tr').each(function (i) {
+            $(this).children('td').each(function (j) {
+                if(j == 0){
+                    colleges.push($(this).text());
+                } else if(j == 1){
+                    avgScores.push($(this).text());
+                } else if(j == 2){
+                    maxScores.push($(this).text());
+                } else if(j == 3){
+                    minScores.push($(this).text());
+                } else if(j == 5){
+                    passRates.push($(this).text()*100);
+                } else if(j == 6){
+                    excellentRates.push($(this).text()*100);
+                }
+            });
+        });
+
+        var title = '';
+
+        var imageModal = new jBox('Modal');
+        imageModal.setWidth($(window).width() * 0.9);
+        imageModal.setHeight($(window).height() * 0.85);
+        imageModal.setTitle('课程学院成绩分析');
+        imageModal.setContent($('#echart-view-content'));
+        imageModal.open();
+
+        var myChart = echarts.init(document.getElementById('echart-content'));
+
+        // 指定图表的配置项和数据
+        var option = {
+            title: {
+                text: '学院成绩分析'
+                // textAlign:'center'
+            },
+            tooltip: {},
+            legend: {
+                data: ['平均分','最高分','最低分','优秀率','及格率']
+            },
+            dataZoom: [{
+                type: 'slider',
+                show: true,
+                xAxisIndex: [0],
+                left: '9%',
+                bottom: -5,
+                start: 10,
+                end: 90 //初始化滚动条
+            }],
+            xAxis: {
+                axisLabel: {
+                    interval:0,
+                    rotate:40
+                },
+                data: colleges
+            },
+            yAxis: [
+                {
+                    type: 'value'
+                }
+            ],
+            series: [{
+                name: '平均分',
+                type: 'bar',
+                data: avgScores
+            },{
+                name: '最高分',
+                type: 'bar',
+                data: maxScores
+            },{
+                name: '最低分',
+                type: 'bar',
+                data: minScores
+            },{
+                name: '优秀率',
+                type: 'bar',
+                data: excellentRates
+            },{
+                name: '及格率',
+                type: 'line',
+                data: passRates
+            }]
+        };
+        // 使用刚指定的配置项和数据显示图表。
+        myChart.setOption(option);
+    }
+
+    function page(n, s) {
+        $("#pageNumber").val(n);
+        $("#pageSize").val(s);
+        $("#searchForm").submit();
+        return false;
+    }
+
+    function goSearch() {
+        $("#pageNumber").val(1);
+        $("#pageSize").val('${query.pageSize}');
+        if ($("#subjectCode").val() == null || $("#subjectCode").val() == '') {
+            alert('请选择科目');
+            return;
+        }
+        $("#searchForm").submit();
+        return false;
+    }
+
+    $(document).keydown(function (event) {
+        if (event.keyCode == 13 || event.keyCode == 108) {
+            goSearch();
+            return false;
+        }
+    });
+</script>
+
+<div id="echart-view-content" class="container-fluid" style="display:none" align="center">
+    <div id="echart-content" style="width: 100%;height:520px;"/>
+</div>
+</body>
+</html>

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

@@ -0,0 +1,199 @@
+<%@ 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" %>
+    <%@include file="/WEB-INF/views/include/dialog.jsp" %>
+    <link rel="stylesheet" type="text/css" href="${ctxStatic}/jBox/Source/jBox.css">
+    <script type="text/javascript" src="${ctxStatic}/jBox/Source/jBox.min.js"></script>
+    <script type="text/javascript" src="${ctxStatic}/echarts/echarts.min.js"></script>
+    <style type="text/css">.sort {
+        color: #0663A2;
+        cursor: pointer;
+    }</style>
+</head>
+<body>
+<ul class="nav nav-tabs">
+
+    <li><a href="${ctx}/admin/exam/reportSubjectCollege?subjectCode=${query.subjectCode}">课程学院分析表</a></li>
+    <li><a href="${ctx}/admin/exam/reportSubjectTeacher?subjectCode=${query.subjectCode}">课程任课老师分析表</a></li>
+    <li><a href="${ctx}/admin/exam/reportSubjectClass?subjectCode=${query.subjectCode}">课程班级分析表</a></li>
+    <li><a href="${ctx}/admin/exam/reportSubjectQuestion?subjectCode=${query.subjectCode}&objective=true">客观题分析表</a>
+    </li>
+    <li><a href="${ctx}/admin/exam/reportSubjectQuestion?subjectCode=${query.subjectCode}&objective=false">主观题分析表</a>
+    </li>
+    <li class="active"><a href="${ctx}/admin/exam/reportSubjectGroup?subjectCode=${query.subjectCode}">大题统计分析表</a></li>
+</ul>
+<form id="searchForm" action="${ctx}/admin/exam/reportSubjectGroup" method="post" class="breadcrumb form-search">
+    <div>
+        <label>科目:</label>
+        <select class="input-large" id="subjectCode" name="subjectCode">
+            <option value="">请选择</option>
+            <c:forEach items="${subjectList }" var="subject">
+                <option value="${subject.code }"
+                        <c:if test="${query.subjectCode eq subject.code }">selected</c:if>>${subject.code}-${subject.name}</option>
+            </c:forEach>
+        </select>
+        &nbsp;
+        <input id="btnSubmit" class="btn btn-primary" type="button" value="查询" onclick="goSearch()"/>
+        <input class="btn btn-primary" type="button" value="查看统计图" onclick="viewGroupEcharts()"/>
+    </div>
+</form>
+<tags:message content="${message}"/>
+<table id="contentTable" class="table table-striped table-bordered table-condensed">
+    <thead>
+    <tr>
+        <th>题型</th>
+        <th>满分</th>
+        <th>最高分</th>
+        <th>最低分</th>
+        <th>平均分</th>
+        <th>标准差</th>
+        <th>差异系数(%)</th>
+        <th>零分人数</th>
+        <th>满分人数</th>
+    </tr>
+    </thead>
+    <tbody>
+    <c:forEach items="${list}" var="group">
+        <tr>
+            <td>${group.groupName}</td>
+            <td>${group.totalScore}</td>
+            <td>${group.maxScore}</td>
+            <td>${group.minScore}</td>
+            <td>${group.avgScore}</td>
+            <td>${group.SD}</td>
+            <td>${group.CV}</td>
+            <td>${group.zeroCount}</td>
+            <td>${group.fullCount}</td>
+        </tr>
+    </c:forEach>
+    </tbody>
+</table>
+<script type="text/javascript">
+
+
+    function viewGroupEcharts() {
+        var groupNames = new Array();
+        var fullScores = new Array();
+        var maxScores = new Array();
+        var minScores = new Array();
+        var avgScores = new Array();
+        var sds = new Array();
+
+        $('tbody tr').each(function (i) {
+            $(this).children('td').each(function (j) {
+                if (j == 0) {
+                    groupNames.push($(this).text());
+                } else if (j == 1) {
+                    fullScores.push($(this).text());
+                } else if (j == 2) {
+                    maxScores.push($(this).text());
+                } else if (j == 3) {
+                    minScores.push($(this).text());
+                } else if (j == 4) {
+                    avgScores.push($(this).text());
+                } else if (j == 5) {
+                    sds.push($(this).text());
+                }
+            });
+        });
+
+        var title = '';
+
+        var imageModal = new jBox('Modal');
+        imageModal.setWidth($(window).width() * 0.9);
+        imageModal.setHeight($(window).height() * 0.85);
+        imageModal.setTitle('大题型分析');
+        imageModal.setContent($('#echart-view-content'));
+        imageModal.open();
+
+        var myChart = echarts.init(document.getElementById('echart-content'));
+
+        // 指定图表的配置项和数据
+        var option = {
+            title: {
+                text: '大题型分析'
+                // textAlign:'center'
+            },
+            tooltip: {},
+            legend: {
+                data: ['满分', '最高分', '最低分', '平均分', '标准差']
+            },
+            dataZoom: [{
+                type: 'slider',
+                show: true,
+                xAxisIndex: [0],
+                left: '9%',
+                bottom: -5,
+                start: 10,
+                end: 90 //初始化滚动条
+            }],
+            xAxis: {
+                axisLabel: {
+                    interval: 0,
+                    rotate: 40
+                },
+                data: groupNames
+            },
+            yAxis: [
+                {
+                    type: 'value'
+                },
+                {
+                    type: 'value'
+                }
+            ],
+            series: [{
+                name: '满分',
+                type: 'bar',
+                data: fullScores
+            }, {
+                name: '最高分',
+                type: 'bar',
+                yAxisIndex: 1,
+                data: maxScores
+            }, {
+                name: '最低分',
+                type: 'bar',
+                data: minScores
+            }, {
+                name: '平均分',
+                type: 'line',
+                data: avgScores
+            }, {
+                name: '标注差',
+                type: 'line',
+                yAxisIndex: 1,
+                data: sds
+            }]
+        };
+        // 使用刚指定的配置项和数据显示图表。
+        myChart.setOption(option);
+    }
+
+
+    function goSearch() {
+        if ($("#subjectCode").val() == null || $("#subjectCode").val() == '') {
+            alert('请选择科目');
+            return;
+        }
+        $("#searchForm").submit();
+        return false;
+    }
+
+    $(document).keydown(function (event) {
+        if (event.keyCode == 13 || event.keyCode == 108) {
+            goSearch();
+            return false;
+        }
+    });
+</script>
+
+<div id="echart-view-content" class="container-fluid" style="display:none" align="center">
+    <div id="echart-content" style="width: 100%;height:520px;"/>
+</div>
+</body>
+</html>

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

@@ -0,0 +1,190 @@
+<%@ 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" %>
+    <%@include file="/WEB-INF/views/include/dialog.jsp" %>
+    <link rel="stylesheet" type="text/css" href="${ctxStatic}/jBox/Source/jBox.css">
+    <script type="text/javascript" src="${ctxStatic}/jBox/Source/jBox.min.js"></script>
+    <script type="text/javascript" src="${ctxStatic}/echarts/echarts.min.js"></script>
+    <style type="text/css">.sort {
+        color: #0663A2;
+        cursor: pointer;
+    }</style>
+</head>
+<body>
+<ul class="nav nav-tabs">
+
+    <li><a href="${ctx}/admin/exam/reportSubjectCollege?subjectCode=${query.subjectCode}">课程学院分析表</a></li>
+    <li><a href="${ctx}/admin/exam/reportSubjectTeacher?subjectCode=${query.subjectCode}">课程任课老师分析表</a></li>
+    <li><a href="${ctx}/admin/exam/reportSubjectClass?subjectCode=${query.subjectCode}">课程班级分析表</a></li>
+    <li id="objectiveLi"><a
+            href="${ctx}/admin/exam/reportSubjectQuestion?subjectCode=${query.subjectCode}&objective=true">客观题分析表</a>
+    </li>
+    <li id="subjectiveLi"><a
+            href="${ctx}/admin/exam/reportSubjectQuestion?subjectCode=${query.subjectCode}&objective=false">主观题分析表</a>
+    </li>
+    <li><a href="${ctx}/admin/exam/reportSubjectGroup?subjectCode=${query.subjectCode}">大题统计分析表</a></li>
+</ul>
+<form id="searchForm" action="${ctx}/admin/exam/reportSubjectQuestion" method="post" class="breadcrumb form-search">
+    <input id="objective" name="objective" value="${query.objective}" type="hidden"/>
+    <div>
+        <label>科目:</label>
+        <select class="input-large" id="subjectCode" name="subjectCode">
+            <option value="">请选择</option>
+            <c:forEach items="${subjectList }" var="subject">
+                <option value="${subject.code }"
+                        <c:if test="${query.subjectCode eq subject.code }">selected</c:if>>${subject.code}-${subject.name}</option>
+            </c:forEach>
+        </select>
+        &nbsp;
+        <input id="btnSubmit" class="btn btn-primary" type="button" value="查询" onclick="goSearch()"/>
+        <input class="btn btn-primary" type="button" value="查看统计图" onclick="viewQuestionEcharts()"/>
+
+    </div>
+</form>
+<tags:message content="${message}"/>
+<table id="contentTable" class="table table-striped table-bordered table-condensed">
+    <thead>
+    <tr>
+        <th>题目名称</th>
+        <th>单题分数</th>
+        <th>单题平均分</th>
+        <th>单题标准差</th>
+        <th>得分率</th>
+        <th>满分率</th>
+    </tr>
+    </thead>
+    <tbody>
+    <c:forEach items="${list}" var="question">
+        <tr>
+            <td>${question.questionName}</td>
+            <td>${question.totalScore}</td>
+            <td>${question.avgScore}</td>
+            <td>${question.sd}</td>
+            <td>${question.scoreRate}</td>
+            <td>${question.fullScoreRate}</td>
+        </tr>
+    </c:forEach>
+    </tbody>
+</table>
+<script type="text/javascript">
+    $(document).ready(function () {
+        var objective = '${query.objective}';
+        if (objective == 'true') {
+            $('#objectiveLi').addClass('active');
+        } else {
+            $('#subjectiveLi').addClass('active');
+        }
+    });
+
+    function viewQuestionEcharts() {
+        var objective = '${query.objective}';
+        var questions = new Array();
+        var avgScores = new Array();
+        var scoreRates = new Array();
+        var fullScoreRates = new Array();
+
+        $('tbody tr').each(function (i) {
+            $(this).children('td').each(function (j) {
+                if(j == 0){
+                    questions.push($(this).text());
+                } else if(j == 2){
+                    avgScores.push($(this).text());
+                } else if(j == 4){
+                    scoreRates.push($(this).text()*100);
+                } else if(j == 5){
+                    fullScoreRates.push($(this).text()*100);
+                }
+            });
+        });
+
+        var title = '';
+
+        var imageModal = new jBox('Modal');
+        imageModal.setWidth($(window).width() * 0.9);
+        imageModal.setHeight($(window).height() * 0.85);
+        imageModal.setTitle(objective == 'true'?'客观题分析':'主观题分析');
+        imageModal.setContent($('#echart-view-content'));
+        imageModal.open();
+
+        var myChart = echarts.init(document.getElementById('echart-content'));
+
+        // 指定图表的配置项和数据
+        var option = {
+            title: {
+                text: objective == 'true'?'客观题分析':'主观题分析'
+                // textAlign:'center'
+            },
+            tooltip: {},
+            legend: {
+                data: ['平均分','得分率','满分率']
+            },
+            dataZoom: [{
+                type: 'slider',
+                show: true,
+                xAxisIndex: [0],
+                left: '9%',
+                bottom: -5,
+                start: 10,
+                end: 90 //初始化滚动条
+            }],
+            xAxis: {
+                axisLabel: {
+                    interval:0,
+                    rotate:40
+                },
+                data: questions
+            },
+            yAxis: [
+                {
+                    type: 'value'
+                },
+                {
+                    type: 'value'
+                }
+            ],
+            series: [{
+                name: '平均分',
+                type: 'bar',
+                data: avgScores
+            },{
+                name: '得分率',
+                type: 'line',
+                yAxisIndex : 1,
+                data: scoreRates
+            },{
+                name: '满分率',
+                type: 'line',
+                yAxisIndex : 1,
+                data: fullScoreRates
+            }]
+        };
+        // 使用刚指定的配置项和数据显示图表。
+        myChart.setOption(option);
+    }
+
+
+    function goSearch() {
+        if ($("#subjectCode").val() == null || $("#subjectCode").val() == '') {
+            alert('请选择科目');
+            return;
+        }
+        $("#searchForm").submit();
+        return false;
+    }
+
+    $(document).keydown(function (event) {
+        if (event.keyCode == 13 || event.keyCode == 108) {
+            goSearch();
+            return false;
+        }
+    });
+</script>
+<div id="echart-view-content" class="container-fluid" style="display:none" align="center">
+    <div id="echart-content" style="width: 100%;height:520px;"/>
+</div>
+</body>
+</html>

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

@@ -0,0 +1,163 @@
+<%@ page contentType="text/html;charset=UTF-8" %>
+<%@ include file="/WEB-INF/views/include/taglib.jsp" %>
+<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
+<html>
+<head>
+    <title>成绩分析</title>
+    <meta name="decorator" content="default"/>
+    <%@include file="/WEB-INF/views/include/head.jsp" %>
+    <%@include file="/WEB-INF/views/include/dialog.jsp" %>
+    <link rel="stylesheet" type="text/css" href="${ctxStatic}/jBox/Source/jBox.css">
+    <script type="text/javascript" src="${ctxStatic}/jBox/Source/jBox.min.js"></script>
+    <script type="text/javascript" src="${ctxStatic}/echarts/echarts.min.js"></script>
+    <style type="text/css">.sort {
+        color: #0663A2;
+        cursor: pointer;
+    }</style>
+</head>
+<body>
+<ul class="nav nav-tabs">
+    <li class="active"><a href="${ctx}/admin/exam/reportSubjectRange">课程分段统计</a></li>
+    <li><a href="${ctx}/admin/exam/reportSubject">课程总量统计</a></li>
+</ul>
+<form id="searchForm" action="${ctx}/admin/exam/reportSubjectRange" method="post" class="breadcrumb form-search">
+    <input type="hidden" id="pageNumber" name="pageNumber" value="${query.pageNumber }"/>
+    <input type="hidden" id="pageSize" name="pageSize" value="${query.pageSize }"/>
+    <div>
+        <label>科目</label>
+        <select class="input-large" id="subjectCode" name="subjectCode">
+            <option value="">请选择</option>
+            <c:forEach items="${subjectList }" var="subject">
+                <option value="${subject.code }"
+                        <c:if test="${query.subjectCode eq subject.code }">selected</c:if>>${subject.code}-${subject.name}</option>
+            </c:forEach>
+        </select>
+        <input id="btnSubmit" class="btn btn-primary" type="button" value="查询" onclick="goSearch()"/>
+        &nbsp;
+    </div>
+</form>
+<tags:message content="${message}"/>
+<table id="contentTable" class="table table-striped table-bordered table-condensed">
+    <thead>
+    <tr>
+        <th>课程</th>
+        <th>层次</th>
+        <th>0-4</th>
+        <th>0-占比(%)</th>
+        <th>50-</th>
+        <th>50-占比(%)</th>
+        <th>60-</th>
+        <th>60-占比(%)</th>
+        <th>70-</th>
+        <th>70-占比(%)</th>
+        <th>80-</th>
+        <th>80-占比(%)</th>
+        <th>90-</th>
+        <th>90-占比(%)</th>
+        <th><60</th>
+        <th><60占比(%)</th>
+        <th>>=60</th>
+        <th>>=60占比(%)</th>
+        <th>总数</th>
+        <th>操作</th>
+    </tr>
+    </thead>
+    <tbody>
+    <c:forEach items="${list}" var="subject">
+        <tr>
+            <td>
+                <a href="${ctx}/admin/exam/reportSubjectCollege?subjectCode=${subject.subjectCode}">${subject.subjectCode}-${subject.subjectName}</a>
+            </td>
+            <td>${subject.level}</td>
+            <td>${subject.count0_49}</td>
+            <td>${subject.percent0_49}</td>
+            <td>${subject.count50_59}</td>
+            <td>${subject.percent50_59}</td>
+            <td>${subject.count60_69}</td>
+            <td>${subject.percent60_69}</td>
+            <td>${subject.count70_79}</td>
+            <td>${subject.percent70_79}</td>
+            <td>${subject.count80_89}</td>
+            <td>${subject.percent80_89}</td>
+            <td>${subject.count90_100}</td>
+            <td>${subject.percent90_100}</td>
+            <td>${subject.lt60}</td>
+            <td>${subject.percent_lt60}</td>
+            <td>${subject.mte60}</td>
+            <td>${subject.percent_mte60}</td>
+            <td>${subject.totalCount}</td>
+            <td><a href="#"
+                   onclick="viewEcharts('${subject.subjectCode}','${subject.subjectName}',${subject.percent0_49},${subject.percent50_59},${subject.percent60_69},${subject.percent70_79},${subject.percent80_89},${subject.percent90_100})">分段图</a>
+            </td>
+        </tr>
+    </c:forEach>
+    </tbody>
+</table>
+<div class="pagination">${query}</div>
+<script type="text/javascript">
+    function page(n, s) {
+        $("#pageNumber").val(n);
+        $("#pageSize").val(s);
+        $("#searchForm").attr('action', '${ctx}/admin/exam/reportSubjectRange');
+        $("#searchForm").submit();
+        return false;
+    }
+
+    function goSearch() {
+        $("#pageNumber").val(1);
+        $("#pageSize").val('${query.pageSize}');
+        $("#searchForm").attr('action', '${ctx}/admin/exam/reportSubjectRange');
+        $("#searchForm").submit();
+        return false;
+    }
+
+    function viewEcharts(code, name, d1, d2, d3, d4, d5, d6) {
+
+        var title = name + ' ' + code;
+
+        var imageModal = new jBox('Modal');
+        imageModal.setWidth($(window).width() * 0.9);
+        imageModal.setHeight($(window).height() * 0.85);
+        imageModal.setTitle('课程成绩分段图');
+        imageModal.setContent($('#echart-view-content'));
+        imageModal.open();
+
+        var myChart = echarts.init(document.getElementById('echart-content'));
+
+        // 指定图表的配置项和数据
+        var option = {
+            title: {
+                text: title
+                // textAlign:'center'
+            },
+            tooltip: {},
+            legend: {
+                data: [title]
+            },
+            xAxis: {
+                data: ["0-49占比(%)", "50-59占比(%)", "60-69占比(%)", "70-79占比(%)", "80-89占比(%)", "90-100占比(%)"]
+            },
+            yAxis: [
+                {
+                    type: 'value'
+                }
+            ],
+            series: [{
+                name: title,
+                type: 'bar',
+                data: [d1, d2, d3, d4, d5, d6]
+            }]
+        };
+        // 使用刚指定的配置项和数据显示图表。
+        myChart.setOption(option);
+
+    }
+
+</script>
+<div id="echart-view-content" class="container-fluid" style="display:none" align="center">
+    <div id="echart-content" style="width: 80%;height:500px;"/>
+</div>
+</body>
+
+
+</html>

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

@@ -0,0 +1,226 @@
+<%@ 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" %>
+    <%@include file="/WEB-INF/views/include/dialog.jsp" %>
+    <link rel="stylesheet" type="text/css" href="${ctxStatic}/jBox/Source/jBox.css">
+    <script type="text/javascript" src="${ctxStatic}/jBox/Source/jBox.min.js"></script>
+    <script type="text/javascript" src="${ctxStatic}/echarts/echarts.min.js"></script>
+    <style type="text/css">.sort {
+        color: #0663A2;
+        cursor: pointer;
+    }</style>
+</head>
+<body>
+<ul class="nav nav-tabs">
+
+    <li><a href="${ctx}/admin/exam/reportSubjectCollege?subjectCode=${query.subjectCode}">课程学院分析表</a></li>
+    <li class="active"><a href="${ctx}/admin/exam/reportSubjectTeacher?subjectCode=${query.subjectCode}">课程任课老师分析表</a>
+    </li>
+    <li><a href="${ctx}/admin/exam/reportSubjectClass?subjectCode=${query.subjectCode}">课程班级分析表</a></li>
+    <li><a href="${ctx}/admin/exam/reportSubjectQuestion?subjectCode=${query.subjectCode}&objective=true">客观题分析表</a>
+    </li>
+    <li><a href="${ctx}/admin/exam/reportSubjectQuestion?subjectCode=${query.subjectCode}&objective=false">主观题分析表</a>
+    </li>
+    <li><a href="${ctx}/admin/exam/reportSubjectGroup?subjectCode=${query.subjectCode}">大题统计分析表</a></li>
+</ul>
+<form id="searchForm" action="${ctx}/admin/exam/reportSubjectTeacher" method="post" class="breadcrumb form-search">
+    <input id="pageNumber" name="pageNumber" type="hidden"/>
+    <input id="pageSize" name="pageSize" type="hidden"/>
+    <div>
+        <label>科目:</label>
+        <select class="input-large" id="subjectCode" name="subjectCode">
+            <option value="">请选择</option>
+            <c:forEach items="${subjectList }" var="subject">
+                <option value="${subject.code }"
+                        <c:if test="${query.subjectCode eq subject.code }">selected</c:if>>${subject.code}-${subject.name}</option>
+            </c:forEach>
+        </select>
+        <label>任课老师:</label>
+        <input type="text" name="teacherName" value="${query.teacherName}" maxlength="10" class="input-small"/>
+        &nbsp;
+        <input id="btnSubmit" class="btn btn-primary" type="button" value="查询" onclick="goSearch()"/>
+        <input class="btn btn-primary" type="button" value="查看统计图" onclick="viewTeacherEcharts()"/>
+    </div>
+</form>
+<tags:message content="${message}"/>
+<table id="contentTable" class="table table-striped table-bordered table-condensed">
+    <thead>
+    <tr>
+        <th>任课老师</th>
+        <th>实考</th>
+        <th>及格</th>
+        <th>优秀</th>
+        <th>最高分</th>
+        <th>最低分</th>
+        <th>及格率(%)</th>
+        <th>优秀率(%)</th>
+        <th>平均数</th>
+        <th>平均相对分</th>
+    </tr>
+    </thead>
+    <tbody>
+    <c:forEach items="${list}" var="reportSubjectteacher">
+        <tr>
+            <td><a href="#" onclick="redirect2Class('${ctx}/admin/exam/reportSubjectTeacherClass',
+                    '${reportSubjectteacher.teacherName}',
+                ${reportSubjectteacher.examId},
+                    '${reportSubjectteacher.subjectCode}')">${reportSubjectteacher.teacherName}</a></td>
+            <td>${reportSubjectteacher.realityCount}</td>
+            <td>${reportSubjectteacher.passCount}</td>
+            <td>${reportSubjectteacher.excellentCount}</td>
+            <td>${reportSubjectteacher.maxScore}</td>
+            <td>${reportSubjectteacher.minScore}</td>
+            <td>${reportSubjectteacher.passRate}</td>
+            <td>${reportSubjectteacher.excellentRate}</td>
+            <td>${reportSubjectteacher.avgScore}</td>
+            <td>${reportSubjectteacher.relativeAvgScore}</td>
+        </tr>
+    </c:forEach>
+    </tbody>
+</table>
+<script type="text/javascript">
+
+    function viewTeacherEcharts() {
+        var tearchers = new Array();
+        var avgScores = new Array();
+        var maxScores = new Array();
+        var minScores = new Array();
+        var passRates = new Array();
+        var excellentRates = new Array();
+        var relativeAvgScore = new Array();
+
+        $('tbody tr').each(function (i) {
+            $(this).children('td').each(function (j) {
+                if(j == 0){
+                    tearchers.push($(this).text());
+                } else if(j == 8){
+                    avgScores.push($(this).text());
+                } else if(j == 4){
+                    maxScores.push($(this).text());
+                } else if(j == 5){
+                    minScores.push($(this).text());
+                } else if(j == 6){
+                    passRates.push($(this).text()*100);
+                } else if(j == 7){
+                    excellentRates.push($(this).text()*100);
+                } else if(j == 9){
+                    relativeAvgScore.push($(this).text());
+                }
+            });
+        });
+
+        var title = '';
+
+        var imageModal = new jBox('Modal');
+        imageModal.setWidth($(window).width() * 0.9);
+        imageModal.setHeight($(window).height() * 0.85);
+        imageModal.setTitle('任课老师成绩分析');
+        imageModal.setContent($('#echart-view-content'));
+        imageModal.open();
+
+        var myChart = echarts.init(document.getElementById('echart-content'));
+
+        // 指定图表的配置项和数据
+        var option = {
+            title: {
+                text: '任课老师成绩分析'
+                // textAlign:'center'
+            },
+            tooltip: {},
+            legend: {
+                data: ['最高分','最低分','平均分','相对平均分','优秀率','及格率']
+            },
+            dataZoom: [{
+                type: 'slider',
+                show: true,
+                xAxisIndex: [0],
+                left: '9%',
+                bottom: -5,
+                start: 10,
+                end: 90 //初始化滚动条
+            }],
+            xAxis: {
+                axisLabel: {
+                    interval:0,
+                    rotate:40
+                },
+                data: tearchers
+            },
+            yAxis: [
+                {
+                    type: 'value'
+                },
+                {
+                    type: 'value'
+                }
+            ],
+            series: [{
+                name: '最高分',
+                type: 'bar',
+                data: maxScores
+            },{
+                name: '最低分',
+                type: 'bar',
+                data: minScores
+            },{
+                name: '平均分',
+                type: 'bar',
+                data: avgScores
+            },{
+                name: '相对平均分',
+                type: 'line',
+                yAxisIndex : 1,
+                data: relativeAvgScore
+            },{
+                name: '及格率',
+                type: 'line',
+                data: passRates
+            },{
+                name: '优秀率',
+                type: 'line',
+                data: excellentRates
+            }]
+        };
+        // 使用刚指定的配置项和数据显示图表。
+        myChart.setOption(option);
+    }
+
+    function redirect2Class(url, name, examId, subjectCode) {
+        url = url + "?teacherName=" + name + "&examId=" + examId + "&subjectCode=" + subjectCode;
+        location.href = url;
+    }
+
+    function page(n, s) {
+        $("#pageNumber").val(n);
+        $("#pageSize").val(s);
+        $("#searchForm").submit();
+        return false;
+    }
+
+    function goSearch() {
+        $("#pageNumber").val(1);
+        $("#pageSize").val('${query.pageSize}');
+        if ($("#subjectCode").val() == null || $("#subjectCode").val() == '') {
+            alert('请选择科目');
+            return;
+        }
+        $("#searchForm").submit();
+        return false;
+    }
+
+    $(document).keydown(function (event) {
+        if (event.keyCode == 13 || event.keyCode == 108) {
+            goSearch();
+            return false;
+        }
+    });
+</script>
+<div id="echart-view-content" class="container-fluid" style="display:none" align="center">
+    <div id="echart-content" style="width: 100%;height:520px;"/>
+</div>
+</body>
+</html>

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

@@ -0,0 +1,171 @@
+<%@ 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" %>
+    <%@include file="/WEB-INF/views/include/dialog.jsp" %>
+    <link rel="stylesheet" type="text/css" href="${ctxStatic}/jBox/Source/jBox.css">
+    <script type="text/javascript" src="${ctxStatic}/jBox/Source/jBox.min.js"></script>
+    <script type="text/javascript" src="${ctxStatic}/echarts/echarts.min.js"></script>
+    <style type="text/css">.sort {
+        color: #0663A2;
+        cursor: pointer;
+    }</style>
+</head>
+<body>
+<ul class="nav nav-tabs">
+    <li class="active"><a href="#">任课老师班级分析表</a></li>
+</ul>
+<form id="searchForm" action="${ctx}/admin/exam/reportSubjectTeacher" method="post" class="breadcrumb form-search">
+    &nbsp;&nbsp;科目:${subjectName}&nbsp;&nbsp;&nbsp;&nbsp;任课老师:${query.teacherName} &nbsp;&nbsp;
+    <a href="#" class="btn btn-primary" onclick="viewTeacherClassEcharts()"/>查看统计图</a>
+    <a href="#" class="btn" onclick="javascript:history.go(-1)"/>返回</a>
+</form>
+<tags:message content="${message}"/>
+<table id="contentTable" class="table table-striped table-bordered table-condensed">
+    <thead>
+    <tr>
+        <th>班级</th>
+        <th>实考</th>
+        <th>及格</th>
+        <th>优秀</th>
+        <th>最高分</th>
+        <th>最低分</th>
+        <th>及格率(%)</th>
+        <th>优秀率(%)</th>
+        <th>平均数</th>
+        <th>平均相对分</th>
+    </tr>
+    </thead>
+    <tbody>
+    <c:forEach items="${list}" var="reportSubjectteacher">
+        <tr>
+            <td>${reportSubjectteacher.className}</td>
+            <td>${reportSubjectteacher.realityCount}</td>
+            <td>${reportSubjectteacher.passCount}</td>
+            <td>${reportSubjectteacher.excellentCount}</td>
+            <td>${reportSubjectteacher.maxScore}</td>
+            <td>${reportSubjectteacher.minScore}</td>
+            <td>${reportSubjectteacher.passRate}</td>
+            <td>${reportSubjectteacher.excellentRate}</td>
+            <td>${reportSubjectteacher.avgScore}</td>
+            <td>${reportSubjectteacher.relativeAvgScore}</td>
+        </tr>
+    </c:forEach>
+    </tbody>
+</table>
+<script type="text/javascript">
+
+    function viewTeacherClassEcharts() {
+        var classs = new Array();
+        var avgScores = new Array();
+        var maxScores = new Array();
+        var minScores = new Array();
+        var passRates = new Array();
+        var excellentRates = new Array();
+        var relativeAvgScore = new Array();
+
+        $('tbody tr').each(function (i) {
+            $(this).children('td').each(function (j) {
+                if(j == 0){
+                    classs.push($(this).text());
+                } else if(j == 8){
+                    avgScores.push($(this).text());
+                } else if(j == 4){
+                    maxScores.push($(this).text());
+                } else if(j == 5){
+                    minScores.push($(this).text());
+                } else if(j == 6){
+                    passRates.push($(this).text()*100);
+                } else if(j == 7){
+                    excellentRates.push($(this).text()*100);
+                } else if(j == 9){
+                    relativeAvgScore.push($(this).text());
+                }
+            });
+        });
+
+        var title = '';
+
+        var imageModal = new jBox('Modal');
+        imageModal.setWidth($(window).width() * 0.9);
+        imageModal.setHeight($(window).height() * 0.85);
+        imageModal.setTitle('任课班级成绩分析');
+        imageModal.setContent($('#echart-view-content'));
+        imageModal.open();
+
+        var myChart = echarts.init(document.getElementById('echart-content'));
+
+        // 指定图表的配置项和数据
+        var option = {
+            title: {
+                text: '任课班级成绩分析'
+                // textAlign:'center'
+            },
+            tooltip: {},
+            legend: {
+                data: ['最高分','最低分','平均分','相对平均分','优秀率','及格率']
+            },
+            dataZoom: [{
+                type: 'slider',
+                show: true,
+                xAxisIndex: [0],
+                left: '9%',
+                bottom: -5,
+                start: 10,
+                end: 90 //初始化滚动条
+            }],
+            xAxis: {
+                axisLabel: {
+                    interval:0,
+                    rotate:40
+                },
+                data: classs
+            },
+            yAxis: [
+                {
+                    type: 'value'
+                },
+                {
+                    type: 'value'
+                }
+            ],
+            series: [{
+                name: '最高分',
+                type: 'bar',
+                data: maxScores
+            },{
+                name: '最低分',
+                type: 'bar',
+                data: minScores
+            },{
+                name: '平均分',
+                type: 'bar',
+                data: avgScores
+            },{
+                name: '相对平均分',
+                type: 'line',
+                yAxisIndex : 1,
+                data: relativeAvgScore
+            },{
+                name: '及格率',
+                type: 'line',
+                data: passRates
+            },{
+                name: '优秀率',
+                type: 'line',
+                data: excellentRates
+            }]
+        };
+        // 使用刚指定的配置项和数据显示图表。
+        myChart.setOption(option);
+    }
+
+</script>
+<div id="echart-view-content" class="container-fluid" style="display:none" align="center">
+    <div id="echart-content" style="width: 100%;height:520px;"/>
+</div>
+</body>
+</html>