|
@@ -0,0 +1,513 @@
|
|
|
+<template>
|
|
|
+ <!-- 导航栏 -->
|
|
|
+ <van-nav-bar
|
|
|
+ :title="query.vehicle + '>' + query.name"
|
|
|
+ left-arrow
|
|
|
+ @click-left="back"
|
|
|
+ fixed
|
|
|
+ placeholder
|
|
|
+ >
|
|
|
+ <template #right>
|
|
|
+ <m-icon type="shezhi" @click="setShow = true" />
|
|
|
+ </template>
|
|
|
+ </van-nav-bar>
|
|
|
+ <!-- 导航栏end -->
|
|
|
+ <!-- 答题模式选择 -->
|
|
|
+ <div class="answerType">
|
|
|
+ <span
|
|
|
+ v-for="(answerType, index) in answerTypeList"
|
|
|
+ :key="index"
|
|
|
+ :class="{ selected: currentType == index }"
|
|
|
+ @click="currentType = index"
|
|
|
+ >{{ answerType.name }}</span
|
|
|
+ >
|
|
|
+ <span :class="{ selected: aotuPlayFlag }" @click="aotuPlaySet"
|
|
|
+ >自动读题</span
|
|
|
+ >
|
|
|
+ </div>
|
|
|
+ <!-- 答题模式选择end -->
|
|
|
+ <!-- 分割线 -->
|
|
|
+ <div class="divider" />
|
|
|
+ <!-- 题目模块 -->
|
|
|
+ <!-- 题目预加载 -->
|
|
|
+ <m-empty v-if="!currentSubject" />
|
|
|
+ <!-- 题目预加载end -->
|
|
|
+ <div class="problem-box" v-else>
|
|
|
+ <!-- 题目内容 -->
|
|
|
+ <div class="problem">
|
|
|
+ <span class="type">{{ currentSubject.type }}</span>
|
|
|
+ <span class="text">{{ currentSubject.explain }}</span>
|
|
|
+ <van-image
|
|
|
+ v-if="currentSubject.image"
|
|
|
+ :src="currentSubject.image"
|
|
|
+ class="img"
|
|
|
+ >
|
|
|
+ <template v-slot:loading>
|
|
|
+ <van-loading type="spinner" size="20" />
|
|
|
+ </template>
|
|
|
+ </van-image>
|
|
|
+ </div>
|
|
|
+ <!-- 背题模式展示 -->
|
|
|
+ <div v-if="typeParams.answerShow">
|
|
|
+ <div>
|
|
|
+ <div
|
|
|
+ class="answer-box"
|
|
|
+ v-for="(item, index) in currentSubject.opts"
|
|
|
+ :key="Number(index)"
|
|
|
+ >
|
|
|
+ <div class="choose-icon">
|
|
|
+ {{ String.fromCharCode(65 + Number(index)) }}
|
|
|
+ </div>
|
|
|
+ <span
|
|
|
+ class="answer-text"
|
|
|
+ :class="{ true: currentSubject.answer.includes(item) }"
|
|
|
+ >
|
|
|
+ {{ item }}
|
|
|
+ </span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="checkbox-answer">
|
|
|
+ 答案: {{ currentSubject.answer.toString() }}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <!-- 背题模式展示end -->
|
|
|
+ <!-- 选择内容 -->
|
|
|
+ <div v-else-if="currentSubject.isTrue === null">
|
|
|
+ <!-- 单选 -->
|
|
|
+ <van-radio-group
|
|
|
+ v-model="currentSubject.userAnswer"
|
|
|
+ v-if="currentSubject.type != '多选题'"
|
|
|
+ @change="userAnswerChange"
|
|
|
+ icon-size="35px"
|
|
|
+ >
|
|
|
+ <van-radio
|
|
|
+ v-for="(item, index) in currentSubject.opts"
|
|
|
+ :key="Number(index)"
|
|
|
+ :name="item"
|
|
|
+ class="answer"
|
|
|
+ >{{ item }}
|
|
|
+ <template #icon="props">
|
|
|
+ <div class="choose-icon" :class="{ selected: props.checked }">
|
|
|
+ {{ String.fromCharCode(65 + Number(index)) }}
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </van-radio>
|
|
|
+ </van-radio-group>
|
|
|
+ <!-- 多选 -->
|
|
|
+ <div v-else>
|
|
|
+ <van-checkbox-group
|
|
|
+ v-model="currentSubject.userAnswer"
|
|
|
+ icon-size="35px"
|
|
|
+ >
|
|
|
+ <van-checkbox
|
|
|
+ v-for="(item, index) in currentSubject.opts"
|
|
|
+ :key="Number(index)"
|
|
|
+ :name="item"
|
|
|
+ class="answer"
|
|
|
+ >{{ item }}
|
|
|
+ <template #icon="props">
|
|
|
+ <div class="choose-icon" :class="{ selected: props.checked }">
|
|
|
+ {{ String.fromCharCode(65 + Number(index)) }}
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </van-checkbox>
|
|
|
+ </van-checkbox-group>
|
|
|
+ <van-button
|
|
|
+ round
|
|
|
+ type="primary"
|
|
|
+ class="checkbox-btn"
|
|
|
+ :disabled="currentSubject.userAnswer.length == 0"
|
|
|
+ @click="userAnswerChange"
|
|
|
+ >确定</van-button
|
|
|
+ >
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <!-- 展示答题后选择内容 -->
|
|
|
+ <div v-else>
|
|
|
+ <div>
|
|
|
+ <div
|
|
|
+ v-for="(item, index) in currentSubject.optsBack"
|
|
|
+ :key="Number(index)"
|
|
|
+ class="answer-box"
|
|
|
+ >
|
|
|
+ <div
|
|
|
+ class="choose-icon"
|
|
|
+ :class="{ iconTrue: item.status % 2 !== 0 }"
|
|
|
+ v-if="item.status < 2"
|
|
|
+ >
|
|
|
+ {{ String.fromCharCode(65 + Number(index)) }}
|
|
|
+ </div>
|
|
|
+ <m-icon
|
|
|
+ v-else-if="item.status == 3"
|
|
|
+ type="dui"
|
|
|
+ size="30px"
|
|
|
+ style="margin-left: 5px"
|
|
|
+ />
|
|
|
+ <m-icon
|
|
|
+ v-else-if="item.status == 2"
|
|
|
+ size="30px"
|
|
|
+ type="cuo"
|
|
|
+ style="margin-left: 5px"
|
|
|
+ />
|
|
|
+ <span
|
|
|
+ class="answer-text"
|
|
|
+ :class="{ true: item.status % 2 !== 0, false: item.status == 2 }"
|
|
|
+ >
|
|
|
+ {{ item.opt }}
|
|
|
+ </span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="checkbox-answer">
|
|
|
+ 答案: {{ currentSubject.answer.toString() }}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <!-- 展示答题后选择内容end -->
|
|
|
+ </div>
|
|
|
+ <!-- 选择内容End -->
|
|
|
+ <!-- 分割线 -->
|
|
|
+ <van-divider />
|
|
|
+ <!-- 功能选择列表 -->
|
|
|
+ <div class="function-list">
|
|
|
+ <div class="function-item" @click="addCurrentQuestion">
|
|
|
+ <m-icon
|
|
|
+ :type="currentSubject?.isCollection ? 'shoucanghuang' : 'shoucanghui'"
|
|
|
+ size="25px"
|
|
|
+ />
|
|
|
+ <span>收藏</span>
|
|
|
+ </div>
|
|
|
+ <div class="function-item" @click="subjectAudioPlay('读题+答案')">
|
|
|
+ <m-icon type="a-dtda" size="25px" />
|
|
|
+ <span>读题+答案</span>
|
|
|
+ </div>
|
|
|
+ <div class="function-item" @click="subjectAudioPlay('读题')">
|
|
|
+ <m-icon type="duti" size="25px" />
|
|
|
+ <span>读题</span>
|
|
|
+ </div>
|
|
|
+ <div class="function-item" @click="skillsShow = true">
|
|
|
+ <m-icon type="jqjj" size="25px" />
|
|
|
+ <span>技巧讲解</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <!-- 功能选择列表End -->
|
|
|
+ <!-- 技巧讲解 -->
|
|
|
+ <van-overlay :show="skillsShow" @click="skillsShow = false" z-index="10">
|
|
|
+ <div class="skills-box" @click.stop>
|
|
|
+ <div class="skills">
|
|
|
+ <div class="title">技巧讲解</div>
|
|
|
+ <img :src="currentSubject.explainGif" class="img" />
|
|
|
+ <van-divider class="divider">本题速记口诀</van-divider>
|
|
|
+ <div class="text">{{ currentSubject.explainJq }}</div>
|
|
|
+ <div class="btn">
|
|
|
+ <span @click="skillsShow = false">关闭</span>
|
|
|
+ <span @click="subjectAudioPlay('读技巧解释')">语音重播</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </van-overlay>
|
|
|
+ <!-- 技巧讲解end -->
|
|
|
+ <!-- 官方解释 -->
|
|
|
+ <van-overlay :show="officialShow" @click="officialShow = false" z-index="10">
|
|
|
+ <div class="skills-box" @click.stop>
|
|
|
+ <div class="skills">
|
|
|
+ <div class="title">官方解释</div>
|
|
|
+ <div class="text">
|
|
|
+ {{ currentSubject.explainJs }}
|
|
|
+ </div>
|
|
|
+ <div class="btn">
|
|
|
+ <span @click="officialShow = false">关闭</span>
|
|
|
+ <span @click="subjectAudioPlay('读官方解释')">语音重播</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </van-overlay>
|
|
|
+ <!-- 官方解释end -->
|
|
|
+ <!-- 题目模块end -->
|
|
|
+ <!-- 设置操作栏 -->
|
|
|
+ <van-popup v-model:show="setShow" position="bottom">
|
|
|
+ <van-cell center title="答对跳转下一题">
|
|
|
+ <template #right-icon>
|
|
|
+ <van-switch v-model="isJumpNext" size="24" />
|
|
|
+ </template>
|
|
|
+ </van-cell>
|
|
|
+ <van-cell center title="答题音效提示">
|
|
|
+ <template #right-icon>
|
|
|
+ <van-switch v-model="isSoundEffect" size="24" />
|
|
|
+ </template>
|
|
|
+ </van-cell>
|
|
|
+ </van-popup>
|
|
|
+ <!-- 设置操作栏end -->
|
|
|
+ <!-- 底部操作栏 -->
|
|
|
+ <van-tabbar placeholder route>
|
|
|
+ <van-tabbar-item @click="lastSubject"
|
|
|
+ >上一题
|
|
|
+ <template #icon>
|
|
|
+ <m-icon type="shangyiti" />
|
|
|
+ </template>
|
|
|
+ </van-tabbar-item>
|
|
|
+ <van-tabbar-item
|
|
|
+ >{{ trueNum }}
|
|
|
+ <template #icon>
|
|
|
+ <m-icon type="dui" />
|
|
|
+ </template>
|
|
|
+ </van-tabbar-item>
|
|
|
+ <van-tabbar-item
|
|
|
+ >{{ falseNum }}
|
|
|
+ <template #icon>
|
|
|
+ <m-icon type="cuo" />
|
|
|
+ </template>
|
|
|
+ </van-tabbar-item>
|
|
|
+ <van-tabbar-item
|
|
|
+ >{{ currentSubjectIndex + 1 }}/{{ subjectTotal }}
|
|
|
+ <template #icon>
|
|
|
+ <m-icon type="zongtishu" />
|
|
|
+ </template>
|
|
|
+ </van-tabbar-item>
|
|
|
+ <van-tabbar-item @click="officialShow = true"
|
|
|
+ >官方解释
|
|
|
+ <template #icon>
|
|
|
+ <m-icon type="gfjs" />
|
|
|
+ </template>
|
|
|
+ </van-tabbar-item>
|
|
|
+ <van-tabbar-item @click="nextSubject"
|
|
|
+ >下一题
|
|
|
+ <template #icon>
|
|
|
+ <m-icon type="xiayiti" />
|
|
|
+ </template>
|
|
|
+ </van-tabbar-item>
|
|
|
+ </van-tabbar>
|
|
|
+ <!-- 底部操作栏end -->
|
|
|
+</template>
|
|
|
+
|
|
|
+<script lang="ts" setup>
|
|
|
+import { computed, ref } from "vue";
|
|
|
+import { useTopicMode, useAudioSet, useSubjectShowLogic } from "./hooks";
|
|
|
+import { RouterBus } from "@/hooks";
|
|
|
+const {
|
|
|
+ router: { back },
|
|
|
+ route: { query },
|
|
|
+} = new RouterBus();
|
|
|
+
|
|
|
+//答题模式选择逻辑
|
|
|
+const { answerTypeList, currentType, typeParams } = useTopicMode();
|
|
|
+
|
|
|
+const skillsShow = ref(false); //显示技巧讲解
|
|
|
+const officialShow = ref(false); //显示官方解释
|
|
|
+
|
|
|
+//设置操作栏
|
|
|
+const setShow = ref(false); //显示设置栏
|
|
|
+const isSoundEffect = ref(true); //答题音效
|
|
|
+
|
|
|
+//题目展示逻辑
|
|
|
+const {
|
|
|
+ currentSubject,
|
|
|
+ currentSubjectIndex,
|
|
|
+ subjectTotal,
|
|
|
+ nextSubject,
|
|
|
+ lastSubject,
|
|
|
+ trueNum,
|
|
|
+ falseNum,
|
|
|
+ isJumpNext,
|
|
|
+ userAnswerChange,
|
|
|
+ addCurrentQuestion,
|
|
|
+} = useSubjectShowLogic();
|
|
|
+
|
|
|
+//音频模块
|
|
|
+const { aotuPlayFlag, subjectAudioPlay, aotuPlaySet } =
|
|
|
+ useAudioSet(currentSubject);
|
|
|
+</script>
|
|
|
+
|
|
|
+<style lang="scss" scoped>
|
|
|
+.parsing-img {
|
|
|
+ width: 100%;
|
|
|
+ margin-top: 10px;
|
|
|
+}
|
|
|
+.function-list {
|
|
|
+ width: 100%;
|
|
|
+ font-size: 13px;
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-around;
|
|
|
+ padding: 15px;
|
|
|
+ box-sizing: border-box;
|
|
|
+ .function-item {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ align-items: center;
|
|
|
+ font-size: 13px;
|
|
|
+ font-weight: 400;
|
|
|
+ color: #8a9099;
|
|
|
+ span {
|
|
|
+ margin-top: 5px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+.answerType {
|
|
|
+ width: 100%;
|
|
|
+ font-size: 13px;
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-around;
|
|
|
+ padding: 15px;
|
|
|
+ box-sizing: border-box;
|
|
|
+ span {
|
|
|
+ border-radius: 20px;
|
|
|
+ padding: 3px 10px;
|
|
|
+ background-color: #b8c0cc;
|
|
|
+ color: #ffffff;
|
|
|
+ }
|
|
|
+ .selected {
|
|
|
+ background-color: #498ef5;
|
|
|
+ }
|
|
|
+}
|
|
|
+.divider {
|
|
|
+ width: 100%;
|
|
|
+ height: 10px;
|
|
|
+ background-color: #f2f3f5;
|
|
|
+}
|
|
|
+.problem-box {
|
|
|
+ font-size: 17px;
|
|
|
+ padding: 15px;
|
|
|
+ .problem {
|
|
|
+ .type {
|
|
|
+ width: 47px;
|
|
|
+ height: 24px;
|
|
|
+ background: #498ef5;
|
|
|
+ border-radius: 10px 10px 0px 10px;
|
|
|
+ font-size: 11px;
|
|
|
+ padding: 2px 7px;
|
|
|
+ margin-right: 5px;
|
|
|
+ }
|
|
|
+ .text {
|
|
|
+ font-family: PingFang SC;
|
|
|
+ font-weight: 400;
|
|
|
+ color: #0a1a33;
|
|
|
+ letter-spacing: 0.3px;
|
|
|
+ }
|
|
|
+ .img {
|
|
|
+ width: 100%;
|
|
|
+ margin-top: 10px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .answer {
|
|
|
+ margin-top: 25px;
|
|
|
+ }
|
|
|
+ .answer-box {
|
|
|
+ display: flex;
|
|
|
+ margin-top: 25px;
|
|
|
+ align-items: center;
|
|
|
+ .iconTrue {
|
|
|
+ background-color: #01c18d;
|
|
|
+ }
|
|
|
+ .answer-text {
|
|
|
+ margin-left: 10px;
|
|
|
+ }
|
|
|
+ .true {
|
|
|
+ color: #01c18d;
|
|
|
+ }
|
|
|
+ .false {
|
|
|
+ color: #ff4d53;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .choose-icon {
|
|
|
+ width: 30px;
|
|
|
+ height: 30px;
|
|
|
+ border-radius: 50%;
|
|
|
+ display: flex;
|
|
|
+ justify-content: center;
|
|
|
+ align-items: center;
|
|
|
+ font-size: 17px;
|
|
|
+ box-shadow: 0px 2px 6px rgba(0, 0, 0, 0.16);
|
|
|
+ box-sizing: border-box;
|
|
|
+ margin-left: 5px;
|
|
|
+ margin-top: 1px;
|
|
|
+ }
|
|
|
+ .selected {
|
|
|
+ background-color: #498ef5;
|
|
|
+ }
|
|
|
+ .checkbox-btn {
|
|
|
+ width: 266px;
|
|
|
+ height: 40px;
|
|
|
+ margin: auto;
|
|
|
+ margin-top: 25px;
|
|
|
+ left: 50%;
|
|
|
+ transform: translateX(-50%);
|
|
|
+ }
|
|
|
+ .checkbox-answer {
|
|
|
+ padding: 8px 10px;
|
|
|
+ background-color: #f2f3f5;
|
|
|
+ margin-top: 25px;
|
|
|
+ }
|
|
|
+}
|
|
|
+.skills-box {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ height: 100%;
|
|
|
+ .skills {
|
|
|
+ width: 290px;
|
|
|
+ background: #ffffff;
|
|
|
+ box-shadow: 0px 0px 8px rgba(124, 129, 136, 0.16);
|
|
|
+ border-radius: 10px;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ align-items: center;
|
|
|
+ padding: 20px 16px;
|
|
|
+ box-sizing: border-box;
|
|
|
+ .title {
|
|
|
+ font-size: 15px;
|
|
|
+ font-family: PingFang SC;
|
|
|
+ font-weight: bold;
|
|
|
+ line-height: 21px;
|
|
|
+ color: #0a1a33;
|
|
|
+ }
|
|
|
+ .img {
|
|
|
+ width: 258px;
|
|
|
+ height: 129px;
|
|
|
+ border: 1px solid #e8e8e8;
|
|
|
+ margin-top: 16px;
|
|
|
+ }
|
|
|
+ .divider {
|
|
|
+ margin-top: 20px;
|
|
|
+ color: #0a1a33;
|
|
|
+ background: #ffffff;
|
|
|
+ }
|
|
|
+ .text {
|
|
|
+ font-size: 13px;
|
|
|
+ font-family: PingFang SC;
|
|
|
+ font-weight: 400;
|
|
|
+ line-height: 19px;
|
|
|
+ color: #5c6066;
|
|
|
+ margin-top: 10px;
|
|
|
+ }
|
|
|
+ .btn {
|
|
|
+ width: 100%;
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ padding: 0 40px;
|
|
|
+ box-sizing: border-box;
|
|
|
+ margin-top: 20px;
|
|
|
+ span {
|
|
|
+ width: 76px;
|
|
|
+ height: 30px;
|
|
|
+ border-radius: 15px;
|
|
|
+ font-size: 13px;
|
|
|
+ display: flex;
|
|
|
+ justify-content: center;
|
|
|
+ align-items: center;
|
|
|
+ &:active {
|
|
|
+ background-color: #afaaaa;
|
|
|
+ filter: brightness(50%);
|
|
|
+ }
|
|
|
+ &:nth-of-type(1) {
|
|
|
+ border: 1px solid #707070;
|
|
|
+ color: #5c6066;
|
|
|
+ }
|
|
|
+ &:nth-of-type(2) {
|
|
|
+ background: #498ef5;
|
|
|
+ border: 1px solid #498ef5;
|
|
|
+ color: #ffffff;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|