Browse Source

pdf页面添加

zhangjie 6 years ago
parent
commit
ded774b198

+ 446 - 3
stmms-web/src/main/webapp/WEB-INF/views/modules/report/pdf.jsp

@@ -2,10 +2,453 @@
 <%@ include file="/WEB-INF/views/include/taglib.jsp"%>
 <html>
 <head>
+  <title>教研报告</title>
+  <meta charset="UTF-8" />
+  <meta name="viewport" content="width=device-width,initial-scale=1, maximum-scale=1, user-scalable=1" />
+  <meta name="renderer" content="webkit|ie-comp|ie-stand" />
+  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
+  <link rel="stylesheet" type="text/css" href="${ctxStatic}/report-pdf/css/teaching.css" />
+  <script>
+  	var dataStatic = ${data};
+  </script>
+  
 </head>
 <body>
-<div class="container">
-  ${data}
-</div>
+ <!-- body-main -->
+  <div class="body-main" id="body-main">
+
+  </div>
+
+
+  <!-- template -->
+  <!-- page-box -->
+  <script id="page-box" type="text/html">
+    <div class="page-box <#:=boxType#>">
+      <div class="page-body">
+        <h1 class="page-title-1">教研分析报告</h1>
+        <div class="page-content">
+          <#:=bodyDom#>
+        </div>
+      </div>
+    </div>
+  </script>
+  <!-- page-footer -->
+  <script id="page-foot" type="text/html">
+    <div class="page-foot">
+      <div class="foot-left">
+        <p>版权所有:武汉启明泰和软件服务有限公司</p>
+      </div>
+      <div class="foot-right">
+        <span class="page-num">PAGE <#:=pageNum#></span>
+      </div>
+    </div>
+  </script>
+  <!-- cover -->
+  <script id="cover" type="text/html">
+    <div class="page-box cover-box">
+      <div class="cover-title"></div>
+      <div class="cover-footer">
+        <p><span>考试名称:</span><span><#:=examName#></span></p>
+        <p><span>学校:</span><span><#:=schoolName#></span></p>
+        <p><span>科目:</span><span><#:=subjectName#></span></p>
+      </div>
+    </div>
+  </script>
+  <!-- page-chart bar-point line line-reverse -->
+  <script id="page-chart" type="text/html">
+    <h2 class="page-title-2"><#:=title#></h2>
+    <div class="page-chart <#:=chartClassName#>" id="<#:=chartId#>" style="height: <#:=height#>;"></div>
+  </script>
+  <!-- teacher-score -->
+  <script id="teacher-score" type="text/html">
+    <h2 class="page-title-2">任课老师成绩分析</h2>
+    <div class="page-chart chart-teachers" id="<#:=chartId#>" ></div>
+    <#:=teacherScoreTableTpl({dataList: dataList, pageTableClass: 'teacher-table'})#>
+  </script>
+  <!-- teacher-score-table -->
+  <script id="teacher-score-table" type="text/html">
+    <div class="page-table <#:=pageTableClass#>">
+      <table class="table table-border">
+        <tr>
+          <th>任课<br>老师</th>
+          <th>实考<br>人数</th>
+          <th>最高分</th>
+          <th>最低分</th>
+          <th>及格<br>人数</th>
+          <th>及格率(%)</th>
+          <th>优秀<br>人数</th>
+          <th>优秀率(%)</th>
+          <th>平均分</th>
+          <th>相对<br>平均分</th>
+        </tr>
+        <# for (var i = 0;i < dataList.length; i++) {#>
+        <# var total = dataList[i].total #>
+        <tr>
+          <td><#:=dataList[i].name#></td>
+          <td><#:=total.totalCount#></td>
+          <td><#:=total.maxScore#></td>
+          <td><#:=total.minScore#></td>
+          <td><#:=total.passCount#></td>
+          <td><#:=Math.round(total.passRate * 100)#></td>
+          <td><#:=total.excellentCount#></td>
+          <td><#:=Math.round(total.excellentRate * 100)#></td>
+          <td><#:=total.avgScore#></td>
+          <td><#:=total.relativeAvgScore#></td>
+        </tr>
+        <# } #>
+      </table>
+    </div>
+  </script>
+
+  <!-- teacher-grade -->
+  <script id="teacher-grade" type="text/html">
+    <# for (var i = 0; i < chartList.length; i++) { #>
+    <div class="page-chart chart-teacher-grade" id="<#:=chartList[i]#>"></div>
+    <# } #>
+    <div class="page-chart-legend">
+      <ul>
+        <li>平均分</li>
+        <li>相对平均分</li>
+        <li>最高分</li>
+        <li>最低分</li>
+        <li>及格率</li>
+        <li>优秀率</li>
+      </ul>
+    </div>
+  </script>
+  <!-- discrimination-level-table -->
+  <script id="discrimination-level-table" type="text/html">
+    <h2 class="page-title-2">区分度等级分布</h2>
+    <div class="page-table level-table">
+      <table class="table table-border">
+        <tr>
+          <th rowspan="2"></th>
+          <th rowspan="2">题型</th>
+          <th rowspan="2">题量</th>
+          <th rowspan="2">满分</th>
+          <th rowspan="2">差异<br>系数</th>
+          <th colspan="3">优</th>
+          <th colspan="3">良</th>
+          <th colspan="3">可</th>
+          <th colspan="3">差</th>
+        </tr>
+        <tr>
+          <th>题量</th>
+          <th>分值</th>
+          <th>%</th>
+          <th>题量</th>
+          <th>分值</th>
+          <th>%</th>
+          <th>题量</th>
+          <th>分值</th>
+          <th>%</th>
+          <th>题量</th>
+          <th>分值</th>
+          <th>%</th>
+        </tr>
+        <# for (var i = 0;i < dataList.length; i++) {#>
+        <# var groups = dataList[i].groups; #>
+        <# for (var j = 0;j < groups.length; j++) {#>
+        <tr>
+          <# if (j == 0) { #>
+          <td rowspan="<#:=groups.length#>"><#:=dataList[i].name#></td>
+          <# } #>
+          <# var levels = groups[j].levels; #>
+          <td><#:=groups[j].name#></td>
+          <td><#:=groups[j].questionCount#></td>
+          <td><#:=groups[j].fullScore#></td>
+          <td><#:=groups[j].coefficient#></td>
+          <td><#:=levels.excellent.questionCount#></td>
+          <td><#:=levels.excellent.fullScore#></td>
+          <td><#:=levels.excellent.questionRate#></td>
+          <td><#:=levels.good.questionCount#></td>
+          <td><#:=levels.good.fullScore#></td>
+          <td><#:=levels.good.questionRate#></td>
+          <td><#:=levels.general.questionCount#></td>
+          <td><#:=levels.general.fullScore#></td>
+          <td><#:=levels.general.questionRate#></td>
+          <td><#:=levels.bad.questionCount#></td>
+          <td><#:=levels.bad.fullScore#></td>
+          <td><#:=levels.bad.questionRate#></td>
+        </tr>
+        <# } #>
+        <# } #>
+      </table>
+    </div>
+    <div class="table-tips">
+      <span class="tips-tag">区分度评定标准</span>
+      <span>优 D≥0.40;良 0.40>D≥0.30;可 0.30>D≥0.20;差 D < 0.20;</span>
+    </div>
+  </script>
+  <!-- difficulty-level-table -->
+  <script id="difficulty-level-table" type="text/html">
+    <h2 class="page-title-2">难度等级分布</h2>
+    <div class="page-table level-table">
+      <table class="table table-border">
+        <tr>
+          <th rowspan="2"></th>
+          <th rowspan="2">题型</th>
+          <th rowspan="2">题量</th>
+          <th rowspan="2">满分</th>
+          <th rowspan="2">难度</th>
+          <th colspan="3">高难度</th>
+          <th colspan="3">中等难度</th>
+          <th colspan="3">低难度</th>
+        </tr>
+        <tr>
+          <th>题量</th>
+          <th>分值</th>
+          <th>%</th>
+          <th>题量</th>
+          <th>分值</th>
+          <th>%</th>
+          <th>题量</th>
+          <th>分值</th>
+          <th>%</th>
+        </tr>
+        <# for (var i = 0;i < dataList.length; i++) {#>
+        <# var groups = dataList[i].groups; #>
+        <# for (var j = 0;j < groups.length; j++) {#>
+        <tr>
+          <# if (j == 0) { #>
+          <td rowspan="<#:=groups.length#>"><#:=dataList[i].name#></td>
+          <# } #>
+          <# var levels = groups[j].levels #>
+          <td><#:=groups[j].name#></td>
+          <td><#:=groups[j].questionCount#></td>
+          <td><#:=groups[j].fullScore#></td>
+          <td><#:=groups[j].difficulty#></td>
+          <td><#:=levels.high.questionCount#></td>
+          <td><#:=levels.high.fullScore#></td>
+          <td><#:=levels.high.questionRate#></td>
+          <td><#:=levels.middle.questionCount#></td>
+          <td><#:=levels.middle.fullScore#></td>
+          <td><#:=levels.middle.questionRate#></td>
+          <td><#:=levels.low.questionCount#></td>
+          <td><#:=levels.low.fullScore#></td>
+          <td><#:=levels.low.questionRate#></td>
+        </tr>
+        <# } #>
+        <# } #>
+      </table>
+    </div>
+    <div class="table-tips">
+      <span class="tips-tag">难度等级分布</span>
+      <span>高难度 P<0.40;中等难度 0.40≤P≤0.70;低难度 P>0.70</span>
+    </div>
+  </script>
+  <!-- basic-question-table -->
+  <script id="basic-question-table" type="text/html">
+    <h2 class="page-title-2">题目统计特征</h2>
+    <div class="page-table level-table">
+      <table class="table table-border">
+        <tr>
+          <th>题号</th>
+          <th>满分</th>
+          <th>最高分</th>
+          <th>最低分</th>
+          <th>平均分</th>
+          <th>标准差</th>
+          <th>差异系数</th>
+          <th>难度</th>
+          <th>区分度</th>
+          <th>零分人数</th>
+          <th>满分人数</th>
+          <th>有效卷数</th>
+        </tr>
+        <# for (var i = 0;i < dataList.length; i++) {#>
+        <# var dataItem = dataList[i] #>
+        <tr>
+          <td><#:=dataItem.number#></td>
+          <td><#:=dataItem.fullScore#></td>
+          <td><#:=dataItem.maxScore#></td>
+          <td><#:=dataItem.minScore#></td>
+          <td><#:=dataItem.avgScore#></td>
+          <td><#:=dataItem.stdevScore#></td>
+          <td><#:=dataItem.coefficient#></td>
+          <td><#:=dataItem.difficulty#></td>
+          <td><#:=dataItem.discrimination#></td>
+          <td><#:=dataItem.zeroCount#></td>
+          <td><#:=dataItem.fullCount#></td>
+          <td><#:=dataItem.totalCount#></td>
+        </tr>
+        <# } #>
+      </table>
+    </div>
+  </script>
+  <!-- basic-main-question-table -->
+  <script id="basic-main-question-table" type="text/html">
+    <h2 class="page-title-2">大题结构特征</h2>
+    <div class="page-table level-table">
+      <table class="table table-border">
+        <tr>
+          <th></th>
+          <th>题型</th>
+          <th>满分</th>
+          <th>最高分</th>
+          <th>最低分</th>
+          <th>平均分</th>
+          <th>标准差</th>
+          <th>差异系数</th>
+          <th>难度</th>
+          <th>区分度</th>
+          <th>零分人数</th>
+          <th>满分人数</th>
+          <th>有效卷数</th>
+        </tr>
+        <# for (var i = 0;i < dataList.length; i++) {#>
+        <# var dataItem = dataList[i] #>
+        <tr>
+          <# if (i == 0) { #>
+            <td rowspan="<#:=dataList.length#>">全部</td>
+          <# } #>
+          <td><#:=dataItem.name#></td>
+          <td><#:=dataItem.fullScore#></td>
+          <td><#:=dataItem.maxScore#></td>
+          <td><#:=dataItem.minScore#></td>
+          <td><#:=dataItem.avgScore#></td>
+          <td><#:=dataItem.stdevScore#></td>
+          <td><#:=dataItem.coefficient#></td>
+          <td><#:=dataItem.difficulty#></td>
+          <td><#:=dataItem.discrimination#></td>
+          <td><#:=dataItem.zeroCount#></td>
+          <td><#:=dataItem.fullCount#></td>
+          <td><#:=dataItem.totalCount#></td>
+        </tr>
+        <# } #>
+      </table>
+    </div>
+  </script>
+  <!-- basic-question-option-table -->
+  <script id="basic-question-option-table" type="text/html">
+    <h2 class="page-title-2">选项分析</h2>
+    <div class="page-table level-table">
+      <table class="table table-border">
+        <tr>
+          <th rowspan="2">题号</th>
+          <th rowspan="2">标答</th>
+          <th colspan="<#:=options.length#>">选项分布(%)</th>
+          <th rowspan="2">空选</th>
+          <th rowspan="2">难度</th>
+          <th rowspan="2">区分度</th>
+          <th rowspan="2">答对人数</th>
+          <th rowspan="2">总人数</th>
+        </tr>
+        <tr>
+          <# for (var i = 0; i < options.length; i++) { #>
+          <th><#:=options[i]#></th>
+          <# } #>
+        </tr>
+        <# for (var i = 0; i < questions.length; i++) { #>
+        <tr>
+          <td><#:=questions[i].number#></td>
+          <td><#:=questions[i].answer#></td>
+          <# var qoptions = questions[i].optionsRate #>
+          <# for (var j = 0; j < options.length; j++) { #>
+          <td><#:=qoptions[options[j]] || '0.00'#></td>
+          <# } #>
+          <td><#:=qoptions['#'] || '0.00' #></td>
+          <td><#:=questions[i].difficulty#></td>
+          <td><#:=questions[i].discrimination#></td>
+          <td><#:=questions[i].correctCount#></td>
+          <td><#:=questions[i].totalCount#></td>
+        </tr>
+        <# } #>
+      </table>
+    </div>
+  </script>
+  <!-- range-level-table -->
+  <script id="range-level-table" type="text/html">
+    <h2 class="page-title-2">考生分段比例</h2>
+    <div class="page-table level-table">
+      <table class="table table-border">
+        <tr>
+          <th>班级</th>
+          <th>低分段临界值</th>
+          <th>高分段临界值</th>
+          <th>有效卷数</th>
+        </tr>
+        <# for (var i = 0; i < dataList.length; i++ )  {#>
+        <tr>
+          <td><#:=dataList[i].name#></td>
+          <td><#:=dataList[i].lowScore#></td>
+          <td><#:=dataList[i].highScore#></td>
+          <td><#:=dataList[i].totalCount#></td>
+        </tr>
+        <# } #>
+      </table>
+    </div>
+    <div class="range-tips">
+      <p>高分段考生是指得分在全体考生排名前27%的考生。低分段考生是指得分在全体考生排名后27%的考生。</p>
+    </div>
+  </script>
+  <!-- range-totalScore -->
+  <script id="range-totalScore" type="text/html">
+    <h2 class="page-title-2"><#:=title#></h2>
+    <# if (chartId) { #>
+    <div class="page-chart chart-line" id="<#:=chartId#>" ></div>
+    <# } #>
+    <div class="page-table <#:=pageTableClass#>">
+      <table class="table table-border">
+        <tr>
+            <th>分数段</th>
+            <th>人数</th>
+            <th>频率(%)</th>
+            <th>累计人数</th>
+            <th>累计频率(%)</th>
+        </tr>
+        <# for (var i = 0; i < dataList.length; i++ )  {#>
+        <tr>
+          <td><#:=dataList[i].score#></td>
+          <td><#:=dataList[i].rangeCount#></td>
+          <td><#:=dataList[i].rangeRate#></td>
+          <td><#:=dataList[i].sumCount#></td>
+          <td><#:=dataList[i].sumRate#></td>
+        </tr>
+        <# } #>
+      </table>
+    </div>
+  </script>
+  <!-- range-segment-table -->
+  <script id="range-segment-table" type="text/html">
+    <h2 class="page-title-2"><#:=title#></h2>
+    <div class="page-table page-table-pad">
+      <table class="table table-border table-ave-6">
+        <tr>
+          <th class="th-empty"></th>
+          <th>分数段</th>
+          <th>人数</th>
+          <th>频率(%)</th>
+          <th>累计人数</th>
+          <th>累计频率(%)</th>
+        </tr>
+        <# for (var i = 0;i < dataList.length; i++) {#>
+        <# var segments = dataList[i].segments; #>
+        <# for (var j = 0;j < segments.length; j++) {#>
+        <tr>
+          <# if (j == 0) { #>
+          <td rowspan="<#:=segments.length#>"><#:=dataList[i].name#></td>
+          <# } #>
+          <# var levels = segments[j].levels; #>
+          <td><#:=segments[j].score#></td>
+          <td><#:=segments[j].rangeCount#></td>
+          <td><#:=segments[j].rangeRate#></td>
+          <td><#:=segments[j].sumCount#></td>
+          <td><#:=segments[j].sumRate#></td>
+        </tr>
+        <# } #>
+        <# } #>
+      </table>
+    </div>
+  </script>
+
+
+  <!-- js -->
+  <script src="${ctxStatic}/report-pdf/libs/jquery-2.1.4.min.js"></script>
+  <script src="${ctxStatic}/report-pdf/libs/echarts.min.4.2.0-rc2.js"></script>
+  <script src="${ctxStatic}/report-pdf/libs/template.js"></script>
+  <script src="${ctxStatic}/report-pdf/js/chart-render.js"></script>
+  <script src="${ctxStatic}/report-pdf/js/data-parse.js"></script>
+  <script src="${ctxStatic}/report-pdf/js/teaching.js"></script>
 </body>
 </html>

