zhangjie 2 сар өмнө
parent
commit
c489719d97

+ 1 - 1
src/features/mark/MarkBodyBase.vue

@@ -27,7 +27,7 @@
           v-for="(item, index) in markStore.sliceImagesWithTrackList"
           :key="index"
         >
-          <div class="single-image-container">
+          <div :id="item.sliceId" class="single-image-container">
             <img
               :src="item.url"
               draggable="false"

+ 15 - 2
src/features/mark/composables/useAutoChooseFirstQuestion.ts

@@ -19,12 +19,13 @@ export default function useAutoChooseFirstQuestion() {
         markStore.currentQuestion = undefined;
         markStore.currentScore = undefined;
 
-        // FIXed ME: 此时取到的还是score:null,但是 chooseQuestion之后就变成了score:0
         const firstQuestion = markStore.currentTask?.questionList.find(
           (question) => !isDisabledQuestion(question)
         );
         if (firstQuestion) {
-          chooseQuestion(firstQuestion);
+          setTimeout(() => {
+            chooseQuestion(firstQuestion);
+          }, 300);
         }
       },
       {
@@ -68,12 +69,24 @@ export default function useAutoChooseFirstQuestion() {
     }
   };
 
+  const scrollToQuestionArea = (question: Question) => {
+    const area = question.picList && question.picList[0];
+    if (!area) return;
+
+    const areaNode = document.getElementById(
+      `${area.i}_${area.x}_${area.y}_${area.w}_${area.h}`
+    );
+    if (!areaNode) return;
+    areaNode.scrollIntoView({ block: "start", behavior: "smooth" });
+  };
+
   function chooseQuestion(question: Question) {
     if (isDisabledQuestion(question)) return;
 
     markStore.currentQuestion = question;
     // FIXME: maybe should be an async function, temp fix for eslint
     void scrollToQuestionOfBoard(question);
+    scrollToQuestionArea(question);
 
     void nextTick(() => {
       if (markStore.currentQuestion) {

+ 19 - 0
src/features/mark/composables/useMakeTrack.ts

@@ -1,6 +1,7 @@
 import { SliceImage, SpecialTag, Track, Question, SplitConfig } from "@/types";
 import { useMarkStore } from "@/store";
 import { randomCode } from "@/utils/utils";
+import { message } from "ant-design-vue";
 
 export default function useMakeTrack() {
   const markStore = useMarkStore();
@@ -131,8 +132,26 @@ export default function useMakeTrack() {
     item.tagList.push(track);
   }
 
+  function checkTrackValidate(item: SliceImage): boolean {
+    if (!markStore.currentQuestion) return true;
+
+    const valid = (markStore.currentQuestion.picList || []).some(
+      (area) =>
+        `${area.i}_${area.x}_${area.y}_${area.w}_${area.h}` === item.sliceId
+    );
+
+    return valid;
+  }
+
   // 标记轨迹
   function makeTrack(event: MouseEvent, item: SliceImage) {
+    if (markStore.currentQuestion && !checkTrackValidate(item)) {
+      void message.warning({
+        content: "只能在设置的评卷区中评卷",
+        duration: 3,
+      });
+      return;
+    }
     if (markStore.currentSpecialTagType) {
       makeSpecialTagTrack(event, item);
       if (markStore.currentSpecialTagType === "TEXT") {

+ 6 - 0
src/features/mark/composables/useMarkTask.ts

@@ -23,6 +23,12 @@ export default function useMarkTask() {
       try {
         preDrawing = true;
         newTask.sliceUrls = await processSliceUrls(newTask);
+        newTask.sliceConfig = (newTask.sliceConfig || []).map((item) => {
+          return {
+            ...item,
+            id: `${item.i}_${item.x}_${item.y}_${item.w}_${item.h}`,
+          };
+        });
       } finally {
         preDrawing = false;
       }

+ 1 - 0
src/features/mark/composables/useSliceTrack.ts

@@ -105,6 +105,7 @@ export default function useSliceTrack(hasMarkResultToRender = false) {
 
       const sliceImageRendered = await loadImage(dataUrl);
       tempSliceImagesWithTrackList.push({
+        sliceId: sliceConfig.id,
         url: dataUrl,
         indexInSliceUrls: sliceConfig.i,
         // 通过轨迹位置是否落在裁切图上来定位轨迹在第几张图片

+ 6 - 1
src/types/index.ts

@@ -1,5 +1,7 @@
 import type { AxiosResponse } from "axios";
 interface SplitConfig {
+  //  ${i}_${x}_${y}_${w}_${h}
+  id: string;
   /** index of sheets */
   i: number;
   /** 覆盖区域的width */
@@ -223,7 +225,7 @@ interface RawTask {
   /** sliceUrls为空,则是多媒体阅卷,显示JSON */
   jsonUrl: string;
   /** 最高显示优先级,有sliceConfig就用sliceConfig,否则使用sheetConfig */
-  sliceConfig: Array<PictureSlice>;
+  sliceConfig: Array<SplitConfig>;
   /** 裁切图url */
   sliceUrls: Array<string>;
   // 试题列表
@@ -328,6 +330,7 @@ interface RawQuestion {
   title: string;
   /** 得分;null的值时是为打回时可以被评卷修改的;null也是从未评分过的情况,要通过rejected来判断 */
   score: number | null;
+  markerScore: number | null;
   /** 限制最大分数 */
   maxScore: number;
   /** 限制最小分数 */
@@ -505,6 +508,8 @@ export interface MarkResult {
 
 /** 前端自用,用来渲染裁切图 */
 export interface SliceImage {
+  // 裁切图区域ID
+  sliceId: string;
   /** 当前是 ObjectURL , 因为 DataURL 性能太差 */
   url: string;
   indexInSliceUrls: number;