| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450 |
- <template>
- <ie-page :fix-height="true" :safe-area-inset-bottom="false">
- <block v-if="isReady">
- <exam-navbar :total-exam-time="totalExamTime" @left-click="handleLeftClick" @right-click="handleRightClick" />
- <exam-subtitle />
- <exam-swiper @submit="beforeSubmit" />
- <exam-toolbar @submit="beforeSubmit" />
- </block>
- </ie-page>
- <fast-guide v-model:show="guideShow" :list="guideList" v-model:index="guideIndex"
- @close="handleGuideClose"></fast-guide>
- <question-swiper-tip :visible="showSwiperTip" @next="handleSwiperTipNext" />
- <exam-mode ref="examModeRef" />
- </template>
- <script lang="ts" setup>
- import ExamNavbar from './components/exam-navbar.vue';
- import ExamSubtitle from './components/exam-subtitle.vue';
- import ExamSwiper from './components/exam-swiper.vue';
- import ExamToolbar from './components/exam-toolbar.vue';
- import ExamMode from './components/exam-mode.vue';
- import QuestionSwiperTip from './components/question-swiper-tip.vue';
- import { useTransferPage } from '@/hooks/useTransferPage';
- import { useUserStore } from '@/store/userStore';
- import { EnumPaperType, EnumQuestionType } from '@/common/enum';
- import { getOpenExaminee, getPaper, commitExamineePaper, beginExaminee, getExamineeResult } from '@/api/modules/study';
- import { useExam } from '@/composables/useExam';
- import { Study, Transfer } from '@/types';
- import {
- EXAM_AUTO_SUBMIT,
- EXAM_PAGE_OPTIONS,
- EXAM_DATA
- } from '@/types/injectionSymbols';
- const userStore = useUserStore();
- // import { Examinee, ExamPaper, ExamPaperSubmit } from '@/types/study';
- const { prevData, transferBack, transferTo } = useTransferPage<Transfer.ExamAnalysisPageOptions, {}>();
- const examData = useExam();
- const { setQuestionList, questionList, flatQuestionList, setSubQuestionIndex,
- notDoneCount, isAllDone,
- practiceDuration, startTiming, stopTiming, submit, changeIndex, setDuration } = examData;
- //
- const showSwiperTip = ref(false);
- const guideShow = ref(false);
- const guideList = ref([
- {
- target: '#question-calendar-btn',
- position: 'top',
- msg: '[答题卡]\n查看答题卡,掌握考试进度'
- },
- {
- target: '#question-favorite-btn',
- position: 'top',
- msg: '[题目收藏]\n收藏的题目可以在收藏夹查看'
- },
- {
- target: '#question-mark-btn',
- position: 'top',
- msg: '[题目标记]\n标记的题目可以在答题卡中快速找到'
- },
- {
- target: '#question-correct-btn',
- position: 'top',
- msg: '[试题纠错]\n点击试题纠错,帮助我们改进题目'
- }
- ]);
- const guideIndex = ref(0);
- const isReady = ref(false);
- // 考试规定时间
- const totalExamTime = ref<number>(0);
- // 自动提交只提醒1次
- const hasShowSubmitConfirm = ref(false);
- const examineeId = ref<number | undefined>(undefined);
- const paperData = ref<Study.ExamPaper>({} as Study.ExamPaper);
- // 是否确认退出
- const confirmQuit = ref(false);
- const confirmShowing = ref(false);
- /**
- * 自动提交
- */
- const autoSubmit = () => {
- if (hasShowSubmitConfirm.value) {
- return;
- }
- hasShowSubmitConfirm.value = true;
- beforeSubmit();
- }
- provide(EXAM_PAGE_OPTIONS, prevData.value);
- provide(EXAM_DATA, examData);
- provide(EXAM_AUTO_SUBMIT, autoSubmit);
- const isPracticeExam = computed(() => {
- return prevData.value.paperType === EnumPaperType.PRACTICE || prevData.value.paperType === EnumPaperType.COURSE;
- });
- const isSimulationExam = computed(() => {
- // prevData.value
- return prevData.value.paperType === EnumPaperType.SIMULATED;
- });
- const isTestExam = computed(() => {
- return prevData.value.paperType === EnumPaperType.TEST;
- });
- const isReadOnly = computed(() => {
- return prevData.value.readonly || false;
- });
- const handleLeftClick = () => {
- if (!isReady.value || isReadOnly.value) {
- confirmQuit.value = true;
- transferBack();
- return;
- }
- beforeQuit();
- };
- const examModeRef = ref();
- const handleRightClick = () => {
- examModeRef.value.open();
- }
- const beforeQuit = () => {
- const { paperType } = prevData.value;
- if (!isReady.value || isReadOnly.value) {
- return;
- }
- stopTime();
- const msg = paperType === EnumPaperType.PRACTICE ? '当前练习未完成,确认退出?' : '当前考试未完成,确认退出?';
- confirmShowing.value = true;
- uni.$ie.showModal({
- title: '提示',
- content: msg,
- }).then(confirm => {
- if (confirm) {
- handleSubmit(true);
- } else {
- confirmQuit.value = false;
- confirmShowing.value = false;
- startTime();
- }
- });
- };
- const startTime = () => {
- startTiming();
- }
- const stopTime = () => {
- stopTiming();
- }
- const beforeSubmit = async () => {
- const text = notDoneCount.value > 0 ? `还有${notDoneCount.value}题未做,确认交卷?` : '是否确认交卷?';
- stopTime();
- uni.$ie.showModal({
- title: '提示',
- content: text,
- }).then(confirm => {
- if (confirm) {
- handleSubmit(false);
- } else {
- startTime();
- }
- });
- }
- /**
- * 提交试卷
- * @param tempSave 是否临时保存
- */
- const handleSubmit = (tempSave: boolean = false) => {
- // 执行完后续逻辑
- submit();
- const msg = tempSave ? '保存中...' : '提交中...';
- uni.$ie.showLoading(msg);
- setTimeout(async () => {
- const params: Study.ExamPaperSubmit = {
- ...paperData.value,
- questions: questionList.value.map(item => {
- return {
- ...item,
- title: '',
- isDone: tempSave ? item.isDone : true,
- subQuestions: item.subQuestions.map(subItem => {
- return {
- ...subItem,
- title: '',
- };
- })
- };
- }),
- examineeId: examineeId.value,
- // examineeId: examineerData.value.examineeId,
- isDone: tempSave ? isAllDone.value : true,
- duration: practiceDuration.value
- };
- console.log('提交试卷参数', params)
- await commitExamineePaper(params);
- if (isSimulationExam.value || isTestExam.value) {
- if (!tempSave) {
- setTimeout(async () => {
- uni.$ie.hideLoading();
- await nextTick();
- confirmQuit.value = true;
- confirmShowing.value = false;
- transferTo('/pagesStudy/pages/simulation-analysis/simulation-analysis', {
- data: {
- examineeId: examineeId.value,
- paperType: prevData.value.paperType
- } as Transfer.SimulationAnalysisPageOptions,
- type: 'redirectTo'
- });
- }, 2500);
- } else {
- uni.$ie.hideLoading();
- confirmQuit.value = true;
- confirmShowing.value = false;
- nextTick(() => {
- transferBack();
- });
- }
- } else if (isPracticeExam.value) {
- if (!tempSave) {
- setTimeout(async () => {
- uni.$ie.hideLoading();
- await nextTick();
- confirmQuit.value = true;
- confirmShowing.value = false;
- transferTo('/pagesStudy/pages/knowledge-practice-detail/knowledge-practice-detail', {
- data: {
- paperType: prevData.value.paperType,
- examineeId: examineeId.value,
- name: prevData.value.practiceInfo?.name,
- directed: prevData.value.practiceInfo?.directed,
- questionType: prevData.value.practiceInfo?.questionType
- } as Transfer.PracticeResultPageOptions,
- type: 'redirectTo'
- });
- }, 2500);
- } else {
- uni.$ie.hideLoading();
- confirmQuit.value = true;
- confirmShowing.value = false;
- nextTick(() => {
- transferBack();
- });
- }
- }
- }, 300);
- }
- /**
- * 恢复上次做题历史数据
- * @param savedQuestion 上次做题历史数据
- * @param fullQuestion 当前试卷数据
- */
- const restoreQuestion = (savedQuestion: Study.ExamineeQuestion[], fullQuestion: Study.ExamineeQuestion[]) => {
- if (!savedQuestion) {
- return fullQuestion;
- }
- for (let index = 0; index < fullQuestion.length; index++) {
- const item = fullQuestion[index];
- const savedQs = savedQuestion[index]
- if (savedQs) {
- if (savedQs.answers) {
- item.answers = savedQs.answers.filter(ans => ans.trim());
- }
- item.answer1 = savedQs.answer1;
- item.answer2 = savedQs.answer2;
- item.isMark = savedQs.isMark;
- item.isFavorite = savedQs.isFavorite;
- item.isNotKnow = savedQs.isNotKnow;
- item.parse = savedQs.parse;
- item.totalScore = savedQs.totalScore;
- if (item.subQuestions) {
- restoreQuestion(savedQs.subQuestions, item.subQuestions);
- }
- }
- }
- return fullQuestion;
- }
- // 1、加载知识点练习数据
- const loadPracticeData = async () => {
- const { paperType, readonly, practiceInfo } = prevData.value;
- let data: Study.Examinee | null = null;
- if (readonly) {
- if (practiceInfo?.examineeId) {
- const res = await getExamineeResult(practiceInfo.examineeId);
- data = res.data;
- }
- } else {
- const params = {
- paperType: paperType,
- relateId: practiceInfo?.relateId,
- } as Study.OpenExamineeRequestDTO;
- if (userStore.isVHS) {
- params.questionType = practiceInfo?.questionType;
- } else {
- params.directed = practiceInfo?.directed || false;
- }
- const res = await getOpenExaminee(params);
- data = res.data || {};
- }
- if (!data) {
- uni.$ie.hideLoading();
- transferBack();
- return;
- }
- // 练习没有规定时间,设置为最大值
- totalExamTime.value = Number.MAX_SAFE_INTEGER;
- combinePaperData(data, paperType);
- }
- // 2、加载模拟考试数据
- const loadExamData = async () => {
- const { paperType, readonly, simulationInfo } = prevData.value;
- let data: Study.Examinee;
- if (simulationInfo?.examineeId) {
- if (readonly) {
- const res = await getExamineeResult(simulationInfo.examineeId);
- data = res.data;
- } else {
- const res = await beginExaminee(simulationInfo.examineeId);
- data = res.data || {};
- }
- if (!data) {
- uni.$ie.hideLoading();
- transferBack();
- return;
- }
- totalExamTime.value = data.paperInfo?.time || 0;
- combinePaperData(data, paperType);
- }
- }
- // 3、加载对口升学试卷数据
- const loadVHSPaperData = async () => {
- const { paperType, readonly, simulationInfo } = prevData.value;
- let data: Study.Examinee;
- if (simulationInfo?.examineeId) {
- if (readonly) {
- const res = await getExamineeResult(simulationInfo.examineeId);
- data = res.data;
- } else {
- const params = {
- paperType: paperType,
- relateId: simulationInfo?.examineeId,
- } as Study.OpenExamineeRequestDTO;
- const res = await getOpenExaminee(params);
- data = res.data || {};
- }
- if (!data) {
- uni.$ie.hideLoading();
- transferBack();
- return;
- }
- totalExamTime.value = data.paperInfo?.time || Number.MAX_SAFE_INTEGER;
- combinePaperData(data, paperType);
- }
- }
- const combinePaperData = async (examinee: Study.Examinee, paperType: EnumPaperType) => {
- examineeId.value = examinee.examineeId;
- if (examinee.paperId) {
- const res = await getPaper({
- type: paperType,
- id: examinee.paperId
- });
- paperData.value = res.data;
- paperData.value.questions = restoreQuestion(examinee.questions, res.data.questions);
- console.log('初始化数据', paperData.value.questions)
- setQuestionList(paperData.value.questions);
- setDuration(examinee.duration || 0);
- await nextTick();
- const targetQuestion = flatQuestionList.value.find(item => item.id === prevData.value.questionId);
- if (targetQuestion) {
- changeIndex(targetQuestion.index);
- } else {
- changeIndex(0);
- }
- setTimeout(() => {
- if (targetQuestion?.isSubQuestion) {
- setSubQuestionIndex(targetQuestion.subIndex || 0);
- }
- }, 50);
- await new Promise(resolve => setTimeout(resolve, 50));
- await nextTick();
- // 读取用户练习设置
- // setPracticeSettings(userStore.practiceSettings);
- isReady.value = true;
- console.log('试卷信息', res)
- if (!userStore.isExamGuideShow) {
- setTimeout(() => {
- uni.$ie.hideLoading();
- setTimeout(() => {
- showSwiperTip.value = true;
- }, 100);
- }, 300);
- } else {
- uni.$ie.hideLoading();
- if (!isReadOnly.value) {
- startTime();
- }
- }
- }
- }
- const handleSwiperTipNext = () => {
- showSwiperTip.value = false;
- guideShow.value = true;
- }
- const handleGuideClose = () => {
- userStore.isExamGuideShow = true;
- startTime();
- }
- const loadData = async () => {
- uni.$ie.showLoading();
- const { paperType } = prevData.value;
- if (paperType === EnumPaperType.PRACTICE || paperType === EnumPaperType.COURSE) {
- loadPracticeData();
- } else if (paperType === EnumPaperType.SIMULATED || paperType === EnumPaperType.TEST) {
- if (paperType === EnumPaperType.SIMULATED && userStore.isVHS) {
- loadVHSPaperData();
- } else {
- loadExamData();
- }
- }
- };
- onLoad(() => {
- console.log(prevData.value)
- loadData();
- uni.addInterceptor('navigateBack', {
- invoke: (e) => {
- if (confirmShowing.value) {
- return false;
- }
- if (confirmQuit.value) {
- return e;
- }
- handleLeftClick();
- return false;
- }
- })
- });
- onUnload(() => {
- uni.removeInterceptor('navigateBack');
- });
- </script>
- <style lang="scss" scoped></style>
|