import { ActionSheet, Button, Cell, CountDown, Icon, Image, Popup, showDialog, Swipe, SwipeItem, Tag } from 'vant' import { defineComponent, nextTick, onMounted, reactive, ref } from 'vue' import { useRoute, useRouter } from 'vue-router' import styles from './index.module.less' import iconQuestionNums from '../images/icon-question-nums.png' import iconCountDown from '../images/icon-count-down.png' import iconButtonList from '../images/icon-button-list.png' import OSticky from '@/components/o-sticky' import ChoiceQuestion from '../model/choice-question' import AnswerList from '../model/answer-list' import ODialog from '@/components/o-dialog' import DragQuestion from '../model/drag-question' import KeepLookQuestion from '../model/keep-look-question' import PlayQuestion from '../model/play-question' import request from '@/helpers/request' import dayjs from 'dayjs' import ResultFinish from '../model/result-finish' import { eventUnit, QuestionType } from '../unit' import { useRect } from '@vant/use' export default defineComponent({ name: 'unit-detail', setup() { const route = useRoute() const router = useRouter() const countDownRef = ref() const swipeRef = ref() const state = reactive({ id: route.query.id, examDetail: {} as any, visiableAnswer: false, currentIndex: 0, questionList: [], time: 0, visiableSure: false, visiableResult: false, resultInfo: {} as any, resultStatusType: 'SUCCESS', // 'SUCCESS' | 'FAIL' visiableExam: false, // 考试已结束 nextStatus: false, swipeHeight: 'auto' as any, quitStatus: false }) const getExamDetails = async () => { try { const { data } = await request.post( '/api-student/studentUnitExamination/startExamination', { requestType: 'form', data: { studentUnitExaminationId: state.id } } ) const { questionJson, studentAnswerJson, ...res } = data const temp = questionJson || [] temp.forEach((item: any) => { item.userAnswer = formatUserAnswers(item, studentAnswerJson) }) state.questionList = temp state.examDetail = { ...res } || {} calcTime() } catch { // } } /** * @description 计算考试时间剩余时间 */ const calcTime = async () => { const examDetail = state.examDetail || {} const startTime = examDetail.startTime const nowTime = examDetail.now const timeMinutes = examDetail.timeMinutes || 0 // 测验时间 // 返回秒 const minu = dayjs(startTime).add(timeMinutes, 'minute').diff(dayjs(nowTime)) // 时间到了考试结束 if (minu <= 0) { await onConfirmExam() state.visiableExam = true } else { state.time = Math.ceil(minu / 1000) * 1000 setTimeout(() => { countDownRef.value?.start() }, 10) } } /** * @description 初始化用户答案 */ const formatUserAnswers = (item: any, userAnswer: any) => { // 判断是否有结果 if (!userAnswer) return [] const answers = userAnswer || [] return answers[item.id] ? answers[item.id] : [] } /** * @description 重置当前的题目高度 */ let size = 0 const resizeSwipeItemHeight = (scroll = true) => { nextTick(() => { scroll && window.scrollTo(0, 0) setTimeout(() => { // const currentItemDom: Element = // document.querySelectorAll('.swipe-item-question')[state.currentIndex] const currentItemDom: any = document .querySelectorAll('.van-swipe-item') [state.currentIndex]?.querySelector('.swipe-item-question') const allImg = currentItemDom.querySelectorAll('.answerTitleImg img') let status = true // console.log(allImg) allImg.forEach((img: any) => { console.log(img.complete) if (!img.complete) { status = false } }) // 判断图片是否加载完了 if (!status && size < 3) { setTimeout(() => { size += 1 resizeSwipeItemHeight(scroll) }, 300) } if (status) { size = 0 } const rect = useRect(currentItemDom) state.swipeHeight = rect.height }, 100) }) } /** * @description 下一题 | 测试完成 */ const onNextQuestion = async () => { try { const questionList = state.questionList || [] const userAnswerList: any = [] // 所有题目的答案 // let currentResult = false // 当前题目是否已经答题 questionList.forEach((question: any, index: number) => { // 格式化所有题目的答案 if (question.userAnswer && question.userAnswer.length > 0) { userAnswerList.push({ questionId: question.id, details: question.userAnswer }) } }) // 判断是否是最后一题 // console.log(state.questionList.length, state.currentIndex, userAnswerList, '-----') if (state.questionList.length === state.currentIndex + 1) { state.visiableSure = true return } state.nextStatus = true await request.post('/api-student/studentUnitExamination/submitAnswer', { hideLoading: true, data: { answers: userAnswerList, studentUnitExaminationId: state.id } }) swipeRef.value?.next() state.nextStatus = false } catch { // state.nextStatus = false } } /** * @description 提交最终答案 */ const onConfirmExam = async () => { try { const questionList = state.questionList || [] const userAnswerList: any = [] // 所有题目的答案 questionList.forEach((question: any) => { // 格式化所有题目的答案 if (question.userAnswer && question.userAnswer.length > 0) { userAnswerList.push({ questionId: question.id, details: question.userAnswer }) } }) const { data } = await request.post( '/api-student/studentUnitExamination/completionExamination', { data: { answers: userAnswerList, studentUnitExaminationId: state.id } } ) if (data.status === 'A_PASS') { state.resultStatusType = 'SUCCESS' state.resultInfo = { tips: '恭喜你,测验通过!', score: data.score, examName: state.examDetail.unitExaminationName } } else { state.resultStatusType = 'FAIL' state.resultInfo = { tips: '本次测验不合格!', score: data.score, examName: state.examDetail.unitExaminationName } } onAfter() state.visiableResult = true } catch { // } } // 拦截 const onBack = () => { // showDialog({ // title: '提示', // message: '您考试还未提交,是否退出?', // theme: 'round-button', // confirmButtonColor: '#ff8057' // }).then(() => { // onAfter() // router.back() // }) state.quitStatus = true } const onAfter = () => { window.removeEventListener('popstate', onBack, false) } onMounted(async () => { await getExamDetails() // 初始化高度 resizeSwipeItemHeight() window.history.pushState(null, '', document.URL) window.addEventListener('popstate', onBack, false) }) return () => (
{{ title: () =>
{state.examDetail.unitExaminationName}
, label: () => (
题目数量{' '} {state.currentIndex + 1} /{state.examDetail.questionNum}
剩余时长: { await onConfirmExam() state.visiableExam = true }} />
) }}
{ eventUnit.emit('unitAudioStop') state.currentIndex = index resizeSwipeItemHeight() }} > {state.questionList.map((item: any, index: number) => ( // item.questionTypeCode === QuestionType.LINK && ( // // // // )
{item.questionTypeCode === QuestionType.RADIO && ( )} {item.questionTypeCode === QuestionType.CHECKBOX && ( )} {item.questionTypeCode === QuestionType.SORT && ( { resizeSwipeItemHeight(false) }} data={item} index={index + 1} /> )} {item.questionTypeCode === QuestionType.LINK && ( )} {item.questionTypeCode === QuestionType.PLAY && ( )}
))}
{state.currentIndex > 0 && ( )} (state.visiableAnswer = true)} />
{/* 题目集合 */} { // 跳转,并且跳过动画 swipeRef.value?.swipeTo(item, { immediate: true }) state.visiableAnswer = false }} /> { state.visiableResult = false router.back() router.back() }} onConform={() => { state.visiableResult = false router.back() router.back() }} /> { onAfter() state.visiableResult = true }} /> { onAfter() router.back() }} />
) } })