|
@@ -1,8 +1,975 @@
|
|
|
|
|
+<!-- 模拟考试答题页 -->
|
|
|
<template>
|
|
<template>
|
|
|
|
|
+ <view class="exam-screen">
|
|
|
|
|
+ <!-- 顶部栏 -->
|
|
|
|
|
+ <view class="topbar">
|
|
|
|
|
+ <view class="topbar-left" @click="requestSubmit(false)">‹ 交卷</view>
|
|
|
|
|
+ <view class="topbar-title">{{ examInfo.examName || '模拟考试' }}</view>
|
|
|
|
|
+ <view class="topbar-right" @click="toggleQuestionNav">题号</view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 剩余时间条 -->
|
|
|
|
|
+ <view class="time-bar">
|
|
|
|
|
+ <view class="time-bar-left">
|
|
|
|
|
+ <text class="time-label">剩余时间</text>
|
|
|
|
|
+ <text class="time-value">{{ formattedTime }}</text>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ <text class="time-tip">请合理安排答题时间</text>
|
|
|
|
|
+ </view>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 答题统计(答对/答错/正确率) -->
|
|
|
|
|
+ <view class="stat-row">
|
|
|
|
|
+ <view class="stat-item">
|
|
|
|
|
+ <text class="stat-num stat-correct">{{ correct }}</text>
|
|
|
|
|
+ <text class="stat-label">答对</text>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ <view class="stat-divider"></view>
|
|
|
|
|
+ <view class="stat-item">
|
|
|
|
|
+ <text class="stat-num stat-wrong">{{ incorrect }}</text>
|
|
|
|
|
+ <text class="stat-label">答错</text>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ <view class="stat-divider"></view>
|
|
|
|
|
+ <view class="stat-item">
|
|
|
|
|
+ <text class="stat-num">{{ (accuracy * 100).toFixed(0) }}%</text>
|
|
|
|
|
+ <text class="stat-label">正确率</text>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ <view class="stat-divider"></view>
|
|
|
|
|
+ <view class="stat-item">
|
|
|
|
|
+ <text class="stat-num">{{ totalCount }}</text>
|
|
|
|
|
+ <text class="stat-label">总题</text>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 题号导航面板 -->
|
|
|
|
|
+ <view v-if="showQuestionNav" class="q-nav-panel">
|
|
|
|
|
+ <view class="q-nav-scroll-wrapper">
|
|
|
|
|
+ <view class="q-nav-header">
|
|
|
|
|
+ <text class="q-nav-title">题目列表</text>
|
|
|
|
|
+ <text class="q-nav-close" @click="toggleQuestionNav">✕</text>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ <scroll-view scroll-y class="q-nav-scroll">
|
|
|
|
|
+ <view v-for="(group, gi) in questionTypeGroups" :key="gi" class="q-group">
|
|
|
|
|
+ <view class="q-group-title">{{ group.questionTypeName }}({{ group.questionCount }}题 {{ group.totalScore }}分)</view>
|
|
|
|
|
+ <view class="q-num-row">
|
|
|
|
|
+ <view
|
|
|
|
|
+ v-for="(q, qi) in group.questions"
|
|
|
|
|
+ :key="qi"
|
|
|
|
|
+ class="q-num"
|
|
|
|
|
+ :class="getNumClass(gi, qi, q)"
|
|
|
|
|
+ @click="selectQuestion(gi, qi)"
|
|
|
|
|
+ >{{ q.questionNo }}</view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </scroll-view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 题目内容 -->
|
|
|
|
|
+ <scroll-view scroll-y class="q-scroll-content">
|
|
|
|
|
+ <view v-if="currentQuestion.snapshotQuestionId" class="q-card">
|
|
|
|
|
+ <!-- 题目头部 -->
|
|
|
|
|
+ <view class="q-header">
|
|
|
|
|
+ <view class="q-header-left">
|
|
|
|
|
+ <text class="q-type-badge">{{ currentQuestion.questionTypeName }}</text>
|
|
|
|
|
+ <text class="q-num-text">第 {{ currentQuestion.questionNo }} 题</text>
|
|
|
|
|
+ <text class="q-score-text">({{ currentQuestion.questionScore }}分)</text>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ <view class="q-header-right">
|
|
|
|
|
+ <view v-if="currentQuestion.difficulty" class="q-stars">
|
|
|
|
|
+ <text
|
|
|
|
|
+ v-for="s in 4"
|
|
|
|
|
+ :key="s"
|
|
|
|
|
+ :class="['star-icon', s <= currentQuestion.difficulty ? 'star-active' : 'star-empty']"
|
|
|
|
|
+ >★</text>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ <view class="view-answer-btn" @click="viewAnswerShowType = !viewAnswerShowType">
|
|
|
|
|
+ {{ viewAnswerShowType ? '关闭答案' : '查看答案' }}
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 题目内容 -->
|
|
|
|
|
+ <view class="q-content">
|
|
|
|
|
+ <rich-text :nodes="currentQuestion.questionContent || ''"></rich-text>
|
|
|
|
|
+ </view>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 选项 -->
|
|
|
|
|
+ <view class="q-options">
|
|
|
|
|
+ <view
|
|
|
|
|
+ v-for="(opt, oi) in (currentQuestion.options || [])"
|
|
|
|
|
+ :key="oi"
|
|
|
|
|
+ class="q-option"
|
|
|
|
|
+ :class="{ selected: isSelected(opt.optionLabel) }"
|
|
|
|
|
+ @click="selectAnswer(opt)"
|
|
|
|
|
+ >
|
|
|
|
|
+ <view class="q-option-label">{{ opt.optionLabel }}</view>
|
|
|
|
|
+ <view class="q-option-content">
|
|
|
|
|
+ <rich-text :nodes="opt.optionContent || opt.optionLabel"></rich-text>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 查看答案区域 -->
|
|
|
|
|
+ <view v-if="viewAnswerShowType" class="answer-result-box">
|
|
|
|
|
+ <view class="answer-row">
|
|
|
|
|
+ <text class="answer-label">答案:</text>
|
|
|
|
|
+ <text class="answer-value">{{ arrayToString(currentQuestion.correctAnswerTags) }}</text>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ <view class="analysis-title">试题解析</view>
|
|
|
|
|
+ <view class="analysis-content">
|
|
|
|
|
+ <rich-text v-if="currentQuestion.analysis" :nodes="currentQuestion.analysis"></rich-text>
|
|
|
|
|
+ <text v-else class="analysis-empty">无</text>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ <view v-else-if="pageLoading" class="empty-tip">加载中...</view>
|
|
|
|
|
+ <view v-else class="empty-tip">暂无题目</view>
|
|
|
|
|
+ <view class="scroll-bottom-space"></view>
|
|
|
|
|
+ </scroll-view>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 上一题/下一题 -->
|
|
|
|
|
+ <view class="q-nav">
|
|
|
|
|
+ <view class="q-nav-btn" :class="{ disabled: isFirstQuestion }" @click="prevQuestion">上一题</view>
|
|
|
|
|
+ <view class="q-nav-btn q-nav-btn-next" :class="{ disabled: isLastQuestion }" @click="nextQuestion">下一题</view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 底部提交 -->
|
|
|
|
|
+ <view class="exam-bottom">
|
|
|
|
|
+ <view class="btn-primary" @click="requestSubmit(false)">提交试卷</view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 交卷结果遮罩 -->
|
|
|
|
|
+ <view v-if="showResult" class="result-shade">
|
|
|
|
|
+ <view class="result-card">
|
|
|
|
|
+ <view class="result-title">{{ resultData.title }}</view>
|
|
|
|
|
+ <view class="result-score">
|
|
|
|
|
+ <text class="result-score-num">{{ resultData.score }}</text>
|
|
|
|
|
+ <text class="result-score-unit">分</text>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ <view class="result-desc">{{ resultData.desc }}</view>
|
|
|
|
|
+ <view class="result-btns">
|
|
|
|
|
+ <view v-if="resultData.canRetake" class="result-btn result-btn-outline" @click="retakeExam">重新考试</view>
|
|
|
|
|
+ <view class="result-btn result-btn-primary" @click="closeResult">{{ resultData.canRetake ? '返回' : '确认' }}</view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
</template>
|
|
</template>
|
|
|
|
|
|
|
|
<script>
|
|
<script>
|
|
|
|
|
+ import {
|
|
|
|
|
+ examElExamAttemptReviewSidebar,
|
|
|
|
|
+ examElExamAttemptReviewQuestion,
|
|
|
|
|
+ examUserExamGetExamSurplusTime,
|
|
|
|
|
+ examUserExamAnswerSave,
|
|
|
|
|
+ examUserExamSubmit,
|
|
|
|
|
+ examUserExamStart,
|
|
|
|
|
+ } from '@/pages_safetyEducationExamination/api/index.js'
|
|
|
|
|
+
|
|
|
|
|
+ export default {
|
|
|
|
|
+ data() {
|
|
|
|
|
+ return {
|
|
|
|
|
+ examId: '',
|
|
|
|
|
+ attemptId: '',
|
|
|
|
|
+ examInfo: {},
|
|
|
|
|
+ questionTypeGroups: [],
|
|
|
|
|
+ currentQuestion: {},
|
|
|
|
|
+ groupIndex: 0,
|
|
|
|
|
+ questionIndex: 0,
|
|
|
|
|
+ remainingSeconds: 0,
|
|
|
|
|
+ timer: null,
|
|
|
|
|
+ hasWarnedTime: false,
|
|
|
|
|
+ showQuestionNav: false,
|
|
|
|
|
+ pageLoading: false,
|
|
|
|
|
+ isSaving: false,
|
|
|
|
|
+ isSubmitting: false,
|
|
|
|
|
+ hasSubmitted: false,
|
|
|
|
|
+ showResult: false,
|
|
|
|
|
+ resultData: {},
|
|
|
|
|
+ viewAnswerShowType: false,
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ computed: {
|
|
|
|
|
+ isFirstQuestion() {
|
|
|
|
|
+ return this.groupIndex === 0 && this.questionIndex === 0
|
|
|
|
|
+ },
|
|
|
|
|
+ isLastQuestion() {
|
|
|
|
|
+ const lastGi = this.questionTypeGroups.length - 1
|
|
|
|
|
+ if (lastGi < 0) return true
|
|
|
|
|
+ const lastGroup = this.questionTypeGroups[lastGi]
|
|
|
|
|
+ return this.groupIndex === lastGi && this.questionIndex === (lastGroup.questions.length - 1)
|
|
|
|
|
+ },
|
|
|
|
|
+ totalCount() {
|
|
|
|
|
+ return this.questionTypeGroups.reduce((s, g) => s + (g.questions ? g.questions.length : 0), 0)
|
|
|
|
|
+ },
|
|
|
|
|
+ // 答对:isCorrect === 1
|
|
|
|
|
+ correct() {
|
|
|
|
|
+ let count = 0
|
|
|
|
|
+ this.questionTypeGroups.forEach(g => {
|
|
|
|
|
+ ;(g.questions || []).forEach(q => { if (q.isCorrect === 1) count++ })
|
|
|
|
|
+ })
|
|
|
|
|
+ return count
|
|
|
|
|
+ },
|
|
|
|
|
+ // 答错:isCorrect === 0
|
|
|
|
|
+ incorrect() {
|
|
|
|
|
+ let count = 0
|
|
|
|
|
+ this.questionTypeGroups.forEach(g => {
|
|
|
|
|
+ ;(g.questions || []).forEach(q => { if (q.isCorrect === 0) count++ })
|
|
|
|
|
+ })
|
|
|
|
|
+ return count
|
|
|
|
|
+ },
|
|
|
|
|
+ // 正确率
|
|
|
|
|
+ accuracy() {
|
|
|
|
|
+ if (this.totalCount === 0) return 0
|
|
|
|
|
+ return parseFloat((this.correct / this.totalCount).toFixed(2))
|
|
|
|
|
+ },
|
|
|
|
|
+ formattedTime() {
|
|
|
|
|
+ const s = Math.max(0, Math.floor(this.remainingSeconds))
|
|
|
|
|
+ const m = Math.floor(s / 60)
|
|
|
|
|
+ const sec = s % 60
|
|
|
|
|
+ return m + '分' + (sec < 10 ? '0' : '') + sec + '秒'
|
|
|
|
|
+ },
|
|
|
|
|
+ },
|
|
|
|
|
+ onLoad(options) {
|
|
|
|
|
+ this.examId = options.examId || ''
|
|
|
|
|
+ this.attemptId = options.attemptId || ''
|
|
|
|
|
+ if (!this.attemptId) {
|
|
|
|
|
+ uni.showToast({ title: '考试信息无效', icon: 'none' })
|
|
|
|
|
+ setTimeout(() => uni.navigateBack(), 1500)
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ this.pageLoading = true
|
|
|
|
|
+ this.loadSidebar()
|
|
|
|
|
+ },
|
|
|
|
|
+ onShow() {
|
|
|
|
|
+ if (this.hasSubmitted || !this.attemptId) return
|
|
|
|
|
+ if (this.questionTypeGroups.length > 0) {
|
|
|
|
|
+ this.syncRemainingTime()
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ onHide() {
|
|
|
|
|
+ this.clearTimer()
|
|
|
|
|
+ this.saveCurrentAnswer()
|
|
|
|
|
+ },
|
|
|
|
|
+ onUnload() {
|
|
|
|
|
+ this.clearTimer()
|
|
|
|
|
+ this.saveCurrentAnswer()
|
|
|
|
|
+ },
|
|
|
|
|
+ methods: {
|
|
|
|
|
+ // 加载左侧题号导航
|
|
|
|
|
+ async loadSidebar() {
|
|
|
|
|
+ try {
|
|
|
|
|
+ const response = await examElExamAttemptReviewSidebar({ attemptId: this.attemptId })
|
|
|
|
|
+ const data = response.data
|
|
|
|
|
+ this.examInfo = {
|
|
|
|
|
+ examTypeName: data.examTypeName || '',
|
|
|
|
|
+ examName: data.examName || '',
|
|
|
|
|
+ questionCount: data.questionCount || 0,
|
|
|
|
|
+ totalScore: data.totalScore || 0,
|
|
|
|
|
+ passScore: data.passScore || 0,
|
|
|
|
|
+ }
|
|
|
|
|
+ this.$set(this, 'questionTypeGroups', data.questionTypeGroups || [])
|
|
|
|
|
+ this.groupIndex = 0
|
|
|
|
|
+ this.questionIndex = 0
|
|
|
|
|
+ const firstGroup = this.questionTypeGroups[0]
|
|
|
|
|
+ if (firstGroup && firstGroup.questions && firstGroup.questions.length > 0) {
|
|
|
|
|
+ await this.loadQuestion(firstGroup.questions[0].snapshotQuestionId)
|
|
|
|
|
+ this.syncRemainingTime()
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (e) {
|
|
|
|
|
+ uni.showToast({ title: '加载失败', icon: 'none' })
|
|
|
|
|
+ } finally {
|
|
|
|
|
+ this.pageLoading = false
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ // 加载题目详情(examScene:2 模拟考试)
|
|
|
|
|
+ async loadQuestion(snapshotQuestionId) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ const response = await examElExamAttemptReviewQuestion({
|
|
|
|
|
+ attemptId: this.attemptId,
|
|
|
|
|
+ snapshotQuestionId: snapshotQuestionId,
|
|
|
|
|
+ examScene: 2,
|
|
|
|
|
+ })
|
|
|
|
|
+ this.$set(this, 'currentQuestion', response.data)
|
|
|
|
|
+ this.$set(this, 'viewAnswerShowType', false)
|
|
|
|
|
+ } catch (e) {
|
|
|
|
|
+ uni.showToast({ title: '题目加载失败', icon: 'none' })
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ // 同步剩余时间并启动倒计时
|
|
|
|
|
+ async syncRemainingTime() {
|
|
|
|
|
+ try {
|
|
|
|
|
+ const response = await examUserExamGetExamSurplusTime({ attemptId: this.attemptId })
|
|
|
|
|
+ this.remainingSeconds = Number(response.data) || 0
|
|
|
|
|
+ this.clearTimer()
|
|
|
|
|
+ this.startTimer()
|
|
|
|
|
+ } catch (e) {
|
|
|
|
|
+ console.error('获取剩余时间失败', e)
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ startTimer() {
|
|
|
|
|
+ if (this.timer) return
|
|
|
|
|
+ this.timer = setInterval(() => {
|
|
|
|
|
+ if (this.remainingSeconds <= 0) {
|
|
|
|
|
+ this.clearTimer()
|
|
|
|
|
+ this.autoSubmit()
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ this.remainingSeconds--
|
|
|
|
|
+ if (this.remainingSeconds === 60 && !this.hasWarnedTime) {
|
|
|
|
|
+ this.hasWarnedTime = true
|
|
|
|
|
+ uni.showToast({ title: '请注意剩余时间', icon: 'none', duration: 2000 })
|
|
|
|
|
+ }
|
|
|
|
|
+ }, 1000)
|
|
|
|
|
+ },
|
|
|
|
|
+ clearTimer() {
|
|
|
|
|
+ if (this.timer) {
|
|
|
|
|
+ clearInterval(this.timer)
|
|
|
|
|
+ this.timer = null
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ // 选择答案
|
|
|
|
|
+ selectAnswer(opt) {
|
|
|
|
|
+ if (!this.currentQuestion.snapshotQuestionId) return
|
|
|
|
|
+ let tags = Array.isArray(this.currentQuestion.answerTags) ? [...this.currentQuestion.answerTags] : []
|
|
|
|
|
+ const qType = this.currentQuestion.questionType
|
|
|
|
|
+ if (qType == 2) {
|
|
|
|
|
+ // 多选
|
|
|
|
|
+ const idx = tags.indexOf(opt.optionLabel)
|
|
|
|
|
+ if (idx === -1) { tags.push(opt.optionLabel) } else { tags.splice(idx, 1) }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ // 单选 / 判断
|
|
|
|
|
+ tags = [opt.optionLabel]
|
|
|
|
|
+ }
|
|
|
|
|
+ this.$set(this.currentQuestion, 'answerTags', tags)
|
|
|
|
|
+ },
|
|
|
|
|
+ isSelected(label) {
|
|
|
|
|
+ const tags = this.currentQuestion.answerTags
|
|
|
|
|
+ return Array.isArray(tags) && tags.indexOf(label) !== -1
|
|
|
|
|
+ },
|
|
|
|
|
+ // 保存当前答案,同时回写 isCorrect 到题号列表
|
|
|
|
|
+ saveCurrentAnswer() {
|
|
|
|
|
+ const q = this.currentQuestion
|
|
|
|
|
+ if (!q || !q.snapshotQuestionId) return Promise.resolve()
|
|
|
|
|
+ const tags = Array.isArray(q.answerTags) ? q.answerTags.filter(Boolean) : []
|
|
|
|
|
+ if (tags.length === 0) return Promise.resolve()
|
|
|
|
|
+ return examUserExamAnswerSave({
|
|
|
|
|
+ attemptId: this.attemptId,
|
|
|
|
|
+ snapshotQuestionId: q.snapshotQuestionId,
|
|
|
|
|
+ userAnswer: tags.join(','),
|
|
|
|
|
+ }).then(response => {
|
|
|
|
|
+ // response.data 是 isCorrect 值(1正确 0错误)
|
|
|
|
|
+ const groups = this.questionTypeGroups
|
|
|
|
|
+ if (groups[this.groupIndex] && groups[this.groupIndex].questions[this.questionIndex]) {
|
|
|
|
|
+ this.$set(groups[this.groupIndex].questions[this.questionIndex], 'isCorrect', response.data)
|
|
|
|
|
+ }
|
|
|
|
|
+ }).catch(e => {
|
|
|
|
|
+ console.error('保存答案失败', e)
|
|
|
|
|
+ })
|
|
|
|
|
+ },
|
|
|
|
|
+ // 切换题目(先保存当前答案)
|
|
|
|
|
+ async changeQuestion(targetGi, targetQi) {
|
|
|
|
|
+ if (this.isSaving) return
|
|
|
|
|
+ if (targetGi === this.groupIndex && targetQi === this.questionIndex) return
|
|
|
|
|
+ const group = this.questionTypeGroups[targetGi]
|
|
|
|
|
+ if (!group || !group.questions || !group.questions[targetQi]) return
|
|
|
|
|
+ this.isSaving = true
|
|
|
|
|
+ await this.saveCurrentAnswer()
|
|
|
|
|
+ this.isSaving = false
|
|
|
|
|
+ this.groupIndex = targetGi
|
|
|
|
|
+ this.questionIndex = targetQi
|
|
|
|
|
+ await this.loadQuestion(group.questions[targetQi].snapshotQuestionId)
|
|
|
|
|
+ },
|
|
|
|
|
+ selectQuestion(gi, qi) {
|
|
|
|
|
+ this.changeQuestion(gi, qi)
|
|
|
|
|
+ this.showQuestionNav = false
|
|
|
|
|
+ },
|
|
|
|
|
+ prevQuestion() {
|
|
|
|
|
+ if (this.isFirstQuestion || this.isSaving) return
|
|
|
|
|
+ if (this.questionIndex > 0) {
|
|
|
|
|
+ this.changeQuestion(this.groupIndex, this.questionIndex - 1)
|
|
|
|
|
+ } else {
|
|
|
|
|
+ const prevGi = this.groupIndex - 1
|
|
|
|
|
+ const prevGroup = this.questionTypeGroups[prevGi]
|
|
|
|
|
+ if (prevGroup) this.changeQuestion(prevGi, prevGroup.questions.length - 1)
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ nextQuestion() {
|
|
|
|
|
+ if (this.isLastQuestion || this.isSaving) return
|
|
|
|
|
+ const currentGroup = this.questionTypeGroups[this.groupIndex]
|
|
|
|
|
+ if (this.questionIndex < currentGroup.questions.length - 1) {
|
|
|
|
|
+ this.changeQuestion(this.groupIndex, this.questionIndex + 1)
|
|
|
|
|
+ } else {
|
|
|
|
|
+ this.changeQuestion(this.groupIndex + 1, 0)
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ toggleQuestionNav() {
|
|
|
|
|
+ this.showQuestionNav = !this.showQuestionNav
|
|
|
|
|
+ },
|
|
|
|
|
+ // 题号样式:答对绿、答错红、当前蓝、未答灰
|
|
|
|
|
+ getNumClass(gi, qi, q) {
|
|
|
|
|
+ if (gi === this.groupIndex && qi === this.questionIndex) return 'current'
|
|
|
|
|
+ if (q.isCorrect === 1) return 'correct'
|
|
|
|
|
+ if (q.isCorrect === 0) return 'wrong'
|
|
|
|
|
+ return ''
|
|
|
|
|
+ },
|
|
|
|
|
+ // 提交前确认
|
|
|
|
|
+ async requestSubmit(isAuto) {
|
|
|
|
|
+ if (this.isSubmitting || this.hasSubmitted) return
|
|
|
|
|
+ this.isSubmitting = true
|
|
|
|
|
+ await this.saveCurrentAnswer()
|
|
|
|
|
+ // 统计未答题数
|
|
|
|
|
+ let unanswered = 0
|
|
|
|
|
+ this.questionTypeGroups.forEach(g => {
|
|
|
|
|
+ ;(g.questions || []).forEach(q => { if (q.isCorrect == null) unanswered++ })
|
|
|
|
|
+ })
|
|
|
|
|
+ if (isAuto) {
|
|
|
|
|
+ await this.doSubmit()
|
|
|
|
|
+ this.isSubmitting = false
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ const content = unanswered > 0 ? `还有${unanswered}题未答,确认要交卷吗?` : '确认要交卷吗?'
|
|
|
|
|
+ uni.showModal({
|
|
|
|
|
+ title: '提示',
|
|
|
|
|
+ content: content,
|
|
|
|
|
+ success: async (res) => {
|
|
|
|
|
+ if (res.confirm) { await this.doSubmit() }
|
|
|
|
|
+ this.isSubmitting = false
|
|
|
|
|
+ },
|
|
|
|
|
+ fail: () => { this.isSubmitting = false }
|
|
|
|
|
+ })
|
|
|
|
|
+ },
|
|
|
|
|
+ async autoSubmit() {
|
|
|
|
|
+ if (this.isSubmitting || this.hasSubmitted) return
|
|
|
|
|
+ this.isSubmitting = true
|
|
|
|
|
+ await this.saveCurrentAnswer()
|
|
|
|
|
+ uni.showToast({ title: '考试时间结束,正在提交…', icon: 'none' })
|
|
|
|
|
+ await this.doSubmit()
|
|
|
|
|
+ this.isSubmitting = false
|
|
|
|
|
+ },
|
|
|
|
|
+ async doSubmit() {
|
|
|
|
|
+ try {
|
|
|
|
|
+ const response = await examUserExamSubmit({ attemptId: this.attemptId })
|
|
|
|
|
+ this.hasSubmitted = true
|
|
|
|
|
+ this.clearTimer()
|
|
|
|
|
+ this.buildResult(response.data)
|
|
|
|
|
+ this.showResult = true
|
|
|
|
|
+ } catch (e) {
|
|
|
|
|
+ uni.showToast({ title: '交卷失败', icon: 'none' })
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ buildResult(resp) {
|
|
|
|
|
+ const score = resp.totalScore || 0
|
|
|
|
|
+ const pass = score >= (this.examInfo.passScore || 0)
|
|
|
|
|
+ if (pass) {
|
|
|
|
|
+ this.resultData = {
|
|
|
|
|
+ title: '模拟考试通过',
|
|
|
|
|
+ score: score,
|
|
|
|
|
+ desc: '本次模拟考试成绩有效',
|
|
|
|
|
+ canRetake: false,
|
|
|
|
|
+ }
|
|
|
|
|
+ } else if (resp.canContinueExam === 1) {
|
|
|
|
|
+ this.resultData = {
|
|
|
|
|
+ title: '本次模拟考试不及格',
|
|
|
|
|
+ score: score,
|
|
|
|
|
+ desc: `未达及格线 ${this.examInfo.passScore} 分,可重新考试`,
|
|
|
|
|
+ canRetake: true,
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ this.resultData = {
|
|
|
|
|
+ title: '本次模拟考试不及格',
|
|
|
|
|
+ score: score,
|
|
|
|
|
+ desc: '未达及格线',
|
|
|
|
|
+ canRetake: false,
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ async retakeExam() {
|
|
|
|
|
+ try {
|
|
|
|
|
+ const response = await examUserExamStart({ examId: this.examId, examScene: 2 })
|
|
|
|
|
+ const data = response.data
|
|
|
|
|
+ if (data && data.attemptId) {
|
|
|
|
|
+ this.attemptId = data.attemptId
|
|
|
|
|
+ this.showResult = false
|
|
|
|
|
+ this.hasSubmitted = false
|
|
|
|
|
+ this.isSubmitting = false
|
|
|
|
|
+ this.hasWarnedTime = false
|
|
|
|
|
+ this.viewAnswerShowType = false
|
|
|
|
|
+ this.$set(this, 'questionTypeGroups', [])
|
|
|
|
|
+ this.$set(this, 'currentQuestion', {})
|
|
|
|
|
+ this.groupIndex = 0
|
|
|
|
|
+ this.questionIndex = 0
|
|
|
|
|
+ this.remainingSeconds = 0
|
|
|
|
|
+ this.pageLoading = true
|
|
|
|
|
+ this.loadSidebar()
|
|
|
|
|
+ } else {
|
|
|
|
|
+ uni.showToast({ title: response.message || '重新考试失败', icon: 'none' })
|
|
|
|
|
+ uni.navigateBack()
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (e) {
|
|
|
|
|
+ uni.showToast({ title: '重新考试失败', icon: 'none' })
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ closeResult() {
|
|
|
|
|
+ this.showResult = false
|
|
|
|
|
+ uni.navigateBack()
|
|
|
|
|
+ },
|
|
|
|
|
+ // 答案标签转显示文字(Y→对 N→错)
|
|
|
|
|
+ arrayToString(list) {
|
|
|
|
|
+ if (!Array.isArray(list)) return ''
|
|
|
|
|
+ return list.map(item => {
|
|
|
|
|
+ if (item === 'Y') return '对'
|
|
|
|
|
+ if (item === 'N') return '错'
|
|
|
|
|
+ return item
|
|
|
|
|
+ }).join(',')
|
|
|
|
|
+ },
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
</script>
|
|
</script>
|
|
|
|
|
|
|
|
-<style>
|
|
|
|
|
-</style>
|
|
|
|
|
|
|
+<style lang="stylus" scoped>
|
|
|
|
|
+ .exam-screen
|
|
|
|
|
+ height 100%
|
|
|
|
|
+ display flex
|
|
|
|
|
+ flex-direction column
|
|
|
|
|
+ background #f5f7fa
|
|
|
|
|
+ position relative
|
|
|
|
|
+
|
|
|
|
|
+ .topbar
|
|
|
|
|
+ display flex
|
|
|
|
|
+ align-items center
|
|
|
|
|
+ justify-content space-between
|
|
|
|
|
+ height 88rpx
|
|
|
|
|
+ padding 0 28rpx
|
|
|
|
|
+ background #fff
|
|
|
|
|
+ border-bottom 1rpx solid #e8edf3
|
|
|
|
|
+ flex-shrink 0
|
|
|
|
|
+
|
|
|
|
|
+ .topbar-left
|
|
|
|
|
+ font-size 28rpx
|
|
|
|
|
+ color #1677ff
|
|
|
|
|
+ min-width 80rpx
|
|
|
|
|
+
|
|
|
|
|
+ .topbar-title
|
|
|
|
|
+ font-size 28rpx
|
|
|
|
|
+ font-weight 600
|
|
|
|
|
+ color #222
|
|
|
|
|
+ flex 1
|
|
|
|
|
+ text-align center
|
|
|
|
|
+
|
|
|
|
|
+ .topbar-right
|
|
|
|
|
+ font-size 28rpx
|
|
|
|
|
+ color #1677ff
|
|
|
|
|
+ min-width 80rpx
|
|
|
|
|
+ text-align right
|
|
|
|
|
+
|
|
|
|
|
+ .time-bar
|
|
|
|
|
+ display flex
|
|
|
|
|
+ align-items center
|
|
|
|
|
+ justify-content space-between
|
|
|
|
|
+ padding 20rpx 28rpx
|
|
|
|
|
+ background linear-gradient(90deg, #1677ff 0%, #0958d9 100%)
|
|
|
|
|
+ flex-shrink 0
|
|
|
|
|
+
|
|
|
|
|
+ .time-bar-left
|
|
|
|
|
+ display flex
|
|
|
|
|
+ align-items baseline
|
|
|
|
|
+
|
|
|
|
|
+ .time-label
|
|
|
|
|
+ font-size 24rpx
|
|
|
|
|
+ color rgba(255,255,255,0.85)
|
|
|
|
|
+ margin-right 16rpx
|
|
|
|
|
+
|
|
|
|
|
+ .time-value
|
|
|
|
|
+ font-size 44rpx
|
|
|
|
|
+ font-weight 700
|
|
|
|
|
+ color #fff
|
|
|
|
|
+
|
|
|
|
|
+ .time-tip
|
|
|
|
|
+ font-size 22rpx
|
|
|
|
|
+ color rgba(255,255,255,0.75)
|
|
|
|
|
+
|
|
|
|
|
+ .stat-row
|
|
|
|
|
+ display flex
|
|
|
|
|
+ align-items center
|
|
|
|
|
+ background #fff
|
|
|
|
|
+ padding 20rpx 0
|
|
|
|
|
+ flex-shrink 0
|
|
|
|
|
+ border-bottom 1rpx solid #e8edf3
|
|
|
|
|
+
|
|
|
|
|
+ .stat-item
|
|
|
|
|
+ flex 1
|
|
|
|
|
+ display flex
|
|
|
|
|
+ flex-direction column
|
|
|
|
|
+ align-items center
|
|
|
|
|
+
|
|
|
|
|
+ .stat-divider
|
|
|
|
|
+ width 1rpx
|
|
|
|
|
+ height 40rpx
|
|
|
|
|
+ background #eee
|
|
|
|
|
+
|
|
|
|
|
+ .stat-num
|
|
|
|
|
+ font-size 36rpx
|
|
|
|
|
+ font-weight 700
|
|
|
|
|
+ color #333
|
|
|
|
|
+ line-height 1
|
|
|
|
|
+
|
|
|
|
|
+ .stat-correct
|
|
|
|
|
+ color #52c41a
|
|
|
|
|
+
|
|
|
|
|
+ .stat-wrong
|
|
|
|
|
+ color #ff4d4f
|
|
|
|
|
+
|
|
|
|
|
+ .stat-label
|
|
|
|
|
+ font-size 22rpx
|
|
|
|
|
+ color #999
|
|
|
|
|
+ margin-top 6rpx
|
|
|
|
|
+
|
|
|
|
|
+ .q-nav-panel
|
|
|
|
|
+ position fixed
|
|
|
|
|
+ top 0
|
|
|
|
|
+ left 0
|
|
|
|
|
+ right 0
|
|
|
|
|
+ bottom 0
|
|
|
|
|
+ background rgba(0,0,0,0.45)
|
|
|
|
|
+ z-index 100
|
|
|
|
|
+ display flex
|
|
|
|
|
+ flex-direction column
|
|
|
|
|
+ justify-content flex-end
|
|
|
|
|
+
|
|
|
|
|
+ .q-nav-scroll-wrapper
|
|
|
|
|
+ background #fff
|
|
|
|
|
+ border-radius 32rpx 32rpx 0 0
|
|
|
|
|
+ max-height 70vh
|
|
|
|
|
+ display flex
|
|
|
|
|
+ flex-direction column
|
|
|
|
|
+
|
|
|
|
|
+ .q-nav-header
|
|
|
|
|
+ display flex
|
|
|
|
|
+ align-items center
|
|
|
|
|
+ justify-content space-between
|
|
|
|
|
+ padding 28rpx 28rpx 16rpx
|
|
|
|
|
+ flex-shrink 0
|
|
|
|
|
+
|
|
|
|
|
+ .q-nav-title
|
|
|
|
|
+ font-size 30rpx
|
|
|
|
|
+ font-weight 600
|
|
|
|
|
+ color #222
|
|
|
|
|
+
|
|
|
|
|
+ .q-nav-close
|
|
|
|
|
+ font-size 32rpx
|
|
|
|
|
+ color #999
|
|
|
|
|
+ padding 10rpx
|
|
|
|
|
+
|
|
|
|
|
+ .q-nav-scroll
|
|
|
|
|
+ flex 1
|
|
|
|
|
+ overflow hidden
|
|
|
|
|
+ padding-bottom 40rpx
|
|
|
|
|
+
|
|
|
|
|
+ .q-group
|
|
|
|
|
+ padding 0 28rpx 16rpx
|
|
|
|
|
+
|
|
|
|
|
+ .q-group-title
|
|
|
|
|
+ font-size 24rpx
|
|
|
|
|
+ color #666
|
|
|
|
|
+ line-height 60rpx
|
|
|
|
|
+
|
|
|
|
|
+ .q-num-row
|
|
|
|
|
+ display flex
|
|
|
|
|
+ flex-wrap wrap
|
|
|
|
|
+
|
|
|
|
|
+ .q-num
|
|
|
|
|
+ width 72rpx
|
|
|
|
|
+ height 72rpx
|
|
|
|
|
+ line-height 72rpx
|
|
|
|
|
+ text-align center
|
|
|
|
|
+ font-size 24rpx
|
|
|
|
|
+ border-radius 12rpx
|
|
|
|
|
+ margin 8rpx
|
|
|
|
|
+ background #f4f6fa
|
|
|
|
|
+ color #333
|
|
|
|
|
+ border 1rpx solid transparent
|
|
|
|
|
+
|
|
|
|
|
+ .q-num.correct
|
|
|
|
|
+ background #f6ffed
|
|
|
|
|
+ color #52c41a
|
|
|
|
|
+ border-color #b7eb8f
|
|
|
|
|
+
|
|
|
|
|
+ .q-num.wrong
|
|
|
|
|
+ background #fff2f0
|
|
|
|
|
+ color #ff4d4f
|
|
|
|
|
+ border-color #ffa39e
|
|
|
|
|
+
|
|
|
|
|
+ .q-num.current
|
|
|
|
|
+ background #1677ff
|
|
|
|
|
+ color #fff
|
|
|
|
|
+
|
|
|
|
|
+ .q-scroll-content
|
|
|
|
|
+ flex 1
|
|
|
|
|
+ overflow hidden
|
|
|
|
|
+
|
|
|
|
|
+ .q-card
|
|
|
|
|
+ margin 24rpx
|
|
|
|
|
+ padding 28rpx
|
|
|
|
|
+ background #fff
|
|
|
|
|
+ border-radius 20rpx
|
|
|
|
|
+ border 1rpx solid #dde3ed
|
|
|
|
|
+
|
|
|
|
|
+ .q-header
|
|
|
|
|
+ display flex
|
|
|
|
|
+ align-items center
|
|
|
|
|
+ justify-content space-between
|
|
|
|
|
+ margin-bottom 20rpx
|
|
|
|
|
+
|
|
|
|
|
+ .q-header-left
|
|
|
|
|
+ display flex
|
|
|
|
|
+ align-items center
|
|
|
|
|
+ flex 1
|
|
|
|
|
+ flex-wrap wrap
|
|
|
|
|
+
|
|
|
|
|
+ .q-header-right
|
|
|
|
|
+ display flex
|
|
|
|
|
+ align-items center
|
|
|
|
|
+ flex-shrink 0
|
|
|
|
|
+ margin-left 12rpx
|
|
|
|
|
+
|
|
|
|
|
+ .q-type-badge
|
|
|
|
|
+ font-size 20rpx
|
|
|
|
|
+ padding 4rpx 14rpx
|
|
|
|
|
+ background #e6f4ff
|
|
|
|
|
+ color #1677ff
|
|
|
|
|
+ border 1rpx solid #91caff
|
|
|
|
|
+ border-radius 8rpx
|
|
|
|
|
+ margin-right 12rpx
|
|
|
|
|
+
|
|
|
|
|
+ .q-num-text
|
|
|
|
|
+ font-size 26rpx
|
|
|
|
|
+ color #333
|
|
|
|
|
+
|
|
|
|
|
+ .q-score-text
|
|
|
|
|
+ font-size 22rpx
|
|
|
|
|
+ color #999
|
|
|
|
|
+
|
|
|
|
|
+ .q-stars
|
|
|
|
|
+ display flex
|
|
|
|
|
+ align-items center
|
|
|
|
|
+ margin-right 16rpx
|
|
|
|
|
+
|
|
|
|
|
+ .star-icon
|
|
|
|
|
+ font-size 28rpx
|
|
|
|
|
+ font-style normal
|
|
|
|
|
+
|
|
|
|
|
+ .star-active
|
|
|
|
|
+ color #fadb14
|
|
|
|
|
+
|
|
|
|
|
+ .star-empty
|
|
|
|
|
+ color #d9d9d9
|
|
|
|
|
+
|
|
|
|
|
+ .view-answer-btn
|
|
|
|
|
+ font-size 22rpx
|
|
|
|
|
+ padding 6rpx 18rpx
|
|
|
|
|
+ background #0183fa
|
|
|
|
|
+ color #fff
|
|
|
|
|
+ border-radius 8rpx
|
|
|
|
|
+ white-space nowrap
|
|
|
|
|
+
|
|
|
|
|
+ .q-content
|
|
|
|
|
+ font-size 28rpx
|
|
|
|
|
+ line-height 1.8
|
|
|
|
|
+ color #222
|
|
|
|
|
+ margin-bottom 24rpx
|
|
|
|
|
+
|
|
|
|
|
+ .q-options
|
|
|
|
|
+ display flex
|
|
|
|
|
+ flex-direction column
|
|
|
|
|
+
|
|
|
|
|
+ .q-option
|
|
|
|
|
+ display flex
|
|
|
|
|
+ align-items center
|
|
|
|
|
+ padding 22rpx 20rpx
|
|
|
|
|
+ margin-bottom 16rpx
|
|
|
|
|
+ border 2rpx solid #dde3ed
|
|
|
|
|
+ border-radius 16rpx
|
|
|
|
|
+ background #fff
|
|
|
|
|
+
|
|
|
|
|
+ .q-option.selected
|
|
|
|
|
+ border-color #1677ff
|
|
|
|
|
+ background #e6f4ff
|
|
|
|
|
+
|
|
|
|
|
+ .q-option-label
|
|
|
|
|
+ width 48rpx
|
|
|
|
|
+ height 48rpx
|
|
|
|
|
+ line-height 48rpx
|
|
|
|
|
+ text-align center
|
|
|
|
|
+ border-radius 50%
|
|
|
|
|
+ background #f4f6fa
|
|
|
|
|
+ color #333
|
|
|
|
|
+ font-size 24rpx
|
|
|
|
|
+ font-weight 600
|
|
|
|
|
+ margin-right 20rpx
|
|
|
|
|
+ flex-shrink 0
|
|
|
|
|
+
|
|
|
|
|
+ .q-option.selected .q-option-label
|
|
|
|
|
+ background #1677ff
|
|
|
|
|
+ color #fff
|
|
|
|
|
+
|
|
|
|
|
+ .q-option-content
|
|
|
|
|
+ flex 1
|
|
|
|
|
+ font-size 26rpx
|
|
|
|
|
+ color #333
|
|
|
|
|
+ line-height 1.6
|
|
|
|
|
+
|
|
|
|
|
+ .answer-result-box
|
|
|
|
|
+ background #f5f5f5
|
|
|
|
|
+ border-radius 12rpx
|
|
|
|
|
+ padding 24rpx 28rpx
|
|
|
|
|
+ margin-top 20rpx
|
|
|
|
|
+
|
|
|
|
|
+ .answer-row
|
|
|
|
|
+ display flex
|
|
|
|
|
+ align-items center
|
|
|
|
|
+ margin-bottom 16rpx
|
|
|
|
|
+
|
|
|
|
|
+ .answer-label
|
|
|
|
|
+ font-size 26rpx
|
|
|
|
|
+ font-weight 600
|
|
|
|
|
+ color #333
|
|
|
|
|
+
|
|
|
|
|
+ .answer-value
|
|
|
|
|
+ font-size 26rpx
|
|
|
|
|
+ color #1677ff
|
|
|
|
|
+ font-weight 700
|
|
|
|
|
+
|
|
|
|
|
+ .analysis-title
|
|
|
|
|
+ font-size 26rpx
|
|
|
|
|
+ font-weight 600
|
|
|
|
|
+ color #333
|
|
|
|
|
+ margin-bottom 12rpx
|
|
|
|
|
+
|
|
|
|
|
+ .analysis-content
|
|
|
|
|
+ font-size 24rpx
|
|
|
|
|
+ color #666
|
|
|
|
|
+ line-height 1.7
|
|
|
|
|
+ padding 0 8rpx
|
|
|
|
|
+
|
|
|
|
|
+ .analysis-empty
|
|
|
|
|
+ font-size 24rpx
|
|
|
|
|
+ color #aaa
|
|
|
|
|
+
|
|
|
|
|
+ .scroll-bottom-space
|
|
|
|
|
+ height 200rpx
|
|
|
|
|
+
|
|
|
|
|
+ .q-nav
|
|
|
|
|
+ display flex
|
|
|
|
|
+ background #fff
|
|
|
|
|
+ border-top 1rpx solid #e8edf3
|
|
|
|
|
+ flex-shrink 0
|
|
|
|
|
+
|
|
|
|
|
+ .q-nav-btn
|
|
|
|
|
+ flex 1
|
|
|
|
|
+ height 88rpx
|
|
|
|
|
+ line-height 88rpx
|
|
|
|
|
+ text-align center
|
|
|
|
|
+ font-size 28rpx
|
|
|
|
|
+ color #1677ff
|
|
|
|
|
+
|
|
|
|
|
+ .q-nav-btn.q-nav-btn-next
|
|
|
|
|
+ border-left 1rpx solid #e8edf3
|
|
|
|
|
+
|
|
|
|
|
+ .q-nav-btn.disabled
|
|
|
|
|
+ color #ccc
|
|
|
|
|
+
|
|
|
|
|
+ .exam-bottom
|
|
|
|
|
+ padding 20rpx 24rpx
|
|
|
|
|
+ padding-bottom calc(20rpx + env(safe-area-inset-bottom))
|
|
|
|
|
+ background #fff
|
|
|
|
|
+ border-top 1rpx solid #e8edf3
|
|
|
|
|
+ flex-shrink 0
|
|
|
|
|
+
|
|
|
|
|
+ .btn-primary
|
|
|
|
|
+ background #1677ff
|
|
|
|
|
+ color #fff
|
|
|
|
|
+ border-radius 16rpx
|
|
|
|
|
+ font-size 30rpx
|
|
|
|
|
+ font-weight 600
|
|
|
|
|
+ height 88rpx
|
|
|
|
|
+ line-height 88rpx
|
|
|
|
|
+ text-align center
|
|
|
|
|
+
|
|
|
|
|
+ .result-shade
|
|
|
|
|
+ position fixed
|
|
|
|
|
+ top 0
|
|
|
|
|
+ left 0
|
|
|
|
|
+ right 0
|
|
|
|
|
+ bottom 0
|
|
|
|
|
+ background rgba(0,0,0,0.55)
|
|
|
|
|
+ z-index 200
|
|
|
|
|
+ display flex
|
|
|
|
|
+ align-items center
|
|
|
|
|
+ justify-content center
|
|
|
|
|
+
|
|
|
|
|
+ .result-card
|
|
|
|
|
+ width 580rpx
|
|
|
|
|
+ background #fff
|
|
|
|
|
+ border-radius 24rpx
|
|
|
|
|
+ padding 48rpx 40rpx 36rpx
|
|
|
|
|
+ display flex
|
|
|
|
|
+ flex-direction column
|
|
|
|
|
+ align-items center
|
|
|
|
|
+
|
|
|
|
|
+ .result-title
|
|
|
|
|
+ font-size 32rpx
|
|
|
|
|
+ font-weight 700
|
|
|
|
|
+ color #222
|
|
|
|
|
+ margin-bottom 20rpx
|
|
|
|
|
+
|
|
|
|
|
+ .result-score
|
|
|
|
|
+ display flex
|
|
|
|
|
+ align-items baseline
|
|
|
|
|
+ margin-bottom 16rpx
|
|
|
|
|
+
|
|
|
|
|
+ .result-score-num
|
|
|
|
|
+ font-size 80rpx
|
|
|
|
|
+ font-weight 700
|
|
|
|
|
+ color #F59A23
|
|
|
|
|
+ line-height 1
|
|
|
|
|
+
|
|
|
|
|
+ .result-score-unit
|
|
|
|
|
+ font-size 30rpx
|
|
|
|
|
+ color #F59A23
|
|
|
|
|
+ margin-left 8rpx
|
|
|
|
|
+
|
|
|
|
|
+ .result-desc
|
|
|
|
|
+ font-size 26rpx
|
|
|
|
|
+ color #666
|
|
|
|
|
+ text-align center
|
|
|
|
|
+ margin-bottom 36rpx
|
|
|
|
|
+ line-height 1.6
|
|
|
|
|
+
|
|
|
|
|
+ .result-btns
|
|
|
|
|
+ display flex
|
|
|
|
|
+ width 100%
|
|
|
|
|
+
|
|
|
|
|
+ .result-btn
|
|
|
|
|
+ flex 1
|
|
|
|
|
+ height 80rpx
|
|
|
|
|
+ line-height 80rpx
|
|
|
|
|
+ text-align center
|
|
|
|
|
+ border-radius 14rpx
|
|
|
|
|
+ font-size 28rpx
|
|
|
|
|
+
|
|
|
|
|
+ .result-btn-outline
|
|
|
|
|
+ border 1rpx solid #1677ff
|
|
|
|
|
+ color #1677ff
|
|
|
|
|
+ margin-right 20rpx
|
|
|
|
|
+
|
|
|
|
|
+ .result-btn-primary
|
|
|
|
|
+ background #1677ff
|
|
|
|
|
+ color #fff
|
|
|
|
|
+
|
|
|
|
|
+ .empty-tip
|
|
|
|
|
+ text-align center
|
|
|
|
|
+ padding 80rpx 0
|
|
|
|
|
+ color #aaa
|
|
|
|
|
+ font-size 26rpx
|
|
|
|
|
+</style>
|