wyling 3 éve
szülő
commit
b40069a3a5

+ 69 - 8
src/api/modules/test.ts

@@ -1,15 +1,76 @@
 import request from "../request";
-import Mcok from "mockjs";
+import { AxiosPromise } from "axios";
 
-interface topicQuery {
-  //分类练习
-  classIssue: string;
-  //当前页码
-  pageNum: string;
-  //每页数据量
-  pageSize: string;
+class Test {
+  /** 获取题目列表 */
+  list(params: Test.listParams): AxiosPromise<Test.listRes> {
+    return request("/student/qustion/info/list", {
+      params,
+    });
+  }
+
+  /** 获取非VIP题目列表 */
+  normalList(params: Test.listParams): AxiosPromise<Test.listRes> {
+    return request("/student/qustion/info/normalList", {
+      params,
+    });
+  }
+
+  /** 根据ids批量获取问题详情  */
+  getQuestionInfoByIds(
+    params: Test.QuestionInfoByIdsParams
+  ): AxiosPromise<Test.QuestionInfoByIdsRes> {
+    return request("/student/qustion/info/getQuestionInfoByIds", {
+      params: {
+        ...params,
+        ids: params.ids.toString(),
+      },
+    });
+  }
+
+  /** 获取地方题分类 */
+  selectDfQustionInfo(
+    params: Partial<Test.getTopicClassParams>
+  ): AxiosPromise<Test.selectDfQustionInfoRes[]> {
+    return request({
+      url: `/student/qustion/info/selectDfQustionInfo`,
+      params,
+    });
+  }
+
+  /** 获取分类专题分类 */
+  selectFlQustionInfo(
+    params: Partial<Test.getTopicClassParams>
+  ): AxiosPromise<Test.selectFlQustionInfoRes[]> {
+    return request({
+      url: `/student/qustion/info/selectFlQustionInfo`,
+      params,
+    });
+  }
+
+  /** 获取精选题分类 */
+  selectJxQustionInfo(
+    params: Partial<Test.getTopicClassParams>
+  ): AxiosPromise<Test.selectJxQustionInfoRes[]> {
+    return request({
+      url: `/student/qustion/info/selectJxQustionInfo`,
+      params,
+    });
+  }
+
+  /** 获取顺序练习分类 */
+  selectSxQustionInfo(
+    params: Partial<Test.getTopicClassParams>
+  ): AxiosPromise<Test.selectSxQustionInfoRes[]> {
+    return request({
+      url: `/student/qustion/info/selectSxQustionInfo`,
+      params,
+    });
+  }
 }
 
+export const test = new Test();
+
 /**
  * 获取题目列表
  * @returns

+ 1 - 1
src/api/types/cashOut.d.ts

@@ -6,7 +6,7 @@ declare namespace CashOutType {
     hierarchy: string;
     openid: string;
     percentage: string;
-    profitPrice: string;
+    profitPrice: number;
   }
   interface extensionIncomeListRes extends Common.Res {
     rows: otherUserInfo[];

+ 34 - 0
src/api/types/test.d.ts

@@ -38,6 +38,9 @@ declare namespace Test {
     titlekeyword: string;
   }
 
+  type listParams = Partial<QuestionInfo> & Common.Paging;
+  type listRes = QuestionInfoByIdsRes;
+
   interface QuestionInfoByIdsParams extends Common.Paging {
     ids: number[];
   }
@@ -46,4 +49,35 @@ declare namespace Test {
     rows: QuestionInfo[];
     count: number;
   }
+
+  interface getTopicClassParams {
+    liceBus: string;
+    liceCar: string;
+    liceMoto: string;
+    liceTruck: string;
+    subject1: string;
+    subject2: string;
+    subject3: string;
+    subject4: string;
+  }
+
+  interface selectDfQustionInfoRes {
+    placeIssue: string;
+    placeIssueName: string;
+  }
+
+  interface selectFlQustionInfoRes {
+    classIssue: string;
+    classIssueName: string;
+  }
+
+  interface selectJxQustionInfoRes {
+    excellIssue: string;
+    excellIssueName: string;
+  }
+
+  interface selectSxQustionInfoRes {
+    sequeIssue: string;
+    sequeIssueName: string;
+  }
 }

+ 20 - 3
src/dataModel/cashOut.ts

@@ -8,14 +8,31 @@ export class CashOutModel {
   async extensionIncomeList() {
     const res = await this.api.extensionIncomeList();
     return {
-      rows: res.data.rows,
+      rows: res.data.rows.map((item) => {
+        item.profitPrice /= 100;
+        return {
+          ...item,
+          profitPrice: item.profitPrice.toFixed(2),
+        };
+      }),
       total: res.data.total,
     };
   }
 
   /**查询收益金额(总金额、已提现金额、未提现金额) */
   async extensionIncomePrice() {
-    const res = await this.api.extensionIncomePrice();
-    return res.data.data;
+    const {
+      data: { data },
+    } = await this.api.extensionIncomePrice();
+
+    data.extractPrice /= 100;
+    data.remainderPrice /= 100;
+    data.totalPrice /= 100;
+    return {
+      ...data,
+      extractPrice: data.extractPrice.toFixed(2),
+      remainderPrice: data.remainderPrice.toFixed(2),
+      totalPrice: data.totalPrice.toFixed(2),
+    };
   }
 }

