train.vue 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396
  1. <template>
  2. <view v-if="quData!=null && quData.id!=null" style="padding-bottom: 80px;">
  3. <uni-row :gutter="1" v-if="mode!=='13'">
  4. <uni-col :span="8">
  5. <view class="st-item">
  6. <uni-icons type="checkbox-filled" size="20" color="#4c9d44" style="margin-right: 5px;" />
  7. {{ trueCount }}
  8. </view>
  9. </uni-col>
  10. <uni-col :span="8">
  11. <view class="st-item">
  12. <uni-icons type="clear" size="20" color="#ff0000" style="margin-right: 5px;" />
  13. {{ wrongCount }}
  14. </view>
  15. </uni-col>
  16. <uni-col :span="8">
  17. <view class="st-item">
  18. 正确率:{{ calcRate() }}%
  19. </view>
  20. </uni-col>
  21. </uni-row>
  22. <view style="padding: 12px 15px">
  23. <!-- 引用题目组件 -->
  24. <train-qu-item v-model="quData" :card="cardItem" @rest="handleRest" :mode="mode" />
  25. <view class="true-next" v-if="mode!=='13'">
  26. <checkbox :checked="nextIfTrue" @click="nextChange">答对继续下一题</checkbox>
  27. </view>
  28. <view class="bottom-bar">
  29. <uni-row :gutter="20">
  30. <uni-col :span="6">
  31. <button @click="fetchPrevious" :disabled="currentSort === 1">上题</button>
  32. </uni-col>
  33. <uni-col :span="6">
  34. <button @click="fetchNext" :disabled="currentSort >= maxSort">下题</button>
  35. </uni-col>
  36. <uni-col :span="6">
  37. <button type="warn" @click="handleFinish">结束</button>
  38. </uni-col>
  39. <uni-col :span="6">
  40. <button type="primary" @click="showCard">答题卡</button>
  41. </uni-col>
  42. </uni-row>
  43. </view>
  44. </view>
  45. <uni-drawer ref="cardDrawer">
  46. <view class="card-title">答题卡</view>
  47. <scroll-view scroll-y="true" class="scroll-y">
  48. <view class="card-context">
  49. <view v-for="item in cardList" :key="item.quId"
  50. :class="{'card-num': true, 'current':item.quId === quData.id, 'right':item.quId !== quData.id && item.answered && item.isRight, 'error':item.quId !== quData.id && item.answered && !item.isRight}"
  51. @click="switchQu(item)">
  52. {{ item.sort }}
  53. </view>
  54. </view>
  55. </scroll-view>
  56. </uni-drawer>
  57. </view>
  58. </template>
  59. <script>
  60. import {
  61. hasTrain,
  62. startTrain,
  63. listCard,
  64. finishTrain,
  65. quDetail
  66. } from '@/api/repo/train'
  67. import TrainQuItem from './components/TrainQuItem.vue'
  68. export default {
  69. components: {
  70. TrainQuItem
  71. },
  72. data() {
  73. return {
  74. trainId: '',
  75. cardShow: true,
  76. currentSort: 1,
  77. maxSort: 100,
  78. trueCount: 0,
  79. wrongCount: 0,
  80. totalCount: 0,
  81. rightRate: 0,
  82. repoId: '',
  83. quId: '',
  84. mode: 0,
  85. cardList: [],
  86. cardItem: {},
  87. quData: {
  88. quType: 1,
  89. content: ''
  90. },
  91. nextIfTrue: false
  92. }
  93. },
  94. onLoad(option) {
  95. this.repoId = option.repoId
  96. this.mode = option.mode
  97. this.handlerStart(true)
  98. },
  99. computed: {
  100. },
  101. methods: {
  102. calcRate() {
  103. if (this.trueCount === 0 || this.totalCount === 0) {
  104. return 0
  105. }
  106. let rate = parseInt(this.trueCount * 100 / this.totalCount)
  107. if (!rate) {
  108. rate = 0
  109. }
  110. return rate
  111. },
  112. nextChange(e) {
  113. this.nextIfTrue = !this.nextIfTrue
  114. },
  115. // 显示答题卡
  116. showCard() {
  117. this.$refs.cardDrawer.open()
  118. },
  119. handleRest(data) {
  120. let that = this
  121. this.cardItem.isRight = data.isRight
  122. this.cardItem.answers = data.answers
  123. this.cardItem.answered = true
  124. if (data.isRight) {
  125. this.trueCount += 1
  126. // 继续下一题
  127. if (this.nextIfTrue) {
  128. uni.showToast({
  129. icon: 'none',
  130. title: '回答正确,继续下一题...'
  131. })
  132. setTimeout(function() {
  133. that.fetchNext()
  134. }, 1500)
  135. }
  136. } else {
  137. this.wrongCount += 1
  138. }
  139. },
  140. // 查找答题卡
  141. fetchCard() {
  142. uni.showLoading({
  143. title: '获取答题卡...'
  144. })
  145. // 正确树立
  146. let that = this
  147. listCard(this.trainId).then(data => {
  148. this.cardList = data
  149. this.totalCount = data.length
  150. // 最后一个
  151. this.maxSort = this.cardList[this.cardList.length - 1].sort
  152. this.cardList.forEach(function(item) {
  153. if (item.isRight) {
  154. that.trueCount += 1
  155. }
  156. if (!item.isRight && item.answered) {
  157. that.wrongCount += 1
  158. }
  159. })
  160. // 查找第一题
  161. this.switchQu(this.cardList[0])
  162. // 关闭
  163. uni.hideLoading()
  164. })
  165. },
  166. handlerStart(clear) {
  167. uni.showLoading({
  168. title: '加载中...'
  169. });
  170. // 开始训练
  171. startTrain(this.mode, this.repoId, this.userId, clear).then(data => {
  172. // 返回训练
  173. this.trainId = data.id
  174. uni.hideLoading()
  175. // 获取答题卡
  176. this.fetchCard()
  177. }).catch(e => {
  178. setTimeout(()=>{
  179. // 错题训练。题库=考试
  180. this.handleBack()
  181. // 关闭
  182. uni.hideLoading()
  183. }, 1500)
  184. })
  185. },
  186. handleBack() {
  187. // 错题训练。题库=考试
  188. if (this.mode == 0) {
  189. uni.redirectTo({
  190. url: '/pages/paper/book?id=' + this.repoId
  191. });
  192. } else {
  193. // 跳回题库详情
  194. uni.redirectTo({
  195. url: '/pages/repo/detail?id=' + this.repoId + '&mode=' + this.mode
  196. });
  197. }
  198. },
  199. // 切换试题
  200. switchQu(item) {
  201. this.quId = item.quId
  202. this.currentSort = item.sort
  203. this.cardItem = item
  204. this.fetchQuDetail()
  205. },
  206. // 查找试题详细
  207. fetchQuDetail() {
  208. // 打开
  209. uni.showLoading({
  210. title: '加载中...'
  211. });
  212. quDetail(this.trainId, this.quId).then(data => {
  213. // 试题信息
  214. this.quData = data
  215. uni.hideLoading()
  216. // 切换题目后滑动到顶部
  217. uni.pageScrollTo({
  218. duration: 500,
  219. scrollTop: 0,
  220. })
  221. })
  222. },
  223. // 上一题
  224. fetchNext() {
  225. const index = this.currentSort
  226. const item = this.cardList[index]
  227. this.switchQu(item)
  228. },
  229. // 下一题
  230. fetchPrevious() {
  231. const index = this.currentSort - 2
  232. const item = this.cardList[index]
  233. this.switchQu(item)
  234. },
  235. handleFinish() {
  236. const that = this
  237. uni.showModal({
  238. title: '提示',
  239. content: '确实要结束本次训练吗?',
  240. success: function(res) {
  241. if (res.confirm) {
  242. finishTrain(that.trainId).then(() => {
  243. uni.showToast({
  244. title: '结束成功,您随时可以在个人中心查看此训练记录!!',
  245. duration: 2000
  246. });
  247. // 跳回题库详情
  248. that.handleBack()
  249. })
  250. }
  251. }
  252. });
  253. },
  254. // 答题卡样式
  255. itemClass(quId, isRight, answered) {
  256. if (quId === this.quData.id) {
  257. return 'current'
  258. }
  259. if (isRight) {
  260. return 'right'
  261. } else if (answered) {
  262. return 'error'
  263. }
  264. }
  265. }
  266. }
  267. </script>
  268. <style>
  269. .st-item {
  270. height: 50px;
  271. text-align: center;
  272. background: #eee;
  273. display: flex;
  274. flex-direction: row;
  275. align-items: center;
  276. justify-content: center;
  277. }
  278. .true-next {
  279. font-size: 12px;
  280. color: #666;
  281. margin-top: 15px;
  282. }
  283. .uni-card {
  284. margin: 15px 0px !important;
  285. z-index: 0 !important;
  286. }
  287. .scroll-y {
  288. width: 100%;
  289. height: 90%;
  290. white-space: nowrap;
  291. }
  292. </style>