|
@@ -42,9 +42,31 @@
|
|
|
:style="minfo.style"
|
|
|
class="mark-info"
|
|
|
>
|
|
|
- <div>
|
|
|
- <p v-for="user in minfo.users" :key="user.userId">
|
|
|
- 评卷员:{{ user.userName }},评分:{{ user.score }}
|
|
|
+ <div v-if="minfo.isFillQuestion">
|
|
|
+ <div
|
|
|
+ v-for="user in minfo.users"
|
|
|
+ :key="user.userId"
|
|
|
+ :style="{ color: user.color }"
|
|
|
+ >
|
|
|
+ <p>{{ user.prename }}:{{ user.userName }},评分:</p>
|
|
|
+ <p>
|
|
|
+ {{
|
|
|
+ user.scores
|
|
|
+ .map((s) => `${s.subNumber}:${s.score}分`)
|
|
|
+ .join(",")
|
|
|
+ }}
|
|
|
+ </p>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div v-else>
|
|
|
+ <p
|
|
|
+ v-for="user in minfo.users"
|
|
|
+ :key="user.userId"
|
|
|
+ :style="{ color: user.color }"
|
|
|
+ >
|
|
|
+ {{ user.prename }}:{{ user.userName }},评分:{{
|
|
|
+ user.score
|
|
|
+ }}
|
|
|
</p>
|
|
|
</div>
|
|
|
<h3>得分:{{ minfo.score }},满分:{{ minfo.maxScore }}</h3>
|
|
@@ -68,7 +90,13 @@
|
|
|
import { reactive, watch } from "vue";
|
|
|
import { store } from "@/store/store";
|
|
|
import MarkDrawTrack from "@/features/mark/MarkDrawTrack.vue";
|
|
|
-import type { SpecialTag, Track, ColorMap, PaperRecogData } from "@/types";
|
|
|
+import type {
|
|
|
+ SpecialTag,
|
|
|
+ Track,
|
|
|
+ ColorMap,
|
|
|
+ PaperRecogData,
|
|
|
+ Question,
|
|
|
+} from "@/types";
|
|
|
import { useTimers } from "@/setups/useTimers";
|
|
|
import { loadImage, addHeaderTrackColorAttr, calcSum } from "@/utils/utils";
|
|
|
import { dragImage } from "@/features/mark/use/draggable";
|
|
@@ -179,9 +207,6 @@ async function processImage() {
|
|
|
|
|
|
maxImageWidth = Math.max(...images.map((i) => i.naturalWidth));
|
|
|
|
|
|
- // 解析各试题答题区域以及评分
|
|
|
- const markDetailList = parseMarkDetailList();
|
|
|
-
|
|
|
const trackLists = (store.currentTask.questionList || [])
|
|
|
// .map((q) => q.trackList)
|
|
|
.map((q) => {
|
|
@@ -193,6 +218,9 @@ async function processImage() {
|
|
|
.flat();
|
|
|
store.setting.doubleTrack = trackLists.some((item) => item.isByMultMark);
|
|
|
|
|
|
+ // 解析各试题答题区域以及评分
|
|
|
+ const markDetailList = parseMarkDetailList();
|
|
|
+
|
|
|
for (const url of urls) {
|
|
|
const indexInSliceUrls = urls.indexOf(url) + 1;
|
|
|
const image = images[indexInSliceUrls - 1];
|
|
@@ -395,51 +423,181 @@ function parseQuestionAreas(questions: QuestionItem[]) {
|
|
|
return combinePictureConfigList;
|
|
|
}
|
|
|
|
|
|
+// 获取属于填空题的试题号
|
|
|
+function getFillLines() {
|
|
|
+ if (!store.currentTask.cardData?.length) return {};
|
|
|
+
|
|
|
+ const questions: Record<number, string[]> = {};
|
|
|
+ store.currentTask.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;
|
|
|
+}
|
|
|
+
|
|
|
// 解析各试题答题区域以及评分
|
|
|
+interface MarkDetailUserItem {
|
|
|
+ userId: string;
|
|
|
+ userName: string;
|
|
|
+ prename: string;
|
|
|
+ color: string;
|
|
|
+ scores: Array<{ subNumber: string; score: number }>;
|
|
|
+ score: number;
|
|
|
+}
|
|
|
+type UserMapType = Record<string, MarkDetailUserItem>;
|
|
|
interface MarkDetailItem {
|
|
|
mainNumber: number;
|
|
|
subNumber: string;
|
|
|
+ isFillQuestion: boolean;
|
|
|
score: number;
|
|
|
maxScore: number;
|
|
|
- users: Array<{
|
|
|
- userId: string;
|
|
|
- userName: string;
|
|
|
- scores: number[];
|
|
|
- score: number;
|
|
|
- }>;
|
|
|
+ users: MarkDetailUserItem[];
|
|
|
area: QuestionArea;
|
|
|
style: Record<string, string>;
|
|
|
}
|
|
|
+
|
|
|
function parseMarkDetailList(): Array<MarkDetailItem[]> {
|
|
|
const dataList: Array<MarkDetailItem[]> = [];
|
|
|
+ const questions = store.currentTask.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}`)
|
|
|
+ );
|
|
|
+ }
|
|
|
|
|
|
- (store.currentTask.questionList || []).forEach((question) => {
|
|
|
- const areas = parseQuestionAreas([question]);
|
|
|
+ // 填空题:合并所有小题为一个区域
|
|
|
+ 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];
|
|
|
- if (!dataList[area.i - 1]) {
|
|
|
- dataList[area.i - 1] = [];
|
|
|
+ const area = { ...areas[0] };
|
|
|
+ const imgIndex = area.i - 1;
|
|
|
+ if (!dataList[imgIndex]) {
|
|
|
+ dataList[imgIndex] = [];
|
|
|
}
|
|
|
|
|
|
- const userMap = {};
|
|
|
+ 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,
|
|
|
+ color: track.color || "red",
|
|
|
+ prename: "",
|
|
|
+ scores: [],
|
|
|
+ score: 0,
|
|
|
+ };
|
|
|
+ }
|
|
|
+ userMap[track.userId].scores.push({
|
|
|
+ score: track.score,
|
|
|
+ subNumber: track.subNumber,
|
|
|
+ });
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ const users = Object.values(userMap).map((user, index) => {
|
|
|
+ const zhs = ["一", "二", "三"];
|
|
|
+ const prename = isDoubleMark ? `${zhs[index] || ""}评` : "评卷员";
|
|
|
+ return {
|
|
|
+ ...user,
|
|
|
+ prename,
|
|
|
+ score: calcSum(user.scores.map((s) => s.score)),
|
|
|
+ };
|
|
|
+ });
|
|
|
+
|
|
|
+ const score = calcSum(groupQuestions.map((item) => item.score || 0));
|
|
|
+ const maxScore = calcSum(groupQuestions.map((item) => item.maxScore));
|
|
|
+
|
|
|
+ dataList[imgIndex].push({
|
|
|
+ mainNumber: groupQuestions[0].mainNumber,
|
|
|
+ subNumber: "",
|
|
|
+ isFillQuestion: true,
|
|
|
+ score,
|
|
|
+ maxScore,
|
|
|
+ users,
|
|
|
+ area,
|
|
|
+ style: {
|
|
|
+ position: "absolute",
|
|
|
+ left: (100 * area.x).toFixed(4) + "%",
|
|
|
+ top: (100 * area.y).toFixed(4) + "%",
|
|
|
+ width: (100 * area.w).toFixed(4) + "%",
|
|
|
+ fontSize: "14px",
|
|
|
+ lineHeight: 1,
|
|
|
+ zIndex: 9,
|
|
|
+ },
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ // 其他试题
|
|
|
+ otherQuestions.forEach((question) => {
|
|
|
+ const areas = parseQuestionAreas([question]);
|
|
|
+ const area = { ...areas[0] };
|
|
|
+ const imgIndex = area.i - 1;
|
|
|
+ if (!dataList[imgIndex]) {
|
|
|
+ dataList[imgIndex] = [];
|
|
|
+ }
|
|
|
+
|
|
|
+ const userMap: UserMapType = {};
|
|
|
question.trackList.forEach((track) => {
|
|
|
if (!userMap[track.userId]) {
|
|
|
userMap[track.userId] = {
|
|
|
userId: track.userId,
|
|
|
userName: track.userName,
|
|
|
+ color: track.color || "red",
|
|
|
+ prename: "",
|
|
|
scores: [],
|
|
|
+ score: 0,
|
|
|
};
|
|
|
}
|
|
|
- userMap[track.userId].scores.push(track.score);
|
|
|
+ userMap[track.userId].scores.push({
|
|
|
+ score: track.score,
|
|
|
+ subNumber: track.subNumber,
|
|
|
+ });
|
|
|
});
|
|
|
|
|
|
- const users = Object.values(userMap).map((user) => {
|
|
|
- return { ...user, score: calcSum(user.scores) };
|
|
|
+ const isDoubleMark = Object.keys(userMap).length > 1;
|
|
|
+ const users = Object.values(userMap).map((user, index) => {
|
|
|
+ const zhs = ["一", "二", "三"];
|
|
|
+ const prename = isDoubleMark ? `${zhs[index] || ""}评` : "评卷员";
|
|
|
+ return {
|
|
|
+ ...user,
|
|
|
+ prename,
|
|
|
+ score: calcSum(user.scores.map((s) => s.score)),
|
|
|
+ };
|
|
|
});
|
|
|
|
|
|
- dataList[area.i - 1].push({
|
|
|
+ dataList[imgIndex].push({
|
|
|
mainNumber: question.mainNumber,
|
|
|
subNumber: question.subNumber,
|
|
|
+ isFillQuestion: false,
|
|
|
score: question.score,
|
|
|
maxScore: question.maxScore,
|
|
|
users,
|
|
@@ -449,7 +607,6 @@ function parseMarkDetailList(): Array<MarkDetailItem[]> {
|
|
|
left: (100 * area.x).toFixed(4) + "%",
|
|
|
top: (100 * area.y).toFixed(4) + "%",
|
|
|
width: (100 * area.w).toFixed(4) + "%",
|
|
|
- color: "#f53f3f",
|
|
|
fontSize: "14px",
|
|
|
lineHeight: 1,
|
|
|
zIndex: 9,
|