From 98f494cf633e3acf5c20f3e9de0d708f2a6c2045 Mon Sep 17 00:00:00 2001 From: ZhangXianQiang <1135831638@qq.com> Date: 星期五, 05 七月 2024 09:39:59 +0800 Subject: [PATCH] feat:视频浏览 --- src/views/exam/index.vue | 177 ++++++++++++++++++++++++++++++++++++++++++++++++---------- 1 files changed, 145 insertions(+), 32 deletions(-) diff --git a/src/views/exam/index.vue b/src/views/exam/index.vue index 585a0ec..591e735 100644 --- a/src/views/exam/index.vue +++ b/src/views/exam/index.vue @@ -5,9 +5,9 @@ <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></AnswerTime> + <AnswerTime @timeOut="timeOut"></AnswerTime> <div class="return-container grow flex justify-end"> <el-button type="danger" size="large" circle @click="closeClick"> @@ -40,7 +40,7 @@ </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> @@ -50,7 +50,9 @@ <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 ">{{ examType[currentType] }} ({{ examStore.getActiveQuestion.score}}鍒�)</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"> @@ -79,58 +81,120 @@ <!-- 閫�鍑鸿�冭瘯鎻愮ず寮圭獥 --> - <el-dialog v-model="dialogVisible" title="娉ㄦ剰" width="500"> + <el-dialog v-model="quitDialog" title="娉ㄦ剰" width="500"> <div class="dialog-container"> <p>璇风‘璁ゆ槸鍚﹂��鍑哄綋鍓嶈�冭瘯</p> - <p>褰撳墠鑰冭瘯璇曞嵎浼氳嚜鍔ㄦ彁浜�,鍚庣画灏嗘棤娉曠户缁綔绛�</p> + <p>褰撳墠璇曞嵎浼氳嚜鍔ㄦ彁浜�,鍚庣画灏嗘棤娉曠户缁綔绛�</p> </div> <template #footer> <div class="dialog-footer"> - <el-button @click="dialogVisible = false">鍙栨秷</el-button> - <el-button type="primary" @click="confirmCancel"> - 纭畾 + <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, watchEffect } from 'vue'; +import { ref, watchEffect, watch, onMounted } from 'vue'; import { storeToRefs } from 'pinia'; -import { Close } from '@element-plus/icons-vue'; +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 AnswerTime from './components/answer-time/index.vue'; -import { useExamStore } from '@/store/index.js'; +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'; + const router = useRouter(); const examStore = useExamStore(); -const { currentType, currentIndex, examDetail, examType } = storeToRefs(examStore); +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 dialogVisible = ref(false); +const quitDialog = ref(false); +const submitDialog = ref(false); +const timeDialog = ref(false); +const { status, message, error, connect, disconnect, sendMessage } = useWebScoket({ + url: 'ws://192.168.3.64:8000/websocket/' + userInfo.value.id, + heartBeatData: 'ping' +}); + + +// 涓婁竴棰� const prevQuestion = () => { currentIndex.value--; checkList(); }; +// 涓嬩竴棰� const nextQuestion = () => { currentIndex.value++; checkList(); }; +// 鏌ヨ棰樼洰 const checkList = () => { let tempIndex = 0; const typeQuestion = examDetail.value.find((typeItem, index) => { @@ -162,40 +226,78 @@ currentIndex.value = 0; } } - // findQuestion(currentType.value, currentIndex.value); } }; -const findQuestion = (type, index) => { - const typeQuestion = examDetail.value.find(typeItem => typeItem.questionType === type); - if (typeQuestion) { - const question = typeQuestion.questionList[index]; - if (question) { - examStore.setActiveQuestion(question); - } - } -}; - +// 閫�鍑鸿�冭瘯 const closeClick = () => { - dialogVisible.value = true; + quitDialog.value = true; }; -const confirmCancel = () => { - dialogVisible.value = false; - router.back(); +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.correct) { + if (question.answer || (Array.isArray(question.answerList) && question.answerList.length)) { progress += 1; } }); }); examStore.setProgress(progress); +}); + +watch(() => message.value, (msg) => { + console.log(msg); +}); + + +// -----------------------------------鐢熷懡鍛ㄦ湡 +onMounted(() => { + // 杩炴帴webscoket + connect(); }); </script> @@ -236,7 +338,7 @@ } .answer-left { - width: 340px; + width: 370px; } .submit-button, @@ -248,4 +350,15 @@ .tool-button { margin: 0 20px; } + +.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> \ No newline at end of file -- Gitblit v1.8.0