|
@@ -1,14 +1,14 @@
|
|
|
<template>
|
|
<template>
|
|
|
<ie-page :fix-height="true" :safe-area-inset-bottom="false">
|
|
<ie-page :fix-height="true" :safe-area-inset-bottom="false">
|
|
|
<ie-navbar :title="pageTitle" custom-back @left-click="handleLeftClick">
|
|
<ie-navbar :title="pageTitle" custom-back @left-click="handleLeftClick">
|
|
|
- <template #headerRight>
|
|
|
|
|
|
|
+ <template v-if="isReady" #headerRight>
|
|
|
<view v-if="isExamMode" class="countdown-text" :class="{ 'text-red-500': examDuration < 30 }">
|
|
<view v-if="isExamMode" class="countdown-text" :class="{ 'text-red-500': examDuration < 30 }">
|
|
|
{{ formatExamDuration }}
|
|
{{ formatExamDuration }}
|
|
|
</view>
|
|
</view>
|
|
|
<view v-else class="">{{ formatPracticeDuration }}</view>
|
|
<view v-else class="">{{ formatPracticeDuration }}</view>
|
|
|
</template>
|
|
</template>
|
|
|
</ie-navbar>
|
|
</ie-navbar>
|
|
|
- <view class="px-20 py-14 bg-back flex justify-between items-center gap-x-20">
|
|
|
|
|
|
|
+ <view v-if="isReady" class="px-20 py-14 bg-back flex justify-between items-center gap-x-20">
|
|
|
<text class="flex-1 min-w-1 text-26 ellipsis-1">{{ pageSubtitle }}</text>
|
|
<text class="flex-1 min-w-1 text-26 ellipsis-1">{{ pageSubtitle }}</text>
|
|
|
<view class="flex items-baseline">
|
|
<view class="flex items-baseline">
|
|
|
<text class="text-34 text-primary font-bold">{{ currentIndex + 1 }}</text>/
|
|
<text class="text-34 text-primary font-bold">{{ currentIndex + 1 }}</text>/
|
|
@@ -26,7 +26,7 @@
|
|
|
</swiper>
|
|
</swiper>
|
|
|
</view>
|
|
</view>
|
|
|
</view>
|
|
</view>
|
|
|
- <ie-safe-toolbar :height="64" :shadow="false">
|
|
|
|
|
|
|
+ <ie-safe-toolbar v-if="isReady" :height="64" :shadow="false">
|
|
|
<view class="px-18 h-full flex items-center justify-around border-0 border-t border-solid border-[#EFEFEF]">
|
|
<view class="px-18 h-full flex items-center justify-around border-0 border-t border-solid border-[#EFEFEF]">
|
|
|
<view class="w-48 h-48 flex items-center justify-center" @click="handleFavorite">
|
|
<view class="w-48 h-48 flex items-center justify-center" @click="handleFavorite">
|
|
|
<uv-icon v-if="currentQuestion.isFavorite" name="star-fill" color="#FF9A18" size="27" />
|
|
<uv-icon v-if="currentQuestion.isFavorite" name="star-fill" color="#FF9A18" size="27" />
|
|
@@ -56,17 +56,20 @@
|
|
|
<scroll-view class="h-full" scroll-y>
|
|
<scroll-view class="h-full" scroll-y>
|
|
|
<view v-for="(item, i) in stateQuestionList" :key="i" class="">
|
|
<view v-for="(item, i) in stateQuestionList" :key="i" class="">
|
|
|
<template v-if="item.list.length > 0">
|
|
<template v-if="item.list.length > 0">
|
|
|
- <view class="h-60 bg-back px-20 leading-60 text-fore-subcontent">{{ questionTypeDesc[item.type] }}</view>
|
|
|
|
|
- <view class="grid grid-cols-5 place-items-center gap-x-20 gap-y-20">
|
|
|
|
|
- <view v-for="(qs, j) in item.list" :key="j" class="py-20 flex items-center justify-center">
|
|
|
|
|
|
|
+ <view class="h-70 bg-back px-20 leading-70 text-fore-subcontent">{{ questionTypeDesc[item.type] }}</view>
|
|
|
|
|
+ <view class="grid grid-cols-5 place-items-center gap-x-20 gap-y-20 p-30">
|
|
|
|
|
+ <view v-for="(qs, j) in item.list" :key="j" class="aspect-square flex items-center justify-center"
|
|
|
|
|
+ @click="hanadleNavigate(qs.index)">
|
|
|
<view
|
|
<view
|
|
|
- class="w-52 h-52 rounded-full flex items-center justify-center bg-white border border-solid border-border"
|
|
|
|
|
|
|
+ class="w-74 h-74 rounded-full flex items-center justify-center bg-white border border-solid border-border relative"
|
|
|
:class="{
|
|
:class="{
|
|
|
'is-done': qs.question.isDone,
|
|
'is-done': qs.question.isDone,
|
|
|
'is-not-know': qs.question.isNotKnow,
|
|
'is-not-know': qs.question.isNotKnow,
|
|
|
'is-mark': qs.question.isMark
|
|
'is-mark': qs.question.isMark
|
|
|
}">
|
|
}">
|
|
|
- {{ qs.index + 1 }}
|
|
|
|
|
|
|
+ <text>{{ qs.index + 1 }}</text>
|
|
|
|
|
+ <ie-image v-if="qs.question.isMark" src="/pagesStudy/static/image/icon-mark-active.png"
|
|
|
|
|
+ custom-class="absolute -top-20 right-16 w-32 h-32" mode="aspectFill" />
|
|
|
</view>
|
|
</view>
|
|
|
</view>
|
|
</view>
|
|
|
|
|
|
|
@@ -77,11 +80,11 @@
|
|
|
</scroll-view>
|
|
</scroll-view>
|
|
|
</view>
|
|
</view>
|
|
|
<view class="h-150 bg-white flex items-center gap-x-120 px-40">
|
|
<view class="h-150 bg-white flex items-center gap-x-120 px-40">
|
|
|
- <view class="flex flex-col items-center gap-x-10">
|
|
|
|
|
- <uv-icon name="reload" size="20" />
|
|
|
|
|
- <text class="mt-4 text-20 text-subcontent">重新作答</text>
|
|
|
|
|
|
|
+ <view class="flex flex-col items-center gap-x-10" @click="handleReset">
|
|
|
|
|
+ <uv-icon name="reload" size="20" :color="doneCount > 0 ? '#999' : '#cccccc'" />
|
|
|
|
|
+ <text class="mt-4 text-20 text-subcontent" :class="{ 'text-fore-light': doneCount <= 0 }">重新作答</text>
|
|
|
</view>
|
|
</view>
|
|
|
- <view class="flex-1 py-20 text-center rounded-full bg-primary text-white">交卷</view>
|
|
|
|
|
|
|
+ <view class="flex-1 py-20 text-center rounded-full bg-primary text-white" @click="beforeSubmit">交卷</view>
|
|
|
</view>
|
|
</view>
|
|
|
</view>
|
|
</view>
|
|
|
</question-stats-popup>
|
|
</question-stats-popup>
|
|
@@ -92,16 +95,17 @@ import QuestionItem from './components/question-item.vue';
|
|
|
import QuestionStatsPopup from './components/question-stats-popup.vue';
|
|
import QuestionStatsPopup from './components/question-stats-popup.vue';
|
|
|
import { useTransferPage } from '@/hooks/useTransferPage';
|
|
import { useTransferPage } from '@/hooks/useTransferPage';
|
|
|
import { EnumExamMode, EnumQuestionType } from '@/common/enum';
|
|
import { EnumExamMode, EnumQuestionType } from '@/common/enum';
|
|
|
-import { getOpenExaminee } from '@/api/modules/study';
|
|
|
|
|
|
|
+import { getOpenExaminee, getPaper, commitExamineePaper } from '@/api/modules/study';
|
|
|
import { useExam } from '@/composables/useExam';
|
|
import { useExam } from '@/composables/useExam';
|
|
|
import { Study } from '@/types';
|
|
import { Study } from '@/types';
|
|
|
import { NEXT_QUESTION, PREV_QUESTION, NEXT_QUESTION_QUICKLY, PREV_QUESTION_QUICKLY } from '@/types/injectionSymbols';
|
|
import { NEXT_QUESTION, PREV_QUESTION, NEXT_QUESTION_QUICKLY, PREV_QUESTION_QUICKLY } from '@/types/injectionSymbols';
|
|
|
-const { prevData } = useTransferPage();
|
|
|
|
|
-const { questionList, stateQuestionList, questionTypeDesc, favoriteList, notKnowList, markList, currentIndex,
|
|
|
|
|
|
|
+import { ExamPaper, ExamPaperSubmit } from '@/types/study';
|
|
|
|
|
+const { prevData, transferBack } = useTransferPage();
|
|
|
|
|
+const { setQuestionList, questionList, stateQuestionList, questionTypeDesc, favoriteList, notKnowList, markList, currentIndex,
|
|
|
totalCount, doneCount, notDoneCount, notKnowCount, markCount,
|
|
totalCount, doneCount, notDoneCount, notKnowCount, markCount,
|
|
|
loadExamData, nextQuestion, prevQuestion, nextQuestionQuickly, prevQuestionQuickly, swiperDuration,
|
|
loadExamData, nextQuestion, prevQuestion, nextQuestionQuickly, prevQuestionQuickly, swiperDuration,
|
|
|
formatPracticeDuration, formatExamDuration, practiceDuration, startPracticeDuration, stopPracticeDuration,
|
|
formatPracticeDuration, formatExamDuration, practiceDuration, startPracticeDuration, stopPracticeDuration,
|
|
|
- examDuration, startExamDuration, stopExamDuration, setExamDuration, setCountDownCallback } = useExam();
|
|
|
|
|
|
|
+ examDuration, startExamDuration, stopExamDuration, setExamDuration, setCountDownCallback, changeIndex, reset } = useExam();
|
|
|
|
|
|
|
|
provide(NEXT_QUESTION, nextQuestion);
|
|
provide(NEXT_QUESTION, nextQuestion);
|
|
|
provide(PREV_QUESTION, prevQuestion);
|
|
provide(PREV_QUESTION, prevQuestion);
|
|
@@ -111,6 +115,8 @@ provide(PREV_QUESTION_QUICKLY, prevQuestionQuickly);
|
|
|
const isAnimationFinish = ref(false);
|
|
const isAnimationFinish = ref(false);
|
|
|
const transitionStartX = ref(null);
|
|
const transitionStartX = ref(null);
|
|
|
const transitionEndX = ref(null);
|
|
const transitionEndX = ref(null);
|
|
|
|
|
+const isReady = ref(false);
|
|
|
|
|
+const paperData = ref<ExamPaper>({} as ExamPaper);
|
|
|
const pageTitle = computed(() => {
|
|
const pageTitle = computed(() => {
|
|
|
const { mode } = prevData.value;
|
|
const { mode } = prevData.value;
|
|
|
return mode === EnumExamMode.PRACTICE ? '练习' : '考试';
|
|
return mode === EnumExamMode.PRACTICE ? '练习' : '考试';
|
|
@@ -123,6 +129,10 @@ const isExamMode = computed(() => {
|
|
|
return prevData.value.mode === EnumExamMode.EXAM;
|
|
return prevData.value.mode === EnumExamMode.EXAM;
|
|
|
});
|
|
});
|
|
|
const handleLeftClick = () => {
|
|
const handleLeftClick = () => {
|
|
|
|
|
+ if (!isReady.value) {
|
|
|
|
|
+ transferBack();
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
beforeQuit();
|
|
beforeQuit();
|
|
|
};
|
|
};
|
|
|
const handleSwiperChange = (e: any) => {
|
|
const handleSwiperChange = (e: any) => {
|
|
@@ -152,19 +162,28 @@ const beforeQuitPractice = () => {
|
|
|
});
|
|
});
|
|
|
};
|
|
};
|
|
|
const beforeQuitExam = () => {
|
|
const beforeQuitExam = () => {
|
|
|
|
|
+ if (!isReady.value) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
uni.$ie.showModal({
|
|
uni.$ie.showModal({
|
|
|
title: '提示',
|
|
title: '提示',
|
|
|
content: '当前考试未完成,确认退出?',
|
|
content: '当前考试未完成,确认退出?',
|
|
|
}).then(confirm => {
|
|
}).then(confirm => {
|
|
|
if (confirm) {
|
|
if (confirm) {
|
|
|
- uni.navigateBack();
|
|
|
|
|
|
|
+ handleSubmit();
|
|
|
|
|
+ // uni.navigateBack();
|
|
|
}
|
|
}
|
|
|
});
|
|
});
|
|
|
};
|
|
};
|
|
|
const currentQuestion = computed(() => {
|
|
const currentQuestion = computed(() => {
|
|
|
console.log(questionList.value[currentIndex.value])
|
|
console.log(questionList.value[currentIndex.value])
|
|
|
- return questionList.value[currentIndex.value];
|
|
|
|
|
|
|
+ return questionList.value[currentIndex.value] || {};
|
|
|
});
|
|
});
|
|
|
|
|
+const hanadleNavigate = (index: number) => {
|
|
|
|
|
+ // console.log('hanadleNavigate', qs)
|
|
|
|
|
+ // const index = questionList.value.findIndex(q => q.id === qs.id);
|
|
|
|
|
+ changeIndex(index);
|
|
|
|
|
+}
|
|
|
const handleFavorite = () => {
|
|
const handleFavorite = () => {
|
|
|
console.log('handleFavorite')
|
|
console.log('handleFavorite')
|
|
|
currentQuestion.value.isFavorite = !currentQuestion.value.isFavorite;
|
|
currentQuestion.value.isFavorite = !currentQuestion.value.isFavorite;
|
|
@@ -189,6 +208,7 @@ const handleSwiperTransition = (e: any) => {
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
};
|
|
};
|
|
|
|
|
+
|
|
|
const startTime = () => {
|
|
const startTime = () => {
|
|
|
if (isExamMode.value) {
|
|
if (isExamMode.value) {
|
|
|
startExamDuration();
|
|
startExamDuration();
|
|
@@ -196,6 +216,7 @@ const startTime = () => {
|
|
|
startPracticeDuration();
|
|
startPracticeDuration();
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
const stopTime = () => {
|
|
const stopTime = () => {
|
|
|
if (isExamMode.value) {
|
|
if (isExamMode.value) {
|
|
|
stopExamDuration();
|
|
stopExamDuration();
|
|
@@ -203,6 +224,7 @@ const stopTime = () => {
|
|
|
stopPracticeDuration();
|
|
stopPracticeDuration();
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
const handleSwiperAnimationFinish = (e: any) => {
|
|
const handleSwiperAnimationFinish = (e: any) => {
|
|
|
if (transitionStartX.value == null || transitionEndX.value == null || currentIndex.value !== questionList.value.length - 1) {
|
|
if (transitionStartX.value == null || transitionEndX.value == null || currentIndex.value !== questionList.value.length - 1) {
|
|
|
isAnimationFinish.value = true;
|
|
isAnimationFinish.value = true;
|
|
@@ -212,57 +234,95 @@ const handleSwiperAnimationFinish = (e: any) => {
|
|
|
}
|
|
}
|
|
|
const offsetX = transitionEndX.value - transitionStartX.value;
|
|
const offsetX = transitionEndX.value - transitionStartX.value;
|
|
|
if (offsetX < 0 && offsetX > -150) {
|
|
if (offsetX < 0 && offsetX > -150) {
|
|
|
- const text = notDoneCount.value > 0 ? `还有${notDoneCount.value}题未做,确认交卷?` : '是否确认交卷?';
|
|
|
|
|
- stopTime();
|
|
|
|
|
- uni.$ie.showModal({
|
|
|
|
|
- title: '提示',
|
|
|
|
|
- content: text,
|
|
|
|
|
- }).then(confirm => {
|
|
|
|
|
- if (confirm) {
|
|
|
|
|
- // uni.navigateBack();
|
|
|
|
|
- handleSubmit();
|
|
|
|
|
- } else {
|
|
|
|
|
- startTime();
|
|
|
|
|
- }
|
|
|
|
|
- });
|
|
|
|
|
|
|
+ beforeSubmit();
|
|
|
}
|
|
}
|
|
|
isAnimationFinish.value = true;
|
|
isAnimationFinish.value = true;
|
|
|
transitionStartX.value = null;
|
|
transitionStartX.value = null;
|
|
|
transitionEndX.value = null;
|
|
transitionEndX.value = null;
|
|
|
};
|
|
};
|
|
|
|
|
+
|
|
|
|
|
+const beforeSubmit = () => {
|
|
|
|
|
+ const text = notDoneCount.value > 0 ? `还有${notDoneCount.value}题未做,确认交卷?` : '是否确认交卷?';
|
|
|
|
|
+ stopTime();
|
|
|
|
|
+ uni.$ie.showModal({
|
|
|
|
|
+ title: '提示',
|
|
|
|
|
+ content: text,
|
|
|
|
|
+ }).then(confirm => {
|
|
|
|
|
+ if (confirm) {
|
|
|
|
|
+ // uni.navigateBack();
|
|
|
|
|
+ handleSubmit();
|
|
|
|
|
+ } else {
|
|
|
|
|
+ startTime();
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const handleReset = () => {
|
|
|
|
|
+ if (doneCount.value <= 0) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ uni.$ie.showModal({
|
|
|
|
|
+ title: '重新作答',
|
|
|
|
|
+ content: '是否确认清空全部作答数据?',
|
|
|
|
|
+ }).then(confirm => {
|
|
|
|
|
+ if (confirm) {
|
|
|
|
|
+ questionStatsPopupRef.value.close();
|
|
|
|
|
+ reset();
|
|
|
|
|
+ setTimeout(() => {
|
|
|
|
|
+ startTime();
|
|
|
|
|
+ }, 300);
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
const handleSubmit = () => {
|
|
const handleSubmit = () => {
|
|
|
|
|
+ console.log('handleSubmit', questionList.value)
|
|
|
uni.$ie.showLoading('保存中...');
|
|
uni.$ie.showLoading('保存中...');
|
|
|
setTimeout(() => {
|
|
setTimeout(() => {
|
|
|
uni.$ie.hideLoading();
|
|
uni.$ie.hideLoading();
|
|
|
|
|
+ const params = {
|
|
|
|
|
+ ...paperData.value,
|
|
|
|
|
+ questions: questionList.value,
|
|
|
|
|
+ } as ExamPaperSubmit;
|
|
|
|
|
+ if (!isExamMode.value) {
|
|
|
|
|
+ params.duration = practiceDuration.value;
|
|
|
|
|
+ }
|
|
|
|
|
+ console.log(params);
|
|
|
|
|
+ commitExamineePaper(params);
|
|
|
uni.navigateBack();
|
|
uni.navigateBack();
|
|
|
}, 1000);
|
|
}, 1000);
|
|
|
console.log('handleSubmit')
|
|
console.log('handleSubmit')
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
const loadData = async () => {
|
|
const loadData = async () => {
|
|
|
- // const { data } = await getOpenExaminee({
|
|
|
|
|
- // paperType: prevData.value.paperType,
|
|
|
|
|
- // relateId: prevData.value.relateId
|
|
|
|
|
- // });
|
|
|
|
|
- // console.log(data)
|
|
|
|
|
- // 构造模拟数据
|
|
|
|
|
- console.log(questionList.value)
|
|
|
|
|
- loadExamData();
|
|
|
|
|
- // setExamDuration(35)
|
|
|
|
|
|
|
+ uni.$ie.showLoading();
|
|
|
|
|
+ const { data } = await getOpenExaminee({
|
|
|
|
|
+ paperType: prevData.value.paperType,
|
|
|
|
|
+ relateId: prevData.value.relateId
|
|
|
|
|
+ });
|
|
|
|
|
+ if (!data) {
|
|
|
|
|
+ uni.$ie.hideLoading();
|
|
|
|
|
+ transferBack();
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (data.paperId) {
|
|
|
|
|
+ const res = await getPaper({
|
|
|
|
|
+ type: prevData.value.paperType,
|
|
|
|
|
+ id: data.paperId
|
|
|
|
|
+ });
|
|
|
|
|
+ uni.$ie.hideLoading();
|
|
|
|
|
+ paperData.value = res.data;
|
|
|
|
|
+ setQuestionList(paperData.value.questions)
|
|
|
|
|
+ // console.log(123, paperData)
|
|
|
|
|
+ // loadExamData(prevData.value.paperType, data.paperId);
|
|
|
|
|
+ }
|
|
|
|
|
+ isReady.value = true;
|
|
|
setCountDownCallback(() => {
|
|
setCountDownCallback(() => {
|
|
|
- uni.$ie.showToast('考试结束');
|
|
|
|
|
- // uni.navigateBack();
|
|
|
|
|
|
|
+ handleSubmit();
|
|
|
});
|
|
});
|
|
|
startTime();
|
|
startTime();
|
|
|
- // startExamDuration();
|
|
|
|
|
};
|
|
};
|
|
|
-onMounted(() => {
|
|
|
|
|
- setTimeout(() => {
|
|
|
|
|
- console.log(stateQuestionList.value)
|
|
|
|
|
- handleCalendar();
|
|
|
|
|
- }, 500);
|
|
|
|
|
-});
|
|
|
|
|
onLoad(() => {
|
|
onLoad(() => {
|
|
|
- console.log(prevData.value)
|
|
|
|
|
loadData();
|
|
loadData();
|
|
|
});
|
|
});
|
|
|
</script>
|
|
</script>
|