MarkBoardInspect.vue 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  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)"
  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 v-if="store.currentTask.inspectTime > 0" @click="reject">打回</div>
  66. <div v-else-if="checkedQuestions.length === 0" @click="inspect">复核</div>
  67. <div v-else @click="reject">打回</div>
  68. </div>
  69. </div>
  70. </template>
  71. <script lang="ts">
  72. import { Question } from "@/types";
  73. import { computed, defineComponent, reactive, watch } from "vue";
  74. import { store } from "./store";
  75. export default defineComponent({
  76. name: "MarkBoardInspect",
  77. emits: ["inspect", "reject"],
  78. setup(props, { emit }) {
  79. let checkedQuestions = reactive([] as Array<Question>);
  80. watch(
  81. () => store.currentTask,
  82. () => {
  83. checkedQuestions.splice(0);
  84. }
  85. );
  86. const groups = computed(() => {
  87. const gs = store.currentTask?.questionList.map((q) => q.groupNumber);
  88. return [...new Set(gs)].sort((a, b) => a - b);
  89. });
  90. const questions = computed(() => {
  91. const qs = store.currentTask?.questionList;
  92. return qs;
  93. });
  94. const markerScore = computed(() =>
  95. questions.value?.map((q) => q.score || 0).reduce((acc, s) => acc + s)
  96. );
  97. function addToCheckedQuestion(question: Question) {
  98. checkedQuestions.push(question);
  99. }
  100. function removeCheckedQuestion(question: Question) {
  101. const idx = checkedQuestions.indexOf(question);
  102. checkedQuestions.splice(idx, 1);
  103. }
  104. function groupChecked(groupNumber: number) {
  105. return (
  106. checkedQuestions.filter((q) => q.groupNumber === groupNumber).length ===
  107. questions.value?.filter((q) => q.groupNumber === groupNumber).length
  108. );
  109. }
  110. function questionChecked(question: Question) {
  111. return checkedQuestions.includes(question);
  112. }
  113. function questionCheckChanged(question: Question) {
  114. const checked = questionChecked(question);
  115. if (checked) {
  116. removeCheckedQuestion(question);
  117. } else {
  118. addToCheckedQuestion(question);
  119. }
  120. }
  121. function groupClicked(groupNumber: number) {
  122. if (groupChecked(groupNumber)) {
  123. checkedQuestions
  124. .filter((q) => q.groupNumber === groupNumber)
  125. .forEach((q) => {
  126. const idx = checkedQuestions.indexOf(q);
  127. checkedQuestions.splice(idx, 1);
  128. });
  129. } else {
  130. questions.value
  131. ?.filter((q) => q.groupNumber === groupNumber)
  132. .forEach((q) => {
  133. if (!questionChecked(q)) checkedQuestions.push(q);
  134. });
  135. }
  136. }
  137. function addFocusTrack(
  138. groupNumber: number,
  139. mainNumber: number,
  140. subNumber: string
  141. ) {
  142. store.focusTracks.splice(0);
  143. if (groupNumber) {
  144. questions.value
  145. ?.filter((q) => q.groupNumber === groupNumber)
  146. ?.map((q) => q.trackList)
  147. .reduce((acc, ts) => acc.concat(ts))
  148. .forEach((t) => {
  149. store.focusTracks.push(t);
  150. });
  151. } else {
  152. questions.value
  153. ?.map((q) => q.trackList)
  154. .reduce((acc, ts) => acc.concat(ts))
  155. .filter((t) => {
  156. if (mainNumber) {
  157. return t.mainNumber === mainNumber && t.subNumber === subNumber;
  158. } else {
  159. return false;
  160. }
  161. })
  162. .forEach((t) => {
  163. store.focusTracks.push(t);
  164. });
  165. }
  166. // console.log(store.focusTracks);
  167. }
  168. function removeFocusTrack() {
  169. store.focusTracks.splice(0);
  170. }
  171. function reject() {
  172. emit("reject", checkedQuestions);
  173. }
  174. function inspect() {
  175. emit("inspect");
  176. }
  177. return {
  178. store,
  179. markerScore,
  180. groups,
  181. checkedQuestions,
  182. questions,
  183. groupChecked,
  184. questionChecked,
  185. questionCheckChanged,
  186. groupClicked,
  187. addFocusTrack,
  188. removeFocusTrack,
  189. reject,
  190. inspect,
  191. };
  192. },
  193. });
  194. </script>
  195. <style scoped>
  196. .mark-board-track-container {
  197. max-width: 250px;
  198. min-width: 250px;
  199. border-left: 1px solid grey;
  200. padding-left: 6px;
  201. padding-right: 6px;
  202. }
  203. .question {
  204. min-width: 100px;
  205. border: 1px solid grey;
  206. }
  207. .current-question {
  208. border: 1px solid yellowgreen;
  209. background-color: lightblue;
  210. }
  211. .single-score {
  212. width: 30px;
  213. height: 30px;
  214. display: grid;
  215. place-content: center;
  216. border: 1px solid black;
  217. border-radius: 5px;
  218. }
  219. .current-score {
  220. border: 1px solid yellowgreen;
  221. background-color: lightblue;
  222. }
  223. </style>