Jelajahi Sumber

feat: yuejuan

zhangjie 3 bulan lalu
induk
melakukan
f996c7c51b
44 mengubah file dengan 817 tambahan dan 279 penghapusan
  1. 5 5
      README.md
  2. 4 4
      cypress/fixtures/task-1.json
  3. 4 4
      cypress/fixtures/task-2.json
  4. 4 4
      cypress/fixtures/task-3.json
  5. 1 0
      package.json
  6. 548 27
      pnpm-lock.yaml
  7. 5 1
      src/App.vue
  8. 4 4
      src/api/arbitratePage.ts
  9. 2 2
      src/api/inspectPage.ts
  10. 9 9
      src/api/markPage.ts
  11. 1 1
      src/directives/eleMove.ts
  12. 7 7
      src/features/arbitrate/Arbitrate.vue
  13. 8 8
      src/features/arbitrate/ArbitrateBody.vue
  14. 20 20
      src/features/check-subjective/CheckSubjective.vue
  15. 7 7
      src/features/check-subjective/MarkBodyBase.vue
  16. 5 5
      src/features/check-subjective/composables/useSliceTrack.ts
  17. 1 1
      src/features/check-subjective/composables/useTask.ts
  18. 2 2
      src/features/check-subjective/composables/useTrackColor.ts
  19. 2 2
      src/features/mark/Mark.vue
  20. 7 7
      src/features/mark/MarkBodyBase.vue
  21. 1 0
      src/features/mark/MarkBodyCursor.vue
  22. 2 2
      src/features/mark/MarkBodySepecialTag.vue
  23. 13 19
      src/features/mark/MarkDrawTrack.vue
  24. 16 3
      src/features/mark/composables/useAutoChooseFirstQuestion.ts
  25. 7 7
      src/features/mark/composables/useFocusTracks.ts
  26. 8 8
      src/features/mark/composables/useMakeTrack.ts
  27. 19 12
      src/features/mark/composables/useMarkSubmit.ts
  28. 1 22
      src/features/mark/composables/useMarkTask.ts
  29. 5 3
      src/features/mark/composables/useSetting.ts
  30. 23 18
      src/features/mark/composables/useSliceTrack.ts
  31. 1 1
      src/features/mark/composables/useStatus.ts
  32. 4 4
      src/features/mark/composables/useTaskRejection.ts
  33. 9 8
      src/features/mark/composables/useTaskWatch.ts
  34. 1 1
      src/features/mark/modals/ModalMinimap.vue
  35. 2 2
      src/features/mark/modals/ModalSpecialTag.vue
  36. 4 1
      src/features/mark/scoring/MarkBoardKeyBoard.vue
  37. 1 1
      src/features/mark/scoring/MarkBoardMouse.vue
  38. 11 6
      src/features/mark/scoring/MarkBoardTrack.vue
  39. 1 1
      src/features/mark/stores/mark.ts
  40. 7 7
      src/features/mark/toolbar/MarkTool.vue
  41. 9 9
      src/features/track/TrackBody.vue
  42. 2 2
      src/features/track/composables/useTrack.ts
  43. 15 13
      src/features/track/composables/useTrackTag.ts
  44. 9 9
      src/types/index.ts

+ 5 - 5
README.md

@@ -29,14 +29,14 @@ src/features/student/studentInspect/MarkBody.vue 整卷渲染的组件,凡是
 
 1. currentTask 切换后,所有组件都得跟着变
 1. 轨迹模式下,
-   1. 分数轨迹发生变化,MarkBoardTrack.vue 改变 store.removeScoreTracks ,CommonMarkBody.vue 监听 store.removeScoreTracks 改变 sliceImagesWithTrackList 的 trackList
-   1. 特殊标记轨迹发生变化,SpecialTagModal.vue 改变 store.currentMarkResult.specialTagList ,CommonMarkBody.vue 监听 store.currentMarkResult.specialTagList 改变 sliceImagesWithTrackList 的 tagList
+   1. 分数轨迹发生变化,MarkBoardTrack.vue 改变 store.removeScoreTracks ,CommonMarkBody.vue 监听 store.removeScoreTracks 改变 sliceImagesWithTrackList 的 markerTrackList
+   1. 特殊标记轨迹发生变化,SpecialTagModal.vue 改变 store.currentMarkResult.markerTagList ,CommonMarkBody.vue 监听 store.currentMarkResult.markerTagList 改变 sliceImagesWithTrackList 的 tagList
 1. 分数之间的关系,(理想设计)
    1. 来源: question.score 和 track.score, history.task.markerScore 评卷时不参与给分板的计算和显示
-   1. 初始收集: markResult.scoreList markResult.trackList.score markResult.markerScore 要区分 0 分和 null
+   1. 初始收集: markResult.scoreList markResult.markerTrackList.score markResult.markerScore 要区分 0 分和 null
    1. 轨迹改变:track.score 动态计算 scoreList,再显示到给分板上(单题和总分自动计算),只有轨迹改变才去计算 scoreList 对应的题的分数,这样可以尽可能长时间的显示旧分数
    1. 普通改变:scoreList\[index\]的值
-   1. 回评时普通模式评分的记录在轨迹模式下如何保持?先将 task 中的 question.score 转移到 markResult.scoreList,如果 trackList 有变化,则更新对应 scoreList,不然则保持原样。
+   1. 回评时普通模式评分的记录在轨迹模式下如何保持?先将 task 中的 question.score 转移到 markResult.scoreList,如果 markerTrackList 有变化,则更新对应 scoreList,不然则保持原样。
 1. 优化
    1. markResult 放到 task 里面? 回评清理它的 markResult . DONE!
    1. 使用 pinia . DONE!
@@ -48,7 +48,7 @@ src/features/student/studentInspect/MarkBody.vue 整卷渲染的组件,凡是
    1.1 openSide
 2. header watch setting / status
 3. history watch open , change currentTask
-4. body watch trackList, computed score? emit 'trackListChange'('add', questionIndex, trackList)/('removeLast', questionIndex)/('removeAll',questionIndex)
+4. body watch markerTrackList, computed score? emit 'trackListChange'('add', questionIndex, markerTrackList)/('removeLast', questionIndex)/('removeAll',questionIndex)
 5. markboard watch currentQuestion, normal mode -> change scoreList[index]
 
 ### 版本信息

+ 4 - 4
cypress/fixtures/task-1.json

@@ -99,7 +99,7 @@
       "score": null,
       "maxScore": 30,
       "minScore": 0,
-      "trackList": []
+      "markerTrackList": []
     },
     {
       "groupNumber": 9,
@@ -111,7 +111,7 @@
       "score": null,
       "maxScore": 5,
       "minScore": 0,
-      "trackList": []
+      "markerTrackList": []
     },
     {
       "groupNumber": 9,
@@ -123,10 +123,10 @@
       "score": null,
       "maxScore": 40,
       "minScore": 0,
-      "trackList": []
+      "markerTrackList": []
     }
   ],
-  "specialTagList": null,
+  "markerTagList": null,
   "sheetUrls": [
     "sheet/1/581/1501581-1.jpg",
     "sheet/1/581/1501581-2.jpg",

+ 4 - 4
cypress/fixtures/task-2.json

@@ -99,7 +99,7 @@
       "score": null,
       "maxScore": 30,
       "minScore": 0,
-      "trackList": []
+      "markerTrackList": []
     },
     {
       "groupNumber": 9,
@@ -111,7 +111,7 @@
       "score": null,
       "maxScore": 5,
       "minScore": 0,
-      "trackList": []
+      "markerTrackList": []
     },
     {
       "groupNumber": 9,
@@ -123,10 +123,10 @@
       "score": null,
       "maxScore": 40,
       "minScore": 0,
-      "trackList": []
+      "markerTrackList": []
     }
   ],
-  "specialTagList": null,
+  "markerTagList": null,
   "sheetUrls": [
     "sheet/1/591/1501591-1.jpg",
     "sheet/1/591/1501591-2.jpg",

+ 4 - 4
cypress/fixtures/task-3.json

@@ -99,7 +99,7 @@
       "score": null,
       "maxScore": 30,
       "minScore": 0,
-      "trackList": []
+      "markerTrackList": []
     },
     {
       "groupNumber": 9,
@@ -111,7 +111,7 @@
       "score": null,
       "maxScore": 5,
       "minScore": 0,
-      "trackList": []
+      "markerTrackList": []
     },
     {
       "groupNumber": 9,
@@ -123,10 +123,10 @@
       "score": null,
       "maxScore": 40,
       "minScore": 0,
-      "trackList": []
+      "markerTrackList": []
     }
   ],
