SubjectProgress.vue 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. <template>
  2. <div class="p-base">
  3. <div class="fill-blank radius-base p-base chart-info">
  4. <vue-e-charts class="full" :option="totalChartsOption" autoresize></vue-e-charts>
  5. </div>
  6. <div class="m-t-base fill-blank radius-base p-base">
  7. <base-table :data="subjectProgressEndList" :columns="columns" :span-method="tableSpanMethod"></base-table>
  8. </div>
  9. </div>
  10. </template>
  11. <script setup lang="ts" name="SubjectProgress">
  12. /** 科目进度 */
  13. import { reactive, ref, computed } from 'vue'
  14. import { minus } from '@/utils/common'
  15. import useFetch from '@/hooks/useFetch'
  16. import useMainStore from '@/store/main'
  17. import VueECharts from 'vue-echarts'
  18. import BaseTable from '@/components/element/BaseTable.vue'
  19. import type { EChartsOption } from 'echarts'
  20. import type { ExtractApiResponse } from 'api-type'
  21. import type { EpTableColumn, InstanceTable } from 'global-type'
  22. type SubjectProgress = ExtractArrayValue<ExtractApiResponse<'subjectProgressEnd'>>
  23. const mainStore = useMainStore()
  24. const { fetch: subjectProgressEnd, result: subjectProgressEndList } = useFetch('subjectProgressEnd')
  25. subjectProgressEnd({ subjectCode: mainStore.myUserInfo?.subjectCode || '' })
  26. const getMainName = (row?: SubjectProgress) => {
  27. const { questionMainName: name, questionMainNumber: number } = row || {}
  28. return [number, name].filter(Boolean).join('-')
  29. }
  30. const getYAxisData = (field: keyof SubjectProgress | 'name', data?: SubjectProgress[]) => {
  31. if (!data) {
  32. return []
  33. }
  34. return data.map((v) => {
  35. if (field === 'name') {
  36. return getMainName(v)
  37. }
  38. return v[field]
  39. })
  40. }
  41. const totalChartsOption = computed<EChartsOption>(() => {
  42. return {
  43. grid: {
  44. top: 20,
  45. bottom: -20,
  46. left: 20,
  47. right: 30,
  48. containLabel: true,
  49. },
  50. legend: {
  51. right: 0,
  52. itemWidth: 14,
  53. data: ['试卷总量', '已完成', '完成比'],
  54. },
  55. yAxis: {
  56. axisLine: { show: false },
  57. axisTick: { show: false },
  58. splitLine: { show: false },
  59. inverse: true,
  60. axisLabel: {
  61. align: 'right',
  62. verticalAlign: 'bottom',
  63. },
  64. data: getYAxisData('name', subjectProgressEndList?.value),
  65. },
  66. xAxis: [
  67. {
  68. position: 'top',
  69. type: 'value',
  70. splitLine: { show: true },
  71. },
  72. {
  73. position: 'bottom',
  74. type: 'value',
  75. show: false,
  76. axisLabel: {
  77. formatter: `{value}%`,
  78. },
  79. splitLine: { show: false },
  80. },
  81. ],
  82. series: [
  83. {
  84. name: '试卷总量',
  85. type: 'bar',
  86. barWidth: 11,
  87. barGap: '-200%',
  88. itemStyle: {
  89. color: '#3AD500',
  90. },
  91. data: getYAxisData('totalPaper', subjectProgressEndList?.value),
  92. },
  93. {
  94. name: '已完成',
  95. type: 'bar',
  96. barWidth: 11,
  97. barGap: '-200%',
  98. itemStyle: {
  99. color: '#0064FF',
  100. },
  101. data: getYAxisData('finishCount', subjectProgressEndList?.value),
  102. },
  103. {
  104. name: '完成比',
  105. type: 'bar',
  106. barWidth: 44,
  107. barGap: '-200%',
  108. showBackground: true,
  109. xAxisIndex: 1,
  110. itemStyle: {
  111. color: 'rgba(0, 186, 151,0.3)',
  112. },
  113. label: {
  114. show: true,
  115. color: '#444',
  116. fontSize: 10,
  117. formatter({ value }) {
  118. return value > 0 ? `${value}%` : ''
  119. },
  120. position: 'insideTopRight',
  121. },
  122. data: getYAxisData('finishRate', subjectProgressEndList?.value),
  123. },
  124. ],
  125. }
  126. })
  127. const columns: EpTableColumn<SubjectProgress>[] = [
  128. {
  129. label: '科目',
  130. formatter() {
  131. return mainStore.myUserInfo?.subjectCode + '-' + mainStore.myUserInfo?.subjectName
  132. },
  133. },
  134. { label: '大题', prop: 'questionMainName' },
  135. { label: '试卷总量', prop: 'totalPaper' },
  136. { label: '已完成', prop: 'finishCount' },
  137. {
  138. label: '完成比',
  139. prop: 'finishRate',
  140. formatter(row) {
  141. return `${row.finishRate}%`
  142. },
  143. },
  144. {
  145. label: '待完成',
  146. formatter(row) {
  147. return `${minus(row.totalPaper, row.finishCount)}`
  148. },
  149. },
  150. {
  151. label: '待完成比',
  152. prop: 'totalPaper',
  153. formatter(row) {
  154. return `${minus(100, row.finishRate)}%`
  155. },
  156. },
  157. { label: '问题卷待处理', prop: 'todoProblemPaperCount' },
  158. { label: '雷同卷待处理', prop: 'todoSamePaperCount' },
  159. { label: '主观题校验待处理', prop: 'subjectiveUnVerifyPaperCount' },
  160. {
  161. label: '抽查比例',
  162. prop: 'checkPaperRate',
  163. formatter(row) {
  164. return `${row.checkPaperRate}%`
  165. },
  166. },
  167. { label: '仲裁卷待处理', prop: 'todoArbitrationPaperCount' },
  168. {
  169. label: '仲裁率',
  170. prop: 'arbitrationPaperRate',
  171. formatter(row) {
  172. return `${row.arbitrationPaperRate}%`
  173. },
  174. },
  175. ]
  176. const tableSpanMethod: InstanceTable['spanMethod'] = (scope) => {
  177. if (scope.columnIndex === 0) {
  178. if (scope.rowIndex === 0) {
  179. return {
  180. rowspan: subjectProgressEndList.value?.length || 1,
  181. colspan: 1,
  182. }
  183. } else {
  184. return {
  185. rowspan: 0,
  186. colspan: 0,
  187. }
  188. }
  189. }
  190. return {
  191. rowspan: 1,
  192. colspan: 1,
  193. }
  194. }
  195. </script>
  196. <style scoped lang="scss">
  197. .chart-info {
  198. height: 260px;
  199. }
  200. </style>