Michael Wang 4 år sedan
förälder
incheckning
d59f3d4709

+ 3 - 2
src/features/inspect/MarkBoardInspect.vue

@@ -12,7 +12,8 @@
       <template v-for="(groupNumber, index) in groups" :key="index">
         <div class="tw-mb-4">
           <div
-            class="tw-flex tw-justify-between tw-place-items-center"
+            class="tw-flex tw-justify-between tw-place-items-center hover:tw-bg-gray-200"
+            style="border-bottom: 1px solid grey"
             @mouseover="addFocusTrack(groupNumber, undefined, undefined)"
             @mouseleave="removeFocusTrack"
           >
@@ -236,7 +237,7 @@ export default defineComponent({
 }
 .question {
   min-width: 100px;
-  border-bottom: 1px solid grey;
+  border-bottom: 1px dotted grey;
 }
 
 .current-question {

+ 80 - 83
src/features/inspect/MarkBody.vue

@@ -1,60 +1,68 @@
 <template>
-  <div
-    class="mark-body-container tw-flex-auto tw-p-2"
-    :class="isGrabbing && 'grabbing'"
-    ref="container"
-    @mousedown="mouseDownHandler"
-    @mouseup="mouseUpHandler"
-    @mousemove="mouseMoveHandler"
-  >
-    <div v-if="!store.currentTask" class="tw-text-center">暂无待复核任务</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"
-          :original-image="item.originalImage"
-        />
-        <hr class="image-seperator" />
+  <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>
+      <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 lang="ts">
-import {
-  computed,
-  defineComponent,
-  onUnmounted,
-  reactive,
-  ref,
-  watchEffect,
-} from "vue";
+import { computed, defineComponent, reactive, ref, watchEffect } from "vue";
 import { store } from "./store";
 import filters from "@/filters";
 import MarkDrawTrack from "./MarkDrawTrack.vue";
-import { Track } from "@/types";
+import { SpecialTag, Track } from "@/types";
 import { useTimers } from "@/setups/useTimers";
-import { loadImage } from "@/utils/utils";
+import {
+  getDataUrlForSliceConfig,
+  getDataUrlForSplitConfig,
+  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;
 }
+// should not render twice at the same time
+let __lock = false;
+let __currentLibraryId = -1; // save __currentLibraryId of lock
 export default defineComponent({
   name: "MarkBody",
   components: { MarkDrawTrack },
-  setup() {
+  emits: ["error"],
+  setup(props, { emit }) {
+    const { dragContainer } = dragImage();
+
     const { addTimeout } = useTimers();
 
+    let rendering = ref(false);
     let sliceImagesWithTrackList: Array<SliceImage> = reactive([]);
-    let _studentId = -1; // 判断是否改变了任务
 
     async function processImage() {
       if (!store.currentTask) return;
@@ -67,14 +75,14 @@ export default defineComponent({
         images.push(image);
       }
 
-      // TODO: add loading
       for (const url of store.currentTask.sliceUrls) {
         const completeUrl = filters.toCompleteUrlWithFileServer(
           store.setting.fileServer,
           url
         );
 
-        const image = await loadImage(completeUrl);
+        const indexInSliceUrls = store.currentTask.sliceUrls.indexOf(url) + 1;
+        const image = images[indexInSliceUrls - 1];
 
         const trackLists = store.currentTask.questionList
           .map((q) => q.trackList)
@@ -83,30 +91,53 @@ export default defineComponent({
             return acc;
           }, [] as Array<Track>);
         const thisImageTrackList = trackLists.filter(
-          (t) =>
-            t.offsetIndex ===
-            (store.currentTask && store.currentTask.sliceUrls.indexOf(url) + 1)
+          (t) => t.offsetIndex === indexInSliceUrls
+        );
+        const thisImageTagList = store.currentTask.specialTagList.filter(
+          (t) => t.offsetIndex === indexInSliceUrls
         );
 
         sliceImagesWithTrackList.push({
           url: completeUrl,
-          indexInSliceUrls: store.currentTask.sliceUrls.indexOf(url) + 1,
+          indexInSliceUrls,
           trackList: thisImageTrackList,
+          tagList: thisImageTagList,
           originalImage: image,
         });
       }
     }
     const renderPaperAndMark = async () => {
-      if (!store.currentTask) return;
+      if (__lock) {
+        if (store.currentTask?.libraryId === __currentLibraryId) {
+          console.log("重复渲染,返回");
+          return;
+        }
+        console.log("上个任务还未渲染完毕,稍等一秒再尝试渲染");
+        await new Promise((res) => setTimeout(res, 1000));
+        await renderPaperAndMark();
+        return;
+      }
+      __lock = true;
+      __currentLibraryId = store.currentTask?.libraryId ?? -1;
+      sliceImagesWithTrackList.splice(0);
 
-      // reset sliceImagesWithTrackList ,当切换任务时,要重新绘制图片和轨迹
-      if (_studentId !== store.currentTask.studentId) {
-        // 还原轨迹用得上
-        sliceImagesWithTrackList.splice(0);
-        _studentId = store.currentTask.studentId;
+      if (!store.currentTask) {
+        __lock = false;
+        return;
       }
 
-      await processImage();
+      try {
+        rendering.value = true;
+        await processImage();
+      } catch (error) {
+        sliceImagesWithTrackList.splice(0);
+        console.log("render error ", error);
+        // 图片加载出错,自动加载下一个任务
+        emit("error");
+      } finally {
+        __lock = false;
+        rendering.value = false;
+      }
     };
 
     watchEffect(renderPaperAndMark);
@@ -137,46 +168,12 @@ export default defineComponent({
       return scale * 100 + "%";
     });
 
-    // grab moving
-    let pos = { top: 0, left: 0, x: 0, y: 0 };
-    const container = ref((null as unknown) as HTMLDivElement);
-    const isGrabbing = ref(false);
-
-    const mouseDownHandler = function (e: MouseEvent) {
-      pos = {
-        // The current scroll
-        left: container.value.scrollLeft,
-        top: container.value.scrollTop,
-        // Get the current mouse position
-        x: e.clientX,
-        y: e.clientY,
-      };
-      isGrabbing.value = true;
-    };
-
-    const mouseMoveHandler = function (e: MouseEvent) {
-      if (!isGrabbing.value) return;
-      // How far the mouse has been moved
-      const dx = e.clientX - pos.x;
-      const dy = e.clientY - pos.y;
-
-      // Scroll the element
-      container.value.scrollTop = pos.top - dy;
-      container.value.scrollLeft = pos.left - dx;
-    };
-    const mouseUpHandler = function () {
-      isGrabbing.value = false;
-    };
-
     return {
+      dragContainer,
       store,
+      rendering,
       sliceImagesWithTrackList,
       answerPaperScale,
-      container,
-      isGrabbing,
-      mouseDownHandler,
-      mouseMoveHandler,
-      mouseUpHandler,
     };
   },
 });

+ 0 - 1
src/features/mark/MarkBody.vue

@@ -222,7 +222,6 @@ export default defineComponent({
         images.push(image);
       }
 
-      // TODO: add loading
       const splitConfigPairs = (store.setting.splitConfig
         .map((v, index, ary) => (index % 2 === 0 ? [v, ary[index + 1]] : false))
         .filter((v) => v) as unknown) as Array<[number, number]>;