index.vue 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. <template>
  2. <div class="flex direction-column full">
  3. <mark-header
  4. :exclude-operations="['remark', 'problem', 'example', 'delete', 'bookmark']"
  5. :paper-path="current?.url"
  6. :secret-number="current?.secretNumber"
  7. @click="onOperationClick"
  8. ></mark-header>
  9. <div class="flex flex-1 overflow-hidden p-base mark-container">
  10. <splitpanes class="default-theme" style="height: 100%" @resize="setPaneSize">
  11. <pane
  12. max-size="80"
  13. :size="paneSize"
  14. class="flex flex-1 direction-column radius-base fill-blank mark-content"
  15. :class="{ 'text-center': center }"
  16. :style="{ 'background-color': backgroundColor }"
  17. >
  18. <!-- <right-button class="next-button" @click="checkNext" /> -->
  19. <div class="flex-1 p-base scroll-auto mark-content-paper img-wrap relative">
  20. <img :src="dataUrl" alt="" class="paper-img" :style="{ 'background-color': frontColor }" />
  21. <p v-if="current" class="absolute mark-score">{{ current?.markScore }}</p>
  22. </div>
  23. </pane>
  24. <pane max-size="80" :size="100 - paneSize" class="p-base radius-base fill-blank scroll-auto table-view">
  25. <base-table
  26. ref="tableRef"
  27. border
  28. stripe
  29. size="small"
  30. height="100%"
  31. :data="tableData"
  32. :columns="columns"
  33. highlight-current-row
  34. :cell-style="{ padding: '6px 0' }"
  35. :memory-column="true"
  36. @current-change="onCurrentChange"
  37. @row-dblclick="onDbClick"
  38. ></base-table>
  39. </pane>
  40. </splitpanes>
  41. </div>
  42. </div>
  43. <mark-history-list
  44. :id="currentViewHistory?.taskId"
  45. v-model="visibleHistory"
  46. :task="currentViewHistory"
  47. :number="current?.number"
  48. ></mark-history-list>
  49. </template>
  50. <script setup lang="ts" name="MarkingTrainingRecord">
  51. /** 查看培训记录 */
  52. import { computed } from 'vue'
  53. import { useSetImgBg } from '@/hooks/useSetImgBg'
  54. import useFetch from '@/hooks/useFetch'
  55. import useMarkHeader from '@/hooks/useMarkHeader'
  56. import useTableCheck from '@/hooks/useTableCheck'
  57. import MarkHeader from '@/components/shared/MarkHeader.vue'
  58. import BaseTable from '@/components/element/BaseTable.vue'
  59. import MarkHistoryList from '@/components/shared/MarkHistoryList.vue'
  60. import RightButton from '@/components/shared/RightButton.vue'
  61. import type { SetImgBgOption } from '@/hooks/useSetImgBg'
  62. import type { ExtractApiResponse } from '@/api/api'
  63. import type { MarkHeaderInstance, EpTableColumn } from 'global-type'
  64. import { Splitpanes, Pane } from 'splitpanes'
  65. import { setPaneSize } from '@/utils/common'
  66. import useMainStore from '@/store/main'
  67. const mainStore = useMainStore()
  68. const paneSize = computed(() => {
  69. return mainStore.paneSizeConfig[location.pathname] || 60
  70. })
  71. type RowType = ExtractArrayValue<ExtractApiResponse<'viewTrainingRecord'>> & { index: number }
  72. const {
  73. rotate,
  74. scale,
  75. center,
  76. frontColor,
  77. backgroundColor,
  78. onBack,
  79. onScaleChange,
  80. onCenter,
  81. onRotate,
  82. setBackgroundColor,
  83. setFrontColor,
  84. onViewStandard,
  85. } = useMarkHeader()
  86. /** 刷新 */
  87. const onRefresh = () => {
  88. viewTrainingRecord()
  89. }
  90. type OperationClick = MarkHeaderInstance['onClick']
  91. type OperationType = Parameters<Exclude<OperationClick, undefined>>[0]['type']
  92. const operationHandles: Partial<Record<OperationType, (...args: any) => void>> = {
  93. back: onBack,
  94. 'scale-change': onScaleChange,
  95. center: onCenter,
  96. rotate: onRotate,
  97. 'front-color': setFrontColor,
  98. 'background-color': setBackgroundColor,
  99. refresh: onRefresh,
  100. standard: onViewStandard,
  101. }
  102. const onOperationClick: OperationClick = ({ type, value }) => {
  103. operationHandles[type]?.(value)
  104. }
  105. /** 查询培训记录 */
  106. const taskTypeMap: Record<string, string> = {
  107. SAMPLE_A: 'A',
  108. SAMPLE_B: 'B',
  109. }
  110. const columns: EpTableColumn<RowType>[] = [
  111. // { label: '密号', prop: 'secretNumber' },
  112. { label: '序号', minWidth: 40, prop: 'number' },
  113. { label: '分数', prop: 'markScore' },
  114. { label: '标准分', prop: 'score' },
  115. {
  116. label: '分组',
  117. prop: 'taskType',
  118. formatter(row) {
  119. return row.taskType ? taskTypeMap[row.taskType] || '-' : '-'
  120. },
  121. },
  122. ]
  123. //该接口貌似是返回全量,不需要pageSize
  124. const { fetch: viewTrainingRecord, result: trainingRecordList } = useFetch('viewTrainingRecord')
  125. const {
  126. tableRef,
  127. tableData,
  128. current,
  129. currentView: currentViewHistory,
  130. next: checkNext,
  131. visibleHistory,
  132. onDbClick,
  133. onCurrentChange,
  134. } = useTableCheck(trainingRecordList)
  135. viewTrainingRecord()
  136. const imgOption = computed<SetImgBgOption>(() => {
  137. return {
  138. image: current?.value?.url,
  139. rotate: rotate.value,
  140. scale: scale.value,
  141. }
  142. })
  143. const { drawing, dataUrl } = useSetImgBg(imgOption, frontColor, setFrontColor)
  144. </script>
  145. <style scoped lang="scss">
  146. .mark-container {
  147. .mark-content {
  148. position: relative;
  149. .preview {
  150. position: absolute;
  151. cursor: pointer;
  152. top: 20px;
  153. right: 25px;
  154. font-size: 38px;
  155. }
  156. .next-button {
  157. position: absolute;
  158. right: -20px;
  159. top: 300px;
  160. }
  161. .mark-content-paper {
  162. img {
  163. max-width: 100%;
  164. }
  165. }
  166. }
  167. .table-view {
  168. // width: 580px;
  169. }
  170. }
  171. </style>