+ 31 - 0
src/dataModel/test.ts

@@ -0,0 +1,31 @@
+import { test } from "@/api";
+
+class TestModel {
+  /** 根据不同类型获取分类 */
+  async getTopicClass(
+    type: "df" | "fl" | "jx" | "sx",
+    params: Partial<Test.getTopicClassParams>
+  ) {
+    switch (type) {
+      case "df": {
+        const res = await test.selectDfQustionInfo(params);
+        return res.data;
+      }
+      case "fl": {
+        const res = await test.selectFlQustionInfo(params);
+        return res.data;
+      }
+      case "jx": {
+        const res = await test.selectJxQustionInfo(params);
+        return res.data;
+      }
+      case "sx": {
+        const res = await test.selectSxQustionInfo(params);
+        return res.data;
+      }
+    }
+  }
+
+  /** 获取题目列表 */
+  async getList() {}
+}

+ 325 - 0
src/logicModel/exercise.ts

@@ -0,0 +1,325 @@
+import {
+  ref,
+  watch,
+  onBeforeMount,
+  computed,
+  nextTick,
+  ComputedRef,
+} from "vue";
+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";
+
+class Execrise {
+  constructor() {}
+
+  /** 答题模式切换 */
+  useTopicMode = () => {
+    const answerTypeList = ref([
+      { name: "顺序练习" },
+      { name: "随机练习" },
+      { name: "背题模式" },
+    ]);
+    const currentType = ref(0);
+    const typeParams = computed(() => {
+      switch (currentType.value) {
+        case 0:
+          return {
+            order: true, //顺序练习
+            answerShow: false, //背题模式
+          };
+        case 1:
+          return {
+            order: false, //顺序练习
+            answerShow: false, //背题模式
+          };
+        case 2:
+          return {
+            order: true, //顺序练习
+            answerShow: true, //背题模式
+          };
+      }
+    });
+
+    return {
+      answerTypeList,
+      currentType,
+      typeParams,
+    };
+  };
+}
+
+//语音设置
+export function useAudioSet(currentSubject: ComputedRef<any>) {
+  const aotuPlayFlag = ref(false);
+
+  let sound: Howl;
+  /**
+   * 播放音频
+   * @param audioUrl
+   */
+  const audioPlay = (audioUrl: string | string[]) => {
+    audioPause();
+    sound = new Howl({
+      src: audioUrl,
+    });
+    sound.once("load", function () {
+      sound.play();
+    });
+    if (typeof audioUrl === "object") {
+      sound.once("end", () => {
+        sound = new Howl({
+          src: audioUrl[1],
+        });
+        sound.once("load", function () {
+          sound.play();
+        });
+      });
+    }
+  };
+
+  /**
+   * 停止播放
+   */
+  const audioPause = () => {
+    sound && sound.pause();
+  };
+
+  /**
+   * 读题
+   */
+  const subjectAudioPlay = (
+    type: "读题" | "读官方解释" | "读技巧解释" | "读题+答案"
+  ) => {
+    switch (type) {
+      case "读题":
+        audioPlay(currentSubject.value.issuemp3);
+        break;
+      case "读官方解释":
+        audioPlay(currentSubject.value.explainjsmp3);
+        break;
+      case "读技巧解释":
+        audioPlay(currentSubject.value.explainMp3);
+        break;
+      case "读题+答案":
+        audioPlay([
+          currentSubject.value.issuemp3,
+          currentSubject.value.answermp3,
+        ]);
+        break;
+      default:
+        break;
+    }
+  };
+
+  //音频模块end
+  const aotuPlaySet = () => {
+    aotuPlayFlag.value = !aotuPlayFlag.value;
+    aotuPlayFlag.value ? subjectAudioPlay("读题") : audioPause();
+  };
+
+  //自动读题
+  watch(currentSubject, () => {
+    if (aotuPlayFlag.value) subjectAudioPlay("读题"); //自动读题
+  });
+
+  return {
+    aotuPlayFlag,
+    aotuPlaySet,
+    subjectAudioPlay,
+  };
+}
+
+const useSubjectList = () => {
+  const subjectList = ref<any[]>([]); //题目列表
+  const subjectTotal = ref(0); //题目总数
+  const pageNum = ref(1); //当前请求页码
+  const pageSize = ref(100); //当前请求每页数据
+  const query = useRoute().query; //路由query参数
+  onBeforeMount(async () => {
+    const res = await API.getTopicList({
+      ...query,
+      pageNum: pageNum.value,
+      pageSize: pageSize.value,
+    });
+    subjectList.value = res.list;
+    subjectTotal.value = res.total;
+  });
+  //加载下一页数据
+  const loadNewSubject = async () => {
+    if (subjectList.value.length == subjectTotal.value) return;
+    pageNum.value++;
+    const res = await API.getTopicList({
+      ...query,
+      pageNum: pageNum.value,
+      pageSize: pageSize.value,
+    });
+    subjectList.value = subjectList.value.concat(res.list);
+  };
+  const currentSubjectIndex = ref(0); //当前题目下标
+  //当前题目内容
+  const currentSubject = computed(() => {
+    return subjectList.value[currentSubjectIndex.value];
+  });
+  return {
+    subjectList,
+    subjectTotal,
+    loadNewSubject,
+    currentSubject,
+    currentSubjectIndex,
+  };
+};
+
+const useSubjectCheck = (
+  currentSubject: ComputedRef<any>,
+  nextSubject: () => Promise<void>
+) => {
+  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 });
+    }
+  };
+  /**
+   * 选择答案后进行校验
+   */
+  const userAnswerChange = () => {
+    currentSubject.value.optsBack = currentSubject.value.opts.map(
+      (val: String) => {
+        let status;
+        if (currentSubject.value.answer.includes(val)) {
+          status = 1;
+        } else {
+          status = 0;
+        }
+        if (currentSubject.value.userAnswer.includes(val)) {
+          status += 2;
+        }
+        return { opt: val, status };
+      }
+    );
+    if (
+      JSON.stringify(currentSubject.value.answer) ==
+      JSON.stringify(currentSubject.value.userAnswer)
+    ) {
+      //答案正确
+      currentSubject.value.isTrue = true;
+      trueNum.value++;
+      if (isJumpNext.value) {
+        nextTick(() => {
+          nextSubject();
+        });
+      }
+    } else {
+      //答案错误
+      wrongModel.adds([
+        {
+          carType: query.vehicle as CollectionAndWrongType.CarType,
+          km: query.name as CollectionAndWrongType.Km,
+          questionId: currentSubject.value.id,
+        },
+      ]);
+      currentSubject.value.isTrue = false;
+      falseNum.value++;
+    }
+  };
+
+  return {
+    trueNum,
+    falseNum,
+    isJumpNext,
+    userAnswerChange,
+    addCurrentQuestion,
+  };
+};
+
+export const useSubjectShowLogic = () => {
+  const {
+    subjectList,
+    subjectTotal,
+    loadNewSubject,
+    currentSubject,
+    currentSubjectIndex,
+  } = useSubjectList(); //获取题目列表
+
+  const nextBtnState = ref(true); //下一题数据请求锁
+
+  /** 展示下一题 */
+  const nextSubject = async () => {
+    if (currentSubjectIndex.value < subjectList.value.length - 1) {
+      currentSubjectIndex.value++;
+    } else {
+      if (nextBtnState.value) {
+        //禁用下一题按钮
+        nextBtnState.value = false;
+        //题目数量不足加载数据
+        await loadNewSubject();
+        //启用按钮
+        nextBtnState.value = true;
+      }
+    }
+  };
+
+  /** 展示上一题  */
+  const lastSubject = () => {
+    if (currentSubjectIndex.value > 0) {
+      currentSubjectIndex.value--;
+    }
+  };
+
+  const {
+    trueNum,
+    falseNum,
+    isJumpNext,
+    userAnswerChange,
+    addCurrentQuestion,
+  } = useSubjectCheck(currentSubject, nextSubject);
+
+  return {
+    currentSubject,
+    currentSubjectIndex,
+    subjectTotal,
+    nextSubject,
+    lastSubject,
+    trueNum,
+    falseNum,
+    isJumpNext,
+    userAnswerChange,
+    addCurrentQuestion,
+  };
+};

