Browse Source

Merge branch 'develop' of http://52.130.252.100:10000/TEAMMODEL/TEAMModelOS into develop

XW 2 years ago
parent
commit
137b876f80

+ 10 - 0
TEAMModelOS/ClientApp/src/common/BaseLayout.vue

@@ -587,6 +587,16 @@ export default {
               permission: 'research-read|research-upd',
               menuName: 'ResearchMgt',
               isShow: this.isOpenLessonRecord
+            },
+            {
+              icon: 'iconfont icon-data-count',
+              name: this.$t('system.menu.cusVideoMgt'),
+              router: '/home/ResearchMgtOld',
+              tag: '',
+              role: 'admin',
+              permission: 'research-read|research-upd',
+              menuName: 'ResearchMgtOld',
+              isShow: this.isGlobalSite
             }
           ]
         },

+ 38 - 3
TEAMModelOS/ClientApp/src/components/evaluation/ExerciseList.vue

@@ -33,7 +33,7 @@
           </div>
         </div>
         <div class="exercise-item-children" v-if="item.children.length">
-          <BaseChild :children="item.children" :isShowAnalysis="isShowAnalysis" :analysisJson="getChildAnalysisJson(item)" :optionRate="getChildOptionRate(item)" inBank></BaseChild>
+          <BaseChild :parentIndex="index" :children="item.children" :isShowAnalysis="isShowAnalysis" :analysisJson="getChildAnalysisJson(item)" :optionRate="getChildOptionRate(item)" inBank></BaseChild>
         </div>
         <transition name="slide" v-if="item.type !== 'compose'">
           <div v-if="collapseList.includes(exerciseList.indexOf(item))" class="toggle-area">
@@ -102,6 +102,11 @@
                   </br>
                   <OptionsTable v-if="item.type === 'single' || item.type === 'multiple' || item.type === 'judge'" :options="item.option.map(i => i.code)" :optionRate="optionRate[index]" :answer="item.answer"></OptionsTable>
                   </br>
+                  <Row>
+                    <Col span="24">
+                    <BaseTestSingleScatter :ids="'singleScatter' + index" :scatterData="scatterData" :currentIndex="index > 8 ? '' + (index + 1) : '0' + (index + 1)"></BaseTestSingleScatter>
+                    </Col>
+                  </Row>
                   <Row>
                     <Col span="12" v-if="item.type === 'single' || item.type === 'multiple' || item.type === 'judge'">
                     <BaseRateLine :ids="'R1R6' + index" :echartsData="getOptionLineData(item,index)"></BaseRateLine>
@@ -110,7 +115,6 @@
                     <BaseLine :ids="'rateLine' + index" :echartsData="analysisJson[index]"></BaseLine>
                     </Col>
                   </Row>
-
                 </div>
               </div>
             </div>
@@ -143,8 +147,9 @@ import AnalysisItemTable from '@/components/evaluation/AnalysisItemTable'
 import OptionsTable from '@/components/evaluation/OptionsTable'
 import BaseLine from '@/components/student-analysis/total/BaseLine.vue'
 import BaseRateLine from '@/components/student-analysis/total/BaseRateLine.vue'
