TestAnalysis.vue 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421
  1. <template>
  2. <div class="scatter-container">
  3. <Row>
  4. <Col span="12">
  5. <span class="component-title">{{$t('totalAnalysis.ta_title1')}}</span>
  6. <BaseTestScatter @handleIndexClick="handleIndexClick" :scatterData="scatterData" :currentIndex="currentExerciseIndex"></BaseTestScatter>
  7. </Col>
  8. <Col span="12">
  9. <div class="scatter-statistics">
  10. <div class="scatter-table-line">
  11. <span>{{$t('totalAnalysis.ta_text1')}}</span>
  12. <span>{{$t('totalAnalysis.ta_text2')}}</span>
  13. <span>{{$t('totalAnalysis.ta_text3')}}</span>
  14. <span>{{$t('totalAnalysis.ta_text4')}}</span>
  15. </div>
  16. <Divider />
  17. <div class="scatter-table-line">
  18. <span>A</span>
  19. <span class="scatter-explain" :title="$t('totalAnalysis.ta_text6')">{{$t('totalAnalysis.ta_text6')}}</span>
  20. <span>{{A1List.length}}</span>
  21. <div class="index-box"><span v-for="(item,index) in A1List" :key="index" class="scatter-exercise-index" @click="handleIndexClick(item.id)">{{Number(item.id) > 9 ? item.id : '0' + item.id}}</span></div>
  22. </div>
  23. <Divider />
  24. <div class="scatter-table-line">
  25. <span>A-</span>
  26. <span class="scatter-explain" :title="$t('totalAnalysis.ta_text7')">{{$t('totalAnalysis.ta_text7')}}</span>
  27. <span>{{A2List.length}}</span>
  28. <div class="index-box"><span v-for="(item,index) in A2List" :key="index" class="scatter-exercise-index" @click="handleIndexClick(item.id)">{{Number(item.id) > 9 ? item.id : '0' + item.id}}</span></div>
  29. </div>
  30. <Divider />
  31. <div class="scatter-table-line">
  32. <span>B</span>
  33. <span class="scatter-explain" :title="$t('totalAnalysis.ta_text8')">{{$t('totalAnalysis.ta_text8')}}</span>
  34. <span>{{B1List.length}}</span>
  35. <div class="index-box"><span v-for="(item,index) in B1List" :key="index" class="scatter-exercise-index" @click="handleIndexClick(item.id)">{{Number(item.id) > 9 ? item.id : '0' + item.id}}</span></div>
  36. </div>
  37. <Divider />
  38. <div class="scatter-table-line">
  39. <span>B-</span>
  40. <span class="scatter-explain" :title="$t('totalAnalysis.ta_text9')">{{$t('totalAnalysis.ta_text9')}}</span>
  41. <span>{{B2List.length}}</span>
  42. <div class="index-box"><span v-for="(item,index) in B2List" :key="index" class="scatter-exercise-index" @click="handleIndexClick(item.id)">{{Number(item.id) > 9 ? item.id : '0' + item.id}}</span></div>
  43. </div>
  44. </div>
  45. </Col>
  46. </Row>
  47. <Divider />
  48. <!-- 年级单题得分率表 -->
  49. <Row>
  50. <span class="component-title">
  51. <span>{{$t('totalAnalysis.ta_title2')}}</span>
  52. <div class="index-wrap" style="display: unset">
  53. <span v-for="(item,index) in exerciseIndexList"
  54. :key="index"
  55. :title="index"
  56. class="exercise-item-index"
  57. @click="onIndexClick(item)"
  58. :style="{background: (+item > 9 ? item : '0' + item) === currentExerciseIndex ? '#d482ab':'#018B99' }">
  59. {{+item > 9 ? item : '0' + item}}
  60. </span>
  61. </div>
  62. <!-- <Poptip trigger="hover" title="选择题号" placement="right" word-wrap>
  63. <span style="font-size:14px;font-weight:bold;margin-left:20px;color:#66cccc">{{$t('totalAnalysis.ta_text5')}} :{{currentExerciseIndex}}</span>
  64. <div slot="content" class="index-wrap">
  65. <span v-for="(item,index) in exerciseIndexList"
  66. :key="index"
  67. :title="index"
  68. class="exercise-item-index"
  69. @click="onIndexClick(item)"
  70. :style="{background: (+item > 9 ? item : '0' + item) === currentExerciseIndex ? '#d482ab':'#018B99' }">
  71. {{+item > 9 ? item : '0' + item}}
  72. </span>
  73. </div>
  74. </Poptip> -->
  75. </span>
  76. <div>
  77. <BaseLineBar :exerciseIndex="currentExerciseIndex" ref="lineBar"></BaseLineBar>
  78. </div>
  79. </Row>
  80. <Divider />
  81. <!-- 试题分析总表 -->
  82. <Row>
  83. <span class="component-title">{{$t('totalAnalysis.ta_title3')}}</span>
  84. <div style="padding:20px 50px;">
  85. <BaseTable :columns="tableColumns"
  86. :tableDatas="tableData"
  87. :tableName="$t('totalAnalysis.ta_title3')"
  88. tableRef="exerciseAnalsisTable"
  89. ref="analysisTable"
  90. :tips="$t('totalAnalysis.ta_table_tip2')"></BaseTable>
  91. </div>
  92. </Row>
  93. <Divider />
  94. <!-- 试题得分率表 -->
  95. <Row>
  96. <span class="component-title">{{$t('totalAnalysis.ta_title4')}}</span>
  97. <div style="padding:20px 50px;">
  98. <BaseTable :columns="exerciseColumns"
  99. :tableDatas="tableData"
  100. :tableName="$t('totalAnalysis.ta_title4')"
  101. tableRef="exerciseScoreRateTable"
  102. ref="scoreRateTable"
  103. :tips="$t('totalAnalysis.ta_table_tip1')"></BaseTable>
  104. </div>
  105. </Row>
  106. </div>
  107. </template>
  108. <script>
  109. import BaseTestScatter from '@/components/student-analysis/total/BaseTestScatter.vue'
  110. import BaseTable from '@/components/student-analysis/total/BaseMyTable.vue'
  111. import BaseLineBar from '@/components/student-analysis/total/BaseLineBar.vue'
  112. export default {
  113. components: {
  114. BaseTestScatter, BaseTable, BaseLineBar
  115. },
  116. data() {
  117. return {
  118. tableData: [],
  119. scatterData:[],
  120. exerciseIndexList: [],
  121. currentExerciseIndex: 0,
  122. A1List: [],
  123. A2List: [],
  124. B1List: [],
  125. B2List: [],
  126. tableColumns: [
  127. {
  128. title: this.$t('totalAnalysis.ta_table_text1'),
  129. key: 'id',
  130. width: 100,
  131. renderType: 'renderEventIndex'
  132. },
  133. {
  134. title: this.$t('totalAnalysis.ta_table_text2'),
  135. key: 'type',
  136. minWidth: 100,
  137. renderType: function(h, params) {
  138. return h('span', params.row.type || '暂无')
  139. },
  140. },
  141. {
  142. title: this.$t('totalAnalysis.ta_table_text3'),
  143. key: 'knowledge',
  144. minWidth: 150,
  145. renderType: function(h, params) {
  146. return h('span', params.row.knowledge || '暂无')
  147. },
  148. },
  149. {
  150. title: this.$t('totalAnalysis.sca_table_text6'),
  151. key: 'areaName',
  152. minWidth: 100
  153. },
  154. {
  155. title: this.$t('totalAnalysis.ta_table_text4'),
  156. key: 'score',
  157. sortable: true,
  158. minWidth: 80
  159. },
  160. {
  161. title: this.$t('totalAnalysis.ta_table_text5'),
  162. key: 'diff',
  163. sortable: true,
  164. minWidth: 100,
  165. renderType: function(h, params) {
  166. return h('span', (Number(params.row.diff) * 100).toFixed(0) + '%')
  167. },
  168. },
  169. {
  170. title: this.$t('totalAnalysis.ta_table_text6'),
  171. key: 'identify',
  172. renderType: function(h, params) {
  173. return h('span', Number(params.row.identify).toFixed(0))
  174. },
  175. minWidth: 120
  176. },
  177. {
  178. title: 'R1',
  179. key: 'R1',
  180. sortable: true,
  181. renderType: function(h, params) {
  182. return h('span', (Number(params.row.R1) * 100).toFixed(0) + '%')
  183. },
  184. minWidth: 100
  185. },
  186. {
  187. title: 'R2',
  188. key: 'R2',
  189. sortable: true,
  190. renderType: function(h, params) {
  191. return h('span', (Number(params.row.R2) * 100).toFixed(0) + '%')
  192. },
  193. minWidth: 100
  194. },
  195. {
  196. title: 'R3',
  197. sortable: true,
  198. key: 'R3',
  199. renderType: function(h, params) {
  200. return h('span', (Number(params.row.R3) * 100).toFixed(0) + '%')
  201. },
  202. minWidth: 100
  203. },
  204. {
  205. title: 'R4',
  206. sortable: true,
  207. key: 'R4',
  208. renderType: function(h, params) {
  209. return h('span', (Number(params.row.R4) * 100).toFixed(0) + '%')
  210. },
  211. minWidth: 100
  212. },
  213. {
  214. title: 'R5',
  215. sortable: true,
  216. key: 'R5',
  217. renderType: function(h, params) {
  218. return h('span', (Number(params.row.R5) * 100).toFixed(0) + '%')
  219. },
  220. minWidth: 100
  221. },
  222. {
  223. title: 'R6',
  224. sortable: true,
  225. key: 'R6',
  226. renderType: function(h, params) {
  227. return h('span', (Number(params.row.R6) * 100).toFixed(0) + '%')
  228. },
  229. minWidth: 100
  230. }
  231. ],
  232. exerciseColumns: [
  233. {
  234. title: this.$t('totalAnalysis.ta_table_text1'),
  235. key: 'id',
  236. fixed: 'left',
  237. width: 100,
  238. renderType: 'renderEventIndex'
  239. },
  240. {
  241. title: this.$t('totalAnalysis.ta_table_text10'),
  242. key: 'PH',
  243. sortable: true,
  244. renderType: function(h, params) {
  245. return h('span', (Number(params.row.PH) * 100).toFixed(0) + '%')
  246. },
  247. width: 150
  248. },
  249. {
  250. title: this.$t('totalAnalysis.ta_table_text11'),
  251. key: 'PL',
  252. sortable: true,
  253. renderType: function(h, params) {
  254. return h('span', (Number(params.row.PL) * 100).toFixed(0) + '%')
  255. },
  256. width: 150
  257. },
  258. {
  259. title: this.$t('totalAnalysis.ta_table_text8'),
  260. key: 'examScoreRate',
  261. sortable: true,
  262. renderType: function(h, params) {
  263. return h('span', (Number(params.row.examScoreRate)).toFixed(0) + '%')
  264. },
  265. width: 150
  266. },
  267. // {
  268. // title: this.$t('totalAnalysis.ta_table_text9'),
  269. // key: 'areaScoreRate',
  270. // sortable: true,
  271. // renderType: function(h, params) {
  272. // return h('span', (Number(params.row.areaScoreRate)).toFixed(0) + '%')
  273. // },
  274. // width: 150
  275. // }
  276. ]
  277. }
  278. },
  279. created() {
  280. this.$parent.$parent.$parent.isShowQuestions = false
  281. },
  282. methods: {
  283. renderClassColumns(classData) {
  284. let classCloumns = []
  285. // 渲染进线表格的班级数据
  286. classData.classes.forEach(item => {
  287. let classColumn = {
  288. title: item.className,
  289. sortable: 'custom',
  290. key: item.className,
  291. render: (h, params) => {
  292. return h('span', (Number(params.row[item.className])).toFixed(0) + '%')
  293. },
  294. minWidth: 150
  295. }
  296. classCloumns.push(classColumn)
  297. })
  298. this.exerciseColumns.splice(4,this.exerciseColumns.length - 4,...classCloumns)
  299. },
  300. // 点击落点图某个点事件
  301. handleItemClick(item) {
  302. let index = item.data[item.data.length - 1]
  303. this.currentExerciseIndex = index > 9 ? '' + index : '0' + index
  304. // 题目编号联动
  305. this.$nextTick(() => {
  306. let indexDomList = Array.prototype.slice.call(document.getElementsByClassName('scatter-exercise-index'))
  307. let hignlightIndexDom = indexDomList.filter(item => +item.innerText === +this.currentExerciseIndex)
  308. indexDomList.forEach(item => {
  309. item.style.background = 'transparent'
  310. })
  311. if (hignlightIndexDom.length) {
  312. hignlightIndexDom[0].style.background = '#018b99'
  313. hignlightIndexDom[0].style.borderRadius = '50%'
  314. }
  315. })
  316. },
  317. onIndexClick(item) {
  318. this.handleItemClick({ data: [+item] })
  319. },
  320. handleIndexClick(index) {
  321. this.$router.push({ path: '/total/questionList', query: { QIndex: index } })
  322. },
  323. // 调整图表所需数据结构格式
  324. renderData(data) {
  325. let analysisJson = JSON.parse(JSON.stringify(this.getAnalysisJson))
  326. let curSubjectIndex = analysisJson.subjects.map(i => i.name).indexOf(this.$store.state.totalAnalysis.currentSubject)
  327. let result = []
  328. analysisJson.paper[curSubjectIndex].Value.forEach((exercise,exerciseIndex) => {
  329. let obj = {}
  330. analysisJson.paperKey.forEach((key, index) => {
  331. obj[key] = exercise[index]
  332. })
  333. analysisJson.classes.forEach(classItem => {
  334. obj[classItem.className] = classItem.subjects[curSubjectIndex].item[exerciseIndex]
  335. })
  336. result.push(obj)
  337. })
  338. console.log(result)
  339. return result
  340. },
  341. doRender(analysisJson){
  342. let exerciseList = this.renderData(analysisJson)
  343. this.renderClassColumns(analysisJson)
  344. this.exerciseIndexList = exerciseList.map(item => item.id)
  345. this.A1List = exerciseList.filter(item => item.areaName === 'A')
  346. this.A2List = exerciseList.filter(item => item.areaName === 'A-')
  347. this.B1List = exerciseList.filter(item => item.areaName === 'B')
  348. this.B2List = exerciseList.filter(item => item.areaName === 'B-')
  349. this.tableData = JSON.parse(JSON.stringify(exerciseList))
  350. this.getScatterData()
  351. console.log('最新试题数据',this.tableData)
  352. },
  353. getScatterData(){
  354. let analysisJson = JSON.parse(JSON.stringify(this.getAnalysisJson))
  355. let curSubjectIndex = analysisJson.subjects.map(i => i.name).indexOf(this.$store.state.totalAnalysis.currentSubject)
  356. let result = []
  357. analysisJson.paper[curSubjectIndex].Value.forEach((exercise, exerciseIndex) => {
  358. let obj = {}
  359. analysisJson.paperKey.forEach((key, index) => {
  360. obj[key] = exercise[index]
  361. })
  362. result.push(obj)
  363. })
  364. let arr = result
  365. let newArr = []
  366. arr.forEach(item => {
  367. let arr2 = []
  368. arr2.push((+item.X).toFixed(2))
  369. arr2.push((item.Y * 100).toFixed(2))
  370. arr2.push(item.type)
  371. arr2.push(item.id)
  372. newArr.push(arr2)
  373. })
  374. this.scatterData = newArr
  375. },
  376. getLineBarData(){
  377. }
  378. },
  379. mounted() {
  380. this.$refs.analysisTable.$el.childNodes[1].style.borderRight = '0'
  381. this.handleItemClick({ data: [1] })
  382. this.getAnalysisJson && this.doRender(this.getAnalysisJson)
  383. this.$EventBus.$off('onSubjectChange')
  384. this.$EventBus.$on('onSubjectChange',val => {
  385. this.doRender(this.getAnalysisJson)
  386. // this.$nextTick(() => {
  387. // this.$refs.lineBar.renderData(this.getAnalysisJson)
  388. // })
  389. })
  390. },
  391. computed: {
  392. // 获取最新试题分析模块数据
  393. getAnalysisJson() {
  394. return this.$store.state.totalAnalysis.analysisJson
  395. }
  396. }
  397. }
  398. </script>
  399. <style src="./TestAnalysis.css" scoped></style>
  400. <style>
  401. .scatter-container .ivu-poptip-content {
  402. max-width:520px;
  403. }
  404. </style>