Răsfoiți Sursa

复用代码

Michael Wang 4 ani în urmă
părinte
comite
cecb1d6438

+ 1 - 1
src/features/student/inspect/Inspect.vue

@@ -23,7 +23,7 @@ import {
   rejectInspectedTask,
   saveInspectedTask,
 } from "@/api/inspectPage";
-import { store } from "./store";
+import { store } from "../store";
 import MarkHeader from "./MarkHeader.vue";
 import { useRoute } from "vue-router";
 import MarkBody from "./MarkBody.vue";

+ 1 - 1
src/features/student/inspect/MarkBoardInspect.vue

@@ -94,7 +94,7 @@
 import type { Question } from "@/types";
 import { message } from "ant-design-vue";
 import { computed, defineEmit, reactive, watch } from "vue";
-import { store } from "./store";
+import { store } from "../store";
 
 const emit = defineEmit(["inspect", "reject"]);
 let checkedQuestions = reactive([] as Array<Question>);

+ 1 - 4
src/features/student/inspect/MarkBody.vue

@@ -30,7 +30,7 @@
 
 <script setup lang="ts">
 import { computed, defineEmit, reactive, ref, watch } from "vue";
-import { store } from "./store";
+import { store } from "../store";
 import MarkDrawTrack from "./MarkDrawTrack.vue";
 import type { SpecialTag, Track } from "@/types";
 import { useTimers } from "@/setups/useTimers";
