index.vue 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405
  1. <template>
  2. <Container
  3. title="学习本"
  4. bgColor="#f8f8f8"
  5. :scrollStyle="{
  6. padding: 0,
  7. }"
  8. :showBack="false"
  9. headerColor="#fff"
  10. >
  11. <div class="top">
  12. <div
  13. class="item col left"
  14. :class="currentIndex === 0 && 'select'"
  15. @click="currentIndex = 0"
  16. >
  17. <span>
  18. <span class="primary">{{ info.answer_total }}</span
  19. >/{{ info.topic_total }}
  20. </span>
  21. <span
  22. >正确率<span class="primary">{{ info.accuracy }}</span></span
  23. >
  24. </div>
  25. <div
  26. class="item"
  27. :class="currentIndex === 1 && 'select'"
  28. @click="currentIndex = 1"
  29. >
  30. 考试记录(<span class="primary">{{ info.real_paper_total }}</span
  31. >)
  32. </div>
  33. <div
  34. class="item right"
  35. :class="currentIndex === 2 && 'select'"
  36. @click="currentIndex = 2"
  37. >
  38. 题目收藏(<span class="primary">{{ info.favorite_total }}</span
  39. >)
  40. </div>
  41. </div>
  42. <div class="tab">
  43. <scroll-view class="scroll" scroll-x>
  44. <div class="box">
  45. <div
  46. v-for="(item, index) in info.chapter_infos"
  47. class="item"
  48. :class="{
  49. select: item.id === currentTab,
  50. }"
  51. :key="item.id"
  52. @click="
  53. () => {
  54. currentTab = item.id;
  55. }
  56. "
  57. >
  58. {{ item.name }}
  59. </div>
  60. </div>
  61. </scroll-view>
  62. <div class="select-line" v-if="currentIndex === 0">
  63. <div class="item" :class="{ select: isRight }" @click="isRight = 1">
  64. 答案正确({{ rightTotal }})
  65. </div>
  66. <div class="item" :class="{ select: !isRight }" @click="isRight = 0">
  67. 答案错误({{ errorTotal }})
  68. </div>
  69. </div>
  70. </div>
  71. <div class="context">
  72. <template v-if="currentIndex === 0 && dataList.length">
  73. <QuestionsItem :data="dataList" :isRight="isRight" :catalogue_id="currentTab" />
  74. </template>
  75. <template v-else-if="currentIndex === 1 && examList.length">
  76. <div class="card" v-for="item in examList" :key="item.catalogue_id">
  77. <div class="card-header">
  78. <span class="title">{{ item.year }}年真题</span>
  79. <span class="exam-count">已考试{{ item.exam_count }}次</span>
  80. </div>
  81. <div class="card-body">
  82. <span>最低分:{{ item.min_score }}分</span>
  83. <span>最高分:{{ item.max_score }}分</span>
  84. </div>
  85. <div class="footer">
  86. <div class="c-primary" @click="toHistory(item)">再考一次</div>
  87. </div>
  88. </div>
  89. </template>
  90. <template v-else-if="currentIndex === 2 && favoriteList.length">
  91. <QuestionsItem
  92. :data="favoriteList"
  93. isRight
  94. :onClick="toFavorite"
  95. />
  96. </template>
  97. <Empty v-else text="暂无数据"></Empty>
  98. </div>
  99. </Container>
  100. </template>
  101. <script setup>
  102. import Container from "@/components/Container/Container.vue";
  103. import Empty from "@/components/Empty/Empty.vue";
  104. import { ref, watch } from "vue";
  105. import { onShow } from "@dcloudio/uni-app";
  106. import { request } from "../../utils/request";
  107. import QuestionsItem from "../../components/Topic/QuestionsItem.vue";
  108. import { router } from "../../utils/router";
  109. const currentIndex = ref(0);
  110. const currentTab = ref(0);
  111. const isRight = ref(1);
  112. const info = ref({});
  113. const rightTotal = ref(0);
  114. const errorTotal = ref(0);
  115. const dataList = ref([]);
  116. const examList = ref([]);
  117. const favoriteList = ref([]);
  118. const toHistory = (item) => {
  119. router.push({
  120. url: "/pages/real/history",
  121. params: {
  122. id: item.catalogue_id,
  123. },
  124. });
  125. };
  126. const requestTopic = (is_correct, onSucess) => {
  127. request(
  128. "api/question_bank/question_reception/study_book/get_answer_topic_record",
  129. {
  130. chapter_id: currentTab.value,
  131. is_correct,
  132. }
  133. ).then((res) => {
  134. if (onSucess) {
  135. onSucess(res.data.data);
  136. return;
  137. }
  138. if (is_correct) {
  139. rightTotal.value = res.data.total;
  140. dataList.value = res.data.data;
  141. } else {
  142. errorTotal.value = res.data.total;
  143. }
  144. });
  145. };
  146. const requestExamList = () => {
  147. request("api/question_bank/question_reception/real_topic/get_exam_record", {
  148. chapter_id: currentTab.value,
  149. }).then((res) => {
  150. examList.value = res.data;
  151. });
  152. };
  153. const requestFavo = () => {
  154. request(
  155. "api/question_bank/question_reception/favorite/get_user_favorite_list",
  156. {
  157. chapter_id: currentTab.value,
  158. }
  159. ).then((res) => {
  160. favoriteList.value = res.data.data;
  161. });
  162. };
  163. const toFavorite = () => {
  164. router.redirectTo({
  165. url: "/pages/learn/favorite",
  166. params: {
  167. chapter_id: currentTab.value,
  168. title: '收藏'
  169. },
  170. });
  171. };
  172. watch(currentIndex, () => {
  173. switch (currentIndex.value) {
  174. case 1:
  175. requestExamList();
  176. break;
  177. case 2:
  178. requestFavo();
  179. break;
  180. default:
  181. break;
  182. }
  183. });
  184. watch(currentTab, () => {
  185. switch (currentIndex.value) {
  186. case 0:
  187. isRight.value = 1;
  188. requestTopic(isRight.value);
  189. requestTopic(Number(!isRight.value));
  190. break;
  191. case 1:
  192. requestExamList();
  193. break;
  194. case 2:
  195. requestFavo();
  196. break;
  197. default:
  198. break;
  199. }
  200. });
  201. watch(isRight, () => {
  202. dataList.value = [];
  203. requestTopic(isRight.value, (data) => {
  204. dataList.value = data;
  205. });
  206. });
  207. onShow(() => {
  208. request(
  209. "api/question_bank/question_reception/study_book/get_study_record_title"
  210. ).then((res) => {
  211. info.value = res.data;
  212. currentTab.value = res.data.chapter_infos[0].id;
  213. });
  214. });
  215. // 示例数据
  216. </script>
  217. <style scoped lang="scss">
  218. @import "@/uni.scss";
  219. .primary {
  220. color: $primary;
  221. }
  222. .top {
  223. margin: 24rpx 32rpx 0;
  224. display: grid;
  225. grid-template-columns: repeat(3, 1fr);
  226. .item {
  227. border: 1px solid $primary;
  228. display: flex;
  229. align-items: center;
  230. justify-content: center;
  231. height: 113rpx;
  232. background-color: #fff;
  233. font-weight: 500;
  234. font-size: 24rpx;
  235. color: #333333;
  236. }
  237. .item.col {
  238. flex-direction: column;
  239. gap: 12rpx;
  240. }
  241. .item.left {
  242. border-top-left-radius: 24rpx;
  243. }
  244. .item.right {
  245. border-top-right-radius: 24rpx;
  246. }
  247. .select {
  248. border-color: #fff;
  249. }
  250. }
  251. .tab {
  252. background-color: #fff;
  253. .select-line {
  254. display: grid;
  255. grid-template-columns: repeat(2, 1fr);
  256. .item {
  257. display: flex;
  258. align-items: center;
  259. justify-content: center;
  260. padding: 28rpx;
  261. border-bottom: 1px solid #fff;
  262. font-weight: 500;
  263. font-size: 32rpx;
  264. }
  265. .item.select {
  266. color: $primary;
  267. border-color: $primary;
  268. }
  269. }
  270. }
  271. .scroll {
  272. white-space: nowrap;
  273. font-weight: 500;
  274. font-size: 32rpx;
  275. color: #333333;
  276. .box {
  277. padding: 30rpx;
  278. }
  279. .item {
  280. display: inline-flex;
  281. padding: 8rpx 36rpx;
  282. }
  283. .item.select {
  284. border-radius: 200rpx;
  285. background-color: $primary;
  286. color: #fff;
  287. }
  288. }
  289. .context {
  290. padding: 20rpx 32rpx;
  291. display: flex;
  292. flex-direction: column;
  293. gap: 16rpx;
  294. .card {
  295. border-radius: 16rpx;
  296. padding: 16rpx;
  297. background-color: #fff;
  298. display: flex;
  299. flex-direction: column;
  300. .question-header {
  301. display: flex;
  302. justify-content: space-between;
  303. margin-bottom: 12rpx;
  304. color: #999;
  305. .question-type {
  306. font-weight: 500;
  307. font-size: 32rpx;
  308. color: #999999;
  309. border-radius: 8rpx 8rpx 8rpx 8rpx;
  310. border: 1rpx solid #dddddd;
  311. padding: 0 10rpx;
  312. }
  313. .question-date {
  314. color: #999;
  315. font-size: 24rpx;
  316. }
  317. }
  318. .question-text {
  319. font-size: 28rpx;
  320. color: #333;
  321. margin-bottom: 16rpx;
  322. }
  323. .options {
  324. margin-top: 8rpx;
  325. .option {
  326. display: flex;
  327. align-items: center;
  328. margin-bottom: 12rpx;
  329. gap: 14rpx;
  330. .option-select {
  331. width: 51rpx;
  332. height: 51rpx;
  333. display: flex;
  334. align-items: center;
  335. justify-content: center;
  336. border: 1rpx solid #dddddd;
  337. border-radius: 50%;
  338. }
  339. }
  340. }
  341. .footer {
  342. display: flex;
  343. align-items: center;
  344. justify-content: center;
  345. }
  346. .card-header {
  347. display: flex;
  348. justify-content: space-between;
  349. margin-bottom: 12rpx;
  350. .title {
  351. font-weight: bold;
  352. font-size: 28rpx;
  353. color: #333;
  354. }
  355. .exam-count {
  356. color: #999;
  357. font-size: 24rpx;
  358. }
  359. }
  360. .card-body {
  361. display: flex;
  362. justify-content: space-between;
  363. align-items: center;
  364. font-weight: 500;
  365. font-size: 28rpx;
  366. color: #000000;
  367. }
  368. }
  369. }
  370. .c-primary {
  371. padding: 2rpx 10rpx;
  372. border-radius: 4rpx;
  373. border: 1rpx solid $primary;
  374. color: $primary;
  375. font-size: 24rpx;
  376. }
  377. .c-error {
  378. padding: 2rpx 10rpx;
  379. border-radius: 4rpx;
  380. border: 1rpx solid $error;
  381. color: $error;
  382. font-size: 24rpx;
  383. }
  384. </style>