|
@@ -1,71 +1,143 @@
|
|
|
-import {
|
|
|
- ActionSheet,
|
|
|
- Button,
|
|
|
- Cell,
|
|
|
- CountDown,
|
|
|
- Icon,
|
|
|
- Image,
|
|
|
- Popup,
|
|
|
- Swipe,
|
|
|
- SwipeItem,
|
|
|
- Tag
|
|
|
-} from 'vant'
|
|
|
-import { defineComponent, onMounted, reactive, ref } from 'vue'
|
|
|
+import { ActionSheet, Button, Cell, Icon, Image, Swipe, SwipeItem } from 'vant'
|
|
|
+import { defineComponent, onMounted, reactive, ref, nextTick } from 'vue'
|
|
|
import { useRoute, useRouter } from 'vue-router'
|
|
|
-import NoticeStart from '../model/notice-start'
|
|
|
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 { 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: [5],
|
|
|
- answerList: {},
|
|
|
- time: 30 * 60 * 1000,
|
|
|
- visiableSure: false,
|
|
|
- childs: [
|
|
|
- { name: 'John', id: 0 },
|
|
|
- { name: 'Joao', id: 1 },
|
|
|
- { name: 'Jean', id: 2 }
|
|
|
- ]
|
|
|
+ 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-school/studentUnitExamination/detail', {
|
|
|
+ requestType: 'form',
|
|
|
+ data: {
|
|
|
+ studentUnitExaminationId: state.id
|
|
|
+ }
|
|
|
+ })
|
|
|
+ const { questionJson, studentAnswerJson, answerResult, ...res } = data
|
|
|
+ const temp = questionJson || []
|
|
|
+ temp.forEach((item: any) => {
|
|
|
+ item.userAnswer = formatUserAnswers(item, studentAnswerJson)
|
|
|
+ })
|
|
|
+ // 问题列表
|
|
|
+ state.questionList = temp
|
|
|
+ // 正确答案
|
|
|
+ state.answerResult = answerResult ? JSON.parse(answerResult) : []
|
|
|
+
|
|
|
+ // 详情
|
|
|
+ state.examDetail = { ...res } || {}
|
|
|
+ } catch {
|
|
|
+ //
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @description 初始化用户答案
|
|
|
+ */
|
|
|
+ const formatUserAnswers = (item: any, userAnswer: any) => {
|
|
|
+ // 判断是否有结果
|
|
|
+ if (!userAnswer) return []
|
|
|
+ const answers = JSON.parse(userAnswer) || []
|
|
|
+
|
|
|
+ const questionItem = answers.find((child: any) => child.questionId === item.id)
|
|
|
+ return questionItem ? questionItem.details : []
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @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 重置当前的题目高度
|
|
|
+ */
|
|
|
+ const resizeSwipeItemHeight = () => {
|
|
|
+ nextTick(() => {
|
|
|
+ window.scrollTo(0, 0)
|
|
|
+ setTimeout(() => {
|
|
|
+ const currentItemDom: Element =
|
|
|
+ document.querySelectorAll('.swipe-item-question')[state.currentIndex]
|
|
|
+ console.log(currentItemDom, state.currentIndex)
|
|
|
+ const rect = useRect(currentItemDom)
|
|
|
+ state.swipeHeight = rect.height
|
|
|
+ }, 100)
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @description 下一题 | 测试完成
|
|
|
+ */
|
|
|
+ const onNextQuestion = async () => {
|
|
|
+ try {
|
|
|
+ state.nextStatus = true
|
|
|
+ if (state.questionList.length === state.currentIndex + 1) {
|
|
|
+ router.back()
|
|
|
+ }
|
|
|
+ swipeRef.value?.next()
|
|
|
+ state.nextStatus = false
|
|
|
+ } catch {
|
|
|
+ //
|
|
|
+ state.nextStatus = false
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ onMounted(async () => {
|
|
|
+ await getExamDetails()
|
|
|
+
|
|
|
+ // 初始化高度
|
|
|
+ resizeSwipeItemHeight()
|
|
|
})
|
|
|
|
|
|
return () => (
|
|
|
<div class={styles.unitDetail}>
|
|
|
<Cell center class={styles.unitSection}>
|
|
|
{{
|
|
|
- title: () => <div class={styles.unitTitle}>长笛level1上册测验一</div>,
|
|
|
+ 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}>1</span>/4
|
|
|
- </div>
|
|
|
- <div class={styles.qNums}>
|
|
|
- <Icon class={styles.icon} name={iconCountDown} />
|
|
|
- 剩余时长:
|
|
|
- <CountDown
|
|
|
- ref={countDownRef}
|
|
|
- time={state.time}
|
|
|
- format={'mm:ss'}
|
|
|
- autoStart={false}
|
|
|
- />
|
|
|
+ 题目数量{' '}
|
|
|
+ <span class={styles.num} style={{ paddingLeft: '6px' }}>
|
|
|
+ {state.currentIndex + 1}
|
|
|
+ </span>
|
|
|
+ /{state.examDetail.questionNum || 0}
|
|
|
</div>
|
|
|
</div>
|
|
|
)
|
|
@@ -79,26 +151,109 @@ export default defineComponent({
|
|
|
duration={300}
|
|
|
touchable={false}
|
|
|
lazyRender
|
|
|
- // initialSwipe={state.currentIndex}
|
|
|
+ style={{ paddingBottom: '12px' }}
|
|
|
+ height={state.swipeHeight}
|
|
|
onChange={(index: number) => {
|
|
|
state.currentIndex = index
|
|
|
+ resizeSwipeItemHeight()
|
|
|
}}
|
|
|
>
|
|
|
- <SwipeItem>
|
|
|
- <ChoiceQuestion v-model:value={state.answerList[0]} type="checkbox" />
|
|
|
- </SwipeItem>
|
|
|
- <SwipeItem>
|
|
|
- <ChoiceQuestion v-model:value={state.answerList[1]} type="radio" />
|
|
|
- </SwipeItem>
|
|
|
- <SwipeItem>
|
|
|
- <DragQuestion />
|
|
|
- </SwipeItem>
|
|
|
- <SwipeItem>
|
|
|
- <KeepLookQuestion />
|
|
|
- </SwipeItem>
|
|
|
- <SwipeItem>
|
|
|
- <PlayQuestion />
|
|
|
- </SwipeItem>
|
|
|
+ {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="radio"
|
|
|
+ // showAnalysis
|
|
|
+ // analysis={{
|
|
|
+ // message: item.answerAnalysis,
|
|
|
+ // topic: true, // 是否显示结果
|
|
|
+ // userResult: formatUserResult(item.id) // 用户答题对错
|
|
|
+ // }}
|
|
|
+ // />
|
|
|
+ // </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"
|
|
|
+ showAnalysis
|
|
|
+ analysis={{
|
|
|
+ message: item.answerAnalysis,
|
|
|
+ topic: true, // 是否显示结果
|
|
|
+ userResult: formatUserResult(item.id) // 用户答题对错
|
|
|
+ }}
|
|
|
+ />
|
|
|
+ )}
|
|
|
+ {item.questionTypeCode === QuestionType.CHECKBOX && (
|
|
|
+ <ChoiceQuestion
|
|
|
+ v-model:value={item.userAnswer}
|
|
|
+ index={index + 1}
|
|
|
+ data={item}
|
|
|
+ readOnly
|
|
|
+ type="checkbox"
|
|
|
+ showAnalysis
|
|
|
+ analysis={{
|
|
|
+ message: item.answerAnalysis,
|
|
|
+ topic: true, // 是否显示结果
|
|
|
+ userResult: formatUserResult(item.id) // 用户答题对错
|
|
|
+ }}
|
|
|
+ />
|
|
|
+ )}
|
|
|
+ {item.questionTypeCode === QuestionType.SORT && (
|
|
|
+ <DragQuestion
|
|
|
+ readOnly
|
|
|
+ v-model:value={item.userAnswer}
|
|
|
+ data={item}
|
|
|
+ index={index + 1}
|
|
|
+ showAnalysis
|
|
|
+ analysis={{
|
|
|
+ message: item.answerAnalysis,
|
|
|
+ topic: true, // 是否显示结果
|
|
|
+ userResult: formatUserResult(item.id) // 用户答题对错
|
|
|
+ }}
|
|
|
+ />
|
|
|
+ )}
|
|
|
+ {item.questionTypeCode === QuestionType.LINK && (
|
|
|
+ <KeepLookQuestion
|
|
|
+ readOnly
|
|
|
+ v-model:value={item.userAnswer}
|
|
|
+ data={item}
|
|
|
+ index={index + 1}
|
|
|
+ showAnalysis
|
|
|
+ analysis={{
|
|
|
+ message: item.answerAnalysis,
|
|
|
+ topic: true, // 是否显示结果
|
|
|
+ userResult: formatUserResult(item.id) // 用户答题对错
|
|
|
+ }}
|
|
|
+ />
|
|
|
+ )}
|
|
|
+ {item.questionTypeCode === QuestionType.PLAY && (
|
|
|
+ <PlayQuestion
|
|
|
+ readOnly
|
|
|
+ v-model:value={item.userAnswer}
|
|
|
+ data={item}
|
|
|
+ index={index + 1}
|
|
|
+ unitId={state.id as any}
|
|
|
+ showAnalysis
|
|
|
+ analysis={{
|
|
|
+ message: item.answerAnalysis,
|
|
|
+ topic: true, // 是否显示结果
|
|
|
+ userResult: formatUserResult(item.id) // 用户答题对错
|
|
|
+ }}
|
|
|
+ />
|
|
|
+ )}
|
|
|
+ </div>
|
|
|
+ </SwipeItem>
|
|
|
+ ))}
|
|
|
</Swipe>
|
|
|
|
|
|
<OSticky position="bottom" background="white">
|
|
@@ -120,16 +275,11 @@ export default defineComponent({
|
|
|
block
|
|
|
round
|
|
|
type="primary"
|
|
|
- onClick={() => {
|
|
|
- // if (state.questionList.length - 1 === state.currentIndex) {
|
|
|
- // state.visiableSure = true
|
|
|
- // } else {
|
|
|
- swipeRef.value?.next()
|
|
|
- // }
|
|
|
- }}
|
|
|
+ onClick={onNextQuestion}
|
|
|
+ loading={state.nextStatus}
|
|
|
+ disabled={state.nextStatus}
|
|
|
>
|
|
|
- 下一题
|
|
|
- {/* {state.questionList.length === state.currentIndex + 1 ? '测试完成' : '下一题'} */}
|
|
|
+ {state.questionList.length === state.currentIndex + 1 ? '确定' : '下一题'}
|
|
|
</Button>
|
|
|
<Image
|
|
|
src={iconButtonList}
|
|
@@ -142,7 +292,19 @@ export default defineComponent({
|
|
|
{/* 题目集合 */}
|
|
|
<ActionSheet v-model:show={state.visiableAnswer} title="题目列表" safeAreaInsetBottom>
|
|
|
<AnswerList
|
|
|
- value={[1, 3, 4]}
|
|
|
+ value={state.questionList}
|
|
|
+ answerResult={state.answerResult}
|
|
|
+ look
|
|
|
+ statusList={[
|
|
|
+ {
|
|
|
+ text: '答对',
|
|
|
+ color: '#71B0FF'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ text: '答错',
|
|
|
+ color: '#FF8486'
|
|
|
+ }
|
|
|
+ ]}
|
|
|
onSelect={(item: any) => {
|
|
|
// 跳转,并且跳过动画
|
|
|
swipeRef.value?.swipeTo(item, {
|
|
@@ -152,16 +314,6 @@ export default defineComponent({
|
|
|
}}
|
|
|
/>
|
|
|
</ActionSheet>
|
|
|
-
|
|
|
- <ODialog
|
|
|
- v-model:show={state.visiableSure}
|
|
|
- title="测验完成"
|
|
|
- message="确认本次测验的题目都完成了吗?\n提交后不可修改哦"
|
|
|
- messageAlign="left"
|
|
|
- showCancelButton
|
|
|
- cancelButtonText="再等等"
|
|
|
- confirmButtonText="确认完成"
|
|
|
- />
|
|
|
</div>
|
|
|
)
|
|
|
}
|