@@ -163,9 +163,6 @@ const answerPaperScale = computed(() => {
   cursor: grab;
   user-select: none;
 }
-.grabbing {
-  cursor: grabbing;
-}
 .mark-body-container img {
   width: 100%;
 }

+ 1 - 1
src/features/student/inspect/MarkDrawTrack.vue

@@ -24,8 +24,8 @@
 
 <script setup lang="ts">
 import type { SpecialTag, Track } from "@/types";
+import { store } from "../store";
 import { defineProps, watch } from "vue";
-import { store } from "./store";
 
 const props =
   defineProps<{

+ 2 - 21
src/features/student/inspect/MarkHeader.vue

@@ -72,9 +72,9 @@
 </template>
 
 <script setup lang="ts">
-import { clearInspectedTask, getInspectedHistory } from "@/api/inspectPage";
+import { clearInspectedTask } from "@/api/inspectPage";
 import { computed, onMounted, ref } from "vue";
-import { store } from "./store";
+import { store } from "../store";
 import {
   ZoomInOutlined,
   ZoomOutOutlined,
@@ -82,8 +82,6 @@ import {
   SnippetsOutlined,
   UserOutlined,
   PoweroffOutlined,
-  ClockCircleOutlined,
-  QuestionCircleOutlined,
 } from "@ant-design/icons-vue";
 import { useRoute } from "vue-router";
 
@@ -118,23 +116,6 @@ 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(studentId, subjectCode);
 }

+ 1 - 1
src/features/student/inspect/MarkHistory.vue

@@ -56,7 +56,7 @@ import { getInspectedHistory } from "@/api/inspectPage";
 import type { Task } from "@/types";
 import { defineEmit, defineProps, ref, watch, watchEffect } from "vue";
 import { useRoute } from "vue-router";
-import { store } from "./store";
+import { store } from "../store";
 import { CloseOutlined } from "@ant-design/icons-vue";
 import { cloneDeep } from "lodash";
 

+ 0 - 0
src/features/student/inspect/store.ts → src/features/student/store.ts


+ 0 - 174
src/features/student/studentTrack/MarkBody.vue

@@ -1,174 +0,0 @@
-<template>
-  <div class="mark-body-container tw-flex-auto tw-p-2" ref="dragContainer">
-    <a-spin
-      :spinning="rendering"
-      size="large"
-      tip="Loading..."
-      style="margin-top: 50px"
-    >
-      <div v-if="!store.currentTask" class="tw-text-center">
-        {{ store.message }}
-      </div>
-      <div v-else :style="{ width: answerPaperScale }">
-        <div
-          v-for="(item, index) in sliceImagesWithTrackList"
-          :key="index"
-          class="single-image-container"
-        >
-          <img :src="item.url" draggable="false" />
-          <MarkDrawTrack
-            :track-list="item.trackList"
-            :special-tag-list="item.tagList"
-            :original-image="item.originalImage"
-          />
-          <hr class="image-seperator" />
-        </div>
-      </div>
-    </a-spin>
-  </div>
-</template>
-
-<script setup lang="ts">
-import { computed, defineEmit, reactive, ref, watchEffect } from "vue";
-import { store } from "./store";
-import MarkDrawTrack from "./MarkDrawTrack.vue";
-import type { SpecialTag, Track } from "@/types";
-import { useTimers } from "@/setups/useTimers";
-import { loadImage } from "@/utils/utils";
-import { dragImage } from "@/features/mark/use/draggable";
-
-interface SliceImage {
-  url: string;
-  indexInSliceUrls: number;
-  trackList: Array<Track>;
-  tagList: Array<SpecialTag>;
-  originalImage: HTMLImageElement;
-}
-
-const emit = defineEmit(["error"]);
-const { dragContainer } = dragImage();
-
-const { addTimeout } = useTimers();
-
-let rendering = ref(false);
-let sliceImagesWithTrackList: Array<SliceImage> = reactive([]);
-
-async function processImage() {
-  if (!store.currentTask) return;
-
-  const images = [];
-  for (const url of store.currentTask.sliceUrls) {
-    const image = await loadImage(url);
-    images.push(image);
-  }
-
-  for (const url of store.currentTask.sliceUrls) {
-    const completeUrl = url;
-
-    const indexInSliceUrls = store.currentTask.sliceUrls.indexOf(url) + 1;
-    const image = images[indexInSliceUrls - 1];
-
-    const trackLists = store.currentTask.questionList
-      .map((q) => q.trackList)
-      .reduce((acc, t) => {
-        acc = acc.concat(t);
-        return acc;
-      }, [] as Array<Track>);
-    const thisImageTrackList = trackLists.filter(
-      (t) => t.offsetIndex === indexInSliceUrls
-    );
-    const thisImageTagList = store.currentTask.specialTagList.filter(
-      (t) => t.offsetIndex === indexInSliceUrls
-    );
-
-    sliceImagesWithTrackList.push({
-      url: completeUrl,
-      indexInSliceUrls,
-      trackList: thisImageTrackList,
-      tagList: thisImageTagList,
-      originalImage: image,
-    });
-  }
-}
-
-// should not render twice at the same time
-let renderLock = false;
-const renderPaperAndMark = async () => {
-  if (renderLock) {
-    console.log("上个任务还未渲染完毕,稍等一秒再尝试渲染");
-    await new Promise((res) => setTimeout(res, 1000));
-    await renderPaperAndMark();
-    return;
-  }
-  renderLock = true;
-  sliceImagesWithTrackList.splice(0);
-
-  if (!store.currentTask) {
-    renderLock = false;
-    return;
-  }
-
-  try {
-    rendering.value = true;
-    await processImage();
-  } catch (error) {
-    sliceImagesWithTrackList.splice(0);
-    console.log("render error ", error);
-    // 图片加载出错,自动加载下一个任务
-    emit("error");
-  } finally {
-    renderLock = false;
-    rendering.value = false;
-  }
-};
-
-watchEffect(renderPaperAndMark);
-
-const answerPaperScale = computed(() => {
-  // 放大、缩小不影响页面之前的滚动条定位
-  let percentWidth = 0;
-  let percentTop = 0;
-  const container = document.querySelector(
-    ".mark-body-container"
-  ) as HTMLDivElement;
-  if (container) {
-    const { scrollLeft, scrollTop, scrollWidth, scrollHeight } = container;
-    percentWidth = scrollLeft / scrollWidth;
-    percentTop = scrollTop / scrollHeight;
-  }
-
-  addTimeout(() => {
-    if (container) {
-      const { scrollWidth, scrollHeight } = container;
-      container.scrollTo({
-        left: scrollWidth * percentWidth,
-        top: scrollHeight * percentTop,
-      });
-    }
-  }, 10);
-  const scale = store.setting.uiSetting["answer.paper.scale"];
-  return scale * 100 + "%";
-});
-</script>
-
-<style scoped>
-.mark-body-container {
-  height: calc(100vh - 41px);
-  overflow: auto;
-  background-size: 8px 8px;
-  background-image: linear-gradient(to right, #e7e7e7 4px, transparent 4px),
-    linear-gradient(to bottom, transparent 4px, #e7e7e7 4px);
-
-  cursor: grab;
-  user-select: none;
-}
-.mark-body-container img {
-  width: 100%;
-}
-.single-image-container {
-  position: relative;
-}
-.image-seperator {
-  border: 2px solid rgba(120, 120, 120, 0.1);
-}
-</style>

+ 0 - 111
src/features/student/studentTrack/MarkDrawTrack.vue

@@ -1,111 +0,0 @@
-<template>
-  <template v-for="(track, index) in trackList" :key="index">
-    <div
-      class="score-container"
-      :class="[focusedTrack(track) && 'score-animation']"
-      :style="computeTopAndLeft(track)"
-    >
-      <span
-        class="tw-m-auto"
-        :id="'a' + track.mainNumber + track.subNumber + track.offsetY"
-      >
-        {{ track.score }}
-      </span>
-    </div>
-  </template>
-  <template v-for="(tag, index) in specialTagList" :key="index">
-    <div class="score-container" :style="computeTopAndLeft(tag)">
-      <span class="tw-m-auto">
-        {{ tag.tagName }}
-      </span>
-    </div>
-  </template>
-</template>
-
-<script setup lang="ts">
-import type { SpecialTag, Track } from "@/types";
-import { defineProps, watch } from "vue";
-import { store } from "./store";
-
-const props =
-  defineProps<{
-    trackList: Array<Track>;
-    specialTagList: Array<SpecialTag>;
-    originalImage: HTMLImageElement;
-  }>();
-const { originalImage } = props;
-
-const focusedTrack = (track: Track) => {
-  return store.focusTracks.includes(track);
-};
-const computeTopAndLeft = (track: Track | SpecialTag) => {
-  const topInsideSlice = track.offsetY;
-  const leftInsideSlice = track.offsetX;
-  return {
-    top: (topInsideSlice / originalImage.naturalHeight) * 100 + "%",
-    left: (leftInsideSlice / originalImage.naturalWidth) * 100 + "%",
-    "font-size": store.setting.uiSetting["answer.paper.scale"] * 2.2 + "em",
-  };
-};
-
-watch(
-  () => store.focusTracks.length,
-  () => {
-    if (store.focusTracks.length === 0) return;
-    const minImageIndex = Math.min(
-      ...store.focusTracks.map((t) => t.offsetIndex)
-    );
-    const minImageOffsetY = Math.min(
-      ...store.focusTracks
-        .filter((t) => t.offsetIndex === minImageIndex)
-        .map((t) => t.offsetY)
-    );
-    const topTrack = store.focusTracks.find(
-      (t) => t.offsetIndex === minImageIndex && t.offsetY === minImageOffsetY
-    );
-    if (topTrack) {
-      document
-        .querySelector(
-          `#a${topTrack.mainNumber + topTrack.subNumber + topTrack.offsetY}`
-        )
-        ?.scrollIntoView({ behavior: "smooth" });
-    }
-  }
-);
-</script>
-
-<style scoped>
-.score-container {
-  position: absolute;
-  display: flex;
-  place-content: center;
-  color: red;
-
-  /* to center score */
-  width: 200px;
-  height: 200px;
-  margin-top: -100px;
-  margin-left: -100px;
-
-  /* to click through div */
-  pointer-events: none;
-}
-.score-animation {
-  animation: 2s ease-in-out 0s infinite alternate change_size;
-}
-
-@keyframes change_size {
-  from {
-    color: red;
-    font-size: 2em;
-    margin-top: -100px;
-    margin-left: -100px;
-  }
-  to {
-    color: black;
-    font-size: 4em;
-    margin-top: -80px;
-    margin-left: -80px;
-  }
-}
-</style>

+ 1 - 4
src/features/student/studentTrack/MarkHeader.vue

@@ -48,16 +48,13 @@
 
 <script setup lang="ts">
 import { computed } from "vue";
-import { store } from "./store";
+import { store } from "../store";
 import {
   ZoomInOutlined,
   ZoomOutOutlined,
   FullscreenOutlined,
   PoweroffOutlined,
 } from "@ant-design/icons-vue";
-import { useRoute } from "vue-router";
-
-const route = useRoute();
 
 const upScale = () => {
   const s = store.setting.uiSetting["answer.paper.scale"];

+ 2 - 2
src/features/student/studentTrack/StudentTrack.vue

@@ -9,10 +9,10 @@
 
 <script setup lang="ts">
 import { onMounted } from "vue";
-import { store } from "./store";
+import { store } from "../store";
 import MarkHeader from "./MarkHeader.vue";
 import { useRoute } from "vue-router";
-import MarkBody from "./MarkBody.vue";
+import MarkBody from "../inspect/MarkBody.vue";
 import type { Task } from "@/types";
 import { message } from "ant-design-vue";
 import { getSingleStudentTask } from "@/api/studentTrackPage";

+ 0 - 26
src/features/student/studentTrack/store.ts

@@ -1,26 +0,0 @@
-import { InspectStore, Task } from "@/types";
-import { reactive } from "vue";
-
-const obj = {
-  setting: {
-    fileServer: "",
-    userName: "",
-    subject: { name: "", code: "" },
-    uiSetting: {
-      "answer.paper.scale": 1,
-      "score.board.collapse": false,
-    },
-    splitConfig: [],
-  },
-  status: {
-    totalCount: 0,
-  },
-  currentTask: undefined,
-  historyOpen: false,
-  MarkBoardTrackCollapse: false,
-  historyTasks: [],
-  focusTracks: [],
-  message: null,
-} as InspectStore;
-
-export const store = reactive(obj);