incorrectQuestionsList.vue 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. <!-- 历史错题 -->
  2. <template>
  3. <view class="safetyEducationExamination-incorrectQuestions">
  4. <!-- 顶部知识点标签 -->
  5. <!-- <scroll-view scroll-x class="tag-scroll">
  6. <view class="tag-scroll-inner">
  7. <text
  8. v-for="(tag, index) in typeTags"
  9. :key="index"
  10. class="filter-tag"
  11. :class="{ 'filter-tag-active': activeTagIndex === index }"
  12. @click="onTagChange(index)"
  13. >{{ tag.label }}</text>
  14. </view>
  15. </scroll-view> -->
  16. <!-- 错题列表 -->
  17. <scroll-view scroll-y class="scroll-content" @scrolltolower="onScrollToLower">
  18. <view class="panel">
  19. <view v-for="(item, index) in questionList" :key="index" class="question-card">
  20. <view class="row-between mb8">
  21. <view class="q-head">
  22. <text class="q-type-badge">{{ questionTypeName(item.questionType) }}</text>
  23. <text v-if="examName" class="text-xs text-gray q-exam-name">{{ examName }}</text>
  24. </view>
  25. <text class="tag text-xs" :class="item.errorCount >= 3 ? 'tag-red' : 'tag-orange'">答错{{ item.errorCount || 0 }}次</text>
  26. </view>
  27. <view class="q-content">
  28. <!-- <text class="text-sm">{{ item.questionContent }}</text> -->
  29. <rich-text class="text-sm" :nodes="item.questionContent || ''"></rich-text>
  30. </view>
  31. <view v-if="item.userAnswer || item.correctAnswer" class="answer-box">
  32. <view v-if="item.userAnswer" class="mb4">
  33. <text class="text-xs text-gray">我的答案:</text>
  34. <text class="text-xs text-red fw500">{{ item.userAnswer }}</text>
  35. </view>
  36. <view v-if="item.correctAnswer">
  37. <text class="text-xs text-gray">正确答案:</text>
  38. <text class="text-xs text-green fw500">{{ item.correctAnswer }}</text>
  39. </view>
  40. </view>
  41. <view v-if="item.analysis" class="analysis-box">
  42. <text>解析:{{ item.analysis }}</text>
  43. </view>
  44. </view>
  45. <view v-if="!questionList[0] && !loading" class="empty-tip">暂无错题记录</view>
  46. <view v-if="loading" class="loading-tip">加载中...</view>
  47. <view v-if="noMore && questionList[0]" class="loading-tip">没有更多了</view>
  48. </view>
  49. </scroll-view>
  50. </view>
  51. </template>
  52. <script>
  53. import {
  54. examElKnowledgePointTreeList,
  55. examElExamAttemptAnswerAttemptAnswer,
  56. } from '@/pages_safetyEducationExamination/api/index.js'
  57. // 题型映射
  58. const QUESTION_TYPE_MAP = {
  59. 1: '单选题',
  60. 2: '多选题',
  61. 3: '判断题',
  62. };
  63. export default {
  64. data() {
  65. return {
  66. attemptId: '',
  67. examName: '',
  68. typeTags: [{ label: '全部', value: null }],
  69. activeTagIndex: 0,
  70. questionList: [],
  71. loading: false,
  72. page: 1,
  73. pageSize: 10,
  74. total: 0,
  75. noMore: false,
  76. }
  77. },
  78. onLoad(options) {
  79. this.attemptId = options.attemptId || '';
  80. this.examName = options.examName ? decodeURIComponent(options.examName) : '';
  81. if (!this.attemptId) {
  82. uni.showToast({ title: '考试信息无效', icon: 'none' });
  83. setTimeout(() => uni.navigateBack(), 1500);
  84. return;
  85. }
  86. // this.loadTypeTags();
  87. this.loadQuestionList();
  88. },
  89. methods: {
  90. questionTypeName(type) {
  91. return QUESTION_TYPE_MAP[type] || '';
  92. },
  93. // 知识点标签
  94. async loadTypeTags() {
  95. try {
  96. const { data } = await examElKnowledgePointTreeList({ dataScope: 1 });
  97. if (data.code === 200 && data.data) {
  98. const tags = (data.data || []).map(item => ({
  99. label: item.knowledgePointName,
  100. value: item.id,
  101. }));
  102. this.$set(this, 'typeTags', [{ label: '全部', value: null }, ...tags]);
  103. }
  104. } catch (e) {
  105. console.error('获取知识点类型失败', e);
  106. }
  107. },
  108. onTagChange(index) {
  109. if (this.activeTagIndex === index) return;
  110. this.activeTagIndex = index;
  111. this.resetList();
  112. },
  113. resetList() {
  114. this.page = 1;
  115. this.noMore = false;
  116. this.$set(this, 'questionList', []);
  117. this.loadQuestionList();
  118. },
  119. // 错题列表(分页)
  120. async loadQuestionList() {
  121. if (this.loading || this.noMore) return;
  122. this.loading = true;
  123. try {
  124. // const tag = this.typeTags[this.activeTagIndex];
  125. const { data } = await examElExamAttemptAnswerAttemptAnswer({
  126. page: this.page,
  127. pageSize: this.pageSize,
  128. attemptId: this.attemptId,
  129. // knowledgePointId: tag ? tag.value : undefined,
  130. });
  131. if (data.code === 200) {
  132. const records = data.data.records || [];
  133. const newList = this.page === 1 ? records : [...this.questionList, ...records];
  134. this.$set(this, 'questionList', newList);
  135. this.total = data.data.total;
  136. if (newList.length >= this.total) {
  137. this.noMore = true;
  138. } else {
  139. this.page++;
  140. }
  141. }
  142. } catch (e) {
  143. console.error('获取错题列表失败', e);
  144. } finally {
  145. this.loading = false;
  146. }
  147. },
  148. onScrollToLower() {
  149. this.loadQuestionList();
  150. },
  151. },
  152. }
  153. </script>
  154. <style lang="stylus" scoped>
  155. .safetyEducationExamination-incorrectQuestions
  156. height 100%
  157. display flex
  158. flex-direction column
  159. overflow hidden
  160. background-color #f0f4fb
  161. // 知识点标签横滚
  162. .tag-scroll
  163. background #fff
  164. white-space nowrap
  165. padding 20rpx 24rpx 16rpx
  166. flex-shrink 0
  167. .tag-scroll-inner
  168. display inline-flex
  169. gap 16rpx
  170. .filter-tag
  171. display inline-block
  172. font-size 22rpx
  173. padding 10rpx 24rpx
  174. border-radius 40rpx
  175. background #f4f6fa
  176. color #8896a7
  177. white-space nowrap
  178. .filter-tag-active
  179. background #1857d4
  180. color #fff
  181. box-shadow 0 4rpx 16rpx rgba(24,87,212,0.3)
  182. // 滚动区
  183. .scroll-content
  184. flex 1
  185. overflow hidden
  186. .panel
  187. padding 16rpx 24rpx 32rpx
  188. // 错题卡片
  189. .question-card
  190. background #fff
  191. border 1rpx solid #dde3ed
  192. border-radius 20rpx
  193. padding 28rpx
  194. margin-bottom 20rpx
  195. .row-between
  196. display flex
  197. align-items center
  198. justify-content space-between
  199. .q-head
  200. display flex
  201. align-items center
  202. .q-type-badge
  203. background #1857d4
  204. color #fff
  205. font-size 24rpx
  206. padding 4rpx 16rpx
  207. border-radius 8rpx
  208. .q-exam-name
  209. margin-left 16rpx
  210. .q-content
  211. line-height 1.7
  212. margin-bottom 20rpx
  213. // 答案区
  214. .answer-box
  215. background #f4f6fa
  216. border-radius 16rpx
  217. padding 20rpx
  218. margin-bottom 20rpx
  219. // 解析区
  220. .analysis-box
  221. background #f6ffed
  222. border-radius 16rpx
  223. padding 20rpx
  224. font-size 26rpx
  225. line-height 1.7
  226. color #4a5568
  227. // 标签
  228. .tag
  229. display inline-flex
  230. align-items center
  231. padding 4rpx 16rpx
  232. border-radius 40rpx
  233. font-weight 500
  234. .tag-orange
  235. background #fef6ec
  236. color #e67e22
  237. .tag-red
  238. background #fff5f5
  239. color #e53e3e
  240. .text-xs
  241. font-size 22rpx
  242. .text-sm
  243. font-size 24rpx
  244. .text-gray
  245. color #8896a7
  246. .text-green
  247. color #0d8f6f
  248. .text-red
  249. color #e53e3e
  250. .fw500
  251. font-weight 500
  252. .mb4
  253. margin-bottom 8rpx
  254. .mb8
  255. margin-bottom 16rpx
  256. // 提示
  257. .empty-tip
  258. text-align center
  259. line-height 80rpx
  260. color #aaa
  261. font-size 24rpx
  262. .loading-tip
  263. text-align center
  264. line-height 60rpx
  265. color #aaa
  266. font-size 22rpx
  267. </style>