index.vue 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433
  1. <template>
  2. <div class="collection-box">
  3. <van-nav-bar title="错题收藏" left-arrow @click-left="onClickLeft" placeholder> </van-nav-bar>
  4. <div>
  5. <img class="collectionHeader" :src="collectionHeader" />
  6. </div>
  7. <div class="choose">
  8. <div @click="goExercise('wrong')" class="choose-img">
  9. <span class="choose-text1"> 做错题 </span>
  10. <span class="choose-text2"> 共 {{ wrongList.length }} 题 </span>
  11. <img class="" :src="wrongBg" />
  12. <img class="goArrow" :src="goArrow" />
  13. <button @click="clearTopicsWrong" style="color: #498ef5" class="clear">清空错题</button>
  14. <button
  15. @click.stop="
  16. () => {
  17. wrongSyncVisible = true;
  18. }
  19. "
  20. style="color: #498ef5; left: 60vw"
  21. class="clear">
  22. 同步错题
  23. </button>
  24. </div>
  25. <div @click="goExercise('collection')" class="choose-img">
  26. <span class="choose-text1">收藏题</span>
  27. <span class="choose-text2"> 共 {{ collectionList.length }} 题 </span>
  28. <img class="" :src="collectionBg" />
  29. <img class="goArrow" :src="goArrow" />
  30. <button @click="clearTopicsCollection" style="color: #01c18d" class="clear">清空收藏</button>
  31. <button
  32. @click.stop="
  33. () => {
  34. collectSyncVisible = true;
  35. }
  36. "
  37. style="color: #01c18d; left: 60vw"
  38. class="clear">
  39. 同步收藏
  40. </button>
  41. </div>
  42. </div>
  43. <div class="bottom">
  44. <img :src="collectionBottomBg" />
  45. </div>
  46. <van-popup position="bottom" v-model:show="wrongSyncVisible">
  47. <van-picker
  48. @cancel="
  49. () => {
  50. wrongSyncVisible = false;
  51. }
  52. "
  53. @confirm="sendWrongSync"
  54. :columns="[
  55. { text: '合并本机和云端错题', value: 0 },
  56. { text: '备份本机收藏到错题', value: 1 },
  57. { text: '恢复云端收藏到错题', value: 2 },
  58. ]"></van-picker>
  59. </van-popup>
  60. <van-popup position="bottom" v-model:show="collectSyncVisible">
  61. <van-picker
  62. @cancel="
  63. () => {
  64. collectSyncVisible = false;
  65. }
  66. "
  67. @confirm="sendCollectSync"
  68. :columns="[
  69. { text: '合并本机和云端收藏', value: 0 },
  70. { text: '备份本机收藏到云端', value: 1 },
  71. { text: '恢复云端收藏到本机', value: 2 },
  72. ]"></van-picker>
  73. </van-popup>
  74. <!-- <listCom type="wrong"></listCom> -->
  75. <!-- <van-swipe ref="swiper" :show-indicators="false" :touchable="false">
  76. <van-swipe-item> <listCom type="wrong" /> </van-swipe-item>
  77. <van-swipe-item> <listCom type="collection" /> </van-swipe-item>
  78. </van-swipe> -->
  79. </div>
  80. </template>
  81. <script setup lang="ts">
  82. import { ref, onMounted } from "vue";
  83. import { useRouter, useRoute } from "vue-router";
  84. import listCom from "./components/list.vue";
  85. import collectionHeader from "@/assets/img/collectionHeader.png";
  86. import collectionBg from "@/assets/img/collectionBg.png";
  87. import wrongBg from "@/assets/img/wrongBg.png";
  88. import collectionBottomBg from "@/assets/img/collectionBottomBg.png";
  89. import goArrow from "@/assets/img/goArrow.png";
  90. import { CollectionModel } from "@/model/collection";
  91. import { CollectionAndWrong } from "@/api/index";
  92. import { Dialog } from "vant";
  93. import { RouterBus } from "@/hooks";
  94. const router = useRouter();
  95. const query = useRoute().query;
  96. const wrongList = ref<{ id: number; timestamp: number }[]>([]);
  97. const collectionList = ref<{ id: number; timestamp: number }[]>([]);
  98. onMounted(() => {
  99. let localVuex = JSON.parse(window.localStorage.getItem("vuex") || "{}");
  100. let subject = query.subject;
  101. let userWrongKey = localVuex.userData.openid + "_用户错题id_" + subject;
  102. let userCollectKey = localVuex.userData.openid + "_用户收藏id_" + subject;
  103. wrongList.value = JSON.parse(window.localStorage.getItem(userWrongKey) || "[]");
  104. collectionList.value = JSON.parse(window.localStorage.getItem(userCollectKey) || "[]");
  105. });
  106. const onClickLeft = () => {
  107. router.back();
  108. };
  109. const {
  110. router: { push },
  111. } = new RouterBus();
  112. const gsMap: {
  113. xc: string;
  114. hc: string;
  115. kc: string;
  116. mtc: string;
  117. } = {
  118. xc: "小车",
  119. hc: "货车",
  120. kc: "客车",
  121. mtc: "摩托车",
  122. };
  123. const sendWrongSync = (column: { text: string; value: number }) => {
  124. let collectionModel = new CollectionAndWrong("wrong");
  125. let km = Number(query.subject);
  126. let localVuex = JSON.parse(window.localStorage.getItem("vuex") || "{}");
  127. let subject = query.subject;
  128. let userWrongKey = localVuex.userData.openid + "_用户错题id_" + subject;
  129. switch (column.value) {
  130. case 0:
  131. collectionModel
  132. .merge({
  133. wrongs: wrongList.value,
  134. km,
  135. })
  136. .then((res) => {
  137. collectionModel
  138. .getList({
  139. km,
  140. })
  141. .then((res) => {
  142. wrongList.value = res.data;
  143. window.localStorage.setItem(userWrongKey, JSON.stringify(wrongList.value));
  144. });
  145. });
  146. break;
  147. case 1:
  148. collectionModel
  149. .backups({
  150. wrongs: wrongList.value,
  151. km,
  152. })
  153. .then((res) => {
  154. collectionModel
  155. .getList({
  156. km,
  157. })
  158. .then((res) => {
  159. wrongList.value = res.data;
  160. });
  161. });
  162. break;
  163. case 2:
  164. collectionModel
  165. .getList({
  166. km,
  167. })
  168. .then((res) => {
  169. wrongList.value = res.data;
  170. window.localStorage.setItem(userWrongKey, JSON.stringify(wrongList.value));
  171. });
  172. break;
  173. }
  174. wrongSyncVisible.value = false;
  175. };
  176. const sendCollectSync = (column: { text: string; value: number }) => {
  177. let collectionModel = new CollectionAndWrong("collection");
  178. let km = Number(query.subject);
  179. let localVuex = JSON.parse(window.localStorage.getItem("vuex") || "{}");
  180. let subject = query.subject;
  181. let userCollectKey = localVuex.userData.openid + "_用户收藏id_" + subject;
  182. switch (column.value) {
  183. case 0:
  184. collectionModel
  185. .merge({
  186. cols: collectionList.value,
  187. km,
  188. })
  189. .then((res) => {
  190. collectionModel
  191. .getList({
  192. km,
  193. })
  194. .then((res) => {
  195. collectionList.value = res.data;
  196. window.localStorage.setItem(userCollectKey, JSON.stringify(collectionList.value));
  197. });
  198. });
  199. break;
  200. case 1:
  201. collectionModel
  202. .backups({
  203. cols: collectionList.value,
  204. km,
  205. })
  206. .then((res) => {
  207. collectionModel
  208. .getList({
  209. km,
  210. })
  211. .then((res) => {
  212. collectionList.value = res.data;
  213. });
  214. });
  215. break;
  216. case 2:
  217. collectionModel
  218. .getList({
  219. km,
  220. })
  221. .then((res) => {
  222. collectionList.value = res.data;
  223. window.localStorage.setItem(userCollectKey, JSON.stringify(collectionList.value));
  224. });
  225. break;
  226. }
  227. collectSyncVisible.value = false;
  228. };
  229. const clearTopicsCollection = (e: PointerEvent) => {
  230. e.preventDefault();
  231. e.stopPropagation();
  232. let collectionModel = new CollectionModel("collection");
  233. Dialog.confirm({
  234. title: "清除收藏",
  235. message: "是否清除收藏",
  236. })
  237. .then(() => {
  238. // on confirm
  239. collectionModel
  240. .deleteAll({
  241. km: Number(router.currentRoute.value.query.subject),
  242. })
  243. .then((res) => {
  244. Dialog.alert({ message: "清除成功" });
  245. let collectionModel = new CollectionAndWrong("collection");
  246. collectionModel
  247. .getList({
  248. km: Number(router.currentRoute.value.query.subject),
  249. })
  250. .then((res) => {
  251. let localVuex = JSON.parse(window.localStorage.getItem("vuex") || "{}");
  252. let subject = query.subject;
  253. let userCollectKey = localVuex.userData.openid + "_用户收藏id_" + subject;
  254. window.localStorage.setItem(userCollectKey, "[]");
  255. collectionList.value = [];
  256. });
  257. });
  258. })
  259. .catch(() => {
  260. // on cancel
  261. });
  262. };
  263. const clearTopicsWrong = (e: PointerEvent) => {
  264. e.preventDefault();
  265. e.stopPropagation();
  266. let collectionModel = new CollectionModel("wrong");
  267. Dialog.confirm({
  268. title: "清除错题",
  269. message: "是否清除错题",
  270. })
  271. .then(() => {
  272. // on confirm
  273. collectionModel
  274. .deleteAll({
  275. km: Number(router.currentRoute.value.query.subject),
  276. })
  277. .then((res) => {
  278. Dialog.alert({ message: "清除成功" });
  279. let wrongModel = new CollectionAndWrong("wrong");
  280. wrongModel
  281. .getList({
  282. km: Number(router.currentRoute.value.query.subject),
  283. })
  284. .then((res) => {
  285. let localVuex = JSON.parse(window.localStorage.getItem("vuex") || "{}");
  286. let subject = query.subject;
  287. let userWrongKey = localVuex.userData.openid + "_用户错题id_" + subject;
  288. window.localStorage.setItem(userWrongKey, "[]");
  289. wrongList.value = [];
  290. });
  291. });
  292. })
  293. .catch(() => {
  294. // on cancel
  295. });
  296. };
  297. const goExercise = (type: string) => {
  298. switch (type) {
  299. case "wrong":
  300. if (wrongList.value.length == 0) {
  301. Dialog.alert({ title: "没有题目" });
  302. return;
  303. }
  304. push({
  305. name: "wrongExercise",
  306. query: {
  307. ...query,
  308. title: "错题",
  309. },
  310. });
  311. break;
  312. case "collection":
  313. if (collectionList.value.length == 0) {
  314. Dialog.alert({ title: "没有题目" });
  315. return;
  316. }
  317. push({
  318. name: "collectionExercise",
  319. query: {
  320. ...query,
  321. title: "收藏",
  322. },
  323. });
  324. break;
  325. default:
  326. break;
  327. }
  328. };
  329. const isType = ref(0); //0错题 1收藏
  330. const swiper = ref();
  331. const wrongSyncVisible = ref(false);
  332. const collectSyncVisible = ref(false);
  333. </script>
  334. <style lang="scss" scoped>
  335. .bottom {
  336. bottom: 0;
  337. img {
  338. width: 100%;
  339. }
  340. }
  341. .choose {
  342. width: 100%;
  343. display: flex;
  344. justify-content: center;
  345. flex-wrap: wrap;
  346. transform: translate(0%, -8%);
  347. .choose-img {
  348. width: 92%;
  349. position: relative;
  350. .clear {
  351. background: #fff;
  352. border-radius: 15px;
  353. position: absolute;
  354. bottom: 20px;
  355. width: 100px;
  356. height: 30px;
  357. left: 20px;
  358. bottom: 20px;
  359. border: 0;
  360. font-size: 13px;
  361. }
  362. .goArrow {
  363. position: absolute;
  364. top: 32px;
  365. right: 20px;
  366. width: 73px;
  367. }
  368. .choose-text1 {
  369. position: absolute;
  370. font-size: 25px;
  371. color: #fff;
  372. left: 20px;
  373. top: 20px;
  374. }
  375. .choose-text2 {
  376. position: absolute;
  377. top: 56px;
  378. left: 22px;
  379. font-size: 25px;
  380. color: #fff;
  381. }
  382. img {
  383. width: 100%;
  384. }
  385. }
  386. }
  387. .collectionHeader {
  388. width: 100%;
  389. }
  390. .collection-box {
  391. height: 100vh;
  392. display: flex;
  393. flex-direction: column;
  394. }
  395. .title {
  396. display: flex;
  397. width: 130px;
  398. justify-content: space-between;
  399. align-items: center;
  400. span {
  401. font-size: 15px;
  402. font-family: PingFang SC;
  403. font-weight: 400;
  404. line-height: 13px;
  405. color: #0a1a33;
  406. position: relative;
  407. padding: 8px;
  408. }
  409. .active {
  410. &:after {
  411. position: absolute;
  412. content: "";
  413. width: 20px;
  414. height: 4px;
  415. border-radius: 3px;
  416. background-color: #498ef5;
  417. bottom: 0;
  418. left: 50%;
  419. transform: translateX(-50%);
  420. z-index: 100;
  421. }
  422. }
  423. }
  424. </style>