Michael Wang пре 4 година
родитељ
комит
456ba84518

+ 0 - 1
src/api/markPage.ts

@@ -96,7 +96,6 @@ export async function saveTask() {
     //     acc[acc.length-1] += cur.score
     //   }
     // }, [0])
-    const allScoreList = markResult.trackList.map((t) => t.score);
     markResult.markerScore =
       markResult.trackList
         .map((t) => t.score)

+ 6 - 1
src/components/mark/Mark.vue

@@ -1,9 +1,10 @@
 <template>
-  <div class="my-container" @dblclick="saveTaskToServer">
+  <div class="my-container">
     <mark-header />
     <div class="flex gap-1">
       <mark-history />
       <mark-body />
+      <mark-board @submit="saveTaskToServer" />
     </div>
   </div>
 </template>
@@ -24,6 +25,7 @@ import MarkHeader from "./MarkHeader.vue";
 import MarkBody from "./MarkBody.vue";
 import { useTimers } from "@/setups/useTimers";
 import MarkHistory from "./MarkHistory.vue";
+import MarkBoard from "./MarkBoard.vue";
 
 export default defineComponent({
   name: "Mark",
@@ -31,6 +33,7 @@ export default defineComponent({
     MarkHeader,
     MarkBody,
     MarkHistory,
+    MarkBoard,
   },
   setup: () => {
     const { addInterval } = useTimers();
@@ -67,6 +70,8 @@ export default defineComponent({
         updateTask();
       }
     }, 5 * 1000);
+
+    // TODO: 后续改掉,不需要
     addInterval(() => {
       updateStatus();
     }, 30 * 1000);

+ 159 - 0
src/components/mark/MarkBoard.vue

@@ -0,0 +1,159 @@
+<template>
+  <div
+    v-if="store.currentTask"
+    :style="{ display: store.markBoardCollapse ? 'none' : 'block' }"
+    style="max-width: 250px; min-width: 250px; border: 1px solid grey"
+  >
+    <div>
+      <h1 class="text-3xl text-center">总分:{{ markResultScore }}</h1>
+    </div>
+    <div>
+      <div class="text-2xl text-center" @click="submit">提交</div>
+    </div>
+
+    <div
+      v-if="store.currentTask && store.currentTask.questionList"
+      class="flex gap-1 flex-wrap"
+    >
+      <template
+        v-for="(question, index) in store.currentTask?.questionList"
+        :key="index"
+      >
+        <div
+          @click="chooseQuestion(question)"
+          class="question"
+          :class="isCurrentQuestion(question) && 'current-question'"
+        >
+          <div>
+            {{ question.title }} {{ question.mainNumber }}-{{
+              question.subNumber
+            }}
+          </div>
+          <div class="text-center">
+            {{ question.score || 0 }}
+          </div>
+        </div>
+      </template>
+    </div>
+
+    <div class="flex gap-1 flex-wrap mt-5">
+      <div
+        v-for="(s, i) in questionScoreSteps"
+        :key="i"
+        @click="chooseScore(s)"
+        class="single-score"
+        :class="isCurrentScore(s) && 'current-score'"
+      >
+        {{ s }}
+      </div>
+    </div>
+  </div>
+</template>
+
+<script lang="ts">
+import { Question } from "@/types";
+import { computed, defineComponent, watch } from "vue";
+import { findCurrentTaskMarkResult, store } from "./store";
+
+export default defineComponent({
+  name: "MarkBoard",
+  emits: ["submit"],
+  setup(props, { emit }) {
+    const markResult = findCurrentTaskMarkResult();
+
+    const markResultScore = computed(() => {
+      return markResult
+        ? markResult.trackList
+            .map((t) => t.score)
+            .reduce((acc, v) => (acc += v * 100), 0) / 100
+        : 0;
+    });
+
+    const questionScoreSteps = computed(() => {
+      const question = store.currentQuestion;
+      if (!question) return [];
+
+      const steps = [];
+      for (
+        let i = 0;
+        i <= question.maxScore - question.score;
+        i += question.intervalScore
+      ) {
+        steps.push(i);
+      }
+      if ((question.maxScore - question.score) % question.intervalScore !== 0) {
+        steps.push(question.maxScore - question.score);
+      }
+
+      return steps;
+    });
+
+    function isCurrentQuestion(question: Question) {
+      return (
+        store.currentQuestion?.mainNumber === question.mainNumber &&
+        store.currentQuestion?.subNumber === question.subNumber
+      );
+    }
+    watch(
+      () => store.currentTask,
+      () => {
+        store.currentQuestion = undefined;
+        store.currentScore = undefined;
+      }
+    );
+    watch(
+      () => store.currentQuestion,
+      () => {
+        store.currentScore = undefined;
+      }
+    );
+    function chooseQuestion(question: Question) {
+      store.currentQuestion = question;
+    }
+    function isCurrentScore(score: number) {
+      return store.currentScore === score;
+    }
+    function chooseScore(score: number) {
+      store.currentScore = score;
+    }
+
+    function submit() {
+      emit("submit");
+    }
+
+    return {
+      store,
+      markResult,
+      markResultScore,
+      isCurrentQuestion,
+      chooseQuestion,
+      isCurrentScore,
+      chooseScore,
+      questionScoreSteps,
+      submit,
+    };
+  },
+});
+</script>
+
+<style scoped>
+.question {
+  min-width: 80px;
+  border: 1px solid grey;
+}
+.current-question {
+  border: 1px solid yellowgreen;
+}
+.single-score {
+  width: 30px;
+  height: 30px;
+  display: grid;
+  place-content: center;
+
+  border: 1px solid black;
+  border-radius: 5px;
+}
+.current-score {
+  border: 1px solid yellowgreen;
+}
+</style>

+ 22 - 4
src/components/mark/MarkBody.vue

@@ -101,6 +101,18 @@ export default defineComponent({
         for (const url of store.currentTask.sliceUrls) {
           await loadImage(filters.toCompleteUrl(url));
         }
+        // 必须要先加载一遍,把“选择整图”的宽高重置后,再算总高度
+        for (const sliceConfig of store.currentTask.sliceConfig) {
+          const url = filters.toCompleteUrl(
+            store.currentTask.sliceUrls[sliceConfig.i - 1]
+          );
+          const image = await loadImage(url);
+          if (sliceConfig.w === 0 && sliceConfig.h === 0) {
+            // 选择整图时,w/h 为0
+            sliceConfig.w = image.naturalWidth;
+            sliceConfig.h = image.naturalHeight;
+          }
+        }
         theFinalHeight = store.currentTask.sliceConfig
           .map((v) => v.h)
           .reduce((acc, v) => (acc += v));
@@ -112,6 +124,11 @@ export default defineComponent({
             store.currentTask.sliceUrls[sliceConfig.i - 1]
           );
           const image = await loadImage(url);
+          if (sliceConfig.w === 0 && sliceConfig.h === 0) {
+            // 选择整图时,w/h 为0
+            sliceConfig.w = image.naturalWidth;
+            sliceConfig.h = image.naturalHeight;
+          }
 
           const div = (container.value as unknown) as HTMLDivElement;
           maxSliceWidth = Math.max(
@@ -291,13 +308,14 @@ export default defineComponent({
 
     const makeMark = (event: MouseEvent, item: SliceImage) => {
       // console.log(item);
+      if (!store.currentQuestion || !store.currentScore) return;
       const target = event.target as HTMLImageElement;
       const track = {} as Track;
       // TODO: choose question first
-      track.mainNumber = 4;
-      track.subNumber = "1";
-      track.number = 0;
-      track.score = 2;
+      track.mainNumber = store.currentQuestion?.mainNumber;
+      track.subNumber = store.currentQuestion?.subNumber;
+      track.number = Math.round(Math.random() * 10000000);
+      track.score = store.currentScore;
       track.offsetIndex = item.indexInSliceUrls;
       track.offsetX = Math.round(
         event.offsetX * (target.naturalWidth / target.width) + item.dx

+ 4 - 0
src/components/mark/store.ts

@@ -27,8 +27,11 @@ const obj = {
   groups: [],
   tasks: [],
   currentTask: <Task>{},
+  currentQuestion: undefined,
+  currentScore: undefined,
   markResults: [],
   historyOpen: false,
+  markBoardCollapse: false,
   historyTasks: [],
 } as MarkStore;
 
@@ -45,6 +48,7 @@ export function toggleMode() {
 }
 
 export function findCurrentTaskMarkResult() {
+  if (!store.currentTask) return;
   const { libraryId, studentId } = store.currentTask;
   const statusValue = store.setting.statusValue;
   return store.markResults.find(

+ 4 - 1
src/types/index.ts

@@ -10,8 +10,11 @@ export interface MarkStore {
   };
   tasks: Array<Task>; // 保持数量为3
   currentTask?: Task; // 用来切换task,还有回看
+  currentQuestion?: Question;
+  currentScore?: number;
   markResults: Array<MarkResult>;
   historyOpen: boolean; // 是否打开回评侧边栏
+  markBoardCollapse: boolean; // 是否收缩评分版
   historyTasks: Array<Task>;
 }
 
@@ -89,7 +92,7 @@ export interface Task {
   rejected: boolean; // 是否是打回
 }
 
-interface Question {
+export interface Question {
   groupNumber: number; // 分组序号
   mainNumber: number; // 大题号
   subNumber: string; // 小题号