+ 11 - 0
src/store/index.ts

@@ -6,8 +6,13 @@ const store = createStore({
   state: () => ({
     token: "",
     userData: {},
+    carType: "0",
+    suject: "0",
   }),
   getters: {
+    getCarType(state) {
+      return state.carType;
+    },
     getToken(state) {
       return state.token;
     },
@@ -16,6 +21,12 @@ const store = createStore({
     },
   },
   mutations: {
+    setSuject(state, suject: string) {
+      state.suject = suject;
+    },
+    setCatType(state, carType: string) {
+      state.carType = carType;
+    },
     setToken(state, token: string) {
       state.token = token;
     },

+ 19 - 2
src/views/cashOut/index.vue

@@ -68,7 +68,17 @@ import { RouterBus } from "@/hooks";
 const cashOutModel = new CashOutModel();
 /** 获取下级用户列表 */
 const useOtherUserInfoList = () => {
-  const otherUserInfoList = ref<CashOutType.otherUserInfo[]>([]);
+  const otherUserInfoList = ref<
+    {
+      profitPrice: string;
+      headImage: string;
+      nickName: string;
+      createTime: string;
+      hierarchy: string;
+      openid: string;
+      percentage: string;
+    }[]
+  >([]);
   onBeforeMount(async () => {
     const res = await cashOutModel.extensionIncomeList();
     otherUserInfoList.value.push(...res.rows);
@@ -79,7 +89,14 @@ const useOtherUserInfoList = () => {
 };
 /** 获取用户可提现信息 */
 const useUserInfo = () => {
-  const userInfo = ref<CashOutType.userInfo>();
+  const userInfo = ref<{
+    extractPrice: string;
+    remainderPrice: string;
+    totalPrice: string;
+    beneficiaryOpenid: string;
+    headImage: string;
+    nickName: string;
+  }>();
   onBeforeMount(async () => {
     const res = await cashOutModel.extensionIncomePrice();
     userInfo.value = res;

+ 39 - 5
src/views/home/children/test/index.vue

@@ -4,8 +4,18 @@
   <!-- 轮播图 -->
   <!-- <swiper /> -->
   <!-- 用户做题预选界面 -->
-  <van-tabs class="car-type" line-width="0" animated>
-    <van-tab v-for="(carTypeItem, index) in carTypeList" :key="index">
+  <van-tabs
+    class="car-type"
+    line-width="0"
+    animated
+    ref="carTypeRef"
+    @click="carTypeChange"
+  >
+    <van-tab
+      v-for="(carTypeItem, index) in carTypeList"
+      :key="index"
+      :name="carTypeItem.name"
+    >
       <template #title>
         <div class="car-choose">
           <m-icon :type="carTypeItem.icon" class="img" />
@@ -13,11 +23,17 @@
           <span>{{ carTypeItem.name }}</span>
         </div>
       </template>
-      <van-tabs class="test-type" animated>
+      <van-tabs
+        class="test-type"
+        animated
+        ref="sujectRef"
+        @click="sujectChange"
+      >
         <van-tab
           :title="sujectItem.name"
           v-for="(sujectItem, index) in carTypeItem.sujectList"
           :key="index"
+          :name="sujectItem.name"
         >
           <component
             :is="sujectOne"
@@ -31,9 +47,27 @@
 
 <script lang="ts" setup>
 import sujectOne from "./components/sujectOne.vue";
-import swiper from "./components/swiper.vue";
 import userData from "./components/userData.vue";
-import { ref } from "vue";
+import { ref, nextTick } from "vue";
+import { useStore } from "vuex";
+const store = useStore();
+
+const carTypeRef = ref<any>(null);
+nextTick(() => {
+  carTypeRef.value.scrollTo(store.state.carType);
+  nextTick(() => {
+    sujectRef.value.scrollTo(store.state.suject);
+  });
+});
+const carTypeChange = (e: string) => {
+  store.commit("setCatType", e);
+};
+
+const sujectRef = ref<any>(null);
+
+const sujectChange = (e: string) => {
+  store.commit("setSuject", e);
+};
 
 const carTypeList = ref([
   {