Browse Source

加锁: 防止试卷被重新渲染

Michael Wang 4 years ago
parent
commit
fa615ef361
2 changed files with 76 additions and 38 deletions
  1. 10 2
      src/features/mark/Mark.vue
  2. 66 36
      src/features/mark/MarkBody.vue

+ 10 - 2
src/features/mark/Mark.vue

@@ -3,7 +3,7 @@
     <mark-header />
     <div class="tw-flex tw-gap-1">
       <mark-history />
-      <mark-body />
+      <mark-body @error="updateTask" />
       <mark-board-track v-if="showMarkBoardTrack" @submit="saveTaskToServer" />
       <mark-board-key-board
         v-if="showMarkBoardKeyBoard"
@@ -84,7 +84,14 @@ export default defineComponent({
         store.tasks.push(res.data);
         if (!store.historyOpen) {
           // 回评中,不能替换task
-          store.currentTask = store.tasks[0];
+          // TODO: 疑似替换多次引起重新渲染
+          if (store.currentTask?.studentId !== store.tasks[0].studentId)
+            store.currentTask = store.tasks[0];
+        }
+
+        // 如果是评完后,再取到的任务,则此时要更新一下status
+        if (store.status.totalCount - store.status.markedCount === 0) {
+          await updateStatus();
         }
       }
     }
@@ -167,6 +174,7 @@ export default defineComponent({
 
     return {
       store,
+      updateTask,
       saveTaskToServer,
       showMarkBoardTrack,
       showMarkBoardKeyBoard,

+ 66 - 36
src/features/mark/MarkBody.vue

@@ -1,27 +1,29 @@
 <template>
   <div class="mark-body-container tw-flex-auto tw-p-2" ref="dragContainer">
-    <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"
-          @click="(event) => makeScoreTrack(event, item)"
-          draggable="false"
-        />
-        <MarkDrawTrack
-          :track-list="item.trackList"
-          :original-image="item.originalImage"
-          :slice-image="item.sliceImage"
-          :dx="item.dx"
-          :dy="item.dy"
-        />
-        <hr class="image-seperator" />
+    <a-spin :spinning="rendering" tip="Loading...">
+      <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"
+            @click="(event) => makeScoreTrack(event, item)"
+            draggable="false"
+          />
+          <MarkDrawTrack
+            :track-list="item.trackList"
+            :original-image="item.originalImage"
+            :slice-image="item.sliceImage"
+            :dx="item.dx"
+            :dy="item.dy"
+          />
+          <hr class="image-seperator" />
+        </div>
       </div>
-    </div>
+    </a-spin>
   </div>
   <div class="cursor">
     <div class="cursor-border">
@@ -37,6 +39,7 @@ import {
   onMounted,
   onUnmounted,
   reactive,
+  ref,
   watch,
   watchEffect,
 } from "vue";
@@ -63,10 +66,13 @@ interface SliceImage {
   accumTopHeight: number;
   effectiveWidth: number;
 }
+// should not render twice at the same time
+let __lock = false;
 export default defineComponent({
   name: "MarkBody",
   components: { MarkDrawTrack },
-  setup() {
+  emits: ["error"],
+  setup(props, { emit }) {
     const { dragContainer } = dragImage();
 
     const { addTimeout } = useTimers();
@@ -75,6 +81,7 @@ export default defineComponent({
       return store.currentTask?.sliceConfig?.length;
     }
 
+    let rendering = ref(false);
     let sliceImagesWithTrackList: Array<SliceImage> = reactive([]);
     let _studentId = -1; // 判断是否改变了任务
     let maxSliceWidth = 0; // 最大的裁切块宽度,图片容器以此为准
@@ -87,9 +94,9 @@ export default defineComponent({
       if (!markResult || !store.currentTask) return;
 
       // TODO: 图片加载出错,自动加载下一个任务
-      for (const url of store.currentTask.sliceUrls) {
-        await loadImage(filters.toCompleteUrl(url));
-      }
+      // for (const url of store.currentTask.sliceUrls) {
+      //   await loadImage(filters.toCompleteUrl(url));
+      // }
       // 必须要先加载一遍,把“选择整图”的宽高重置后,再算总高度
       for (const sliceConfig of store.currentTask.sliceConfig) {
         const url = filters.toCompleteUrl(
@@ -259,11 +266,23 @@ export default defineComponent({
     // 供回退和清除使用
     // let trackLen = store.currentMarkResult?.trackList.length;
     const renderPaperAndMark = async () => {
+      if (__lock) {
+        await new Promise((res) => setTimeout(res, 1000));
+        await renderPaperAndMark();
+      }
+      __lock = true;
+      sliceImagesWithTrackList.splice(0);
       // check if have MarkResult for currentTask
       let markResult = findCurrentTaskMarkResult();
-      if (!store.currentTask) _studentId = -1;
+      // if (!store.currentTask) {
+      //   sliceImagesWithTrackList.splice(0);
+      //   _studentId = -1;
+      // }
 
-      if (!markResult || !store.currentTask) return;
+      if (!markResult || !store.currentTask) {
+        __lock = false;
+        return;
+      }
       // console.log(markResult.trackList.length);
       // if (markResult.trackList.length !== trackLen) {
       //   sliceImagesWithTrackList.splice(0);
@@ -271,16 +290,26 @@ export default defineComponent({
       // }
 
       // reset sliceImagesWithTrackList ,当切换任务时,要重新绘制图片和轨迹
-      if (_studentId !== store.currentTask.studentId) {
-        // 还原轨迹用得上
-        sliceImagesWithTrackList.splice(0);
-        _studentId = store.currentTask.studentId;
-      }
+      // if (_studentId !== store.currentTask.studentId) {
+      //   // 还原轨迹用得上
+      //   sliceImagesWithTrackList.splice(0);
+      //   _studentId = store.currentTask.studentId;
+      // }
 
-      if (hasSliceConfig()) {
-        await processSliceConfig();
-      } else {
-        await processSplitConfig();
+      try {
+        rendering.value = true;
+        if (hasSliceConfig()) {
+          await processSliceConfig();
+        } else {
+          await processSplitConfig();
+        }
+      } catch (error) {
+        sliceImagesWithTrackList.splice(0);
+        console.log("render error ", error);
+        emit("error");
+      } finally {
+        __lock = false;
+        rendering.value = false;
       }
     };
 
@@ -491,6 +520,7 @@ export default defineComponent({
     return {
       dragContainer,
       store,
+      rendering,
       sliceImagesWithTrackList,
       answerPaperScale,
       makeScoreTrack,