|
@@ -0,0 +1,688 @@
|
|
|
+import { ActionSheet, Button, Image, Popup, Swipe, SwipeItem } from 'vant';
|
|
|
+import {
|
|
|
+ computed,
|
|
|
+ defineComponent,
|
|
|
+ nextTick,
|
|
|
+ onMounted,
|
|
|
+ onUnmounted,
|
|
|
+ reactive,
|
|
|
+ watch,
|
|
|
+ ref
|
|
|
+} from 'vue';
|
|
|
+import { useRoute, useRouter } from 'vue-router';
|
|
|
+import styles from './index.module.less';
|
|
|
+import iconButtonList from '../images/icon-button-list.png';
|
|
|
+import MSticky from '@/components/m-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 ErrorMode from '../model/error-mode';
|
|
|
+import ResultFinish from '../model/result-finish';
|
|
|
+import { eventUnit, QuestionType } from '../unit';
|
|
|
+import request from '@/helpers/request';
|
|
|
+import { useRect } from '@vant/use';
|
|
|
+import MHeader from '@/components/m-header';
|
|
|
+import { useEventListener, useInterval, useWindowScroll } from '@vueuse/core';
|
|
|
+
|
|
|
+export default defineComponent({
|
|
|
+ name: 'unit-detail',
|
|
|
+ setup() {
|
|
|
+ const route = useRoute();
|
|
|
+ const router = useRouter();
|
|
|
+ const swipeRef = ref();
|
|
|
+ const state = reactive({
|
|
|
+ background: 'transparent',
|
|
|
+ color: '#fff',
|
|
|
+ visiableError: false,
|
|
|
+ visiableAnswer: false,
|
|
|
+ id: route.query.id,
|
|
|
+ currentIndex: 0,
|
|
|
+ questionList: [] as any,
|
|
|
+ page: 1,
|
|
|
+ rows: 10,
|
|
|
+ total: 0,
|
|
|
+ isFinish: false, // 是否完成加载
|
|
|
+ visiableInfo: {
|
|
|
+ show: false,
|
|
|
+ operationType: 'RESULT' as 'RESULT' | 'BACK' | 'CONTINUE' | 'GRASP',
|
|
|
+ type: 'DEFAULT' as 'DEFAULT' | 'FAIL' | 'PASS' | 'GOOD' | 'COUNTDOWN',
|
|
|
+ content: '',
|
|
|
+ showCancelButton: false,
|
|
|
+ confirmButtonText: '',
|
|
|
+ cancelButtonText: '',
|
|
|
+ title: '',
|
|
|
+ graspItem: {} as any
|
|
|
+ },
|
|
|
+ nextStatus: false,
|
|
|
+ swipeHeight: 'auto' as any,
|
|
|
+ answerAnalysis: '',
|
|
|
+ questionTypeCode: '',
|
|
|
+ overResult: {
|
|
|
+ time: '00:00', // 时长
|
|
|
+ questionLength: 0, // 答题数
|
|
|
+ errorLength: 0, // 错题数
|
|
|
+ rate: 0 // 正确率
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ // 计时
|
|
|
+ const { counter, resume, pause } = useInterval(1000, { controls: true });
|
|
|
+
|
|
|
+ const getExamDetails = async () => {
|
|
|
+ try {
|
|
|
+ const { data } = await request.post(
|
|
|
+ '/edu-app/studentUnitExamination/errorEdition',
|
|
|
+ {
|
|
|
+ data: {
|
|
|
+ page: state.page,
|
|
|
+ rows: state.rows
|
|
|
+ }
|
|
|
+ }
|
|
|
+ );
|
|
|
+ const temp = data || {};
|
|
|
+ state.total = temp.total || 0;
|
|
|
+ state.isFinish = temp.current < temp.pages ? false : true;
|
|
|
+ temp.records.forEach((item: any) => {
|
|
|
+ item.showAnalysis = false; // 默认不显示解析
|
|
|
+ item.grasp = false; // 是否掌握题目
|
|
|
+ item.analysis = {
|
|
|
+ message: item.answerAnalysis,
|
|
|
+ topic: true, // 是否显示结果
|
|
|
+ userResult: false // 用户答题对错
|
|
|
+ };
|
|
|
+ item.userAnswer = []; // 用户答题
|
|
|
+ });
|
|
|
+ state.questionList.push(...(temp.records || []));
|
|
|
+ } catch {
|
|
|
+ //
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ // 监听索引
|
|
|
+ watch(
|
|
|
+ () => state.currentIndex,
|
|
|
+ () => {
|
|
|
+ console.log(state.currentIndex, 'index');
|
|
|
+ // 判断是否在倒数第三题,并且没有加载完
|
|
|
+ if (
|
|
|
+ state.currentIndex + 3 >= state.questionList.length &&
|
|
|
+ !state.isFinish
|
|
|
+ ) {
|
|
|
+ state.page = state.page + 1;
|
|
|
+ getExamDetails();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ );
|
|
|
+
|
|
|
+ /** 已掌握此题 */
|
|
|
+ const onGraspQuestion = async (item: any) => {
|
|
|
+ // 判断是否掌握此题
|
|
|
+ if (item.grasp) return;
|
|
|
+ state.visiableInfo.show = true;
|
|
|
+ state.visiableInfo.title = '确定掌握此题?';
|
|
|
+ state.visiableInfo.showCancelButton = true;
|
|
|
+ state.visiableInfo.operationType = 'GRASP';
|
|
|
+ state.visiableInfo.cancelButtonText = '取消';
|
|
|
+ state.visiableInfo.confirmButtonText = '确定';
|
|
|
+ state.visiableInfo.content = `你确定已掌握该题知识要点,此题将移除你的错题集。`;
|
|
|
+ state.visiableInfo.graspItem = item;
|
|
|
+ };
|
|
|
+
|
|
|
+ /** 已掌握此题确认 */
|
|
|
+ const onGraspQuestionConfirm = async () => {
|
|
|
+ try {
|
|
|
+ state.visiableInfo.show = false;
|
|
|
+ await request.get('/edu-app/studentExaminationErrorEdition/del', {
|
|
|
+ hideLoading: false,
|
|
|
+ params: {
|
|
|
+ studentExaminationErrorEditionId:
|
|
|
+ state.visiableInfo.graspItem.studentExaminationErrorEditionId
|
|
|
+ }
|
|
|
+ });
|
|
|
+ state.visiableInfo.graspItem.grasp = true;
|
|
|
+ } catch {
|
|
|
+ //
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @description 下一题 | 测试完成
|
|
|
+ */
|
|
|
+ const onNextQuestion = async () => {
|
|
|
+ try {
|
|
|
+ const questionList = state.questionList || [];
|
|
|
+
|
|
|
+ let result: any = {};
|
|
|
+ questionList.forEach((question: any, index: number) => {
|
|
|
+ // 格式化所有题目的答案
|
|
|
+ if (index === state.currentIndex) {
|
|
|
+ result = {
|
|
|
+ questionId: question.id,
|
|
|
+ details: question.userAnswer || []
|
|
|
+ };
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ const { data } = await request.post(
|
|
|
+ '/edu-app/studentUnitExamination/submitTrainingAnswer',
|
|
|
+ {
|
|
|
+ hideLoading: true,
|
|
|
+ data: result
|
|
|
+ }
|
|
|
+ );
|
|
|
+ // 初始化是否显示解析
|
|
|
+ questionList.forEach((question: any, index: number) => {
|
|
|
+ // 格式化所有题目的答案
|
|
|
+ if (index === state.currentIndex) {
|
|
|
+ state.answerAnalysis = question.answerAnalysis;
|
|
|
+ state.questionTypeCode = question.questionTypeCode;
|
|
|
+ question.showAnalysis = true;
|
|
|
+ question.analysis.userResult = data;
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ // 判断是否是最后一题
|
|
|
+ if (state.questionList.length === state.currentIndex + 1) {
|
|
|
+ eventUnit.emit('unitAudioStop');
|
|
|
+ state.visiableInfo.show = true;
|
|
|
+ state.visiableInfo.title = '练习完成';
|
|
|
+ state.visiableInfo.showCancelButton = true;
|
|
|
+ state.visiableInfo.operationType = 'CONTINUE';
|
|
|
+ state.visiableInfo.cancelButtonText = '再等等';
|
|
|
+ state.visiableInfo.confirmButtonText = '确认完成';
|
|
|
+ state.visiableInfo.content = `确认本次练习的题目都完成了吗?`;
|
|
|
+
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (data) {
|
|
|
+ swipeRef.value?.next();
|
|
|
+ } else {
|
|
|
+ state.visiableError = true;
|
|
|
+ }
|
|
|
+ } catch {
|
|
|
+ //
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ //
|
|
|
+ const getAnswerResult = computed(() => {
|
|
|
+ const questionList = state.questionList || [];
|
|
|
+ let count = 0;
|
|
|
+ let passCount = 0;
|
|
|
+ let noPassCount = 0;
|
|
|
+ questionList.forEach((item: any) => {
|
|
|
+ if (item.showAnalysis) {
|
|
|
+ count += 1;
|
|
|
+ if (item.analysis.userResult) {
|
|
|
+ passCount += 1;
|
|
|
+ } else {
|
|
|
+ noPassCount += 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ return {
|
|
|
+ count,
|
|
|
+ passCount,
|
|
|
+ noPassCount
|
|
|
+ };
|
|
|
+ });
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @description 重置当前的题目高度
|
|
|
+ * @param {any} scroll 是否滚动到顶部
|
|
|
+ */
|
|
|
+ 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) => {
|
|
|
+ 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);
|
|
|
+ });
|
|
|
+ };
|
|
|
+
|
|
|
+ const onConfirmResult = () => {
|
|
|
+ if (state.visiableInfo.operationType === 'RESULT') {
|
|
|
+ state.visiableInfo.show = false;
|
|
|
+ onAfter();
|
|
|
+ } else if (state.visiableInfo.operationType === 'BACK') {
|
|
|
+ state.visiableInfo.show = false;
|
|
|
+ onAfter();
|
|
|
+ } else if (state.visiableInfo.operationType === 'CONTINUE') {
|
|
|
+ onResultPopup();
|
|
|
+ } else if (state.visiableInfo.operationType === 'GRASP') {
|
|
|
+ onGraspQuestionConfirm();
|
|
|
+ }
|
|
|
+ };
|
|
|
+ const onCloseResult = async () => {
|
|
|
+ const operationType = state.visiableInfo.operationType;
|
|
|
+ if (operationType === 'RESULT') {
|
|
|
+ } else if (operationType === 'BACK') {
|
|
|
+ state.visiableInfo.show = false;
|
|
|
+ window.history.pushState(null, '', document.URL);
|
|
|
+ window.addEventListener('popstate', onBack, false);
|
|
|
+ } else if (operationType === 'CONTINUE' || operationType === 'GRASP') {
|
|
|
+ state.visiableInfo.show = false;
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ /** 结果页面弹窗 */
|
|
|
+ const onResultPopup = () => {
|
|
|
+ const answerResult = getAnswerResult.value;
|
|
|
+ let rate = 0;
|
|
|
+
|
|
|
+ if (answerResult.count > 0) {
|
|
|
+ rate = Math.floor((answerResult.passCount / answerResult.count) * 100);
|
|
|
+ }
|
|
|
+
|
|
|
+ const times = counter.value;
|
|
|
+ const minute =
|
|
|
+ Math.floor(times / 60) >= 10
|
|
|
+ ? Math.floor(times / 60)
|
|
|
+ : '0' + Math.floor(times / 60);
|
|
|
+ const seconds = times % 60 >= 10 ? times % 60 : '0' + (times % 60);
|
|
|
+ state.overResult = {
|
|
|
+ time: minute + ':' + seconds, // 时长
|
|
|
+ questionLength: answerResult.count, // 答题数
|
|
|
+ errorLength: answerResult.noPassCount, // 错题数
|
|
|
+ rate // 正确率
|
|
|
+ };
|
|
|
+ // 重置计时
|
|
|
+ pause();
|
|
|
+ counter.value = 0;
|
|
|
+
|
|
|
+ // 60 及格
|
|
|
+ // 85 及以上优秀
|
|
|
+ state.visiableInfo.show = true;
|
|
|
+ state.visiableInfo.title = '已完成';
|
|
|
+ state.visiableInfo.showCancelButton = false;
|
|
|
+ state.visiableInfo.operationType = 'RESULT';
|
|
|
+ state.visiableInfo.confirmButtonText = '确认';
|
|
|
+ state.visiableInfo.content = `<div>您已完成本次测试,答对<span class='${
|
|
|
+ styles.right
|
|
|
+ }'>${answerResult.passCount}</span>,答错<span class='${styles.error}'>${
|
|
|
+ answerResult.count - answerResult.passCount
|
|
|
+ }</span>,正确率${rate}%~</div>`;
|
|
|
+ };
|
|
|
+
|
|
|
+ // 拦截
|
|
|
+ const onBack = () => {
|
|
|
+ const answerResult = getAnswerResult.value;
|
|
|
+ state.visiableInfo.show = true;
|
|
|
+ state.visiableInfo.title = '确认退出吗?';
|
|
|
+ state.visiableInfo.showCancelButton = true;
|
|
|
+ state.visiableInfo.operationType = 'BACK';
|
|
|
+ state.visiableInfo.cancelButtonText = '取消';
|
|
|
+ state.visiableInfo.confirmButtonText = '确定';
|
|
|
+ state.visiableInfo.content = `您已经完成${
|
|
|
+ answerResult.passCount + answerResult.noPassCount
|
|
|
+ }道题了,继续做题可以巩固所学知识哦~`;
|
|
|
+ eventUnit.emit('unitAudioStop');
|
|
|
+ };
|
|
|
+
|
|
|
+ const onAfter = () => {
|
|
|
+ window.removeEventListener('popstate', onBack, false);
|
|
|
+ router.back();
|
|
|
+ };
|
|
|
+
|
|
|
+ onMounted(async () => {
|
|
|
+ useEventListener(document, 'scroll', () => {
|
|
|
+ const { y } = useWindowScroll();
|
|
|
+ if (y.value > 52) {
|
|
|
+ state.background = '#fff';
|
|
|
+ state.color = '#323333';
|
|
|
+ } else {
|
|
|
+ state.background = 'transparent';
|
|
|
+ state.color = '#fff';
|
|
|
+ }
|
|
|
+ });
|
|
|
+ await getExamDetails();
|
|
|
+
|
|
|
+ resizeSwipeItemHeight();
|
|
|
+
|
|
|
+ // window.history.pushState(null, '', document.URL);
|
|
|
+ // window.addEventListener('popstate', onBack, false);
|
|
|
+ });
|
|
|
+
|
|
|
+ onUnmounted(() => {
|
|
|
+ // 关闭所有音频
|
|
|
+ eventUnit.emit('unitAudioStop');
|
|
|
+ });
|
|
|
+ return () => (
|
|
|
+ <div class={styles.unitDetail}>
|
|
|
+ <MSticky position="top">
|
|
|
+ <MHeader
|
|
|
+ border={false}
|
|
|
+ background={state.background}
|
|
|
+ color={state.color}
|
|
|
+ />
|
|
|
+ </MSticky>
|
|
|
+ <Swipe
|
|
|
+ loop={false}
|
|
|
+ showIndicators={false}
|
|
|
+ ref={swipeRef}
|
|
|
+ duration={300}
|
|
|
+ touchable={false}
|
|
|
+ class={styles.unitSwipe}
|
|
|
+ style={{ paddingBottom: '12px' }}
|
|
|
+ lazyRender
|
|
|
+ height={state.swipeHeight}
|
|
|
+ onChange={(index: number) => {
|
|
|
+ eventUnit.emit('unitAudioStop');
|
|
|
+ state.currentIndex = index;
|
|
|
+ resizeSwipeItemHeight();
|
|
|
+ }}>
|
|
|
+ {state.questionList.map((item: any, index: number) => (
|
|
|
+ <SwipeItem>
|
|
|
+ <div class="swipe-item-question">
|
|
|
+ {item.questionTypeCode === QuestionType.RADIO && (
|
|
|
+ <ChoiceQuestion
|
|
|
+ v-model:value={item.userAnswer}
|
|
|
+ index={index + 1}
|
|
|
+ data={item}
|
|
|
+ type="radio"
|
|
|
+ showAnalysis={item.showAnalysis}
|
|
|
+ analysis={item.analysis}>
|
|
|
+ {{
|
|
|
+ title: () => (
|
|
|
+ <div class={styles.questionTitle}>
|
|
|
+ <div class={styles.questionNum}>
|
|
|
+ <span>{state.currentIndex + 1}</span>/{state.total}
|
|
|
+ </div>
|
|
|
+ {/* <div class={styles.questionType}>
|
|
|
+ <i></i>
|
|
|
+ <span>{item.knowledgePointName}</span>
|
|
|
+ </div> */}
|
|
|
+ <Button
|
|
|
+ round
|
|
|
+ plain
|
|
|
+ size="mini"
|
|
|
+ color={item.grasp ? '#FF5A56' : '#1CACF1'}
|
|
|
+ class={styles.controlBtn}
|
|
|
+ disabled={item.grasp}
|
|
|
+ onClick={() => onGraspQuestion(item)}>
|
|
|
+ {item.grasp ? '已掌握此题' : '掌握此题'}
|
|
|
+ </Button>
|
|
|
+ </div>
|
|
|
+ )
|
|
|
+ }}
|
|
|
+ </ChoiceQuestion>
|
|
|
+ )}
|
|
|
+ {item.questionTypeCode === QuestionType.CHECKBOX && (
|
|
|
+ <ChoiceQuestion
|
|
|
+ v-model:value={item.userAnswer}
|
|
|
+ index={index + 1}
|
|
|
+ data={item}
|
|
|
+ type="checkbox"
|
|
|
+ showAnalysis={item.showAnalysis}
|
|
|
+ analysis={item.analysis}>
|
|
|
+ {{
|
|
|
+ title: () => (
|
|
|
+ <div class={styles.questionTitle}>
|
|
|
+ <div class={styles.questionNum}>
|
|
|
+ <span>{state.currentIndex + 1}</span>/{state.total}
|
|
|
+ </div>
|
|
|
+ {/* <div class={styles.questionType}>
|
|
|
+ <i></i>
|
|
|
+ <span>{item.knowledgePointName}</span>
|
|
|
+ </div> */}
|
|
|
+ <Button
|
|
|
+ round
|
|
|
+ plain
|
|
|
+ size="mini"
|
|
|
+ color={item.grasp ? '#FF5A56' : '#1CACF1'}
|
|
|
+ class={styles.controlBtn}
|
|
|
+ disabled={item.grasp}
|
|
|
+ onClick={() => onGraspQuestion(item)}>
|
|
|
+ {item.grasp ? '已掌握此题' : '掌握此题'}
|
|
|
+ </Button>
|
|
|
+ </div>
|
|
|
+ )
|
|
|
+ }}
|
|
|
+ </ChoiceQuestion>
|
|
|
+ )}
|
|
|
+ {item.questionTypeCode === QuestionType.SORT && (
|
|
|
+ <DragQuestion
|
|
|
+ v-model:value={item.userAnswer}
|
|
|
+ onUpdate:value={() => {
|
|
|
+ // 如果是空则滑动到顶部
|
|
|
+ const status =
|
|
|
+ item.userAnswer && item.userAnswer.length > 0
|
|
|
+ ? false
|
|
|
+ : true;
|
|
|
+ resizeSwipeItemHeight(status);
|
|
|
+ }}
|
|
|
+ data={item}
|
|
|
+ index={index + 1}
|
|
|
+ showAnalysis={item.showAnalysis}
|
|
|
+ analysis={item.analysis}>
|
|
|
+ {{
|
|
|
+ title: () => (
|
|
|
+ <div class={styles.questionTitle}>
|
|
|
+ <div class={styles.questionNum}>
|
|
|
+ <span>{state.currentIndex + 1}</span>/{state.total}
|
|
|
+ </div>
|
|
|
+ {/* <div class={styles.questionType}>
|
|
|
+ <i></i>
|
|
|
+ <span>{item.knowledgePointName}</span>
|
|
|
+ </div> */}
|
|
|
+ <Button
|
|
|
+ round
|
|
|
+ plain
|
|
|
+ size="mini"
|
|
|
+ color={item.grasp ? '#FF5A56' : '#1CACF1'}
|
|
|
+ class={styles.controlBtn}
|
|
|
+ disabled={item.grasp}
|
|
|
+ onClick={() => onGraspQuestion(item)}>
|
|
|
+ {item.grasp ? '已掌握此题' : '掌握此题'}
|
|
|
+ </Button>
|
|
|
+ </div>
|
|
|
+ )
|
|
|
+ }}
|
|
|
+ </DragQuestion>
|
|
|
+ )}
|
|
|
+ {item.questionTypeCode === QuestionType.LINK && (
|
|
|
+ <KeepLookQuestion
|
|
|
+ v-model:value={item.userAnswer}
|
|
|
+ data={item}
|
|
|
+ index={index + 1}
|
|
|
+ showAnalysis={item.showAnalysis}
|
|
|
+ analysis={item.analysis}>
|
|
|
+ {{
|
|
|
+ title: () => (
|
|
|
+ <div class={styles.questionTitle}>
|
|
|
+ <div class={styles.questionNum}>
|
|
|
+ <span>{state.currentIndex + 1}</span>/{state.total}
|
|
|
+ </div>
|
|
|
+ {/* <div class={styles.questionType}>
|
|
|
+ <i></i>
|
|
|
+ <span>{item.knowledgePointName}</span>
|
|
|
+ </div> */}
|
|
|
+ <Button
|
|
|
+ round
|
|
|
+ plain
|
|
|
+ size="mini"
|
|
|
+ color={item.grasp ? '#FF5A56' : '#1CACF1'}
|
|
|
+ class={styles.controlBtn}
|
|
|
+ disabled={item.grasp}
|
|
|
+ onClick={() => onGraspQuestion(item)}>
|
|
|
+ {item.grasp ? '已掌握此题' : '掌握此题'}
|
|
|
+ </Button>
|
|
|
+ </div>
|
|
|
+ )
|
|
|
+ }}
|
|
|
+ </KeepLookQuestion>
|
|
|
+ )}
|
|
|
+ {item.questionTypeCode === QuestionType.PLAY && (
|
|
|
+ <PlayQuestion
|
|
|
+ v-model:value={item.userAnswer}
|
|
|
+ data={item}
|
|
|
+ index={index + 1}
|
|
|
+ unitId={state.id as any}
|
|
|
+ showAnalysis={item.showAnalysis}
|
|
|
+ analysis={item.analysis}>
|
|
|
+ {{
|
|
|
+ title: () => (
|
|
|
+ <div class={styles.questionTitle}>
|
|
|
+ <div class={styles.questionNum}>
|
|
|
+ <span>{state.currentIndex + 1}</span>/{state.total}
|
|
|
+ </div>
|
|
|
+ {/* <div class={styles.questionType}>
|
|
|
+ <i></i>
|
|
|
+ <span>{item.knowledgePointName}</span>
|
|
|
+ </div> */}
|
|
|
+ <Button
|
|
|
+ round
|
|
|
+ plain
|
|
|
+ size="mini"
|
|
|
+ color={item.grasp ? '#FF5A56' : '#1CACF1'}
|
|
|
+ disabled={item.grasp}
|
|
|
+ class={styles.controlBtn}
|
|
|
+ onClick={() => onGraspQuestion(item)}>
|
|
|
+ {item.grasp ? '已掌握此题' : '掌握此题'}
|
|
|
+ </Button>
|
|
|
+ </div>
|
|
|
+ )
|
|
|
+ }}
|
|
|
+ </PlayQuestion>
|
|
|
+ )}
|
|
|
+ </div>
|
|
|
+ </SwipeItem>
|
|
|
+ ))}
|
|
|
+ </Swipe>
|
|
|
+
|
|
|
+ <MSticky position="bottom">
|
|
|
+ <div class={['btnGroup btnMore', styles.btnSection]}>
|
|
|
+ <Button
|
|
|
+ round
|
|
|
+ block
|
|
|
+ class={
|
|
|
+ state.currentIndex > 0 ? styles.activePrevBtn : styles.prevBtn
|
|
|
+ }
|
|
|
+ disabled={state.currentIndex > 0 ? false : true}
|
|
|
+ onClick={() => {
|
|
|
+ swipeRef.value?.prev();
|
|
|
+ }}>
|
|
|
+ 上一题
|
|
|
+ </Button>
|
|
|
+ <Button
|
|
|
+ block
|
|
|
+ round
|
|
|
+ class={styles.nextBtn}
|
|
|
+ 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>
|
|
|
+ </MSticky>
|
|
|
+
|
|
|
+ {/* 题目集合 */}
|
|
|
+ <ActionSheet
|
|
|
+ v-model:show={state.visiableAnswer}
|
|
|
+ title="题目列表"
|
|
|
+ safeAreaInsetBottom>
|
|
|
+ <AnswerList
|
|
|
+ value={state.questionList}
|
|
|
+ lookType={'PRACTICE'}
|
|
|
+ statusList={[
|
|
|
+ {
|
|
|
+ text: '答对',
|
|
|
+ color: '#1CACF1'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ text: '答错',
|
|
|
+ color: '#FF8486'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ text: '未答',
|
|
|
+ color: '#EAEAEA'
|
|
|
+ }
|
|
|
+ ]}
|
|
|
+ onSelect={(item: any) => {
|
|
|
+ // 跳转,并且跳过动画
|
|
|
+ swipeRef.value?.swipeTo(item, {
|
|
|
+ immediate: true
|
|
|
+ });
|
|
|
+ state.visiableAnswer = false;
|
|
|
+ }}
|
|
|
+ />
|
|
|
+ </ActionSheet>
|
|
|
+
|
|
|
+ <Popup
|
|
|
+ v-model:show={state.visiableError}
|
|
|
+ style={{ width: '90%' }}
|
|
|
+ round
|
|
|
+ closeOnClickOverlay={false}>
|
|
|
+ <ErrorMode
|
|
|
+ onClose={() => (state.visiableError = false)}
|
|
|
+ answerAnalysis={state.answerAnalysis}
|
|
|
+ questionTypeCode={state.questionTypeCode}
|
|
|
+ onConform={() => {
|
|
|
+ swipeRef.value?.next();
|
|
|
+ state.answerAnalysis = '';
|
|
|
+ }}
|
|
|
+ />
|
|
|
+ </Popup>
|
|
|
+
|
|
|
+ <Popup
|
|
|
+ v-model:show={state.visiableInfo.show}
|
|
|
+ closeOnClickOverlay={false}
|
|
|
+ style={{
|
|
|
+ background: 'transparent',
|
|
|
+ width: '100%',
|
|
|
+ maxWidth: '100%',
|
|
|
+ transform: 'translateY(-55%)'
|
|
|
+ }}>
|
|
|
+ <ResultFinish
|
|
|
+ title={state.visiableInfo.title}
|
|
|
+ showCancelButton={state.visiableInfo.showCancelButton}
|
|
|
+ cancelButtonText={state.visiableInfo.cancelButtonText}
|
|
|
+ confirmButtonText={state.visiableInfo.confirmButtonText}
|
|
|
+ status={state.visiableInfo.type}
|
|
|
+ content={state.visiableInfo.content}
|
|
|
+ contentHtml
|
|
|
+ onConform={onConfirmResult}
|
|
|
+ onClose={onCloseResult}
|
|
|
+ />
|
|
|
+ </Popup>
|
|
|
+ </div>
|
|
|
+ );
|
|
|
+ }
|
|
|
+});
|