<template>
<div class="cloze-filling-drag-popup" ref="popup">
<div
class="title"
@touchstart.stop.prevent="touchStart"
@touchmove.stop.prevent="touchmove"
@touchend.stop.prevent="touchend"
ref="titleBar"
></div> <
div class="popup-content" ref="popupContent">
<!-- <slot name="popupContent"></slot> -->
<div class="options-title" ref="refOptionsTitle">
<span>填空{{activefillIndex}}</span>
<span style="float:right;">
<span style="color:#0096f0">{{activefillIndex}}</span>
/{{fills.length}}
</span>
<div
style="width:100%;height:1px;box-sizing: border-box;border-bottom:1px solid #e0e0e0;position:absolute;bottom:0px;"
></div>
</div>
<van-swipe
:loop="false"
:show-indicators="false"
indicator-color="white"
ref="swiper2"
:initial-swipe="initialSwipe"
@change="swiperChange"
>
<template v-for="(fill,index) in fills">
<van-swipe-item :key="index">
<div class="options">
<template v-for="(item,idx) in fill">
<div :key="idx" class="option" @click="itemClick(idx,index,item,fill)">
<div class="tag">
<span class="normal-option" :class="[ item.checked ?'active-option':'']">
<!--:class="[ item.checked ?'active-option':'']" -->
{{idx == 0 ? 'A'
: idx == 1 ? 'B'
:idx == 2 ? 'C'
: 'D'
}}
</span>
</div>
<div class="content" v-html="item.content"></div>
</div>
</template>
</div>
</van-swipe-item>
</template>
</van-swipe>
</div>
</div>
</template>
<script>
import { mapActions, mapGetters, mapState } from "vuex";
import { Popup, Swipe, SwipeItem } from "vant";
export default {
name: "exam-drag-component",
components: {
vanPopup: Popup,
vanSwipe: Swipe,
vanSwipeItem: SwipeItem
},
props: {
scrollTop: {
type: Number,
default: 0
},
question: {
type: Object,
default: () => {
return {};
}
},
footHeight: {
type: Number,
default: 0
}
},
watch: {
scrollTop: {
handler(val) {
this.obj.ele.style.top = this.bottom + "px";
//this.moveBottomHandler();
}
},
footHeight: {
handler(val) {
this.$nextTick(() => {
if (this.$refs.popup) {
this.initData();
}
});
},
immediate: true
},
question: {
handler(val) {
if (val) {
this.data = val;
if (val.fills && val.fills.length > 0) {
let arr = val.fills.reduce((ls, cur) => {
let a = [];
if (cur.length > 0) {
cur.forEach(val => {
let o = {};
o.content = val;
o.checked = false;
a.push(o);
});
}
ls.push(a);
return ls;
}, []);
this.fills = arr;
} else {
this.fills = [];
}
}
},
immediate: true,
deep: true
},
currentUserAnswer: {
handler(val) {
this.currentAnswer = [];
if (this.data.id == val.questionId) {
this.userCheckedData = val.checkOption;
this.initUserCheckedFills();
}
},
immediate: true,
deep: true
},
activeQuestion: {
handler(val) {
this.activefillIndex = 1;
this.obj.ele.style.top = this.bottom + "px";
}
}
},
data() {
return {
msg: "拖拽组件",
obj: {},
app: this.isApp,
android: this.isAndroid,
bottom: 0,
data: {},
currentAnswer: [],
activefillIndex: 1,
fills: [],
initialSwipe: 0,
userCheckedData: [],
titleHeight: 0
};
},
mounted() {
console.log(this.activeQuestion);
this.initData();
this.initUserCheckedFills();
},
computed: {
...mapGetters(["activeQuestion", "currentUserAnswer"]),
...mapState({
qsNum: state => state.examPaper.qsNum
})
},
methods: {
...mapActions(["setUserAnswers"]),
initData() {
this.obj.ele = this.$refs.popup;
this.titleHeight =
this.$refs.refOptionsTitle.offsetHeight +
this.$refs.titleBar.offsetHeight;
//alert(document.documentElement.clientHeight);
let clientHeight = document.documentElement.clientHeight;
this.bottom =
document.documentElement.clientHeight -
this.footHeight -
this.titleHeight;
this.obj.ele.style.top = this.bottom + "px";
},
swiperChange(data) {
this.activefillIndex = data + 1;
},
itemClick(data, currentfill, item, fill) {
fill.forEach(val => {
val.checked = false;
});
item.checked = true;
let that = this;
let obj = {};
obj.fill = currentfill;
obj.answer = data;
let idx = -1;
if (this.currentAnswer.length > 0) {
this.currentAnswer.forEach((val, index) => {
if (val.fill == currentfill) {
idx = index;
}
});
}
if (idx > -1) {
this.currentAnswer.splice(idx, 1);
this.currentAnswer.push(obj);
} else {
this.currentAnswer.push(obj);
}
this.itemClickHandler();
},
itemClickHandler() {
let obj = {};
obj.id = this.activeQuestion;
obj.questionId = this.data.id;
obj.fillLen = this.fills.length;
obj.mode = this.data.mode_id;
obj.checkOption = this.currentAnswer;
obj.img = "";
//this.setUserAnswers(obj);
console.log(obj);
//this.$emit("submitItemAnswer", obj);
this.setUserAnswers(obj);
//console.log(this.currentAnswer);
},
initUserCheckedFills() {
console.log(this.userCheckedData);
this.currentAnswer = this.userCheckedData;
if (
this.currentUserAnswer.questionId == this.data.id &&
this.currentUserAnswer.id == this.activeQuestion
) {
if (this.userCheckedData.length > 0 && this.fills.length > 0) {
this.userCheckedData.forEach(val => {
console.log(val);
this.fills[val.fill][val.answer].checked = true;
});
}
}
},
moveTopHandler() {
this.animateMove(this.obj.ele, this.top);
},
moveBottomHandler() {
this.animateMove(this.obj.ele, this.bottom);
},
animateMove(element, target) {
clearInterval(timer);
var left = element.offsetTop;
//设置步长 表示一步动作的差值
//通过比较element当前的left值和target值的大小,来确定平移方向
var step = (target - left) / 1;
var timer = setInterval(function() {
//如果目标值大于当前的left值,step为正数,向右移动
//如果目标值小于当前的left值,step为负数,向左移动
left += step;
element.style.top = left + "px";
//判断停止动画
//比较差值,取绝对值,当两者的差值小于了步进值时,停止动画,
if (Math.abs(target - left) <= Math.abs(step)) {
clearInterval(timer);
element.style.top = target + "px";
}
}, 1);
},
touchStart(evt) {
if (this.android || !this.isApp) {
this.obj.Y = evt.changedTouches[0].clientY;
this.obj.newTop = evt.path[1].style.top.split("px")[0];
this.obj.minTop = this.bottom - this.$refs.popupContent.offsetHeight;
} else {
this.obj.Y = evt.targetTouches[0].clientY;
this.obj.newTop = this.obj.ele.style.top.split("px")[0];
this.obj.minTop = this.bottom - this.$refs.popupContent.offsetHeight;
console.log(this.obj.minTop, "2222");
}
},
touchmove(evt) {
let moveY = 0;
if (this.android || !this.isApp) {
moveY = evt.changedTouches[0].clientY;
} else if (!this.android && this.isApp) {
moveY = evt.targetTouches[0].clientY;
}
let len = this.obj.Y - moveY;
if (len > 0) {
if (this.obj.newTop - len > this.obj.minTop + this.titleHeight) {
this.obj.ele.style.top = this.obj.newTop - len + "px";
} else {
this.obj.ele.style.top = this.obj.minTop + this.titleHeight + "px";
}
} else {
//console.log(this.bottom);
if (Number(this.obj.newTop) + Math.abs(len) > this.bottom) {
this.obj.ele.style.top = this.bottom + "px";
} else {
let top = this.obj.newTop - len;
this.obj.ele.style.top = top + "px";
}
}
this.obj.len = Math.abs(len);
},
touchend(evt) {
//console.log(this.obj, "end");
}
}
};
</script>
<style lang="less">
.cloze-filling-drag-popup {
position: fixed;
width: 100%;
z-index: 99;
-webkit-overflow-scrolling: touch;
.title {
position: relative;
width: 32vw;
height: 10vw;
background: #f8f8f8;
margin-left: 35%;
border-radius: 8px 8px 0px 0px;
border: 1px solid #d8c9c9;
border-bottom: none;
background-image: url(./../assets/img/sgt.png);
background-size: 50% 50%;
background-repeat: no-repeat;
background-position: center center;
box-sizing: border-box;
z-index: 3;
}
.popup-content {
width: 100%;
background: #ffffff;
border-top: 1px solid #e0e0e0;
padding-bottom: 10vw;
.title {
padding: 2vw 2vw 0vw 2vw;
font-size: 5vw;
height: 8vw;
box-sizing: border-box;
}
.options-title {
position: relative;
padding: 2vw 2vw 0vw 2vw;
font-size: 5vw;
height: 10vw;
box-sizing: border-box;
}
.options {
padding: 0vw 1vw 1vw 0;
width: 100%;
font-size: 4vw;
.option {
display: flex;
margin-top: 2vw;
flex-wrap: nowrap;
.tag {
width: 10vw;
height: 8vw;
line-height: 5.5vw;
text-align: center;
.normal-option {
display: inline-block;
width: 5vw;
height: 5vw;
padding: 1vw;
margin-top: 1vw;
border: 1px solid #646464;
border-radius: 100%;
}
.active-option {
background: #0096f0;
color: #ffffff;
}
}
.content {
padding-top: 1vw;
flex: 1;
}
}
}
}
}
</style>