Parcourir la source

新增收藏也错题记录功能

wyling il y a 3 ans
Parent
commit
f43e7bdb07

+ 7 - 4
src/api/modules/collectionAndWrong.ts

@@ -1,4 +1,5 @@
 import request from "../request";
+import { AxiosPromise } from "axios";
 
 export class CollectionAndWrong {
   private urlList: {
@@ -42,13 +43,15 @@ export class CollectionAndWrong {
    * @param params
    * @returns
    */
-  adds = async (params: CollectionAndWrongType.AddCullectionsParams) => {
-    const res = await request({
+  adds(
+    params: CollectionAndWrongType.AddCullectionsParams
+  ): AxiosPromise<CollectionAndWrongType.AddCullectionsRes> {
+    return request({
       url: this.urlList.add,
       data: params,
+      method: "post",
     });
-    return <CollectionAndWrongType.AddCullectionsRes>res.data;
-  };
+  }
 
   /**
    * 批量删除问题

+ 1 - 0
src/api/modules/test.ts

@@ -57,6 +57,7 @@ export async function getTopicList(params: any, isVip: Boolean = true) {
         answer: item.answer,
         userAnswer: getUserAnswer(getType(item.answer.split("-"))),
         isTrue: null,
+        isCollection: false,
       };
     }),
   };

+ 19 - 0
src/dataModel/collection.ts

@@ -29,4 +29,23 @@ export class CollectionModel {
       };
     }
   }
+
+  /** 删除已收藏的问题 */
+  async deletes(
+    ids: number[],
+    collectionList: CollectionAndWrongType.QuestionRes[]
+  ) {
+    const deletesCollectionList = collectionList.filter((item) => {
+      return ids.includes(item.questionId);
+    });
+    const deletesIds = deletesCollectionList.map((item) => item.id);
+    const res = await this.collectionApi.deletes(deletesIds);
+    return res;
+  }
+
+  /** 新增收藏或者错题 */
+  async adds(params: CollectionAndWrongType.AddCullectionsParams) {
+    const res = await this.collectionApi.adds(params);
+    return res.data;
+  }
 }

+ 113 - 112
src/views/collection/index.vue

@@ -1,84 +1,94 @@
 <template>
-  <van-nav-bar left-arrow @click-left="onClickLeft" fixed placeholder>
-    <template #title>
-      <div class="title">
-        <span :class="{ active: isType == 0 }" @click="isType = 0">做错题</span>
-        <span :class="{ active: isType == 1 }" @click="isType = 1">收藏题</span>
-      </div>
-    </template>
-  </van-nav-bar>
-  <div>
-    <van-checkbox-group v-model="checked" ref="checkboxGroup">
-      <van-cell-group>
-        <van-list
-          v-model="loading"
-          :finished="finished"
-          finished-text="没有更多了"
-          @load="onLoad"
-        >
-          <van-swipe-cell
-            v-for="(item, index) in list"
-            :key="index"
-            :disabled="isChoose"
+  <div class="collection-box">
+    <van-nav-bar left-arrow @click-left="onClickLeft" placeholder>
+      <template #title>
+        <div class="title">
+          <span :class="{ active: isType == 0 }" @click="isType = 0"
+            >做错题</span
+          >
+          <span :class="{ active: isType == 1 }" @click="isType = 1"
+            >收藏题</span
           >
-            <van-cell clickable :title="`${item.id}. ${item.issue}`" @click="">
-              <template #icon v-if="isChoose">
-                <van-checkbox :name="item.id" class="checkbox" />
+        </div>
+      </template>
+    </van-nav-bar>
+    <div class="list-box">
+      <van-checkbox-group v-model="checked" ref="checkboxGroup">
+        <van-cell-group>
+          <van-list
+            v-model="loading"
+            :finished="finished"
+            finished-text="没有更多了"
+            @load="onLoad"
+          >
+            <van-swipe-cell
+              v-for="(item, index) in list"
+              :key="index"
+              :disabled="isChoose"
+            >
+              <van-cell
+                clickable
+                :title="`${item.id}. ${item.issue}`"
+                @click=""
+              >
+                <template #icon v-if="isChoose">
+                  <van-checkbox :name="item.id" class="checkbox" />
+                </template>
+              </van-cell>
+              <template #right>
+                <van-button
+                  square
+                  style="height: 100%"
+                  type="danger"
+                  text="删除"
+                  @click="deleteClick(item.id)"
+                />
+                <van-button
+                  square
+                  style="height: 100%"
+                  type="primary"
+                  text="收藏"
+                  v-if="isType == 0"
+                />
               </template>
-            </van-cell>
-            <template #right>
-              <van-button
-                square
-                style="height: 100%"
-                type="danger"
-                text="删除"
-                @click="deleteClick(item.id)"
-              />
-              <van-button
-                square
-                style="height: 100%"
-                type="primary"
-                text="收藏"
-                v-if="isType == 0"
-              />
-            </template>
-          </van-swipe-cell>
-        </van-list>
-      </van-cell-group>
-    </van-checkbox-group>
-  </div>
-  <div style="height: 50px"></div>
-  <div class="bottom-cell">
-    <div>
-      <span v-if="!isChoose" @click="isChoose = true">批量选中</span>
-      <div class="choose" v-else>
-        <van-checkbox v-model="isSelectAll">全选</van-checkbox>
-        <span
-          @click="
-            isChoose = false;
-            unSelectAll();
-          "
-          >取消</span
-        >
-      </div>
+            </van-swipe-cell>
+          </van-list>
+        </van-cell-group>
+      </van-checkbox-group>
     </div>
-    <div>
-      <div class="operate">
-        <van-button
-          round
-          type="danger"
-          size="small"
-          :disabled="checked.length == 0"
-          @click="deletesClick"
-          >删除选中</van-button
-        >
-        <van-button
-          round
-          type="primary"
-          size="small"
-          :disabled="checked.length == 0"
-          >移入收藏夹</van-button
-        >
+    <!-- <div style="height: 50px"></div> -->
+    <div class="bottom-cell">
+      <div>
+        <span v-if="!isChoose" @click="isChoose = true">批量选中</span>
+        <div class="choose" v-else>
+          <van-checkbox v-model="isSelectAll">全选</van-checkbox>
+          <span
+            @click="
+              isChoose = false;
+              unSelectAll();
+            "
+            >取消</span
+          >
+        </div>
+      </div>
+      <div>
+        <div class="operate">
+          <van-button
+            round
+            type="danger"
+            size="small"
+            :disabled="checked.length == 0"
+            @click="deletesClick"
+            >删除选中</van-button
+          >
+          <van-button
+            round
+            type="primary"
+            size="small"
+            :disabled="checked.length == 0"
+            >移入收藏夹</van-button
+          >
+        </div>
       </div>
     </div>
   </div>
@@ -86,7 +96,6 @@
 
 <script lang="ts">
 import { onBeforeMount, computed } from "vue";
-import { getQuestionInfoByIds, CollectionAndWrong } from "@/api";
 import { CollectionModel } from "@/dataModel/collection";
 
 /**
@@ -94,43 +103,29 @@ import { CollectionModel } from "@/dataModel/collection";
  */
 const useQuestionList = (type: CollectionAndWrongType.type) => {
   const collectionModel = new CollectionModel(type);
-  const QuestionApi = new CollectionAndWrong(type);
   const questionList = ref<Test.QuestionInfo[]>([]);
   const collectionList = ref<CollectionAndWrongType.QuestionRes[]>([]);
-  const total = ref(100);
-  const pageNum = ref(0);
+
+  const total = ref(0);
+  const pageNum = ref(1);
   const pageSize = ref(10);
-  const loading = ref(true);
+  const loading = ref(false);
   /**数据是否全部加载完成 */
   const finished = ref(false);
 
   /** 删除已收藏的问题 */
   const deletes = async (ids: number[]) => {
-    const deletesCollectionList = collectionList.value.filter((item) => {
-      return ids.includes(item.questionId);
-    });
-    const deletesIds = deletesCollectionList.map((item) => item.id);
-    const res = await QuestionApi.deletes(deletesIds);
-    //删除完成重新请求数据
-    setData();
-  };
-
-  /** 设置列表数据 */
-  const setData = async () => {
-    const res = await collectionModel.getList({
-      carType: "小车",
-      km: "科目一",
-      pageNum: pageNum.value,
-      pageSize: pageSize.value,
-    });
-    total.value = res.total;
-    collectionList.value = res.collectionList;
-    questionList.value = res.rows;
-    loading.value = false;
+    const res = await collectionModel.deletes(ids, collectionList.value);
+    //乐观删除本地数据
+    questionList.value = questionList.value.filter(
+      (item) => !ids.includes(item.id)
+    );
   };
 
   /**获取下一页数据 */
   const onLoadData = async () => {
+    if (loading.value) return;
+    loading.value = true;
     const res = await collectionModel.getList({
       carType: "小车",
       km: "科目一",
@@ -141,13 +136,10 @@ const useQuestionList = (type: CollectionAndWrongType.type) => {
     collectionList.value.push(...res.collectionList);
     questionList.value.push(...res.rows);
     loading.value = false;
-    finished.value = questionList.value.length === total.value;
+    finished.value = questionList.value.length >= total.value;
     pageNum.value++;
   };
 
-  onBeforeMount(() => {
-    // setData();
-  });
   return {
     questionList,
     deletes,
@@ -191,9 +183,10 @@ const loading = computed(() => {
   return currentView.value.loading;
 });
 
-const onLoad = computed(() => {
-  return currentView.value.onLoadData;
-});
+/**加载数据 */
+const onLoad = async () => {
+  await currentView.value.onLoadData();
+};
 
 const isChoose = ref(false); //开启批量选中
 const isSelectAll = ref(false); //是否全选
@@ -240,6 +233,16 @@ const deletesClick = () => {
 </script>
 
 <style lang="scss" scoped>
+.collection-box {
+  height: 100vh;
+  display: flex;
+  flex-direction: column;
+}
+
+.list-box {
+  flex-grow: 1;
+  overflow-y: auto;
+}
 .title {
   display: flex;
   width: 130px;
@@ -273,8 +276,6 @@ const deletesClick = () => {
   margin-right: 5px;
 }
 .bottom-cell {
-  position: fixed;
-  bottom: 0;
   border-top: 1px solid #bdbaba;
   display: flex;
   justify-content: space-between;

+ 59 - 12
src/views/exercise/hooks.ts

@@ -10,6 +10,9 @@ import {
 import * as API from "@/api";
 import { Howl, Howler } from "howler";
 import { useRoute } from "vue-router";
+import { CollectionModel } from "@/dataModel/collection";
+import { RouterBus } from "@/hooks";
+import { Notify } from "vant";
 
 //答题模式切换
 export function useTopicMode() {
@@ -174,7 +177,41 @@ const useSubjectCheck = (
   const trueNum = ref(0); //正确数量
   const falseNum = ref(0); //错误数量
   const isJumpNext = ref(false); //答对跳转下一题
+  const wrongModel = new CollectionModel("wrong");
+  const collectionModel = new CollectionModel("collection");
+  const {
+    route: { query },
+  } = new RouterBus();
 
+  /** 批量新增收藏 */
+  const addsCullection = async (ids: number[]) => {
+    const questionList = ids.map((id) => {
+      return {
+        carType: query.vehicle as CollectionAndWrongType.CarType,
+        km: query.name as CollectionAndWrongType.Km,
+        questionId: id,
+      };
+    });
+    collectionModel.adds(questionList);
+  };
+
+  /** 收藏当前题目 */
+  const addCurrentQuestion = async () => {
+    const res = await collectionModel.adds([
+      {
+        carType: query.vehicle as CollectionAndWrongType.CarType,
+        km: query.name as CollectionAndWrongType.Km,
+        questionId: currentSubject.value.id,
+      },
+    ]);
+    if (res.data == 1) {
+      currentSubject.value.isCollection = true;
+      Notify({ type: "success", message: "收藏成功" });
+    } else {
+      currentSubject.value.isCollection = true;
+      Notify({ type: "primary", message: res.msg });
+    }
+  };
   /**
    * 选择答案后进行校验
    */
@@ -197,7 +234,7 @@ const useSubjectCheck = (
       JSON.stringify(currentSubject.value.answer) ==
       JSON.stringify(currentSubject.value.userAnswer)
     ) {
-      console.log("答案正确");
+      //答案正确
       currentSubject.value.isTrue = true;
       trueNum.value++;
       if (isJumpNext.value) {
@@ -206,7 +243,14 @@ const useSubjectCheck = (
         });
       }
     } else {
-      console.log("错误");
+      //答案错误
+      wrongModel.adds([
+        {
+          carType: query.vehicle as CollectionAndWrongType.CarType,
+          km: query.name as CollectionAndWrongType.Km,
+          questionId: currentSubject.value.id,
+        },
+      ]);
       currentSubject.value.isTrue = false;
       falseNum.value++;
     }
@@ -217,6 +261,7 @@ const useSubjectCheck = (
     falseNum,
     isJumpNext,
     userAnswerChange,
+    addCurrentQuestion,
   };
 };
 
@@ -230,9 +275,8 @@ export const useSubjectShowLogic = () => {
   } = useSubjectList(); //获取题目列表
 
   const nextBtnState = ref(true); //下一题数据请求锁
-  /**
-   * 展示下一题
-   */
+
+  /** 展示下一题 */
   const nextSubject = async () => {
     if (currentSubjectIndex.value < subjectList.value.length - 1) {
       currentSubjectIndex.value++;
@@ -247,19 +291,21 @@ export const useSubjectShowLogic = () => {
       }
     }
   };
-  /**
-   * 展示上一题
-   */
+
+  /** 展示上一题  */
   const lastSubject = () => {
     if (currentSubjectIndex.value > 0) {
       currentSubjectIndex.value--;
     }
   };
 
-  const { trueNum, falseNum, isJumpNext, userAnswerChange } = useSubjectCheck(
-    currentSubject,
-    nextSubject
-  );
+  const {
+    trueNum,
+    falseNum,
+    isJumpNext,
+    userAnswerChange,
+    addCurrentQuestion,
+  } = useSubjectCheck(currentSubject, nextSubject);
 
   return {
     currentSubject,
@@ -271,5 +317,6 @@ export const useSubjectShowLogic = () => {
     falseNum,
     isJumpNext,
     userAnswerChange,
+    addCurrentQuestion,
   };
 };

+ 7 - 3
src/views/exercise/index.vue

@@ -168,8 +168,11 @@
   <van-divider />
   <!-- 功能选择列表 -->
   <div class="function-list">
-    <div class="function-item">
-      <m-icon type="shoucanghui" size="25px" />
+    <div class="function-item" @click="addCurrentQuestion">
+      <m-icon
+        :type="currentSubject?.isCollection ? 'shoucanghuang' : 'shoucanghui'"
+        size="25px"
+      />
       <span>收藏</span>
     </div>
     <div class="function-item" @click="subjectAudioPlay('读题+答案')">
@@ -276,7 +279,7 @@
 </template>
 
 <script lang="ts" setup>
-import { ref } from "vue";
+import { computed, ref } from "vue";
 import { useTopicMode, useAudioSet, useSubjectShowLogic } from "./hooks";
 import { RouterBus } from "@/hooks";
 const {
@@ -305,6 +308,7 @@ const {
   falseNum,
   isJumpNext,
   userAnswerChange,
+  addCurrentQuestion,
 } = useSubjectShowLogic();
 
 //音频模块