Sfoglia il codice sorgente

feat: 单题阅取卷逻辑调整

zhangjie 3 mesi fa
parent
commit
83a8022a30

+ 11 - 2
src/api/markPage.ts

@@ -50,11 +50,20 @@ export async function getGroup() {
 }
 
 /** 获取评卷任务 */
-export async function getTask(questionModel: Setting["questionModel"]) {
+export async function getTask(
+  questionModel: Setting["questionModel"],
+  questionId?: string
+) {
   return httpApp.post<Task>(
     "/api/mark/getTask",
     {},
-    { params: { questionModel, ...getMarkInfo() } }
+    {
+      params: {
+        ...getMarkInfo(),
+        questionModel,
+        questionId: questionId || undefined,
+      },
+    }
   );
 }
 

+ 5 - 1
src/features/mark/Mark.vue

@@ -97,16 +97,20 @@ const markStore = useMarkStore();
 useTaskWatch();
 const { clearTask, nextTask, removeBrokenTask } = useMarkTask();
 const { updateSetting } = useSetting();
-const { updateStatus } = useStatus();
+const { updateStatus, listenStatusQuestion } = useStatus();
 const { saveTaskToServer, allZeroSubmit, unselectiveSubmit } = useMarkSubmit();
 
 const { addInterval } = useTimers();
+
 onMounted(async () => {
   let result = true;
   try {
     markStore.resetInfo();
     await clearTask();
     await updateSetting();
+    if (markStore.isSingelQuestionModel) {
+      listenStatusQuestion();
+    }
     await updateStatus();
     await nextTask();
   } catch (error) {

+ 10 - 0
src/features/mark/composables/useMarkSubmit.ts

@@ -8,12 +8,14 @@ import type { Question, MarkResult } from "@/types";
 import useStatus from "./useStatus";
 import useMarkTask from "./useMarkTask";
 import useTaskTips from "./useTaskTips";
+import useTaskQuestion from "./useTaskQuestion";
 
 export default function useMarkSubmit() {
   const markStore = useMarkStore();
   const { updateStatus } = useStatus();
   const { nextTask } = useMarkTask();
   const { setPrevTips, registTaskChangeTips } = useTaskTips();
+  const { updateStatusQuestionCount } = useTaskQuestion();
   registTaskChangeTips();
 
   // 检查分数
@@ -162,6 +164,14 @@ export default function useMarkSubmit() {
       // 保存成功后,缓存当前评卷提示信息
       setPrevTips();
 
+      // 单题模式下,更新当前题目的状态
+      if (markStore.isSingelQuestionModel) {
+        updateStatusQuestionCount({
+          quesionId: markStore.currentQuestion.questionId,
+          leftCount: res.data.data.leftCount,
+        });
+      }
+
       void message.success({ content: "保存成功", duration: 2 });
       if (!markStore.historyOpen) {
         markStore.currentTask = undefined;

+ 9 - 8
src/features/mark/composables/useMarkTask.ts

@@ -1,12 +1,13 @@
 import { clearMarkTask, getTask } from "@/api/markPage";
 import { useMarkStore } from "@/store";
 import useDraw from "./useDraw";
-import useStatus from "./useStatus";
+import useTaskQuestion from "./useTaskQuestion";
 
 export default function useMarkTask() {
   const markStore = useMarkStore();
-  const { updateStatus } = useStatus();
   const { processSliceUrls } = useDraw();
+  const { getNextTaskQuestionId, updateStatusQuestionCount } =
+    useTaskQuestion();
 
   let preDrawing = false;
 
@@ -15,7 +16,8 @@ export default function useMarkTask() {
   }
 
   async function updateTask() {
-    const res = await getTask(markStore.setting.questionModel);
+    const nextQuestionId = getNextTaskQuestionId();
+    const res = await getTask(markStore.setting.questionModel, nextQuestionId);
     if (res.data) {
       const newTask = res.data;
       newTask.sheetUrls = newTask.sheetUrls || [];
@@ -32,10 +34,6 @@ export default function useMarkTask() {
           markStore.currentTask = markStore.tasks[0];
       }
 
-      if (markStore.status.totalCount - markStore.status.markedCount === 0) {
-        await updateStatus();
-      }
-
       if (markStore.tasks.length > 1) {
         await new Promise((resolve) => setTimeout(resolve, 3000));
       }
@@ -43,8 +41,11 @@ export default function useMarkTask() {
       markStore.message = res.message || "数据错误";
     }
 
-    if (!res.data && markStore.message === "成功")
+    if (!res.data && markStore.message === "成功") {
+      // 如果获取不到任务,说明nextQuestionId已经评完
+      updateStatusQuestionCount({ quesionId: nextQuestionId, leftCount: 0 });
       markStore.message = "当前无评卷任务";
+    }
   }
 
   function nextTask() {

+ 25 - 0
src/features/mark/composables/useStatus.ts

@@ -1,5 +1,6 @@
 import { useMarkStore } from "@/store";
 import { getStatus } from "@/api/markPage";
+import { watch } from "vue";
 
 export default function useStatus() {
   const markStore = useMarkStore();
@@ -7,9 +8,33 @@ export default function useStatus() {
   async function updateStatus() {
     const res = await getStatus(markStore.setting.questionModel);
     markStore.setInfo({ status: res.data });
+
+    // 单题阅的模式status可能有多条,需要依据评卷的试题来确定显示哪一条
+    // 整卷阅的模式下只有一条,所以只取第一条数据
+    if (!markStore.isSingelQuestionModel) {
+      markStore.setInfo({ curStatus: res.data[0] });
+    }
+  }
+
+  // 单题阅的模式下才需要监听当前题目状态
+  function listenStatusQuestion() {
+    watch(
+      () => markStore.currentQuestion,
+      (val) => {
+        if (!val) return;
+        const { mainNumber, subNumber } = val;
+        markStore.setInfo({
+          curStatus: markStore.status.find(
+            (item) =>
+              item.mainNumber === mainNumber && item.subNumber === subNumber
+          ),
+        });
+      }
+    );
   }
 
   return {
     updateStatus,
+    listenStatusQuestion,
   };
 }

+ 55 - 0
src/features/mark/composables/useTaskQuestion.ts

@@ -0,0 +1,55 @@
+import { useMarkStore } from "@/store";
+
+export default function useTaskQuestion() {
+  const markStore = useMarkStore();
+
+  function getFirstUnfinishedQuestionStatus() {
+    return markStore.status.find((item) => item.leftCount > 0);
+  }
+
+  // 获取下一个未评数量不为0的试题状态信息
+  function getNextQuestionStatus(questionId: string) {
+    const questionIndex = markStore.status
+      .filter((item) => item.questionId !== questionId)
+      .findIndex((item) => item.leftCount > 0);
+    if (questionIndex < 0) return;
+
+    return markStore.status[questionIndex];
+  }
+
+  function getNextTaskQuestionId() {
+    if (!markStore.isSingelQuestionModel) return;
+
+    const firstUnfinishedQuestion = getFirstUnfinishedQuestionStatus();
+    if (!firstUnfinishedQuestion) return;
+
+    const { questionId, leftCount } = firstUnfinishedQuestion;
+    const taskCount = markStore.tasks.length;
+    if (leftCount - taskCount > 0) {
+      return questionId;
+    }
+
+    const nextQuestion = getNextQuestionStatus(questionId);
+    if (!nextQuestion) return;
+    return nextQuestion.questionId;
+  }
+
+  // 提交试题任务之后,更新试题状态信息
+  function updateStatusQuestionCount(data: {
+    quesionId: string;
+    leftCount: number;
+  }) {
+    if (!quesionId) return;
+
+    const questionIndex = markStore.status.findIndex(
+      (item) => item.questionId === data.questionId
+    );
+    if (questionIndex < 0) return;
+    markStore.status[questionIndex].leftCount = data.leftCount;
+  }
+
+  return {
+    getNextTaskQuestionId,
+    updateStatusQuestionCount,
+  };
+}

+ 5 - 1
src/features/mark/stores/mark.ts

@@ -38,7 +38,8 @@ const useMarkStore = defineStore("mark", {
       enableSplit: true,
       showObjectiveScore: false,
     },
-    status: <MarkStore["status"]>{},
+    status: [],
+    curStatus: {},
     tasks: [],
     currentTask: undefined,
     // 主观题检查时,缓存已经修改过的试题
@@ -81,6 +82,9 @@ const useMarkStore = defineStore("mark", {
     isTrackMode(state: MarkStore): boolean {
       return state.setting.mode && state.setting.mode === "TRACK";
     },
+    isSingelQuestionModel(state: MarkStore): boolean {
+      return state.setting.questionModel === "SINGLE";
+    },
     modeName(state: MarkStore): string {
       return state.setting.mode === "TRACK" ? "轨迹模式" : "普通模式";
     },

+ 8 - 17
src/features/mark/toolbar/MarkHeader.vue

@@ -25,9 +25,9 @@
       </div>
       <a-tooltip overlayClassName="mark-tooltip">
         <template #title>
-          问题卷 {{ markStore.status.problemCount }}
+          问题卷 {{ markStore.curStatus.problemCount }}
           <br />
-          待仲裁 {{ markStore.status.arbitrateCount }}
+          待仲裁 {{ markStore.curStatus.arbitrateCount }}
         </template>
         <div class="header-programs">
           <img
@@ -69,11 +69,11 @@
           <span> {{ totalScore }} </span>
         </div>
       </div>
-      <div v-show="markStore.status.totalCount" class="header-total">
+      <div v-show="markStore.curStatus.totalCount" class="header-total">
         <span class="header-noun">
           <span>已评:</span>
-          <span :key="markStore.status.personCount || 0">
-            {{ markStore.status.personCount }}
+          <span :key="markStore.curStatus.personCount || 0">
+            {{ markStore.curStatus.personCount }}
           </span>
         </span>
         <span v-if="markStore.setting.topCount" class="header-noun">
@@ -82,8 +82,8 @@
         </span>
         <span class="header-noun">
           <span>未评:</span>
-          <span :key="todoCount || 0">
-            {{ todoCount }}
+          <span :key="markStore.curStatus.leftCount || 0">
+            {{ markStore.curStatus.leftCount }}
           </span>
         </span>
         <span class="header-noun">
@@ -197,7 +197,7 @@ async function toggleSettingMode() {
 }
 
 const progress = $computed(() => {
-  const { totalCount, markedCount } = markStore.status;
+  const { totalCount, markedCount } = markStore.curStatus;
   if (typeof totalCount !== "number" || totalCount === 0) return 0;
   let p = markedCount / totalCount;
   if (p < 0.01 && markedCount >= 1) p = 0.01;
@@ -216,15 +216,6 @@ const totalScore = $computed(() => {
   );
 });
 
-const todoCount = $computed(() =>
-  typeof markStore.status.totalCount === "number"
-    ? markStore.status.totalCount -
-      markStore.status.markedCount -
-      markStore.status.problemCount -
-      markStore.status.arbitrateCount
-    : "-"
-);
-
 const logout = async () => {
   await clearMarkTask();
   doLogout();

+ 25 - 14
src/types/index.ts

@@ -12,24 +12,35 @@ interface SplitConfig {
   y: number;
 }
 
+interface MarkStatus {
+  /** 个人评卷数量 */
+  personCount: number;
+  /** 总评卷数量 */
+  markedCount: number;
+  /** 总数量 */
+  totalCount: number;
+  // 待评数量
+  leftCount: number;
+  /** 问题卷数量 */
+  problemCount: number;
+  /** 待仲裁卷数量 */
+  arbitrateCount: number;
+  // 大题号
+  mainNumber: number;
+  // 小题号
+  subNumber: number;
+  // 题目Id
+  questionId: number;
+  /**成绩校验,批量校验时,已校验的学生id的集合 */
+  markedCountStuIds?: any;
+}
+
 type SingleSheetConfig = SplitConfig;
 export type PictureSlice = SplitConfig;
 export interface MarkStore {
   setting: Setting;
-  status: {
-    /** 个人评卷数量 */
-    personCount: number;
-    /** 总评卷数量 */
-    markedCount: number;
-    /** 总数量 */
-    totalCount: number;
-    /** 问题卷数量 */
-    problemCount: number;
-    /** 待仲裁卷数量 */
-    arbitrateCount: number;
-    /**成绩校验,批量校验时,已校验的学生id的集合 */
-    markedCountStuIds?: any;
-  };
+  status: MarkStatus[];
+  curStatus: MarkStatus;
   /** 保持数量为3(prefetchCount) */
   tasks: Array<Task>;
   /** 用来切换task,还有回看 */