MarkBoardInspect.vue 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. <template>
  2. <div
  3. v-if="store.currentTask"
  4. :style="{ display: store.MarkBoardTrackCollapse ? 'none' : 'block' }"
  5. class="mark-board-track-container"
  6. >
  7. <div>
  8. <h1 class="tw-text-3xl tw-text-center">试卷总分:{{ markerScore }}</h1>
  9. </div>
  10. <div v-if="groups">
  11. <template v-for="(groupNumber, index) in groups" :key="index">
  12. <div class="mb-2">
  13. <div
  14. class="tw-flex tw-justify-between"
  15. @mouseover="addFocusTrack(groupNumber, undefined, undefined)"
  16. @mouseleave="removeFocusTrack"
  17. >
  18. 分组 {{ groupNumber }}
  19. <div>
  20. 打回
  21. <input
  22. type="checkbox"
  23. @click="groupClicked(groupNumber)"
  24. :checked="groupChecked(groupNumber)"
  25. />
  26. </div>
  27. </div>
  28. <div v-if="questions">
  29. <template v-for="(question, index) in questions" :key="index">
  30. <div
  31. v-if="question.groupNumber === groupNumber"
  32. class="question tw-rounded tw-flex tw-mb-1"
  33. @mouseover="
  34. addFocusTrack(
  35. undefined,
  36. question.mainNumber,
  37. question.subNumber
  38. )
  39. "
  40. @mouseleave="removeFocusTrack"
  41. >
  42. <div class="tw-flex-1">
  43. {{ question.title }} {{ question.mainNumber }}-{{
  44. question.subNumber
  45. }}
  46. </div>
  47. <div class="tw-flex-1 tw-text-center">
  48. {{ question.score || 0 }}
  49. </div>
  50. <div>
  51. 打回
  52. <input
  53. type="checkbox"
  54. @change="questionCheckChanged(question)"
  55. :checked="questionChecked(question)"
  56. />
  57. </div>
  58. </div>
  59. </template>
  60. </div>
  61. </div>
  62. </template>
  63. </div>
  64. <div class="tw-flex tw-justify-center">
  65. <div
  66. v-if="
  67. store.currentTask.inspectTime && store.currentTask.inspectTime > 0
  68. "
  69. @click="reject"
  70. >
  71. 打回
  72. </div>
  73. <div v-else-if="checkedQuestions.length === 0" @click="inspect">复核</div>
  74. <div v-else @click="reject">打回</div>
  75. </div>
  76. </div>
  77. </template>
  78. <script lang="ts">
  79. import { Question } from "@/types";
  80. import { computed, defineComponent, reactive, watch } from "vue";
  81. import { store } from "./store";
  82. export default defineComponent({
  83. name: "MarkBoardInspect",
  84. emits: ["inspect", "reject"],
  85. setup(props, { emit }) {
  86. let checkedQuestions = reactive([] as Array<Question>);
  87. watch(
  88. () => store.currentTask,
  89. () => {
  90. checkedQuestions.splice(0);
  91. }
  92. );
  93. const groups = computed(() => {
  94. const gs = store.currentTask?.questionList.map((q) => q.groupNumber);
  95. return [...new Set(gs)].sort((a, b) => a - b);
  96. });
  97. const questions = computed(() => {
  98. const qs = store.currentTask?.questionList;
  99. return qs;
  100. });
  101. const markerScore = computed(
  102. () =>
  103. (questions.value
  104. ?.map((q) => Math.round((q.score || 0) * 100))
  105. .reduce((acc, s) => acc + s) || 0) / 100
  106. );
  107. function addToCheckedQuestion(question: Question) {
  108. checkedQuestions.push(question);
  109. }
  110. function removeCheckedQuestion(question: Question) {
  111. const idx = checkedQuestions.indexOf(question);
  112. checkedQuestions.splice(idx, 1);
  113. }
  114. function groupChecked(groupNumber: number) {
  115. return (
  116. checkedQuestions.filter((q) => q.groupNumber === groupNumber).length ===
  117. questions.value?.filter((q) => q.groupNumber === groupNumber).length
  118. );
  119. }
  120. function questionChecked(question: Question) {
  121. return checkedQuestions.includes(question);
  122. }
  123. function questionCheckChanged(question: Question) {
  124. const checked = questionChecked(question);
  125. if (checked) {
  126. removeCheckedQuestion(question);
  127. } else {
  128. addToCheckedQuestion(question);
  129. }
  130. }
  131. function groupClicked(groupNumber: number) {
  132. if (groupChecked(groupNumber)) {
  133. checkedQuestions
  134. .filter((q) => q.groupNumber === groupNumber)
  135. .forEach((q) => {
  136. const idx = checkedQuestions.indexOf(q);
  137. checkedQuestions.splice(idx, 1);
  138. });
  139. } else {
  140. questions.value
  141. ?.filter((q) => q.groupNumber === groupNumber)
  142. .forEach((q) => {
  143. if (!questionChecked(q)) checkedQuestions.push(q);
  144. });
  145. }
  146. }
  147. function addFocusTrack(
  148. groupNumber: number | undefined,
  149. mainNumber: number | undefined,
  150. subNumber: string | undefined
  151. ) {
  152. store.focusTracks.splice(0);
  153. if (groupNumber) {
  154. questions.value
  155. ?.filter((q) => q.groupNumber === groupNumber)
  156. ?.map((q) => q.trackList)
  157. .reduce((acc, ts) => acc.concat(ts))
  158. .forEach((t) => {
  159. store.focusTracks.push(t);
  160. });
  161. } else {
  162. questions.value
  163. ?.map((q) => q.trackList)
  164. .reduce((acc, ts) => acc.concat(ts))
  165. .filter((t) => {
  166. if (mainNumber) {
  167. return t.mainNumber === mainNumber && t.subNumber === subNumber;
  168. } else {
  169. return false;
  170. }
  171. })
  172. .forEach((t) => {
  173. store.focusTracks.push(t);
  174. });
  175. }
  176. // console.log(store.focusTracks);
  177. }
  178. function removeFocusTrack() {
  179. store.focusTracks.splice(0);
  180. }
  181. function reject() {
  182. emit("reject", checkedQuestions);
  183. }
  184. function inspect() {
  185. emit("inspect");
  186. }
  187. return {
  188. store,
  189. markerScore,
  190. groups,
  191. checkedQuestions,
  192. questions,
  193. groupChecked,
  194. questionChecked,
  195. questionCheckChanged,
  196. groupClicked,
  197. addFocusTrack,
  198. removeFocusTrack,
  199. reject,
  200. inspect,
  201. };
  202. },
  203. });
  204. </script>
  205. <style scoped>
  206. .mark-board-track-container {
  207. max-width: 250px;
  208. min-width: 250px;
  209. border-left: 1px solid grey;
  210. padding-left: 6px;
  211. padding-right: 6px;
  212. max-height: calc(100vh - 41px);
  213. }
  214. .question {
  215. min-width: 100px;
  216. border: 1px solid grey;
  217. }
  218. .current-question {
  219. border: 1px solid yellowgreen;
  220. background-color: lightblue;
  221. }
  222. .single-score {
  223. width: 30px;
  224. height: 30px;
  225. display: grid;
  226. place-content: center;
  227. border: 1px solid black;
  228. border-radius: 5px;
  229. }
  230. .current-score {
  231. border: 1px solid yellowgreen;
  232. background-color: lightblue;
  233. }
  234. </style>