Jelajahi Sumber

复核:移动到试题时,分数动画显示

Michael Wang 4 tahun lalu
induk
melakukan
7fd453f51a

+ 52 - 1
src/components/inspect/MarkBoardInspect.vue

@@ -11,7 +11,11 @@
     <div v-if="groups">
       <template v-for="(groupNumber, index) in groups" :key="index">
         <div class="mb-2">
-          <div class="tw-flex tw-justify-between">
+          <div
+            class="tw-flex tw-justify-between"
+            @mouseover="addFocusTrack(groupNumber)"
+            @mouseleave="removeFocusTrack"
+          >
             分组 {{ groupNumber }}
             <div>
               打回
@@ -27,6 +31,14 @@
               <div
                 v-if="question.groupNumber === groupNumber"
                 class="question tw-rounded tw-flex tw-mb-1"
+                @mouseover="
+                  addFocusTrack(
+                    undefined,
+                    question.mainNumber,
+                    question.subNumber
+                  )
+                "
+                @mouseleave="removeFocusTrack"
               >
                 <div class="tw-flex-1">
                   {{ question.title }} {{ question.mainNumber }}-{{
@@ -134,6 +146,43 @@ export default defineComponent({
       }
     }
 
+    function addFocusTrack(
+      groupNumber: number,
+      mainNumber: number,
+      subNumber: string
+    ) {
+      store.focusTracks.splice(0);
+
+      if (groupNumber) {
+        questions.value
+          ?.filter((q) => q.groupNumber === groupNumber)
+          ?.map((q) => q.trackList)
+          .reduce((acc, ts) => acc.concat(ts))
+          .forEach((t) => {
+            store.focusTracks.push(t);
+          });
+      } else {
+        questions.value
+          ?.map((q) => q.trackList)
+          .reduce((acc, ts) => acc.concat(ts))
+          .filter((t) => {
+            if (mainNumber) {
+              return t.mainNumber === mainNumber && t.subNumber === subNumber;
+            } else {
+              return false;
+            }
+          })
+          .forEach((t) => {
+            store.focusTracks.push(t);
+          });
+      }
+      // console.log(store.focusTracks);
+    }
+
+    function removeFocusTrack() {
+      store.focusTracks.splice(0);
+    }
+
     function reject() {
       emit("reject", checkedQuestions);
     }
@@ -152,6 +201,8 @@ export default defineComponent({
       questionChecked,
       questionCheckChanged,
       groupClicked,
+      addFocusTrack,
+      removeFocusTrack,
       reject,
       inspect,
     };

+ 61 - 4
src/components/inspect/MarkDrawTrack.vue

@@ -1,7 +1,14 @@
 <template>
   <template v-for="(track, index) in trackList" :key="index">
-    <div class="score-container" :style="computeTopAndLeft(track)">
-      <span class="tw-m-auto">
+    <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>
@@ -10,7 +17,7 @@
 
 <script lang="ts">
 import { Track } from "@/types";
-import { defineComponent, PropType } from "vue";
+import { defineComponent, PropType, watch } from "vue";
 import { store } from "./store";
 
 export default defineComponent({
@@ -25,6 +32,9 @@ export default defineComponent({
     },
   },
   setup({ trackList, originalImage }) {
+    const focusedTrack = (track: Track) => {
+      return store.focusTracks.includes(track);
+    };
     const computeTopAndLeft = (track: Track) => {
       const topInsideSlice = track.offsetY;
       const leftInsideSlice = track.offsetX;
@@ -34,6 +44,9 @@ export default defineComponent({
       //   offx: track.offsetX,
       //   offy: track.offsetY,
       // });
+      // if (store.focusTracks.includes(track)) {
+      //   console.log("has track");
+      // }
       return {
         top: (topInsideSlice / originalImage.naturalHeight) * 100 + "%",
         left: (leftInsideSlice / originalImage.naturalWidth) * 100 + "%",
@@ -41,7 +54,33 @@ export default defineComponent({
       };
     };
 
-    return { store, computeTopAndLeft };
+    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();
+        }
+      }
+    );
+
+    return { store, focusedTrack, computeTopAndLeft };
   },
 });
 </script>
@@ -62,4 +101,22 @@ export default defineComponent({
   /* to click through div */
   pointer-events: none;
 }
+.score-animation {
+  animation: 2s ease-in-out 0s infinite alternate change_color;
+}
+
+@keyframes change_color {
+  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 - 0
src/components/inspect/store.ts

@@ -18,6 +18,7 @@ const obj = {
   historyOpen: false,
   MarkBoardTrackCollapse: false,
   historyTasks: [],
+  focusTracks: [],
 } as InspectStore;
 
 export const store = reactive(obj);

+ 1 - 0
src/types/index.ts

@@ -177,4 +177,5 @@ export interface InspectStore {
   historyOpen: boolean; // 是否打开回评侧边栏
   MarkBoardTrackCollapse: boolean; // 是否收缩评分版
   historyTasks: Array<Task>;
+  focusTracks: Array<Track>;
 }