ExamQu.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. <template>
  2. <div class="qu-score">
  3. <div class="qu-score-count" :id="`class-score-count-${id}`"></div>
  4. <p class="legend-info">
  5. <!-- <span>{{ $t('studentWeb.exam.chart.legendSimple.legend1') }}</span> -->
  6. <span>{{ $t('studentWeb.exam.chart.legendSimple.legend2') }}
  7. <span style="color: #00AD6C;">√</span>
  8. </span>
  9. <span>{{ $t('studentWeb.exam.chart.legendSimple.legend3') }}
  10. <span style="color: #FF5508;">×</span>
  11. </span>
  12. </p>
  13. </div>
  14. </template>
  15. <script>
  16. import elementResizeDetectorMaker from "element-resize-detector"
  17. export default {
  18. props: {
  19. quData: {
  20. type: Array,
  21. default: () => {
  22. return []
  23. }
  24. }
  25. },
  26. data() {
  27. let _this = this
  28. return {
  29. isShowRate: true,
  30. progressPie: undefined,
  31. stuCount: 0,
  32. option: {},
  33. id: "",
  34. }
  35. },
  36. created() {
  37. this.id = this.$jsFn.getBtwRandom(0, 100000000)
  38. },
  39. mounted() {
  40. this.progressPie = this.$echarts.init(document.getElementById(`class-score-count-${this.id}`), 'macarons')
  41. this.progressPie.setOption(this.option)
  42. let erd11 = elementResizeDetectorMaker()
  43. erd11.listenTo(document.getElementById(`class-score-count-${this.id}`), () => {
  44. this.$nextTick(() => {
  45. //监听到事件后执行的业务逻辑
  46. this.progressPie.resize()
  47. })
  48. })
  49. },
  50. watch: {
  51. quData: {
  52. handler(n, o) {
  53. console.log(n);
  54. let _this = this
  55. this.$nextTick(() => {
  56. if (this.quData.length) _this.stuCount = this.quData[0].correct + this.quData[0].wrong
  57. this.option = {
  58. tooltip: {
  59. trigger: 'item',
  60. formatter: '{b} : {c}' + this.$t('unit.text7')
  61. },
  62. title: {
  63. "text": this.$t('learnActivity.simple.quCorrectRate'),
  64. "left": "center",
  65. "top": 0,
  66. "textStyle": {
  67. fontSize: 15,
  68. color: "#333"
  69. }
  70. },
  71. legend: {
  72. /* itemStyle: {
  73. opacity: 0
  74. }, */
  75. /* formatter: (params) => {
  76. return `√表示答对`
  77. }, */
  78. bottom: 0,
  79. },
  80. tooltip: {
  81. formatter: (params) => {
  82. return `${_this.$t('learnActivity.simple.rac')} ${params.data.value.toFixed(0)}%(${_this.quData[params.dataIndex].correct}${_this.$t('unit.text7')})`
  83. }
  84. },
  85. grid: {
  86. // width: "100%",
  87. left: 50,
  88. right: 50
  89. },
  90. xAxis: {
  91. show: true,
  92. // name:'题号',
  93. nameLocation: 'end',
  94. type: 'category',
  95. data: [],
  96. axisLine: {
  97. lineStyle: {
  98. color: "#AAA"
  99. }
  100. },
  101. axisLabel: {
  102. rotate: 0,
  103. /* formatter: (params) => {
  104. return `${params}\n${_this.quData[params-1].type ? '{typea|√}' : '{typeb|×}'}`
  105. },
  106. rich: {
  107. typea: {
  108. color: '#00AD6C',
  109. fontSize: 20,
  110. // height: 24,
  111. // padding: [0, 5, 0, 5],
  112. align: 'center'
  113. },
  114. typeb: {
  115. color: '#FF5508',
  116. fontSize: 20,
  117. // height: 24,
  118. // padding: [0, 5, 0, 5],
  119. align: 'center'
  120. },
  121. count: {
  122. color: '#333',
  123. height: 24,
  124. // padding: [0, 5, 0, 5],
  125. // align: 'right'
  126. },
  127. }, */
  128. }
  129. },
  130. yAxis: {
  131. // name:'正确率',
  132. type: 'value',
  133. axisLine: {
  134. lineStyle: {
  135. color: "#AAA"
  136. }
  137. },
  138. },
  139. series: [
  140. {
  141. data: [],
  142. type: 'bar',
  143. barMinWidth: 30,
  144. barMaxWidth: 30,
  145. label: {
  146. show: true,
  147. position: 'top',
  148. formatter: (params) => {
  149. //统计人数的算法
  150. // if (_this.stuCount > 0) {
  151. // return `${(params.data * 100 / _this.stuCount).toFixed(1)}%`
  152. // } else {
  153. // return params.data
  154. // }
  155. // 统计正确率的算法
  156. return _this.isShowRate ? `${params.data.type ? '{typea|√}' : '{typeb|×}'}\n{count|${params.data.value.toFixed(0)}%}` : ''
  157. },
  158. rich: {
  159. typea: {
  160. color: '#00AD6C',
  161. fontSize: 20,
  162. // height: 24,
  163. // padding: [0, 5, 0, 5],
  164. align: 'center'
  165. },
  166. typeb: {
  167. color: '#FF5508',
  168. fontSize: 20,
  169. // height: 24,
  170. // padding: [0, 5, 0, 5],
  171. align: 'center'
  172. },
  173. count: {
  174. color: '#333',
  175. height: 24,
  176. // padding: [0, 5, 0, 5],
  177. // align: 'right'
  178. },
  179. },
  180. },
  181. itemStyle: {
  182. normal: {
  183. color: function (params) {
  184. const colorList = ['#ed4014', '#ff9900', '#19be6b']
  185. //统计人数的算法
  186. // if (_this.stuCount >= 0) {
  187. // let rate = params.data * 100 / _this.stuCount
  188. // console.log(params, rate)
  189. // if (rate >= 70) {
  190. // return colorList[2]
  191. // } else if (rate > 50) {
  192. // return colorList[1]
  193. // } else {
  194. // return colorList[0]
  195. // }
  196. // } else {
  197. // return colorList[2]
  198. // }
  199. // 统计正确率的算法
  200. if (params.data.value >= 70) {
  201. return colorList[2]
  202. } else if (params.data.value > 50) {
  203. return colorList[1]
  204. } else {
  205. return colorList[0]
  206. }
  207. }
  208. }
  209. },
  210. stillShowZeroSum: true,
  211. },
  212. ]
  213. }
  214. if (!this.progressPie) {
  215. this.progressPie = this.$echarts.init(document.getElementById(`class-score-count-${this.id}`), 'macarons')
  216. }
  217. this.option.series[0].data = this.quData.map(item => {
  218. return {
  219. value: item.correct * 100 / this.stuCount,
  220. type: item.type
  221. }
  222. })
  223. /* this.option.series[0].data = [
  224. {
  225. value: this.quData.map(item => item.correct * 100 / this.stuCount)
  226. },
  227. {
  228. value: this.quData.map(item => {return item.type})
  229. }
  230. ] */
  231. // this.option.series[0].data = this.quData.map(item => item.correct * 100 / this.stuCount) //计算正确率
  232. this.option.xAxis.data = this.quData.map(item => item.quLabel)
  233. // if (this.quData.length) this.option.yAxis.max = this.quData[0].correct + this.quData[0].wrong
  234. if (this.quData.length) this.option.yAxis.max = 100 //计算比例不算人数
  235. if (this.quData.length > 8) {
  236. this.option.dataZoom = [
  237. {
  238. show: true,
  239. height: 8,
  240. xAxisIndex: [
  241. 0
  242. ],
  243. bottom: 10,
  244. endValue: 30,
  245. startValue: 0,
  246. handleIcon: 'M512 497.821538m-418.264615 0a418.264615 418.264615 0 1 0 836.52923 0 418.264615 418.264615 0 1 0-836.52923 0Z',
  247. handleSize: '100%',
  248. handleStyle: {
  249. color: '#d3dee5'
  250. },
  251. textStyle: {
  252. color: '#fff'
  253. },
  254. borderRadius: '5px',
  255. maxValue: 30,
  256. },
  257. {
  258. type: 'inside',
  259. show: true,
  260. height: 15,
  261. endValue: 30,
  262. startValue: 0,
  263. maxValue: 30,
  264. }
  265. ]
  266. } else {
  267. this.option.dataZoom = []
  268. }
  269. this.progressPie.setOption(this.option, true)
  270. /* this.progressPie.on('datazoom', (params) => {
  271. let start = params.batch[0]?.start
  272. let end = params.batch[0]?.end
  273. if (end - start > 30) {
  274. this.isShowRate = false
  275. } else {
  276. this.isShowRate = true
  277. }
  278. }) */
  279. })
  280. },
  281. deep: true,
  282. immediate: true
  283. },
  284. }
  285. }
  286. </script>
  287. <style scoped lang="less">
  288. .qu-score {
  289. padding: 15px 20px 0 20px;
  290. width: 440px;
  291. height: 250px;
  292. }
  293. .qu-score-count {
  294. width: 100%;
  295. height: 100%;
  296. }
  297. .legend-info {
  298. text-align: center;
  299. font-weight: bold;
  300. & > span:not(:last-child) {
  301. margin-right: 10px;
  302. }
  303. }
  304. </style>