index.vue 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. <template>
  2. <div class="flex direction-column full group-monitoring-view">
  3. <div class="p-l-base p-r-base p-t-medium-base fill-blank">
  4. <base-form size="small" :label-width="'60px'" :disabled="loading" :model="model" :items="items">
  5. <template #form-item-button-group>
  6. <el-button :loading="loading" type="primary" @click="onSearch">刷新</el-button>
  7. </template>
  8. </base-form>
  9. </div>
  10. <div class="flex-1 p-base">
  11. <div class="radius-base p-l-base p-r-base p-t-mini fill-blank p-b-mini">
  12. <base-table border stripe size="small" :columns="columns" :data="result">
  13. <template #column-leader="{ row }">
  14. <div style="text-align: left; overflow: hidden; white-space: nowrap; text-overflow: ellipsis">
  15. <span
  16. :style="{
  17. backgroundColor: row.online ? '#00B42A' : '#ddd',
  18. display: 'inline-block',
  19. width: '10px',
  20. height: '10px',
  21. marginRight: '4px',
  22. borderRadius: '2px',
  23. }"
  24. ></span>
  25. <span>{{ row.markingGroupLeader }}</span>
  26. </div>
  27. </template>
  28. </base-table>
  29. </div>
  30. <div class="radius-base m-t-base p-l-base p-r-base p-t-mini fill-blank p-b-mini">
  31. <div class="chart-wrap">
  32. <vue-echarts :option="chartOptions" autoresize></vue-echarts>
  33. </div>
  34. </div>
  35. </div>
  36. </div>
  37. </template>
  38. <script setup lang="tsx" name="AnalysisGroupMonitoring">
  39. /** 小组监控 */
  40. import { computed } from 'vue'
  41. import { useRouter } from 'vue-router'
  42. import { ElButton } from 'element-plus'
  43. import BaseForm from '@/components/element/BaseForm.vue'
  44. import BaseTable from '@/components/element/BaseTable.vue'
  45. import useFetch from '@/hooks/useFetch'
  46. import useVW from '@/hooks/useVW'
  47. import useFormFilter from './hooks/useFormFilter'
  48. import { reactive } from 'vue'
  49. import VueEcharts from 'vue-echarts'
  50. import type { EpTableColumn } from 'global-type'
  51. import type { ExtractApiResponse } from '@/api/api'
  52. const jumpParams = reactive<any>({
  53. subjectCode: '',
  54. questionMainNumber: void 0,
  55. })
  56. const { push } = useRouter()
  57. const { model, formModel, items, onOptionInit } = useFormFilter()
  58. const { loading, fetch: getGroupMonitor, result } = useFetch('getGroupMonitor')
  59. const columns: any = [
  60. {
  61. label: '组长',
  62. prop: 'markingGroupLeader',
  63. width: 150,
  64. fixed: 'left',
  65. slotName: 'leader',
  66. align: 'left',
  67. },
  68. {
  69. label: '已浏览试卷总数',
  70. prop: 'totalCount',
  71. minWidth: 138,
  72. sortable: true,
  73. formatter(row) {
  74. return (
  75. <ElButton type="primary" link onClick={() => viewMonitoringDetail(row, 'VIEW')}>
  76. {row.totalCount}
  77. </ElButton>
  78. )
  79. },
  80. },
  81. {
  82. label: '已给分试卷总数',
  83. prop: 'totalReScoreCount',
  84. minWidth: 138,
  85. sortable: true,
  86. formatter(row) {
  87. return (
  88. <ElButton type="primary" link onClick={() => viewMonitoringDetail(row, 'MARK')}>
  89. {row.totalReScoreCount}
  90. </ElButton>
  91. )
  92. },
  93. },
  94. { label: '已浏览系统抽查卷数', prop: 'sysCheckCount', minWidth: 160, sortable: true },
  95. { label: '已给分系统抽查卷数', prop: 'sysCheckReScoreCount', minWidth: 160, sortable: true },
  96. { label: '打回量', prop: 'rejectCount', minWidth: 85, sortable: true },
  97. { label: '主动抽查次数', prop: 'initiativeCheckCount', minWidth: 120, sortable: true },
  98. { label: '主动抽查给分次数', prop: 'initiativeCheckReScoreCount', minWidth: 150, sortable: true },
  99. { label: '已浏览问题卷数', prop: 'problemCount', minWidth: 138, sortable: true },
  100. { label: '已给分问题卷数', prop: 'problemReScoreCount', minWidth: 138, sortable: true },
  101. { label: '已浏览自定义抽查卷数', prop: 'customCheckCount', minWidth: 178, sortable: true },
  102. { label: '已给分自定义抽查卷数', prop: 'customCheckReScoreCount', minWidth: 178, sortable: true },
  103. ]
  104. /** 刷新按钮 */
  105. function onSearch() {
  106. let markingGroupNumbers: any = formModel.value.markingGroupNumbers
  107. if (
  108. !markingGroupNumbers ||
  109. (Array.isArray(markingGroupNumbers) && markingGroupNumbers.length !== markingGroupNumbers.filter((v) => !!v).length)
  110. ) {
  111. markingGroupNumbers = []
  112. }
  113. getGroupMonitor({ ...formModel.value, markingGroupNumbers }).then(() => {
  114. jumpParams.subjectCode = formModel.value.subjectCode
  115. jumpParams.questionMainNumber = formModel.value.questionMainNumber
  116. })
  117. }
  118. /** 查看抽查详情 */
  119. function viewMonitoringDetail(
  120. row: ExtractArrayValue<ExtractApiResponse<'getGroupMonitor'>>,
  121. operateType: 'VIEW' | 'MARK'
  122. ) {
  123. push({
  124. name: 'AnalysisGroupDetail',
  125. query: {
  126. operateType,
  127. headerId: row.markingGroupLeaderId,
  128. source: '组长监控',
  129. subjectCode: jumpParams.subjectCode,
  130. questionMainNumber: jumpParams.questionMainNumber,
  131. },
  132. })
  133. }
  134. onOptionInit(onSearch)
  135. const chartOptions = computed(() => {
  136. return {
  137. grid: {
  138. top: 50,
  139. bottom: 15,
  140. left: 30,
  141. right: 30,
  142. containLabel: true,
  143. },
  144. legend: {
  145. top: 10,
  146. itemWidth: 14,
  147. data: ['已浏览', '已给分'],
  148. },
  149. tooltip: {
  150. trigger: 'item',
  151. triggerOn: 'mousemove',
  152. },
  153. xAxis: {
  154. axisLine: { show: false },
  155. axisTick: { show: false },
  156. splitLine: { show: false },
  157. // axisLabel: {
  158. // align: 'right',
  159. // },
  160. data: result.value?.map((item) => item.markingGroupLeader) || [],
  161. },
  162. yAxis: {
  163. axisTick: { show: false },
  164. type: 'value',
  165. },
  166. series: [
  167. {
  168. name: '已浏览',
  169. type: 'bar',
  170. itemStyle: {
  171. color: '#0064FF',
  172. },
  173. data: result.value?.map((item) => item.totalCount) || [],
  174. label: {
  175. show: true,
  176. color: '#444',
  177. fontSize: 10,
  178. position: 'top',
  179. formatter({ value }) {
  180. return value > 0 ? `${value}` : ''
  181. },
  182. },
  183. },
  184. {
  185. name: '已给分',
  186. type: 'bar',
  187. itemStyle: {
  188. color: '#3AD500',
  189. },
  190. data: result.value?.map((item) => item.totalReScoreCount) || [],
  191. label: {
  192. show: true,
  193. color: '#444',
  194. fontSize: 10,
  195. position: 'top',
  196. formatter({ value }) {
  197. return value > 0 ? `${value}` : ''
  198. },
  199. },
  200. },
  201. ],
  202. }
  203. })
  204. </script>
  205. <style scoped lang="scss">
  206. .group-monitoring-view {
  207. .chart-wrap {
  208. height: 300px;
  209. }
  210. }
  211. </style>