소스 검색

feat: 客观题统分信息,依赖知学知考3.4.0

zhangjie 11 달 전
부모
커밋
6feefc4090

+ 1 - 1
package.json

@@ -1,7 +1,7 @@
 {
   "name": "teachcloud-mark-tool",
   "description": "teachcloud mark tool",
-  "version": "1.0.1",
+  "version": "1.0.2",
   "main": "./out/main/index.js",
   "author": "chulinice",
   "license": "MIT",

+ 5 - 1
src/api/types/task.ts

@@ -170,6 +170,8 @@ export type StudentObjectiveInfo = {
     exist: boolean;
     questionType: string;
     standardAnswer: string;
+    score: number;
+    totalScore: number;
   }>;
   titles: { [index: number]: string };
   success: boolean;
@@ -199,6 +201,7 @@ export interface TrackExportDetailListFilter {
   paperNumber: string;
   college?: string;
   majorName?: string;
+  teachClassName?: string;
   className?: string;
   studentName?: string;
   studentCode?: string;
@@ -218,7 +221,8 @@ export type TrackExportDetailListParams =
   PageParams<TrackExportDetailListFilter>;
 
 export interface TrackExportDetailItem {
-  className: string;
+  teachClassName: string; // 教学班
+  className: string; // 行政班
   college: string;
   courseCode: string;
   courseName: string;

+ 38 - 11
src/views/base/track-export/indexDetail.vue

@@ -26,9 +26,15 @@
           allow-clear
         >
         </a-input>
+        <a-input
+          v-model.trim="searchModel.teachClassName"
+          placeholder="教学班"
+          allow-clear
+        >
+        </a-input>
         <a-input
           v-model.trim="searchModel.className"
-          placeholder="班级"
+          placeholder="行政班"
           allow-clear
         >
         </a-input>
@@ -238,6 +244,7 @@
     college: '',
     majorName: '',
     className: '',
+    teachClassName: '',
     studentName: '',
     studentCode: '',
     startStudentCode: '',
@@ -267,20 +274,45 @@
       dataIndex: 'studentCode',
       width: 140,
     },
+    {
+      title: '状态',
+      dataIndex: 'statusDisplay',
+      width: 140,
+    },
+    {
+      title: '成绩',
+      dataIndex: 'totalScore',
+      width: 80,
+    },
+    {
+      title: '主观分',
+      dataIndex: 'subjectiveScore',
+      width: 80,
+    },
+    {
+      title: '客观分',
+      dataIndex: 'objectiveScore',
+      width: 80,
+    },
     {
       title: '院系',
       dataIndex: 'collegeName',
-      width: 140,
+      width: 180,
     },
     {
       title: '专业',
       dataIndex: 'majorName',
-      width: 140,
+      width: 180,
     },
     {
-      title: '班级',
+      title: '教学班',
+      dataIndex: 'teachClassName',
+      width: 200,
+    },
+    {
+      title: '行政班',
       dataIndex: 'className',
-      width: 140,
+      width: 200,
     },
     {
       title: '考试时间',
@@ -290,12 +322,7 @@
     {
       title: '课程(代码)',
       slotName: 'courseCode',
-      width: 240,
-    },
-    {
-      title: '成绩',
-      dataIndex: 'totalScore',
-      width: 80,
+      width: 260,
     },
     {
       title: '操作',

+ 2 - 13
src/views/base/track-export/readme.md

@@ -1,18 +1,7 @@
-# 计划
-
-- sqlite3 -ok-
-- model/db -ok-
-- api
-- page view set -ok-
-- gm-imagemagic -ok-
-- task build -ok-
-- process manange
-
 ## 轨迹图导出执行流程
 
-- 设置任务参数,保存数据
+- 设置任务参数。
 - 获取任务列表详情数据,保存数据。
-  - 此过程如果耗时过长,会触发 token 更新机制。
 - 开启多窗口执行任务。
-- 单个窗口获取当前任务配置,获取数据完整的细分任务,执行任务。
+- 单个窗口获取当前任务配置,获取细分任务的完整数据,执行任务。
 - 主窗口轮询任务进度。一旦结束,广播任务结束事件,关闭所有隐藏窗口。

+ 129 - 11
src/views/base/track-export/useDraw.ts

@@ -15,7 +15,10 @@ import { DrawTrackItem } from '../../../../electron/preload/types';
 import { TrackTaskData } from '../../../../electron/db/models/trackTask';
 import { TrackTaskDetailData } from '../../../../electron/db/models/trackTaskDetail';
 
-type AnswerMap = Record<string, { answer: string; isRight: boolean }>;
+type AnswerMap = Record<
+  string,
+  { answer: string; isRight: boolean; score: number; totalScore: number }
+>;
 
 interface TrackItemType {
   url: string;
@@ -31,6 +34,16 @@ type ElementType =
   | 'COMPOSITION'
   | 'TOPIC_HEAD'
   | 'CARD_HEAD';
+interface CardBaseElement {
+  id: string;
+  type: ElementType;
+  topicNo: number;
+  startNumber: number;
+  questionsCount: number;
+}
+interface CardElement extends CardBaseElement {
+  parent: CardBaseElement;
+}
 interface CardDataItem {
   exchange: {
     answer_area: Array<{
@@ -38,14 +51,20 @@ interface CardDataItem {
       sub_number: number | string;
       area: [number, number, number, number];
     }>;
+    fill_area: Array<{
+      field: 'question' | 'examNumber';
+      index: number;
+      single: boolean;
+      horizontal: boolean;
+      items: Array<{
+        main_number: number;
+        sub_number: number | string;
+        options: [number, number, number, number][];
+      }>;
+    }>;
   };
   columns: Array<{
-    elements: Array<{
-      type: ElementType;
-      topicNo: number;
-      startNumber: number;
-      questionsCount: number;
-    }>;
+    elements: CardElement[];
   }>;
 }
 
@@ -218,6 +237,8 @@ export default function useDraw(winId: number) {
     objectiveData.answers.forEach((item) => {
       answerMap[`${item.mainNumber}_${item.subNumber}`] = {
         answer: item.answer,
+        totalScore: item.totalScore,
+        score: item.score,
         isRight: item.answer === item.standardAnswer,
       };
     });
@@ -291,6 +312,7 @@ export default function useDraw(winId: number) {
       .flat();
 
     const markDeailList = parseMarkDetailList(originImgs);
+    const objectiveAnswerTagList = parseObjectiveAnswerTags(originImgs);
 
     for (let i = 0; i < originImgs.length; i++) {
       const img = originImgs[i];
@@ -308,6 +330,10 @@ export default function useDraw(winId: number) {
       const answerTags = paserRecogData(i);
       drawTrackList.push(...answerTags);
       drawTrackList.push(...(markDeailList[i] || []));
+      const oTags = (objectiveAnswerTagList[i] || []).map(
+        (tag) => tag.trackItem
+      );
+      drawTrackList.push(...oTags);
       drawTrackList.push(getTotalTrack(img));
 
       trackData[i] = {
@@ -589,10 +615,10 @@ export default function useDraw(winId: number) {
       dataArr.push({
         type: 'text',
         option: {
-          x: area.x + area.w - Math.ceil(tContLen * 30),
+          x: area.x + area.w - Math.ceil(tContLen * trackTextFontSize),
           y: area.y,
           text: tCont,
-          fontSize: 30,
+          fontSize: trackTextFontSize,
         },
       });
     });
@@ -661,10 +687,10 @@ export default function useDraw(winId: number) {
       dataArr.push({
         type: 'text',
         option: {
-          x: area.x + area.w - Math.ceil(tContLen * 30),
+          x: area.x + area.w - Math.ceil(tContLen * trackTextFontSize),
           y: area.y,
           text: tCont,
-          fontSize: 30,
+          fontSize: trackTextFontSize,
         },
       });
     });
@@ -822,6 +848,98 @@ export default function useDraw(winId: number) {
   }
   // answer tag ----- end->
 
+  // objective answer tag ----- start->
+  interface ObjectiveAnswerTagItem {
+    id: string;
+    mainNumber: number;
+    subNumbers: string;
+    score: number;
+    totalScore: number;
+    trackItem: DrawTrackItem;
+  }
+  function parseObjectiveAnswerTags(images: ImageItem[]) {
+    const objectiveAnswerTags: Array<ObjectiveAnswerTagItem[]> = [];
+
+    if (!cardData?.length) return objectiveAnswerTags;
+
+    cardData.forEach((page, pindex) => {
+      if (!objectiveAnswerTags[pindex]) objectiveAnswerTags[pindex] = [];
+      const img = images[pindex] as ImageItem;
+
+      page.columns.forEach((column) => {
+        column.elements.forEach((element) => {
+          if (element.type !== 'FILL_QUESTION') return;
+
+          const ogroup = objectiveAnswerTags.find((tgroup) =>
+            tgroup.some((oitem) => oitem.id === element.parent.id)
+          );
+          if (ogroup) return;
+
+          const parent = element.parent;
+          const oaTagItem: ObjectiveAnswerTagItem = {
+            id: parent.id,
+            mainNumber: parent.topicNo,
+            subNumbers: `${parent.startNumber}~${
+              parent.startNumber + parent.questionsCount - 1
+            }`,
+            score: 0,
+            totalScore: 0,
+            trackItem: {} as DrawTrackItem,
+          };
+          // 位置
+          const area = { x: 0, y: 0, w: 0.44 };
+          page.exchange.fill_area.forEach((fa) => {
+            fa.items.forEach((fitem) => {
+              if (
+                fitem.main_number === oaTagItem.mainNumber &&
+                fitem.sub_number === parent.startNumber
+              ) {
+                const [x, y] = fitem.options[0];
+                area.x = x;
+                area.y = y;
+              }
+            });
+          });
+          area.x = (area.x - 0.015) * img.width;
+          area.y = (area.y - 0.04) * img.height;
+          area.w *= img.width;
+
+          // 分数统计
+          const questions: Array<{ score: number; totalScore: number }> = [];
+          for (let i = 0; i < parent.questionsCount; i++) {
+            const qans = answerMap[
+              `${parent.topicNo}_${i + parent.startNumber}`
+            ] || { score: 0, totalScore: 0 };
+            questions[i] = {
+              score: qans.score,
+              totalScore: qans.totalScore,
+            };
+          }
+          oaTagItem.score = calcSum(questions.map((q) => q.score || 0));
+          oaTagItem.totalScore = calcSum(
+            questions.map((q) => q.totalScore || 0)
+          );
+          const tCont = `得分:${oaTagItem.score},满分:${oaTagItem.totalScore}`;
+          const tContLen = strGbLen(tCont) / 2;
+          oaTagItem.trackItem = {
+            type: 'text',
+            option: {
+              x: area.x + area.w - Math.ceil(tContLen * trackTextFontSize),
+              y: area.y,
+              text: tCont,
+              fontSize: trackTextFontSize,
+            },
+          };
+
+          objectiveAnswerTags[pindex].push(oaTagItem);
+        });
+      });
+    });
+
+    return objectiveAnswerTags;
+  }
+  // objective answer tag ----- end->
+
   return {
     runTask,
     getTrackTask,

+ 2 - 2
src/views/base/track-export/useTask.ts

@@ -115,7 +115,7 @@ export default function useTask() {
           studentId: item.studentId,
           studentName: item.studentName,
           studentCode: item.studentCode,
-          className: item.className,
+          className: item.teachClassName,
           status: TRACK_TASK_DETAIL_STATUS.INIT,
         };
       });
@@ -139,7 +139,7 @@ export default function useTask() {
           studentId: item.studentId,
           studentName: item.studentName,
           studentCode: item.studentCode,
-          className: item.className,
+          className: item.teachClassName,
           status: TRACK_TASK_DETAIL_STATUS.INIT,
         };
       });