Browse Source

复核:单个学生,初始化

Michael Wang 4 years ago
parent
commit
49990cb750

+ 6 - 0
src/api/inspectPage.ts

@@ -0,0 +1,6 @@
+import { httpApp } from "@/plugins/axiosApp";
+
+/** 查看单个学生的复核任务 */
+export async function getSingleStudentTask(studentId: string) {
+  return httpApp.post("/admin/exam/inspected/getTask?studentId=" + studentId);
+}

+ 166 - 0
src/components/inspect/Inspect.vue

@@ -0,0 +1,166 @@
+<template>
+  <div class="my-container">
+    <mark-header />
+    <!-- <div class="tw-flex tw-gap-1">
+      <mark-history />
+      <mark-body />
+      <mark-board-track v-if="showMarkBoardTrack" @submit="saveTaskToServer" />
+      <mark-board-key-board
+        v-if="showMarkBoardKeyBoard"
+        @submit="saveTaskToServer"
+      />
+      <mark-board-mouse v-if="showMarkBoardMouse" @submit="saveTaskToServer" />
+    </div> -->
+  </div>
+</template>
+
+<script lang="ts">
+import { computed, defineComponent, onMounted, watch } from "vue";
+import { getSingleStudentTask } from "@/api/inspectPage";
+import { store } from "./store";
+import MarkHeader from "./MarkHeader.vue";
+// import MarkBody from "./MarkBody.vue";
+import { useTimers } from "@/setups/useTimers";
+// import MarkHistory from "./MarkHistory.vue";
+
+export default defineComponent({
+  name: "Inspect",
+  components: {
+    MarkHeader,
+    // MarkBody,
+    // MarkHistory,
+  },
+  setup: () => {
+    // const { addInterval } = useTimers();
+
+    // async function updateMarkTask() {
+    //   const settingRes = await clearMarkTask();
+    // }
+
+    // async function updateSetting() {
+    //   const settingRes = await getSetting();
+    //   // settingRes.data.uiSetting["answer.paper.scale"] ||= 1;
+    //   if (isEmpty(settingRes.data.uiSetting)) {
+    //     settingRes.data.uiSetting = {
+    //       "answer.paper.scale": 1,
+    //       "score.board.collapse": false,
+    //       "normal.mode": "keyboard",
+    //     } as Setting["uiSetting"];
+    //   }
+    //   store.setting = settingRes.data;
+    // }
+    // async function updateStatus() {
+    //   const res = await getStatus();
+    //   store.status = res.data;
+    // }
+    // async function updateGroups() {
+    //   const res = await getGroup();
+    //   store.groups = res.data;
+    // }
+    // async function updateTask() {
+    //   const res = await getTask();
+    //   if (res.data.libraryId) {
+    //     store.tasks.push(res.data);
+    //     store.currentTask = store.tasks[0];
+    //   }
+    // }
+
+    // // 5秒更新一次tasks
+    // addInterval(() => {
+    //   // console.log("get task", store.tasks);
+    //   if (store.tasks.length < 3) {
+    //     updateTask();
+    //   }
+    // }, 5 * 1000);
+
+    // // TODO: 后续改掉,不需要
+    // addInterval(() => {
+    //   updateStatus();
+    // }, 30 * 1000);
+
+    // onMounted(async () => {
+    //   await updateMarkTask();
+    //   updateSetting();
+    //   updateStatus();
+    //   updateGroups();
+    //   updateTask();
+    // });
+
+    // watch(
+    //   () => [store.setting.uiSetting, store.setting.mode],
+    //   () => {
+    //     updateUISetting(store.setting.mode, store.setting.uiSetting);
+    //   },
+    //   { deep: true }
+    // );
+
+    // const showMarkBoardTrack = computed(() => {
+    //   return store.setting.mode === ModeEnum.TRACK;
+    // });
+
+    // const showMarkBoardKeyBoard = computed(() => {
+    //   return (
+    //     store.setting.mode === ModeEnum.COMMON &&
+    //     store.setting.uiSetting["normal.mode"] === "keyboard"
+    //   );
+    // });
+
+    // const showMarkBoardMouse = computed(() => {
+    //   return (
+    //     store.setting.mode === ModeEnum.COMMON &&
+    //     store.setting.uiSetting["normal.mode"] === "mouse"
+    //   );
+    // });
+
+    // const saveTaskToServer = async () => {
+    //   console.log("save task to server");
+    //   const res = (await saveTask()) as any;
+    //   updateStatus();
+    //   if (res.data.success && store.currentTask) {
+    //     let { libraryId, studentId } = store.currentTask;
+    //     const i = store.markResults.findIndex(
+    //       (s) => s.libraryId === libraryId && s.studentId === studentId
+    //     );
+    //     store.markResults.splice(i, 1);
+    //     store.currentTask = undefined;
+    //     store.tasks.shift();
+    //   } else {
+    //     console.log(res.data.message);
+    //   }
+    // };
+
+    async function getSingleStuTask() {
+      return getSingleStudentTask("1581");
+    }
+    console.log(getSingleStuTask());
+    return {
+      store,
+      // saveTaskToServer,
+      // showMarkBoardTrack,
+      // showMarkBoardKeyBoard,
+      // showMarkBoardMouse,
+    };
+  },
+});
+</script>
+
+<style scoped>
+.my-container {
+  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>

+ 198 - 0
src/components/inspect/MarkHeader.vue

@@ -0,0 +1,198 @@
+<template>
+  <div
+    class="tw-flex tw-gap-4 tw-justify-between tw-items-center header-bg"
+    style="z-index: 10000; position: relative; font-size: 16px; height: 40px"
+  >
+    <div>
+      {{ store.setting.subject?.name }}
+    </div>
+    <div class="tw-flex tw-gap-1">
+      <div>
+        编号<span class="highlight-text">{{
+          store.currentTask?.secretNumber
+        }}</span>
+      </div>
+    </div>
+    <ul class="tw-flex tw-gap-2 tw-mb-0">
+      <li @click="upScale" title="放大" style="line-height: 20px">
+        <PlusCircleOutlined
+          :style="{
+            'font-size': '20px',
+            color: greaterThanOneScale ? 'red' : 'white',
+          }"
+        />
+      </li>
+      <li @click="downScale" title="缩小" style="line-height: 20px">
+        <MinusCircleOutlined
+          :style="{
+            'font-size': '20px',
+            color: lessThanOneScale ? 'red' : 'white',
+          }"
+        />
+      </li>
+      <li @click="normalScale" title="适应" style="line-height: 20px">
+        <FullscreenOutlined :style="{ 'font-size': '20px' }" />
+      </li>
+    </ul>
+    <div @click="toggleSettingMode" style="line-height: 20px">
+      {{ modeName }} {{ store.setting.forceMode ? "" : "(切换)" }}
+    </div>
+    <div @click="toggleHistory" style="line-height: 20px" title="回看">
+      <HistoryOutlined :style="{ 'font-size': '20px' }" />
+    </div>
+    <div class="tw-flex tw-place-items-center">
+      <UserOutlined
+        :style="{ 'font-size': '18px' }"
+        style="line-height: 18px"
+      />{{ store.setting.marker?.name }}
+    </div>
+    <div class="tw-flex tw-place-items-center">
+      <PoweroffOutlined
+        :style="{ 'font-size': '18px' }"
+        style="line-height: 18px"
+      />退出
+    </div>
+  </div>
+</template>
+
+<script lang="ts">
+import { getGroups, getHistoryTask } from "@/api/markPage";
+import { computed, defineComponent } from "vue";
+import { store } from "./store";
+import {
+  PlusCircleOutlined,
+  MinusCircleOutlined,
+  FullscreenOutlined,
+  HistoryOutlined,
+  UserOutlined,
+  PoweroffOutlined,
+  ClockCircleOutlined,
+  QuestionCircleOutlined,
+} from "@ant-design/icons-vue";
+import { ModeEnum } from "@/types";
+
+export default defineComponent({
+  name: "MarkHeader",
+  components: {
+    PlusCircleOutlined,
+    MinusCircleOutlined,
+    FullscreenOutlined,
+    HistoryOutlined,
+    UserOutlined,
+    PoweroffOutlined,
+    ClockCircleOutlined,
+    QuestionCircleOutlined,
+  },
+  setup() {
+    const modeName = computed(() =>
+      store.setting.mode === ModeEnum.TRACK ? "轨迹模式" : "普通模式"
+    );
+    function toggleSettingMode() {
+      if (store.setting.mode === ModeEnum.TRACK) {
+        store.setting.mode = ModeEnum.COMMON;
+      } else {
+        store.setting.mode = ModeEnum.TRACK;
+      }
+      if (store.currentMarkResult) {
+        store.currentMarkResult.scoreList = [];
+        store.currentMarkResult.trackList = [];
+      }
+      if (store.currentTask) {
+        store.currentTask.questionList.forEach((q) => (q.score = null));
+      }
+      store.currentQuestion = undefined;
+      store.currentScore = undefined;
+    }
+    const progress = computed(() => {
+      const { totalCount, markedCount } = store.status;
+      if (totalCount <= 0) return 0;
+      let p = markedCount / totalCount;
+      if (p < 0.01 && markedCount >= 1) p = 0.01;
+      p = Math.floor(p * 100);
+      return p;
+    });
+    const group = computed(() => {
+      return store.groups.find((g) => g.number === store.setting.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;
+    });
+
+    async function switchGroupDialog() {
+      const groups = await getGroups();
+      console.log(groups);
+    }
+
+    async function updateHistoryTask({
+      pageNumber = 1,
+      pageSize = 10,
+      order = "markerTime",
+      sort = "DESC",
+      secretNumber = null,
+    }: {
+      pageNumber: number; // 从1开始
+      pageSize: number;
+      order: "markerTime" | "markerScore";
+      sort: "ASC" | "DESC";
+      secretNumber: string | null;
+    }) {
+      const res = await getHistoryTask({
+        pageNumber,
+        pageSize,
+        order,
+        sort,
+        secretNumber,
+      });
+      if (res.data) {
+        store.historyTasks.push(res.data);
+      }
+    }
+
+    return {
+      store,
+      modeName,
+      toggleSettingMode,
+      progress,
+      group,
+      upScale,
+      downScale,
+      normalScale,
+      greaterThanOneScale,
+      lessThanOneScale,
+      updateHistoryTask,
+      toggleHistory,
+      switchGroupDialog,
+    };
+  },
+});
+</script>
+
+<style scoped>
+.header-bg {
+  background-color: #5d6d7d;
+  color: white;
+}
+.highlight-text {
+  color: #ffe400;
+}
+</style>

+ 46 - 0
src/components/inspect/store.ts

@@ -0,0 +1,46 @@
+import { ModeEnum, Setting, MarkStore, Task } from "@/types";
+import { reactive, watch } from "vue";
+
+const obj = {
+  setting: {
+    mode: "TRACK",
+    examType: "SCAN_IMAGE",
+    forceMode: false,
+    sheetView: false,
+    sheetConfig: [],
+    enableAllZero: false,
+    fileServer: "",
+    marker: <Setting["marker"]>{},
+    subject: <Setting["subject"]>{},
+    forceSpecialTag: false,
+    uiSetting: {
+      "answer.paper.scale": 1,
+      "score.board.collapse": false,
+      "normal.mode": "keyboard",
+    },
+    statusValue: "FORMAL",
+    problemTypes: [],
+    groupNumber: 0,
+    topCount: 0,
+    splitConfig: [],
+    prefetchCount: 3,
+    startTime: 0,
+    endTime: 0,
+  },
+  status: <MarkStore["status"]>{},
+  groups: [],
+  tasks: [],
+  currentMarkResult: undefined,
+  currentTask: <Task>{},
+  currentQuestion: undefined,
+  currentScore: undefined,
+  markResults: [],
+  historyOpen: false,
+  MarkBoardTrackCollapse: false,
+  historyTasks: [],
+} as MarkStore;
+
+/** 给当前任务评分 */
+export function markScore() {}
+
+export const store = reactive(obj);

+ 3 - 1
src/router/index.ts

@@ -1,9 +1,11 @@
 import { createRouter, createWebHistory } from "vue-router";
 import Mark from "@/components/mark/Mark.vue";
+import Inspect from "@/components/inspect/Inspect.vue";
 
 const routes = [
   { path: "/", component: Mark },
   { path: "/mark", component: Mark },
+  { path: "/admin/exam/inspected/start", component: Inspect },
 ];
 
 // 3. Create the router instance and pass the `routes` option
@@ -11,7 +13,7 @@ const routes = [
 // keep it simple for now.
 const router = createRouter({
   // 4. Provide the history implementation to use. We are using the hash history for simplicity here.
-  history: createWebHistory(),
+  history: createWebHistory("web"),
   routes, // short for `routes: routes`
 });