|
@@ -5,7 +5,7 @@ import {
|
|
|
studentObjectiveConfirmData,
|
|
|
getSingleStudentCardData,
|
|
|
} from '@/api/task';
|
|
|
-import { Task, Track, SpecialTag } from '@/api/types/task';
|
|
|
+import { Task, Track, SpecialTag, Question } from '@/api/types/task';
|
|
|
import { TrackConfigType } from '@/store/modules/app/types';
|
|
|
import { PictureTypeEnum } from '@/constants/enumerate';
|
|
|
import { calcSum, maxNum, strGbLen } from '@/utils/utils';
|
|
@@ -21,6 +21,13 @@ interface TrackItemType {
|
|
|
drawTrackList: DrawTrackItem[];
|
|
|
}
|
|
|
|
|
|
+type ElementType =
|
|
|
+ | 'FILL_QUESTION'
|
|
|
+ | 'FILL_LINE'
|
|
|
+ | 'EXPLAIN'
|
|
|
+ | 'COMPOSITION'
|
|
|
+ | 'TOPIC_HEAD'
|
|
|
+ | 'CARD_HEAD';
|
|
|
interface CardDataItem {
|
|
|
exchange: {
|
|
|
answer_area: Array<{
|
|
@@ -29,6 +36,14 @@ interface CardDataItem {
|
|
|
area: [number, number, number, number];
|
|
|
}>;
|
|
|
};
|
|
|
+ columns: Array<{
|
|
|
+ elements: Array<{
|
|
|
+ type: ElementType;
|
|
|
+ topicNo: number;
|
|
|
+ startNumber: number;
|
|
|
+ questionsCount: number;
|
|
|
+ }>;
|
|
|
+ }>;
|
|
|
}
|
|
|
|
|
|
interface CardContentType {
|
|
@@ -50,7 +65,11 @@ interface QuestionArea {
|
|
|
|
|
|
type UserMapType = Record<
|
|
|
string,
|
|
|
- { userId: string; userName: string; scores: number[] }
|
|
|
+ {
|
|
|
+ userId: string;
|
|
|
+ userName: string;
|
|
|
+ scores: Array<{ subNumber: string; score: number }>;
|
|
|
+ }
|
|
|
>;
|
|
|
|
|
|
interface ImageItem {
|
|
@@ -419,8 +438,96 @@ export default function useDraw(winId: number) {
|
|
|
// 解析各试题答题区域以及评分
|
|
|
function parseMarkDetailList(images: ImageItem[]): Array<DrawTrackItem[]> {
|
|
|
const dataList: Array<DrawTrackItem[]> = [];
|
|
|
+ const questions = rawTask.questionList || [];
|
|
|
+
|
|
|
+ const fillQues = getFillLines();
|
|
|
+ let fillQuestions = [] as Question[];
|
|
|
+ let otherQuestions = questions;
|
|
|
+ if (Object.keys(fillQues).length) {
|
|
|
+ const fillQNos = Object.values(fillQues).flat();
|
|
|
+ fillQuestions = questions.filter((q) =>
|
|
|
+ fillQNos.includes(`${q.mainNumber}_${q.subNumber}`)
|
|
|
+ );
|
|
|
+ otherQuestions = questions.filter(
|
|
|
+ (q) => !fillQNos.includes(`${q.mainNumber}_${q.subNumber}`)
|
|
|
+ );
|
|
|
+ }
|
|
|
+ // 填空题:合并所有小题为一个区域
|
|
|
+ Object.values(fillQues).forEach((qnos) => {
|
|
|
+ const groupQuestions = fillQuestions.filter((q) =>
|
|
|
+ qnos.includes(`${q.mainNumber}_${q.subNumber}`)
|
|
|
+ );
|
|
|
+ const areas = parseQuestionAreas(groupQuestions);
|
|
|
+ if (!areas.length) return;
|
|
|
+ const area = { ...areas[0] };
|
|
|
+ const imgIndex = area.i - 1;
|
|
|
+ if (!dataList[imgIndex]) {
|
|
|
+ dataList[imgIndex] = [];
|
|
|
+ }
|
|
|
+
|
|
|
+ const img = images[imgIndex] as ImageItem;
|
|
|
+ area.x *= img.width;
|
|
|
+ area.y *= img.height;
|
|
|
+ area.w *= img.width;
|
|
|
+
|
|
|
+ const dataArr = dataList[imgIndex];
|
|
|
+ const userMap: UserMapType = {};
|
|
|
+ const isDoubleMark = !groupQuestions.some((question) => {
|
|
|
+ const userIds = question.trackList.map((track) => track.userId);
|
|
|
+ const uids = new Set(userIds);
|
|
|
+ return uids.size === 1;
|
|
|
+ });
|
|
|
+ groupQuestions.forEach((question) => {
|
|
|
+ question.trackList.forEach((track) => {
|
|
|
+ if (!userMap[track.userId]) {
|
|
|
+ userMap[track.userId] = {
|
|
|
+ userId: track.userId,
|
|
|
+ userName: track.userName,
|
|
|
+ scores: [],
|
|
|
+ };
|
|
|
+ }
|
|
|
+ userMap[track.userId].scores.push({
|
|
|
+ score: track.score,
|
|
|
+ subNumber: track.subNumber,
|
|
|
+ });
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ Object.values(userMap).forEach((user, index) => {
|
|
|
+ const userScore = user.scores
|
|
|
+ .map((item) => `${item.subNumber}:${item.score}分`)
|
|
|
+ .join(',');
|
|
|
+
|
|
|
+ const zhs = ['一', '二', '三'];
|
|
|
+ const prename = isDoubleMark ? `${zhs[index] || ''}评` : '评卷员';
|
|
|
+ const content = `${prename}:${user.userName},评分:${userScore}`;
|
|
|
+ dataArr.push({
|
|
|
+ type: 'text',
|
|
|
+ option: {
|
|
|
+ x: area.x,
|
|
|
+ y: area.y + index * 20,
|
|
|
+ text: content,
|
|
|
+ },
|
|
|
+ });
|
|
|
+ });
|
|
|
|
|
|
- (rawTask.questionList || []).forEach((question) => {
|
|
|
+ const score = calcSum(groupQuestions.map((item) => item.score || 0));
|
|
|
+ const maxScore = calcSum(groupQuestions.map((item) => item.maxScore));
|
|
|
+ const tCont = `得分:${score},满分:${maxScore}`;
|
|
|
+ const tContLen = strGbLen(tCont) / 2;
|
|
|
+ dataArr.push({
|
|
|
+ type: 'text',
|
|
|
+ option: {
|
|
|
+ x: area.x + area.w - Math.ceil(tContLen * 20),
|
|
|
+ y: area.y,
|
|
|
+ text: tCont,
|
|
|
+ fontSize: 20,
|
|
|
+ },
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ // 其他试题
|
|
|
+ otherQuestions.forEach((question) => {
|
|
|
const areas = parseQuestionAreas([question]);
|
|
|
if (!areas.length) return;
|
|
|
const area = { ...areas[0] };
|
|
@@ -444,11 +551,14 @@ export default function useDraw(winId: number) {
|
|
|
scores: [],
|
|
|
};
|
|
|
}
|
|
|
- userMap[track.userId].scores.push(track.score);
|
|
|
+ userMap[track.userId].scores.push({
|
|
|
+ score: track.score,
|
|
|
+ subNumber: track.subNumber,
|
|
|
+ });
|
|
|
});
|
|
|
|
|
|
Object.values(userMap).forEach((user, index) => {
|
|
|
- const userScore = calcSum(user.scores);
|
|
|
+ const userScore = calcSum(user.scores.map((item) => item.score));
|
|
|
const content = `评卷员:${user.userName},评分:${userScore}`;
|
|
|
dataArr.push({
|
|
|
type: 'text',
|
|
@@ -475,6 +585,27 @@ export default function useDraw(winId: number) {
|
|
|
return dataList;
|
|
|
}
|
|
|
|
|
|
+ // 获取属于填空题的试题号
|
|
|
+ function getFillLines() {
|
|
|
+ const questions: Record<number, string[]> = {};
|
|
|
+ cardData.forEach((page) => {
|
|
|
+ page.columns.forEach((column) => {
|
|
|
+ column.elements.forEach((element) => {
|
|
|
+ if (element.type !== 'FILL_LINE') return;
|
|
|
+
|
|
|
+ if (!questions[element.topicNo]) questions[element.topicNo] = [];
|
|
|
+
|
|
|
+ for (let i = 0; i < element.questionsCount; i++) {
|
|
|
+ questions[element.topicNo].push(
|
|
|
+ `${element.topicNo}_${element.startNumber + i}`
|
|
|
+ );
|
|
|
+ }
|
|
|
+ });
|
|
|
+ });
|
|
|
+ });
|
|
|
+ return questions;
|
|
|
+ }
|
|
|
+
|
|
|
function parseQuestionAreas(questions: QuestionItem[]) {
|
|
|
if (!questions.length || !cardData?.length) return [];
|
|
|
|