|
|
@@ -9,7 +9,7 @@
|
|
|
<div
|
|
|
v-for="({ content, mark, multilingual, paragraph_list }, j) in item"
|
|
|
:key="mark"
|
|
|
- :class="['item-wrapper', `item-${mark}`, computedAnswerClass(mark), { isMobile: isMobile }]"
|
|
|
+ :class="['item-wrapper', `item-${mark}`, computedAnswerClass(mark, i, j), { isMobile: isMobile }]"
|
|
|
:style="{
|
|
|
cursor: disabled ? 'default' : 'pointer',
|
|
|
flex: isMobile ? '0 1 auto' : '',
|
|
|
@@ -51,6 +51,7 @@
|
|
|
|
|
|
<script>
|
|
|
import { getMatchingData, svgNS } from '@/views/book/courseware/data/matching';
|
|
|
+import { arraysIntersect } from '@/utils/validate';
|
|
|
|
|
|
import PreviewMixin from '../common/PreviewMixin';
|
|
|
|
|
|
@@ -89,34 +90,26 @@ export default {
|
|
|
let arr = [];
|
|
|
|
|
|
list.forEach((item) => {
|
|
|
- item.forEach(({ mark, preMark, nextMark }, j) => {
|
|
|
- if (preMark.length === 0 && nextMark.length === 0) return;
|
|
|
- if (nextMark.length > 0 && j === 0) {
|
|
|
- nextMark.forEach((m) => {
|
|
|
- arr.push([{ mark }, { mark: m }]);
|
|
|
- });
|
|
|
+ let markArr = [];
|
|
|
+ item.forEach(({ mark, nextMark }, j) => {
|
|
|
+ if (j === 0) {
|
|
|
+ markArr.push(mark);
|
|
|
+ markArr.push([...nextMark]);
|
|
|
+ } else if (item.length === 3 && j === 1) {
|
|
|
+ markArr.push([...nextMark]);
|
|
|
}
|
|
|
});
|
|
|
+ arr.push(markArr);
|
|
|
});
|
|
|
-
|
|
|
+ // 答案数组为 第一个值为固定字符串,后面为连接的值数组,如:['A', ['B', 'C'], ['1', '2']],根据此结构来判断对错、绘制连线
|
|
|
this.answer.answer_list = arr;
|
|
|
},
|
|
|
deep: true,
|
|
|
},
|
|
|
- isJudgingRightWrong(cur) {
|
|
|
- if (cur) {
|
|
|
- this.$nextTick(() => {
|
|
|
- this.clearLine();
|
|
|
- this.circulateAnswerList();
|
|
|
- });
|
|
|
- } else {
|
|
|
- // this.clearLine();
|
|
|
- }
|
|
|
- },
|
|
|
isShowRightAnswer(cur) {
|
|
|
if (cur) {
|
|
|
this.$nextTick(() => {
|
|
|
- this.circulateAnswerList(true);
|
|
|
+ this.circulateAnswerList();
|
|
|
});
|
|
|
}
|
|
|
},
|
|
|
@@ -266,26 +259,38 @@ export default {
|
|
|
this.createLine(mark);
|
|
|
},
|
|
|
|
|
|
- // 循环答案列表
|
|
|
- circulateAnswerList(isShowRightAnswer = false) {
|
|
|
- let answer_list = isShowRightAnswer ? this.data.answer.answer_list : this.answer.answer_list;
|
|
|
- answer_list.forEach((item) => {
|
|
|
- item.forEach((_m, j) => {
|
|
|
- let mark = isShowRightAnswer ? _m.mark : _m;
|
|
|
- if (mark.length <= 0 || j >= item.length - 1) return;
|
|
|
-
|
|
|
- let cur = { i: -1, j: -1 }; // 当前连线点
|
|
|
- this.answerList.findIndex((item, i) => {
|
|
|
- return item.some((li, j) => {
|
|
|
- if (li.mark === mark) {
|
|
|
- cur = { i, j };
|
|
|
+ /**
|
|
|
+ * @description 循环答案列表
|
|
|
+ */
|
|
|
+ circulateAnswerList() {
|
|
|
+ this.data.answer.answer_list.forEach((item, index) => {
|
|
|
+ let preMark = ''; // 上一个连线点标识
|
|
|
+ item.forEach(({ mark }, j) => {
|
|
|
+ if (j === 0) {
|
|
|
+ preMark = mark;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (mark.length <= 0) return;
|
|
|
+ if (j === 2) {
|
|
|
+ preMark = this.data.option_list[index][j - 1].mark;
|
|
|
+ }
|
|
|
+ let cur = { i: -1, j: -1, mark: '' }; // 当前连线点
|
|
|
+
|
|
|
+ // 根据 preMark 查找当前连线点的位置
|
|
|
+ this.data.option_list.find((list, i) => {
|
|
|
+ return list.find((li, idx) => {
|
|
|
+ if (li.mark === preMark) {
|
|
|
+ cur = { i, j: idx };
|
|
|
return true;
|
|
|
}
|
|
|
});
|
|
|
});
|
|
|
- this.curConnectionPoint = { i: cur.i, j: cur.j, mark };
|
|
|
- const nextMark = isShowRightAnswer ? item[j + 1].mark : item[j + 1].mark;
|
|
|
- this.createLine(nextMark, false, isShowRightAnswer);
|
|
|
+
|
|
|
+ // 循环 mark 数组,创建连接线
|
|
|
+ mark.forEach((m) => {
|
|
|
+ this.curConnectionPoint = { i: cur.i, j: cur.j, mark: preMark };
|
|
|
+ this.createLine(m, false, true);
|
|
|
+ });
|
|
|
});
|
|
|
});
|
|
|
},
|
|
|
@@ -432,42 +437,55 @@ export default {
|
|
|
/**
|
|
|
* 计算答题对错选项class
|
|
|
* @param {string} mark 选项标识
|
|
|
+ * @param {number} i 选项列表索引
|
|
|
+ * @param {number} j 选项索引
|
|
|
+ * @returns {string} 返回 class 名称
|
|
|
*/
|
|
|
- computedAnswerClass(mark) {
|
|
|
+ computedAnswerClass(mark, i, j) {
|
|
|
if (!this.isJudgingRightWrong) return '';
|
|
|
- let answer = this.data.answer.answer_list.filter((item) => {
|
|
|
- return item.some((li) => li.mark === mark);
|
|
|
- });
|
|
|
- let userAnswer = this.answer.answer_list.filter((item) => {
|
|
|
- return item.some((li) => li.mark === mark);
|
|
|
- });
|
|
|
+ if (j === 0) {
|
|
|
+ return this.judgeFirstAnswerRightWrong(i);
|
|
|
+ }
|
|
|
+ let answer = this.data.answer.answer_list.find((item) => {
|
|
|
+ return item.some((li) => Array.isArray(li.mark) && li.mark.includes(mark));
|
|
|
+ }); // 正确答案列
|
|
|
+
|
|
|
+ let userAnswer = this.answer.answer_list.find((item) => {
|
|
|
+ return item.some((li) => Array.isArray(li) && li.includes(mark));
|
|
|
+ }); // 选项对应的用户答案列
|
|
|
+
|
|
|
+ if (answer === undefined || userAnswer === undefined) return 'wrong';
|
|
|
if (answer.length === 0 && userAnswer.length === 0) return '';
|
|
|
if (answer.length === 0 || userAnswer.length === 0) return 'wrong';
|
|
|
|
|
|
let isRight = true;
|
|
|
- userAnswer.forEach((item) => {
|
|
|
- let len = item.length;
|
|
|
- let index = item.findIndex((li) => li.mark === mark);
|
|
|
- // 根据 mark 查找答案列表中对应的选项
|
|
|
- let answerList = answer.filter((item) => {
|
|
|
- return item.findIndex((li) => li.mark === mark) === index;
|
|
|
- });
|
|
|
|
|
|
- // 循环答案列表和用户答案,判断是否完全相等
|
|
|
- for (let i = 0; i < answerList.length; i++) {
|
|
|
- let isAllRight = true;
|
|
|
- for (let j = 0; j < len; j++) {
|
|
|
- if (j === index) continue;
|
|
|
- let isEqual = item[j].mark === answerList[i][j].mark;
|
|
|
- if (!isEqual) {
|
|
|
- isAllRight = false;
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- isRight = isAllRight;
|
|
|
- if (isRight) break;
|
|
|
- }
|
|
|
- });
|
|
|
+ if (j === 1) {
|
|
|
+ // 判断第二行答案对错,answer[0].mark 和 userAnswer[0] 是否相等
|
|
|
+ isRight = answer[0].mark === userAnswer[0];
|
|
|
+ } else if (j === 2) {
|
|
|
+ // 判断第三行答案对错,answer[1].mark 和 userAnswer[1] 是否相交
|
|
|
+ isRight = arraysIntersect(answer[1].mark, userAnswer[1]);
|
|
|
+ }
|
|
|
+
|
|
|
+ return isRight ? 'right' : 'wrong';
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 判断第一列答案对错,是否有个一个选项连接正确
|
|
|
+ * @param {number} i 选项列表索引
|
|
|
+ */
|
|
|
+ judgeFirstAnswerRightWrong(i) {
|
|
|
+ let answer = this.data.answer.answer_list[i]; // 正确答案列
|
|
|
+ let userAnswer = this.answer.answer_list[i]; // 选项对应的用户答案列
|
|
|
+ if (answer === undefined || userAnswer === undefined) return 'wrong';
|
|
|
+ if (answer.length === 0 && userAnswer.length === 0) return '';
|
|
|
+ if (answer.length === 0 || userAnswer.length === 0) return 'wrong';
|
|
|
+ let isRight = true;
|
|
|
+
|
|
|
+ // 判断 answer[1].mark 和 userAnswer[1] 是否相交
|
|
|
+ const answerSet = new Set(answer[1].mark);
|
|
|
+ isRight = userAnswer[1].some((x) => answerSet.has(x));
|
|
|
+
|
|
|
return isRight ? 'right' : 'wrong';
|
|
|
},
|
|
|
},
|
|
|
@@ -492,6 +510,7 @@ export default {
|
|
|
display: flex;
|
|
|
column-gap: 8px;
|
|
|
align-items: center;
|
|
|
+ padding: 1px;
|
|
|
|
|
|
.item-wrapper {
|
|
|
position: relative;
|
|
|
@@ -503,7 +522,7 @@ export default {
|
|
|
min-height: 48px;
|
|
|
padding: 12px 24px;
|
|
|
background-color: $content-color;
|
|
|
- border-radius: 40px;
|
|
|
+ border-radius: 4px;
|
|
|
|
|
|
&:not(:last-child, .isMobile) {
|
|
|
margin-right: 52px;
|