<template>
|
<div class="drag-box">
|
<div
|
v-for="(item, index) in drageQuestion"
|
:key="item.id"
|
@mousemove="mousemove"
|
@mouseup="mouseup"
|
:num="index"
|
class="question-box"
|
>
|
<!-- 题干 -->
|
<div class="stem">
|
<span v-for="(ditem, dindex) in item.stem" :key="dindex">
|
<span v-if="typeof ditem == 'string'">
|
{{ ditem }}
|
</span>
|
<span class="space" v-else>{{ item.userAnswer[ditem.num].txt }}</span>
|
</span>
|
</div>
|
|
<!-- 选项 -->
|
<ul class="option-box">
|
<li v-for="(citem, cindex) in item.option" :key="cindex">
|
<span class="drag-option" @mousedown="mousedown" v-show="item.userAnswer.findIndex(eitem => eitem.value == citem.value) == -1"
|
>{{ citem.value }}、{{ citem.txt }}</span
|
>
|
</li>
|
</ul>
|
<!-- 提交后解析 -->
|
<div class="analysis" v-if="item.isComplete">
|
<el-collapse
|
v-model="item.isUnfold"
|
@change="handleChange(item)"
|
accordion
|
v-if="item.questionType != 'shortAnswer'"
|
>
|
<el-collapse-item :name="item.id" class="objective">
|
<template #title>
|
<div class="headerBox">
|
<div class="headerConent">
|
<p class="correct" :title="arrayToString(item.answer)">
|
<span>正确答案:</span>
|
<span
|
v-html="arrayToString(item.answer)"
|
class="correctBox"
|
></span>
|
</p>
|
<p
|
:class="
|
item.isRight
|
? 'correct textOverFlow'
|
: 'error textOverFlow'
|
"
|
:title="arrayToString(item.userAnswer)"
|
style="margin-left: 20px"
|
>
|
<span>您的答案:</span>
|
<span
|
class="errorBox"
|
v-if="item.userAnswer.length"
|
>
|
<span v-for="(answerItem,answerIdnex) in item.userAnswer" :key="answerIdnex">{{answerItem.value}}<span v-if="answerIdnex !== item.userAnswer.length - 1 && answerItem.value">,</span></span>
|
|
</span
|
>
|
</p>
|
</div>
|
<p class="difficulty" v-if="item.difficulty">
|
<span style="color: #333">难度等级:</span>
|
<el-rate
|
v-model="item.difficulty"
|
:max="3"
|
size="large"
|
disabled
|
disabled-void-color="#949494"
|
/>
|
</p>
|
<!-- 正确错误图标 -->
|
<span class="mr-10 judge-icon">
|
<svg
|
v-if="item.isRight"
|
t="1716986419862"
|
class="icon"
|
viewBox="0 0 1820 1024"
|
version="1.1"
|
xmlns="http://www.w3.org/2000/svg"
|
p-id="18767"
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
width="40"
|
height="20"
|
>
|
<path
|
d="M1439.374222 216.007111s-169.472 56.490667-367.179852 282.443852C888.604444 703.222519 846.241185 787.949037 775.632593 900.93037 768.568889 893.866667 662.651259 689.095111 380.207407 540.814222l148.290371-141.226666s134.162963 91.790222 225.953185 261.262222c0 0 233.016889-360.116148 684.923259-536.642371v91.799704z m0 0"
|
fill="#1AFA29"
|
p-id="18768"
|
></path>
|
</svg>
|
<svg
|
v-if="item.isRight == false"
|
t="1716987085767"
|
class="icon"
|
viewBox="0 0 1024 1024"
|
version="1.1"
|
xmlns="http://www.w3.org/2000/svg"
|
p-id="25745"
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
width="20"
|
height="20"
|
>
|
<path
|
d="M116.579135 38.64349531L38.703935 103.74399781c138.82075969 102.96027281 268.24660875 221.31426938 381.68489719 339.96758156C246.29374906 618.40145938 109.95003031 790.19602344 38.10817906 859.25288281l148.35573469 123.62658094c52.61360812-108.17625656 167.23381594-272.86683656 320.56281844-445.01635875 153.50744156 173.21056312 268.36844625 338.43166313 321.38977781 447.49243969 0 0 144.5682225-152.96636906 157.47435281-129.29729625-55.80632344-62.49011156-191.37776625-244.16501625-374.17990593-430.27403438 104.68422375-107.1132975 222.15274031-213.10127719 347.60304468-306.24740437L925.17746562 56.03842156C782.85412063 126.51895625 647.69328031 231.09093594 526.07845437 342.39755 403.34886594 226.82662719 264.46095125 116.16373719 116.579135 38.64349531L116.579135 38.64349531zM116.579135 38.64349531"
|
fill="#d81e06"
|
p-id="25746"
|
></path>
|
</svg>
|
</span>
|
|
<div class="headerConent sitgBox">
|
<p v-if="!item.isUnfold">
|
<span class="analysisColor">展开解析</span><el-image />
|
</p>
|
<p v-else>
|
<span class="analysisColor">收起解析</span><el-image />
|
</p>
|
</div>
|
</div>
|
</template>
|
<!-- 解析 -->
|
<div v-if="item.analysisCon" v-html="item.analysisCon"></div>
|
<div v-else>暂无数据</div>
|
</el-collapse-item>
|
<!-- 主观题 -->
|
</el-collapse>
|
</div>
|
</div>
|
<div class="drag-bottom-btn">
|
<el-button @click="saveData">保存</el-button>
|
<el-button @click="submitData">提交</el-button>
|
<el-button @click="redio">重做</el-button>
|
<el-button @click="seeAnswer">查看答案</el-button>
|
</div>
|
</div>
|
</template>
|
|
<script>
|
export default {
|
name: "drag",
|
props: {
|
question: {
|
type: Array,
|
default: [],
|
},
|
page: {
|
type: Number,
|
},
|
},
|
watch: {
|
question: {
|
handler(newValue, oldValue) {
|
console.log("监听传值", newValue);
|
let oldAnswer = localStorage.getItem(
|
this.config.activeBook.name + "-drag-" + this.page
|
);
|
if (oldAnswer) {
|
oldAnswer = JSON.parse(oldAnswer);
|
for (let index = 0; index < newValue.length; index++) {
|
// 旧答案赋值
|
const item = newValue[index];
|
const oldItem = oldAnswer.find((citem) => citem.id == item.id);
|
item.userAnswer = oldItem.userAnswer;
|
// 隐藏旧答案里的选项
|
// for (let cindex = 0; cindex < item.option.length; cindex++) {
|
// const citem = item.option[cindex];
|
// if(item.userAnswer.findIndex(ditem => ditem.value == citem.value) > -1) {
|
// citem.isShow = false
|
// }
|
// }
|
}
|
}
|
this.drageQuestion = newValue;
|
},
|
immediate: true,
|
},
|
},
|
data() {
|
return {
|
questionIndex: null,
|
drageQuestion: [],
|
moveDom: null,
|
parentDom: null,
|
parentX: null, // 父盒子在页面的位置
|
parentY: null,
|
maxX: null,
|
maxY: null,
|
spaceList: [],
|
};
|
},
|
mounted() {
|
console.log("传值", this.question);
|
},
|
methods: {
|
// 1.选项拖拽
|
// 2.限制拖拽移动只能在题范围内
|
// 3.限制鼠标松开要在空格的范围内
|
mousedown(e) {
|
e.preventDefault();
|
console.log("鼠标按下", e);
|
this.moveDom = e.toElement;
|
this.parentDom = this.getParentWithClass(e.toElement, "question-box");
|
this.questionIndex = this.parentDom.getAttribute("num");
|
this.getSpaceInfo(this.parentDom);
|
const parentInfo = this.parentDom.getBoundingClientRect();
|
this.parentX = parentInfo.x;
|
this.parentY = parentInfo.y;
|
this.maxX = parentInfo.x + this.parentDom.clientWidth;
|
this.maxY = parentInfo.y + this.parentDom.clientHeight;
|
console.log("父盒子", parentInfo);
|
},
|
// 鼠标移动
|
mousemove(e) {
|
if (!this.moveDom) return false;
|
this.moveDom.style.position = "absolute";
|
// 限制在此题范围内拖动
|
if (e.x <= this.maxX && e.y < this.maxY) {
|
const moveX = e.x - this.parentX;
|
const moveY = e.y - this.parentY;
|
this.moveDom.style.left = moveX + "px";
|
this.moveDom.style.top = moveY + "px";
|
// 如果移动到空格范围内,将答案填入空格
|
if (this.spaceList.length) {
|
for (let index = 0; index < this.spaceList.length; index++) {
|
const item = this.spaceList[index];
|
if (
|
e.x >= item.minX &&
|
e.x <= item.maxX &&
|
e.y >= item.minY &&
|
e.y <= item.maxY
|
) {
|
this.$set(
|
this.drageQuestion[this.questionIndex].userAnswer,
|
index,
|
{
|
value:this.moveDom.textContent.charAt(0),
|
txt:this.moveDom.textContent.slice(2)
|
}
|
);
|
this.moveDom.style.display = "none";
|
}
|
}
|
}
|
}
|
},
|
// 鼠标抬起
|
mouseup(e) {
|
if (this.moveDom) {
|
this.moveDom = null;
|
}
|
},
|
// 获取题目空格坐标
|
getSpaceInfo(parentDom) {
|
let arr = [];
|
const list = parentDom.querySelectorAll(".space");
|
for (let index = 0; index < list.length; index++) {
|
const itemInfo = list[index].getBoundingClientRect();
|
arr.push({
|
minX: itemInfo.x,
|
maxX: itemInfo.x + itemInfo.width,
|
minY: itemInfo.y,
|
maxY: itemInfo.y + itemInfo.height,
|
});
|
}
|
this.spaceList = arr;
|
console.log("空格范围", arr);
|
},
|
// 获取父元素
|
getParentWithClass(element, className) {
|
while (element.parentElement) {
|
element = element.parentElement;
|
if (element.classList.contains(className)) {
|
return element;
|
}
|
}
|
},
|
// 保存答案
|
saveData(e) {
|
let answerArr = [];
|
for (let index = 0; index < this.drageQuestion.length; index++) {
|
const item = this.drageQuestion[index];
|
answerArr.push({
|
id: item.id,
|
userAnswer: item.userAnswer,
|
});
|
}
|
localStorage.setItem(
|
this.config.activeBook.name + "-drag-" + this.page,
|
JSON.stringify(answerArr)
|
);
|
},
|
// 提交
|
submitData() {
|
let arr = [];
|
const data = this.drageQuestion;
|
for (let index = 0; index < data.length; index++) {
|
const item = data[index];
|
for (let cindex = 0; cindex < item.userAnswer.length; cindex++) {
|
let citem = item.userAnswer[cindex];
|
arr[cindex] = citem.value
|
}
|
item.isRight = arr == item.answer
|
item.isComplete = true
|
}
|
|
console.log(arr,this.drageQuestion[0]);
|
},
|
redio() {
|
localStorage.removeItem(
|
this.config.activeBook.name + "-drag-" + this.page
|
);
|
let arr = []
|
// const data = []
|
for (let index = 0; index < this.drageQuestion.length; index++) {
|
const item = this.drageQuestion[index];
|
item.isComplete = false
|
for (let cindex = 0; cindex < item.option.length; cindex++) {
|
const citem = item.option[cindex];
|
arr.push(
|
{
|
txt:'',
|
value:''
|
}
|
)
|
}
|
item.userAnswer = arr
|
}
|
console.log(this.drageQuestion);
|
const optionList = (
|
this.container ? this.container : document
|
).querySelectorAll(".drag-option");
|
for (let index = 0; index < optionList.length; index++) {
|
const item = optionList[index];
|
item.style.position = null
|
item.style.top = null
|
item.style.left = null
|
}
|
},
|
seeAnswer() {
|
for (let index = 0; index < this.drageQuestion.length; index++) {
|
const item = this.drageQuestion[index];
|
item.isComplete = true;
|
}
|
},
|
// 数组转为字符串方法
|
arrayToString(data) {
|
// 检查是否为数组
|
if (Array.isArray(data)) {
|
// 使用 join 方法将数组转换为字符串,默认使用逗号分隔
|
return data.join(",").replace(/<[^>]*>/g, "");
|
} else {
|
// 如果不是数组,直接返回原始值
|
return data.replace(/<[^>]*>/g, "");
|
}
|
},
|
isHaveAnswer(data) {
|
if (typeof data == "string") {
|
data = data
|
.replace(/<[^>]*>/g, "")
|
.replace(/ /g, "")
|
.trim();
|
if (data.length) {
|
return true;
|
} else {
|
return false;
|
}
|
} else {
|
const answer = data.find((item) => item.length > 0);
|
if (answer) {
|
return true;
|
} else {
|
return false;
|
}
|
}
|
},
|
},
|
};
|
</script>
|
|
<style lang="less" scoped>
|
p {
|
text-indent: 0 !important;
|
}
|
.drag-box {
|
position: relative;
|
}
|
.space {
|
display: inline-block;
|
text-align: center;
|
min-width: 60px !important;
|
min-height: 15px !important;
|
}
|
.option-box {
|
display: flex;
|
justify-content: space-evenly;
|
}
|
.drag-option {
|
cursor: pointer;
|
}
|
.stem {
|
line-height: 2em;
|
}
|
.drag-bottom-btn {
|
width: 100%;
|
display: flex;
|
flex-wrap: wrap;
|
justify-content: center;
|
.el-button {
|
height: 30px;
|
width: 78px;
|
padding: 4px 10px;
|
}
|
}
|
.analysis {
|
margin: 20px 0;
|
width: 94%;
|
// margin-left: 12px;
|
}
|
.judge-icon {
|
display: flex;
|
align-items: center;
|
}
|
.el-collapse {
|
width: 100%;
|
}
|
/** 解析 */
|
.objective {
|
/deep/ .el-collapse-item__header {
|
min-height: 48px;
|
height: min-content;
|
padding: 0 20px;
|
font-size: 16px;
|
background-color: #f4f4f4;
|
.headerBox {
|
width: 100%;
|
height: 100%;
|
display: flex;
|
justify-content: space-between;
|
align-items: center;
|
flex-wrap: wrap;
|
.headerConent {
|
height: 100%;
|
display: flex;
|
align-items: center;
|
flex-wrap: wrap;
|
p {
|
margin-bottom: 0;
|
}
|
.el-image {
|
width: 9px;
|
height: 9px;
|
}
|
.correct {
|
color: #1fbc1f;
|
width: 180px;
|
text-align: left;
|
display: flex;
|
span:nth-child(1) {
|
display: inline-block;
|
text-indent: 0;
|
width: 82px;
|
}
|
}
|
.correctBox {
|
width: 100px;
|
height: min-content;
|
word-break: break-all;
|
text-overflow: ellipsis;
|
display: -webkit-box;
|
-webkit-box-orient: vertical;
|
-webkit-line-clamp: 1; /* 这里是超出几行省略 */
|
overflow: hidden;
|
}
|
.error {
|
display: flex;
|
text-align: left;
|
width: 170px;
|
color: #ee1818;
|
span {
|
height: min-content;
|
width: 100px;
|
}
|
.errorBox {
|
width: 100px;
|
// height: 48px;
|
overflow: hidden;
|
text-overflow: ellipsis;
|
white-space: nowrap;
|
::v-deep {
|
img {
|
max-height: 48px;
|
}
|
}
|
}
|
}
|
}
|
}
|
|
.checkAnalysis {
|
cursor: pointer;
|
height: 100%;
|
display: flex;
|
align-items: center;
|
}
|
}
|
}
|
/deep/ .el-collapse-item__header:focus:not(:hover) {
|
color: #333;
|
}
|
/deep/ .el-collapse-item__content {
|
width: 93%;
|
padding: 0 20px;
|
background-color: #f4f4f4;
|
font-size: 16px;
|
color: #333;
|
}
|
/deep/ .el-collapse-item__arrow {
|
display: none;
|
}
|
</style>
|