-  "specialTagList": null,
+  "markerTagList": null,
   "sheetUrls": [
     "sheet/1/110/1501110-1.jpg",
     "sheet/1/110/1501110-2.jpg",

+ 1 - 0
package.json

@@ -27,6 +27,7 @@
     "mitt": "^3.0.0",
     "moment": "^2.29.4",
     "pinia": "^2.0.16",
+    "pinia-plugin-persistedstate": "^4.2.0",
     "tailwindcss": "^3.1.6",
     "ua-parser-js": "^1.0.2",
     "viewerjs": "^1.10.5",

File diff ditekan karena terlalu besar
+ 548 - 27
pnpm-lock.yaml


+ 5 - 1
src/App.vue

@@ -22,7 +22,11 @@ let spinning = $ref(false);
 
 watch(
   () => markStore.globalMask,
-  () => (spinning = markStore.globalMask)
+  () => {
+    console.log(markStore.globalMask);
+
+    spinning = markStore.globalMask;
+  }
 );
 
 watchEffect(() => {

+ 4 - 4
src/api/arbitratePage.ts

@@ -113,8 +113,8 @@ export async function saveArbitrateTask(
   markerScore: number,
   scoreList: Array<number>,
   unselective: boolean,
-  trackList?: any,
-  specialTagList?: any
+  markerTrackList?: any,
+  markerTagList?: any
 ) {
   return httpApp.post<CommonResponse>("/api/admin/mark/arbitrate/saveTask", {
     taskId,
@@ -122,7 +122,7 @@ export async function saveArbitrateTask(
     markerScore,
     scoreList,
     unselective,
-    trackList,
-    specialTagList,
+    markerTrackList,
+    markerTagList,
   });
 }

+ 2 - 2
src/api/inspectPage.ts

@@ -134,8 +134,8 @@ export async function rejectInspectedTask(
   reason: string
 ) {
   // questionList = questionList.map((item: any) => {
-  //   if (Array.isArray(item.trackList)) {
-  //     item.trackList = item.trackList.map((v: any) => {
+  //   if (Array.isArray(item.markerTrackList)) {
+  //     item.markerTrackList = item.markerTrackList.map((v: any) => {
   //       delete v.isByMultMark;
   //       return v;
   //     });

+ 9 - 9
src/api/markPage.ts

@@ -32,7 +32,7 @@ export async function getSetting() {
 }
 
 /** 获取评卷状态 */
-export async function getStatus(questionModel: Setting["questionModal"]) {
+export async function getStatus(questionModel: Setting["questionModel"]) {
   return httpApp.post<MarkStore["status"]>(
     "/api/mark/getStatus",
     {},
@@ -50,11 +50,11 @@ export async function getGroup() {
 }
 
 /** 获取评卷任务 */
-export async function getTask(questionModal: Setting["questionModal"]) {
+export async function getTask(questionModel: Setting["questionModel"]) {
   return httpApp.post<Task>(
     "/api/mark/getTask",
     {},
-    { params: { questionModal, ...getMarkInfo() } }
+    { params: { questionModel, ...getMarkInfo() } }
   );
 }
 
@@ -62,7 +62,7 @@ export async function getTask(questionModal: Setting["questionModal"]) {
 export async function updateUISetting(
   mode?: Setting["mode"],
   uiSetting?: UISetting,
-  questionModal?: Setting["questionModal"]
+  questionModel?: Setting["questionModel"]
 ) {
   return httpApp.post<void>(
     "/api/mark/updateSetting",
@@ -71,7 +71,7 @@ export async function updateUISetting(
       params: {
         mode: mode || undefined,
         uiSetting: uiSetting ? JSON.stringify(uiSetting) : undefined,
-        questionModal: questionModal || undefined,
+        questionModel: questionModel || undefined,
         ...getMarkInfo(),
       },
     }
@@ -162,8 +162,8 @@ export async function doProblemType({
   datas.problemRemark = problemRemark || undefined;
   datas.markerScore = null;
   datas.scoreList = [];
-  datas.specialTagList = [];
-  datas.trackList = [];
+  datas.markerTagList = [];
+  datas.markerTrackList = [];
   datas.spent = Date.now() - markStore.currentTask.__markStartTime;
 
   return httpApp.post<CommonResponse>("/api/mark/saveTask", datas, {
@@ -178,8 +178,8 @@ export async function doUnselectiveType() {
   const datas = { ...markStore.currentTask?.markResult };
   datas.markerScore = -1;
   datas.scoreList = [];
-  datas.specialTagList = [];
-  datas.trackList = [];
+  datas.markerTagList = [];
+  datas.markerTrackList = [];
   datas.spent = Date.now() - markStore.currentTask.__markStartTime;
 
   return httpApp.post<CommonResponse>("/api/mark/saveTask", datas, {

+ 1 - 1
src/directives/eleMove.ts

@@ -1,6 +1,6 @@
 export const vEleMoveDirective = {
   mounted(el, { value, modifiers }) {
-    const [_x, _y] = [0, 0];
+    let [_x, _y] = [0, 0];
     // 只允许鼠标左键触发
     const moveHandle = function (e) {
       if (e.button !== 0) return;

+ 7 - 7
src/features/arbitrate/Arbitrate.vue

@@ -172,15 +172,15 @@ onMounted(async () => {
 
 // 保存任务
 const saveTaskToServerByTrack = async () => {
-  let trackList = markStore.currentTask.markResult.trackList;
-  let specialTagList = markStore.currentTask.markResult.specialTagList;
-  await saveTaskToServer(false, trackList, specialTagList);
+  let markerTrackList = markStore.currentTask.markResult.markerTrackList;
+  let markerTagList = markStore.currentTask.markResult.markerTagList;
+  await saveTaskToServer(false, markerTrackList, markerTagList);
 };
 
 const saveTaskToServer = async (
   unselective: boolean,
-  trackList?: any,
-  specialTagList?: any
+  markerTrackList?: any,
+  markerTagList?: any
 ) => {
   if (!markStore.currentTask) return;
   const markResult = markStore.currentTask.markResult;
@@ -241,8 +241,8 @@ const saveTaskToServer = async (
       markStore.currentTask.markResult.markerScore,
       markStore.currentTask.markResult.scoreList,
       false,
-      trackList,
-      specialTagList
+      markerTrackList,
+      markerTagList
     );
   }
   if (!res.data.success) {

+ 8 - 8
src/features/arbitrate/ArbitrateBody.vue

@@ -48,7 +48,7 @@ const makeScoreTrack = (
     return;
   }
   if (
-    item.trackList.some((t) => {
+    item.markerTrackList.some((t) => {
       return (
         Math.pow(Math.abs(t.offsetX - track.offsetX), 2) +
           Math.pow(Math.abs(t.offsetY - track.offsetY), 2) <
@@ -77,18 +77,18 @@ const makeScoreTrack = (
   }
   const markResult = markStore.currentTaskEnsured.markResult;
   const maxNumber =
-    markResult.trackList.length === 0
+    markResult.markerTrackList.length === 0
       ? 0
-      : Math.max(...markResult.trackList.map((t) => t.number));
+      : Math.max(...markResult.markerTrackList.map((t) => t.number));
   track.number = maxNumber + 1;
-  markResult.trackList = [...markResult.trackList, track];
+  markResult.markerTrackList = [...markResult.markerTrackList, track];
   const { __index, mainNumber, subNumber } = markStore.currentQuestion;
   markResult.scoreList[__index] =
-    markResult.trackList
+    markResult.markerTrackList
       .filter((t) => t.mainNumber === mainNumber && t.subNumber === subNumber)
-      .map((t) => t.score)
+      .map((t) => t.markerScore)
       .reduce((acc, v) => (acc += Math.round(v * 1000)), 0) / 1000;
-  item.trackList.push(track);
+  item.markerTrackList.push(track);
 };
 
 const makeSpecialTagTrack = (
@@ -127,7 +127,7 @@ const makeSpecialTagTrack = (
     console.log("两个轨迹相距过近");
     return;
   }
-  markStore.currentTaskEnsured.markResult.specialTagList.push(track);
+  markStore.currentTaskEnsured.markResult.markerTagList.push(track);
   item.tagList.push(track);
 };
 

+ 20 - 20
src/features/check-subjective/CheckSubjective.vue

@@ -201,22 +201,22 @@ const allZeroSubmit = async () => {
   const markResult = markStore.currentTask?.markResult;
   if (!markResult) return;
 
-  const { markerScore, scoreList, trackList, specialTagList } = markResult;
+  const { markerScore, scoreList, markerTrackList, markerTagList } = markResult;
   markResult.markerScore = 0;
   const ss = new Array(markStore.currentTaskEnsured.questionList.length);
   markResult.scoreList = ss.fill(0);
-  markResult.trackList = [];
+  markResult.markerTrackList = [];
 
   try {
     await saveTaskToServer();
   } catch (error) {
     console.log("error restore");
   } finally {
-    // console.log({ markerScore, scoreList, trackList });
+    // console.log({ markerScore, scoreList, markerTrackList });
     markResult.markerScore = markerScore;
     markResult.scoreList = scoreList;
-    markResult.trackList = trackList;
-    markResult.specialTagList = specialTagList;
+    markResult.markerTrackList = markerTrackList;
+    markResult.markerTagList = markerTagList;
   }
 };
 
@@ -238,8 +238,8 @@ const getMarkData = () => {
         groupMap[groupNumber] = {
           ...commomData,
           groupNumber,
-          trackList: [],
-          specialTagList: [],
+          markerTrackList: [],
+          markerTagList: [],
           markerScore: [],
           scoreList: [],
           studentId: markStore.currentTask.studentId,
@@ -265,28 +265,28 @@ const getMarkData = () => {
   }
 
   let groupMap = {};
-  markResult.trackList.forEach((track) => {
+  markResult.markerTrackList.forEach((track) => {
     const { groupNumber } =
       taskQuestionInfo[`${track.mainNumber * 1000}${track.subNumber}`];
     if (!groupMap[groupNumber]) {
       groupMap[groupNumber] = {
         groupNumber,
-        trackList: [],
-        specialTagList: [],
+        markerTrackList: [],
+        markerTagList: [],
       };
     }
-    groupMap[groupNumber].trackList.push(track);
+    groupMap[groupNumber].markerTrackList.push(track);
   });
-  markResult.specialTagList.forEach((track) => {
+  markResult.markerTagList.forEach((track) => {
     const { groupNumber } = track;
     if (!groupMap[groupNumber]) {
       groupMap[groupNumber] = {
         groupNumber,
-        trackList: [],
-        specialTagList: [],
+        markerTrackList: [],
+        markerTagList: [],
       };
     }
-    groupMap[groupNumber].specialTagList.push(track);
+    groupMap[groupNumber].markerTagList.push(track);
   });
 
   const modifiedQuestions = Object.keys(
@@ -295,12 +295,12 @@ const getMarkData = () => {
 
   let groups = Object.values(groupMap).map((item) => {
     let qScore = {};
-    const trackList = item.trackList.filter((track) =>
+    const markerTrackList = item.markerTrackList.filter((track) =>
       modifiedQuestions.includes(`${track.mainNumber}_${track.subNumber}`)
     );
-    if (!trackList.length && !item.specialTagList.length) return null;
+    if (!markerTrackList.length && !item.markerTagList.length) return null;
 
-    trackList.forEach((track) => {
+    markerTrackList.forEach((track) => {
       const qno = `${track.mainNumber * 1000}${track.subNumber}`;
       if (!qScore[qno]) {
         qScore[qno] = {
@@ -309,13 +309,13 @@ const getMarkData = () => {
           score: 0,
         };
       }
-      qScore[qno].score += track.score;
+      qScore[qno].markerScore += track.markerScore;
     });
 
     return {
       ...commomData,
       ...item,
-      trackList,
+      markerTrackList,
       markerScore: Object.values(qScore),
       studentId: markStore.currentTask.studentId,
     };

+ 7 - 7
src/features/check-subjective/MarkBodyBase.vue

@@ -32,8 +32,8 @@
               @contextmenu="showBigImage"
             />
             <MarkDrawTrack
-              :trackList="item.trackList"
-              :specialTagList="item.tagList"
+              :markerTrackList="item.markerTrackList"
+              :markerTagList="item.tagList"
               :sliceImageHeight="item.originalImageHeight"
               :sliceImageWidth="item.originalImageWidth"
               :dx="item.dx"
@@ -90,8 +90,8 @@ const { answerPaperScale } = useBodyScroll({
   shortCut: true,
   autoScroll: true,
 });
-const { sliceImagesWithTrackList, maxSliceWidth, theFinalHeight } =
-  useSliceTrack();
+const { rotateBoard, sliceImagesWithTrackList, maxSliceWidth, theFinalHeight } =
+  useSliceTrack(hasMarkResultToRender);
 
 // 图片拖动。在轨迹模式下,仅当没有选择分数时可用。
 const { dragContainer } = useDraggable();
@@ -112,7 +112,7 @@ function initWatch() {
   watchEffect(() => {
     for (const track of markStore.removeScoreTracks) {
       for (const sliceImage of sliceImagesWithTrackList) {
-        sliceImage.trackList = sliceImage.trackList.filter(
+        sliceImage.markerTrackList = sliceImage.markerTrackList.filter(
           (t) =>
             !(
               t.mainNumber === track.mainNumber &&
@@ -131,7 +131,7 @@ function initWatch() {
     if (!markStore.currentTask) return;
     for (const sliceImage of sliceImagesWithTrackList) {
       sliceImage.tagList = sliceImage.tagList.filter((t) =>
-        markStore.currentTaskEnsured.markResult?.specialTagList.find(
+        markStore.currentTaskEnsured.markResult?.markerTagList.find(
           (st) =>
             st.offsetIndex === t.offsetIndex &&
             st.offsetX === t.offsetX &&
@@ -139,7 +139,7 @@ function initWatch() {
         )
       );
     }
-    if (markStore.currentTaskEnsured.markResult?.specialTagList.length === 0) {
+    if (markStore.currentTaskEnsured.markResult?.markerTagList.length === 0) {
       for (const sliceImage of sliceImagesWithTrackList) {
         sliceImage.tagList = [];
       }

+ 5 - 5
src/features/check-subjective/composables/useSliceTrack.ts

@@ -35,14 +35,14 @@ export default function useSliceTrack() {
 
     const trackLists = (markStore.currentTask.questionList || [])
       .map((q) => {
-        const tList = q.trackList;
-        return q.headerTrack?.length
-          ? addHeaderTrackColorAttr(q.headerTrack)
+        const tList = q.markerTrackList;
+        return q.headerTrackList?.length
+          ? addHeaderTrackColorAttr(q.headerTrackList)
           : addTrackColorAttr(tList, q.groupNumber);
       })
       .flat();
     let tagLists = markStore.isTrackMode
-      ? markStore.currentTask.specialTagList ?? []
+      ? markStore.currentTask.markerTagList ?? []
       : [];
     tagLists = addSpecialTrackColorAttr(tagLists);
 
@@ -63,7 +63,7 @@ export default function useSliceTrack() {
       sliceImagesWithTrackList.push({
         url,
         indexInSliceUrls,
-        trackList: thisImageTrackList,
+        markerTrackList: thisImageTrackList,
         tagList: thisImageTagList,
         originalImageWidth: image.naturalWidth,
         originalImageHeight: image.naturalHeight,

+ 1 - 1
src/features/check-subjective/composables/useTask.ts

@@ -52,7 +52,7 @@ export default function useTask(ids: string[]) {
       const qno = `${question.mainNumber * 1000}${question.subNumber}`;
       taskQuestionInfo[qno] = {
         groupNumber: question.groupNumber,
-        score: question.score,
+        score: question.markerScore,
       };
     });
   }

+ 2 - 2
src/features/check-subjective/composables/useTrackColor.ts

@@ -39,8 +39,8 @@ export default function useTrackColor() {
     });
   }
 
-  function addHeaderTrackColorAttr(headerTrack: any): any {
-    return headerTrack.map((item: any) => {
+  function addHeaderTrackColorAttr(headerTrackList: any): any {
+    return headerTrackList.map((item: any) => {
       item.color = "green";
       return item;
     });

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

@@ -61,8 +61,8 @@ import { getHistoryTask } from "@/api/markPage";
 import { useMarkStore } from "@/store";
 
 // components
-import MarkHeader from "./MarkHeader.vue";
-import MarkTool from "./MarkTool.vue";
+import MarkHeader from "./toolbar/MarkHeader.vue";
+import MarkTool from "./toolbar/MarkTool.vue";
 import MarkBody from "./MarkBody.vue";
 import MarkHistory from "./MarkHistory.vue";
 

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

@@ -35,8 +35,8 @@
               @contextmenu="showBigImage"
             />
             <MarkDrawTrack
-              :trackList="item.trackList"
-              :specialTagList="item.tagList"
+              :markerTrackList="item.markerTrackList"
+              :markerTagList="item.tagList"
               :sliceImageWidth="item.sliceImageWidth"
               :sliceImageHeight="item.sliceImageHeight"
               :dx="item.dx"
@@ -99,8 +99,8 @@ const { answerPaperScale } = useBodyScroll({
   shortCut: true,
   autoScroll: true,
 });
-const { sliceImagesWithTrackList, maxSliceWidth, theFinalHeight } =
-  useSliceTrack();
+const { rotateBoard, sliceImagesWithTrackList, maxSliceWidth, theFinalHeight } =
+  useSliceTrack(hasMarkResultToRender);
 const { showBigImage } = useBigImage();
 
 // 在轨迹模式下,仅当没有选择分数时可用。
@@ -122,7 +122,7 @@ function initWatch() {
   watchEffect(() => {
     for (const track of markStore.removeScoreTracks) {
       for (const sliceImage of sliceImagesWithTrackList) {
-        sliceImage.trackList = sliceImage.trackList.filter(
+        sliceImage.markerTrackList = sliceImage.markerTrackList.filter(
           (t) =>
             !(
               t.mainNumber === track.mainNumber &&
@@ -141,7 +141,7 @@ function initWatch() {
     if (!markStore.currentTask) return;
     for (const sliceImage of sliceImagesWithTrackList) {
       sliceImage.tagList = sliceImage.tagList.filter((t) =>
-        markStore.currentTaskEnsured.markResult?.specialTagList.find(
+        markStore.currentTaskEnsured.markResult?.markerTagList.find(
           (st) =>
             st.offsetIndex === t.offsetIndex &&
             st.offsetX === t.offsetX &&
@@ -149,7 +149,7 @@ function initWatch() {
         )
       );
     }
-    if (markStore.currentTaskEnsured.markResult?.specialTagList.length === 0) {
+    if (markStore.currentTaskEnsured.markResult?.markerTagList.length === 0) {
       for (const sliceImage of sliceImagesWithTrackList) {
         sliceImage.tagList = [];
       }

+ 1 - 0
src/features/mark/MarkBodyCursor.vue

@@ -65,6 +65,7 @@ watch(
 
 onMounted(() => {
   if (markStore.isTrackMode) {
+    if (!document.querySelector(".cursor")) return;
     // eslint-disable-next-line @typescript-eslint/no-unsafe-call
     theCursor = new CustomCursor(".cursor", {
       focusElements: [

+ 2 - 2
src/features/mark/MarkBodySepecialTag.vue

@@ -185,7 +185,7 @@ function specialMouseStop() {
     });
   }
 
-  markStore.currentTaskEnsured.markResult.specialTagList.push(track);
+  markStore.currentTaskEnsured.markResult.markerTagList.push(track);
   curSliceImagesWithTrackItem.tagList.push(track);
   specialPoint = { x: 0, y: 0, ex: 0, ey: 0 };
 }
@@ -265,7 +265,7 @@ function textTrackBlur() {
       curSliceImagesWithTrackItem.accumTopHeight) /
     theFinalHeight;
 
-  markStore.currentTaskEnsured.markResult.specialTagList.push(track);
+  markStore.currentTaskEnsured.markResult.markerTagList.push(track);
   curSliceImagesWithTrackItem.tagList.push(track);
   initCacheTextTrack();
 }

+ 13 - 19
src/features/mark/MarkDrawTrack.vue

@@ -1,8 +1,8 @@
 <template>
   <transition-group name="track-score" tag="div">
-    <template v-for="track in trackList">
+    <template v-for="track in markerTrackList">
       <div
-        v-if="store.shouldShowTrack && (doubleTrack || !track.isByMultMark)"
+        v-if="markStore.shouldShowTrack && (doubleTrack || !track.isByMultMark)"
         :key="`key-${track.mainNumber}-${track.subNumber}-${track.offsetY}-${track.offsetX}`"
         class="score-container no-event"
         :class="[focusedTrack(track) && 'score-animation']"
@@ -12,15 +12,12 @@
           :id="`a-${track.mainNumber}-${track.subNumber}-${track.offsetY}-${track.offsetX}`"
           class="tw-m-auto"
         >
-          {{ track.unanswered ? "空" : track.score }}
+          {{ track.unanswered ? "空" : track.markerScore }}
         </span>
       </div>
     </template>
   </transition-group>
-  <template
-    v-for="tag in specialTagList"
-    :key="`${tag.offsetX}_${tag.offsetY}`"
-  >
+  <template v-for="tag in markerTagList" :key="`${tag.offsetX}_${tag.offsetY}`">
     <img
       v-if="tag.tagType === 'TEXT'"
       class="special-text"
@@ -74,8 +71,8 @@ const doubleTrack = computed(() => {
   return !!markStore.setting?.doubleTrack;
 });
 const props = defineProps<{
-  trackList: Array<Track>;
-  specialTagList: Array<SpecialTag>;
+  markerTrackList: Array<Track>;
+  markerTagList: Array<SpecialTag>;
   sliceImageWidth: number;
   sliceImageHeight: number;
   dx: number;
@@ -83,7 +80,7 @@ const props = defineProps<{
 }>();
 const emit = defineEmits(["click-specialtag"]);
 
-const { trackList } = toRefs(props);
+const { markerTrackList } = toRefs(props);
 
 const computeSpecialLineStyle = (track: SpecialTag) => {
   // {"tagName":"{\"len\":241.9842519685039}","tagType":"LINE","offsetIndex":2,"offsetX":324.8193228048039,"offsetY":759.8560783391572,"positionX":0.06189180773871382,"positionY":-0.01054037309709878}
@@ -224,14 +221,11 @@ const computeTopAndLeft = (track: Track | SpecialTag) => {
   };
 };
 const hasMember = (track: any) => {
-  return (
-    // (store.getMarkStatus === "正评" || store.getMarkStatus === "试评") &&
-    markStore.focusTracks.find((item: any) => {
-      return (
-        item.mainNumber == track.mainNumber && item.subNumber == track.subNumber
-      );
-    })
-  );
+  return markStore.focusTracks.find((item: any) => {
+    return (
+      item.mainNumber == track.mainNumber && item.subNumber == track.subNumber
+    );
+  });
 };
 const focusedTrack = (track: Track) => {
   return markStore.focusTracks.includes(track) || hasMember(track);
@@ -257,7 +251,7 @@ watch(
     );
     if (topTrack) {
       let allHeaderTracks = markStore.currentTask.questionList
-        .map((item: any) => item.headerTrack || [])
+        .map((item: any) => item.headerTrackList || [])
         .flat();
       console.log("allHeaderTracks", allHeaderTracks);
       let find = allHeaderTracks.find(

+ 16 - 3
src/features/mark/composables/useAutoChooseFirstQuestion.ts

@@ -1,14 +1,20 @@
 import { Question } from "@/types";
-import useMarkStore from "@/store";
-import { watch } from "vue";
+import { useMarkStore } from "@/store";
+import { watch, nextTick } from "vue";
+import useTaskRejection from "./useTaskRejection";
 
 /** chooseQuestion 当currentTask改变是,自动选择第一题 */
 export default function useAutoChooseFirstQuestion() {
   const markStore = useMarkStore();
+  const { showRejectedReason } = useTaskRejection();
 
   watch(
     () => markStore.currentTask,
     () => {
+      // 重置当前选择的quesiton和score
+      markStore.currentQuestion = undefined;
+      markStore.currentScore = undefined;
+
       // FIXed ME: 此时取到的还是score:null,但是 chooseQuestion之后就变成了score:0
       const firstQuestion = markStore.currentTask?.questionList[0];
       if (firstQuestion) {
@@ -53,9 +59,16 @@ export default function useAutoChooseFirstQuestion() {
   };
 
   function chooseQuestion(question: Question) {
-    store.currentQuestion = question;
+    if (!question.selfMark) return;
+    markStore.currentQuestion = question;
     // FIXME: maybe should be an async function, temp fix for eslint
     void scrollToQuestionOfBoard(question);
+
+    void nextTick(() => {
+      if (markStore.currentQuestion) {
+        showRejectedReason(markStore.currentQuestion);
+      }
+    });
   }
 
   return { chooseQuestion };

+ 7 - 7
src/features/mark/composables/useFocusTracks.ts

@@ -36,9 +36,9 @@ export default function useFocusTracks() {
     const listArr = unref(list);
     // console.log("listArr:", listArr);
     if (listArr) {
-      const trackList: any = list.map((q) => q.trackList).flat();
+      const markerTrackList: any = list.map((q) => q.markerTrackList).flat();
 
-      trackList
+      markerTrackList
         .filter((t) => {
           if (mainNumber) {
             return t.mainNumber === mainNumber && t.subNumber === subNumber;
@@ -48,7 +48,7 @@ export default function useFocusTracks() {
         })
         .forEach((t: any) => {
           // 回评时,如果没被删除
-          const shouldAdd = isMark ? trackList.includes(t) : true;
+          const shouldAdd = isMark ? markerTrackList.includes(t) : true;
           if (shouldAdd) {
             markStore.focusTracks.push(t);
           }
@@ -59,18 +59,18 @@ export default function useFocusTracks() {
     if (groupNumber) {
       markStore.currentTask?.questionList
         ?.filter((q) => q.groupNumber === groupNumber)
-        ?.map((q) => q.trackList)
+        ?.map((q) => q.markerTrackList)
         .flat()
         .forEach((t) => {
           // 回评时,如果没被删除
           const shouldAdd = isMark
-            ? markStore.currentTask?.markResult.trackList.includes(t)
+            ? markStore.currentTask?.markResult.markerTrackList.includes(t)
             : true;
           if (shouldAdd) markStore.focusTracks.push(t);
         });
     } else {
       markStore.currentTask?.questionList
-        ?.map((q) => q.trackList)
+        ?.map((q) => q.markerTrackList)
         .flat()
         .filter((t) => {
           if (mainNumber) {
@@ -82,7 +82,7 @@ export default function useFocusTracks() {
         .forEach((t) => {
           // 回评时,如果没被删除
           const shouldAdd = isMark
-            ? markStore.currentTask?.markResult.trackList.includes(t)
+            ? markStore.currentTask?.markResult.markerTrackList.includes(t)
             : true;
           if (shouldAdd) markStore.focusTracks.push(t);
         });

+ 8 - 8
src/features/mark/composables/useMakeTrack.ts

@@ -44,7 +44,7 @@ export default function useMakeTrack() {
       return;
     }
     if (
-      item.trackList.some((t) => {
+      item.markerTrackList.some((t) => {
         return (
           Math.pow(Math.abs(t.offsetX - track.offsetX), 2) +
             Math.pow(Math.abs(t.offsetY - track.offsetY), 2) <
@@ -73,19 +73,19 @@ export default function useMakeTrack() {
     }
     const markResult = markStore.currentTaskEnsured.markResult;
     const maxNumber =
-      markResult.trackList.length === 0
+      markResult.markerTrackList.length === 0
         ? 0
-        : Math.max(...markResult.trackList.map((t) => t.number));
+        : Math.max(...markResult.markerTrackList.map((t) => t.number));
     track.number = maxNumber + 1;
 
-    markResult.trackList = [...markResult.trackList, track];
+    markResult.markerTrackList = [...markResult.markerTrackList, track];
     const { __index, mainNumber, subNumber } = markStore.currentQuestion;
     markResult.scoreList[__index] =
-      markResult.trackList
+      markResult.markerTrackList
         .filter((t) => t.mainNumber === mainNumber && t.subNumber === subNumber)
-        .map((t) => t.score)
+        .map((t) => t.markerScore)
         .reduce((acc, v) => (acc += Math.round(v * 1000)), 0) / 1000;
-    item.trackList.push(track);
+    item.markerTrackList.push(track);
   }
 
   // 标记特殊轨迹 (特殊轨迹包括:文字、线条、圆圈)
@@ -133,7 +133,7 @@ export default function useMakeTrack() {
       console.log("两个轨迹相距过近");
       return;
     }
-    markStore.currentTaskEnsured.markResult.specialTagList.push(track);
+    markStore.currentTaskEnsured.markResult.markerTagList.push(track);
     item.tagList.push(track);
   }
 

+ 19 - 12
src/features/mark/composables/useMarkSubmit.ts

@@ -6,10 +6,10 @@ import { h } from "vue";
 import EventBus from "@/plugins/eventBus";
 import type { Question, MarkResult } from "@/types";
 import useStatus from "./useStatus";
-import { useMarkTask } from "./useMarkTask";
+import useMarkTask from "./useMarkTask";
 import { deepCopy } from "@/utils/utils";
 
-export function useMarkSubmit() {
+export default function useMarkSubmit() {
   const markStore = useMarkStore();
   const { updateStatus } = useStatus();
   const { nextTask } = useMarkTask();
@@ -68,7 +68,7 @@ export function useMarkSubmit() {
 
     if (markStore.isTrackMode) {
       const trackScores =
-        markResult.trackList
+        markResult.markerTrackList
           .map((t) => Math.round((t.score || 0) * 100))
           .reduce((acc, s) => acc + s, 0) / 100;
       if (trackScores !== markResult.markerScore) {
@@ -82,8 +82,8 @@ export function useMarkSubmit() {
 
     if (markStore.setting.forceSpecialTag) {
       if (
-        markResult.trackList.length === 0 &&
-        markResult.specialTagList.length === 0
+        markResult.markerTrackList.length === 0 &&
+        markResult.markerTagList.length === 0
       ) {
         void message.error({
           content: "强制标记已开启,请至少使用一个标记。",
@@ -101,14 +101,20 @@ export function useMarkSubmit() {
     const datas = deepCopy(markStore.currentTask.markResult);
     datas.spent = Date.now() - markStore.currentTask.__markStartTime;
     datas.questionList = datas.questionList.map((q) => {
-      q.trackList = datas.trackList.filter(
+      q.markerTrackList = datas.markerTrackList.filter(
         (t) => t.mainNumber === q.mainNumber && t.subNumber === q.subNumber
       );
-      q.specialTagList = datas.specialTagList.filter(
+      q.markerTagList = datas.markerTagList.filter(
         (t) => t.mainNumber === q.mainNumber && t.subNumber === q.subNumber
       );
+      q.markerScore = q.markerTrackList.reduce((acc, t) => {
+        return acc + (t.score || 0);
+      }, 0);
       return q;
     }) as Question[];
+
+    datas.markerTrackList = [];
+    datas.markerTagList = [];
     return datas;
   }
 
@@ -121,7 +127,7 @@ export function useMarkSubmit() {
     if (!checkMarkResult(markResult)) return;
 
     if (!markStore.isTrackMode) {
-      markResult.trackList = [];
+      markResult.markerTrackList = [];
     }
 
     console.log("save task to server");
@@ -159,11 +165,12 @@ export function useMarkSubmit() {
     const markResult = markStore.currentTask?.markResult;
     if (!markResult) return;
 
-    const { markerScore, scoreList, trackList, specialTagList } = markResult;
+    const { markerScore, scoreList, markerTrackList, markerTagList } =
+      markResult;
     markResult.markerScore = 0;
     const ss = new Array(markStore.currentTaskEnsured.questionList.length);
     markResult.scoreList = ss.fill(0);
-    markResult.trackList = [];
+    markResult.markerTrackList = [];
 
     try {
       await saveTaskToServer();
@@ -172,8 +179,8 @@ export function useMarkSubmit() {
     } finally {
       markResult.markerScore = markerScore;
       markResult.scoreList = scoreList;
-      markResult.trackList = trackList;
-      markResult.specialTagList = specialTagList;
+      markResult.markerTrackList = markerTrackList;
+      markResult.markerTagList = markerTagList;
     }
   };
 

+ 1 - 22
src/features/mark/composables/useMarkTask.ts

@@ -1,13 +1,10 @@
 import { clearMarkTask, getTask } from "@/api/markPage";
 import { useMarkStore } from "@/store";
-import { nextTick, watch } from "vue";
-import useTaskRejection from "./useTaskRejection";
 import useDraw from "./useDraw";
 import useStatus from "./useStatus";
 
 export default function useMarkTask() {
   const markStore = useMarkStore();
-  const { showRejectedReason } = useTaskRejection();
   const { updateStatus } = useStatus();
   const { processSliceUrls } = useDraw();
 
@@ -18,7 +15,7 @@ export default function useMarkTask() {
   }
 
   async function updateTask() {
-    const res = await getTask(markStore.setting.questionModal);
+    const res = await getTask(markStore.setting.questionModel);
     if (res.data) {
       const newTask = res.data;
       newTask.sheetUrls = newTask.sheetUrls || [];
@@ -70,24 +67,6 @@ export default function useMarkTask() {
     }
   }
 
-  function watchCurrentTask() {
-    watch(
-      () => markStore.currentTask,
-      () => {
-        // 重置当前选择的quesiton和score
-        markStore.currentQuestion = undefined;
-        markStore.currentScore = undefined;
-        void nextTick(() => {
-          if (markStore.currentTask) {
-            showRejectedReason(markStore.currentTask);
-          }
-        });
-      }
-    );
-  }
-
-  watchCurrentTask();
-
   return {
     updateMarkTask,
     updateTask,

+ 5 - 3
src/features/mark/composables/useSetting.ts

@@ -34,9 +34,11 @@ export default function useSetting() {
   }
 
   const debouncedUpdateUISetting = debounce(() => {
-    updateUISetting(markStore.setting.mode, markStore.setting.uiSetting).catch(
-      (e) => console.log("保存设置出错", e)
-    );
+    updateUISetting(
+      markStore.setting.mode,
+      markStore.setting.uiSetting,
+      markStore.setting.questionModel
+    ).catch((e) => console.log("保存设置出错", e));
   }, 3000);
 
   watch(

+ 23 - 18
src/features/mark/composables/useSliceTrack.ts

@@ -1,13 +1,13 @@
 import { message } from "ant-design-vue";
-import { ref } from "vue";
+import { ref, watch } from "vue";
 import type { SliceImage } from "@/types";
 import { useMarkStore } from "@/store";
 import { loadImage } from "@/utils/utils";
 import EventBus from "@/plugins/eventBus";
 import useDraw from "./useDraw";
 // 计算裁切图和裁切图上的分数轨迹和特殊标记轨迹
-export default function useSliceTrack() {
-  const emit = defineEmits(["error"]);
+export default function useSliceTrack(hasMarkResultToRender = false) {
+  // const emit = defineEmits(["error"]);
 
   const markStore = useMarkStore();
   const { getDataUrlForSliceConfig, getDataUrlForSplitConfig } = useDraw();
@@ -66,12 +66,12 @@ export default function useSliceTrack() {
     let accumTopHeight = 0;
     let accumBottomHeight = 0;
     const trackLists = hasMarkResultToRender
-      ? markResult.trackList
-      : markStore.currentTask.questionList.map((q) => q.trackList).flat();
+      ? markResult.markerTrackList
+      : markStore.currentTask.questionList.map((q) => q.markerTrackList).flat();
 
     const tagLists = hasMarkResultToRender
-      ? markResult.specialTagList ?? []
-      : markStore.currentTask.specialTagList ?? [];
+      ? markResult.markerTagList ?? []
+      : markStore.currentTask.markerTagList ?? [];
 
     const tempSliceImagesWithTrackList: Array<SliceImage> = [];
     for (const sliceConfig of markStore.currentTask.sliceConfig) {
@@ -100,7 +100,7 @@ export default function useSliceTrack() {
         url: dataUrl,
         indexInSliceUrls: sliceConfig.i,
         // 通过positionY来定位是第几张slice的还原,并过滤出相应的track
-        trackList: thisImageTrackList.filter(
+        markerTrackList: thisImageTrackList.filter(
           (t) =>
             t.positionY >= accumTopHeight / theFinalHeight.value &&
             t.positionY < accumBottomHeight / theFinalHeight.value
@@ -125,7 +125,7 @@ export default function useSliceTrack() {
     // 测试是否所有的track和tag都在待渲染的tempSliceImagesWithTrackList中
     const numOfTrackAndTagInData = trackLists.length + tagLists.length;
     const numOfTrackAndTagInTempSlice = tempSliceImagesWithTrackList
-      .map((v) => v.trackList.length + v.tagList.length)
+      .map((v) => v.markerTrackList.length + v.tagList.length)
       .reduce((p, c) => p + c);
     if (numOfTrackAndTagInData !== numOfTrackAndTagInTempSlice) {
       console.warn({ tagLists, trackLists, tempSliceImagesWithTrackList });
@@ -137,7 +137,7 @@ export default function useSliceTrack() {
       // 初次渲染,不做动画
       sliceImagesWithTrackList.push(...tempSliceImagesWithTrackList);
       // 没抽象好,这里不好做校验
-      // const renderedTrackAndTagNumber = sliceImagesWithTrackList.map(s => s.trackList.length + s.tagList.length).reduce((p,c) => p+ c);
+      // const renderedTrackAndTagNumber = sliceImagesWithTrackList.map(s => s.markerTrackList.length + s.tagList.length).reduce((p,c) => p+ c);
       // if(renderedTrackAndTagNumber === thisIma)
     } else {
       rotateBoard.value = 1;
@@ -211,13 +211,13 @@ export default function useSliceTrack() {
     let accumBottomHeight = 0;
     const tempSliceImagesWithTrackList: SliceImage[] = [];
     const trackLists = hasMarkResultToRender
-      ? markResult.trackList
+      ? markResult.markerTrackList
       : (markStore.currentTask.questionList || [])
-          .map((q) => q.trackList)
+          .map((q) => q.markerTrackList)
           .flat();
     const tagLists = hasMarkResultToRender
-      ? markResult.specialTagList ?? []
-      : markStore.currentTask.specialTagList ?? [];
+      ? markResult.markerTagList ?? []
+      : markStore.currentTask.markerTagList ?? [];
     for (const url of markStore.currentTask.sliceUrls) {
       for (const config of splitConfigPairs) {
         const indexInSliceUrls =
@@ -251,7 +251,7 @@ export default function useSliceTrack() {
         tempSliceImagesWithTrackList.push({
           url: dataUrl,
           indexInSliceUrls: markStore.currentTask.sliceUrls.indexOf(url) + 1,
-          trackList: thisImageTrackList.filter(
+          markerTrackList: thisImageTrackList.filter(
             (t) =>
               t.positionY >= accumTopHeight / theFinalHeight.value &&
               t.positionY < accumBottomHeight / theFinalHeight.value
@@ -282,7 +282,7 @@ export default function useSliceTrack() {
     // 测试是否所有的track和tag都在待渲染的tempSliceImagesWithTrackList中
     const numOfTrackAndTagInData = trackLists.length + tagLists.length;
     const numOfTrackAndTagInTempSlice = tempSliceImagesWithTrackList
-      .map((v) => v.trackList.length + v.tagList.length)
+      .map((v) => v.markerTrackList.length + v.tagList.length)
       .reduce((p, c) => p + c);
     if (numOfTrackAndTagInData !== numOfTrackAndTagInTempSlice) {
       console.warn({ tagLists, trackLists, tempSliceImagesWithTrackList });
@@ -330,7 +330,7 @@ export default function useSliceTrack() {
       sliceImagesWithTrackList.splice(0);
       console.trace("render error ", error);
       // 图片加载出错,自动加载下一个任务
-      emit("error");
+      // emit("error");
     } finally {
       markStore.renderLock = false;
       markStore.globalMask = false;
@@ -353,5 +353,10 @@ export default function useSliceTrack() {
     { deep: true }
   );
 
-  return { maxSliceWidth, theFinalHeight, sliceImagesWithTrackList };
+  return {
+    rotateBoard,
+    maxSliceWidth,
+    theFinalHeight,
+    sliceImagesWithTrackList,
+  };
 }

+ 1 - 1
src/features/mark/composables/useStatus.ts

@@ -13,7 +13,7 @@ export default function useStatus() {
   const loadingStatusSpinning = ref(true);
 
   async function updateStatus() {
-    const res = await getStatus(markStore.setting.questionModal);
+    const res = await getStatus(markStore.setting.questionModel);
     markStore.setInfo({ status: res.data });
   }
 

+ 4 - 4
src/features/mark/composables/useTaskRejection.ts

@@ -1,12 +1,12 @@
 import { Modal } from "ant-design-vue";
 import { h } from "vue";
-import type { Task } from "@/types";
+import type { Question } from "@/types";
 
 export default function useTaskRejection() {
-  const showRejectedReason = (task: Task) => {
-    if (!task || !task.rejectReason || !task.rejectReason) return;
+  const showRejectedReason = (question: Question) => {
+    if (!question || !question.rejectReason) return;
 
-    const [reasonType, reasonDesc] = task.rejectReason.split(":");
+    const [reasonType, reasonDesc] = question.rejectReason.split(":");
     Modal.info({
       title: null,
       closable: false,

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

@@ -34,20 +34,21 @@ export default function useTaskWatch() {
           studentId,
           spent: 0,
           statusValue,
-          trackList: task.questionList
+          questionList: task.questionList,
+          markerTrackList: task.questionList
             .map((q) =>
-              q.headerTrack && q.headerTrack.length
-                ? q.headerTrack
-                : q.trackList
+              q.headerTrackList && q.headerTrackList.length
+                ? q.headerTrackList
+                : q.markerTrackList
             )
             .flat(),
-          specialTagList: task.questionList
-            .map((q) => q.specialTagList || [])
+          markerTagList: task.questionList
+            .map((q) => q.markerTagList || [])
             .flat(),
-          scoreList: task.questionList.map((q) => q.score),
+          scoreList: task.questionList.map((q) => q.markerScore),
           markerScore: null, // 后期通过 scoreList 自动更新
         };
-        task.markResult.trackList.forEach((t) => {
+        task.markResult.markerTrackList.forEach((t) => {
           if (t.unanswered) {
             t.score = -0;
           }

+ 1 - 1
src/features/mark/modals/ModalMinimap.vue

@@ -1,6 +1,6 @@
 <template>
   <qm-dialog
-    v-if="store.setting.uiSetting['minimap.modal']"
+    v-if="markStore.setting.uiSetting['minimap.modal']"
     top="10%"
     width="312px"
     height="400px"

+ 2 - 2
src/features/mark/modals/ModalSpecialTag.vue

@@ -106,12 +106,12 @@ const markStore = useMarkStore();
 
 function clearLatestTagOfCurrentTask() {
   if (!markStore.currentTask?.markResult) return;
-  markStore.currentTask.markResult.specialTagList.splice(-1);
+  markStore.currentTask.markResult.markerTagList.splice(-1);
 }
 
 function clearAllTagsOfCurrentTask() {
   if (!markStore.currentTask?.markResult) return;
-  markStore.currentTask.markResult.specialTagList = [];
+  markStore.currentTask.markResult.markerTagList = [];
 }
 
 function chooseSpecialTag(tagName: string, tagType: string) {

+ 4 - 1
src/features/mark/scoring/MarkBoardKeyBoard.vue

@@ -69,7 +69,10 @@
             :id="'bq-' + question.mainNumber + '-' + question.subNumber"
             :class="[
               'board-question',
-              { 'is-current': isCurrentQuestion(question) },
+              {
+                'is-current': isCurrentQuestion(question),
+                'is-disabled': !question.selfMark,
+              },
             ]"
             @click="
               () => {

+ 1 - 1
src/features/mark/scoring/MarkBoardMouse.vue

@@ -66,7 +66,7 @@
         <div class="board-question-full-box">
           <div
             :id="'bq-' + question.mainNumber + '-' + question.subNumber"
-            :class="['board-question']"
+            :class="['board-question', { 'is-disabled': !question.selfMark }]"
           >
             <div class="question-info">
               <div class="question-title" :title="question.title">

+ 11 - 6
src/features/mark/scoring/MarkBoardTrack.vue

@@ -67,7 +67,10 @@
             "
             :class="[
               'board-question',
-              { 'is-current': isCurrentQuestion(question) },
+              {
+                'is-current': isCurrentQuestion(question),
+                'is-disabled': !question.selfMark,
+              },
             ]"
             tabindex="0"
             outline="0"
@@ -278,7 +281,7 @@ watch(
 );
 
 const questionScoreDisabled = $computed(() => {
-  const qno = `${markStore.currentQuestion.mainNumber}_${markStore.currentQuestion.subNumber}`;
+  const qno = `${markStore.currentQuestion?.mainNumber}_${markStore.currentQuestion?.subNumber}`;
   return props.isCheckAnswer && !markStore.currentTaskModifyQuestion[qno];
 });
 
@@ -427,7 +430,7 @@ function clearLatestMarkOfCurrentQuetion() {
 
   const { __index, mainNumber, subNumber } = markStore.currentQuestion;
   const markResult = markStore.currentTask.markResult;
-  const ts = markResult.trackList.filter(
+  const ts = markResult.markerTrackList.filter(
     (q) => q.mainNumber === mainNumber && q.subNumber === subNumber
   );
   console.log(ts);
@@ -437,7 +440,9 @@ function clearLatestMarkOfCurrentQuetion() {
   }
   const lastMark = ts.splice(-1)[0];
   markStore.removeScoreTracks = [lastMark];
-  markResult.trackList = markResult.trackList.filter((t) => t !== lastMark);
+  markResult.markerTrackList = markResult.markerTrackList.filter(
+    (t) => t !== lastMark
+  );
 
   markResult.scoreList[__index] =
     ts.length === 0
@@ -457,12 +462,12 @@ function clearAllMarksOfCurrentQuetion() {
   markStore.currentTaskModifyQuestion[qno] = true;
 
   const markResult = markStore.currentTask.markResult;
-  markStore.removeScoreTracks = markResult.trackList.filter(
+  markStore.removeScoreTracks = markResult.markerTrackList.filter(
     (q) =>
       q.mainNumber === markStore.currentQuestion?.mainNumber &&
       q.subNumber === markStore.currentQuestion?.subNumber
   );
-  markResult.trackList = markResult.trackList.filter(
+  markResult.markerTrackList = markResult.markerTrackList.filter(
     (q) => !markStore.removeScoreTracks.includes(q)
   );
   const { __index } = markStore.currentQuestion;

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

@@ -6,7 +6,7 @@ const useMarkStore = defineStore("mark", {
     setting: {
       examType: "SCAN_IMAGE",
       mode: "TRACK",
-      questionModal: "MULTI",
+      questionModel: "MULTI",
       forceMode: false,
       sheetView: false,
       sheetConfig: [],

+ 7 - 7
src/features/mark/toolbar/MarkTool.vue

@@ -301,24 +301,24 @@ function toEyecare() {
 }
 // 阅卷模式切换
 const questionModalName = computed(() => {
-  return markStore.setting.questionModal === "SINGLE"
+  return markStore.setting.questionModel === "SINGLE"
     ? "按小题阅卷"
     : "阅全部题目";
 });
 const toSwitchQuestionModal = () => {
   const qname =
-    markStore.setting.questionModal === "SINGLE" ? "阅全部题目" : "按小题阅卷";
+    markStore.setting.questionModel === "SINGLE" ? "阅全部题目" : "按小题阅卷";
 
   Modal.confirm({
     title: "操作警告",
     content: `确定切换为${qname}吗?`,
     async onOk() {
-      markStore.setting.questionModal =
-        markStore.setting.questionModal === "SINGLE" ? "MULTI" : "SINGLE";
+      markStore.setting.questionModel =
+        markStore.setting.questionModel === "SINGLE" ? "MULTI" : "SINGLE";
       await updateUISetting(
         markStore.setting.mode,
         markStore.setting.uiSetting,
-        markStore.setting.questionModal
+        markStore.setting.questionModel
       );
       window.location.reload();
     },
@@ -327,12 +327,12 @@ const toSwitchQuestionModal = () => {
 
 function clearLatestTagOfCurrentTask() {
   if (!markStore.currentTask?.markResult) return;
-  markStore.currentTask.markResult.specialTagList.splice(-1);
+  markStore.currentTask.markResult.markerTagList.splice(-1);
 }
 
 function clearAllTagsOfCurrentTask() {
   if (!markStore.currentTask?.markResult) return;
-  markStore.currentTask.markResult.specialTagList = [];
+  markStore.currentTask.markResult.markerTagList = [];
 }
 
 function chooseSpecialTag(tagName: string, tagType: string) {

+ 9 - 9
src/features/track/TrackBody.vue

@@ -20,8 +20,8 @@
         >
           <img :src="item.url" draggable="false" />
           <MarkDrawTrack
-            :trackList="item.trackList"
-            :specialTagList="item.tagList"
+            :markerTrackList="item.markerTrackList"
+            :markerTagList="item.tagList"
             :sliceImageHeight="item.originalImageHeight"
             :sliceImageWidth="item.originalImageWidth"
             :dx="0"
@@ -170,7 +170,7 @@ const subjectiveScore = $computed(() => {
 
 interface SliceImage {
   url: string;
-  trackList: Array<Track>;
+  markerTrackList: Array<Track>;
   tagList: Array<SpecialTag>;
   originalImageWidth: number;
   originalImageHeight: number;
@@ -216,11 +216,11 @@ async function processImage() {
   maxImageWidth = Math.max(...images.map((i) => i.naturalWidth));
 
   const trackLists = (markStore.currentTask.questionList || [])
-    // .map((q) => q.trackList)
+    // .map((q) => q.markerTrackList)
     .map((q) => {
-      let tList = q.trackList;
-      return q.headerTrack?.length
-        ? addHeaderTrackColorAttr(q.headerTrack)
+      let tList = q.markerTrackList;
+      return q.headerTrackList?.length
+        ? addHeaderTrackColorAttr(q.headerTrackList)
         : addTrackColorAttr(tList);
     })
     .flat();
@@ -244,7 +244,7 @@ async function processImage() {
           )
         )
       : addTagColorAttr(
-          (markStore.currentTask.specialTagList || []).filter(
+          (markStore.currentTask.markerTagList || []).filter(
             (t) => t.offsetIndex === indexInSliceUrls
           )
         );
@@ -252,7 +252,7 @@ async function processImage() {
 
     sliceImagesWithTrackList.push({
       url,
-      trackList: thisImageTrackList,
+      markerTrackList: thisImageTrackList,
       tagList: thisImageTagList,
       originalImageWidth: image.naturalWidth,
       originalImageHeight: image.naturalHeight,

+ 2 - 2
src/features/track/composables/useTrack.ts

@@ -54,8 +54,8 @@ export default function useTrack() {
     return tList;
   }
 
-  function addHeaderTrackColorAttr(headerTrack: Track[]): Track[] {
-    return headerTrack.map((item: Track) => {
+  function addHeaderTrackColorAttr(headerTrackList: Track[]): Track[] {
+    return headerTrackList.map((item: Track) => {
       item.color = "green";
       return item;
     });

+ 15 - 13
src/features/track/composables/useTrackTag.ts

@@ -237,7 +237,7 @@ export default function useTrackTag() {
       const userMap: UserMapType = {};
       // 大题分成两个部分给两个人评 与 大题被两人同时评 是不一样的
       const isDoubleMark = !groupQuestions.some((question) => {
-        let userIds = question.trackList.map((track) => track.userId);
+        let userIds = question.markerTrackList.map((track) => track.userId);
         if (
           !userIds.length &&
           question.markerList &&
@@ -251,7 +251,7 @@ export default function useTrackTag() {
         return uids.size === 1;
       });
       groupQuestions.forEach((question) => {
-        question.trackList.forEach((track) => {
+        question.markerTrackList.forEach((track) => {
           if (!userMap[track.userId]) {
             userMap[track.userId] = {
               userId: track.userId,
@@ -266,10 +266,10 @@ export default function useTrackTag() {
             (s) => s.subNumber === track.subNumber
           );
           if (existUserScore) {
-            existUserScore.score += track.score;
+            existUserScore.score += track.markerScore;
           } else {
             userMap[track.userId].scores.push({
-              score: track.score,
+              score: track.markerScore,
               subNumber: track.subNumber,
             });
           }
@@ -277,7 +277,7 @@ export default function useTrackTag() {
 
         // 普通模式没有轨迹
         if (
-          !question.trackList.length &&
+          !question.markerTrackList.length &&
           question.markerList &&
           question.markerList.length
         ) {
@@ -349,8 +349,10 @@ export default function useTrackTag() {
       }
 
       const userMap: UserMapType = {};
-      const isArbitration = Boolean(question.headerTrack?.length);
-      const tList = isArbitration ? question.headerTrack : question.trackList;
+      const isArbitration = Boolean(question.headerTrackList?.length);
+      const tList = isArbitration
+        ? question.headerTrackList
+        : question.markerTrackList;
       tList.forEach((track) => {
         if (!userMap[track.userId]) {
           userMap[track.userId] = {
@@ -363,7 +365,7 @@ export default function useTrackTag() {
           };
         }
         userMap[track.userId].scores.push({
-          score: track.score,
+          score: track.markerScore,
           subNumber: track.subNumber,
         });
       });
@@ -518,7 +520,7 @@ export default function useTrackTag() {
     // 只有单评才展示summary
     const isDoubleMark = (markStore.currentTask.questionList || []).some(
       (question) => {
-        let userIds = question.trackList.map((track) => track.userId);
+        let userIds = question.markerTrackList.map((track) => track.userId);
         if (
           !userIds.length &&
           question.markerList &&
@@ -536,10 +538,10 @@ export default function useTrackTag() {
 
     return (markStore.currentTask.questionList || []).map((q) => {
       let markerName = "";
-      if (q.headerTrack && q.headerTrack.length) {
-        markerName = q.headerTrack[0].userName;
-      } else if (q.trackList && q.trackList.length) {
-        markerName = q.trackList[0].userName;
+      if (q.headerTrackList && q.headerTrackList.length) {
+        markerName = q.headerTrackList[0].userName;
+      } else if (q.markerTrackList && q.markerTrackList.length) {
+        markerName = q.markerTrackList[0].userName;
       } else if (q.markerList && q.markerList.length) {
         let markers = q.markerList.filter((marker) => marker.header);
         if (!markers.length) {

+ 9 - 9
src/types/index.ts

@@ -67,7 +67,7 @@ export interface Setting {
   /** 阅卷模式 TRACK | COMMON */
   mode: "TRACK" | "COMMON";
   /** 试题评阅方式 SINGLE:单题阅,MULTI:多题阅 */
-  questionModal: "SINGLE" | "MULTI";
+  questionModel: "SINGLE" | "MULTI";
   /** 是否允许模式切换,true为不允许 */
   forceMode: boolean;
   /** 是否显示原图功能 */
@@ -313,8 +313,8 @@ interface RawQuestion {
   // 任务状态: WAIT_ARBITRATE:待仲裁,PROBLEM:问题卷
   status: "WAIT_ARBITRATE" | "PROBLEM" | "WAITING" | "MARKED";
   /** 轨迹列表 */
-  trackList: Array<Track>;
-  headerTrack?: Array<Track>;
+  markerTrackList: Array<Track>;
+  headerTrackList?: Array<Track>;
   /** 无轨迹情况下评卷员打分信息 */
   markerList: null | Array<{
     // 是否是科组长
@@ -325,7 +325,7 @@ interface RawQuestion {
     userName: string;
   }>;
   // 特殊标记列表
-  specialTagList: Array<SpecialTag> | null;
+  markerTagList: Array<SpecialTag> | null;
   // 打回原因
   rejectReason: string | null;
   // 打回前给分数据
@@ -425,11 +425,11 @@ export interface MarkResultQuestion {
   // 轨迹 or 键盘
   markerScore: number | null;
   /** 轨迹列表 */
-  trackList: Array<Track>;
+  markerTrackList: Array<Track>;
   /** 给分列表 */
   scoreList: Array<number | null>;
   /** 轨迹和键盘都需要 */
-  specialTagList: Array<SpecialTag>;
+  markerTagList: Array<SpecialTag>;
   /** 问题卷 */
   problem: boolean;
   /** 问题卷类型 */
@@ -453,9 +453,9 @@ export interface MarkResult {
   /** 试题列表 */
   questionList: Array<MarkResultQuestion>;
   /** 轨迹列表 */
-  trackList: Array<Track>;
+  markerTrackList: Array<Track>;
   /** 特殊标记列表 */
-  specialTagList: Array<SpecialTag>;
+  markerTagList: Array<SpecialTag>;
   /** 给分列表 */
   scoreList: Array<number | null>;
   /** 评卷员分数 */
@@ -467,7 +467,7 @@ export interface SliceImage {
   /** 当前是 ObjectURL , 因为 DataURL 性能太差 */
   url: string;
   indexInSliceUrls: number;
-  trackList: Array<Track>;
+  markerTrackList: Array<Track>;
   tagList: Array<SpecialTag>;
   // originalImageWidth: number; // 为了兼容原图还原轨迹而添加的属性,当前CommonMarkBody用不到
   // originalImageHeight: number; // 为了兼容原图还原轨迹而添加的属性,当前CommonMarkBody用不到

Beberapa file tidak ditampilkan karena terlalu banyak file yang berubah dalam diff ini