+import BaseTestSingleScatter from '@/components/student-analysis/total/BaseTestSingleScatter.vue'
 export default {
-  components: { AnalysisItemTable, OptionsTable, BaseRateLine, BaseLine },
+  components: { AnalysisItemTable, OptionsTable, BaseRateLine, BaseLine, BaseTestSingleScatter },
   props: {
     propsList: {
       type: Array,
@@ -215,13 +220,39 @@ export default {
       selectList: [],
       originData: [],
       exerciseList: [],
+      scatterData: []
     };
   },
   created() {
     this.pageSize = this.isAnalysis ? 999 : 5
     this.pageChange(1)
+    this.getScatterData()
   },
   methods: {
+    getScatterData() {
+      let analysisJson = JSON.parse(JSON.stringify(this.getAnalysisJson))
+      let curSubjectIndex = analysisJson.subjects.map(i => i.name).indexOf(this.$store.state.totalAnalysis
+        .currentSubject)
+      let result = []
+      analysisJson.paper[curSubjectIndex].value.forEach((exercise, exerciseIndex) => {
+        let obj = {}
+        analysisJson.paperKey.forEach((key, index) => {
+          obj[key] = exercise[index]
+        })
+        result.push(obj)
+      })
+      let arr = result
+      let newArr = []
+      arr.forEach(item => {
+        let arr2 = []
+        arr2.push((+item.X).toFixed(2))
+        arr2.push((item.Y * 100).toFixed(2))
+        arr2.push(item.type)
+        arr2.push(item.id)
+        newArr.push(arr2)
+      })
+      this.scatterData = newArr
+    },
     /* 补救资源点击事件 */
     onRepairLinkClick(link) {
       window.open(/^(http:|https:)/i.test(link.blobUrl) ? link.blobUrl : "http://" + link.blobUrl)
@@ -400,6 +431,10 @@ export default {
     this.selectList = this.selQue
   },
   computed: {
+    // 获取最新试题分析模块数据
+    getAnalysisJson() {
+      return this.$store.state.totalAnalysis.analysisJson
+    },
     curScope() {
       return this.filterOrigin === this.$store.state.userInfo.schoolCode ?
         "school" :

+ 286 - 0
TEAMModelOS/ClientApp/src/components/student-analysis/total/BaseTestSingleScatter.vue

@@ -0,0 +1,286 @@
+<template>
+  <div :id="ids" class="singleTestScatter"></div>
+</template>
+
+<script>
+export default {
+  name: 'testScatter',
+  props: ['ids', 'currentIndex', 'scatterData'],
+  data() {
+    return {
+      originArr: [],
+      dataArr: [],
+      activeItemIndex: 0,
+      exersicesType: this.$GLOBAL.EXERCISE_TYPES(),
+    }
+  },
+  created() {
+
+  },
+
+  methods: {
+    drawLine(data) {
+      // 基于准备好的dom,初始化echarts实例
+      let myScatter = this.$echarts.init(document.getElementById(this.ids), 'chalk')
+      let _this = this
+      console.log('试题落点数据', data)
+
+      // 指定图表的配置项和数据
+      var option = {
+        tooltip: {
+          trigger: 'item',
+          showDelay: 0,
+          axisPointer: {
+            show: true,
+            lineStyle: {
+              type: 'dashed',
+              width: 1
+            }
+          },
+          textStyle: {
+            height: '160px'
+          },
+          formatter: function (params) {
+            const item = params
+            return `${_this.$t('totalAnalysis.ta_table_text1')}:${item.data[3]}
+                        <br/>${_this.$t('totalAnalysis.ta_table_text2')}:${that.exersicesType[item.data[2]]}
+                        <br/>${_this.$t('totalAnalysis.ta_chart_text2')}:${item.data[1]}%
+                        <br/>${_this.$t('totalAnalysis.ta_chart_text3')}:${item.data[0]}
+                       `
+          }
+        },
+        legend: {
+          data: [_this.$t('totalAnalysis.ta_chart_text1')]
+        },
+        title: {
+          text: this.$t('totalAnalysis.ta_title1'),
+          textStyle: {
+            align: 'center',
+            color: '#333',
+            fontSize: 14
+          },
+        },
+        grid: {
+          height: 400,
+          left: '5%',
+          right: '5%',
+          bottom: '5%'
+        },
+        xAxis: [{
+          type: 'value',
+          splitNumber: 2,
+          min: 0,
+          max: 1,
+          name: _this.$t('totalAnalysis.ta_chart_text3'),
+          nameTextStyle: {
+            color: '#757575'
+          },
+          scale: false,
+          splitLine: {
+            show: true,
+            lineStyle: {
+              color: '#595959'
+            }
+          }
+        }],
+        yAxis: [{
+          type: 'value',
+          name: _this.$t('totalAnalysis.ta_chart_text2'),
+          nameTextStyle: {
+            color: '#757575'
+          },
+          max: 100,
+          min: 0,
+          splitLine: {
+            show: false,
+            lineStyle: {
+              color: '#595959'
+            }
+          },
+          interval: 50,
+          axisLabel: {
+            show: true,
+            formatter: function (value) {
+              let val = []
+              if (value !== 25) {
+                val.push(value + '%')
+              }
+              return val
+            }
+          },
+          spiltArea: {
+            show: true
+          }
+        }],
+        series: [{
+          name: _this.$t('totalAnalysis.ta_chart_text1'),
+          type: 'scatter',
+          data: data,
+          symbolSize: 20,
+          emphasis: {
+            itemStyle: {
+              color: '#ff99cc'
+            }
+          },
+          itemStyle: {
+            color: function (params) {
+              var key = params.dataIndex
+              if (key === _this.activeItemIndex) {
+                return '#ff99cc'
+              } else {
+                return '#ccc'
+              }
+            },
+            width: 20
+          },
+          markLine: {
+            silent: true,
+            animation: false,
+            data: [{
+              yAxis: 50
+            }, {
+              yAxis: 100
+            }],
+            label: {
+              color: '#757575',
+              formatter: '{c}%'
+            },
+            lineStyle: {
+              color: '#595959',
+              type: 'solid'
+            }
+          },
+          markArea: {
+            silent: true,
+            data: [
+              [{
+                xAxis: '0.5',
+                yAxis: '50',
+                itemStyle: {
+                  color: 'rgba(128,28,128,0)'
+                },
+                label: {
+                  show: true,
+                  position: ['90%', '10%'],
+                  color: '#008955',
+                  fontSize: 20,
+                  formatter: 'B'
+                }
+              }, {
+                xAxis: '0',
+                yAxis: '0'
+              }],
+              [{
+                xAxis: '1',
+                yAxis: '50',
+                itemStyle: {
+                  color: 'rgba(90,90,90,.1)'
+
+                },
+                label: {
+                  show: true,
+                  position: ['5%', '10%'],
+                  color: '#008955',
+                  fontSize: 20,
+                  formatter: "B'"
+                }
+
+              }, {
+                xAxis: '0.5',
+                yAxis: '0'
+              }],
+              [{
+                xAxis: '0.5',
+                yAxis: '100',
+                itemStyle: {
+                  color: 'rgba(90,90,90,.1)'
+
+                },
+                label: {
+                  show: true,
+                  position: ['90%', '80%'],
+                  color: '#008955',
+                  fontSize: 20,
+                  formatter: 'A'
+                }
+
+              }, {
+                xAxis: '0',
+                yAxis: '50'
+              }],
+              [{
+                xAxis: '1',
+                yAxis: '100',
+                itemStyle: {
+                  color: 'rgba(128,128,128,0)'
+
+                },
+                label: {
+                  show: true,
+                  position: ['5%', '40%'],
+                  color: '#008955',
+                  fontSize: 20,
+                  formatter: "A'"
+                }
+              }, {
+                xAxis: '0.5',
+                yAxis: '0'
+              }]
+            ]
+          }
+        }]
+      }
+
+      // 绘制图表
+      myScatter.setOption(option)
+      window.addEventListener('resize', function () {
+        myScatter.resize()
+      })
+
+      let that = this
+      myScatter.on('click', function (item) {
+        that.activeItemIndex = item.dataIndex
+        that.$emit('handleIndexClick', item.dataIndex + 1)
+        myScatter.setOption(option)
+      })
+    }
+  },
+  watch: {
+    scatterData: {
+      deep: true,
+      immediate: true,
+      handler(val) {
+        if (val) {
+          this.$nextTick(() => {
+            this.drawLine(val)
+          })
+        }
+      }
+    },
+    currentIndex: {
+      deep: true,
+      immediate: true,
+      handler(val) {
+        console.error('currentIndex', val)
+        if (val && this.scatterData) {
+          this.$nextTick(() => {
+            this.activeItemIndex = +val - 1
+            this.drawLine(this.scatterData)
+          })
+        }
+      }
+    }
+  }
+}
+</script>
+
+<!-- Add "scoped" attribute to limit CSS to this component only -->
+<style scoped>
+.singleTestScatter {
+  width: 100%;
+  height: 500px;
+  margin: 0 auto;
+  display: block;
+  margin-top: 20px;
+}
+</style>

+ 421 - 380
TEAMModelOS/ClientApp/src/view/evaluation/components/BaseChild.vue

@@ -1,400 +1,441 @@
 <template>
-	<div class="child-wrap" ref="childRef">
-		<div class="child-item" v-for="(item,index) in children" :key="index"  @click.stop="onQuestionToggle(index, item.id, $event)">
-			<!-- 工具栏部分 -->
-			<div class="child-tools-wrap">
-				<div class="child-tools-t flex-row-center"  v-if="isShowScore"
-					@click.stop="handleChildEdit(item,index)">
-					{{$t('evaluation.editItem')}}{{$t('evaluation.child')}}
-				</div>
-				<div class="child-tools-t flex-row-center"  v-if="canFix"
-					@click.stop="handleFixChild(item,index)">
-					{{ $t('evaluation.fixTip1') }}
-				</div>
-			</div>
-			<div class="child-item-question">
-				<span class="child-item-question-order">({{ index + 1 }})</span>
-				<p class="child-item-question-content" v-html="item.question"></p>
-			</div>
-			<!-- 选项部分 -->
-			<div v-for="(option,optionIndex) in item.option" :key="optionIndex" class="child-item-option"
-				style="pointer-events:none">
-				<div>
-					<div class="child-item-option-order">{{String.fromCharCode(64 + parseInt(optionIndex+1))}} : </div>
-					<div class="child-item-option-text" v-html="option.value"></div>
-				</div>
-			</div>
-			<div class="item-btn-toggle">
-				<template v-if="!inBank">
-					<InputNumber  :min="0" v-model="item.score"  v-if="isShowScore" :step="0.5"
-						style="display: inline-block ;width: 60px;margin-right: 10px;height: 30px;" @click.stop>
-					</InputNumber>
-					<span v-if="!isShowScore" style="margin-right: 10px;color: #2db7f5;font-weight: bold;">{{ item.score }}</span>
-					<span style="margin-right: 20px;">{{$t('evaluation.paperList.score')}}</span>
-				</template>
-				<Icon :type="collapseList.includes(children.indexOf(item)) ? 'ios-arrow-dropup' : 'ios-arrow-dropdown'"/>
-			</div>
-			<transition name="slide">
-				<div v-if="collapseList.includes(children.indexOf(item))" class="toggle-area">
-					<!-- 答案展示部分 -->
-					<div class="item-explain">
-						<span class="explain-title">【{{$t('evaluation.answer')}}】</span>
-						<div class="item-explain-details">
-							<!-- 问答题答案 -->
-							<div v-if="item.type === 'subjective' || item.type === 'complete'">
-								<span v-for="(answer,index) in item.answer" :key="index"
-									v-html="item.answer && item.answer.length ? answer : $t('utils.noData')"></span>
-							</div>
-							<!-- 问答题答案 -->
-							<div v-else-if="item.type === 'judge'">
-								<span>{{ item.answer && item.answer.length ? (item.answer[0] === 'A' ? $t('evaluation.isTrue') : $t('evaluation.isFalse')) : $t('evaluation.answer') }}</span>
-							</div>
-							<!-- 其余题型答案 -->
-							<div v-else>
-								<span :class="[ item.type === 'complete' ? 'item-answer-item':'']"
-									v-for="(answer,index) in item.answer" :key="index" v-html="answer"></span>
-							</div>
-						</div>
-					</div>
-					<!-- 解析部分 -->
-					<div class="item-explain">
-						<span class="explain-title">【{{$t('evaluation.explain')}}】</span>
-						<div class="item-explain-details">
-							<span v-html="item.explain || $t('utils.noData')"></span>
-						</div>
-					</div>
-					<!-- 知识点部分 -->
-					<div class="item-explain">
-						<span class="explain-title">【{{$t('evaluation.knowledgePoints')}}】</span>
-						<div class="item-explain-details">
-							<span v-if="!item.knowledge || !item.knowledge.length">{{ $t('utils.noData') }}</span>
-							<div v-else>
-								<span v-for="(point,index) in item.knowledge" :key="index" class="item-point-tag">
-									<span>{{ point }}</span>
-								</span>
-							</div>
-						</div>
-					</div>
-					<!-- 认知层次部分 -->
-					<div class="item-explain">
-						<span class="explain-title" :style="{ color:isShowAnalysis ? '#099209' : '#10abe7' }">【{{$t('evaluation.field')}}】</span>
-						<div class="item-explain-details">
-							<span>{{ exersicesField[item.field - 1] }}</span>
-						</div>
-					</div>
-					<!-- 补救资源部分 -->
-					<div class="item-explain">
-						<span class="explain-title">【{{ $t('evaluation.newExercise.repair') }}】</span>
-						<div class="item-explain-details">
-							<div v-if="item.repair && item.repair.length" style="display: flex;flex-wrap: wrap;">
-								<div class="repair-item" v-for="(link,index) in item.repair">
-									<img :src="$tools.getFileThum(link.type,link.name)" width="20"/>
-									<span class="repair-item-link" @click.stop="onRepairLinkClick(link)">{{ link.name }}</span>
-								</div>
-							</div>
-							<span v-else>{{ $t('utils.noData') }}</span>
-						</div>
-					</div>
-					<div class="item-explain" v-if="isShowAnalysis">
-						<span class="explain-title">【{{ $t('totalAnalysis.showAnalysis') }}】</span>
-						<div class="item-explain-details">
-							<AnalysisItemTable :analysisJson="analysisJson[index]"></AnalysisItemTable>
-							</br>
-							<OptionsTable v-if="item.type === 'single' || item.type === 'multiple' || item.type === 'judge'" 
-							:options="item.option.map(i => i.code)" :optionRate="optionRate[index]" :answer="item.answer"></OptionsTable>
-							</br>
-							<Row>
-							 <Col span="12" v-if="item.type === 'single' || item.type === 'multiple' || item.type === 'judge'">
-								<BaseRateLine :ids="'cR1' + item.id" :echartsData="getOptionLineData(item,index)"></BaseRateLine>
-							 </Col>
-							 <Col span="12">
-								<BaseLine :ids="'cr' + item.id" :echartsData="analysisJson[index]"></BaseLine>
-							 </Col>
-							</Row>
-						</div>
-					</div>
-				</div>
-			</transition>
-		</div>
-		
-		<!-- 添加子题弹窗 -->
-		<Modal v-model="editChildModal" width="1080" class="edit-exercise-modal" :styles="{top: '20px'}" :mask-closable="false">
-			<div class="modal-header" slot="header">{{$t('evaluation.exerciseList.editChild')}}</div>
-			<!-- <BaseCreateChild v-if="editChildModal" @addFinish='onEditChildFinish' refId="childListEdit" :editItem="curItem" ref="createChildRef"></BaseCreateChild> -->
-			<BaseEditExercise v-if="editChildModal" :exerciseItem="curItem" @onEditSuccess="onEditChildFinish" refId="paperEdit"
-				ref="createChildRef"  hidePeriod></BaseEditExercise>
-			<div slot="footer">
-				<Button type="success" @click="onSaveChild">{{$t('evaluation.confirm')}}</Button>
-			</div>
-		</Modal>
-		
-		<!-- 补充解析和补救资源弹窗 -->
-		<Modal v-model="addExplainModal" :styles="{top: '20px'}" width="1000px" :title="$t('evaluation.fixTip1')">
-			<BaseFixExamItem ref="fixRef" :fixItem="curItem" @onFixFinish="onFixFinish"></BaseFixExamItem>
-			<div slot="footer">
-				<Button @click="addExplainModal = false">{{$t('evaluation.cancel')}}</Button>
-				<Button type="success" :loading="editLoading" @click="doSaveFixItem">{{$t('evaluation.confirm')}}</Button>
-			</div>
-		</Modal>
-	</div>
+  <div class="child-wrap" ref="childRef">
+    <div class="child-item" v-for="(item,index) in children" :key="index" @click.stop="onQuestionToggle(index, item.id, $event)">
+      <!-- 工具栏部分 -->
+      <div class="child-tools-wrap">
+        <div class="child-tools-t flex-row-center" v-if="isShowScore" @click.stop="handleChildEdit(item,index)">
+          {{$t('evaluation.editItem')}}{{$t('evaluation.child')}}
+        </div>
+        <div class="child-tools-t flex-row-center" v-if="canFix" @click.stop="handleFixChild(item,index)">
+          {{ $t('evaluation.fixTip1') }}
+        </div>
+      </div>
+      <div class="child-item-question">
+        <span class="child-item-question-order">({{ index + 1 }})</span>
+        <p class="child-item-question-content" v-html="item.question"></p>
+      </div>
+      <!-- 选项部分 -->
+      <div v-for="(option,optionIndex) in item.option" :key="optionIndex" class="child-item-option" style="pointer-events:none">
+        <div>
+          <div class="child-item-option-order">{{String.fromCharCode(64 + parseInt(optionIndex+1))}} : </div>
+          <div class="child-item-option-text" v-html="option.value"></div>
+        </div>
+      </div>
+      <div class="item-btn-toggle">
+        <template v-if="!inBank">
+          <InputNumber :min="0" v-model="item.score" v-if="isShowScore" :step="0.5" style="display: inline-block ;width: 60px;margin-right: 10px;height: 30px;" @click.stop>
+          </InputNumber>
+          <span v-if="!isShowScore" style="margin-right: 10px;color: #2db7f5;font-weight: bold;">{{ item.score }}</span>
+          <span style="margin-right: 20px;">{{$t('evaluation.paperList.score')}}</span>
+        </template>
+        <Icon :type="collapseList.includes(children.indexOf(item)) ? 'ios-arrow-dropup' : 'ios-arrow-dropdown'" />
+      </div>
+      <transition name="slide">
+        <div v-if="collapseList.includes(children.indexOf(item))" class="toggle-area">
+          <!-- 答案展示部分 -->
+          <div class="item-explain">
+            <span class="explain-title">【{{$t('evaluation.answer')}}】</span>
+            <div class="item-explain-details">
+              <!-- 问答题答案 -->
+              <div v-if="item.type === 'subjective' || item.type === 'complete'">
+                <span v-for="(answer,index) in item.answer" :key="index" v-html="item.answer && item.answer.length ? answer : $t('utils.noData')"></span>
+              </div>
+              <!-- 问答题答案 -->
+              <div v-else-if="item.type === 'judge'">
+                <span>{{ item.answer && item.answer.length ? (item.answer[0] === 'A' ? $t('evaluation.isTrue') : $t('evaluation.isFalse')) : $t('evaluation.answer') }}</span>
+              </div>
+              <!-- 其余题型答案 -->
+              <div v-else>
+                <span :class="[ item.type === 'complete' ? 'item-answer-item':'']" v-for="(answer,index) in item.answer" :key="index" v-html="answer"></span>
+              </div>
+            </div>
+          </div>
+          <!-- 解析部分 -->
+          <div class="item-explain">
+            <span class="explain-title">【{{$t('evaluation.explain')}}】</span>
+            <div class="item-explain-details">
+              <span v-html="item.explain || $t('utils.noData')"></span>
+            </div>
+          </div>
+          <!-- 知识点部分 -->
+          <div class="item-explain">
+            <span class="explain-title">【{{$t('evaluation.knowledgePoints')}}】</span>
+            <div class="item-explain-details">
+              <span v-if="!item.knowledge || !item.knowledge.length">{{ $t('utils.noData') }}</span>
+              <div v-else>
+                <span v-for="(point,index) in item.knowledge" :key="index" class="item-point-tag">
+                  <span>{{ point }}</span>
+                </span>
+              </div>
+            </div>
+          </div>
+          <!-- 认知层次部分 -->
+          <div class="item-explain">
+            <span class="explain-title" :style="{ color:isShowAnalysis ? '#099209' : '#10abe7' }">【{{$t('evaluation.field')}}】</span>
+            <div class="item-explain-details">
+              <span>{{ exersicesField[item.field - 1] }}</span>
+            </div>
+          </div>
+          <!-- 补救资源部分 -->
+          <div class="item-explain">
+            <span class="explain-title">【{{ $t('evaluation.newExercise.repair') }}】</span>
+            <div class="item-explain-details">
+              <div v-if="item.repair && item.repair.length" style="display: flex;flex-wrap: wrap;">
+                <div class="repair-item" v-for="(link,index) in item.repair">
+                  <img :src="$tools.getFileThum(link.type,link.name)" width="20" />
+                  <span class="repair-item-link" @click.stop="onRepairLinkClick(link)">{{ link.name }}</span>
+                </div>
+              </div>
+              <span v-else>{{ $t('utils.noData') }}</span>
+            </div>
+          </div>
+          <div class="item-explain" v-if="isShowAnalysis">
+            <span class="explain-title">【{{ $t('totalAnalysis.showAnalysis') }}】</span>
+            <div class="item-explain-details">
+              <AnalysisItemTable :analysisJson="analysisJson[index]"></AnalysisItemTable>
+              </br>
+              <OptionsTable v-if="item.type === 'single' || item.type === 'multiple' || item.type === 'judge'" :options="item.option.map(i => i.code)" :optionRate="optionRate[index]" :answer="item.answer"></OptionsTable>
+              </br>
+              <Row>
+                <Col span="12" v-if="item.type === 'single' || item.type === 'multiple' || item.type === 'judge'">
+                <BaseRateLine :ids="'cR1' + item.id" :echartsData="getOptionLineData(item,index)"></BaseRateLine>
+                </Col>
+                <Col span="12">
+                <BaseLine :ids="'cr' + item.id" :echartsData="analysisJson[index]"></BaseLine>
+                </Col>
+              </Row>
+              <Row>
+                <Col span="24">
+                <BaseTestSingleScatter :ids="'singleChildScatter' + item.id" :scatterData="scatterData" :currentIndex="childIndex(index)"></BaseTestSingleScatter>
+                </Col>
+              </Row>
+            </div>
+          </div>
+        </div>
+      </transition>
+    </div>
+
+    <!-- 添加子题弹窗 -->
+    <Modal v-model="editChildModal" width="1080" class="edit-exercise-modal" :styles="{top: '20px'}" :mask-closable="false">
+      <div class="modal-header" slot="header">{{$t('evaluation.exerciseList.editChild')}}</div>
+      <!-- <BaseCreateChild v-if="editChildModal" @addFinish='onEditChildFinish' refId="childListEdit" :editItem="curItem" ref="createChildRef"></BaseCreateChild> -->
+      <BaseEditExercise v-if="editChildModal" :exerciseItem="curItem" @onEditSuccess="onEditChildFinish" refId="paperEdit" ref="createChildRef" hidePeriod></BaseEditExercise>
+      <div slot="footer">
+        <Button type="success" @click="onSaveChild">{{$t('evaluation.confirm')}}</Button>
+      </div>
+    </Modal>
+
+    <!-- 补充解析和补救资源弹窗 -->
+    <Modal v-model="addExplainModal" :styles="{top: '20px'}" width="1000px" :title="$t('evaluation.fixTip1')">
+      <BaseFixExamItem ref="fixRef" :fixItem="curItem" @onFixFinish="onFixFinish"></BaseFixExamItem>
+      <div slot="footer">
+        <Button @click="addExplainModal = false">{{$t('evaluation.cancel')}}</Button>
+        <Button type="success" :loading="editLoading" @click="doSaveFixItem">{{$t('evaluation.confirm')}}</Button>
+      </div>
+    </Modal>
+  </div>
 </template>
 <script>
-	import '@/utils/Math.uuid'
-	import AnalysisItemTable from '@/components/evaluation/AnalysisItemTable'
-	import OptionsTable from '@/components/evaluation/OptionsTable'
-	import BaseLine from '@/components/student-analysis/total/BaseLine.vue'
-	import BaseRateLine from '@/components/student-analysis/total/BaseRateLine.vue'
-	export default {
-		name: 'BaseChild',
-		components: { AnalysisItemTable,OptionsTable,BaseRateLine,BaseLine },
-		props: {
-			children: {
-				type: Array,
-				default: []
-			},
-			totalScore: {
-				type: Number,
-				default: 0
-			},
-			analysisJson:{
-				type:Array,
-				default:() => {
-					return []
-				}
-			},
-			optionRate:{
-				type:Array,
-				default:() => {
-					return []
-				}
-			},
-			isShowScore: {
-				type: Boolean,
-				default: false
-			},
-			inBank: {
-				type: Boolean,
-				default: false
-			},
-			isShowAnalysis: {
-				type: Boolean,
-				default: false
-			},
-			canFix: {
-				type: Boolean,
-				default: false
-			}
-		},
-		data() {
-			return {
-				editLoading:false,
-				addExplainModal:false,
-				curIndex: null,
-				curItem: {},
-				editChildModal:false,
-				collapseList:[],
-				surPlusScore: 0,
-				exersicesField: this.$GLOBAL.EXERCISE_LEVELS(),
-			}
-		},
-		created() {
-			if (this.children && this.children.length) {
-				this.children.forEach(i => {
-					if (!i.score) {
-						i.score = 0
-					}
-					this.surPlusScore = this.totalScore - i.score
-				})
-			}
+import '@/utils/Math.uuid'
+import AnalysisItemTable from '@/components/evaluation/AnalysisItemTable'
+import OptionsTable from '@/components/evaluation/OptionsTable'
+import BaseLine from '@/components/student-analysis/total/BaseLine.vue'
+import BaseTestSingleScatter from '@/components/student-analysis/total/BaseTestSingleScatter.vue'
+import BaseRateLine from '@/components/student-analysis/total/BaseRateLine.vue'
+export default {
+  name: 'BaseChild',
+  components: { AnalysisItemTable, OptionsTable, BaseRateLine, BaseLine, BaseTestSingleScatter },
+  props: {
+    children: {
+      type: Array,
+      default: []
+    },
+    totalScore: {
+      type: Number,
+      default: 0
+    },
+    parentIndex: {
+      type: Number,
+      default: 0
+    },
+    analysisJson: {
+      type: Array,
+      default: () => {
+        return []
+      }
+    },
+    optionRate: {
+      type: Array,
+      default: () => {
+        return []
+      }
+    },
+    isShowScore: {
+      type: Boolean,
+      default: false
+    },
+    inBank: {
+      type: Boolean,
+      default: false
+    },
+    isShowAnalysis: {
+      type: Boolean,
+      default: false
+    },
+    canFix: {
+      type: Boolean,
+      default: false
+    }
+  },
+  data() {
+    return {
+      editLoading: false,
+      addExplainModal: false,
+      curIndex: null,
+      curItem: {},
+      editChildModal: false,
+      collapseList: [],
+      surPlusScore: 0,
+      exersicesField: this.$GLOBAL.EXERCISE_LEVELS(),
+      scatterData: []
+    }
+  },
+  created() {
+    if (this.children && this.children.length) {
+      this.children.forEach(i => {
+        if (!i.score) {
+          i.score = 0
+        }
+        this.surPlusScore = this.totalScore - i.score
+      })
+    }
+    this.getScatterData()
+
+  },
+  methods: {
+    getScatterData() {
+      let analysisJson = JSON.parse(JSON.stringify(this.getAnalysisJson))
+      let curSubjectIndex = analysisJson.subjects.map(i => i.name).indexOf(this.$store.state.totalAnalysis
+        .currentSubject)
+      let result = []
+      analysisJson.paper[curSubjectIndex].value.forEach((exercise, exerciseIndex) => {
+        let obj = {}
+        analysisJson.paperKey.forEach((key, index) => {
+          obj[key] = exercise[index]
+        })
+        result.push(obj)
+      })
+      let arr = result
+      let newArr = []
+      arr.forEach(item => {
+        let arr2 = []
+        arr2.push((+item.X).toFixed(2))
+        arr2.push((item.Y * 100).toFixed(2))
+        arr2.push(item.type)
+        arr2.push(item.id)
+        newArr.push(arr2)
+      })
+      this.scatterData = newArr
+    },
+    onSaveChild() {
+      this.$refs.createChildRef.getContent(this.curItem.type)
+    },
+    handleChildEdit(item, index) {
+      this.curItem = item
+      this.curIndex = index
+      this.editChildModal = true
+    },
+    handleFixChild(item, index) {
+      this.curItem = item
+      this.curIndex = index
+      this.addExplainModal = true
+    },
+    /* 保存补充解析的题目 */
+    doSaveFixItem() {
+      this.editLoading = true
+      this.$refs.fixRef.doSave()
+    },
+    /* FIX完成 */
+    onFixFinish(newItem) {
+      // this.exerciseList.splice(this.currentExerciseIndex, 1, newItem)
+      // this.curTypeItems.splice(this.curIndex, 1, newItem)
+      // this.$emit('dataUpdate', this.exerciseList)
+      this.addExplainModal = false
+      this.editLoading = false
+      this.$emit('onEditChildFinish', newItem)
+      this.$Message.success(this.$t('evaluation.editSuc'))
+    },
+    /* 补救资源点击事件 */
+    onRepairLinkClick(link) {
+      window.open(/^(http:|https:)/i.test(link.blobUrl) ? link.blobUrl : "http://" + link.blobUrl)
+    },
+    onEditChildFinish(item) {
+      console.log(item)
+      this.editChildModal = false
+      this.$emit('onEditChildFinish', item)
+    },
+    getOptionLineData(item, index) {
+      let result = []
+      console.log(this.optionRate)
+      let n = this.optionRate[index]
+      let total = this.$store.state.totalAnalysis.analysisJson.all.total // 取总人数
+      let phCount = Math.floor(total * 0.27) //取高分组人数
+      let plCount = Math.ceil(total * 0.27) //取低分组人数
+      item.option.map(i => i.code).forEach(key => {
+        result.push({
+          option: key,
+          rate: n.record[key] ? ((n.record[key] / total) * 100).toFixed(1) : 0,
+          PH: n.ph[key] ? ((n.ph[key] / phCount) * 100).toFixed(1) : 0,
+          PL: n.pl[key] ? ((n.pl[key] / plCount) * 100).toFixed(1) : 0,
+        })
+      })
+      console.log(result)
+      return result
+    },
+
+    onQuestionToggle(index, id, e) {
+      let curClassName = e.target.className;
+      if (
+        curClassName === "item-tools" ||
+        curClassName === "richText-video" ||
+        curClassName === "richText-audio"
+      )
+        return;
+      e.stopPropagation();
+      let listIndex = this.collapseList.indexOf(index);
+      if (listIndex > -1) {
+        this.collapseList.splice(listIndex, 1);
+      } else {
+        this.collapseList.push(index);
+        let exerciseItemDom = e.path.filter(
+          (i) => i.className === "exercise-item"
+        );
+        // if (exerciseItemDom.length) {
+        // 	this.pageScrollTo(exerciseItemDom[0].offsetTop + 240);
+        // }
+      }
+
+      this.$emit("toggleChange", this.collapseList);
+    },
 
-		},
-		methods: {
-			onSaveChild(){
-				this.$refs.createChildRef.getContent(this.curItem.type)
-			},
-			handleChildEdit(item,index){
-				this.curItem = item
-				this.curIndex = index
-				this.editChildModal = true
-			},
-			handleFixChild(item,index){
-				this.curItem = item
-				this.curIndex = index
-				this.addExplainModal = true
-			},
-			/* 保存补充解析的题目 */
-			doSaveFixItem(){
-				this.editLoading = true
-				this.$refs.fixRef.doSave()
-			},
-			/* FIX完成 */
-			onFixFinish(newItem){
-				// this.exerciseList.splice(this.currentExerciseIndex, 1, newItem)
-				// this.curTypeItems.splice(this.curIndex, 1, newItem)
-				// this.$emit('dataUpdate', this.exerciseList)
-				this.addExplainModal = false
-				this.editLoading = false
-				this.$emit('onEditChildFinish', newItem)
-				this.$Message.success(this.$t('evaluation.editSuc'))
-			},
-			/* 补救资源点击事件 */
-			onRepairLinkClick(link){
-				window.open(/^(http:|https:)/i.test(link.blobUrl) ? link.blobUrl : "http://" + link.blobUrl)
-			},
-			onEditChildFinish(item) {
-				console.log(item)
-				this.editChildModal = false
-				this.$emit('onEditChildFinish', item)
-			},
-			getOptionLineData(item,index){
-				let result = []
-				console.log(this.optionRate)
-				let n = this.optionRate[index]
-				let total = this.$store.state.totalAnalysis.analysisJson.all.total // 取总人数
-				let phCount = Math.floor(total * 0.27) //取高分组人数
-				let plCount = Math.ceil(total * 0.27) //取低分组人数
-				item.option.map(i => i.code).forEach(key => {
-					result.push({
-						option:key,
-						rate:n.record[key] ? ((n.record[key] / total) * 100).toFixed(1) : 0,
-						PH: n.ph[key] ? ((n.ph[key] / phCount) * 100).toFixed(1) : 0,
-						PL: n.pl[key] ? ((n.pl[key] / plCount) * 100).toFixed(1) : 0,
-					})
-				})
-				console.log(result)
-				return result
-			},
-			
-			onQuestionToggle(index, id, e) {
-				let curClassName = e.target.className;
-				if (
-					curClassName === "item-tools" ||
-					curClassName === "richText-video" ||
-					curClassName === "richText-audio"
-				)
-					return;
-				e.stopPropagation();
-				let listIndex = this.collapseList.indexOf(index);
-				if (listIndex > -1) {
-					this.collapseList.splice(listIndex, 1);
-				} else {
-					this.collapseList.push(index);
-					let exerciseItemDom = e.path.filter(
-						(i) => i.className === "exercise-item"
-					);
-					// if (exerciseItemDom.length) {
-					// 	this.pageScrollTo(exerciseItemDom[0].offsetTop + 240);
-					// }
-				}
-			
-				this.$emit("toggleChange", this.collapseList);
-			},
+  },
 
-		},
+  computed: {
+    // 获取最新试题分析模块数据
+    getAnalysisJson() {
+      return this.$store.state.totalAnalysis.analysisJson
+    },
+    childIndex() {
+      return index => {
+        let childIndex = this.parentIndex + index + 3
+        return childIndex > 9 ? '' + childIndex : '0' + childIndex
+      }
+    }
+  },
 
-		watch: {
-			children: {
-				handler(n) {
-					this.$nextTick(() => {
-						// this.$MathJax.MathQueue(this.$refs.childRef);
-					})
-				}
-			},
-			totalScore: {
-				handler(n) {
+  watch: {
+    children: {
+      handler(n) {
+        this.$nextTick(() => {
+          // this.$MathJax.MathQueue(this.$refs.childRef);
+        })
+      }
+    },
+    totalScore: {
+      handler(n) {
 
-				}
-			},
-		}
+      }
+    },
+  }
 
-	}
+}
 </script>
 
 <style lang="less" scoped>
-	@import "../../../components/evaluation/ExerciseList.less";
+@import "../../../components/evaluation/ExerciseList.less";
 </style>
 <style lang="less" scoped>
-	.child-wrap {
-		.child-item {
-			position: relative;
-			margin: 20px 10px 0 20px;
-			padding: 10px;
-			border: 1px solid transparent;
-			font-size: 14px;
-			
-			&:hover{
-				border: 1px solid #01b4ef;
-				.child-tools-wrap,.child-tools-t{
-					display: inline-flex;
-				}
-				
-			}
-			
-			.child-tools-wrap{
-				position: absolute;
-				right: -2px;
-				top: -30px;
-				height: 30px;
-				margin: 0;
-				padding: 0;
-				background: #11baa1;
-				display: none;
-			}
-			
-			.child-tools-t{
-				height: 100%;
-				padding: 0 15px;
-				float: left;
-				color: white;
-				cursor: pointer;
-				font-size: 14px;
-				
-				&:hover{
-					background-color: #4a5ae6;
-				}
-			}
-			
-			.item-btn-toggle {
-			  position: absolute;
-			  right: 20px;
-			  top: 5px !important;
-			 }
+.child-wrap {
+  .child-item {
+    position: relative;
+    margin: 20px 10px 0 20px;
+    padding: 10px;
+    border: 1px solid transparent;
+    font-size: 14px;
+
+    &:hover {
+      border: 1px solid #01b4ef;
+      .child-tools-wrap,
+      .child-tools-t {
+        display: inline-flex;
+      }
+    }
+
+    .child-tools-wrap {
+      position: absolute;
+      right: -2px;
+      top: -30px;
+      height: 30px;
+      margin: 0;
+      padding: 0;
+      background: #11baa1;
+      display: none;
+    }
+
+    .child-tools-t {
+      height: 100%;
+      padding: 0 15px;
+      float: left;
+      color: white;
+      cursor: pointer;
+      font-size: 14px;
+
+      &:hover {
+        background-color: #4a5ae6;
+      }
+    }
+
+    .item-btn-toggle {
+      position: absolute;
+      right: 20px;
+      top: 5px !important;
+    }
 
-			&-question {
-				max-width: 85%;
-				// color:#01b087;
+    &-question {
+      max-width: 85%;
+      // color:#01b087;
 
-				&-order {
-					// color: #10abe7;
-					display: inline-block;
-					width: 20px;
-					vertical-align: middle;
-				}
+      &-order {
+        // color: #10abe7;
+        display: inline-block;
+        width: 20px;
+        vertical-align: middle;
+      }
 
-				&-content {
-					display: inline-block;
-					margin-left: 5px;
-					width: calc(90% - 20px);
-					vertical-align: text-top;
-				}
-			}
+      &-content {
+        display: inline-block;
+        margin-left: 5px;
+        width: calc(90% - 20px);
+        vertical-align: text-top;
+      }
+    }
 
-			&-option {
-				margin: 10px 5px;
-				margin-left: 20px;
+    &-option {
+      margin: 10px 5px;
+      margin-left: 20px;
 
-				&-order {
-					display: inline-block;
-					width: 25px;
-				}
+      &-order {
+        display: inline-block;
+        width: 25px;
+      }
 
-				&-text {
-					display: inline-block;
-					margin-left: 5px;
-					width: calc(90% - 25px);
-					vertical-align: text-top;
-				}
-			}
-		}
-	}
+      &-text {
+        display: inline-block;
+        margin-left: 5px;
+        width: calc(90% - 25px);
+        vertical-align: text-top;
+      }
+    }
+  }
+}
 </style>