|
|
|
@ -1,94 +1,14 @@
|
|
|
|
<template>
|
|
|
|
<template>
|
|
|
|
<main class="take-page exam-page" v-loading="loading">
|
|
|
|
<main class="take-page app-container" v-loading="loading">
|
|
|
|
<header v-if="current" class="exam-toolbar">
|
|
|
|
<header v-if="current" class="take-head"><div><h1>{{ paper.name || '在线考试' }}</h1><p>考试结束时间 {{ formatTime(paper.endTime) }}</p></div><div class="timer" :class="{ urgent: remaining < 300 }"><span>剩余时间</span><strong>{{ timerText }}</strong></div><el-button type="danger" plain @click="confirmSubmit">交卷</el-button></header>
|
|
|
|
<div class="toolbar-type">{{ typeName[current.type] }}</div>
|
|
|
|
<div class="exam-body"><aside class="answer-sheet"><h2>答题卡</h2><div v-for="group in grouped" :key="group.type" class="sheet-group"><h3>{{ typeName[group.type] }}</h3><div><button v-for="question in group.items" :key="question.id" :class="{ current:current?.id===question.id,answered:isAnswered(question) }" @click="select(question.id)">{{ question.order }}</button></div></div><footer><span><i class="answered-dot" />已答</span><span><i />未答</span></footer></aside><section v-if="current" class="question-panel" @copy="guardCopy" @contextmenu="guardContextMenu"><header><span>{{ typeName[current.type] }}</span><b>{{ current.score }} 分</b></header><h2>{{ current.order }}. {{ current.stem }}</h2><a v-if="current.attachmentUrl" :href="current.attachmentUrl" target="_blank" class="material"><el-icon><Download /></el-icon>下载题目资料 {{ current.attachmentName }}</a><el-radio-group v-if="current.type==='SINGLE'" v-model="answers[current.id]" class="choice-list" @change="persist(current)"><el-radio v-for="option in current.options" :key="option.label" :label="option.label"><b>{{ option.label }}</b>{{ option.content }}</el-radio></el-radio-group><el-checkbox-group v-else-if="current.type==='MULTIPLE'" v-model="answers[current.id]" class="choice-list" @change="persist(current)"><el-checkbox v-for="option in current.options" :key="option.label" :label="option.label"><b>{{ option.label }}</b>{{ option.content }}</el-checkbox></el-checkbox-group><el-radio-group v-else-if="current.type==='TRUE_FALSE'" v-model="answers[current.id]" class="choice-list judgement" @change="persist(current)"><el-radio :label="true"><b>✓</b>正确</el-radio><el-radio :label="false"><b>×</b>错误</el-radio></el-radio-group><template v-else><el-input v-model="answers[current.id]" type="textarea" :rows="10" placeholder="请输入答案" @blur="persist(current)" @paste="guardPaste" /><div class="file-answer"><span>作答文件:</span><el-upload :show-file-list="false" :http-request="uploadAnswer" accept=".pdf,.doc,.docx,.png,.jpg,.jpeg"><el-button type="primary" :icon="Upload">上传</el-button></el-upload><a v-if="files[current.id]" :href="files[current.id].url" target="_blank">{{ files[current.id].name }}</a></div></template><footer class="question-actions"><el-button :disabled="currentIndex===0" @click="move(-1)">上一题</el-button><el-button type="primary" :disabled="currentIndex===paper.questions.length-1" @click="move(1)">下一题</el-button></footer></section></div>
|
|
|
|
<div class="toolbar-title">题干({{ typeName[current.type] }}):</div>
|
|
|
|
|
|
|
|
<a v-if="current.attachmentUrl" :href="current.attachmentUrl" target="_blank" class="material-button"><el-icon><Download /></el-icon>下载题目资料</a>
|
|
|
|
|
|
|
|
<div class="timer" :class="{ urgent: remaining < 300 }">倒计时:{{ timerText }}</div>
|
|
|
|
|
|
|
|
<button class="submit-button" @click="confirmSubmit"><el-icon><Promotion /></el-icon>交卷</button>
|
|
|
|
|
|
|
|
</header>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<div class="exam-layout">
|
|
|
|
|
|
|
|
<aside class="answer-sheet">
|
|
|
|
|
|
|
|
<section v-for="group in grouped" :key="group.type" class="sheet-group">
|
|
|
|
|
|
|
|
<h2>{{ typeName[group.type] }}</h2>
|
|
|
|
|
|
|
|
<div class="sheet-grid"><button v-for="question in group.items" :key="question.id" :class="{ answered: isAnswered(question), current: current?.id === question.id }" @click="select(question.id)">{{ question.order }}</button></div>
|
|
|
|
|
|
|
|
</section>
|
|
|
|
|
|
|
|
</aside>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<section v-if="current" class="question-panel" @copy="guardCopy" @contextmenu="guardContextMenu">
|
|
|
|
|
|
|
|
<p class="question-stem">{{ current.order }}. {{ current.stem }}</p>
|
|
|
|
|
|
|
|
<el-radio-group v-if="current.type === 'SINGLE'" v-model="answers[current.id]" class="choice-list" @change="persist(current)"><el-radio v-for="option in current.options" :key="option.label" :label="option.label"><b>{{ option.label }}</b>{{ option.content }}</el-radio></el-radio-group>
|
|
|
|
|
|
|
|
<el-checkbox-group v-else-if="current.type === 'MULTIPLE'" v-model="answers[current.id]" class="choice-list" @change="persist(current)"><el-checkbox v-for="option in current.options" :key="option.label" :label="option.label"><b>{{ option.label }}</b>{{ option.content }}</el-checkbox></el-checkbox-group>
|
|
|
|
|
|
|
|
<el-radio-group v-else-if="current.type === 'TRUE_FALSE'" v-model="answers[current.id]" class="choice-list judgement" @change="persist(current)"><el-radio :label="true"><b>✓</b>正确</el-radio><el-radio :label="false"><b>×</b>错误</el-radio></el-radio-group>
|
|
|
|
|
|
|
|
<template v-else><el-input v-model="answers[current.id]" type="textarea" :rows="10" placeholder="请输入答案" @blur="persist(current)" @paste="guardPaste" /><div class="file-answer"><span>作答文件:</span><el-upload :show-file-list="false" :http-request="uploadAnswer" accept=".pdf,.doc,.docx,.png,.jpg,.jpeg"><el-button type="primary" :icon="Upload">上传</el-button></el-upload><a v-if="files[current.id]" :href="files[current.id].url" target="_blank">{{ files[current.id].name }}</a></div></template>
|
|
|
|
|
|
|
|
</section>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<footer v-if="paper.questions?.length" class="exam-navigation"><button class="previous" :disabled="currentIndex === 0" @click="move(-1)">上一题</button><button class="next" :disabled="currentIndex === paper.questions.length - 1" @click="move(1)">下一题</button></footer>
|
|
|
|
|
|
|
|
</main>
|
|
|
|
</main>
|
|
|
|
</template>
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<script setup>
|
|
|
|
<script setup>
|
|
|
|
import { computed, onBeforeUnmount, onMounted, reactive, ref } from "vue";
|
|
|
|
import { computed,onBeforeUnmount,onMounted,reactive,ref } from "vue"; import { useRoute,useRouter } from "vue-router"; import { ElMessage,ElMessageBox } from "element-plus"; import { Download,Upload } from "@element-plus/icons-vue"; import * as examApi from "@/api/exam";
|
|
|
|
import { useRoute, useRouter } from "vue-router";
|
|
|
|
const route=useRoute(),router=useRouter(),examId=route.params.id,loading=ref(false),paper=ref({questions:[]}),currentId=ref(null),remaining=ref(0),answers=reactive({}),files=reactive({});let ticker; const typeName={SINGLE:"单选题",MULTIPLE:"多选题",TRUE_FALSE:"判断题",SHORT_ANSWER:"简答题"}; const current=computed(()=>paper.value.questions.find(q=>q.id===currentId.value)); const currentIndex=computed(()=>paper.value.questions.findIndex(q=>q.id===currentId.value)); const grouped=computed(()=>Object.keys(typeName).map(type=>({type,items:paper.value.questions.filter(q=>q.type===type)})).filter(g=>g.items.length)); const timerText=computed(()=>`${String(Math.floor(remaining.value/60)).padStart(2,"0")} 分钟 ${String(remaining.value%60).padStart(2,"0")} 秒`); onMounted(load); onBeforeUnmount(()=>clearInterval(ticker));
|
|
|
|
import { ElMessage, ElMessageBox } from "element-plus";
|
|
|
|
async function load(){loading.value=true;try{const token=deviceToken();paper.value=(await examApi.getActivePaper(examId,token)).data;paper.value.questions.forEach(q=>{answers[q.id]=q.studentAnswer??(q.type==="MULTIPLE"?[]:"");if(q.answerFileUrl)files[q.id]={name:q.answerFileName,url:q.answerFileUrl}});currentId.value=paper.value.questions[0]?.id;remaining.value=Math.max(0,Math.floor((new Date(paper.value.endTime)-Date.now())/1000));ticker=setInterval(()=>{remaining.value=Math.max(0,remaining.value-1);if(remaining.value===0){clearInterval(ticker);autoSubmit()}},1000)}finally{loading.value=false}} function deviceToken(){return localStorage.getItem(`exam-device-${examId}`)||""} function select(id){currentId.value=id} function move(step){currentId.value=paper.value.questions[currentIndex.value+step]?.id} function isAnswered(q){const answer=answers[q.id];return(Array.isArray(answer)?answer.length:Boolean(String(answer??"").trim()))||Boolean(files[q.id])} function guardCopy(event){if(paper.value.allowCopyQuestion||event.target?.closest("textarea,input"))return;event.preventDefault();ElMessage.warning("该考试不允许复制试题")} function guardContextMenu(event){if(paper.value.allowCopyQuestion||event.target?.closest("textarea,input"))return;event.preventDefault()} function guardPaste(event){if(!paper.value.allowPasteAnswer){event.preventDefault();ElMessage.warning("该考试不允许粘贴答案")}} async function persist(q){await examApi.saveExamAnswer(examId,q.id,{deviceToken:deviceToken(),answer:answers[q.id]})} async function uploadAnswer({file}){const form=new FormData();form.append("file",file);const data=(await examApi.uploadExamAnswerFile(examId,current.value.id,deviceToken(),form)).data;files[current.value.id]={name:data.name,url:data.url};ElMessage.success("作答文件已上传")} async function confirmSubmit(){const unanswered=paper.value.questions.filter(q=>!isAnswered(q)).length;await ElMessageBox.confirm(unanswered?`还有 ${unanswered} 道题未作答,确认交卷?`:"确认提交试卷?","确认交卷",{type:"warning",confirmButtonText:"确认交卷"});await doSubmit()} async function doSubmit(){await examApi.submitExam(examId,deviceToken());ElMessage.success("交卷成功");router.replace(`/examination/result/${examId}`)} async function autoSubmit(){try{await doSubmit()}catch{router.replace("/examination/index")}} function formatTime(v){return v?new Date(v).toLocaleString("zh-CN",{hour12:false}).replaceAll("/","-"):"—"}
|
|
|
|
import { Download, Promotion, Upload } from "@element-plus/icons-vue";
|
|
|
|
|
|
|
|
import * as examApi from "@/api/exam";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const route = useRoute(); const router = useRouter(); const examId = route.params.id;
|
|
|
|
|
|
|
|
const loading = ref(false); const paper = ref({ questions: [] }); const currentId = ref(null); const remaining = ref(0); const answers = reactive({}); const files = reactive({}); let ticker;
|
|
|
|
|
|
|
|
const typeName = { SINGLE: "单选题", MULTIPLE: "多选题", TRUE_FALSE: "判断题", SHORT_ANSWER: "简答题" };
|
|
|
|
|
|
|
|
const current = computed(() => paper.value.questions.find((q) => q.id === currentId.value));
|
|
|
|
|
|
|
|
const currentIndex = computed(() => paper.value.questions.findIndex((q) => q.id === currentId.value));
|
|
|
|
|
|
|
|
const grouped = computed(() => Object.keys(typeName).map((type) => ({ type, items: paper.value.questions.filter((q) => q.type === type) })).filter((group) => group.items.length));
|
|
|
|
|
|
|
|
const timerText = computed(() => `${String(Math.floor(remaining.value / 60)).padStart(2, "0")} 分钟 ${String(remaining.value % 60).padStart(2, "0")} 秒`);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
onMounted(load); onBeforeUnmount(() => clearInterval(ticker));
|
|
|
|
|
|
|
|
async function load() { loading.value = true; try { const token = deviceToken(); paper.value = (await examApi.getActivePaper(examId, token)).data; paper.value.questions.forEach((q) => { answers[q.id] = q.studentAnswer ?? (q.type === "MULTIPLE" ? [] : ""); if (q.answerFileUrl) files[q.id] = { name: q.answerFileName, url: q.answerFileUrl }; }); currentId.value = paper.value.questions[0]?.id; remaining.value = Math.max(0, Math.floor((new Date(paper.value.endTime) - Date.now()) / 1000)); ticker = setInterval(() => { remaining.value = Math.max(0, remaining.value - 1); if (remaining.value === 0) { clearInterval(ticker); autoSubmit(); } }, 1000); } finally { loading.value = false; } }
|
|
|
|
|
|
|
|
function deviceToken() { return localStorage.getItem(`exam-device-${examId}`) || ""; }
|
|
|
|
|
|
|
|
function select(id) { currentId.value = id; }
|
|
|
|
|
|
|
|
function move(step) { currentId.value = paper.value.questions[currentIndex.value + step]?.id; }
|
|
|
|
|
|
|
|
function isAnswered(q) { const answer = answers[q.id]; return (Array.isArray(answer) ? answer.length : Boolean(String(answer ?? "").trim())) || Boolean(files[q.id]); }
|
|
|
|
|
|
|
|
function guardCopy(event) { if (paper.value.allowCopyQuestion || event.target?.closest("textarea,input")) return; event.preventDefault(); ElMessage.warning("该考试不允许复制试题"); }
|
|
|
|
|
|
|
|
function guardContextMenu(event) { if (paper.value.allowCopyQuestion || event.target?.closest("textarea,input")) return; event.preventDefault(); }
|
|
|
|
|
|
|
|
function guardPaste(event) { if (!paper.value.allowPasteAnswer) { event.preventDefault(); ElMessage.warning("该考试不允许粘贴答案"); } }
|
|
|
|
|
|
|
|
async function persist(q) { await examApi.saveExamAnswer(examId, q.id, { deviceToken: deviceToken(), answer: answers[q.id] }); }
|
|
|
|
|
|
|
|
async function uploadAnswer({ file }) { const form = new FormData(); form.append("file", file); const data = (await examApi.uploadExamAnswerFile(examId, current.value.id, deviceToken(), form)).data; files[current.value.id] = { name: data.name, url: data.url }; ElMessage.success("作答文件已上传"); }
|
|
|
|
|
|
|
|
async function confirmSubmit() { const unanswered = paper.value.questions.filter((q) => !isAnswered(q)).length; await ElMessageBox.confirm(unanswered ? `还有 ${unanswered} 道题未作答,确认交卷?` : "确认提交试卷?", "确认交卷", { type: "warning", confirmButtonText: "确认交卷" }); await doSubmit(); }
|
|
|
|
|
|
|
|
async function doSubmit() { await examApi.submitExam(examId, deviceToken()); ElMessage.success("交卷成功"); router.replace(`/examination/result/${examId}`); }
|
|
|
|
|
|
|
|
async function autoSubmit() { try { await doSubmit(); } catch { router.replace("/examination/index"); } }
|
|
|
|
|
|
|
|
</script>
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<style scoped lang="scss">
|
|
|
|
<style scoped lang="scss">
|
|
|
|
.take-page { min-height: calc(100vh - 104px); margin: 10px auto 32px; padding: 18px 30px 34px; }
|
|
|
|
.take-page{--accent:#1f2937;--border:#e5e7eb;--muted:#6b7280;min-height:calc(100vh - 84px);background:#f8fafc;color:#1f2937}.take-head{height:72px;display:grid;grid-template-columns:1fr auto 1fr;align-items:center;padding:0 28px;border-bottom:1px solid var(--border);background:#fff}.take-head h1{margin:0;font-size:17px}.take-head p{margin:4px 0 0;color:var(--muted);font-size:12px}.take-head>button{justify-self:end}.timer{display:grid;gap:2px;text-align:center;color:var(--muted);font-size:12px}.timer strong{color:var(--accent);font-size:18px;font-variant-numeric:tabular-nums}.timer.urgent strong{color:#c2413b}.exam-body{display:grid;grid-template-columns:250px minmax(0,1fr);gap:20px;padding:20px 22px}.answer-sheet,.question-panel{border:1px solid var(--border);border-radius:14px;background:#fff}.answer-sheet{align-self:start;padding:16px;position:sticky;top:16px}.answer-sheet h2{margin:0 0 14px;font-size:14px}.sheet-group{margin-bottom:18px}.sheet-group h3{margin:0 0 10px;color:var(--muted);font-size:12px}.sheet-group>div{display:grid;grid-template-columns:repeat(5,1fr);gap:7px}.sheet-group button{aspect-ratio:1;border:1px solid var(--border);border-radius:6px;background:#fff;color:var(--muted);cursor:pointer}.sheet-group button.answered{border-color:#4a9d6e;color:#4a9d6e;background:#f0fdf4}.sheet-group button.current{outline:2px solid var(--accent);outline-offset:2px}.answer-sheet footer{display:flex;gap:14px;color:var(--muted);font-size:11px}.answer-sheet i{display:inline-block;width:8px;height:8px;margin-right:4px;border:1px solid #d1d5db;border-radius:50%}.answer-sheet i.answered-dot{border-color:#4a9d6e;background:#4a9d6e}.question-panel{min-height:610px;padding:22px 28px 80px;position:relative}.question-panel>header{display:flex;justify-content:space-between;color:var(--muted);font-size:13px}.question-panel>header b{color:var(--accent)}.question-panel h2{margin:18px 0;color:#1f2937;font-size:17px;line-height:1.65}.material{display:inline-flex;gap:6px;margin-bottom:16px;color:var(--accent);font-size:12px;text-decoration:none}.choice-list{display:grid;gap:10px;width:100%}.question-panel:deep(.el-radio),.question-panel:deep(.el-checkbox){height:auto;margin:0;padding:13px 16px;border:1px solid var(--border);border-radius:8px;background:#fff}.question-panel:deep(.el-radio:hover),.question-panel:deep(.el-checkbox:hover),.question-panel:deep(.is-checked){border-color:var(--accent);background:#f9fafb}.question-panel:deep(.el-radio__label),.question-panel:deep(.el-checkbox__label){display:flex;gap:12px;color:#1f2937;font-size:13px;line-height:1.55}.judgement{grid-template-columns:1fr 1fr}.question-panel:deep(.el-textarea__inner){border-color:var(--border);border-radius:8px;box-shadow:none}.file-answer{display:flex;align-items:center;gap:12px;margin-top:12px;color:var(--muted);font-size:12px}.file-answer a{color:var(--accent)}.question-actions{position:absolute;right:28px;bottom:24px;left:28px;display:flex;justify-content:space-between}.take-page:deep(.el-button){height:40px;border-radius:10px;font-weight:700}.take-page:deep(.el-button--primary){border-color:var(--accent);background:var(--accent)}.take-page:deep(.el-button--danger.is-plain){border-color:rgba(31,41,55,.4);background:#fff;color:var(--accent)}@media(max-width:760px){.take-head{grid-template-columns:1fr auto;height:auto;padding:10px 14px}.timer{grid-column:1/3;margin-top:8px}.exam-body{grid-template-columns:1fr;padding:12px}.answer-sheet{position:static}.question-panel{padding:20px 18px 78px}.question-actions{right:18px;left:18px}}
|
|
|
|
.exam-toolbar { display: grid; grid-template-columns: 174px minmax(180px, 1fr) auto auto auto; align-items: center; gap: 18px; min-height: 70px; padding: 0 10px 18px; border-bottom: 1px solid var(--exam-line); }
|
|
|
|
|
|
|
|
.toolbar-type, .material-button, .submit-button { display: inline-flex; align-items: center; justify-content: center; min-height: 50px; border-radius: 8px; color: #fff; font-size: 17px; font-weight: 700; }
|
|
|
|
|
|
|
|
.toolbar-type { background: #159bd0; }
|
|
|
|
|
|
|
|
.toolbar-title { color: var(--exam-text); font-size: 17px; font-weight: 700; text-align: center; }
|
|
|
|
|
|
|
|
.material-button { gap: 6px; min-width: 176px; padding: 0 18px; text-decoration: none; background: #159bd0; }
|
|
|
|
|
|
|
|
.timer { color: #ff4646; font-size: 20px; font-weight: 800; white-space: nowrap; &.urgent { color: #ff3131; } }
|
|
|
|
|
|
|
|
.submit-button { gap: 6px; min-width: 128px; border: 0; cursor: pointer; background: #60bf32; &:hover { background: #4fae24; } }
|
|
|
|
|
|
|
|
.exam-layout { display: grid; grid-template-columns: 34% minmax(0, 1fr); gap: 34px; margin-top: 18px; }
|
|
|
|
|
|
|
|
.answer-sheet { padding: 0 16px 18px 0; border-right: 1px solid var(--exam-line); }
|
|
|
|
|
|
|
|
.sheet-group { margin-bottom: 28px; }
|
|
|
|
|
|
|
|
.sheet-group h2 { width: 174px; margin: 0 0 28px; padding: 14px 10px; border-radius: 8px; color: #fff; background: #159bd0; font-size: 18px; text-align: center; }
|
|
|
|
|
|
|
|
.sheet-grid { display: grid; grid-template-columns: repeat(8, minmax(38px, 1fr)); gap: 18px 20px; }
|
|
|
|
|
|
|
|
.sheet-grid button { min-height: 56px; border: 2px solid rgba(130, 137, 143, .34); border-radius: 3px; color: var(--exam-secondary); background: transparent; font-size: 18px; cursor: pointer; &:hover { border-color: var(--exam-accent); } &.answered { border-color: #3498f4; color: #fff; background: #3b9df4; } &.current { outline: 2px solid var(--exam-current); outline-offset: 2px; } }
|
|
|
|
|
|
|
|
.question-panel { min-width: 0; padding: 4px 0 0; }
|
|
|
|
|
|
|
|
.question-stem { margin: 0 0 22px; color: var(--exam-text); font-size: 19px; line-height: 1.65; white-space: pre-wrap; }
|
|
|
|
|
|
|
|
.choice-list { display: grid; gap: 12px; width: 100%; }
|
|
|
|
|
|
|
|
.judgement { grid-template-columns: 1fr 1fr; }
|
|
|
|
|
|
|
|
.question-panel :deep(.el-radio), .question-panel :deep(.el-checkbox) { min-height: 42px; margin-right: 0; padding: 10px 14px; border: 1px solid var(--exam-line); border-radius: 4px; color: var(--exam-secondary); background: rgba(4, 24, 39, .45); }
|
|
|
|
|
|
|
|
.question-panel :deep(.el-radio.is-checked), .question-panel :deep(.el-checkbox.is-checked) { border-color: #3b9df4; background: rgba(59, 157, 244, .18); }
|
|
|
|
|
|
|
|
.question-panel :deep(.el-radio__label), .question-panel :deep(.el-checkbox__label) { color: inherit; }
|
|
|
|
|
|
|
|
.question-panel :deep(.el-input__wrapper), .question-panel :deep(.el-textarea__inner) { color: var(--exam-text); background: rgba(3, 20, 34, .58); border-color: var(--exam-line); box-shadow: none; }
|
|
|
|
|
|
|
|
.file-answer { display: flex; align-items: center; gap: 14px; margin-top: 26px; color: var(--exam-text); font-size: 17px; }
|
|
|
|
|
|
|
|
.file-answer a { color: var(--exam-accent); }
|
|
|
|
|
|
|
|
.exam-navigation { display: flex; justify-content: center; gap: 140px; margin: 38px 0 0 34%; }
|
|
|
|
|
|
|
|
.exam-navigation button { min-width: 190px; height: 56px; border: 0; border-radius: 8px; color: #fff; font-size: 18px; font-weight: 700; cursor: pointer; &:disabled { opacity: .45; cursor: not-allowed; } }
|
|
|
|
|
|
|
|
.exam-navigation .previous { background: #bd7416; }
|
|
|
|
|
|
|
|
.exam-navigation .next { background: #159bd0; }
|
|
|
|
|
|
|
|
@media (max-width: 1000px) { .exam-toolbar { grid-template-columns: 140px 1fr auto; .toolbar-title { display: none; } .material-button { display: none; } } .exam-layout { grid-template-columns: 1fr; } .answer-sheet { border-right: 0; border-bottom: 1px solid var(--exam-line); padding-right: 0; } .exam-navigation { margin-left: 0; gap: 24px; } }
|
|
|
|
|
|
|
|
@media (max-width: 620px) { .take-page { padding: 14px 16px 24px; } .exam-toolbar { grid-template-columns: 1fr 1fr; gap: 10px; } .toolbar-type, .timer, .submit-button { min-height: 42px; font-size: 14px; } .timer { order: 3; } .submit-button { order: 4; } .sheet-grid { grid-template-columns: repeat(5, 1fr); gap: 10px; } .exam-navigation { gap: 12px; } .exam-navigation button { min-width: 0; flex: 1; } }
|
|
|
|
|
|
|
|
</style>
|
|
|
|
</style>
|
|
|
|
|