فهرست منبع

script setup refactor step done

Michael Wang 4 سال پیش
والد
کامیت
4251a33e03

+ 0 - 12
src/components/404.vue

@@ -1,15 +1,3 @@
 <template>
 <template>
   <div class="tw-text-center tw-text-3xl">页面没找到(404)</div>
   <div class="tw-text-center tw-text-3xl">页面没找到(404)</div>
 </template>
 </template>
-
-<script lang="ts">
-import { defineComponent } from "vue";
-
-export default defineComponent({
-  setup() {
-    return {};
-  },
-});
-</script>
-
-<style scoped></style>

+ 4 - 2
src/components/QmButton.vue

@@ -6,7 +6,7 @@
   </a-button>
   </a-button>
 </template>
 </template>
 
 
-<script>
+<script lang="ts">
 import { reactive, ref } from "@vue/reactivity";
 import { reactive, ref } from "@vue/reactivity";
 
 
 // 默认loading一秒,以免重复点击
 // 默认loading一秒,以免重复点击
@@ -16,14 +16,16 @@ export default {
   props: {
   props: {
     clickTimeout: { type: Number, required: false, default: 1000 },
     clickTimeout: { type: Number, required: false, default: 1000 },
   },
   },
+  // @ts-ignore
   setup(props, { attrs }) {
   setup(props, { attrs }) {
     let newAttrs = reactive({});
     let newAttrs = reactive({});
     Object.assign(newAttrs, attrs);
     Object.assign(newAttrs, attrs);
     let parentOnClick = attrs.onClick;
     let parentOnClick = attrs.onClick;
+    // @ts-ignore
     delete newAttrs["onClick"];
     delete newAttrs["onClick"];
 
 
     let inInterval = ref(false);
     let inInterval = ref(false);
-    const insideClick = (e) => {
+    const insideClick = (e: MouseEvent) => {
       inInterval.value = true;
       inInterval.value = true;
       setTimeout(() => (inInterval.value = false), props.clickTimeout);
       setTimeout(() => (inInterval.value = false), props.clickTimeout);
       parentOnClick(e);
       parentOnClick(e);

+ 161 - 206
src/features/arbitrate/Arbitrate.vue

@@ -20,8 +20,8 @@
   <MinimapModal />
   <MinimapModal />
 </template>
 </template>
 
 
-<script lang="ts">
-import { computed, defineComponent, onMounted, ref, watch } from "vue";
+<script setup lang="ts">
+import { computed, onMounted, ref, watch } from "vue";
 // 要共用UI就要共用store
 // 要共用UI就要共用store
 import {
 import {
   findCurrentTaskMarkResult,
   findCurrentTaskMarkResult,
@@ -46,230 +46,185 @@ import {
   saveArbitrateTask,
   saveArbitrateTask,
 } from "@/api/arbitratePage";
 } from "@/api/arbitratePage";
 import ArbitrateMarkList from "./ArbitrateMarkList.vue";
 import ArbitrateMarkList from "./ArbitrateMarkList.vue";
-import { Setting, Task } from "@/types";
+import type { Setting, Task } from "@/types";
 import { isNumber } from "lodash";
 import { isNumber } from "lodash";
 import AnswerModal from "../mark/AnswerModal.vue";
 import AnswerModal from "../mark/AnswerModal.vue";
 import PaperModal from "../mark/PaperModal.vue";
 import PaperModal from "../mark/PaperModal.vue";
 
 
-export default defineComponent({
-  name: "Arbitrate",
-  components: {
-    MarkHeader,
-    MarkBody,
-    MarkHistory,
-    MarkBoardKeyBoard,
-    MarkBoardMouse,
-    ArbitrateMarkList,
-    MinimapModal,
-    AnswerModal,
-    PaperModal,
-  },
-  setup: () => {
-    const route = useRoute();
-    let isSingleStudent = !!route.query.historyId;
-    const {
-      subjectCode,
-      groupNumber,
-      historyId: libraryId,
-    } = route.query as {
-      subjectCode: string;
-      groupNumber: string;
-      historyId: string;
-    };
-
-    async function updateClearTask() {
-      await clearArbitrateTask(libraryId, subjectCode);
-    }
-
-    async function updateSetting() {
-      const settingRes = await getArbitrateSetting(
-        libraryId,
-        subjectCode,
-        groupNumber
-      );
-      store.setting.fileServer = settingRes.data.fileServer;
-      store.setting.userName = settingRes.data.userName;
-      store.setting.uiSetting = {
-        "answer.paper.scale": 1,
-        "score.board.collapse": false,
-        "normal.mode": "keyboard",
-      } as Setting["uiSetting"];
-      store.setting.splitConfig = settingRes.data.splitConfig;
-      store.setting.subject = settingRes.data.subject;
-      if (store.setting.subject?.answerUrl) {
-        store.setting.subject.answerUrl =
-          store.setting.fileServer + store.setting.subject?.answerUrl;
-      }
-      if (store.setting.subject?.paperUrl) {
-        store.setting.subject.paperUrl =
-          store.setting.fileServer + store.setting.subject?.paperUrl;
-      }
-    }
-    async function updateStatus() {
-      const res = await getArbitrateTaskStatus(subjectCode, groupNumber);
-      if (res.data.valid) store.status = res.data;
-    }
-    async function updateTask() {
-      // const mkey = "fetch_task_key";
-      message.info({ content: "获取任务中...", duration: 2 });
-      let res;
-      if (isSingleStudent) {
-        res = await getSingleStuTask();
-      } else {
-        res = await getOneOfStuTask();
-      }
-      // message.success({ content: "获取成功", key: mkey });
-
-      if (res.data.libraryId) {
-        let rawTask = res.data as Task;
-        rawTask.sliceUrls = rawTask.sliceUrls.map(
-          (s) => store.setting.fileServer + s
-        );
-        rawTask.sheetUrls = rawTask.sheetUrls?.map(
-          (s) => store.setting.fileServer + s
-        );
-        rawTask.jsonUrl = store.setting.fileServer + rawTask.jsonUrl;
-        store.currentTask = res.data;
-        // if (store.currentTask)
-        //   store.setting.subject = store.currentTask.subject;
-      } else {
-        store.message = res.data.message;
-      }
-    }
-
-    const shouldReloadHistory = ref(0);
-
-    async function reloadAndfetchTask() {
-      // 需要清除缓存,才能取到之前锁定的任务
-      await updateClearTask();
-      // await updateSetting();
-      await fetchTask();
-    }
-
-    async function fetchTask() {
-      !isSingleStudent && (await updateStatus());
-      await updateTask();
-    }
+const route = useRoute();
+let isSingleStudent = !!route.query.historyId;
+const {
+  subjectCode,
+  groupNumber,
+  historyId: libraryId,
+} = route.query as {
+  subjectCode: string;
+  groupNumber: string;
+  historyId: string;
+};
+
+async function updateClearTask() {
+  await clearArbitrateTask(libraryId, subjectCode);
+}
 
 
-    const showMarkBoardKeyBoard = computed(() => {
-      return store.setting.uiSetting["normal.mode"] === "keyboard";
-    });
-    const showMarkBoardMouse = computed(() => {
-      return store.setting.uiSetting["normal.mode"] === "mouse";
-    });
+async function updateSetting() {
+  const settingRes = await getArbitrateSetting(
+    libraryId,
+    subjectCode,
+    groupNumber
+  );
+  store.setting.fileServer = settingRes.data.fileServer;
+  store.setting.userName = settingRes.data.userName;
+  store.setting.uiSetting = {
+    "answer.paper.scale": 1,
+    "score.board.collapse": false,
+    "normal.mode": "keyboard",
+  } as Setting["uiSetting"];
+  store.setting.splitConfig = settingRes.data.splitConfig;
+  store.setting.subject = settingRes.data.subject;
+  if (store.setting.subject?.answerUrl) {
+    store.setting.subject.answerUrl =
+      store.setting.fileServer + store.setting.subject?.answerUrl;
+  }
+  if (store.setting.subject?.paperUrl) {
+    store.setting.subject.paperUrl =
+      store.setting.fileServer + store.setting.subject?.paperUrl;
+  }
+}
+async function updateStatus() {
+  const res = await getArbitrateTaskStatus(subjectCode, groupNumber);
+  if (res.data.valid) store.status = res.data;
+}
+async function updateTask() {
+  // const mkey = "fetch_task_key";
+  message.info({ content: "获取任务中...", duration: 2 });
+  let res;
+  if (isSingleStudent) {
+    res = await getSingleStuTask();
+  } else {
+    res = await getOneOfStuTask();
+  }
+  // message.success({ content: "获取成功", key: mkey });
+
+  if (res.data.libraryId) {
+    let rawTask = res.data as Task;
+    rawTask.sliceUrls = rawTask.sliceUrls.map(
+      (s) => store.setting.fileServer + s
+    );
+    rawTask.sheetUrls = rawTask.sheetUrls?.map(
+      (s) => store.setting.fileServer + s
+    );
+    rawTask.jsonUrl = store.setting.fileServer + rawTask.jsonUrl;
+    store.currentTask = res.data;
+    // if (store.currentTask)
+    //   store.setting.subject = store.currentTask.subject;
+  } else {
+    store.message = res.data.message;
+  }
+}
 
 
-    onMounted(async () => {
-      await updateClearTask();
-      await updateSetting();
-      await fetchTask(); // mark-header 会调用 (watchEffect)
-    });
+const shouldReloadHistory = ref(0);
 
 
-    watch(
-      () => store.currentTask,
-      () => {
-        // 回评切换任务,先删除之前回评任务的markResult
-        removeOldPreviousMarkResult();
-        store.currentMarkResult = findCurrentTaskMarkResult();
+async function reloadAndfetchTask() {
+  // 需要清除缓存,才能取到之前锁定的任务
+  await updateClearTask();
+  // await updateSetting();
+  await fetchTask();
+}
 
 
-        // 重置当前选择的quesiton和score
-        store.currentQuestion = undefined;
-        store.currentScore = undefined;
-      }
-    );
+async function fetchTask() {
+  !isSingleStudent && (await updateStatus());
+  await updateTask();
+}
 
 
-    // FIXME: 更新分数,在评卷界面不需要
-    watch(
-      () => store.currentTask,
-      () => {
-        const markResult = store.currentMarkResult;
+const showMarkBoardKeyBoard = computed(() => {
+  return store.setting.uiSetting["normal.mode"] === "keyboard";
+});
+const showMarkBoardMouse = computed(() => {
+  return store.setting.uiSetting["normal.mode"] === "mouse";
+});
 
 
-        if (markResult && store.currentTask) {
-          const scoreList = store.currentTask.questionList.map((q) => q.score);
-          markResult.scoreList = [...(scoreList as number[])];
-          markResult.markerScore =
-            (
-              markResult.scoreList.filter((s) => isNumber(s)) as number[]
-            ).reduce((acc, v) => (acc += Math.round(v * 100)), 0) / 100;
-        }
-      },
-      { deep: true }
-    );
+onMounted(async () => {
+  await updateClearTask();
+  await updateSetting();
+  await fetchTask(); // mark-header 会调用 (watchEffect)
+});
 
 
-    async function getSingleStuTask() {
-      return getSingleArbitrateTask(libraryId);
+watch(
+  () => store.currentTask,
+  () => {
+    // 回评切换任务,先删除之前回评任务的markResult
+    removeOldPreviousMarkResult();
+    store.currentMarkResult = findCurrentTaskMarkResult();
+
+    // 重置当前选择的quesiton和score
+    store.currentQuestion = undefined;
+    store.currentScore = undefined;
+  }
+);
+
+// FIXME: 更新分数,在评卷界面不需要
+watch(
+  () => store.currentTask,
+  () => {
+    const markResult = store.currentMarkResult;
+
+    if (markResult && store.currentTask) {
+      const scoreList = store.currentTask.questionList.map((q) => q.score);
+      markResult.scoreList = [...(scoreList as number[])];
+      markResult.markerScore =
+        (markResult.scoreList.filter((s) => isNumber(s)) as number[]).reduce(
+          (acc, v) => (acc += Math.round(v * 100)),
+          0
+        ) / 100;
     }
     }
+  },
+  { deep: true }
+);
 
 
-    async function getOneOfStuTask() {
-      return getOneOfArbitrateTask(subjectCode, groupNumber);
-    }
+async function getSingleStuTask() {
+  return getSingleArbitrateTask(libraryId);
+}
 
 
-    const realStudentId = computed(
-      () =>
-        (isSingleStudent ? libraryId : store.currentTask?.libraryId) as string
-    );
-    const saveTaskToServer = async () => {
-      if (!store.currentTask) return;
-      console.log("save inspect task to server");
-      const mkey = "save_task_key";
-      message.loading({ content: "保存评卷任务...", key: mkey });
-      const res = (await saveArbitrateTask(
-        store.currentTask.libraryId + "",
-        store.currentTask.studentId + "",
-        store.currentMarkResult?.markerScore as number,
-        store.currentMarkResult?.scoreList as Array<number>
-      )) as any;
-      if (res.data.success && store.currentTask) {
-        message.success({ content: "仲裁成功", key: mkey, duration: 2 });
-        if (!store.historyOpen) {
-          store.currentTask = undefined;
-          if (!isSingleStudent) fetchTask();
-        } else {
-          shouldReloadHistory.value = Date.now();
-        }
-      } else if (res.data.message) {
-        console.log(res.data.message);
-        message.error({ content: res.data.message, key: mkey, duration: 10 });
-      } else if (!store.currentTask) {
-        message.warn({ content: "暂无新任务", key: mkey, duration: 10 });
-      }
-    };
+async function getOneOfStuTask() {
+  return getOneOfArbitrateTask(subjectCode, groupNumber);
+}
 
 
-    const renderError = () => {
+const saveTaskToServer = async () => {
+  if (!store.currentTask) return;
+  console.log("save inspect task to server");
+  const mkey = "save_task_key";
+  message.loading({ content: "保存评卷任务...", key: mkey });
+  const res = (await saveArbitrateTask(
+    store.currentTask.libraryId + "",
+    store.currentTask.studentId + "",
+    store.currentMarkResult?.markerScore as number,
+    store.currentMarkResult?.scoreList as Array<number>
+  )) as any;
+  if (res.data.success && store.currentTask) {
+    message.success({ content: "仲裁成功", key: mkey, duration: 2 });
+    if (!store.historyOpen) {
       store.currentTask = undefined;
       store.currentTask = undefined;
-      store.message = "加载失败,请重新加载。";
-    };
-
-    return {
-      store,
-      fetchTask,
-      reloadAndfetchTask,
-      showMarkBoardKeyBoard,
-      showMarkBoardMouse,
-      saveTaskToServer,
-      shouldReloadHistory,
-      renderError,
-    };
-  },
-});
+      if (!isSingleStudent) fetchTask();
+    } else {
+      shouldReloadHistory.value = Date.now();
+    }
+  } else if (res.data.message) {
+    console.log(res.data.message);
+    message.error({ content: res.data.message, key: mkey, duration: 10 });
+  } else if (!store.currentTask) {
+    message.warn({ content: "暂无新任务", key: mkey, duration: 10 });
+  }
+};
+
+const renderError = () => {
+  store.currentTask = undefined;
+  store.message = "加载失败,请重新加载。";
+};
 </script>
 </script>
 
 
 <style scoped>
 <style scoped>
 .my-container {
 .my-container {
   width: 100%;
   width: 100%;
 }
 }
-a {
-  color: #42b983;
-}
-
-label {
-  margin: 0 0.5em;
-  font-weight: bold;
-}
-
-code {
-  background-color: #eee;
-  padding: 2px 4px;
-  border-radius: 4px;
-  color: #304455;
-}
 </style>
 </style>

+ 17 - 24
src/features/arbitrate/ArbitrateMarkList.vue

@@ -28,8 +28,8 @@
   </div>
   </div>
 </template>
 </template>
 
 
-<script lang="ts">
-import { defineComponent, reactive, watch } from "vue";
+<script setup lang="ts">
+import { reactive, watch } from "vue";
 import { store } from "@/features/mark/store";
 import { store } from "@/features/mark/store";
 import { getArbitrateList } from "@/api/arbitratePage";
 import { getArbitrateList } from "@/api/arbitratePage";
 
 
@@ -40,29 +40,22 @@ interface MarkDetail {
   scoreList: string;
   scoreList: string;
 }
 }
 
 
-export default defineComponent({
-  name: "ArbitrateMarkList",
-  setup() {
-    let list = reactive([] as Array<MarkDetail>);
+let list = reactive([] as Array<MarkDetail>);
 
 
-    watch(
-      () => store.currentTask,
-      async () => {
-        if (store.currentTask) {
-          const res = await getArbitrateList(
-            store.currentTask?.libraryId as unknown as string
-          );
-          list.splice(0);
-          list.push(...res.data);
-        } else {
-          list.splice(0);
-        }
-      }
-    );
-
-    return { list };
-  },
-});
+watch(
+  () => store.currentTask,
+  async () => {
+    if (store.currentTask) {
+      const res = await getArbitrateList(
+        store.currentTask?.libraryId as unknown as string
+      );
+      list.splice(0);
+      list.push(...res.data);
+    } else {
+      list.splice(0);
+    }
+  }
+);
 </script>
 </script>
 
 
 <style scoped>
 <style scoped>

+ 4 - 10
src/features/arbitrate/MarkBody.vue

@@ -5,22 +5,16 @@
     :store="store"
     :store="store"
     uniquePropName="libraryId"
     uniquePropName="libraryId"
     @error="$emit('error')"
     @error="$emit('error')"
+    :makeTrack="() => {}"
   />
   />
 </template>
 </template>
 
 
-<script lang="ts">
+<script setup lang="ts">
 import CommonMarkBody from "@/features/mark/CommonMarkBody.vue";
 import CommonMarkBody from "@/features/mark/CommonMarkBody.vue";
-import { defineComponent, watch } from "vue";
 import { store } from "@/features/mark/store";
 import { store } from "@/features/mark/store";
+import { defineEmit } from "vue";
 
 
-export default defineComponent({
-  name: "MarkBody",
-  components: { CommonMarkBody },
-  emits: ["error"],
-  setup() {
-    return { store };
-  },
-});
+defineEmit(["error"]);
 </script>
 </script>
 
 
 <style scoped></style>
 <style scoped></style>

+ 47 - 77
src/features/arbitrate/MarkHeader.vue

@@ -115,8 +115,8 @@
   </div>
   </div>
 </template>
 </template>
 
 
-<script lang="ts">
-import { computed, defineComponent, onMounted, ref } from "vue";
+<script setup lang="ts">
+import { computed, onMounted } from "vue";
 import { store } from "@/features/mark/store";
 import { store } from "@/features/mark/store";
 import {
 import {
   ZoomInOutlined,
   ZoomInOutlined,
@@ -125,90 +125,60 @@ import {
   SnippetsOutlined,
   SnippetsOutlined,
   UserOutlined,
   UserOutlined,
   PoweroffOutlined,
   PoweroffOutlined,
-  ClockCircleOutlined,
-  QuestionCircleOutlined,
   DownOutlined,
   DownOutlined,
 } from "@ant-design/icons-vue";
 } from "@ant-design/icons-vue";
 import { useRoute } from "vue-router";
 import { useRoute } from "vue-router";
 import { clearArbitrateTask } from "@/api/arbitratePage";
 import { clearArbitrateTask } from "@/api/arbitratePage";
 
 
-export default defineComponent({
-  name: "MarkHeader",
-  components: {
-    ZoomInOutlined,
-    ZoomOutOutlined,
-    FullscreenOutlined,
-    SnippetsOutlined,
-    UserOutlined,
-    PoweroffOutlined,
-    ClockCircleOutlined,
-    QuestionCircleOutlined,
-    DownOutlined,
-  },
-  setup() {
-    const route = useRoute();
-    let isSingleStudent = !!route.query.historyId;
-    const {
-      subjectCode,
-      groupNumber,
-      historyId: libraryId,
-    } = route.query as {
-      subjectCode: string;
-      groupNumber: string;
-      historyId: string;
-    };
+const route = useRoute();
+let isSingleStudent = !!route.query.historyId;
+const {
+  subjectCode,
+  groupNumber,
+  historyId: libraryId,
+} = route.query as {
+  subjectCode: string;
+  groupNumber: string;
+  historyId: string;
+};
 
 
-    const upScale = () => {
-      const s = store.setting.uiSetting["answer.paper.scale"];
-      if (s < 3)
-        store.setting.uiSetting["answer.paper.scale"] = +(s + 0.2).toFixed(1);
-    };
-    const downScale = () => {
-      const s = store.setting.uiSetting["answer.paper.scale"];
-      if (s > 0.2)
-        store.setting.uiSetting["answer.paper.scale"] = +(s - 0.2).toFixed(1);
-    };
-    const normalScale = () => {
-      store.setting.uiSetting["answer.paper.scale"] = 1;
-    };
-    const toggleHistory = () => {
-      store.historyOpen = !store.historyOpen;
-    };
-    const greaterThanOneScale = computed(() => {
-      return store.setting.uiSetting["answer.paper.scale"] > 1;
-    });
-    const lessThanOneScale = computed(() => {
-      return store.setting.uiSetting["answer.paper.scale"] < 1;
-    });
-
-    async function updateClearTask() {
-      await clearArbitrateTask(libraryId, subjectCode, groupNumber);
-    }
+const upScale = () => {
+  const s = store.setting.uiSetting["answer.paper.scale"];
+  if (s < 3)
+    store.setting.uiSetting["answer.paper.scale"] = +(s + 0.2).toFixed(1);
+};
+const downScale = () => {
+  const s = store.setting.uiSetting["answer.paper.scale"];
+  if (s > 0.2)
+    store.setting.uiSetting["answer.paper.scale"] = +(s - 0.2).toFixed(1);
+};
+const normalScale = () => {
+  store.setting.uiSetting["answer.paper.scale"] = 1;
+};
+const toggleHistory = () => {
+  store.historyOpen = !store.historyOpen;
+};
+const greaterThanOneScale = computed(() => {
+  return store.setting.uiSetting["answer.paper.scale"] > 1;
+});
+const lessThanOneScale = computed(() => {
+  return store.setting.uiSetting["answer.paper.scale"] < 1;
+});
 
 
-    const closeWindow = async () => {
-      await updateClearTask();
-      window.close();
-    };
+async function updateClearTask() {
+  await clearArbitrateTask(libraryId, subjectCode, groupNumber);
+}
 
 
-    onMounted(() => {
-      // 不确定是否一定能在关闭页面时调用
-      window.addEventListener("beforeunload", () => {
-        updateClearTask();
-      });
-    });
+const closeWindow = async () => {
+  await updateClearTask();
+  window.close();
+};
 
 
-    return {
-      store,
-      isSingleStudent,
-      upScale,
-      downScale,
-      normalScale,
-      greaterThanOneScale,
-      lessThanOneScale,
-      toggleHistory,
-      closeWindow,
-    };
-  },
+onMounted(() => {
+  // 不确定是否一定能在关闭页面时调用
+  window.addEventListener("beforeunload", () => {
+    updateClearTask();
+  });
 });
 });
 </script>
 </script>
 
 

+ 123 - 154
src/features/arbitrate/MarkHistory.vue

@@ -99,9 +99,9 @@
   </div>
   </div>
 </template>
 </template>
 
 
-<script lang="ts">
-import { MarkHistoryOrderBy, MarkHistorySortField, Task } from "@/types";
-import { defineComponent, ref, watch, watchEffect } from "vue";
+<script setup lang="ts">
+import type { MarkHistoryOrderBy, MarkHistorySortField, Task } from "@/types";
+import { defineEmit, defineProps, ref, watch } from "vue";
 import { useRoute } from "vue-router";
 import { useRoute } from "vue-router";
 import { store } from "@/features/mark/store";
 import { store } from "@/features/mark/store";
 import {
 import {
@@ -113,119 +113,53 @@ import {
 import { cloneDeep } from "lodash";
 import { cloneDeep } from "lodash";
 import { getArbitrateHistory } from "@/api/arbitratePage";
 import { getArbitrateHistory } from "@/api/arbitratePage";
 
 
-export default defineComponent({
-  name: "MarkHistory",
-  components: {
-    CloseOutlined,
-    SearchOutlined,
-    CaretDownOutlined,
-    CaretUpOutlined,
-  },
-  props: {
-    shouldReload: { type: Number, required: true },
-  },
-  emits: ["reload"],
-  setup(props, { emit }) {
-    const route = useRoute();
-    const { subjectCode, groupNumber } = route.query as {
-      subjectCode: string;
-      groupNumber: string;
-    };
+const props = defineProps<{ shouldReload: number }>();
 
 
-    const secretNumberInput = ref("");
-    const loading = ref(false);
-    const currentPage = ref(1);
-    const order = ref("markerTime" as MarkHistoryOrderBy);
-    const sort = ref("DESC" as MarkHistorySortField);
+const emit = defineEmit(["reload"]);
 
 
-    const currentTaskChange = async () => {
-      replaceCurrentTask(undefined);
-      if (store.historyOpen) {
-        await updateHistoryTask({
-          secretNumber: secretNumberInput.value,
-          order: order.value,
-          sort: sort.value,
-          pageNumber: currentPage.value,
-        });
-        replaceCurrentTask(store.historyTasks[0]);
-      } else {
-        emit("reload");
-        secretNumberInput.value = "";
-        currentPage.value = 1;
-        order.value = "markerTime";
-        sort.value = "DESC";
-      }
-    };
-    watch(() => store.historyOpen, currentTaskChange);
-    watch([order, sort, currentPage], currentTaskChange);
+const route = useRoute();
+const { subjectCode, groupNumber } = route.query as {
+  subjectCode: string;
+  groupNumber: string;
+};
 
 
-    watch(
-      () => props.shouldReload,
-      async () => {
-        store.globalMask = true;
-        try {
-          const res = await getArbitrateHistory({
-            subjectCode: subjectCode,
-            groupNumber: groupNumber,
-            secretNumber: store.currentTask?.secretNumber,
-          });
-          if (res.data) {
-            let data = cloneDeep(res.data) as Array<Task>;
-            data = data.map((t) => {
-              t.sliceUrls = t.sliceUrls.map(
-                (s) => store.setting.fileServer + s
-              );
-              t.sheetUrls = t.sheetUrls?.map(
-                (s) => store.setting.fileServer + s
-              );
-              t.jsonUrl = store.setting.fileServer + t.jsonUrl;
+const secretNumberInput = ref("");
+const loading = ref(false);
+const currentPage = ref(1);
+const order = ref("markerTime" as MarkHistoryOrderBy);
+const sort = ref("DESC" as MarkHistorySortField);
 
 
-              return t;
-            });
-            if (store.currentTask) {
-              const indexOfTasks = store.historyTasks.indexOf(
-                store.currentTask
-              );
-              if (data[0]) {
-                store.historyTasks.splice(indexOfTasks, 1, data[0]);
-                replaceCurrentTask(store.historyTasks[indexOfTasks]);
-              } else {
-                // 可能会查找不到,这里直接删除此任务
-                store.historyTasks.splice(indexOfTasks, 1);
-                replaceCurrentTask(store.historyTasks[indexOfTasks]);
-              }
-            }
-          }
-        } finally {
-          store.globalMask = false;
-        }
-      }
-    );
+const currentTaskChange = async () => {
+  replaceCurrentTask(undefined);
+  if (store.historyOpen) {
+    await updateHistoryTask({
+      secretNumber: secretNumberInput.value,
+      order: order.value,
+      sort: sort.value,
+      pageNumber: currentPage.value,
+    });
+    replaceCurrentTask(store.historyTasks[0]);
+  } else {
+    emit("reload");
+    secretNumberInput.value = "";
+    currentPage.value = 1;
+    order.value = "markerTime";
+    sort.value = "DESC";
+  }
+};
+watch(() => store.historyOpen, currentTaskChange);
+watch([order, sort, currentPage], currentTaskChange);
 
 
-    async function updateHistoryTask({
-      pageNumber = 1,
-      pageSize = 10,
-      order = "markerTime",
-      sort = "DESC",
-      secretNumber = null,
-    }: {
-      pageNumber?: number; // 从1开始
-      pageSize?: number;
-      order?: MarkHistoryOrderBy;
-      sort?: MarkHistorySortField;
-      secretNumber?: string | null;
-    }) {
-      loading.value = true;
+watch(
+  () => props.shouldReload,
+  async () => {
+    store.globalMask = true;
+    try {
       const res = await getArbitrateHistory({
       const res = await getArbitrateHistory({
-        pageNumber,
-        pageSize,
-        subjectCode,
-        groupNumber,
-        secretNumber,
-        order,
-        sort,
+        subjectCode: subjectCode,
+        groupNumber: groupNumber,
+        secretNumber: store.currentTask?.secretNumber,
       });
       });
-      loading.value = false;
       if (res.data) {
       if (res.data) {
         let data = cloneDeep(res.data) as Array<Task>;
         let data = cloneDeep(res.data) as Array<Task>;
         data = data.map((t) => {
         data = data.map((t) => {
@@ -235,57 +169,92 @@ export default defineComponent({
 
 
           return t;
           return t;
         });
         });
-        store.historyTasks = data;
-        replaceCurrentTask(store.historyTasks[0]);
+        if (store.currentTask) {
+          const indexOfTasks = store.historyTasks.indexOf(store.currentTask);
+          if (data[0]) {
+            store.historyTasks.splice(indexOfTasks, 1, data[0]);
+            replaceCurrentTask(store.historyTasks[indexOfTasks]);
+          } else {
+            // 可能会查找不到,这里直接删除此任务
+            store.historyTasks.splice(indexOfTasks, 1);
+            replaceCurrentTask(store.historyTasks[indexOfTasks]);
+          }
+        }
       }
       }
+    } finally {
+      store.globalMask = false;
     }
     }
+  }
+);
 
 
-    function replaceCurrentTask(task: Task | undefined) {
-      store.currentTask = task;
-    }
+async function updateHistoryTask({
+  pageNumber = 1,
+  pageSize = 10,
+  order = "markerTime",
+  sort = "DESC",
+  secretNumber = null,
+}: {
+  pageNumber?: number; // 从1开始
+  pageSize?: number;
+  order?: MarkHistoryOrderBy;
+  sort?: MarkHistorySortField;
+  secretNumber?: string | null;
+}) {
+  loading.value = true;
+  const res = await getArbitrateHistory({
+    pageNumber,
+    pageSize,
+    subjectCode,
+    groupNumber,
+    secretNumber,
+    order,
+    sort,
+  });
+  loading.value = false;
+  if (res.data) {
+    let data = cloneDeep(res.data) as Array<Task>;
+    data = data.map((t) => {
+      t.sliceUrls = t.sliceUrls.map((s) => store.setting.fileServer + s);
+      t.sheetUrls = t.sheetUrls?.map((s) => store.setting.fileServer + s);
+      t.jsonUrl = store.setting.fileServer + t.jsonUrl;
 
 
-    function previousPage() {
-      if (currentPage.value > 1) {
-        currentPage.value -= 1;
-      }
-    }
-    function nextPage() {
-      if (store.historyTasks.length >= 10) {
-        currentPage.value += 1;
-      }
-    }
+      return t;
+    });
+    store.historyTasks = data;
+    replaceCurrentTask(store.historyTasks[0]);
+  }
+}
 
 
-    function toggleOrderBy(toOrder: MarkHistoryOrderBy) {
-      if (toOrder === order.value) {
-        sort.value = sort.value === "DESC" ? "ASC" : "DESC";
-      } else {
-        order.value = toOrder;
-      }
-    }
+function replaceCurrentTask(task: Task | undefined) {
+  store.currentTask = task;
+}
 
 
-    function searchHistoryTask() {
-      if (currentPage.value !== 1) {
-        currentPage.value = 1;
-      } else {
-        currentTaskChange();
-      }
-    }
-    return {
-      store,
-      loading,
-      secretNumberInput,
-      updateHistoryTask,
-      replaceCurrentTask,
-      currentPage,
-      previousPage,
-      nextPage,
-      sort,
-      order,
-      toggleOrderBy,
-      searchHistoryTask,
-    };
-  },
-});
+function previousPage() {
+  if (currentPage.value > 1) {
+    currentPage.value -= 1;
+  }
+}
+function nextPage() {
+  if (store.historyTasks.length >= 10) {
+    currentPage.value += 1;
+  }
+}
+
+function toggleOrderBy(toOrder: MarkHistoryOrderBy) {
+  if (toOrder === order.value) {
+    sort.value = sort.value === "DESC" ? "ASC" : "DESC";
+  } else {
+    order.value = toOrder;
+  }
+}
+
+function searchHistoryTask() {
+  if (currentPage.value !== 1) {
+    currentPage.value = 1;
+  } else {
+    currentTaskChange();
+  }
+}
 </script>
 </script>
 
 
 <style scoped>
 <style scoped>

+ 127 - 164
src/features/library/inspect/LibraryInspect.vue

@@ -12,15 +12,15 @@
   </div>
   </div>
 </template>
 </template>
 
 
-<script lang="ts">
-import { computed, defineComponent, onMounted, ref } from "vue";
+<script setup lang="ts">
+import { computed, onMounted, ref } from "vue";
 import { store } from "@/features/mark/store";
 import { store } from "@/features/mark/store";
 import MarkHeader from "./MarkHeader.vue";
 import MarkHeader from "./MarkHeader.vue";
 import { useRoute } from "vue-router";
 import { useRoute } from "vue-router";
 import MarkBody from "./MarkBody.vue";
 import MarkBody from "./MarkBody.vue";
 import MarkHistory from "./MarkHistory.vue";
 import MarkHistory from "./MarkHistory.vue";
 import MarkBoardInspect from "./MarkBoardInspect.vue";
 import MarkBoardInspect from "./MarkBoardInspect.vue";
-import { MarkStore, Question, Task } from "@/types";
+import type { MarkStore, Question, Task } from "@/types";
 import { message } from "ant-design-vue";
 import { message } from "ant-design-vue";
 import {
 import {
   clearInspectedTask,
   clearInspectedTask,
@@ -31,182 +31,145 @@ import {
   saveInspectedTask,
   saveInspectedTask,
 } from "@/api/libraryInspectPage";
 } from "@/api/libraryInspectPage";
 
 
-export default defineComponent({
-  name: "LibraryInspect",
-  components: {
-    MarkHeader,
-    MarkBody,
-    MarkHistory,
-    MarkBoardInspect,
-  },
-  setup: () => {
-    const route = useRoute();
-    let isSingleStudent = !!route.query.libraryId;
-    const { subjectCode, groupNumber, libraryId } = route.query as {
-      subjectCode: string;
-      groupNumber: string;
-      libraryId: string; // TODO: for未来单一任务
-    };
+const route = useRoute();
+let isSingleStudent = !!route.query.libraryId;
+const { subjectCode, groupNumber, libraryId } = route.query as {
+  subjectCode: string;
+  groupNumber: string;
+  libraryId: string; // TODO: for未来单一任务
+};
 
 
-    async function updateClearTask() {
-      await clearInspectedTask(subjectCode, groupNumber);
-    }
+async function updateClearTask() {
+  await clearInspectedTask(subjectCode, groupNumber);
+}
 
 
-    async function updateSetting() {
-      const settingRes = await getInspectedSetting();
-      store.setting.fileServer = settingRes.data.fileServer;
-      store.setting.userName = settingRes.data.userName;
-      store.setting.uiSetting = {
-        "answer.paper.scale": 1,
-        "score.board.collapse": false,
-      } as MarkStore["setting"]["uiSetting"];
-      store.setting.splitConfig = settingRes.data.splitConfig;
-    }
-    async function updateStatus() {
-      const res = await getInspectedTaskStatus(subjectCode, groupNumber);
-      if (res.data.valid) store.status = res.data;
-    }
-    async function updateTask() {
-      // const mkey = "fetch_task_key";
-      message.info({ content: "获取任务中...", duration: 2 });
-      let res;
-      // if (isSingleStudent) {
-      //   res = await getSingleStuTask();
-      // } else {
-      res = await getOneOfStuTask();
-      // }
-      // message.success({ content: "获取成功", key: mkey });
+async function updateSetting() {
+  const settingRes = await getInspectedSetting();
+  store.setting.fileServer = settingRes.data.fileServer;
+  store.setting.userName = settingRes.data.userName;
+  store.setting.uiSetting = {
+    "answer.paper.scale": 1,
+    "score.board.collapse": false,
+  } as MarkStore["setting"]["uiSetting"];
+  store.setting.splitConfig = settingRes.data.splitConfig;
+}
+async function updateStatus() {
+  const res = await getInspectedTaskStatus(subjectCode, groupNumber);
+  if (res.data.valid) store.status = res.data;
+}
+async function updateTask() {
+  // const mkey = "fetch_task_key";
+  message.info({ content: "获取任务中...", duration: 2 });
+  let res;
+  // if (isSingleStudent) {
+  //   res = await getSingleStuTask();
+  // } else {
+  res = await getOneOfStuTask();
+  // }
+  // message.success({ content: "获取成功", key: mkey });
+
+  if (res.data.libraryId) {
+    let rawTask = res.data as Task;
+    rawTask.sliceUrls = rawTask.sliceUrls.map(
+      (s) => store.setting.fileServer + s
+    );
+    rawTask.sheetUrls = rawTask.sheetUrls?.map(
+      (s) => store.setting.fileServer + s
+    );
+    rawTask.jsonUrl = store.setting.fileServer + rawTask.jsonUrl;
+    store.currentTask = res.data;
+    if (store.currentTask)
+      store.setting.subject = store.currentTask
+        .subject as MarkStore["setting"]["subject"];
+  } else {
+    store.message = res.data.message;
+  }
+}
 
 
-      if (res.data.libraryId) {
-        let rawTask = res.data as Task;
-        rawTask.sliceUrls = rawTask.sliceUrls.map(
-          (s) => store.setting.fileServer + s
-        );
-        rawTask.sheetUrls = rawTask.sheetUrls?.map(
-          (s) => store.setting.fileServer + s
-        );
-        rawTask.jsonUrl = store.setting.fileServer + rawTask.jsonUrl;
-        store.currentTask = res.data;
-        if (store.currentTask)
-          store.setting.subject = store.currentTask
-            .subject as MarkStore["setting"]["subject"];
-      } else {
-        store.message = res.data.message;
-      }
-    }
+const shouldReloadHistory = ref(0);
 
 
-    const shouldReloadHistory = ref(0);
+async function reloadAndfetchTask() {
+  await updateClearTask();
+  await updateSetting();
+  await fetchTask();
+}
 
 
-    async function reloadAndfetchTask() {
-      await updateClearTask();
-      await updateSetting();
-      await fetchTask();
-    }
+async function fetchTask() {
+  !isSingleStudent && (await updateStatus());
+  await updateTask();
+}
 
 
-    async function fetchTask() {
-      !isSingleStudent && (await updateStatus());
-      await updateTask();
-    }
+onMounted(async () => {
+  // await updateClearTask();
+  // fetchTask(); // mark-header 会调用 (watchEffect)
+});
 
 
-    onMounted(async () => {
-      // await updateClearTask();
-      // fetchTask(); // mark-header 会调用 (watchEffect)
-    });
+async function getSingleStuTask() {
+  // return getSingleInspectedTask(libraryId);
+}
 
 
-    async function getSingleStuTask() {
-      // return getSingleInspectedTask(libraryId);
-    }
+async function getOneOfStuTask() {
+  return getOneOfInspectedTask(subjectCode, groupNumber);
+}
 
 
-    async function getOneOfStuTask() {
-      return getOneOfInspectedTask(subjectCode, groupNumber);
+const realLibraryId = computed(
+  () => (isSingleStudent ? libraryId : store.currentTask?.libraryId) as string
+);
+const saveTaskToServer = async () => {
+  console.log("save inspect task to server");
+  const mkey = "save_task_key";
+  message.loading({ content: "保存评卷任务...", key: mkey });
+  const res = (await saveInspectedTask(realLibraryId.value)) as any;
+  if (res.data.success && store.currentTask) {
+    message.success({ content: "复核成功", key: mkey, duration: 2 });
+    if (!store.historyOpen) {
+      store.currentTask = undefined;
+      if (!isSingleStudent) fetchTask();
+    } else {
+      shouldReloadHistory.value = Date.now();
     }
     }
-
-    const realLibraryId = computed(
-      () =>
-        (isSingleStudent ? libraryId : store.currentTask?.libraryId) as string
-    );
-    const saveTaskToServer = async () => {
-      console.log("save inspect task to server");
-      const mkey = "save_task_key";
-      message.loading({ content: "保存评卷任务...", key: mkey });
-      const res = (await saveInspectedTask(realLibraryId.value)) as any;
-      if (res.data.success && store.currentTask) {
-        message.success({ content: "复核成功", key: mkey, duration: 2 });
-        if (!store.historyOpen) {
-          store.currentTask = undefined;
-          if (!isSingleStudent) fetchTask();
-        } else {
-          shouldReloadHistory.value = Date.now();
-        }
-      } else if (res.data.message) {
-        console.log(res.data.message);
-        message.error({ content: res.data.message, key: mkey, duration: 10 });
-      } else if (!store.currentTask) {
-        message.warn({ content: "暂无新任务", key: mkey, duration: 10 });
-      }
-    };
-
-    const rejectQuestions = async (questions: Array<Question>) => {
-      if (!store.currentTask) return;
-      const mkey = "reject_task_key";
-      message.loading({ content: "打回评卷任务...", key: mkey });
-      const res = (await rejectInspectedTask(
-        //realLibraryId.value,
-        store.currentTask.libraryId + "",
-        questions
-      )) as any;
-      if (res.data.success) {
-        store.currentTask = undefined;
-        message.success({ content: "打回成功", key: mkey, duration: 2 });
-        if (!store.historyOpen) {
-          store.currentTask = undefined;
-          if (!isSingleStudent) fetchTask();
-        } else {
-          shouldReloadHistory.value = Date.now();
-        }
-      } else if (res.data.message) {
-        console.log(res.data.message);
-        message.error({ content: res.data.message, key: mkey, duration: 10 });
-      } else if (!store.currentTask) {
-        message.warn({ content: "暂无新任务", key: mkey, duration: 10 });
-      }
-    };
-
-    const renderError = () => {
+  } else if (res.data.message) {
+    console.log(res.data.message);
+    message.error({ content: res.data.message, key: mkey, duration: 10 });
+  } else if (!store.currentTask) {
+    message.warn({ content: "暂无新任务", key: mkey, duration: 10 });
+  }
+};
+
+const rejectQuestions = async (questions: Array<Question>) => {
+  if (!store.currentTask) return;
+  const mkey = "reject_task_key";
+  message.loading({ content: "打回评卷任务...", key: mkey });
+  const res = (await rejectInspectedTask(
+    //realLibraryId.value,
+    store.currentTask.libraryId + "",
+    questions
+  )) as any;
+  if (res.data.success) {
+    store.currentTask = undefined;
+    message.success({ content: "打回成功", key: mkey, duration: 2 });
+    if (!store.historyOpen) {
       store.currentTask = undefined;
       store.currentTask = undefined;
-      store.message = "加载失败,请重新加载。";
-    };
-
-    return {
-      store,
-      fetchTask,
-      reloadAndfetchTask,
-      saveTaskToServer,
-      rejectQuestions,
-      shouldReloadHistory,
-      renderError,
-    };
-  },
-});
+      if (!isSingleStudent) fetchTask();
+    } else {
+      shouldReloadHistory.value = Date.now();
+    }
+  } else if (res.data.message) {
+    console.log(res.data.message);
+    message.error({ content: res.data.message, key: mkey, duration: 10 });
+  } else if (!store.currentTask) {
+    message.warn({ content: "暂无新任务", key: mkey, duration: 10 });
+  }
+};
+
+const renderError = () => {
+  store.currentTask = undefined;
+  store.message = "加载失败,请重新加载。";
+};
 </script>
 </script>
 
 
 <style scoped>
 <style scoped>
 .my-container {
 .my-container {
   width: 100%;
   width: 100%;
 }
 }
-a {
-  color: #42b983;
-}
-
-label {
-  margin: 0 0.5em;
-  font-weight: bold;
-}
-
-code {
-  background-color: #eee;
-  padding: 2px 4px;
-  border-radius: 4px;
-  color: #304455;
-}
 </style>
 </style>

+ 111 - 150
src/features/library/inspect/MarkBoardInspect.vue

@@ -90,151 +90,130 @@
   </div>
   </div>
 </template>
 </template>
 
 
-<script lang="ts">
-import { Question } from "@/types";
+<script setup lang="ts">
+import type { Question } from "@/types";
 import { message } from "ant-design-vue";
 import { message } from "ant-design-vue";
-import { computed, defineComponent, reactive, watch } from "vue";
+import { computed, defineEmit, reactive, watch } from "vue";
 import { store } from "@/features/mark/store";
 import { store } from "@/features/mark/store";
 
 
-export default defineComponent({
-  name: "MarkBoardInspect",
-  emits: ["inspect", "reject"],
-  setup(props, { emit }) {
-    let checkedQuestions = reactive([] as Array<Question>);
-
-    watch(
-      () => store.currentTask,
-      () => {
-        checkedQuestions.splice(0);
-      }
-    );
-    const groups = computed(() => {
-      const gs = store.currentTask?.questionList.map((q) => q.groupNumber);
-      return [...new Set(gs)].sort((a, b) => a - b);
-    });
-
-    const questions = computed(() => {
-      const qs = store.currentTask?.questionList;
-      return qs;
-    });
-
-    const markerScore = computed(
-      () =>
-        (questions.value
-          ?.map((q) => Math.round((q.score || 0) * 100))
-          .reduce((acc, s) => acc + s) || 0) / 100
-    );
+const emit = defineEmit(["inspect", "reject"]);
+let checkedQuestions = reactive([] as Array<Question>);
+
+watch(
+  () => store.currentTask,
+  () => {
+    checkedQuestions.splice(0);
+  }
+);
+const groups = computed(() => {
+  const gs = store.currentTask?.questionList.map((q) => q.groupNumber);
+  return [...new Set(gs)].sort((a, b) => a - b);
+});
 
 
-    function addToCheckedQuestion(question: Question) {
-      checkedQuestions.push(question);
-    }
-    function removeCheckedQuestion(question: Question) {
-      const idx = checkedQuestions.indexOf(question);
-      checkedQuestions.splice(idx, 1);
-    }
-    function groupChecked(groupNumber: number) {
-      return (
-        checkedQuestions.filter((q) => q.groupNumber === groupNumber).length ===
-        questions.value?.filter((q) => q.groupNumber === groupNumber).length
-      );
-    }
+const questions = computed(() => {
+  const qs = store.currentTask?.questionList;
+  return qs;
+});
 
 
-    function questionChecked(question: Question) {
-      return checkedQuestions.includes(question);
-    }
+const markerScore = computed(
+  () =>
+    (questions.value
+      ?.map((q) => Math.round((q.score || 0) * 100))
+      .reduce((acc, s) => acc + s) || 0) / 100
+);
 
 
-    function questionCheckChanged(question: Question) {
-      const checked = questionChecked(question);
-      if (checked) {
-        removeCheckedQuestion(question);
-      } else {
-        addToCheckedQuestion(question);
-      }
-    }
+function addToCheckedQuestion(question: Question) {
+  checkedQuestions.push(question);
+}
+function removeCheckedQuestion(question: Question) {
+  const idx = checkedQuestions.indexOf(question);
+  checkedQuestions.splice(idx, 1);
+}
+function groupChecked(groupNumber: number) {
+  return (
+    checkedQuestions.filter((q) => q.groupNumber === groupNumber).length ===
+    questions.value?.filter((q) => q.groupNumber === groupNumber).length
+  );
+}
 
 
-    function groupClicked(groupNumber: number) {
-      if (groupChecked(groupNumber)) {
-        checkedQuestions
-          .filter((q) => q.groupNumber === groupNumber)
-          .forEach((q) => {
-            const idx = checkedQuestions.indexOf(q);
-            checkedQuestions.splice(idx, 1);
-          });
-      } else {
-        questions.value
-          ?.filter((q) => q.groupNumber === groupNumber)
-          .forEach((q) => {
-            if (!questionChecked(q)) checkedQuestions.push(q);
-          });
-      }
-    }
+function questionChecked(question: Question) {
+  return checkedQuestions.includes(question);
+}
 
 
-    function addFocusTrack(
-      groupNumber: number | undefined,
-      mainNumber: number | undefined,
-      subNumber: string | undefined
-    ) {
-      store.focusTracks.splice(0);
+function questionCheckChanged(question: Question) {
+  const checked = questionChecked(question);
+  if (checked) {
+    removeCheckedQuestion(question);
+  } else {
+    addToCheckedQuestion(question);
+  }
+}
 
 
-      if (groupNumber) {
-        questions.value
-          ?.filter((q) => q.groupNumber === groupNumber)
-          ?.map((q) => q.trackList)
-          .reduce((acc, ts) => acc.concat(ts))
-          .forEach((t) => {
-            store.focusTracks.push(t);
-          });
-      } else {
-        questions.value
-          ?.map((q) => q.trackList)
-          .reduce((acc, ts) => acc.concat(ts))
-          .filter((t) => {
-            if (mainNumber) {
-              return t.mainNumber === mainNumber && t.subNumber === subNumber;
-            } else {
-              return false;
-            }
-          })
-          .forEach((t) => {
-            store.focusTracks.push(t);
-          });
-      }
-      // console.log(store.focusTracks);
-    }
+function groupClicked(groupNumber: number) {
+  if (groupChecked(groupNumber)) {
+    checkedQuestions
+      .filter((q) => q.groupNumber === groupNumber)
+      .forEach((q) => {
+        const idx = checkedQuestions.indexOf(q);
+        checkedQuestions.splice(idx, 1);
+      });
+  } else {
+    questions.value
+      ?.filter((q) => q.groupNumber === groupNumber)
+      .forEach((q) => {
+        if (!questionChecked(q)) checkedQuestions.push(q);
+      });
+  }
+}
 
 
-    function removeFocusTrack() {
-      store.focusTracks.splice(0);
-    }
+function addFocusTrack(
+  groupNumber: number | undefined,
+  mainNumber: number | undefined,
+  subNumber: string | undefined
+) {
+  store.focusTracks.splice(0);
+
+  if (groupNumber) {
+    questions.value
+      ?.filter((q) => q.groupNumber === groupNumber)
+      ?.map((q) => q.trackList)
+      .reduce((acc, ts) => acc.concat(ts))
+      .forEach((t) => {
+        store.focusTracks.push(t);
+      });
+  } else {
+    questions.value
+      ?.map((q) => q.trackList)
+      .reduce((acc, ts) => acc.concat(ts))
+      .filter((t) => {
+        if (mainNumber) {
+          return t.mainNumber === mainNumber && t.subNumber === subNumber;
+        } else {
+          return false;
+        }
+      })
+      .forEach((t) => {
+        store.focusTracks.push(t);
+      });
+  }
+  // console.log(store.focusTracks);
+}
 
 
-    function reject() {
-      if (checkedQuestions.length === 0) {
-        message.warn({ content: "请先选择试题。" });
-        return;
-      }
-      emit("reject", checkedQuestions);
-    }
+function removeFocusTrack() {
+  store.focusTracks.splice(0);
+}
 
 
-    function inspect() {
-      emit("inspect");
-    }
+function reject() {
+  if (checkedQuestions.length === 0) {
+    message.warn({ content: "请先选择试题。" });
+    return;
+  }
+  emit("reject", checkedQuestions);
+}
 
 
-    return {
-      store,
-      markerScore,
-      groups,
-      checkedQuestions,
-      questions,
-      groupChecked,
-      questionChecked,
-      questionCheckChanged,
-      groupClicked,
-      addFocusTrack,
-      removeFocusTrack,
-      reject,
-      inspect,
-    };
-  },
-});
+function inspect() {
+  emit("inspect");
+}
 </script>
 </script>
 
 
 <style scoped>
 <style scoped>
@@ -251,22 +230,4 @@ export default defineComponent({
   min-width: 100px;
   min-width: 100px;
   border-bottom: 1px dotted grey;
   border-bottom: 1px dotted grey;
 }
 }
-
-.current-question {
-  border: 1px solid yellowgreen;
-  background-color: lightblue;
-}
-.single-score {
-  width: 30px;
-  height: 30px;
-  display: grid;
-  place-content: center;
-
-  border: 1px solid black;
-  border-radius: 5px;
-}
-.current-score {
-  border: 1px solid yellowgreen;
-  background-color: lightblue;
-}
 </style>
 </style>

+ 4 - 10
src/features/library/inspect/MarkBody.vue

@@ -5,22 +5,16 @@
     :store="store"
     :store="store"
     uniquePropName="studentId"
     uniquePropName="studentId"
     @error="$emit('error')"
     @error="$emit('error')"
+    :makeTrack="() => {}"
   />
   />
 </template>
 </template>
 
 
-<script lang="ts">
+<script setup lang="ts">
 import CommonMarkBody from "@/features/mark/CommonMarkBody.vue";
 import CommonMarkBody from "@/features/mark/CommonMarkBody.vue";
-import { defineComponent, watch } from "vue";
+import { defineEmit } from "vue";
 import { store } from "@/features/mark/store";
 import { store } from "@/features/mark/store";
 
 
-export default defineComponent({
-  name: "MarkBody",
-  components: { CommonMarkBody },
-  emits: ["error"],
-  setup() {
-    return { store };
-  },
-});
+defineEmit(["error"]);
 </script>
 </script>
 
 
 <style scoped></style>
 <style scoped></style>

+ 40 - 92
src/features/library/inspect/MarkHeader.vue

@@ -63,113 +63,61 @@
   </div>
   </div>
 </template>
 </template>
 
 
-<script lang="ts">
-import { computed, defineComponent, onMounted, ref } from "vue";
+<script setup lang="ts">
+import { computed, onMounted, ref } from "vue";
 import { store } from "@/features/mark/store";
 import { store } from "@/features/mark/store";
 import {
 import {
   ZoomInOutlined,
   ZoomInOutlined,
   ZoomOutOutlined,
   ZoomOutOutlined,
   FullscreenOutlined,
   FullscreenOutlined,
-  SnippetsOutlined,
   UserOutlined,
   UserOutlined,
   PoweroffOutlined,
   PoweroffOutlined,
-  ClockCircleOutlined,
-  QuestionCircleOutlined,
 } from "@ant-design/icons-vue";
 } from "@ant-design/icons-vue";
 import { useRoute } from "vue-router";
 import { useRoute } from "vue-router";
 import { clearInspectedTask } from "@/api/libraryInspectPage";
 import { clearInspectedTask } from "@/api/libraryInspectPage";
 
 
-export default defineComponent({
-  name: "MarkHeader",
-  components: {
-    ZoomInOutlined,
-    ZoomOutOutlined,
-    FullscreenOutlined,
-    SnippetsOutlined,
-    UserOutlined,
-    PoweroffOutlined,
-    ClockCircleOutlined,
-    QuestionCircleOutlined,
-  },
-  setup() {
-    const route = useRoute();
-    let isSingleStudent = ref(false);
-    isSingleStudent.value = !!route.query.studentId;
-    const { studentId, subjectCode, groupNumber } = route.query as {
-      studentId: string;
-      subjectCode: string;
-      groupNumber: string;
-    };
+const route = useRoute();
+let isSingleStudent = ref(false);
+isSingleStudent.value = !!route.query.studentId;
+const { subjectCode, groupNumber } = route.query as {
+  subjectCode: string;
+  groupNumber: string;
+};
 
 
-    const upScale = () => {
-      const s = store.setting.uiSetting["answer.paper.scale"];
-      if (s < 3)
-        store.setting.uiSetting["answer.paper.scale"] = +(s + 0.2).toFixed(1);
-    };
-    const downScale = () => {
-      const s = store.setting.uiSetting["answer.paper.scale"];
-      if (s > 0.2)
-        store.setting.uiSetting["answer.paper.scale"] = +(s - 0.2).toFixed(1);
-    };
-    const normalScale = () => {
-      store.setting.uiSetting["answer.paper.scale"] = 1;
-    };
-    const toggleHistory = () => {
-      store.historyOpen = !store.historyOpen;
-    };
-    const greaterThanOneScale = computed(() => {
-      return store.setting.uiSetting["answer.paper.scale"] > 1;
-    });
-    const lessThanOneScale = computed(() => {
-      return store.setting.uiSetting["answer.paper.scale"] < 1;
-    });
-
-    async function updateHistoryTask({
-      pageNumber = 1,
-      pageSize = 10,
-    }: {
-      pageNumber: number; // 从1开始
-      pageSize: number;
-    }) {
-      // const res = await getInspectedHistory({
-      //   pageNumber,
-      //   pageSize,
-      //   subjectCode,
-      // });
-      // if (res.data) {
-      //   store.historyTasks.push(res.data);
-      // }
-    }
-
-    async function updateClearTask() {
-      await clearInspectedTask(subjectCode, groupNumber);
-    }
+const upScale = () => {
+  const s = store.setting.uiSetting["answer.paper.scale"];
+  if (s < 3)
+    store.setting.uiSetting["answer.paper.scale"] = +(s + 0.2).toFixed(1);
+};
+const downScale = () => {
+  const s = store.setting.uiSetting["answer.paper.scale"];
+  if (s > 0.2)
+    store.setting.uiSetting["answer.paper.scale"] = +(s - 0.2).toFixed(1);
+};
+const normalScale = () => {
+  store.setting.uiSetting["answer.paper.scale"] = 1;
+};
+const greaterThanOneScale = computed(() => {
+  return store.setting.uiSetting["answer.paper.scale"] > 1;
+});
+const lessThanOneScale = computed(() => {
+  return store.setting.uiSetting["answer.paper.scale"] < 1;
+});
 
 
-    const closeWindow = async () => {
-      await updateClearTask();
-      window.close();
-    };
+async function updateClearTask() {
+  await clearInspectedTask(subjectCode, groupNumber);
+}
 
 
-    onMounted(() => {
-      // 不确定是否一定能在关闭页面时调用
-      window.addEventListener("beforeunload", () => {
-        updateClearTask();
-      });
-    });
+const closeWindow = async () => {
+  await updateClearTask();
+  window.close();
+};
 
 
-    return {
-      store,
-      isSingleStudent,
-      upScale,
-      downScale,
-      normalScale,
-      greaterThanOneScale,
-      lessThanOneScale,
-      updateHistoryTask,
-      toggleHistory,
-      closeWindow,
-    };
-  },
+onMounted(() => {
+  // 不确定是否一定能在关闭页面时调用
+  window.addEventListener("beforeunload", () => {
+    updateClearTask();
+  });
 });
 });
 </script>
 </script>
 
 

+ 70 - 88
src/features/library/inspect/MarkHistory.vue

@@ -51,108 +51,90 @@
   </div>
   </div>
 </template>
 </template>
 
 
-<script lang="ts">
+<script setup lang="ts">
 import { getInspectedHistory } from "@/api/inspectPage";
 import { getInspectedHistory } from "@/api/inspectPage";
-import { Task } from "@/types";
-import { defineComponent, ref, watch, watchEffect } from "vue";
+import type { Task } from "@/types";
+import { defineEmit, defineProps, ref, watch, watchEffect } from "vue";
 import { useRoute } from "vue-router";
 import { useRoute } from "vue-router";
 import { store } from "@/features/mark/store";
 import { store } from "@/features/mark/store";
 import { CloseOutlined } from "@ant-design/icons-vue";
 import { CloseOutlined } from "@ant-design/icons-vue";
 import { cloneDeep } from "lodash";
 import { cloneDeep } from "lodash";
 
 
-export default defineComponent({
-  name: "MarkHistory",
-  components: { CloseOutlined },
-  props: {
-    shouldReload: { type: Number, required: true },
-  },
-  emits: ["reload"],
-  setup(props, { emit }) {
-    const route = useRoute();
-    const { subjectCode } = route.query as {
-      subjectCode: string;
-    };
+const props = defineProps<{ shouldReload: number }>();
 
 
-    watchEffect(async () => {
-      if (store.historyOpen) {
-        replaceCurrentTask(undefined);
-        await updateHistoryTask({});
-        replaceCurrentTask(store.historyTasks[0]);
-      } else {
-        emit("reload");
-      }
-    });
+const emit = defineEmit(["reload"]);
 
 
-    watch(
-      () => props.shouldReload,
-      async () => {
-        await updateHistoryTask({ pageNumber: currentPage.value });
-        // 提交后,渲染第一条
-        replaceCurrentTask(store.historyTasks[0]);
-      }
-    );
+const route = useRoute();
+const { subjectCode } = route.query as {
+  subjectCode: string;
+};
 
 
-    const secretNumberInput = ref(null);
-    const loading = ref(false);
-    const currentPage = ref(1);
+watchEffect(async () => {
+  if (store.historyOpen) {
+    replaceCurrentTask(undefined);
+    await updateHistoryTask({});
+    replaceCurrentTask(store.historyTasks[0]);
+  } else {
+    emit("reload");
+  }
+});
 
 
-    async function updateHistoryTask({
-      pageNumber = 1,
-      pageSize = 10,
-    }: {
-      pageNumber?: number; // 从1开始
-      pageSize?: number;
-    }) {
-      loading.value = true;
-      const res = await getInspectedHistory({
-        pageNumber,
-        pageSize,
-        subjectCode,
-      });
-      loading.value = false;
-      if (res.data) {
-        let data = cloneDeep(res.data) as Array<Task>;
-        data = data.map((t) => {
-          t.sliceUrls = t.sliceUrls.map((s) => store.setting.fileServer + s);
-          t.sheetUrls = t.sheetUrls?.map((s) => store.setting.fileServer + s);
-          t.jsonUrl = store.setting.fileServer + t.jsonUrl;
+watch(
+  () => props.shouldReload,
+  async () => {
+    await updateHistoryTask({ pageNumber: currentPage.value });
+    // 提交后,渲染第一条
+    replaceCurrentTask(store.historyTasks[0]);
+  }
+);
 
 
-          return t;
-        });
-        store.historyTasks = data;
-        replaceCurrentTask(store.historyTasks[0]);
-      }
-    }
+const loading = ref(false);
+const currentPage = ref(1);
 
 
-    function replaceCurrentTask(task: Task | undefined) {
-      store.currentTask = task;
-    }
+async function updateHistoryTask({
+  pageNumber = 1,
+  pageSize = 10,
+}: {
+  pageNumber?: number; // 从1开始
+  pageSize?: number;
+}) {
+  loading.value = true;
+  const res = await getInspectedHistory({
+    pageNumber,
+    pageSize,
+    subjectCode,
+  });
+  loading.value = false;
+  if (res.data) {
+    let data = cloneDeep(res.data) as Array<Task>;
+    data = data.map((t) => {
+      t.sliceUrls = t.sliceUrls.map((s) => store.setting.fileServer + s);
+      t.sheetUrls = t.sheetUrls?.map((s) => store.setting.fileServer + s);
+      t.jsonUrl = store.setting.fileServer + t.jsonUrl;
 
 
-    function previousPage() {
-      if (currentPage.value > 1) {
-        currentPage.value -= 1;
-        updateHistoryTask({ pageNumber: currentPage.value });
-      }
-    }
-    function nextPage() {
-      if (store.historyTasks.length >= 10) {
-        currentPage.value += 1;
-        updateHistoryTask({ pageNumber: currentPage.value });
-      }
-    }
+      return t;
+    });
+    store.historyTasks = data;
+    replaceCurrentTask(store.historyTasks[0]);
+  }
+}
 
 
-    return {
-      store,
-      loading,
-      secretNumberInput,
-      updateHistoryTask,
-      replaceCurrentTask,
-      currentPage,
-      previousPage,
-      nextPage,
-    };
-  },
-});
+function replaceCurrentTask(task: Task | undefined) {
+  store.currentTask = task;
+}
+
+function previousPage() {
+  if (currentPage.value > 1) {
+    currentPage.value -= 1;
+    updateHistoryTask({ pageNumber: currentPage.value });
+  }
+}
+function nextPage() {
+  if (store.historyTasks.length >= 10) {
+    currentPage.value += 1;
+    updateHistoryTask({ pageNumber: currentPage.value });
+  }
+}
 </script>
 </script>
 
 
 <style scoped>
 <style scoped>

+ 43 - 73
src/features/library/libraryTrack/LibraryTrack.vue

@@ -7,99 +7,69 @@
   </div>
   </div>
 </template>
 </template>
 
 
-<script lang="ts">
-import { defineComponent, onMounted } from "vue";
+<script setup lang="ts">
+import { onMounted } from "vue";
 import { store } from "@/features/mark/store";
 import { store } from "@/features/mark/store";
 import MarkHeader from "./MarkHeader.vue";
 import MarkHeader from "./MarkHeader.vue";
 import { useRoute } from "vue-router";
 import { useRoute } from "vue-router";
 import MarkBody from "./MarkBody.vue";
 import MarkBody from "./MarkBody.vue";
-import { MarkStore, Task } from "@/types";
+import type { MarkStore, Task } from "@/types";
 import { message } from "ant-design-vue";
 import { message } from "ant-design-vue";
 import { getSingleLibraryTask } from "@/api/libraryTrackPage";
 import { getSingleLibraryTask } from "@/api/libraryTrackPage";
 
 
-export default defineComponent({
-  name: "LibraryTrack",
-  components: {
-    MarkHeader,
-    MarkBody,
-  },
-  setup: () => {
-    const route = useRoute();
-    let libraryId = route.query.libraryId;
+const route = useRoute();
+let libraryId = route.query.libraryId;
 
 
-    async function updateTask() {
-      // const mkey = "fetch_task_key";
-      message.info({ content: "获取任务中...", duration: 2 });
-      let res = await getSingleStuTask();
-      // message.success({ content: "获取成功", key: mkey });
+async function updateTask() {
+  // const mkey = "fetch_task_key";
+  message.info({ content: "获取任务中...", duration: 2 });
+  let res = await getSingleStuTask();
+  // message.success({ content: "获取成功", key: mkey });
 
 
-      if (res.data.task) {
-        store.setting.fileServer = res.data.fileServer;
-        store.setting.splitConfig = res.data.splitConfig;
-        store.setting.groupNumber = res.data.groupNumber;
-        store.setting.uiSetting = {
-          "answer.paper.scale": 1,
-          "score.board.collapse": false,
-        } as MarkStore["setting"]["uiSetting"];
+  if (res.data.task) {
+    store.setting.fileServer = res.data.fileServer;
+    store.setting.splitConfig = res.data.splitConfig;
+    store.setting.groupNumber = res.data.groupNumber;
+    store.setting.uiSetting = {
+      "answer.paper.scale": 1,
+      "score.board.collapse": false,
+    } as MarkStore["setting"]["uiSetting"];
 
 
-        let task = res.data.task as Task;
+    let task = res.data.task as Task;
 
 
-        task.sliceUrls = task.sliceUrls.map(
-          (s: string) => store.setting.fileServer + s
-        );
+    task.sliceUrls = task.sliceUrls.map(
+      (s: string) => store.setting.fileServer + s
+    );
 
 
-        store.currentTask = task;
-        if (store.currentTask)
-          store.setting.subject = store.currentTask
-            .subject as MarkStore["setting"]["subject"];
-      } else {
-        store.message = res.data.message;
-      }
-    }
-
-    async function fetchTask() {
-      await updateTask();
-    }
+    store.currentTask = task;
+    if (store.currentTask)
+      store.setting.subject = store.currentTask
+        .subject as MarkStore["setting"]["subject"];
+  } else {
+    store.message = res.data.message;
+  }
+}
 
 
-    onMounted(async () => {
-      await fetchTask();
-    });
+async function fetchTask() {
+  await updateTask();
+}
 
 
-    async function getSingleStuTask() {
-      return getSingleLibraryTask(libraryId as string);
-    }
+onMounted(async () => {
+  await fetchTask();
+});
 
 
-    const renderError = () => {
-      store.currentTask = undefined;
-      store.message = "加载失败,请重新加载。";
-    };
+async function getSingleStuTask() {
+  return getSingleLibraryTask(libraryId as string);
+}
 
 
-    return {
-      store,
-      fetchTask,
-      renderError,
-    };
-  },
-});
+const renderError = () => {
+  store.currentTask = undefined;
+  store.message = "加载失败,请重新加载。";
+};
 </script>
 </script>
 
 
 <style scoped>
 <style scoped>
 .my-container {
 .my-container {
   width: 100%;
   width: 100%;
 }
 }
-a {
-  color: #42b983;
-}
-
-label {
-  margin: 0 0.5em;
-  font-weight: bold;
-}
-
-code {
-  background-color: #eee;
-  padding: 2px 4px;
-  border-radius: 4px;
-  color: #304455;
-}
 </style>
 </style>

+ 4 - 10
src/features/library/libraryTrack/MarkBody.vue

@@ -5,22 +5,16 @@
     :store="store"
     :store="store"
     uniquePropName="libraryId"
     uniquePropName="libraryId"
     @error="$emit('error')"
     @error="$emit('error')"
+    :makeTrack="() => {}"
   />
   />
 </template>
 </template>
 
 
-<script lang="ts">
+<script setup lang="ts">
 import CommonMarkBody from "@/features/mark/CommonMarkBody.vue";
 import CommonMarkBody from "@/features/mark/CommonMarkBody.vue";
-import { defineComponent, watch } from "vue";
+import { defineEmit } from "vue";
 import { store } from "@/features/mark/store";
 import { store } from "@/features/mark/store";
 
 
-export default defineComponent({
-  name: "MarkBody",
-  components: { CommonMarkBody },
-  emits: ["error"],
-  setup() {
-    return { store };
-  },
-});
+defineEmit(["error"]);
 </script>
 </script>
 
 
 <style scoped></style>
 <style scoped></style>

+ 24 - 56
src/features/library/libraryTrack/MarkHeader.vue

@@ -58,71 +58,39 @@
   </div>
   </div>
 </template>
 </template>
 
 
-<script lang="ts">
-import { computed, defineComponent } from "vue";
+<script setup lang="ts">
+import { computed } from "vue";
 import { store } from "@/features/mark/store";
 import { store } from "@/features/mark/store";
 import {
 import {
   ZoomInOutlined,
   ZoomInOutlined,
   ZoomOutOutlined,
   ZoomOutOutlined,
   FullscreenOutlined,
   FullscreenOutlined,
-  SnippetsOutlined,
-  UserOutlined,
   PoweroffOutlined,
   PoweroffOutlined,
-  ClockCircleOutlined,
-  QuestionCircleOutlined,
 } from "@ant-design/icons-vue";
 } from "@ant-design/icons-vue";
-import { useRoute } from "vue-router";
 
 
-export default defineComponent({
-  name: "MarkHeader",
-  components: {
-    ZoomInOutlined,
-    ZoomOutOutlined,
-    FullscreenOutlined,
-    SnippetsOutlined,
-    UserOutlined,
-    PoweroffOutlined,
-    ClockCircleOutlined,
-    QuestionCircleOutlined,
-  },
-  setup() {
-    const route = useRoute();
-
-    const upScale = () => {
-      const s = store.setting.uiSetting["answer.paper.scale"];
-      if (s < 3)
-        store.setting.uiSetting["answer.paper.scale"] = +(s + 0.2).toFixed(1);
-    };
-    const downScale = () => {
-      const s = store.setting.uiSetting["answer.paper.scale"];
-      if (s > 0.2)
-        store.setting.uiSetting["answer.paper.scale"] = +(s - 0.2).toFixed(1);
-    };
-    const normalScale = () => {
-      store.setting.uiSetting["answer.paper.scale"] = 1;
-    };
-    const greaterThanOneScale = computed(() => {
-      return store.setting.uiSetting["answer.paper.scale"] > 1;
-    });
-    const lessThanOneScale = computed(() => {
-      return store.setting.uiSetting["answer.paper.scale"] < 1;
-    });
-
-    const closeWindow = async () => {
-      window.close();
-    };
-
-    return {
-      store,
-      upScale,
-      downScale,
-      normalScale,
-      greaterThanOneScale,
-      lessThanOneScale,
-      closeWindow,
-    };
-  },
+const upScale = () => {
+  const s = store.setting.uiSetting["answer.paper.scale"];
+  if (s < 3)
+    store.setting.uiSetting["answer.paper.scale"] = +(s + 0.2).toFixed(1);
+};
+const downScale = () => {
+  const s = store.setting.uiSetting["answer.paper.scale"];
+  if (s > 0.2)
+    store.setting.uiSetting["answer.paper.scale"] = +(s - 0.2).toFixed(1);
+};
+const normalScale = () => {
+  store.setting.uiSetting["answer.paper.scale"] = 1;
+};
+const greaterThanOneScale = computed(() => {
+  return store.setting.uiSetting["answer.paper.scale"] > 1;
 });
 });
+const lessThanOneScale = computed(() => {
+  return store.setting.uiSetting["answer.paper.scale"] < 1;
+});
+
+const closeWindow = async () => {
+  window.close();
+};
 </script>
 </script>
 
 
 <style scoped>
 <style scoped>

+ 4 - 10
src/features/library/quality/MarkBody.vue

@@ -5,22 +5,16 @@
     :store="store"
     :store="store"
     uniquePropName="studentId"
     uniquePropName="studentId"
     @error="$emit('error')"
     @error="$emit('error')"
+    :makeTrack="() => {}"
   />
   />
 </template>
 </template>
 
 
-<script lang="ts">
+<script setup lang="ts">
 import CommonMarkBody from "@/features/mark/CommonMarkBody.vue";
 import CommonMarkBody from "@/features/mark/CommonMarkBody.vue";
-import { defineComponent, watch } from "vue";
+import { defineEmit } from "vue";
 import { store } from "@/features/mark/store";
 import { store } from "@/features/mark/store";
 
 
-export default defineComponent({
-  name: "MarkBody",
-  components: { CommonMarkBody },
-  emits: ["error"],
-  setup() {
-    return { store };
-  },
-});
+defineEmit(["error"]);
 </script>
 </script>
 
 
 <style scoped></style>
 <style scoped></style>

+ 24 - 86
src/features/library/quality/MarkHeader.vue

@@ -95,103 +95,41 @@
   </div>
   </div>
 </template>
 </template>
 
 
-<script lang="ts">
-import { computed, defineComponent, onMounted, ref } from "vue";
+<script setup lang="ts">
+import { computed, ref } from "vue";
 import { store } from "@/features/mark/store";
 import { store } from "@/features/mark/store";
 import {
 import {
   ZoomInOutlined,
   ZoomInOutlined,
   ZoomOutOutlined,
   ZoomOutOutlined,
   FullscreenOutlined,
   FullscreenOutlined,
-  SnippetsOutlined,
   UserOutlined,
   UserOutlined,
   PoweroffOutlined,
   PoweroffOutlined,
-  ClockCircleOutlined,
-  QuestionCircleOutlined,
   DownOutlined,
   DownOutlined,
 } from "@ant-design/icons-vue";
 } from "@ant-design/icons-vue";
-import { useRoute } from "vue-router";
 
 
-export default defineComponent({
-  name: "MarkHeader",
-  components: {
-    ZoomInOutlined,
-    ZoomOutOutlined,
-    FullscreenOutlined,
-    SnippetsOutlined,
-    UserOutlined,
-    PoweroffOutlined,
-    ClockCircleOutlined,
-    QuestionCircleOutlined,
-    DownOutlined,
-  },
-  setup() {
-    const route = useRoute();
-    let isSingleStudent = ref(false);
-    isSingleStudent.value = !!route.query.studentId;
-    const { studentId, subjectCode, groupNumber } = route.query as {
-      studentId: string;
-      subjectCode: string;
-      groupNumber: string;
-    };
-
-    const upScale = () => {
-      const s = store.setting.uiSetting["answer.paper.scale"];
-      if (s < 3)
-        store.setting.uiSetting["answer.paper.scale"] = +(s + 0.2).toFixed(1);
-    };
-    const downScale = () => {
-      const s = store.setting.uiSetting["answer.paper.scale"];
-      if (s > 0.2)
-        store.setting.uiSetting["answer.paper.scale"] = +(s - 0.2).toFixed(1);
-    };
-    const normalScale = () => {
-      store.setting.uiSetting["answer.paper.scale"] = 1;
-    };
-    const toggleHistory = () => {
-      store.historyOpen = !store.historyOpen;
-    };
-    const greaterThanOneScale = computed(() => {
-      return store.setting.uiSetting["answer.paper.scale"] > 1;
-    });
-    const lessThanOneScale = computed(() => {
-      return store.setting.uiSetting["answer.paper.scale"] < 1;
-    });
-
-    async function updateHistoryTask({
-      pageNumber = 1,
-      pageSize = 10,
-    }: {
-      pageNumber: number; // 从1开始
-      pageSize: number;
-    }) {
-      // const res = await getInspectedHistory({
-      //   pageNumber,
-      //   pageSize,
-      //   subjectCode,
-      // });
-      // if (res.data) {
-      //   store.historyTasks.push(res.data);
-      // }
-    }
-
-    const closeWindow = async () => {
-      window.close();
-    };
-
-    return {
-      store,
-      isSingleStudent,
-      upScale,
-      downScale,
-      normalScale,
-      greaterThanOneScale,
-      lessThanOneScale,
-      updateHistoryTask,
-      toggleHistory,
-      closeWindow,
-    };
-  },
+const upScale = () => {
+  const s = store.setting.uiSetting["answer.paper.scale"];
+  if (s < 3)
+    store.setting.uiSetting["answer.paper.scale"] = +(s + 0.2).toFixed(1);
+};
+const downScale = () => {
+  const s = store.setting.uiSetting["answer.paper.scale"];
+  if (s > 0.2)
+    store.setting.uiSetting["answer.paper.scale"] = +(s - 0.2).toFixed(1);
+};
+const normalScale = () => {
+  store.setting.uiSetting["answer.paper.scale"] = 1;
+};
+const greaterThanOneScale = computed(() => {
+  return store.setting.uiSetting["answer.paper.scale"] > 1;
+});
+const lessThanOneScale = computed(() => {
+  return store.setting.uiSetting["answer.paper.scale"] < 1;
 });
 });
+
+const closeWindow = async () => {
+  window.close();
+};
 </script>
 </script>
 
 
 <style scoped>
 <style scoped>

+ 62 - 84
src/features/library/quality/MarkHistory.vue

@@ -41,101 +41,79 @@
   </div>
   </div>
 </template>
 </template>
 
 
-<script lang="ts">
-import { MarkStore, Task } from "@/types";
-import { defineComponent, ref, watch, watchEffect } from "vue";
+<script setup lang="ts">
+import type { Task } from "@/types";
+import { defineEmit, ref, watchEffect } from "vue";
 import { useRoute } from "vue-router";
 import { useRoute } from "vue-router";
 import { store } from "@/features/mark/store";
 import { store } from "@/features/mark/store";
-import { CloseOutlined } from "@ant-design/icons-vue";
 import { cloneDeep } from "lodash";
 import { cloneDeep } from "lodash";
 import { getQualityHistory } from "@/api/qualityPage";
 import { getQualityHistory } from "@/api/qualityPage";
 
 
-export default defineComponent({
-  name: "MarkHistory",
-  components: { CloseOutlined },
-  emits: ["reload"],
-  setup(props, { emit }) {
-    const route = useRoute();
-    const { markerId, markerScore } = route.query as {
-      markerId: string;
-      markerScore: string;
-    };
+const emit = defineEmit(["reload"]);
+const route = useRoute();
+const { markerId, markerScore } = route.query as {
+  markerId: string;
+  markerScore: string;
+};
 
 
-    watchEffect(async () => {
-      if (store.historyOpen) {
-        replaceCurrentTask(undefined);
-        await updateHistoryTask({});
-        replaceCurrentTask(store.historyTasks[0]);
-      } else {
-        emit("reload");
-      }
-    });
-
-    const secretNumberInput = ref(null);
-    const loading = ref(false);
-    const currentPage = ref(1);
+watchEffect(async () => {
+  if (store.historyOpen) {
+    replaceCurrentTask(undefined);
+    await updateHistoryTask({});
+    replaceCurrentTask(store.historyTasks[0]);
+  } else {
+    emit("reload");
+  }
+});
 
 
-    async function updateHistoryTask({
-      pageNumber = 1,
-      pageSize = 10,
-    }: {
-      pageNumber?: number; // 从1开始
-      pageSize?: number;
-    }) {
-      loading.value = true;
-      const res = await getQualityHistory({
-        markerId,
-        markerScore,
-        pageNumber,
-        pageSize,
-      });
-      loading.value = false;
-      if (res.data) {
-        let data = cloneDeep(res.data) as Array<Task>;
-        data = data.map((t) => {
-          t.sliceUrls = t.sliceUrls.map((s) => store.setting.fileServer + s);
-          t.sheetUrls = t.sheetUrls?.map((s) => store.setting.fileServer + s);
-          t.jsonUrl = store.setting.fileServer + t.jsonUrl;
+const loading = ref(false);
+const currentPage = ref(1);
 
 
-          return t;
-        });
-        store.historyTasks = data;
-        replaceCurrentTask(store.historyTasks[0]);
-      }
-    }
+async function updateHistoryTask({
+  pageNumber = 1,
+  pageSize = 10,
+}: {
+  pageNumber?: number; // 从1开始
+  pageSize?: number;
+}) {
+  loading.value = true;
+  const res = await getQualityHistory({
+    markerId,
+    markerScore,
+    pageNumber,
+    pageSize,
+  });
+  loading.value = false;
+  if (res.data) {
+    let data = cloneDeep(res.data) as Array<Task>;
+    data = data.map((t) => {
+      t.sliceUrls = t.sliceUrls.map((s) => store.setting.fileServer + s);
+      t.sheetUrls = t.sheetUrls?.map((s) => store.setting.fileServer + s);
+      t.jsonUrl = store.setting.fileServer + t.jsonUrl;
 
 
-    function replaceCurrentTask(task: Task | undefined) {
-      store.currentTask = task;
-      // if (task?.subject) {
-      //   store.setting.subject = task.subject as MarkStore["setting"]["subject"];
-      // }
-    }
+      return t;
+    });
+    store.historyTasks = data;
+    replaceCurrentTask(store.historyTasks[0]);
+  }
+}
 
 
-    function previousPage() {
-      if (currentPage.value > 1) {
-        currentPage.value -= 1;
-        updateHistoryTask({ pageNumber: currentPage.value });
-      }
-    }
-    function nextPage() {
-      if (store.historyTasks.length >= 10) {
-        currentPage.value += 1;
-        updateHistoryTask({ pageNumber: currentPage.value });
-      }
-    }
+function replaceCurrentTask(task: Task | undefined) {
+  store.currentTask = task;
+}
 
 
-    return {
-      store,
-      loading,
-      secretNumberInput,
-      updateHistoryTask,
-      replaceCurrentTask,
-      currentPage,
-      previousPage,
-      nextPage,
-    };
-  },
-});
+function previousPage() {
+  if (currentPage.value > 1) {
+    currentPage.value -= 1;
+    updateHistoryTask({ pageNumber: currentPage.value });
+  }
+}
+function nextPage() {
+  if (store.historyTasks.length >= 10) {
+    currentPage.value += 1;
+    updateHistoryTask({ pageNumber: currentPage.value });
+  }
+}
 </script>
 </script>
 
 
 <style scoped>
 <style scoped>

+ 0 - 15
src/features/library/quality/Quality.vue

@@ -88,19 +88,4 @@ export default defineComponent({
 .my-container {
 .my-container {
   width: 100%;
   width: 100%;
 }
 }
-a {
-  color: #42b983;
-}
-
-label {
-  margin: 0 0.5em;
-  font-weight: bold;
-}
-
-code {
-  background-color: #eee;
-  padding: 2px 4px;
-  border-radius: 4px;
-  color: #304455;
-}
 </style>
 </style>

+ 0 - 3
src/features/student/inspect/Inspect.vue

@@ -200,7 +200,4 @@ const renderError = () => {
 .my-container {
 .my-container {
   width: 100%;
   width: 100%;
 }
 }
-a {
-  color: #42b983;
-}
 </style>
 </style>

+ 0 - 15
src/features/student/studentTrack/StudentTrack.vue

@@ -76,19 +76,4 @@ const renderError = () => {
 .my-container {
 .my-container {
   width: 100%;
   width: 100%;
 }
 }
-a {
-  color: #42b983;
-}
-
-label {
-  margin: 0 0.5em;
-  font-weight: bold;
-}
-
-code {
-  background-color: #eee;
-  padding: 2px 4px;
-  border-radius: 4px;
-  color: #304455;
-}
 </style>
 </style>