MarkHistory.vue 7.1 KB

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