2
0

MarkHeader.vue 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. <template>
  2. <div
  3. class="tw-flex tw-gap-4 tw-justify-between tw-items-center header-container"
  4. v-if="store.setting"
  5. >
  6. <div>
  7. <a class="tw-text-white tw-underline" href="/mark/subject-select">{{
  8. store.setting.subject.name
  9. }}</a>
  10. </div>
  11. <div v-if="store.setting.statusValue === 'TRIAL'">试评</div>
  12. <div class="tw-flex tw-gap-1">
  13. <div>
  14. 编号<span class="highlight-text">{{
  15. store.currentTask?.secretNumber
  16. }}</span>
  17. </div>
  18. <div
  19. v-if="store.currentTask && store.currentTask.objectiveScore !== null"
  20. >
  21. 客观分<span class="highlight-text">{{
  22. store.currentTask.objectiveScore
  23. }}</span>
  24. </div>
  25. </div>
  26. <ul class="tw-flex tw-gap-2 tw-mb-0">
  27. <li>
  28. 已评<span class="highlight-text">{{ store.status.markedCount }}</span>
  29. </li>
  30. <li v-if="store.setting.topCount">
  31. 分配<span class="highlight-text">{{ store.setting.topCount }}</span>
  32. </li>
  33. <li>
  34. 未评<span class="highlight-text">{{
  35. store.status.totalCount - store.status.markedCount
  36. }}</span>
  37. </li>
  38. <li
  39. :title="`问题卷${store.status.problemCount}\n待仲裁${store.status.arbitrateCount}`"
  40. class="line-height-20"
  41. >
  42. <QuestionCircleOutlined class="icon-font-size-20" />
  43. </li>
  44. <li>
  45. 进度<span class="highlight-text">{{ progress }}%</span>
  46. </li>
  47. </ul>
  48. <ul class="tw-flex tw-gap-2 tw-mb-0">
  49. <li @click="upScale" title="放大" class="line-height-20">
  50. <PlusCircleOutlined
  51. class="icon-font-size-20"
  52. :style="{
  53. color: greaterThanOneScale ? 'red' : 'white',
  54. }"
  55. />
  56. </li>
  57. <li @click="downScale" title="缩小" class="line-height-20">
  58. <MinusCircleOutlined
  59. class="icon-font-size-20"
  60. :style="{
  61. color: lessThanOneScale ? 'red' : 'white',
  62. }"
  63. />
  64. </li>
  65. <li @click="normalScale" title="适应" class="line-height-20">
  66. <FullscreenOutlined class="icon-font-size-20" />
  67. </li>
  68. </ul>
  69. <div @click="toggleSettingMode" class="line-height-20">
  70. {{ modeName }} {{ store.setting.forceMode ? "" : "(切换)" }}
  71. </div>
  72. <div @click="toggleHistory" class="line-height-20" title="回看">
  73. <HistoryOutlined class="icon-font-size-20" />
  74. </div>
  75. <div
  76. class="tw-flex tw-place-items-center"
  77. :title="
  78. '评卷时间段:' +
  79. $filters.datetimeFilter(store.setting.startTime) +
  80. ' ~ ' +
  81. $filters.datetimeFilter(store.setting.startTime)
  82. "
  83. >
  84. <ClockCircleOutlined class="icon-font-size-20 line-height-20" />
  85. </div>
  86. <div @click="switchGroupDialog">{{ group?.title }}(切换)</div>
  87. <div class="tw-flex tw-place-items-center">
  88. <UserOutlined class="icon-with-text" />{{ store.setting.userName }}
  89. </div>
  90. <div class="tw-flex tw-place-items-center">
  91. <PoweroffOutlined class="icon-with-text" />退出
  92. </div>
  93. </div>
  94. </template>
  95. <script lang="ts">
  96. import { getGroups, getHistoryTask } from "@/api/markPage";
  97. import { computed, defineComponent } from "vue";
  98. import { store } from "./store";
  99. import {
  100. PlusCircleOutlined,
  101. MinusCircleOutlined,
  102. FullscreenOutlined,
  103. HistoryOutlined,
  104. UserOutlined,
  105. PoweroffOutlined,
  106. ClockCircleOutlined,
  107. QuestionCircleOutlined,
  108. } from "@ant-design/icons-vue";
  109. import { ModeEnum } from "@/types";
  110. export default defineComponent({
  111. name: "MarkHeader",
  112. components: {
  113. PlusCircleOutlined,
  114. MinusCircleOutlined,
  115. FullscreenOutlined,
  116. HistoryOutlined,
  117. UserOutlined,
  118. PoweroffOutlined,
  119. ClockCircleOutlined,
  120. QuestionCircleOutlined,
  121. },
  122. setup() {
  123. const modeName = computed(() =>
  124. store.setting.mode === ModeEnum.TRACK ? "轨迹模式" : "普通模式"
  125. );
  126. function toggleSettingMode() {
  127. if (store.setting.mode === ModeEnum.TRACK) {
  128. store.setting.mode = ModeEnum.COMMON;
  129. } else {
  130. store.setting.mode = ModeEnum.TRACK;
  131. }
  132. if (store.currentMarkResult) {
  133. store.currentMarkResult.scoreList = [];
  134. store.currentMarkResult.trackList = [];
  135. }
  136. if (store.currentTask) {
  137. store.currentTask.questionList.forEach((q) => (q.score = null));
  138. }
  139. store.currentQuestion = undefined;
  140. store.currentScore = undefined;
  141. }
  142. const progress = computed(() => {
  143. const { totalCount, markedCount } = store.status;
  144. if (totalCount <= 0) return 0;
  145. let p = markedCount / totalCount;
  146. if (p < 0.01 && markedCount >= 1) p = 0.01;
  147. p = Math.floor(p * 100);
  148. return p;
  149. });
  150. const group = computed(() => {
  151. return store.groups.find((g) => g.number === store.setting.groupNumber);
  152. });
  153. const upScale = () => {
  154. const s = store.setting.uiSetting["answer.paper.scale"];
  155. if (s < 3)
  156. store.setting.uiSetting["answer.paper.scale"] = +(s + 0.2).toFixed(1);
  157. };
  158. const downScale = () => {
  159. const s = store.setting.uiSetting["answer.paper.scale"];
  160. if (s > 0.2)
  161. store.setting.uiSetting["answer.paper.scale"] = +(s - 0.2).toFixed(1);
  162. };
  163. const normalScale = () => {
  164. store.setting.uiSetting["answer.paper.scale"] = 1;
  165. };
  166. const toggleHistory = () => {
  167. store.historyOpen = !store.historyOpen;
  168. };
  169. const greaterThanOneScale = computed(() => {
  170. return store.setting.uiSetting["answer.paper.scale"] > 1;
  171. });
  172. const lessThanOneScale = computed(() => {
  173. return store.setting.uiSetting["answer.paper.scale"] < 1;
  174. });
  175. async function switchGroupDialog() {
  176. const groups = await getGroups();
  177. console.log(groups);
  178. }
  179. async function updateHistoryTask({
  180. pageNumber = 1,
  181. pageSize = 10,
  182. order = "markerTime",
  183. sort = "DESC",
  184. secretNumber = null,
  185. }: {
  186. pageNumber: number; // 从1开始
  187. pageSize: number;
  188. order: "markerTime" | "markerScore";
  189. sort: "ASC" | "DESC";
  190. secretNumber: string | null;
  191. }) {
  192. const res = await getHistoryTask({
  193. pageNumber,
  194. pageSize,
  195. order,
  196. sort,
  197. secretNumber,
  198. });
  199. if (res.data) {
  200. store.historyTasks.push(res.data);
  201. }
  202. }
  203. return {
  204. store,
  205. modeName,
  206. toggleSettingMode,
  207. progress,
  208. group,
  209. upScale,
  210. downScale,
  211. normalScale,
  212. greaterThanOneScale,
  213. lessThanOneScale,
  214. updateHistoryTask,
  215. toggleHistory,
  216. switchGroupDialog,
  217. };
  218. },
  219. });
  220. </script>
  221. <style scoped>
  222. .header-container {
  223. z-index: 10000;
  224. position: relative;
  225. font-size: 16px;
  226. height: 40px;
  227. background-color: #5d6d7d;
  228. color: white;
  229. }
  230. .highlight-text {
  231. color: #ffe400;
  232. }
  233. .icon-font-size-20 {
  234. font-size: 20px;
  235. }
  236. .line-height-20 {
  237. line-height: 20px;
  238. }
  239. .icon-with-text {
  240. font-size: 18px;
  241. line-height: 18px;
  242. }
  243. </style>