MarkBoardMouse.vue 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. <template>
  2. <div
  3. v-if="store.setting.uiSetting['score.board.collapse']"
  4. @mouseover="handleMouseOverWithBoard"
  5. >
  6. <div
  7. class="tw-self-start tw-cursor-pointer tw-pb-10"
  8. @mouseover.stop="() => true"
  9. >
  10. <a-switch
  11. v-model:checked="store.setting.uiSetting['score.board.collapse']"
  12. />
  13. </div>
  14. </div>
  15. <div
  16. v-if="store.currentTask"
  17. class="mark-board-track-container"
  18. :class="store.setting.uiSetting['score.board.collapse'] && 'hide-board'"
  19. @mouseover="handleMouseOverWithBoard"
  20. @mouseout="handleMouseOutWithBoard"
  21. >
  22. <div class="tw-my-2 tw-flex">
  23. <div
  24. class="tw-self-start tw-cursor-pointer hover:tw-bg-gray-200 tw-mr-20"
  25. >
  26. <a-switch
  27. v-model:checked="store.setting.uiSetting['score.board.collapse']"
  28. />
  29. </div>
  30. <a-dropdown class="tw-self-end">
  31. <template #overlay>
  32. <a-menu>
  33. <a-menu-item key="1" @click="toggleKeyMouse">
  34. 键盘给分
  35. </a-menu-item>
  36. </a-menu>
  37. </template>
  38. <a-button>
  39. 鼠标给分
  40. <DownOutlined style="display: inline-flex" />
  41. </a-button>
  42. </a-dropdown>
  43. </div>
  44. <div>
  45. <h1 class="tw-text-3xl tw-text-center">
  46. 总分:{{ store.currentMarkResult?.markerScore || 0 }}
  47. </h1>
  48. </div>
  49. <div class="tw-flex tw-place-content-center tw-mb-2">
  50. <a-popconfirm
  51. v-if="!store.setting.enableAllZero"
  52. title="确定给全零分?"
  53. ok-text="确定"
  54. cancel-text="取消"
  55. @confirm="$emit('allZeroSubmit')"
  56. >
  57. <a-button
  58. type="primary"
  59. shape="round"
  60. size="large"
  61. style="margin-right: 20px !important"
  62. >
  63. 全零分
  64. </a-button>
  65. </a-popconfirm>
  66. <qm-button type="primary" shape="round" size="large" @click="submit">
  67. 提交
  68. </qm-button>
  69. </div>
  70. <div v-if="store.currentTask && store.currentTask.questionList">
  71. <template
  72. v-for="(question, index) in store.currentTask?.questionList"
  73. :key="index"
  74. >
  75. <div class="question tw-rounded tw-p-1 tw-mb-2">
  76. <div>
  77. <div>
  78. {{ question.title }} {{ question.mainNumber }}-{{
  79. question.subNumber
  80. }}
  81. </div>
  82. <div class="tw-flex tw-flex-wrap tw-gap-1">
  83. <div
  84. v-for="(s, i) in questionScoreSteps(question)"
  85. :key="i"
  86. @click="chooseScore(question, s)"
  87. class="single-score"
  88. :class="isCurrentScore(question, s) && 'current-score'"
  89. >
  90. {{ s }}
  91. </div>
  92. </div>
  93. </div>
  94. </div>
  95. </template>
  96. </div>
  97. </div>
  98. </template>
  99. <script lang="ts">
  100. import { Question } from "@/types";
  101. import { isNumber } from "lodash";
  102. import { defineComponent, watch } from "vue";
  103. import { store } from "./store";
  104. import { keyMouse } from "./use/keyboardAndMouse";
  105. import { message } from "ant-design-vue";
  106. import { DownOutlined } from "@ant-design/icons-vue";
  107. export default defineComponent({
  108. name: "MarkBoardMouse",
  109. emits: ["submit", "allZeroSubmit"],
  110. components: { DownOutlined },
  111. setup(props, { emit }) {
  112. const { toggleKeyMouse } = keyMouse();
  113. function chooseScore(question: Question, score: number) {
  114. store.currentQuestion = question;
  115. store.currentQuestion.score = score;
  116. }
  117. function isCurrentScore(question: Question, score: number) {
  118. return question.score === score;
  119. }
  120. function questionScoreSteps(question: Question) {
  121. if (!question) return [];
  122. const remainScore = Math.round(question.maxScore * 100) / 100;
  123. const steps = [];
  124. for (
  125. let i = 0;
  126. i <= remainScore;
  127. i = Math.round(i * 100 + question.intervalScore * 100) / 100
  128. ) {
  129. steps.push(i);
  130. }
  131. if (
  132. Math.round(remainScore * 100) %
  133. Math.round(question.intervalScore * 100) !==
  134. 0
  135. ) {
  136. steps.push(remainScore);
  137. }
  138. return steps;
  139. }
  140. const collapseSideBar = () => {
  141. store.setting.uiSetting["score.board.collapse"] = !!!store.setting
  142. .uiSetting["score.board.collapse"];
  143. };
  144. const handleMouseOverWithBoard = () => {
  145. if (store.setting.uiSetting["score.board.collapse"]) {
  146. const container = document.querySelector(".mark-board-track-container");
  147. if (container) {
  148. container.classList.add("show-board");
  149. }
  150. }
  151. };
  152. const handleMouseOutWithBoard = () => {
  153. if (store.setting.uiSetting["score.board.collapse"]) {
  154. const container = document.querySelector(".mark-board-track-container");
  155. if (container) {
  156. container.classList.remove("show-board");
  157. }
  158. }
  159. };
  160. function submit() {
  161. const errors: any = [];
  162. store.currentTask?.questionList.forEach((question, index) => {
  163. if (!isNumber(question.score)) {
  164. errors.push({
  165. question,
  166. index,
  167. error: `${question.mainNumber}-${question.subNumber} 没有赋分不能提交。`,
  168. });
  169. }
  170. });
  171. if (errors.length === 0) {
  172. emit("submit");
  173. } else {
  174. console.log(errors);
  175. message.error({
  176. content: errors.map((e: any) => `${e.error}`).join("\n"),
  177. duration: 10,
  178. });
  179. }
  180. }
  181. return {
  182. store,
  183. collapseSideBar,
  184. handleMouseOverWithBoard,
  185. handleMouseOutWithBoard,
  186. toggleKeyMouse,
  187. questionScoreSteps,
  188. chooseScore,
  189. isCurrentScore,
  190. submit,
  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. max-height: calc(100vh - 41px);
  203. overflow: scroll;
  204. }
  205. .hide-board {
  206. margin-right: -250px;
  207. }
  208. .show-board {
  209. position: absolute;
  210. background-color: white;
  211. right: 250px;
  212. }
  213. .question {
  214. min-width: 80px;
  215. border: 1px solid grey;
  216. }
  217. .single-score {
  218. width: 29px;
  219. height: 29px;
  220. display: grid;
  221. place-content: center;
  222. border: 1px solid black;
  223. border-radius: 5px;
  224. }
  225. .current-score {
  226. border: 1px solid yellowgreen;
  227. background-color: lightblue;
  228. }
  229. </style>