CommonMarkHeader.vue 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. <template>
  2. <div
  3. v-if="store.setting"
  4. class="tw-flex tw-gap-4 tw-justify-start tw-items-center header-container"
  5. >
  6. <div
  7. v-if="!isSingleStudent"
  8. class="tw-flex tw-place-content-center tw-cursor-pointer tw-relative menu"
  9. style="margin-right: -16px"
  10. :class="[store.historyOpen && 'menu-toggled']"
  11. @click="store.toggleHistory"
  12. >
  13. <span title="回看" class="tw-inline-flex tw-place-content-center">
  14. <img
  15. src="../features/mark/images/left-menu.svg"
  16. :class="[store.historyOpen && 'svg-red']"
  17. />
  18. </span>
  19. <div v-if="store.historyOpen" class="triangle"></div>
  20. </div>
  21. <div
  22. class="tw-text-white tw-block tw-overflow-ellipsis tw-overflow-hidden tw-whitespace-nowrap header-big-text tw-ml-4"
  23. >
  24. {{
  25. `${store.setting.subject?.code ?? ""}-${
  26. store.setting.subject?.name ?? ""
  27. }`
  28. }}
  29. </div>
  30. <div class="tw-flex tw-gap-1">
  31. <slot name="taskInfo">
  32. <div>
  33. <span class="header-small-text">编号</span>
  34. <span class="highlight-text">
  35. {{ store.currentTask?.secretNumber ?? "-" }}
  36. </span>
  37. </div>
  38. </slot>
  39. </div>
  40. <div
  41. v-if="!isSingleStudent"
  42. class="tw-flex tw-gap-2 tw-items-center tw-flex-1"
  43. >
  44. <slot />
  45. </div>
  46. <div class="tw-flex-1"></div>
  47. <a-popover
  48. v-if="store.isScanImage"
  49. title="小助手"
  50. trigger="hover"
  51. class="tw-cursor-pointer tw-flex tw-gap-2 tw-items-center"
  52. >
  53. <template #content>
  54. <table class="assistant-table">
  55. <tr v-if="store.setting.subject.paperUrl && showPaperAndAnswer">
  56. <td>试卷</td>
  57. <td>
  58. <a-switch
  59. v-model:checked="store.setting.uiSetting['paper.modal']"
  60. />
  61. </td>
  62. </tr>
  63. <tr v-if="store.setting.subject.answerUrl && showPaperAndAnswer">
  64. <td>答案</td>
  65. <td>
  66. <a-switch
  67. v-model:checked="store.setting.uiSetting['answer.modal']"
  68. />
  69. </td>
  70. </tr>
  71. <tr>
  72. <td>缩略图</td>
  73. <td>
  74. <a-switch
  75. v-model:checked="store.setting.uiSetting['minimap.modal']"
  76. />
  77. </td>
  78. </tr>
  79. <tr v-if="store.isScanImage">
  80. <td>分数/标记大小</td>
  81. <td>
  82. <a-slider
  83. v-model:value="store.setting.uiSetting['score.fontSize.scale']"
  84. :min="0.5"
  85. :step="0.1"
  86. :max="2"
  87. style="margin: 0"
  88. />
  89. </td>
  90. </tr>
  91. </table>
  92. </template>
  93. <div class="tw-flex">
  94. 小助手
  95. <DownOutlined
  96. style="font-size: 12px; display: inline-block"
  97. class="tw-self-center tw-ml-1"
  98. />
  99. </div>
  100. </a-popover>
  101. <div class="tw-flex tw-cursor-pointer tw-items-center tw-flex-1">
  102. <div
  103. v-if="store.setting.groupNumber !== -987654"
  104. class="tw-overflow-ellipsis tw-overflow-hidden tw-whitespace-nowrap tw-mr-1"
  105. >
  106. <span class="header-small-text">分组</span>
  107. <span class="highlight-text">
  108. {{ store.setting.groupNumber }}
  109. </span>
  110. </div>
  111. </div>
  112. <div class="tw-flex tw-place-items-center">
  113. <UserOutlined class="icon-font icon-with-text" />{{
  114. store.setting.userName
  115. }}
  116. </div>
  117. <div
  118. class="tw-flex tw-place-items-center tw-cursor-pointer tw-pr-4"
  119. @click="closeWindow"
  120. >
  121. <PoweroffOutlined class="icon-font icon-with-text" />关闭
  122. </div>
  123. <div
  124. v-if="showScoreBoard"
  125. class="tw-flex tw-place-content-center tw-cursor-pointer tw-justify-self-end menu"
  126. :class="[
  127. store.isScoreBoardVisible && store.currentTask && 'menu-toggled',
  128. ]"
  129. style="margin-left: -16px"
  130. @click="store.toggleScoreBoard"
  131. >
  132. <span
  133. title="给分板"
  134. class="tw-inline-flex tw-place-content-center tw-relative"
  135. >
  136. <img
  137. src="../features/mark/images/right-menu.svg"
  138. :class="[store.isScoreBoardVisible && 'svg-red']"
  139. />
  140. </span>
  141. <div
  142. v-if="store.isScoreBoardVisible && store.currentTask"
  143. class="triangle"
  144. ></div>
  145. </div>
  146. </div>
  147. </template>
  148. <script setup lang="ts">
  149. import { onMounted } from "vue";
  150. import { store } from "@/store/store";
  151. import {
  152. UserOutlined,
  153. PoweroffOutlined,
  154. DownOutlined,
  155. } from "@ant-design/icons-vue";
  156. import { AxiosResponse } from "axios";
  157. const {
  158. isSingleStudent = true,
  159. clearTasks,
  160. showPaperAndAnswer = false,
  161. showScoreBoard = false,
  162. } = defineProps<{
  163. isSingleStudent?: boolean;
  164. clearTasks?: () => Promise<AxiosResponse<void, any>>;
  165. showPaperAndAnswer?: boolean;
  166. showScoreBoard?: boolean;
  167. }>();
  168. async function updateClearTask() {
  169. clearTasks && (await clearTasks());
  170. }
  171. const closeWindow = async () => {
  172. await updateClearTask();
  173. window.close();
  174. };
  175. onMounted(() => {
  176. // 不确定是否一定能在关闭页面时调用
  177. window.addEventListener("beforeunload", () => {
  178. updateClearTask().catch((e) => console.log(e));
  179. });
  180. });
  181. </script>
  182. <style scoped>
  183. .header-container {
  184. position: relative;
  185. height: 56px;
  186. line-height: 16px;
  187. background-color: var(--header-bg-color);
  188. color: rgba(255, 255, 255, 0.5);
  189. }
  190. .menu {
  191. width: 56px;
  192. height: 56px;
  193. padding: 20px;
  194. }
  195. .menu:hover,
  196. .menu-toggled {
  197. background-color: rgba(255, 255, 255, 0.2);
  198. }
  199. .header-container :deep(span) {
  200. vertical-align: middle;
  201. }
  202. .header-big-text {
  203. font-size: 20px;
  204. line-height: 30px;
  205. }
  206. .header-small-text {
  207. font-size: var(--app-secondary-font-size);
  208. }
  209. .highlight-text {
  210. color: white;
  211. font-size: var(--app-title-font-size);
  212. }
  213. .assistant-table {
  214. z-index: 5500;
  215. border-collapse: separate;
  216. border-spacing: 0 1em;
  217. color: var(--app-bold-text-color);
  218. width: 240px;
  219. }
  220. .assistant-table tr td:nth-child(2) {
  221. text-align: right;
  222. }
  223. .svg-red {
  224. filter: invert(27%) sepia(51%) saturate(2878%) hue-rotate(346deg)
  225. brightness(104%) contrast(97%);
  226. }
  227. .triangle {
  228. background-color: white;
  229. width: 10px;
  230. height: 10px;
  231. clip-path: polygon(0 100%, 100% 100%, 50% 0);
  232. position: absolute;
  233. bottom: -2px;
  234. }
  235. </style>