sequential.vue 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477
  1. <template>
  2. <view class="content" :class="{night:nightFlag}">
  3. <view class="top-box">
  4. <view class="icon"></view>
  5. <selectSwitch class='btn' @change="changeSwitch" :defaultSwitch='kemu==1' :switchList="['科一题目','科四题目']"
  6. checked_bj_color='#E31818' />
  7. <van-icon class='set' name="/static/imgs/sz.png" size='20' @click='show=true' />
  8. </view>
  9. <van-popup :show="show" @close="show=false" position="bottom">
  10. <van-cell title="背题模式" clickable :data-index="index" @click="answerflag=!answerflag">
  11. <van-switch slot="right-icon" :checked="answerflag" size="24px" active-color="#16CC16" />
  12. <!-- <selectSwitch slot="right-icon" @change="changeSwitch" :switchList="['答题模式','背题模式']" checked_bj_color='#E31818' /> -->
  13. </van-cell>
  14. <van-cell title="答对跳转下一题 " clickable :data-index="index" @click="answerjump=!answerjump">
  15. <van-switch slot="right-icon" :checked="answerjump" size="24px" active-color="#16CC16" />
  16. </van-cell>
  17. <!-- <van-cell title="答错展示题目解析" clickable :data-index="index" @click="checked=!checked">
  18. <van-switch slot="right-icon" :checked="checked" size="24px" active-color="#16CC16" />
  19. </van-cell> -->
  20. <van-cell title="错误震动提醒" clickable :data-index="index" @click="checked=!checked">
  21. <van-switch slot="right-icon" :checked="checked" size="24px" active-color="#16CC16" />
  22. </van-cell>
  23. <van-cell title="夜间模式" clickable :data-index="index" @click="nightFlag=!nightFlag">
  24. <van-switch slot="right-icon" :checked="nightFlag" size="24px" active-color="#16CC16" />
  25. </van-cell>
  26. <!-- <van-cell title="主题选择" clickable :data-index="index" @click="checked=!checked">
  27. <van-switch slot="right-icon" :checked="checked" size="24px" active-color="#16CC16" />
  28. </van-cell>
  29. <van-cell title="字体选择" clickable :data-index="index" @click="checked=!checked">
  30. <van-switch slot="right-icon" :checked="checked" size="24px" active-color="#16CC16" />
  31. </van-cell> -->
  32. </van-popup>
  33. <van-skeleton class='skeleton' avatar row="6" :row-width="['100%','40%','70%','70%','70%','70%']" avatar-shape='square'
  34. :loading="loading">
  35. <swiper class="swiper-box" :current="swiperIndex" @change="swiperChange" circular>
  36. <swiper-item v-for="(itembox,indexbox) in questionList" :key='indexbox'>
  37. <view class="swiper-item">
  38. <view class="topic-box">
  39. <view class="topic-right">
  40. <view class="topic-top">
  41. <view class="topic-left">
  42. <text class="topic-type">{{questionType(itembox.type)}}</text>
  43. <van-icon name="star-o" size='20' />
  44. </view>
  45. <!-- <rich-text class="topic-tit" :nodes="itembox.id+'、'+itembox.question"></rich-text> -->
  46. <view class="topic-tit" v-html="itembox.id+'、'+itembox.question"></view>
  47. </view>
  48. <video v-if="itembox.videoUrl" class="topic-img" :muted='true' :loop='true' :autoplay='true' :controls='false'
  49. :src="encodeURI(itembox.mediaUrl)"></video>
  50. <image v-if="itembox.sinaimg" class="topic-img" :src="itembox.mediaUrl" mode="aspectFit"></image>
  51. <view class="topic-opt" v-if='itembox.type==2'>
  52. <van-radio-group :value="userAnswer[itembox.id]">
  53. <van-cell-group>
  54. <van-cell :class='{answer:(itembox.answerTrue.includes(index+1) && (answerflag || completeAnswer[itembox.id]))}'
  55. v-for="(item,index) in choiceList" :key="index" :title="itembox[item]" v-show='itembox[item]' clickable
  56. :data-index="index+1" @click="singleToggle($event,itembox)">
  57. <van-icon v-if="(itembox.answerTrue.includes(index+1) && (answerflag || completeAnswer[itembox.id]))" slot="icon"
  58. name="/static/imgs/true.png" size='20' />
  59. <van-radio slot="right-icon" :ref="`checkboxes${itembox.id}`" checked-color="#1464cc" :name="index+1" />
  60. </van-cell>
  61. </van-cell-group>
  62. </van-radio-group>
  63. <!-- <button @click="submit(itembox)" class="submit" type="default" v-show="!(answerflag || completeAnswer[itembox.id])">提交答案</button> -->
  64. </view>
  65. <view class="topic-opt" v-if='itembox.type==1'>
  66. <van-radio-group :value="userAnswer[itembox.id]">
  67. <van-cell-group>
  68. <van-cell :class='{answer:(itembox.answerTrue.includes(index+1) && (answerflag || completeAnswer[itembox.id]))}'
  69. v-for="(item,index) in 2" :key="index" :title="index?'错误':'正确'" clickable :data-index="index+1" @click="singleToggle($event,itembox)">
  70. <van-icon v-if="(itembox.answerTrue.includes(index+1) && (answerflag || completeAnswer[itembox.id]))" slot="icon"
  71. name="/static/imgs/true.png" size='20' />
  72. <van-radio slot="right-icon" :ref="`checkboxes${itembox.id}`" checked-color="#1464cc" :name="index+1" />
  73. </van-cell>
  74. </van-cell-group>
  75. </van-radio-group>
  76. <!-- <button @click="submit(itembox)" class="submit" type="default" v-show="!(answerflag || completeAnswer[itembox.id])">提交答案</button> -->
  77. </view>
  78. <view class="topic-opt" v-else-if='itembox.type==3'>
  79. <van-checkbox-group :value="userAnswer[itembox.id]" @change="onChange($event,itembox)">
  80. <van-cell-group>
  81. <van-cell :class='{answer:(itembox.answerTrue.includes(index+1) && (answerflag || completeAnswer[itembox.id]))}'
  82. v-for="(item,index) in choiceList" :key="index" :title="itembox[item]" v-show='itembox[item]' clickable
  83. @click='toggle($event,itembox)' :data-index="index">
  84. <van-icon v-if="(itembox.answerTrue.includes(index+1) && (answerflag || completeAnswer[itembox.id]))" slot="icon"
  85. name="/static/imgs/true.png" size='20' />
  86. <van-checkbox shape="square" catch:tap="noop" slot="right-icon" :ref="`checkboxes${itembox.id}`"
  87. checked-color="#1464cc" :name="index+1" />
  88. </van-cell>
  89. </van-cell-group>
  90. </van-checkbox-group>
  91. <button @click="submit(itembox)" class="submit" type="default" v-show="!(answerflag || completeAnswer[itembox.id])">提交答案</button>
  92. </view>
  93. </view>
  94. </view>
  95. <view v-show="answerflag || completeAnswer[itembox.id]">
  96. <view class="flag">
  97. <text v-if="itembox.type==2" class="result">正确答案: {{itembox[choiceList[itembox.answerTrue-1]]}}</text>
  98. <text v-else-if="itembox.type==1" class="result">正确答案: {{itembox.answerTrue==1?'正确':'错误'}}</text>
  99. <text v-else-if="itembox.type==3" class="result">正确答案: {{itembox.answerTrue.split('').map((key)=>{
  100. return itembox[choiceList[key-1]]
  101. })}}</text>
  102. </view>
  103. <view class="parsing">
  104. <view class="item-titBox">
  105. <text class="item-tit">题目解析</text>
  106. </view>
  107. <view class="parsing-text">
  108. <text class="item-tit">{{itembox.explain1 ? itembox.explain1 : "无"}}</text>
  109. </view>
  110. </view>
  111. </view>
  112. </view>
  113. </swiper-item>
  114. </swiper>
  115. </van-skeleton>
  116. </view>
  117. </template>
  118. <script>
  119. import selectSwitch from "@/components/xuan-switch/xuan-switch.vue";
  120. import {
  121. questionList
  122. } from "@/api/answer.js"
  123. export default {
  124. components: {
  125. selectSwitch
  126. },
  127. data() {
  128. return {
  129. loading: true,
  130. answerflag: false,
  131. answerjump: true,
  132. nightFlag: false,
  133. kemu: uni.getStorageSync('kemu') || 1,
  134. completeAnswer: {},
  135. show: false,
  136. checked: true,
  137. radio: null,
  138. result: [],
  139. userAnswer: {},
  140. questionList: {},
  141. choiceList: ['an1', 'an2', 'an3', 'an4', 'an5', 'an6', 'an7'],
  142. swiperIndex: 0,
  143. shakeIndex: 0,
  144. pageNum: uni.getStorageSync('pageNum') || 1,
  145. shake: 0,
  146. }
  147. },
  148. watch: {
  149. kemu(val) {
  150. uni.setStorageSync('kemu', val)
  151. this.pageNum = 1
  152. this.listInit()
  153. }
  154. },
  155. mounted() {
  156. this.listInit()
  157. },
  158. methods: {
  159. async listInit() {
  160. this.loading = true
  161. await questionList({
  162. pageNum: this.pageNum,
  163. pageSize: 10,
  164. kemu: this.kemu
  165. }).then((res) => {
  166. this.questionList = res.rows
  167. this.$nextTick(() => {
  168. this.loading = false
  169. })
  170. })
  171. await questionList({
  172. pageNum: this.pageNum + 1,
  173. pageSize: 10,
  174. kemu: this.kemu
  175. }).then((res) => {
  176. this.questionList = this.questionList.concat(res.rows)
  177. })
  178. await questionList({
  179. orderByClause: (this.pageNum - 2) > 0 ? 'asc' : 'desc',
  180. pageNum: (this.pageNum - 2) > 0 ? (this.pageNum - 2) : Math.abs(this.pageNum - 3),
  181. pageSize: 10,
  182. kemu: this.kemu
  183. }).then((res) => {
  184. (this.pageNum - 2) > 0 || res.rows.reverse()
  185. this.questionList = this.questionList.concat(res.rows)
  186. })
  187. await questionList({
  188. orderByClause: (this.pageNum - 1) > 0 ? 'asc' : 'desc',
  189. pageNum: (this.pageNum - 1) > 0 ? (this.pageNum - 1) : Math.abs(this.pageNum - 2),
  190. pageSize: 10,
  191. kemu: this.kemu
  192. }).then((res) => {
  193. (this.pageNum - 1) > 0 || res.rows.reverse()
  194. this.questionList = this.questionList.concat(res.rows)
  195. })
  196. },
  197. questionType(index) {
  198. switch (index) {
  199. case 1:
  200. return '判断';
  201. case 2:
  202. return '单选';
  203. case 3:
  204. return '多选';
  205. }
  206. },
  207. swiperChange(e) {
  208. let aShake = e.detail.current - this.shakeIndex
  209. this.shake += aShake ** 2 != 1 ? -aShake / Math.abs(aShake) : aShake;
  210. this.swiperIndex = e.detail.current
  211. this.shakeIndex = e.detail.current
  212. if (e.detail.current % 10 == 0) {
  213. if (Math.abs(this.shake) < 10) {
  214. this.shake = 0
  215. return
  216. }
  217. let ascFlag = this.shake / Math.abs(this.shake);
  218. this.pageNum += ascFlag
  219. questionList({
  220. orderByClause: (this.pageNum + ascFlag) > 0 ? 'asc' : 'desc',
  221. pageNum: (this.pageNum + ascFlag) > 0 ? (this.pageNum + ascFlag) : Math.abs(this.pageNum + ascFlag - 1),
  222. pageSize: 10,
  223. kemu: this.kemu
  224. }).then((res) => {
  225. uni.setStorageSync('pageNum', this.pageNum)
  226. this.shake = 0
  227. if (ascFlag > 0) {
  228. if (e.detail.current == 30) {
  229. this.questionList = res.rows.concat(this.questionList.slice(10))
  230. }
  231. if (e.detail.current == 20) {
  232. this.questionList = this.questionList.slice(0, 30).concat(res.rows)
  233. }
  234. if (e.detail.current == 10) {
  235. this.questionList = this.questionList.slice(0, 20).concat(res.rows).concat(this.questionList.slice(30))
  236. }
  237. if (e.detail.current == 0) {
  238. this.questionList = this.questionList.slice(0, 10).concat(res.rows).concat(this.questionList.slice(20))
  239. }
  240. } else {
  241. (this.pageNum + ascFlag) > 0 || res.rows.reverse()
  242. if (e.detail.current == 0) {
  243. this.questionList = this.questionList.slice(0, 20).concat(res.rows).concat(this.questionList.slice(30))
  244. }
  245. if (e.detail.current == 30) {
  246. this.questionList = this.questionList.slice(0, 10).concat(res.rows).concat(this.questionList.slice(20))
  247. }
  248. if (e.detail.current == 20) {
  249. this.questionList = res.rows.concat(this.questionList.slice(10))
  250. }
  251. if (e.detail.current == 10) {
  252. this.questionList = this.questionList.slice(0, 30).concat(res.rows)
  253. }
  254. }
  255. })
  256. }
  257. },
  258. onChange(event, itembox) {
  259. if (this.completeAnswer[itembox.id] || this.answerflag) {
  260. return
  261. }
  262. this.$set(this.userAnswer, itembox.id, event.detail)
  263. },
  264. singleToggle(event, itembox) {
  265. if (this.completeAnswer[itembox.id] || this.answerflag) {
  266. return
  267. }
  268. const {
  269. index
  270. } = event.currentTarget.dataset;
  271. this.$set(this.userAnswer, itembox.id, index)
  272. setTimeout(() => {
  273. this.submit(itembox)
  274. }, 0)
  275. },
  276. toggle(event, itembox) {
  277. const {
  278. index
  279. } = event.currentTarget.dataset;
  280. const checkbox = this.$refs[`checkboxes${itembox.id}`][index];
  281. checkbox.toggle();
  282. },
  283. noop() {},
  284. submit(itembox) {
  285. this.$set(this.completeAnswer, itembox.id, true)
  286. let flag = (this.userAnswer[itembox.id] + '').split(',').sort().join('') == itembox.answerTrue.split('').sort().join(
  287. '')
  288. if (flag) {
  289. wx.vibrateShort();
  290. if (this.answerjump) {
  291. let index = this.swiperIndex
  292. this.swiperIndex = ++index % 40
  293. }
  294. } else {
  295. wx.vibrateLong();
  296. }
  297. },
  298. changeSwitch(e) {
  299. if (e) {
  300. this.kemu = 1
  301. } else {
  302. this.kemu = 4
  303. }
  304. }
  305. }
  306. }
  307. </script>
  308. <style lang="scss" scoped>
  309. /deep/ .answer .van-cell {
  310. background-color: #16CC16 !important;
  311. color: #ffffff;
  312. }
  313. /deep/ .van-cell {
  314. // background-color: #16CC16 !important;
  315. margin: 10rpx;
  316. border-radius: 20rpx;
  317. }
  318. .content {
  319. width: 100%;
  320. height: 100vh;
  321. background-color: #FFFFFF;
  322. }
  323. .skeleton {
  324. // margin: 0rpx 20rpx;
  325. }
  326. .swiper-box {
  327. height: calc(100vh - 120rpx);
  328. margin: 0rpx 20rpx;
  329. swiper-item {
  330. overflow: auto;
  331. }
  332. }
  333. .top-box {
  334. height: 60rpx;
  335. padding: 30rpx;
  336. display: flex;
  337. justify-content: space-between;
  338. align-items: center;
  339. .icon {
  340. width: 60rpx;
  341. }
  342. .btn {}
  343. .set {
  344. color: red;
  345. }
  346. }
  347. .topic-box {
  348. // padding: 20rpx;
  349. display: flex;
  350. justify-content: center;
  351. // border: 2px solid red;
  352. .topic-top {
  353. display: flex;
  354. // border: 2px solid red;
  355. padding: 10rpx;
  356. .topic-left {
  357. display: flex;
  358. flex-direction: column;
  359. .topic-type {
  360. background: #E31818;
  361. border-radius: 10rpx;
  362. // border: 2px solid red;
  363. color: #FFFFFF;
  364. width: 66rpx;
  365. height: 30rpx;
  366. display: flex;
  367. justify-content: center;
  368. align-items: center;
  369. border-radius: 15px 15px 0px 15px;
  370. padding: 10rpx;
  371. margin-bottom: 18rpx;
  372. }
  373. }
  374. .topic-tit {
  375. padding: 10rpx;
  376. }
  377. }
  378. .topic-right {
  379. flex: 1;
  380. display: flex;
  381. flex-direction: column;
  382. padding: 0 10rpx;
  383. .topic-img {
  384. padding: 10rpx;
  385. margin: auto;
  386. width: 500rpx;
  387. height: 250rpx;
  388. // border: 2px solid red;
  389. }
  390. .topic-opt {
  391. // border: 2px solid red;
  392. padding: 30rpx 5rpx;
  393. .submit {
  394. margin: auto;
  395. margin-top: 150rpx;
  396. height: 80rpx;
  397. background: linear-gradient(90deg, #E31818, #ED3E24, #ED4F24);
  398. border-radius: 35rpx;
  399. display: flex;
  400. justify-content: center;
  401. align-items: center;
  402. color: #FFFFFF;
  403. }
  404. }
  405. }
  406. }
  407. .flag {
  408. // border: 2px solid red;
  409. padding: 30rpx 5rpx;
  410. display: flex;
  411. justify-content: center;
  412. .result {
  413. display: inline-block;
  414. background-color: #16CC16;
  415. // border: 2px solid red;
  416. width: 690rpx;
  417. // height: 70rpx;
  418. padding: 20rpx;
  419. display: flex;
  420. align-items: center;
  421. justify-content: center;
  422. border-radius: 20rpx;
  423. color: #ffffff;
  424. }
  425. }
  426. .item-titBox {
  427. display: flex;
  428. justify-content: space-between;
  429. align-items: center;
  430. padding: 20rpx;
  431. border-bottom: 1rpx solid #e8e8e8;
  432. .item-tit {
  433. border-left: 8rpx solid #E31818;
  434. font-size: 30rpx;
  435. // line-height: 38rpx;
  436. padding: 0 11rpx;
  437. }
  438. }
  439. .parsing-text {
  440. padding: 30rpx;
  441. // border: 2px solid red;
  442. }
  443. </style>