From 9c2eb9ed6da32c1830b02431875dacaa7f904b1f Mon Sep 17 00:00:00 2001 From: 黄何裕 <1053952480@qq.com> Date: 星期五, 12 七月 2024 18:16:56 +0800 Subject: [PATCH] 修改资料校验 --- src/views/exam/index.vue | 330 ++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 files changed, 302 insertions(+), 28 deletions(-) diff --git a/src/views/exam/index.vue b/src/views/exam/index.vue index aaf82e4..dbbf30c 100644 --- a/src/views/exam/index.vue +++ b/src/views/exam/index.vue @@ -1,23 +1,35 @@ <template> - <div class="exam-container w-screen h-screen bg-slate-50 relative overflow-hidden"> + <div + class="exam-container w-screen h-screen bg-slate-50 relative overflow-hidden" + > <div class="top-bg bg-blue-500"></div> <div class="exam-content"> <div class="exam-wrapper container mx-auto h-full flex flex-col"> <div class="exam-header flex items-center mt-12 mb-10"> <div class="title-container text-3xl font-semibold text-white mr-8"> - 娴嬭瘯娴嬭瘯娴嬭瘯 + {{ examInfo.examName }} </div> + <AnswerTime @timeOut="timeOut" ref="answerTime"></AnswerTime> - <AnswerTime></AnswerTime> - + <div class="return-container grow flex justify-end"> + <el-button type="danger" size="large" circle @click="closeClick"> + <template #icon> + <el-icon :size="20"> + <Close /> + </el-icon> + </template> + </el-button> + </div> </div> <div class="exam-main grow flex justify-between"> <!-- 绛旈鍗″尯 --> <div class="answer-wrapper answer-left mr-8 shadow-xl p-4 box-border"> <div class="wrapper h-full flex flex-col items-center"> - <div class="title-wrapper w-full flex justify-between items-center mb-5"> - <div class="title text-xl font-semibold ">绛旈鍗�</div> + <div + class="title-wrapper w-full flex justify-between items-center mb-5" + > + <div class="title text-xl font-semibold">绛旈鍗�</div> <AnswerTag></AnswerTag> </div> @@ -32,9 +44,13 @@ </div> <div class="submit-wrapper"> - <el-button type="primary" class="submit-button">鎻愪氦璇曞嵎</el-button> + <el-button + type="primary" + class="submit-button" + @click="submitExamHandle" + >鎻愪氦璇曞嵎</el-button + > </div> - </div> </div> @@ -42,13 +58,20 @@ <div class="answer-wrapper answer-right grow shadow-xl p-4"> <div class="wrapper h-full flex flex-col"> <div class="title-wrapper w-full flex mb-5"> - <div class="title text-xl font-semibold ">鍗曢�夐 (3鍒�)</div> + <div class="title text-xl font-semibold"> + {{ examType[currentType] }} ({{ + examStore.getActiveQuestion.questionScore + }}鍒�) + </div> </div> <div class="main-wrapper w-full grow relative my-5"> <div class="main-content absolute top-0 bottom-0 w-full"> <Transition appear name="fade-transform" mode="out-in"> - <component :is="typeComponent[currentType]" :key="questionIndex"></component> + <component + :is="typeComponent[currentType]" + :key="currentIndex" + ></component> </Transition> </div> </div> @@ -56,10 +79,17 @@ <div class="tool-wrapper flex justify-end"> <div class="button-container flex items-center"> <div class="button-item"> - <el-button class="tool-button" @click="prevQuestion">涓婁竴棰�</el-button> + <el-button class="tool-button" @click="prevQuestion" + >涓婁竴棰�</el-button + > </div> <div class="button-item"> - <el-button class="tool-button" type="primary" @click="nextQuestion">涓嬩竴棰�</el-button> + <el-button + class="tool-button" + type="primary" + @click="nextQuestion" + >涓嬩竴棰�</el-button + > </div> </div> </div> @@ -68,33 +98,265 @@ </div> </div> </div> + + <!-- 閫�鍑鸿�冭瘯鎻愮ず寮圭獥 --> + <el-dialog v-model="quitDialog" title="娉ㄦ剰" width="500"> + <div class="dialog-container"> + <p>璇风‘璁ゆ槸鍚﹂��鍑哄綋鍓嶈�冭瘯</p> + <p>褰撳墠璇曞嵎浼氳嚜鍔ㄦ彁浜�,鍚庣画灏嗘棤娉曠户缁綔绛�</p> + </div> + <template #footer> + <div class="dialog-footer"> + <el-button @click="quitDialog = false">缁х画浣滅瓟</el-button> + <el-button type="danger" @click="confirmQuit"> 纭畾閫�鍑� </el-button> + </div> + </template> + </el-dialog> + + <!-- 浜ゅ嵎鎻愮ず寮圭獥 --> + <el-dialog v-model="submitDialog" title="纭浜ゅ嵎?" width="500"> + <div class="dialog-container"> + <p>璇风‘璁ゆ槸鍚︽彁浜よ瘯鍗�</p> + <p>涓�鏃︿氦鍗峰皢鏃犳硶缁х画浣滅瓟鎴栦慨鏀圭瓟妗�</p> + </div> + <template #footer> + <div class="dialog-footer"> + <el-button @click="submitDialog = false">缁х画浣滅瓟</el-button> + <el-button type="primary" @click="confirmSubmit"> + 纭鎻愪氦 + </el-button> + </div> + </template> + </el-dialog> + + <!-- 鑰冭瘯鏃堕棿寮圭獥 --> + <el-dialog + v-model="timeDialog" + align-center + width="500" + :close-on-click-modal="false" + :close-on-press-escape="false" + :show-close="false" + > + <div class="dialog-container flex flex-col items-center"> + <div class="icon-container"> + <el-icon :size="50" color="#3680fa"> + <Timer /> + </el-icon> + </div> + <div class="dialog-info">鑰冭瘯缁撴潫锛岀郴缁熻嚜鍔ㄦ敹鍗蜂腑.......</div> + </div> + </el-dialog> </div> </template> <script setup> -import {ref} from 'vue'; -import AnswerTag from './components/answer-tag/index.vue'; -import AnswerProgress from './components/answer-progress/index.vue'; -import AnswerSheet from './components/answer-sheet/index.vue'; -import AnswerSingle from './components/answer-main/answer-single/index.vue'; -import AnswerMultiple from './components/answer-main/answer-multiple/index.vue'; -import AnswerTime from './components/answer-time/index.vue'; +import { ref, watchEffect, watch, onMounted ,onUnmounted} from "vue"; +import { storeToRefs } from "pinia"; +import { Close, Timer } from "@element-plus/icons-vue"; +import AnswerTag from "./components/answer-tag/index.vue"; +import AnswerProgress from "./components/answer-progress/index.vue"; +import AnswerSheet from "./components/answer-sheet/index.vue"; +import AnswerTime from "./components/answer-time/index.vue"; + +import AnswerSingle from "./components/answer-main/answer-single/index.vue"; +import AnswerMultiple from "./components/answer-main/answer-multiple/index.vue"; +import AnswerAudio from "./components/answer-main/answer-audio/index.vue"; +import AnswerFill from "./components/answer-main/answer-fill/index.vue"; +import AnswerDetermine from "./components/answer-main/answer-determine/index.vue"; +import AnswerShort from "./components/answer-main/answer-short/index.vue"; +import AnswerCount from "./components/answer-main/answer-count/index.vue"; + +import { useExamStore, useUserStore } from "@/store/index.js"; +import { useRouter } from "vue-router"; + +import { submitExam } from "@/api/modules/exam.js"; +import useWebScoket from "@/hooks/useWebScoket.js"; + +import { ElMessage, ElMessageBox } from "element-plus"; + +const router = useRouter(); + +const examStore = useExamStore(); +const userStore = useUserStore(); + +const { userInfo } = storeToRefs(userStore); +const { currentType, currentIndex, examDetail, examType, examInfo } = + storeToRefs(examStore); const typeComponent = { 1: AnswerSingle, 2: AnswerMultiple, -} + 3: AnswerDetermine, + 4: AnswerFill, + 5: AnswerShort, + 6: AnswerAudio, + 7: AnswerCount, + 8: AnswerShort, +}; -const currentType = ref(1); -const questionIndex = ref(0); +const quitDialog = ref(false); +const submitDialog = ref(false); +const timeDialog = ref(false); +// const { status, message, error, connect, disconnect, sendMessage } = useWebScoket({ +// url: 'wss://42.193.1.25:8000/websocket/' + userInfo.value.id, +// heartBeatData: 'ping' +// }); + +const { status, message, error, connect, disconnect, sendMessage } = + useWebScoket({ + url: "//192.168.3.64:8000/websocket/" + userInfo.value.id, + heartBeatData: "ping", + }); + +// 涓婁竴棰� const prevQuestion = () => { - questionIndex.value--; -} + currentIndex.value--; + checkList(); +}; +// 涓嬩竴棰� const nextQuestion = () => { - questionIndex.value++; -} + currentIndex.value++; + checkList(); +}; + +// 鏌ヨ棰樼洰 +const checkList = () => { + let tempIndex = 0; + const typeQuestion = examDetail.value.find((typeItem, index) => { + if (typeItem.questionType === currentType.value) { + tempIndex = index; + return typeItem; + } else { + return false; + } + }); + if (typeQuestion) { + if (currentIndex.value >= typeQuestion.questionList.length) { + tempIndex++; + if (examDetail.value[tempIndex]) { + currentType.value = examDetail.value[tempIndex].questionType; + currentIndex.value = 0; + } else { + currentType.value = typeQuestion.questionType; + currentIndex.value = typeQuestion.questionList.length - 1; + } + } else if (currentIndex.value < 0) { + tempIndex--; + if (examDetail.value[tempIndex]) { + currentType.value = examDetail.value[tempIndex].questionType; + currentIndex.value = + examDetail.value[tempIndex].questionList.length - 1; + } else { + currentType.value = typeQuestion.questionType; + currentIndex.value = 0; + } + } + } +}; + +// 閫�鍑鸿�冭瘯 +const closeClick = () => { + quitDialog.value = true; +}; + +const confirmQuit = () => { + timeOut(); +}; + +// 浜ゅ嵎 +const submitExamHandle = () => { + submitDialog.value = true; +}; + +const confirmSubmit = () => { + timeOut(); +}; + +const resetAllDialog = () => { + quitDialog.value = false; + submitDialog.value = false; +}; + +// 鏃堕棿缁撴潫 +const timeOut = () => { + const temp = { + ...examInfo.value, + titleList: examDetail.value, + }; + timeDialog.value = true; + resetAllDialog(); + + disconnect(); + + submitExam(temp) + .then((res) => { + returnBack(); + }) + .catch(() => { + returnBack(); + }); +}; + +const returnBack = () => { + setTimeout(() => { + router.back(); + }, 2000); +}; + +watchEffect(() => { + let progress = 0; + examDetail.value.forEach((item) => { + item.questionList.forEach((question) => { + if ( + question.answer || + (Array.isArray(question.answerList) && question.answerList.length) + ) { + progress += 1; + } + }); + }); + examStore.setProgress(progress); +}); +const answerTime = ref(); +watch( + () => message.value, + (msg) => { + if (msg.commend == "delayed") { + answerTime.value.addTime(msg.data.addTimeM); + } else if (msg.commend == "forceSubmit") { + confirmSubmit(); + } + } +); +// document.addEventListener('blur', function() { +// console.log('椤甸潰澶卞幓鐒︾偣'); +// }); +const warningNum = ref(0) +const handleBlur = () => { + if (document.visibilityState === "visible") { + } else if (document.visibilityState === "hidden") { + ElMessageBox.alert("鑰冭瘯杩囩▼涓鍕跨寮�鑰冭瘯椤甸潰锛佽鍛婁笁娆″皢寮哄埗鏀跺嵎", "璀﹀憡", { + confirmButtonText: "纭畾", + }); + warningNum.value++ + if (warningNum.value==3) { + timeOut(); + } + } +}; + +// -----------------------------------鐢熷懡鍛ㄦ湡 +onMounted(() => { + // 杩炴帴webscoket + connect(); + document.addEventListener("visibilitychange", handleBlur); +}); +onUnmounted(()=>{ + document.removeEventListener("visibilitychange", handleBlur); +}) </script> <style lang="scss" scoped> @@ -134,7 +396,7 @@ } .answer-left { - width: 340px; + width: 370px; } .submit-button, @@ -142,7 +404,19 @@ width: 160px; height: 40px; } + .tool-button { margin: 0 20px; } -</style> \ No newline at end of file + +.icon-container { + width: 70px; + height: 70px; + border-radius: 50%; + display: flex; + justify-content: center; + align-items: center; + background-color: rgba($color: #3680fa, $alpha: 0.2); + margin-bottom: 20px; +} +</style> -- Gitblit v1.8.0