+ 311 - 0
stmms-web/src/main/webapp/static/report-pdf/css/teaching.css

@@ -0,0 +1,311 @@
+body,
+div,
+dl,
+dt,
+dd,
+ul,
+ol,
+li,
+h1,
+h2,
+h3,
+h4,
+h5,
+h6,
+p,
+blockquote,
+tr,
+th,
+td,
+span {
+  margin: 0;
+  padding: 0;
+  -webkit-box-sizing: border-box;
+          box-sizing: border-box; }
+
+body {
+  font-size: 19px;
+  color: #666;
+  font-family: "PingFang SC", Tahoma, Helvetica, Arial, sans-serif; }
+
+.font-normal {
+  font-family: "PingFang SC Regular", "Microsoft YaHei", Tahoma, Helvetica,
 Arial, sans-serif; }
+
+.font-bold {
+  font-family: "PingFang SC Semibold", "Microsoft YaHei", Tahoma, Helvetica,
 Arial, sans-serif; }
+
+li {
+  list-style: none; }
+
+em,
+i,
+u {
+  font-style: normal; }
+
+h1,
+h2,
+h3,
+h4,
+h5,
+h6 {
+  font-size: 100%;
+  font-weight: normal; }
+
+fieldset,
+img {
+  border: 0; }
+
+abbr {
+  border: 0;
+  font-variant: normal; }
+
+a {
+  text-decoration: none;
+  color: inherit;
+  *color: #999999; }
+
+img {
+  vertical-align: middle; }
+
+/* page-box */
+.page-box {
+  width: 1160px;
+  height: 1641px;
+  margin: 0 auto;
+  position: relative;
+  padding: 39px 58px 70px; }
+  .page-box .page-body {
+    background: #fff;
+    height: 1530px;
+    overflow: hidden; }
+  .page-box .page-content {
+    margin-top: 39px;
+    height: 1388px;
+    border: 2px dotted #dddddd;
+    position: relative;
+    overflow: hidden; }
+    .page-box .page-content::before {
+      content: "";
+      display: block;
+      position: absolute;
+      left: 0;
+      top: 0;
+      z-index: auto;
+      width: 100%;
+      border-bottom: 4px solid #435088; }
+  .page-box .page-foot {
+    position: absolute;
+    width: 100%;
+    height: 70px;
+    bottom: 0;
+    left: 0;
+    padding: 5px 58px;
+    color: #999; }
+    .page-box .page-foot .foot-left {
+      float: left; }
+    .page-box .page-foot .foot-right {
+      float: right;
+      padding-right: 180px;
+      background-image: url(../images/bg-footer.png);
+      background-repeat: no-repeat;
+      background-position: right 10px; }
+  .page-box .page-chart {
+    min-height: 200px;
+    max-height: 100%; }
+  .page-box .page-table {
+    margin: 0 39px;
+    padding: 1px; }
+    .page-box .page-table.teacher-table {
+      padding-top: 30px; }
+    .page-box .page-table.page-table-pad {
+      padding-top: 100px; }
+    .page-box .page-table.level-table {
+      padding-top: 100px;
+      font-size: 16px; }
+      .page-box .page-table.level-table th,
+      .page-box .page-table.level-table td {
+        padding: 7px 3px; }
+      .page-box .page-table.level-table td[rowspan] {
+        padding: 7px 10px;
+        width: 60px;
+        background-color: #fafafa; }
+  .page-box .page-icon {
+    display: inline-block;
+    vertical-align: middle;
+    width: 30px;
+    height: 30px;
+    background-repeat: no-repeat;
+    background-size: 100% 100%; }
+  .page-box .icon-star {
+    background-image: url(../images/common/icon-star.png); }
+  .page-box .page-title-1 {
+    font-size: 39px;
+    font-weight: 600;
+    color: #435088;
+    line-height: 70px; }
+  .page-box .page-title-2 {
+    position: absolute;
+    top: 0;
+    left: 0;
+    z-index: auto;
+    font-size: 27px;
+    font-weight: 600;
+    background: #435088;
+    color: #fff;
+    line-height: 39px;
+    padding: 10px 39px;
+    height: 58px; }
+    .page-box .page-title-2::after {
+      content: "";
+      display: block;
+      position: absolute;
+      width: 0;
+      height: 0;
+      right: -1px;
+      bottom: -1px;
+      border-width: 14px;
+      border-style: solid;
+      border-color: transparent #fff #fff transparent; }
+
+/* table */
+.table {
+  width: 100%;
+  border-spacing: 0;
+  border-collapse: collapse;
+  text-align: center; }
+  .table th {
+    padding: 10px;
+    background-color: #3da0ff;
+    color: #fff; }
+  .table td {
+    padding: 10px;
+    color: #555; }
+  .table-border th {
+    border: 1px solid #3589d8; }
+  .table-border td {
+    border: 1px solid #e9e9e9; }
+
+.cover-box {
+  background-image: url(../images/cover-bg.png);
+  background-repeat: no-repeat;
+  background-size: 100% 100%;
+  background-position: left top;
+  color: #fff;
+  font-size: 29px; }
+
+.cover-title {
+  position: absolute;
+  width: 745px;
+  height: 117px;
+  left: 160px;
+  top: 263px;
+  background-image: url(../images/cover-title.png);
+  background-size: 100% 100%; }
+
+.cover-footer {
+  position: absolute;
+  width: 450px;
+  height: 175px;
+  left: 156px;
+  bottom: 156px;
+  line-height: 58px; }
+
+.chart-teachers {
+  height: 550px; }
+
+.chart-teacher-grade {
+  height: 420px; }
+
+.page-chart-legend {
+  margin-top: 20px;
+  text-align: center; }
+  .page-chart-legend li {
+    display: inline-block;
+    vertical-align: middle;
+    margin: 0 20px;
+    font-size: 18px; }
+    .page-chart-legend li::before {
+      content: "";
+      width: 16px;
+      height: 16px;
+      display: inline-block;
+      vertical-align: middle;
+      margin-right: 10px;
+      border-radius: 3px; }
+    .page-chart-legend li:nth-of-type(1)::before {
+      background: #3da0ff; }
+    .page-chart-legend li:nth-of-type(2)::before {
+      background: #4bcb74; }
+    .page-chart-legend li:nth-of-type(3)::before {
+      background: #975ee5; }
+    .page-chart-legend li:nth-of-type(4)::before {
+      background: #999999; }
+    .page-chart-legend li:nth-of-type(5)::before {
+      background-image: url(../images/icon-circle-bule.png);
+      background-repeat: no-repeat;
+      background-size: 100% 100%; }
+    .page-chart-legend li:nth-of-type(6)::before {
+      background-image: url(../images/icon-circle-yellow.png);
+      background-repeat: no-repeat;
+      background-size: 100% 100%; }
+
+.chart-line {
+  height: 580px; }
+
+.table-level {
+  font-size: 16px;
+  line-height: 16px; }
+  .table-level th,
+  .table-level td {
+    padding: 8px 2px; }
+
+.table-ave-5 th,
+.table-ave-5 td {
+  width: 20%;
+  padding: 8px; }
+
+.table-ave-6 th,
+.table-ave-6 td {
+  width: 177px;
+  padding: 8px; }
+
+.table-ave-6 td[rowspan] {
+  padding: 13px;
+  background: #fafafa;
+  width: auto !important; }
+
+.table-ave-6 .th-empty {
+  width: auto; }
+
+.table-tips {
+  margin: 30px 39px 0;
+  font-size: 21px; }
+  .table-tips span {
+    display: inline-block;
+    vertical-align: middle;
+    margin-right: 10px;
+    line-height: 39px; }
+    .table-tips span.tips-tag {
+      color: #fff;
+      padding: 0 20px 0 10px;
+      background-image: url(../images/tips-bg.png);
+      background-size: 100% 100%;
+      background-repeat: no-repeat; }
+
+.range-tips {
+  margin: 15px 39px 0;
+  padding-left: 40px;
+  position: relative;
+  color: #666666;
+  line-height: 31px; }
+  .range-tips::before {
+    content: "";
+    display: block;
+    position: absolute;
+    width: 30px;
+    height: 30px;
+    top: 0;
+    left: 0;
+    background-image: url(../images/icon-star.png);
+    background-repeat: no-repeat;
+    background-size: 100% 100%; }

BIN
stmms-web/src/main/webapp/static/report-pdf/images/bg-footer.png


BIN
stmms-web/src/main/webapp/static/report-pdf/images/cover-bg.png


BIN
stmms-web/src/main/webapp/static/report-pdf/images/cover-title.png


BIN
stmms-web/src/main/webapp/static/report-pdf/images/icon-circle-bule.png


BIN
stmms-web/src/main/webapp/static/report-pdf/images/icon-circle-yellow.png


BIN
stmms-web/src/main/webapp/static/report-pdf/images/icon-star.png


BIN
stmms-web/src/main/webapp/static/report-pdf/images/tips-bg.png


+ 1064 - 0
stmms-web/src/main/webapp/static/report-pdf/js/chart-render.js

@@ -0,0 +1,1064 @@
+(function(window, undefined) {
+  var chartOption = {
+    barPointTopic: getBarPointTopicOptions,
+    barPointGrade: getBarPointGradeOptions,
+    barTeachers: getBarTeachersOptions,
+    barTeacherGrade: getBarTeacherGradeOptions,
+    line: getLineOptions,
+    lineReverse: getLineReverseOptions,
+    lineSmooth: getLineSmoothOptions
+  };
+
+  var colors = [
+    "rgba(67, 80, 136, 0.8)",
+    "rgba(151, 94, 229, 0.8)",
+    "rgba(61, 160, 255, 0.8)",
+    "rgba(48, 203, 203, 0.8)",
+    "rgba(75, 203, 116, 0.8)",
+    "rgba(250, 212, 68, 0.8)",
+    "rgba(217, 217, 217, 0.8)"
+  ];
+  var textStyle = {
+    color: "#555",
+    fontFamily:
+      '"PingFang SC", "Microsoft YaHei", Tahoma,Helvetica, Arial, sans-serif'
+  };
+  var animationIsOpen = false;
+
+  var symbolCircle =
+    "path://M16,9.2c-3.8,0-6.8,3.1-6.8,6.8s3.1,6.8,6.8,6.8s6.8-3.1,6.8-6.8S19.8,9.2,16,9.2z M29.7,16  c0,7.6-6.1,13.7-13.7,13.7S2.3,23.6,2.3,16S8.4,2.3,16,2.3S29.7,8.4,29.7,16z";
+
+  function Charts(dome, dataList, chartType, renderType) {
+    this.dome = dome;
+    this.dataList = dataList;
+    this.chartType = chartType;
+    this.renderType = renderType || "canvas";
+  }
+
+  Charts.prototype.initChart = function() {
+    return window.echarts.init(this.dome, "", {
+      renderer: this.renderType
+    });
+  };
+
+  Charts.prototype.renderChart = function() {
+    var options = chartOption[this.chartType](this.dataList);
+    if (options) this.initChart().setOption(options, true);
+  };
+
+  function getBarPointTopicOptions(datas) {
+    var yAxisLabels = datas.map(function(item) {
+      return item.name;
+    });
+    var avgDatas = datas.map(function(item) {
+      return item.avgScore;
+    });
+    var stdDatas = datas.map(function(item) {
+      return item.stdevScore;
+    });
+    var scoreRateDatas = datas.map(function(item) {
+      return item.scoreRate;
+    });
+
+    var legendData = ["单题平均分", "单题标准差", "得分率"];
+    var series = [
+      {
+        type: "bar",
+        data: avgDatas,
+        barWidth: 6,
+        barGap: "50%",
+        name: "单题平均分",
+        xAxisIndex: 0,
+        yAxisIndex: 0,
+        itemStyle: {
+          color: "rgba(61, 160, 255, 0.8)"
+        }
+      },
+      {
+        type: "bar",
+        data: stdDatas,
+        barWidth: 6,
+        barGap: "50%",
+        name: "单题标准差",
+        xAxisIndex: 0,
+        yAxisIndex: 0,
+        itemStyle: {
+          color: "#4bcb74"
+        }
+      },
+      {
+        type: "scatter",
+        data: scoreRateDatas,
+        symbol: symbolCircle,
+        symbolSize: 10,
+        name: "得分率",
+        xAxisIndex: 1,
+        yAxisIndex: 1,
+        itemStyle: {
+          color: "rgba(67, 80, 136, 0.8)"
+        }
+      }
+    ];
+
+    if (datas[0].hasOwnProperty("fullRate") && datas[0].fullRate) {
+      var fullRateDatas = datas.map(function(item) {
+        return item.fullRate;
+      });
+      legendData.push("满分率");
+      series.push({
+        type: "scatter",
+        data: fullRateDatas,
+        symbol: symbolCircle,
+        symbolSize: 10,
+        name: "满分率",
+        xAxisIndex: 1,
+        yAxisIndex: 1,
+        itemStyle: {
+          color: "rgba(250, 212, 68, 0.8)"
+        }
+      });
+    }
+    return {
+      animation: animationIsOpen,
+      textStyle: textStyle,
+      legend: {
+        data: legendData,
+        itemGap: 30,
+        itemWidth: 14,
+        bottom: 40,
+        textStyle: {
+          fontSize: 19
+        }
+      },
+      grid: [
+        {
+          left: "20%",
+          top: 120,
+          width: "36%",
+          bottom: 100,
+          show: true,
+          borderColor: "rgba(230,230,230,1)"
+        },
+        {
+          left: "56%",
+          top: 120,
+          width: "30%",
+          bottom: 100,
+          show: true,
+          borderColor: "rgba(230,230,230,1)"
+        }
+      ],
+      xAxis: [
+        {
+          type: "value",
+          gridIndex: 0,
+          position: "top",
+          inverse: true,
+          axisTick: {
+            show: false
+          },
+          splitLine: {
+            show: true,
+            lineStyle: {
+              color: "rgba(233,233,233,1)"
+            }
+          },
+          axisLine: {
+            lineStyle: {
+              color: "rgba(233,233,233,1)"
+            }
+          },
+          axisLabel: {
+            fontSize: 18,
+            formatter: function(value, index) {
+              if (!index) return "0";
+              return value.toFixed(2);
+            }
+          }
+        },
+        {
+          type: "value",
+          gridIndex: 1,
+          min: 0,
+          max: 1,
+          interval: 0.2,
+          position: "top",
+          axisTick: {
+            show: false
+          },
+          axisLine: {
+            lineStyle: {
+              color: "rgba(233,233,233,1)"
+            }
+          },
+          splitLine: {
+            show: true,
+            lineStyle: {
+              color: "rgba(233,233,233,1)"
+            }
+          },
+          axisLabel: {
+            fontSize: 18,
+            formatter: function(value, index) {
+              if (!index) return "";
+              return parseInt(value * 100) + "%";
+            }
+          }
+        }
+      ],
+      yAxis: [
+        {
+          type: "category",
+          gridIndex: 0,
+          data: yAxisLabels,
+          inverse: true,
+          axisTick: {
+            show: false
+          },
+          splitArea: {
+            show: true,
+            areaStyle: {
+              color: ["rgba(250,250,250,1)", "rgba(255,255,255,1)"]
+            }
+          },
+          splitLine: {
+            show: true,
+            lineStyle: {
+              color: "rgba(233,233,233,1)"
+            }
+          },
+          axisLabel: {
+            fontSize: 19,
+            margin: 50
+          }
+        },
+        {
+          show: true,
+          type: "category",
+          inverse: true,
+          gridIndex: 1,
+          data: yAxisLabels,
+          axisLabel: {
+            show: false,
+            fontSize: 19
+          },
+          axisTick: {
+            show: false
+          },
+          axisLine: {
+            lineStyle: {
+              color: "rgba(170,170,170,1)"
+            }
+          },
+          splitArea: {
+            show: true,
+            areaStyle: {
+              color: ["rgba(250,250,250,1)", "rgba(255,255,255,1)"]
+            }
+          },
+          splitLine: {
+            show: true,
+            lineStyle: {
+              color: "rgba(233,233,233,1)"
+            }
+          }
+        }
+      ],
+      series: series
+    };
+  }
+
+  function getBarPointGradeOptions(datas) {
+    var yAxisLabels = datas.map(function(item) {
+      return item.name;
+    });
+    var avgDatas = datas.map(function(item) {
+      return item.avgScore;
+    });
+    var maxDatas = datas.map(function(item) {
+      return item.maxScore;
+    });
+    var minDatas = datas.map(function(item) {
+      return item.minScore;
+    });
+
+    var passRateDatas = datas.map(function(item) {
+      return Math.round(item.passRate * 100);
+    });
+    var excellentRateDatas = datas.map(function(item) {
+      return Math.round(item.excellentRate * 100);
+    });
+
+    return {
+      animation: animationIsOpen,
+      textStyle: textStyle,
+      legend: {
+        data: ["平均分", "最高分", "最低分", "及格率", "优秀率"],
+        itemGap: 30,
+        itemWidth: 14,
+        bottom: 40,
+        textStyle: {
+          fontSize: 19
+        }
+      },
+      grid: [
+        {
+          left: "20%",
+          top: 120,
+          width: "36%",
+          bottom: 100,
+          show: true,
+          borderColor: "rgba(230,230,230,1)"
+        },
+        {
+          left: "56%",
+          top: 120,
+          width: "30%",
+          bottom: 100,
+          show: true,
+          borderColor: "rgba(230,230,230,1)"
+        }
+      ],
+      xAxis: [
+        {
+          type: "value",
+          gridIndex: 0,
+          position: "top",
+          inverse: true,
+          axisTick: {
+            show: false
+          },
+          splitLine: {
+            show: true,
+            lineStyle: {
+              color: "rgba(233,233,233,1)"
+            }
+          },
+          axisLine: {
+            lineStyle: {
+              color: "rgba(233,233,233,1)"
+            }
+          },
+          axisLabel: {
+            fontSize: 18,
+            color: "#555",
+            formatter: function(value, index) {
+              if (!index) return "0";
+              return value;
+            }
+          }
+        },
+        {
+          type: "value",
+          gridIndex: 1,
+          min: 0,
+          max: 100,
+          interval: 20,
+          position: "top",
+          axisTick: {
+            show: false
+          },
+          axisLine: {
+            lineStyle: {
+              color: "rgba(233,233,233,1)"
+            }
+          },
+          splitLine: {
+            show: true,
+            lineStyle: {
+              color: "rgba(233,233,233,1)"
+            }
+          },
+          axisLabel: {
+            fontSize: 18,
+            color: "#555",
+            formatter: function(value, index) {
+              if (!index) return "";
+              return (value / 100).toFixed(1);
+            }
+          }
+        }
+      ],
+      yAxis: [
+        {
+          type: "category",
+          gridIndex: 0,
+          data: yAxisLabels,
+          inverse: true,
+          axisTick: {
+            show: false
+          },
+          splitArea: {
+            show: true,
+            areaStyle: {
+              color: ["rgba(250,250,250,1)", "rgba(255,255,255,1)"]
+            }
+          },
+          splitLine: {
+            show: true,
+            lineStyle: {
+              color: "rgba(233,233,233,1)"
+            }
+          },
+          axisLabel: {
+            fontSize: 19,
+            margin: 30,
+            formatter: function(value) {
+              if (value.length > 8) {
+                return [value.substring(0, 8), value.substring(8)].join("\n");
+              }
+              return value;
+            }
+          }
+        },
+        {
+          show: true,
+          type: "category",
+          inverse: true,
+          gridIndex: 1,
+          data: yAxisLabels,
+          axisLabel: {
+            show: false,
+            fontSize: 19,
+            formatter: function(value) {
+              if (value.length > 8) {
+                return [value.substring(0, 8), value.substring(8)].join("\n");
+              }
+              return value;
+            }
+          },
+          axisTick: {
+            show: false
+          },
+          axisLine: {
+            lineStyle: {
+              color: "rgba(170,170,170,1)"
+            }
+          },
+          splitArea: {
+            show: true,
+            areaStyle: {
+              color: ["rgba(250,250,250,1)", "rgba(255,255,255,1)"]
+            }
+          },
+          splitLine: {
+            show: true,
+            lineStyle: {
+              color: "rgba(233,233,233,1)"
+            }
+          }
+        }
+      ],
+      series: [
+        {
+          type: "bar",
+          data: avgDatas,
+          barWidth: 6,
+          barGap: "50%",
+          name: "平均分",
+          xAxisIndex: 0,
+          yAxisIndex: 0,
+          itemStyle: {
+            color: "rgba(61, 160, 255, 0.8)"
+          }
+        },
+        {
+          type: "bar",
+          data: maxDatas,
+          barWidth: 6,
+          barGap: "50%",
+          name: "最高分",
+          xAxisIndex: 0,
+          yAxisIndex: 0,
+          itemStyle: {
+            color: "rgba(151, 94, 229, 0.8)"
+          }
+        },
+        {
+          type: "bar",
+          data: minDatas,
+          barWidth: 6,
+          barGap: "50%",
+          name: "最低分",
+          xAxisIndex: 0,
+          yAxisIndex: 0,
+          itemStyle: {
+            color: "rgba(217, 217, 217, 0.8)"
+          }
+        },
+        {
+          type: "scatter",
+          data: passRateDatas,
+          symbol: symbolCircle,
+          symbolSize: 10,
+          name: "及格率",
+          xAxisIndex: 1,
+          yAxisIndex: 1,
+          itemStyle: {
+            color: "rgba(67, 80, 136, 0.8)"
+          }
+        },
+        {
+          type: "scatter",
+          data: excellentRateDatas,
+          symbol: symbolCircle,
+          symbolSize: 10,
+          name: "优秀率",
+          xAxisIndex: 1,
+          yAxisIndex: 1,
+          itemStyle: {
+            color: "rgba(250, 212, 68, 0.8)"
+          }
+        }
+      ]
+    };
+  }
+
+  function getBarTeachersOptions(datas) {
+    var xAxisData = [
+      "实考人数",
+      "最高分",
+      "最低分",
+      "及格人数",
+      "及格率",
+      "优秀人数",
+      "优秀率",
+      "平均分",
+      "相对平均分"
+    ];
+
+    var legendData = datas.map(function(item) {
+      return item.name;
+    });
+
+    var series = datas.map(function(item, index) {
+      return {
+        type: "bar",
+        data: [
+          item.total.totalCount,
+          item.total.maxScore,
+          item.total.minScore,
+          item.total.passCount,
+          Math.round(item.total.passRate * 100),
+          item.total.excellentCount,
+          Math.round(item.total.excellentRate * 100),
+          item.total.avgScore,
+          item.total.relativeAvgScore
+        ],
+        name: item.name
+      };
+    });
+
+    return {
+      animation: animationIsOpen,
+      textStyle: textStyle,
+      color: colors,
+      legend: {
+        data: legendData,
+        left: "center",
+        bottom: 10,
+        itemGap: 20,
+        itemWidth: 14,
+        textStyle: {
+          fontSize: 19
+        }
+      },
+      grid: {
+        show: true,
+        left: 80,
+        right: 50,
+        top: 100,
+        bottom: 100,
+        borderColor: "rgba(230,230,230,1)"
+      },
+      xAxis: {
+        type: "category",
+        data: xAxisData,
+        axisTick: {
+          show: false
+        },
+        splitArea: {
+          show: true,
+          areaStyle: {
+            color: ["rgba(255,255,255,1)", "rgba(250,250,250,1)"]
+          }
+        },
+        splitLine: {
+          show: true,
+          lineStyle: {
+            color: "rgba(233,233,233,1)"
+          }
+        },
+        axisLabel: {
+          fontSize: 18,
+          margin: 12,
+          interval: 0
+        }
+      },
+      yAxis: {
+        type: "value",
+        z: 1,
+        axisTick: {
+          show: false
+        },
+        axisLine: {
+          lineStyle: {
+            color: "rgba(233,233,233,1)"
+          }
+        },
+        splitLine: {
+          show: true,
+          lineStyle: {
+            color: "rgba(233,233,233,1)"
+          }
+        },
+        axisLabel: {
+          fontSize: 16,
+          color: "#555"
+        }
+      },
+      series: series
+    };
+  }
+
+  function getBarTeacherGradeOptions(datas) {
+    var title = datas.name + "_任课班级成绩分析";
+    var symbolCircle =
+      "path://M16,9.2c-3.8,0-6.8,3.1-6.8,6.8s3.1,6.8,6.8,6.8s6.8-3.1,6.8-6.8S19.8,9.2,16,9.2z M29.7,16  c0,7.6-6.1,13.7-13.7,13.7S2.3,23.6,2.3,16S8.4,2.3,16,2.3S29.7,8.4,29.7,16z";
+    var classes = datas.classes;
+    var xAxisData = classes.map(function(item) {
+      return item.name;
+    });
+    var avgDatas = classes.map(function(item) {
+      return item.avgScore;
+    });
+    var relateAvgDatas = classes.map(function(item) {
+      return item.relativeAvgScore;
+    });
+    var maxDatas = classes.map(function(item) {
+      return item.maxScore;
+    });
+    var minDatas = classes.map(function(item) {
+      return item.minScore;
+    });
+    var passRateDatas = classes.map(function(item) {
+      return item.passRate;
+    });
+    var excellentRateDatas = classes.map(function(item) {
+      return item.excellentRate;
+    });
+
+    return {
+      animation: animationIsOpen,
+      textStyle: textStyle,
+      color: [
+        "rgba(61, 160, 255, 0.8)",
+        "#4bcb74",
+        "rgba(151, 94, 229, 0.8)",
+        "#999999",
+        "rgba(67, 80, 136, 0.8)",
+        "rgba(250, 212, 68, 0.8)"
+      ],
+      title: {
+        text: "▲  " + title,
+        left: "center",
+        bottom: 0,
+        textStyle: {
+          color: "rgba(67, 80, 136, 0.8)"
+        }
+      },
+      grid: {
+        top: 50,
+        bottom: 90,
+        show: true,
+        borderColor: "rgba(230,230,230,1)"
+      },
+      xAxis: {
+        type: "category",
+        data: xAxisData,
+        axisTick: {
+          show: false
+        },
+        splitArea: {
+          show: true,
+          areaStyle: {
+            color: ["rgba(255,255,255,1)", "rgba(250,250,250,1)"]
+          }
+        },
+        splitLine: {
+          show: true,
+          lineStyle: {
+            color: "rgba(233,233,233,1)"
+          }
+        },
+        axisLabel: {
+          fontSize: 16,
+          margin: 12,
+          interval: 0,
+          formatter: function(value) {
+            if (value.length > 6) {
+              return [value.substring(0, 6), value.substring(6)].join("\n");
+            }
+            return value;
+          }
+        },
+        axisLine: {
+          lineStyle: {
+            color: "rgba(233,233,233,1)"
+          }
+        }
+      },
+      yAxis: [
+        {
+          type: "value",
+          z: 1,
+          position: "left",
+          axisTick: {
+            show: false
+          },
+          axisLine: {
+            lineStyle: {
+              color: "rgba(233,233,233,1)"
+            }
+          },
+          splitLine: {
+            show: true,
+            lineStyle: {
+              color: "rgba(233,233,233,1)"
+            }
+          },
+          axisLabel: {
+            fontSize: 16,
+            color: "#555"
+          }
+        },
+        {
+          type: "value",
+          min: 0,
+          max: 1,
+          position: "right",
+          axisTick: {
+            show: false
+          },
+          axisLine: {
+            lineStyle: {
+              color: "rgba(233,233,233,1)"
+            }
+          },
+          axisLabel: {
+            fontSize: 16,
+            color: "#555",
+            formatter: function(value) {
+              if (!value) return "0";
+              return value.toFixed(1);
+            }
+          }
+        }
+      ],
+      series: [
+        {
+          type: "bar",
+          data: avgDatas,
+          name: "平均分",
+          barWidth: 12
+        },
+        {
+          type: "bar",
+          data: relateAvgDatas,
+          name: "相对平均分",
+          barWidth: 12
+        },
+        {
+          type: "bar",
+          data: maxDatas,
+          name: "最高分",
+          barWidth: 12
+        },
+        {
+          type: "bar",
+          data: minDatas,
+          name: "最低分",
+          barWidth: 12
+        },
+        {
+          type: "scatter",
+          data: passRateDatas,
+          yAxisIndex: 1,
+          symbol: symbolCircle,
+          symbolSize: 10,
+          name: "及格率"
+        },
+        {
+          type: "scatter",
+          data: excellentRateDatas,
+          yAxisIndex: 1,
+          symbol: symbolCircle,
+          symbolSize: 10,
+          name: "优秀率"
+        }
+      ]
+    };
+  }
+
+  function getLineOptions(datas) {
+    var xAxisData = datas.map(function(item) {
+      return item.name;
+    });
+    var levelDatas = datas.map(function(item) {
+      return item.difficulty;
+    });
+    var linearColor = new echarts.graphic.LinearGradient(0, 1, 0, 0, [
+      {
+        offset: 1,
+        color: "rgba(61,160,255,1)"
+      },
+      {
+        offset: 0,
+        color: "rgba(61,160,255,0)"
+      }
+    ]);
+    return {
+      animation: animationIsOpen,
+      textStyle: textStyle,
+      grid: {
+        top: 120
+      },
+      xAxis: {
+        type: "category",
+        data: xAxisData,
+        boundaryGap: false,
+        splitLine: {
+          show: true,
+          lineStyle: {
+            color: "rgba(233,233,233,1)"
+          }
+        },
+        axisLabel: {
+          fontSize: 19,
+          margin: 20,
+          interval: 0
+        },
+        axisLine: {
+          lineStyle: {
+            color: "rgba(233,233,233,1)"
+          }
+        }
+      },
+      yAxis: {
+        type: "value",
+        min: 0,
+        max: 1,
+        interval: 0.1,
+        axisTick: {
+          show: false
+        },
+        axisLine: {
+          lineStyle: {
+            color: "rgba(233,233,233,1)"
+          }
+        },
+        splitLine: {
+          show: true,
+          lineStyle: {
+            color: "rgba(233,233,233,1)"
+          }
+        },
+        axisLabel: {
+          fontSize: 19,
+          margin: 30,
+          color: "#555",
+          formatter: function(value, index) {
+            return value.toFixed(1);
+          }
+        }
+      },
+      series: [
+        {
+          type: "line",
+          data: levelDatas,
+          symbol: "none",
+          lineStyle: {
+            color: "rgba(61, 160, 255, 0.8)"
+          },
+          areaStyle: {
+            color: linearColor
+          }
+        }
+      ]
+    };
+  }
+
+  function getLineReverseOptions(datas) {
+    var yAxisDatas = datas.map(function(item) {
+      return item.name;
+    });
+    var levelDatas = datas.map(function(item) {
+      return item.difficulty;
+    });
+
+    var linearColor = new echarts.graphic.LinearGradient(0, 0, 1, 0, [
+      {
+        offset: 1,
+        color: "rgba(61,160,255,1)"
+      },
+      {
+        offset: 0,
+        color: "rgba(61,160,255,0)"
+      }
+    ]);
+    return {
+      animation: animationIsOpen,
+      textStyle: textStyle,
+      grid: {
+        top: 150,
+        left: 130,
+        bottom: 50
+      },
+      yAxis: {
+        type: "category",
+        boundaryGap: false,
+        data: yAxisDatas,
+        inverse: true,
+        splitLine: {
+          show: true,
+          lineStyle: {
+            color: "rgba(233,233,233,1)"
+          }
+        },
+        axisLabel: {
+          fontSize: 17,
+          margin: 20,
+          interval: 0
+        },
+        axisLine: {
+          lineStyle: {
+            color: "rgba(233,233,233,1)"
+          }
+        }
+      },
+      xAxis: {
+        type: "value",
+        min: 0,
+        max: 1,
+        interval: 0.1,
+        position: "top",
+        axisTick: {
+          show: false
+        },
+        axisLine: {
+          lineStyle: {
+            color: "rgba(233,233,233,1)"
+          }
+        },
+        splitLine: {
+          show: true,
+          lineStyle: {
+            color: "rgba(233,233,233,1)"
+          }
+        },
+        axisLabel: {
+          fontSize: 16,
+          margin: 20,
+          color: "#555",
+          formatter: function(value, index) {
+            return value.toFixed(1);
+          }
+        }
+      },
+      series: [
+        {
+          type: "line",
+          data: levelDatas,
+          symbol: "none",
+          lineStyle: {
+            color: "rgba(61, 160, 255, 0.8)"
+          },
+          areaStyle: {
+            color: linearColor
+          }
+        }
+      ]
+    };
+  }
+
+  function getLineSmoothOptions(datainfo) {
+    var datas = datainfo.dataList;
+    var lineColor = colors[datainfo.index % colors.length];
+    var xAxisData = datas.map(function(item) {
+      return item.score;
+    });
+    var levelDatas = datas.map(function(item) {
+      return item.rangeRate;
+    });
+
+    return {
+      animation: animationIsOpen,
+      textStyle: textStyle,
+      grid: {
+        top: 110,
+        bottom: 80
+      },
+      xAxis: {
+        type: "category",
+        data: xAxisData,
+        boundaryGap: false,
+        inverse: true,
+        splitLine: {
+          show: false
+        },
+        axisLabel: {
+          fontSize: 19,
+          margin: 20,
+          interval: 0,
+          formatter: function(value) {
+            return value + "-";
+          }
+        },
+        axisLine: {
+          lineStyle: {
+            color: "rgba(233,233,233,1)"
+          }
+        }
+      },
+      yAxis: {
+        type: "value",
+        axisTick: {
+          show: false
+        },
+        axisLine: {
+          lineStyle: {
+            color: "rgba(233,233,233,1)"
+          }
+        },
+        splitLine: {
+          show: true,
+          lineStyle: {
+            color: "rgba(233,233,233,1)"
+          }
+        },
+        axisLabel: {
+          fontSize: 19,
+          margin: 20,
+          formatter: function(value, index) {
+            return value.toFixed(2);
+          }
+        }
+      },
+      series: [
+        {
+          type: "line",
+          data: levelDatas,
+          symbol: "none",
+          smooth: true,
+          smoothMonotone: "none",
+          lineStyle: {
+            color: lineColor,
+            width: 3
+          }
+        }
+      ]
+    };
+  }
+
+  window.Charts = Charts;
+})(window);

+ 77 - 0
stmms-web/src/main/webapp/static/report-pdf/js/data-parse.js

@@ -0,0 +1,77 @@
+var cover = {
+  examName: dataStatic.examName,
+  schoolName: dataStatic.schoolName,
+  subjectName: dataStatic.subjectName
+};
+var basic_question_objective = dataStatic.basic_question_objective;
+var basic_question_subjective = dataStatic.basic_question_subjective;
+var basic_class = dataStatic.basic_class;
+var basic_teacher = dataStatic.basic_teacher;
+var basic_college = dataStatic.basic_college;
+var basic_main_question = dataStatic.basic_main_question;
+var basic_question = basic_question_objective.concat(basic_question_subjective);
+var basic_sub_question = basic_question.map(function(item, index) {
+  return {
+    name: item.name,
+    number: index + 1,
+    difficulty: item.difficulty
+  };
+});
+var discrimination_level = dataStatic.discrimination_level.map(function(item) {
+  item.groups.map(function(elem) {
+    elem.levels.excellent.questionRate = (
+      (100 * elem.levels.excellent.questionCount) /
+      elem.questionCount
+    ).toFixed(2);
+    elem.levels.good.questionRate = (
+      (100 * elem.levels.good.questionCount) /
+      elem.questionCount
+    ).toFixed(2);
+    elem.levels.general.questionRate = (
+      (100 * elem.levels.general.questionCount) /
+      elem.questionCount
+    ).toFixed(2);
+    elem.levels.bad.questionRate = (
+      (100 * elem.levels.bad.questionCount) /
+      elem.questionCount
+    ).toFixed(2);
+  });
+
+  return item;
+});
+var difficulty_level = dataStatic.difficulty_level.map(function(item) {
+  item.groups.map(function(elem) {
+    elem.levels.high.questionRate = (
+      (100 * elem.levels.high.questionCount) /
+      elem.questionCount
+    ).toFixed(2);
+    elem.levels.middle.questionRate = (
+      (100 * elem.levels.middle.questionCount) /
+      elem.questionCount
+    ).toFixed(2);
+    elem.levels.low.questionRate = (
+      (100 * elem.levels.low.questionCount) /
+      elem.questionCount
+    ).toFixed(2);
+  });
+
+  return item;
+});
+dataStatic.basic_question_option.questions = dataStatic.basic_question_option.questions.map(
+  function(item) {
+    item.optionsRate = {};
+    for (key in item.options) {
+      item.optionsRate[key] = (
+        (100 * item.options[key]) /
+        item.totalCount
+      ).toFixed(2);
+    }
+    return item;
+  }
+);
+var basic_question_option = dataStatic.basic_question_option;
+// s bli
+var range_level = dataStatic.range_level;
+var range_10_totalScore = dataStatic.range_10_totalScore;
+var range_1_totalScore = dataStatic.range_1_totalScore;
+var range_segment_6 = dataStatic.range_segment_6;

+ 295 - 0
stmms-web/src/main/webapp/static/report-pdf/js/data-static.js

@@ -0,0 +1,295 @@
+function getNum(num) {
+  var number = num || 10;
+  var list = [];
+  for (var i = 0; i < number; i++) {
+    list[i] = "#";
+  }
+  return list;
+}
+
+function randomNum(max, precision) {
+  if (precision) {
+    return parseFloat((max * Math.random()).toFixed(precision));
+  } else {
+    return parseInt(max * Math.random());
+  }
+}
+
+var options = ["A", "B", "C", "D", "E", "F", "G", "#"];
+
+var chartData = {
+  basic_question: function(index, isObjective) {
+    return {
+      name: "填空题-" + (index + 1),
+      number: index + 1,
+      fullScore: 3,
+      maxScore: 2,
+      minScore: 0,
+      avgScore: randomNum(3, 1),
+      stdevScore: randomNum(3, 1),
+      coefficient: randomNum(10, 1),
+      difficulty: randomNum(1, 1),
+      discrimination: randomNum(2, 1),
+      totalCount: randomNum(100),
+      zeroCount: randomNum(10),
+      fullCount: randomNum(3),
+      fullRate: isObjective ? randomNum(1, 1) : null,
+      scoreRate: randomNum(1, 1)
+    };
+  },
+  basic_class: function(index) {
+    var prename =
+      Math.random() > 0.5 ? "19三四五六七八九十一二" : "18工程造价本";
+    return {
+      name: prename + index,
+      avgScore: randomNum(60),
+      maxScore: randomNum(100),
+      minScore: randomNum(30),
+      stdevScore: randomNum(3, 1),
+      excellentCount: randomNum(10),
+      excellentRate: randomNum(1, 1),
+      passCount: randomNum(20),
+      passRate: randomNum(1, 1)
+    };
+  },
+  basic_teacher: function(index) {
+    return {
+      name: "张小金-" + index,
+      total: {
+        avgScore: randomNum(60),
+        maxScore: randomNum(100),
+        minScore: randomNum(50),
+        stdevScore: randomNum(3, 1),
+        excellentCount: randomNum(10),
+        excellentRate: randomNum(1, 1),
+        passCount: randomNum(20),
+        passRate: randomNum(1, 1),
+        totalCount: randomNum(100),
+        relativeAvgScore: randomNum(20) - 10
+      }
+    };
+  },
+  basic_teacher_class: function(index) {
+    var prename = Math.random() > 0.5 ? "一二三四五六七八九十" : "城乡规划学院";
+    return {
+      name: prename + index,
+      avgScore: randomNum(60),
+      maxScore: randomNum(100),
+      minScore: randomNum(50),
+      stdevScore: randomNum(3, 1),
+      excellentCount: randomNum(10),
+      excellentRate: randomNum(1, 1),
+      passCount: randomNum(20),
+      passRate: randomNum(1, 1),
+      totalCount: randomNum(100),
+      relativeAvgScore: randomNum(10) - 20
+    };
+  },
+  basic_college: function(index) {
+    return {
+      name: "汽车专修学院-" + index,
+      avgScore: randomNum(60),
+      maxScore: randomNum(100),
+      minScore: randomNum(30),
+      stdevScore: randomNum(3, 1),
+      excellentCount: randomNum(10),
+      excellentRate: randomNum(1, 1),
+      passCount: randomNum(20),
+      passRate: randomNum(1, 1)
+    };
+  },
+  basic_main_question: function(index) {
+    return {
+      name: "题名称" + index,
+      objective: true,
+      fullScore: randomNum(20),
+      maxScore: randomNum(20),
+      minScore: randomNum(10),
+      avgScore: randomNum(10),
+      stdevScore: randomNum(5),
+      coefficient: randomNum(10),
+      difficulty: randomNum(1, 1),
+      discrimination: randomNum(2),
+      totalCount: randomNum(1000),
+      zeroCount: randomNum(50),
+      fullCount: randomNum(50)
+    };
+  },
+  discrimination_level_question: function(index) {
+    return {
+      name: "大题名称" + index,
+      questionCount: 50,
+      fullScore: randomNum(150),
+      coefficient: randomNum(10, 2),
+      levels: {
+        excellent: {
+          questionCount: randomNum(10),
+          fullScore: randomNum(50)
+        },
+        good: {
+          questionCount: randomNum(40),
+          fullScore: randomNum(50)
+        },
+        general: {
+          questionCount: randomNum(30),
+          fullScore: randomNum(20)
+        },
+        bad: {
+          questionCount: randomNum(20),
+          fullScore: randomNum(10)
+        }
+      }
+    };
+  },
+  difficulty_level_question: function(index) {
+    return {
+      name: "大题名称" + index,
+      questionCount: 50,
+      fullScore: randomNum(150),
+      difficulty: randomNum(10, 2),
+      levels: {
+        high: {
+          questionCount: randomNum(10),
+          fullScore: randomNum(50)
+        },
+        middle: {
+          questionCount: randomNum(40),
+          fullScore: randomNum(50)
+        },
+        low: {
+          questionCount: randomNum(30),
+          fullScore: randomNum(20)
+        }
+      }
+    };
+  },
+  basic_question_option: function(index) {
+    var optionsAns = {};
+    options
+      .filter(function() {
+        return Math.random() > 0.5;
+      })
+      .map(function(key) {
+        optionsAns[key] = randomNum(2000);
+      });
+
+    return {
+      number: "题号" + index,
+      totalCount: 10000,
+      correctCount: randomNum(5000),
+      difficulty: randomNum(1, 2),
+      discrimination: randomNum(1, 2),
+      answer: "C",
+      options: optionsAns
+    };
+  },
+  range_level: function(index) {
+    return {
+      name: "新媒体" + index,
+      highScore: randomNum(90),
+      lowScore: randomNum(90),
+      totalCount: randomNum(10000)
+    };
+  },
+  range_score_level: function(index, isStep) {
+    return {
+      score: isStep ? 150 - index * 10 : 100 - index,
+      rangeCount: randomNum(10000),
+      rangeRate: randomNum(30, 2),
+      sumCount: randomNum(10000),
+      sumRate: randomNum(100, 2)
+    };
+  }
+};
+
+var dataStatic = {
+  subjectName: "英语",
+  examName: "2019年6月期末考试",
+  schoolName: "呼家楼中心小学",
+  basic_question_objective: getNum(30).map(function(item, index) {
+    return chartData.basic_question(index, true);
+  }),
+  basic_question_subjective: getNum(30).map(function(item, index) {
+    return chartData.basic_question(index, false);
+  }),
+  basic_class: getNum(26).map(function(item, index) {
+    return chartData.basic_class(index);
+  }),
+  basic_teacher: getNum(11).map(function(item, index) {
+    var teacher = chartData.basic_teacher(index);
+    teacher.classes = getNum(7).map(function(elem, eindex) {
+      return chartData.basic_teacher_class(eindex);
+    });
+    return teacher;
+  }),
+  basic_college: getNum(26).map(function(item, index) {
+    return chartData.basic_college(index);
+  }),
+  basic_main_question: getNum(6).map(function(item, index) {
+    return chartData.basic_main_question(index);
+  }),
+  discrimination_level: getNum(8).map(function(item, index) {
+    return {
+      name: index == 0 ? "全部" : "传媒技术" + index + "班",
+      groups: getNum(7).map(function(elem, eindex) {
+        return chartData.discrimination_level_question(eindex);
+      })
+    };
+  }),
+  difficulty_level: getNum(8).map(function(item, index) {
+    return {
+      name: index == 0 ? "全部" : "传媒技术" + index + "班",
+      groups: getNum(7).map(function(elem, eindex) {
+        return chartData.difficulty_level_question(eindex);
+      })
+    };
+  }),
+  basic_question_option: {
+    options: options.slice(0, -1),
+    questions: getNum(78).map(function(elem, eindex) {
+      return chartData.basic_question_option(eindex);
+    })
+  },
+  range_level: getNum(35).map(function(item, index) {
+    return chartData.range_level(index);
+  }),
+  range_10_totalScore: {
+    total: getNum(16).map(function(elem, eindex) {
+      return chartData.range_score_level(eindex, true);
+    }),
+    classes: getNum(5).map(function(item, index) {
+      return {
+        name: "新媒体" + index,
+        ranges: getNum(16).map(function(elem, eindex) {
+          return chartData.range_score_level(eindex, true);
+        })
+      };
+    })
+  },
+  range_1_totalScore: {
+    total: getNum(100).map(function(elem, eindex) {
+      return chartData.range_score_level(eindex, false);
+    }),
+    classes: getNum(5).map(function(item, index) {
+      return {
+        name: "新媒体" + index,
+        ranges: getNum(100).map(function(elem, eindex) {
+          return chartData.range_score_level(eindex, false);
+        })
+      };
+    })
+  },
+  range_segment_6: getNum(8).map(function(item, index) {
+    return {
+      name: "题目类型" + index,
+      groups: getNum(7).map(function(elem, eindex) {
+        return {
+          name: eindex == 0 ? "全部" : "传媒技术" + index + "班",
+          segments: getNum(7).map(function(seg, sindex) {
+            return chartData.range_score_level(sindex, true);
+          })
+        };
+      })
+    };
+  })
+};

+ 218 - 0
stmms-web/src/main/webapp/static/report-pdf/js/linsh.json

@@ -0,0 +1,218 @@
+{
+  "examName": "考试名称",
+  "schoolName": "学校名称",
+  "subjectName": "科目名称",
+  "basic_question_objective": [
+    {
+      "name": "小题名称",
+      "number": "题号",
+      "fullScore": 3,
+      "maxScore": 2,
+      "minScore": 0,
+      "avgScore": 2,
+      "stdevScore": 3,
+      "coefficient": 10,
+      "difficulty": 0.3,
+      "discrimination": 2,
+      "totalCount": 1000,
+      "zeroCount": 10,
+      "fullCount": 10,
+      "fullRate": 0.2,
+      "scoreRate": 0.3
+    }
+  ],
+  "basic_question_subjective": [
+    {
+      "sample": "与basic_question_objective相同"
+    }
+  ],
+  "basic_question_option": {
+    "options": [
+      "A",
+      "B",
+      "C",
+      "D",
+      "E"
+    ],
+    "questions": [
+      {
+        "number": "题号",
+        "totalCount": 1000,
+        "correctCount": 500,
+        "difficulty": 0.5,
+        "discrimination": 0.3,
+        "answer": "正确答案",
+        "options": {
+          "A": 10,
+          "C": 20,
+          "#": 100
+        }
+      }
+    ]
+  },
+  "basic_main_question": [
+    {
+      "name": "大题名称",
+      "objective": true,
+      "fullScore": 3,
+      "maxScore": 2,
+      "minScore": 0,
+      "avgScore": 2,
+      "stdevScore": 3,
+      "coefficient": 10,
+      "difficulty": 0.3,
+      "discrimination": 2,
+      "totalCount": 1000,
+      "zeroCount": 10,
+      "fullCount": 10
+    }
+  ],
+  "basic_class": [
+    {
+      "name": "班级名称",
+      "avgScore": 50,
+      "maxScore": 100,
+      "minScore": 50,
+      "stdevScore": 10,
+      "excellentCount": 10,
+      "excellentRate": 0.1,
+      "passCount": 20,
+      "passRate": 0.3
+    }
+  ],
+  "basic_college": [
+    {
+      "name": "学院名称",
+      "sample": "其他字段与basic_class相同"
+    }
+  ],
+  "basic_teacher": [
+    {
+      "name": "教师姓名",
+      "total": {
+        "totalCount": 100,
+        "maxScore": 100,
+        "minScore": 50,
+        "excellentCount": 10,
+        "excellentRate": 0.1,
+        "passCount": 20,
+        "passRate": 0.3,
+        "avgScore": 50,
+        "relativeAvgScore": -10
+      },
+      "classes": [
+        {
+          "name": "班级名称",
+          "sample": "其他字段与total相同"
+        }
+      ]
+    }
+  ],
+  "discrimination_level": [
+    {
+      "name": "全部或班级名称",
+      "groups": [
+        {
+          "name": "全卷或大题名称",
+          "questionCount": 50,
+          "fullScore": 100,
+          "coefficient": 10,
+          "levels": {
+            "excellent": {
+              "questionCount": 10,
+              "fullScore": 20
+            },
+            "good": {
+              "questionCount": 10,
+              "fullScore": 20
+            },
+            "general": {
+              "questionCount": 10,
+              "fullScore": 20
+            },
+            "bad": {
+              "questionCount": 10,
+              "fullScore": 20
+            }
+          }
+        }
+      ]
+    }
+  ],
+  "difficulty_level": [
+    {
+      "name": "全部或班级名称",
+      "groups": [
+        {
+          "name": "全卷或大题名称",
+          "questionCount": 50,
+          "fullScore": 100,
+          "difficulty": 10,
+          "levels": {
+            "high": {
+              "questionCount": 10,
+              "fullScore": 20
+            },
+            "middle": {
+              "questionCount": 10,
+              "fullScore": 20
+            },
+            "low": {
+              "questionCount": 10,
+              "fullScore": 20
+            }
+          }
+        }
+      ]
+    }
+  ],
+  "range_level": [
+    {
+      "name": "全部或班级名称",
+      "highScore": 120,
+      "lowScore": 20,
+      "totalCount": 1000
+    }
+  ],
+  "range_10_totalScore": {
+    "total": [
+      {
+        "score": 150,
+        "rangeCount": 10,
+        "rangeRate": 0.1,
+        "sumCount": 10,
+        "sumRate": 0.2
+      }
+    ],
+    "classes": [
+      {
+        "name": "班级名称",
+        "ranges": [
+          "数组结构与total相同"
+        ]
+      }
+    ]
+  },
+  "range_1_totalScore": {
+    "sample": "数据结构与range_10_totalScore完全相同"
+  },
+  "range_segment_6": [
+    {
+      "name": "客观题或其他大题名称",
+      "groups": [
+        {
+          "name": "全体或班级名称",
+          "segments": [
+            {
+              "score": "0.5~20",
+              "rangeCount": 10,
+              "rangeRate": 0.1,
+              "sumCount": 10,
+              "sumRate": 0.2
+            }
+          ]
+        }
+      ]
+    }
+  ]
+}

+ 376 - 0
stmms-web/src/main/webapp/static/report-pdf/js/teaching.js

@@ -0,0 +1,376 @@
+var tmpl = window.template;
+tmpl.config({ sTag: "<#", eTag: "#>", compress: true });
+var $bodyMain = $("#body-main");
+var echartList = [];
+
+build();
+publishReady();
+
+function build() {
+  createCover();
+  createBarPointChart(
+    basic_question_objective,
+    26,
+    "客观题成绩分析",
+    "barPointTopic"
+  );
+  createBarPointChart(
+    basic_question_subjective,
+    26,
+    "主观题成绩分析",
+    "barPointTopic"
+  );
+  createBarPointChart(basic_class, 22, "班级成绩分析", "barPointGrade");
+  createTeacherScore(basic_teacher);
+  createTeacherGrade(basic_teacher);
+  createBarPointChart(basic_college, 22, "学院成绩分析", "barPointGrade");
+  createLineChart(basic_main_question);
+  createLineReverseChart(basic_sub_question);
+  createDiscriminationDifficultyLevel(discrimination_level, "discrimination");
+  createDiscriminationDifficultyLevel(difficulty_level, "difficulty");
+  createBasicQuestion(basic_question);
+  createBasicMainQuestion(basic_main_question);
+  createBasicQuestionOption(basic_question_option);
+  createRangeLevel(range_level);
+  createRange10TotalScore(range_10_totalScore);
+  createRangeTotalScore(range_1_totalScore);
+  createRangeSegment(range_segment_6);
+  createEchart();
+  fillCatalogNum();
+}
+
+function publishReady() {
+  var eventEmitInterval = setInterval(function() {
+    document.body.dispatchEvent(new Event("view-ready"));
+  }, 25);
+
+  document.body.addEventListener("view-ready-acknowledged", function() {
+    clearInterval(eventEmitInterval);
+  });
+}
+
+function createCover() {
+  var hTmpl = $("#cover").html();
+  var $dom = $(tmpl(hTmpl, cover));
+  $bodyMain.append($dom);
+}
+// 题型成绩分析,班级成绩分析,学院成绩分析
+function createBarPointChart(dataList, splitRange, title, chartType) {
+  var hTmpl = $("#page-chart").html();
+  var labelHeight = Math.round(1170 / splitRange);
+  sectionArr(dataList, splitRange).forEach(function(item) {
+    var chartId = getEchartId();
+    var $dom = tmpl(hTmpl, {
+      title: title,
+      chartId: chartId,
+      height: 220 + labelHeight * item.length + "px"
+    });
+    $bodyMain.append(createNewBox($dom));
+    addEchart({
+      chartId: chartId,
+      chartType: chartType,
+      datas: item
+    });
+  });
+}
+
+// 任课老师成绩分析
+function createTeacherScore(dataList) {
+  var hTmpl = $("#teacher-score").html();
+  var splitList = sectionArr(dataList, 6);
+  splitList.forEach(function(item) {
+    var chartId = getEchartId();
+    var $dom = tmpl(hTmpl, {
+      chartId: chartId,
+      dataList: item,
+      teacherScoreTableTpl: tmpl($("#teacher-score-table").html())
+    });
+    $bodyMain.append(createNewBox($dom));
+    addEchart({
+      chartId: chartId,
+      chartType: "barTeachers",
+      datas: item
+    });
+  });
+  // 总明细表
+  if (splitList.length > 1) {
+    var hTmpl2 = $("#teacher-score-table").html();
+    sectionArr(dataList, 26).forEach(function(item) {
+      var $dom = tmpl(hTmpl2, {
+        dataList: item,
+        pageTableClass: "teacher-table"
+      });
+      $bodyMain.append(createNewBox($dom));
+    });
+  }
+}
+// 任课老师班级成绩分析
+function createTeacherGrade(dataList) {
+  var hTmpl = $("#teacher-grade").html();
+  sectionArr(dataList, 3).forEach(function(item) {
+    var chartList = item.map(function(elem) {
+      var chartId = getEchartId();
+      addEchart({
+        chartId: chartId,
+        chartType: "barTeacherGrade",
+        datas: elem
+      });
+      return chartId;
+    });
+    var $dom = tmpl(hTmpl, {
+      chartList: chartList
+    });
+    $bodyMain.append(createNewBox($dom));
+  });
+}
+
+// 大题难度分析
+function createLineChart(dataList) {
+  var hTmpl = $("#page-chart").html();
+  var chartId = getEchartId();
+  var $dom = tmpl(hTmpl, {
+    title: "大题难度分析",
+    chartId: chartId,
+    chartClassName: "chart-line"
+  });
+  $bodyMain.append(createNewBox($dom));
+  addEchart({
+    chartId: chartId,
+    chartType: "line",
+    datas: dataList
+  });
+}
+// 小题难度分析
+function createLineReverseChart(dataList) {
+  var hTmpl = $("#page-chart").html();
+  sectionArr(dataList, 46).forEach(function(item) {
+    var chartId = getEchartId();
+    var $dom = tmpl(hTmpl, {
+      title: "小题难度分析",
+      chartId: chartId,
+      height: 200 + 26 * item.length + "px"
+    });
+    $bodyMain.append(createNewBox($dom));
+    addEchart({
+      chartId: chartId,
+      chartType: "lineReverse",
+      datas: item
+    });
+  });
+}
+// 区分度等级分布,难度等级分布
+function createDiscriminationDifficultyLevel(dataList, type) {
+  var hTmpl = $("#" + type + "-level-table").html();
+  sectionArr(dataList, 4).forEach(function(item) {
+    var $dom = tmpl(hTmpl, {
+      dataList: item
+    });
+    $bodyMain.append(createNewBox($dom));
+  });
+}
+// 题目统计特征
+function createBasicQuestion(dataList) {
+  var hTmpl = $("#basic-question-table").html();
+  sectionArr(dataList, 33).forEach(function(item) {
+    var $dom = tmpl(hTmpl, {
+      dataList: item
+    });
+    $bodyMain.append(createNewBox($dom));
+  });
+}
+// 大题结构特征
+function createBasicMainQuestion(dataList) {
+  var hTmpl = $("#basic-main-question-table").html();
+  var $dom = tmpl(hTmpl, {
+    dataList: dataList
+  });
+  $bodyMain.append(createNewBox($dom));
+}
+// 选项分析
+function createBasicQuestionOption(data) {
+  var hTmpl = $("#basic-question-option-table").html();
+  sectionArr(data.questions, 32).forEach(function(item) {
+    var $dom = tmpl(hTmpl, {
+      options: data.options,
+      questions: item
+    });
+    $bodyMain.append(createNewBox($dom));
+  });
+}
+// 考生分段比例
+function createRangeLevel(dataList) {
+  var hTmpl = $("#range-level-table").html();
+  sectionArr(dataList, 31).forEach(function(item) {
+    var $dom = tmpl(hTmpl, {
+      dataList: item
+    });
+    $bodyMain.append(createNewBox($dom));
+  });
+}
+// 总分频率分布
+function createRange10TotalScore(datas) {
+  var pageList = [
+    {
+      title: "总分频率分布分析",
+      dataList: datas.total
+    }
+  ];
+  pageList = pageList.concat(
+    datas.classes.map(function(item) {
+      return {
+        title: item.name + " 总分频率分布",
+        dataList: item.ranges
+      };
+    })
+  );
+  var hTmpl = $("#range-totalScore").html();
+  pageList.forEach(function(item, index) {
+    var chartId = getEchartId();
+    addEchart({
+      chartId: chartId,
+      chartType: "lineSmooth",
+      datas: {
+        index: index,
+        dataList: item.dataList
+      }
+    });
+    var $dom = tmpl(hTmpl, {
+      title: item.title,
+      pageTableClass: "table-ave-5",
+      dataList: item.dataList,
+      chartId: chartId
+    });
+    $bodyMain.append(createNewBox($dom));
+  });
+}
+// 总分一分一段表
+function createRangeTotalScore(datas) {
+  var pageList = [
+    {
+      title: "总分一分一段表",
+      dataList: datas.total
+    }
+  ];
+  pageList = pageList.concat(
+    datas.classes.map(function(item) {
+      return {
+        title: item.name + " 总分一分一段表",
+        dataList: item.ranges
+      };
+    })
+  );
+  var hTmpl = $("#range-totalScore").html();
+  pageList.forEach(function(item, index) {
+    sectionArr(item.dataList, 28).forEach(function(elem) {
+      var $dom = tmpl(hTmpl, {
+        title: item.title,
+        pageTableClass: "table-ave-5 page-table-pad",
+        dataList: elem,
+        chartId: ""
+      });
+      $bodyMain.append(createNewBox($dom));
+    });
+  });
+}
+// 六段频率统计
+function createRangeSegment(dataList) {
+  var hTmpl = $("#range-segment-table").html();
+  dataList.map(function(item) {
+    sectionArr(item.groups, 4).map(function(elem) {
+      var $dom = tmpl(hTmpl, {
+        title: item.name + " 六段频率统计",
+        dataList: elem
+      });
+      $bodyMain.append(createNewBox($dom));
+    });
+  });
+}
+
+/**
+ * 渲染模板
+ * @param {Object} renderItem 渲染配置
+ */
+function renderTmp(renderItem) {
+  var hTmpl = $("#" + renderItem.templateName).html();
+  var $dom = $(tmpl(hTmpl, renderItem.datas || {}));
+  return $dom;
+}
+
+/**
+ * 创建新的box
+ * @param {DomStr} bodyDom 页面填充内容
+ * @param {String} boxType box类型,默认report-box
+ */
+function createNewBox(bodyDom, boxType) {
+  return renderTmp({
+    templateName: "page-box",
+    datas: {
+      bodyDom: bodyDom || "",
+      boxType: boxType || "report-box"
+    }
+  });
+}
+
+/**
+ * 创建echart图表
+ *
+ */
+function createEchart() {
+  echartList.forEach(function(elem) {
+    var charts = new Charts(
+      document.getElementById(elem.chartId),
+      elem.datas,
+      elem.chartType
+    );
+    charts.renderChart();
+  });
+}
+
+/**
+ * 渲染页码
+ */
+function fillCatalogNum() {
+  var hTmpl = $("#page-foot").html();
+  $(".report-box").each(function(index) {
+    var page = index + 1;
+    var dom = tmpl(hTmpl, {
+      name: cover.name,
+      time: cover.time,
+      pageNum: page < 10 ? "0" + page : page
+    });
+    $(this)
+      .attr("id", "page-" + page)
+      .append($(dom));
+  });
+}
+
+/**
+ *
+ * @param {Array} arrayList 要分段的数组
+ * @param {Number} sectionLength 每段的长度
+ */
+function sectionArr(arrayList, sectionLength) {
+  var splitArr = [];
+  for (var i = 0, len = arrayList.length; i < len; i += sectionLength) {
+    splitArr.push(arrayList.slice(i, i + sectionLength));
+  }
+  return splitArr;
+}
+
+/**
+ * 获取chartId
+ */
+function getEchartId() {
+  return "chart-" + echartList.length;
+}
+/**
+ * 添加chart渲染队列
+ * @param {Object} option chart配置
+ */
+function addEchart(option) {
+  echartList.push({
+    chartId: option.chartId || getEchartId(),
+    chartType: option.chartType,
+    datas: option.datas
+  });
+}

File diff suppressed because it is too large
+ 21 - 0
stmms-web/src/main/webapp/static/report-pdf/libs/echarts.min.4.2.0-rc2.js


File diff suppressed because it is too large
+ 1 - 0
stmms-web/src/main/webapp/static/report-pdf/libs/jquery-2.1.4.min.js


+ 311 - 0
stmms-web/src/main/webapp/static/report-pdf/libs/template.js

@@ -0,0 +1,311 @@
+/*!
+ * template.js v0.7.1 (https://github.com/yanhaijing/template.js)
+ * API https://github.com/yanhaijing/template.js/blob/master/doc/api.md
+ * Copyright 2015 yanhaijing. All Rights Reserved
+ * Licensed under MIT (https://github.com/yanhaijing/template.js/blob/master/MIT-LICENSE.txt)
+ */
+;(function(root, factory) {
+    var template = factory(root);
+    if (typeof define === 'function' && define.amd) {
+        // AMD
+        define('template', function() {
+            return template;
+        });
+    } else if (typeof exports === 'object') {
+        // Node.js
+        module.exports = template;
+    } else {
+        // Browser globals
+        var _template = root.template;
+
+        template.noConflict = function() {
+            if (root.template === template) {
+                root.template = _template;
+            }
+
+            return template;
+        };
+        root.template = template;
+    }
+}(this, function(root) {
+    'use strict';
+    var o = {
+        sTag: '<%',//开始标签
+        eTag: '%>',//结束标签
+        compress: false,//是否压缩html
+        escape: true, //默认输出是否进行HTML转义
+        error: function (e) {}//错误回调
+    };
+    var functionMap = {}; //内部函数对象
+    //修饰器前缀
+    var modifierMap = {
+        '': function (param) {return nothing(param)},
+        'h': function (param) {return encodeHTML(param)},
+        'u': function (param) {return encodeURI(param)}
+    };
+
+    var toString = {}.toString;
+    var slice = [].slice;
+    function type(x) {
+        if(x === null){
+            return 'null';
+        }
+
+        var t= typeof x;
+
+        if(t !== 'object'){
+            return t;
+        }
+
+        var c = toString.call(x).slice(8, -1).toLowerCase();
+        if(c !== 'object'){
+            return c;
+        }
+
+        if(x.constructor==Object){
+            return c;
+        }
+
+        return 'unkonw';
+    }
+
+    function isObject(obj) {
+        return type(obj) === 'object';
+    }
+    function isFunction(fn) {
+        return type(fn) === 'function';
+    }
+    function isString(str) {
+        return type(str) === 'string';
+    }
+    function extend() {
+        var target = arguments[0] || {};
+        var arrs = slice.call(arguments, 1);
+        var len = arrs.length;
+     
+        for (var i = 0; i < len; i++) {
+            var arr = arrs[i];
+            for (var name in arr) {
+                target[name] = arr[name];
+            }
+     
+        }
+        return target;
+    }
+    function clone() {
+        var args = slice.call(arguments);
+        return extend.apply(null, [{}].concat(args));
+    }
+    function nothing(param) {
+        return param;
+    }
+    function encodeHTML(source) {
+        return String(source)
+            .replace(/&/g,'&amp;')
+            .replace(/</g,'&lt;')
+            .replace(/>/g,'&gt;')
+            .replace(/\\/g,'&#92;')
+            .replace(/"/g,'&quot;')
+            .replace(/'/g,'&#39;');
+    }
+    function compress(html) {
+        return html.replace(/\s+/g, ' ').replace(/<!--[\w\W]*?-->/g, '');
+    }
+    function consoleAdapter(cmd, msg) {
+        typeof console !== 'undefined' && console[cmd] && console[cmd](msg);
+    }
+    function handelError(e) {
+        var message = 'template.js error\n\n';
+
+        for (var key in e) {
+            message += '<' + key + '>\n' + e[key] + '\n\n';
+        }
+        message += '<message>\n' + e.message + '\n\n';
+        consoleAdapter('error', message);
+
+        o.error(e);
+        function error() {
+            return 'template.js error';
+        }
+        error.toString = function () {
+            return '__code__ = "template.js error"';
+        }
+        return error;
+    }
+    function parse(tpl, opt) {
+        var code = '';
+        var sTag = opt.sTag;
+        var eTag = opt.eTag;
+        var escape = opt.escape;
+        function parsehtml(line) {
+            // 单双引号转义,换行符替换为空格
+            line = line.replace(/('|")/g, '\\$1').replace(/\n/g, ' ');
+            return ';__code__ += ("' + line + '")\n';
+        }
+        function parsejs(line) {              
+            //var reg = /^(:?)(.*?)=(.*)$/;
+            var reg = /^(?:=|(:.*?)=)(.*)$/
+            var html;
+            var arr;
+            var modifier;
+
+            // = := :*=
+            // :h=123 [':h=123', 'h', '123']
+            if (arr = reg.exec(line)) {
+                html = arr[2]; // 输出
+                if (Boolean(arr[1])) {
+                    // :开头
+                    modifier = arr[1].slice(1);
+                } else {
+                    // = 开头
+                    modifier = escape ? 'h' : '';
+                }
+
+                return ';__code__ += __modifierMap__["' + modifier + '"](typeof (' + html + ') !== "undefined" ? (' + html + ') : "")\n';
+            }
+            
+            //原生js
+            return ';' + line + '\n';
+        }
+
+        var tokens = tpl.split(sTag);
+
+        for (var i = 0, len = tokens.length; i < len; i++) {
+            var token = tokens[i].split(eTag);
+
+            if (token.length === 1) {
+                code += parsehtml(token[0]);
+            } else {
+                code += parsejs(token[0], true);
+                if (token[1]) {
+                    code += parsehtml(token[1]);
+                }
+            }
+        }
+
+        return code;
+    }
+    function compiler(tpl, opt) {
+        var mainCode = parse(tpl, opt);
+
+        var headerCode = '\n' + 
+        '    var html = (function (__data__, __modifierMap__) {\n' + 
+        '        var __str__ = "", __code__ = "";\n' + 
+        '        for(var key in __data__) {\n' + 
+        '            __str__+=("var " + key + "=__data__[\'" + key + "\'];");\n' + 
+        '        }\n' + 
+        '        eval(__str__);\n\n';
+
+        var footerCode = '\n' + 
+        '        ;return __code__;\n' + 
+        '    }(__data__, __modifierMap__));\n' + 
+        '    return html;\n';
+
+        var code = headerCode + mainCode + footerCode;
+        code = code.replace(/[\r]/g, ' '); // ie 7 8 会报错,不知道为什么
+        try {
+            var Render = new Function('__data__', '__modifierMap__', code); 
+            Render.toString = function () {
+                return mainCode;
+            }
+            return Render;
+        } catch(e) {
+            e.temp = 'function anonymous(__data__, __modifierMap__) {' + code + '}';
+            throw e;
+        }  
+    }
+    function compile(tpl, opt) {
+        opt = clone(o, opt);
+
+        try {
+            var Render = compiler(tpl, opt);
+        } catch(e) {
+            e.name = 'CompileError';
+            e.tpl = tpl;
+            e.render = e.temp;
+            delete e.temp;
+            return handelError(e);
+        }
+
+        function render(data) {
+            data = clone(functionMap, data);
+            try {
+                var html = Render(data, modifierMap);
+                html = opt.compress ? compress(html) : html;
+                return html;
+            } catch(e) {
+                e.name = 'RenderError';
+                e.tpl = tpl;
+                e.render = Render.toString();
+                return handelError(e)();
+            }            
+        }
+
+        render.toString = function () {
+            return Render.toString();
+        };
+        return render;
+    }
+    function template(tpl, data) {
+        if (typeof tpl !== 'string') {
+            return '';
+        }
+
+        var fn = compile(tpl);
+        if (!isObject(data)) {
+            return fn;
+        }
+
+        return fn(data);
+    }
+
+    template.config = function (option) {
+        if (isObject(option)) {
+            o = extend(o, option);
+        }
+        return clone(o);
+    };
+
+    template.registerFunction = function(name, fn) {
+        if (!isString(name)) {
+            return clone(functionMap);
+        }
+        if (!isFunction(fn)) {
+            return functionMap[name];
+        }
+
+        return functionMap[name] = fn;
+    }
+    template.unregisterFunction = function (name) {
+        if (!isString(name)) {
+            return false;
+        }
+        delete functionMap[name];
+        return true;
+    }
+
+    template.registerModifier = function(name, fn) {
+        if (!isString(name)) {
+            return clone(modifierMap);
+        }
+        if (!isFunction(fn)) {
+            return modifierMap[name];
+        }
+
+        return modifierMap[name] = fn;
+    }
+    template.unregisterModifier = function (name) {
+        if (!isString(name)) {
+            return false;
+        }
+        delete modifierMap[name];
+        return true;
+    }
+
+    template.__encodeHTML = encodeHTML;
+    template.__compress = compress;
+    template.__handelError = handelError;
+    template.__compile = compile;
+    template.version = '0.7.1';
+    return template;
+}));

Some files were not shown because too many files changed in this diff