123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444 |
- import { ActionSheet, Button, Cell, Icon, Image, Swipe, SwipeItem } from 'vant'
- import { defineComponent, onMounted, reactive, ref, nextTick, onUnmounted } from 'vue'
- import { useRoute, useRouter } from 'vue-router'
- import styles from './index.module.less'
- import iconQuestionNums from '../images/icon-question-nums.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 DragQuestion from '../model/drag-question'
- import KeepLookQuestion from '../model/keep-look-question'
- import PlayQuestion from '../model/play-question'
- import request from '@/helpers/request'
- import { eventUnit, QuestionType } from '../unit'
- import { useRect } from '@vant/use'
- import { state as baseState } from '@/state'
- import OHeader from '@/components/o-header'
- export default defineComponent({
- name: 'unit-detail',
- setup() {
- const route = useRoute()
- const router = useRouter()
- const swipeRef = ref()
- const state = reactive({
- id: route.query.id,
- examDetail: {} as any,
- visiableAnswer: false,
- currentIndex: 0,
- questionList: [],
- time: 0,
- resultInfo: {} as any,
- answerResult: [] as any,
- nextStatus: false,
- swipeHeight: 'auto' as any
- })
- // 学员端查看详情
- const getExamDetails = async () => {
- try {
- const { data } = await request.post('/api-student/studentUnitExamination/detail', {
- requestType: 'form',
- data: {
- studentUnitExaminationId: state.id
- }
- })
- const { questionJson, studentAnswerJson, answerResult, ...res } = data
- const temp = questionJson || []
- // 正确答案
- state.answerResult = answerResult ? JSON.parse(answerResult) : []
- temp.forEach((item: any) => {
- item.userAnswer = formatUserAnswers(item, studentAnswerJson)
- item.showAnalysis = true
- item.showScore = true
- item.analysis = {
- message: item.answerAnalysis,
- topic: true, // 是否显示结果
- userResult: formatUserResult(item.id) // 用户答题对错
- }
- })
- // 问题列表
- state.questionList = temp
- // 详情
- state.examDetail = { ...res } || {}
- } catch {
- //
- }
- }
- const getExamTeaherDetails = async () => {
- try {
- const { data } = await request.post(
- baseState.platformApi + '/classGroupUnitExamination/report',
- {
- requestType: 'form',
- data: {
- classGroupUnitExaminationId: state.id,
- level: route.query.level
- }
- }
- )
- // console.log(data)
- // const { questionJson, studentAnswerJson, answerResult, ...res } = data
- state.examDetail = {
- unitExaminationName: data.unitExaminationName,
- questionNum: data.questionNum || 0
- }
- // 问题列表
- const temp = data.examinationQuestionAdds || []
- temp.forEach((item: any) => {
- const rightAnswers = item.rightAnswers || []
- // const answers = item.answers || []
- // answers.forEach((answer: any) => {
- // const child = rightAnswers.find(
- // (right: any) =>
- // right.examinationQuestionAnswerId === answer.examinationQuestionAnswerId
- // )
- // if (child) {
- // answer.selectRate = child.selectRate
- // }
- // })
- // item.answers = answers
- item.userAnswer = formatTeacherAnswer(rightAnswers)
- item.showAnalysis = true
- item.showRate = true
- item.showScore = false
- item.analysis = {
- message: item.answerAnalysis,
- topic: false // 是否显示结果
- }
- })
- // 问题列表
- state.questionList = temp
- // 正确答案
- // console.log(state.questionList, 'state.questionList')
- } catch {
- //
- }
- }
- /**
- * @description 初始化正确答案
- */
- const formatTeacherAnswer = (answers: any) => {
- const result: any = []
- answers.forEach((answer: any) => {
- // rightAnswerFlag 说明是正确的
- if (answer.rightAnswerFlag) {
- const rightOption = answers.find(
- (item: any) => item.questionExtra === answer.questionExtra
- )
- result.push({
- answer: answer.questionAnswer,
- answerId: answer.examinationQuestionAnswerId,
- answerExtra: rightOption ? rightOption.questionExtra : null
- })
- }
- })
- return result || []
- }
- /**
- * @description 初始化用户答案
- */
- const formatUserAnswers = (item: any, userAnswer: any) => {
- // 判断是否有结果
- if (!userAnswer) return []
- const answers = userAnswer || []
- return answers[item.id] ? answers[item.id] : []
- }
- /**
- * @description 检查用户是否答对
- * @returns Boolean
- */
- const formatUserResult = (id: string) => {
- let result = false
- state.answerResult.forEach((item: any) => {
- if (item.questionId === id) {
- result = item.rightFlag
- }
- })
- return result
- }
- /**
- * @description 重置当前的题目高度
- */
- let size = 0
- const resizeSwipeItemHeight = (scroll = true) => {
- nextTick(() => {
- scroll && window.scrollTo(0, 0)
- setTimeout(() => {
- 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)
- // console.log('🚀 ~ setTimeout ~ currentItemDom', currentItemDom)
- // console.log('🚀 ~ setTimeout ~ rect', rect, state.currentIndex)
- state.swipeHeight = rect.height
- }, 100)
- })
- }
- /**
- * @description 下一题 | 测试完成
- */
- const onNextQuestion = async () => {
- try {
- state.nextStatus = true
- if (state.questionList.length === state.currentIndex + 1) {
- // 关闭所有音频
- eventUnit.emit('unitAudioStop')
- router.back()
- }
- swipeRef.value?.next()
- state.nextStatus = false
- } catch {
- //
- state.nextStatus = false
- }
- }
- onMounted(async () => {
- if (baseState.platformType === 'TEACHER' || baseState.platformType === 'SCHOOL') {
- await getExamTeaherDetails()
- } else {
- await getExamDetails()
- }
- // 初始化高度
- resizeSwipeItemHeight()
- })
- onUnmounted(() => {
- // 关闭所有音频
- eventUnit.emit('unitAudioStop')
- })
- return () => (
- <div class={styles.unitDetail}>
- <OHeader />
- <Cell center class={styles.unitSection} border={false}>
- {{
- title: () => <div class={styles.unitTitle}>{state.examDetail.unitExaminationName}</div>,
- label: () => (
- <div class={styles.unitCount}>
- <div class={styles.qNums}>
- <Icon class={styles.icon} name={iconQuestionNums} />
- 题目数量{' '}
- <span class={styles.num} style={{ paddingLeft: '6px' }}>
- {state.currentIndex + 1}
- </span>
- /{state.examDetail.questionNum || 0}
- </div>
- </div>
- )
- }}
- </Cell>
- <Swipe
- loop={false}
- showIndicators={false}
- ref={swipeRef}
- duration={300}
- touchable={false}
- lazyRender
- style={{ paddingBottom: '12px' }}
- height={state.swipeHeight}
- onChange={(index: number) => {
- eventUnit.emit('unitAudioStop')
- state.currentIndex = index
- // .swipe-item-question
- // const t = setInterval(() => {
- // console.log(document.querySelectorAll('.van-swipe-item')[state.currentIndex])
- // console.log(
- // document
- // .querySelectorAll('.van-swipe-item')
- // [state.currentIndex].querySelector('.swipe-item-question')
- // )
- // if (
- // document
- // .querySelectorAll('.van-swipe-item')
- // [state.currentIndex].querySelector('.swipe-item-question')
- // ) {
- // clearInterval(t)
- // }
- // }, 100)
- resizeSwipeItemHeight()
- }}
- >
- {state.questionList.map((item: any, index: number) => (
- // item.questionTypeCode === QuestionType.CHECKBOX && (
- // <SwipeItem>
- // <ChoiceQuestion
- // v-model:value={item.userAnswer}
- // index={index + 1}
- // data={item}
- // readOnly
- // type="checkbox"
- // showRate={item.showRate}
- // showAnalysis={item.showAnalysis}
- // analysis={item.analysis}
- // />
- // </SwipeItem>
- // )
- <SwipeItem>
- <div class="swipe-item-question">
- {item.questionTypeCode === QuestionType.RADIO && (
- <ChoiceQuestion
- v-model:value={item.userAnswer}
- index={index + 1}
- data={item}
- readOnly
- type="radio"
- showRate={item.showRate}
- showAnalysis={item.showAnalysis}
- analysis={item.analysis}
- />
- )}
- {item.questionTypeCode === QuestionType.CHECKBOX && (
- <ChoiceQuestion
- v-model:value={item.userAnswer}
- index={index + 1}
- data={item}
- readOnly
- type="checkbox"
- showRate={item.showRate}
- showAnalysis={item.showAnalysis}
- analysis={item.analysis}
- />
- )}
- {item.questionTypeCode === QuestionType.SORT && (
- <DragQuestion
- readOnly
- v-model:value={item.userAnswer}
- data={item}
- index={index + 1}
- showRate={item.showRate}
- showAnalysis={item.showAnalysis}
- analysis={item.analysis}
- />
- )}
- {item.questionTypeCode === QuestionType.LINK && (
- <KeepLookQuestion
- readOnly
- v-model:value={item.userAnswer}
- data={item}
- index={index + 1}
- showRate={item.showRate}
- showAnalysis={item.showAnalysis}
- analysis={item.analysis}
- />
- )}
- {item.questionTypeCode === QuestionType.PLAY && (
- <PlayQuestion
- readOnly
- v-model:value={item.userAnswer}
- data={item}
- index={index + 1}
- unitId={state.id as any}
- showScore={item.showScore}
- showRate={item.showRate}
- showAnalysis={item.showAnalysis}
- analysis={item.analysis}
- />
- )}
- </div>
- </SwipeItem>
- ))}
- </Swipe>
- <OSticky position="bottom" background="white">
- <div class={['btnGroup btnMore']}>
- {state.currentIndex > 0 && (
- <Button
- round
- block
- type="primary"
- plain
- onClick={() => {
- swipeRef.value?.prev()
- }}
- >
- 上一题
- </Button>
- )}
- <Button
- block
- round
- type="primary"
- onClick={onNextQuestion}
- loading={state.nextStatus}
- disabled={state.nextStatus}
- >
- {state.questionList.length === state.currentIndex + 1 ? '确定' : '下一题'}
- </Button>
- <Image
- src={iconButtonList}
- class={[styles.wapList, 'van-haptics-feedback']}
- onClick={() => (state.visiableAnswer = true)}
- />
- </div>
- </OSticky>
- {/* 题目集合 */}
- <ActionSheet v-model:show={state.visiableAnswer} title="题目列表" safeAreaInsetBottom>
- <AnswerList
- value={state.questionList}
- answerResult={state.answerResult}
- index={state.currentIndex}
- lookType={baseState.platformType === 'STUDENT' ? 'RESULT' : 'CLICK'}
- statusList={
- baseState.platformType === 'STUDENT'
- ? [
- {
- text: '答对',
- color: '#71B0FF'
- },
- {
- text: '答错',
- color: '#FF8486'
- }
- ]
- : []
- }
- onSelect={(item: any) => {
- // 跳转,并且跳过动画
- swipeRef.value?.swipeTo(item, {
- immediate: true
- })
- state.visiableAnswer = false
- }}
- />
- </ActionSheet>
- </div>
- )
- }
- })
|