MarkHistory.vue 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. <template>
  2. <div
  3. :style="{ display: store.historyOpen ? 'block' : 'none' }"
  4. class="history-container tw-px-1"
  5. >
  6. <div class="tw-p-1 tw-flex tw-justify-between tw-place-items-center">
  7. <div class="tw-text-xl">回评</div>
  8. <a-button
  9. class="tw-content-end"
  10. shape="circle"
  11. @click="store.historyOpen = false"
  12. >
  13. <template #icon><CloseOutlined /></template>
  14. </a-button>
  15. </div>
  16. <div class="tw-mt-1 tw-mb-1 tw-flex">
  17. <input
  18. :value="secretNumberInput"
  19. @input="updateSecretNumber"
  20. type="text"
  21. placeholder="查找试卷"
  22. class="
  23. tw-w-full
  24. tw-rounded
  25. tw-h-8
  26. tw-border-solid
  27. tw-border-gray-400
  28. tw-border-2
  29. tw-pl-1
  30. tw-pr-8
  31. "
  32. @keyup.enter="updateHistoryTask({ secretNumber: secretNumberInput })"
  33. />
  34. <SearchOutlined
  35. style="margin-left: -30px; font-size: 24px; padding: 3px"
  36. @click="updateHistoryTask({ secretNumber: secretNumberInput })"
  37. />
  38. </div>
  39. <div class="tw-flex tw-justify-between">
  40. <div class="tw-cursor-pointer tw-flex">编号</div>
  41. <div
  42. @click="toggleOrderBy('markerTime')"
  43. class="tw-cursor-pointer tw-flex"
  44. >
  45. 时间
  46. <CaretUpOutlined
  47. style="font-size: 20px"
  48. v-if="order === 'markerTime' && sort === 'ASC'"
  49. />
  50. <CaretDownOutlined
  51. style="font-size: 20px"
  52. v-if="order === 'markerTime' && sort === 'DESC'"
  53. />
  54. </div>
  55. <div
  56. @click="toggleOrderBy('markerScore')"
  57. class="tw-cursor-pointer tw-flex"
  58. >
  59. 分数
  60. <CaretUpOutlined
  61. style="font-size: 20px"
  62. v-if="order === 'markerScore' && sort === 'ASC'"
  63. />
  64. <CaretDownOutlined
  65. style="font-size: 20px"
  66. v-if="order === 'markerScore' && sort === 'DESC'"
  67. />
  68. </div>
  69. </div>
  70. <a-spin :spinning="loading" size="large" tip="Loading...">
  71. <div v-for="(task, index) of store.historyTasks" :key="index">
  72. <div
  73. @click="replaceCurrentTask(task)"
  74. class="
  75. tw-flex
  76. tw-justify-between
  77. tw-h-6
  78. tw-place-items-center
  79. tw-rounded
  80. tw-cursor-pointer
  81. "
  82. :class="store.currentTask === task && 'current-task'"
  83. >
  84. <div>{{ task.secretNumber }}</div>
  85. <div>
  86. {{ $filters.datetimeFilter(task.markTime) }}
  87. </div>
  88. <div style="width: 30px; text-align: center">
  89. {{ task.markerScore }}
  90. </div>
  91. </div>
  92. </div>
  93. </a-spin>
  94. <div class="tw-flex tw-justify-between tw-place-content-center tw-mt-2">
  95. <a-button @click="previousPage">上一页</a-button>
  96. <div style="line-height: 30px">第{{ currentPage }}页</div>
  97. <a-button @click="nextPage">下一页</a-button>
  98. </div>
  99. </div>
  100. </template>
  101. <script lang="ts">
  102. import { getHistoryTask } from "@/api/markPage";
  103. import { MarkHistoryOrderBy, MarkHistorySortField, Task } from "@/types";
  104. import { defineComponent, ref, watch, watchEffect } from "vue";
  105. import { store } from "./store";
  106. import {
  107. CloseOutlined,
  108. SearchOutlined,
  109. CaretDownOutlined,
  110. CaretUpOutlined,
  111. } from "@ant-design/icons-vue";
  112. import { cloneDeep, throttle } from "lodash";
  113. export default defineComponent({
  114. name: "MarkHistory",
  115. components: {
  116. CloseOutlined,
  117. SearchOutlined,
  118. CaretDownOutlined,
  119. CaretUpOutlined,
  120. },
  121. props: {
  122. shouldReload: { type: Number, required: true },
  123. },
  124. setup(props) {
  125. const secretNumberInput = ref("");
  126. const loading = ref(false);
  127. const currentPage = ref(1);
  128. const order = ref("markerTime" as MarkHistoryOrderBy);
  129. const sort = ref("DESC" as MarkHistorySortField);
  130. watchEffect(async () => {
  131. if (store.historyOpen) {
  132. replaceCurrentTask(undefined);
  133. await updateHistoryTask({
  134. secretNumber: secretNumberInput.value,
  135. order: order.value,
  136. sort: sort.value,
  137. pageNumber: currentPage.value,
  138. });
  139. replaceCurrentTask(store.historyTasks[0]);
  140. } else {
  141. replaceCurrentTask(store.tasks[0]);
  142. store.historyTasks.splice(0);
  143. }
  144. });
  145. watch(
  146. () => props.shouldReload,
  147. async () => {
  148. await updateHistoryTask({
  149. secretNumber: secretNumberInput.value,
  150. order: order.value,
  151. sort: sort.value,
  152. pageNumber: currentPage.value,
  153. });
  154. // 提交后,渲染第一条
  155. replaceCurrentTask(store.historyTasks[0]);
  156. }
  157. );
  158. async function updateHistoryTask({
  159. pageNumber = 1,
  160. pageSize = 10,
  161. order = "markerTime",
  162. sort = "DESC",
  163. secretNumber = null,
  164. }: {
  165. pageNumber?: number; // 从1开始
  166. pageSize?: number;
  167. order?: MarkHistoryOrderBy;
  168. sort?: MarkHistorySortField;
  169. secretNumber?: string | null;
  170. }) {
  171. loading.value = true;
  172. const res = await getHistoryTask({
  173. pageNumber,
  174. pageSize,
  175. order,
  176. sort,
  177. secretNumber,
  178. });
  179. loading.value = false;
  180. if (res.data) {
  181. let data = cloneDeep(res.data) as Array<Task>;
  182. data = data.map((t) => {
  183. t.questionList.map((q) => {
  184. q.__origScore = q.score;
  185. return q;
  186. });
  187. t.sliceUrls = t.sliceUrls.map((s) => store.setting.fileServer + s);
  188. t.sheetUrls = t.sheetUrls?.map((s) => store.setting.fileServer + s);
  189. t.jsonUrl = store.setting.fileServer + t.jsonUrl;
  190. return t;
  191. });
  192. store.historyTasks = data;
  193. replaceCurrentTask(store.historyTasks[0]);
  194. }
  195. }
  196. function replaceCurrentTask(task: Task | undefined) {
  197. if (task) {
  198. task.questionList = task.questionList.map((q) => {
  199. if (typeof q.__origScore !== "undefined") {
  200. // 如果是回评的任务,则将旧分数还原
  201. q.score = q.__origScore;
  202. }
  203. return q;
  204. });
  205. }
  206. store.currentTask = task;
  207. }
  208. function previousPage() {
  209. if (currentPage.value > 1) {
  210. currentPage.value -= 1;
  211. // updateHistoryTask({
  212. // order: order.value,
  213. // sort: sort.value,
  214. // pageNumber: currentPage.value,
  215. // });
  216. }
  217. }
  218. function nextPage() {
  219. if (store.historyTasks.length >= 10) {
  220. currentPage.value += 1;
  221. // updateHistoryTask({
  222. // // order: order.value,
  223. // // sort: sort.value,
  224. // pageNumber: currentPage.value,
  225. // });
  226. }
  227. }
  228. function toggleOrderBy(toOrder: MarkHistoryOrderBy) {
  229. if (toOrder === order.value) {
  230. sort.value = sort.value === "DESC" ? "ASC" : "DESC";
  231. } else {
  232. order.value = toOrder;
  233. }
  234. }
  235. function _updateSecretNumber(event: InputEvent) {
  236. const inputEle = event.target as HTMLInputElement;
  237. secretNumberInput.value = inputEle.value ?? "";
  238. }
  239. const updateSecretNumber = throttle(_updateSecretNumber, 1500);
  240. return {
  241. store,
  242. loading,
  243. secretNumberInput,
  244. updateHistoryTask,
  245. replaceCurrentTask,
  246. currentPage,
  247. previousPage,
  248. nextPage,
  249. sort,
  250. order,
  251. toggleOrderBy,
  252. updateSecretNumber,
  253. };
  254. },
  255. });
  256. </script>
  257. <style scoped>
  258. .history-container {
  259. min-width: 250px;
  260. border-right: 1px solid grey;
  261. }
  262. .current-task {
  263. background-color: aqua;
  264. }
  265. </style>