startTest.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461
  1. <template>
  2. <!-- 导航栏 -->
  3. <van-nav-bar
  4. title="标题"
  5. left-arrow
  6. @click-left="onClickLeft"
  7. fixed
  8. placeholder
  9. >
  10. <template #right>
  11. <m-icon type="shezhi" @click="setShow = true" />
  12. </template>
  13. </van-nav-bar>
  14. <!-- 导航栏end -->
  15. <!-- 考试倒计时 -->
  16. <div class="dowm-box">
  17. <van-count-down :time="45 * 60 * 1000" format="剩余答题时间: mm分ss秒" />
  18. </div>
  19. <!-- 考试倒计时end -->
  20. <!-- 分割线 -->
  21. <div class="divider" />
  22. <!-- 题目模块 -->
  23. <!-- 题目预加载 -->
  24. <m-empty v-if="!currentSubject" />
  25. <!-- 题目预加载end -->
  26. <div class="problem-box" v-else>
  27. <!-- 题目内容 -->
  28. <div class="problem">
  29. <span class="type">{{ currentSubject.type }}</span>
  30. <span class="text">{{ currentSubject.explain }}</span>
  31. <van-image
  32. v-if="currentSubject.image"
  33. :src="currentSubject.image"
  34. class="img"
  35. >
  36. <template v-slot:loading>
  37. <van-loading type="spinner" size="20" />
  38. </template>
  39. </van-image>
  40. </div>
  41. <!-- 选择内容 -->
  42. <div v-if="true">
  43. <!-- 单选 -->
  44. <van-radio-group
  45. v-model="currentSubject.userAnswer"
  46. v-if="currentSubject.type != '多选题'"
  47. icon-size="35px"
  48. >
  49. <van-radio
  50. v-for="(item, index) in currentSubject.opts"
  51. :key="Number(index)"
  52. :name="item"
  53. class="answer"
  54. >{{ item }}
  55. <template #icon="props">
  56. <div class="choose-icon" :class="{ selected: props.checked }">
  57. {{ String.fromCharCode(65 + Number(index)) }}
  58. </div>
  59. </template>
  60. </van-radio>
  61. </van-radio-group>
  62. <!-- 多选 -->
  63. <div v-else>
  64. <van-checkbox-group
  65. v-model="currentSubject.userAnswer"
  66. icon-size="35px"
  67. >
  68. <van-checkbox
  69. v-for="(item, index) in currentSubject.opts"
  70. :key="Number(index)"
  71. :name="item"
  72. class="answer"
  73. >{{ item }}
  74. <template #icon="props">
  75. <div class="choose-icon" :class="{ selected: props.checked }">
  76. {{ String.fromCharCode(65 + Number(index)) }}
  77. </div>
  78. </template>
  79. </van-checkbox>
  80. </van-checkbox-group>
  81. </div>
  82. </div>
  83. <!-- 展示答题后选择内容 -->
  84. <div v-else-if="false">
  85. <div>
  86. <div
  87. v-for="(item, index) in currentSubject.optsBack"
  88. :key="Number(index)"
  89. class="answer-box"
  90. >
  91. <div
  92. class="choose-icon"
  93. :class="{ iconTrue: item.status % 2 !== 0 }"
  94. v-if="item.status < 2"
  95. >
  96. {{ String.fromCharCode(65 + Number(index)) }}
  97. </div>
  98. <m-icon
  99. v-else-if="item.status == 3"
  100. type="dui"
  101. size="30px"
  102. style="margin-left: 5px"
  103. />
  104. <m-icon
  105. v-else-if="item.status == 2"
  106. size="30px"
  107. type="cuo"
  108. style="margin-left: 5px"
  109. />
  110. <span
  111. class="answer-text"
  112. :class="{ true: item.status % 2 !== 0, false: item.status == 2 }"
  113. >
  114. {{ item.opt }}
  115. </span>
  116. </div>
  117. </div>
  118. <div class="checkbox-answer">
  119. 答案: {{ currentSubject.answer.toString() }}
  120. </div>
  121. </div>
  122. <!-- 展示答题后选择内容end -->
  123. </div>
  124. <!-- 选择内容End -->
  125. <!-- 分割线 -->
  126. <van-divider />
  127. <!-- 功能选择列表 -->
  128. <div class="function-list">
  129. <div class="function-item">
  130. <m-icon type="shoucanghui" size="25px" />
  131. <span>收藏</span>
  132. </div>
  133. <!-- <div class="function-item" @click="answerAudioPlay">
  134. <m-icon type="a-dtda" size="25px" />
  135. <span>读题+答案</span>
  136. </div> -->
  137. <div class="function-item" @click="subjectAudioPlay('读题')">
  138. <m-icon type="duti" size="25px" />
  139. <span>读题</span>
  140. </div>
  141. <!-- <div class="function-item" @click="currentAnswerIndexBack">
  142. <m-icon type="shangyiti" size="25px" />
  143. <span>上一题</span>
  144. </div>
  145. <div class="function-item" @click="skillsShow = true">
  146. <m-icon type="zongtishu" size="25px" />
  147. <span>1/100</span>
  148. </div>
  149. <div class="function-item" @click="currentAnswerIndexGo">
  150. <m-icon type="xiayiti" size="25px" />
  151. <span>下一题</span>
  152. </div> -->
  153. </div>
  154. <!-- 功能选择列表End -->
  155. <!-- 题目模块end -->
  156. <!-- 设置操作栏 -->
  157. <van-popup v-model:show="setShow" position="bottom">
  158. <van-cell center title="答题音效提示">
  159. <template #right-icon>
  160. <van-switch v-model="isSoundEffect" size="24" />
  161. </template>
  162. </van-cell>
  163. </van-popup>
  164. <!-- 设置操作栏end -->
  165. <!-- 底部操作栏 -->
  166. <!-- <div style="height: 40px"></div> -->
  167. <!-- <m-button class="submitButton" text="交卷" /> -->
  168. <van-tabbar placeholder route>
  169. <van-tabbar-item @click="lastSubject"
  170. >上一题
  171. <template #icon>
  172. <m-icon type="shangyiti" />
  173. </template>
  174. </van-tabbar-item>
  175. <van-tabbar-item
  176. >{{ currentSubjectIndex + 1 }}/{{ subjectTotal }}
  177. <template #icon>
  178. <m-icon type="zongtishu" />
  179. </template>
  180. </van-tabbar-item>
  181. <van-tabbar-item @click="gotoTest"
  182. >交卷
  183. <template #icon>
  184. <m-icon type="jiaojuan" />
  185. </template>
  186. </van-tabbar-item>
  187. <van-tabbar-item @click="nextSubject"
  188. >下一题
  189. <template #icon>
  190. <m-icon type="xiayiti" />
  191. </template>
  192. </van-tabbar-item>
  193. </van-tabbar>
  194. <!-- 底部操作栏end -->
  195. </template>
  196. <script lang="ts" setup>
  197. import { useRoute, useRouter } from "vue-router";
  198. import { ref, defineEmits } from "vue";
  199. import { Dialog } from "vant";
  200. import { useSubjectShowLogic, useTopicMode, useAudioSet } from "./hooks";
  201. const router = useRouter();
  202. const route = useRoute();
  203. const onClickLeft = () => {
  204. router.back();
  205. };
  206. //父级传参
  207. const emits = defineEmits(["next"]);
  208. const gotoTest = () => {
  209. Dialog.confirm({
  210. message: "确认交卷吗?",
  211. })
  212. .then(() => {
  213. emits("next");
  214. })
  215. .catch(() => {});
  216. };
  217. //题目展示逻辑
  218. const {
  219. currentSubject,
  220. currentSubjectIndex,
  221. subjectTotal,
  222. nextSubject,
  223. lastSubject,
  224. trueNum,
  225. falseNum,
  226. isJumpNext,
  227. userAnswerChange,
  228. } = useSubjectShowLogic();
  229. //设置操作栏
  230. const setShow = ref(false); //显示设置栏
  231. const isSoundEffect = ref(true); //答题音效
  232. //设置操作栏end
  233. //音频模块
  234. const { subjectAudioPlay } = useAudioSet(currentSubject);
  235. //音频模块end
  236. </script>
  237. <style lang="scss" scoped>
  238. .dowm-box {
  239. display: flex;
  240. align-items: center;
  241. justify-content: center;
  242. padding: 10px;
  243. position: sticky;
  244. top: 45px;
  245. font-size: 30px;
  246. background-color: #ffffff;
  247. }
  248. .parsing-img {
  249. width: 100%;
  250. margin-top: 10px;
  251. }
  252. .function-list {
  253. width: 100%;
  254. font-size: 13px;
  255. display: flex;
  256. justify-content: space-around;
  257. flex-wrap: wrap;
  258. padding: 15px;
  259. box-sizing: border-box;
  260. .function-item {
  261. margin-bottom: 20px;
  262. width: 30%;
  263. display: flex;
  264. flex-direction: column;
  265. align-items: center;
  266. font-size: 13px;
  267. font-weight: 400;
  268. color: #8a9099;
  269. span {
  270. margin-top: 5px;
  271. }
  272. }
  273. }
  274. .answerType {
  275. width: 100%;
  276. font-size: 13px;
  277. display: flex;
  278. justify-content: space-around;
  279. padding: 15px;
  280. box-sizing: border-box;
  281. span {
  282. border-radius: 20px;
  283. padding: 3px 10px;
  284. background-color: #b8c0cc;
  285. color: #ffffff;
  286. }
  287. .selected {
  288. background-color: #498ef5;
  289. }
  290. }
  291. .divider {
  292. width: 100%;
  293. height: 10px;
  294. background-color: #f2f3f5;
  295. }
  296. .problem-box {
  297. font-size: 17px;
  298. padding: 15px;
  299. .problem {
  300. .type {
  301. width: 47px;
  302. height: 24px;
  303. background: #498ef5;
  304. border-radius: 10px 10px 0px 10px;
  305. font-size: 11px;
  306. padding: 2px 7px;
  307. margin-right: 5px;
  308. }
  309. .text {
  310. font-family: PingFang SC;
  311. font-weight: 400;
  312. color: #0a1a33;
  313. letter-spacing: 0.3px;
  314. }
  315. .img {
  316. width: 100%;
  317. margin-top: 10px;
  318. }
  319. }
  320. .answer {
  321. margin-top: 25px;
  322. }
  323. .answer-box {
  324. display: flex;
  325. margin-top: 25px;
  326. align-items: center;
  327. .iconTrue {
  328. background-color: #01c18d;
  329. }
  330. .answer-text {
  331. margin-left: 10px;
  332. }
  333. .true {
  334. color: #01c18d;
  335. }
  336. .false {
  337. color: #ff4d53;
  338. }
  339. }
  340. .choose-icon {
  341. width: 30px;
  342. height: 30px;
  343. border-radius: 50%;
  344. display: flex;
  345. justify-content: center;
  346. align-items: center;
  347. font-size: 17px;
  348. box-shadow: 0px 2px 6px rgba(0, 0, 0, 0.16);
  349. box-sizing: border-box;
  350. margin-left: 5px;
  351. margin-top: 1px;
  352. }
  353. .selected {
  354. background-color: #498ef5;
  355. }
  356. .checkbox-btn {
  357. width: 266px;
  358. height: 40px;
  359. margin: auto;
  360. margin-top: 25px;
  361. left: 50%;
  362. transform: translateX(-50%);
  363. }
  364. .checkbox-answer {
  365. padding: 8px 10px;
  366. background-color: #f2f3f5;
  367. margin-top: 25px;
  368. }
  369. }
  370. .skills-box {
  371. display: flex;
  372. align-items: center;
  373. justify-content: center;
  374. height: 100%;
  375. .skills {
  376. width: 290px;
  377. background: #ffffff;
  378. box-shadow: 0px 0px 8px rgba(124, 129, 136, 0.16);
  379. border-radius: 10px;
  380. display: flex;
  381. flex-direction: column;
  382. align-items: center;
  383. padding: 20px 16px;
  384. box-sizing: border-box;
  385. .title {
  386. font-size: 15px;
  387. font-family: PingFang SC;
  388. font-weight: bold;
  389. line-height: 21px;
  390. color: #0a1a33;
  391. }
  392. .img {
  393. width: 258px;
  394. height: 129px;
  395. border: 1px solid #e8e8e8;
  396. margin-top: 16px;
  397. }
  398. .divider {
  399. margin-top: 20px;
  400. color: #0a1a33;
  401. background: #ffffff;
  402. }
  403. .text {
  404. font-size: 13px;
  405. font-family: PingFang SC;
  406. font-weight: 400;
  407. line-height: 19px;
  408. color: #5c6066;
  409. margin-top: 10px;
  410. }
  411. .btn {
  412. width: 100%;
  413. display: flex;
  414. justify-content: space-between;
  415. padding: 0 40px;
  416. box-sizing: border-box;
  417. margin-top: 20px;
  418. span {
  419. width: 76px;
  420. height: 30px;
  421. border-radius: 15px;
  422. font-size: 13px;
  423. display: flex;
  424. justify-content: center;
  425. align-items: center;
  426. &:active {
  427. background-color: #afaaaa;
  428. filter: brightness(50%);
  429. }
  430. &:nth-of-type(1) {
  431. border: 1px solid #707070;
  432. color: #5c6066;
  433. }
  434. &:nth-of-type(2) {
  435. background: #498ef5;
  436. border: 1px solid #498ef5;
  437. color: #ffffff;
  438. }
  439. }
  440. }
  441. }
  442. }
  443. .submitButton {
  444. background-color: #498ef5;
  445. position: fixed;
  446. left: 50%;
  447. transform: translateX(-50%);
  448. bottom: 0;
  449. width: 80%;
  450. color: #ffffff;
  451. font-size: 16px;
  452. }
  453. </style>