Browse Source

练习模块开发中

zhangyujun 3 years ago
parent
commit
66e5606c64

+ 16 - 0
src/api/modules/exam.js

@@ -50,6 +50,22 @@ const exam={
 			params
 		})
 
+	},
+	//查询模拟考试题库
+	studentQuestionInfoSelectTestQuestionInfo(params){
+		return request({
+			url:"student/question/info/selectTestQuestionInfo",
+			method:'get',
+			params
+		})
+	},
+	//查询题库
+	studentQuestionInfoList(params){
+		return request({
+			url:"student/question/info/list",
+			method:'get',
+			params
+		})
 	}
 }
 

+ 9 - 0
src/api/request.js

@@ -63,6 +63,15 @@ service.interceptors.response.use(
 		let {
 			message
 		} = error;
+		console.log(error,'error')
+		if(!message){
+			message = "未知错误"
+			wx.showToast({
+				title: message,
+				icon: 'none'
+			})
+			return Promise.reject(error)
+		}
 		if (message == "Network Error") {
 			message = "后端接口连接异常";
 		} else if (message.includes("timeout")) {

+ 10 - 3
src/otherPages/beforeMockExam/index.vue

@@ -49,6 +49,7 @@
 
 <script>
 import api from "@/api/index";
+import utils from "@/utils/index";
 export default {
   data() {
     return {
@@ -59,12 +60,18 @@ export default {
     this.query = query;
   },
   computed: {
-      realName() {
-          return this.$store.state.user.userInfo.realName
-      }
+    realName() {
+      return this.$store.state.user.userInfo.realName;
+    },
   },
   methods: {
+    goMockExam(e) {},
     gotoNextPage(e) {
+      let query = Object.assign({},this.query)
+      query.title = "模拟考试"
+      uni.navigateTo({
+        url: "/otherPages/mockExam/index?" + utils.mapToUrlQuery(query),
+      });
       api.user
         .studentUserRealname({
           realName: this.realName,

+ 7 - 1
src/otherPages/collection/components/list.vue

@@ -78,7 +78,7 @@
             size="small"
             :disabled="checked.length == 0"
             @click="collectionClick"
-            v-if="props.type == 'wrong'"
+            v-if="type == 'wrong'"
             >移入收藏夹</van-button
           >
         </div>
@@ -94,6 +94,12 @@ export default {
 			list:[]
 		}
 	},
+  props: {
+    type: {
+      type: String,
+      default:'wrong'
+    },
+  },
 	methods: {
 		name() {
 			

+ 49 - 59
src/otherPages/collection/index.vue

@@ -1,50 +1,33 @@
 <template>
   <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;
-              swiper.swipeTo(0);
-            "
-            >做错题</span
-          >
-          <span
-            :class="{ active: isType == 1 }"
-            @click="
-              isType = 1;
-              swiper.swipeTo(1);
-            "
-            >收藏题</span
-          >
-        </div>
-      </template>
-    </van-nav-bar>
-    <van-swipe ref="swiper" :show-indicators="false" :touchable="false">
-      <van-swipe-item> <listCom type="wrong" /> </van-swipe-item>
-      <van-swipe-item> <listCom type="collection" /> </van-swipe-item>
-    </van-swipe>
+    <view class="header">
+      <view class="title">
+        <span :class="{ active: isType == 0 }" @click="isType = 0">做错题</span>
+        <span :class="{ active: isType == 1 }" @click="isType = 1">收藏题</span>
+      </view>
+    </view>
+    <swiper :current="isType" :duration="500">
+      <swiper-item>
+        <scroll-view :scroll-y="true"> </scroll-view>
+      </swiper-item>
+      <swiper-item>
+        <scroll-view :scroll-y="true"> </scroll-view>
+      </swiper-item>
+    </swiper>
   </div>
 </template>
 
 <script >
-import listCom from "./components/list.vue";
 export default {
   data() {
     return {
-        isType:0,
-        
-
+      isType: 0,
     };
   },
   methods: {
     onClickLeft() {},
   },
-  components: {
-    listCom,
-  },
+  components: {},
 };
 </script>
 
@@ -53,33 +36,40 @@ export default {
   height: 100vh;
   display: flex;
   flex-direction: column;
+  background: #fff;
 }
-.title {
-  display: flex;
-  width: 130px;
-  justify-content: space-between;
-  align-items: center;
-  span {
-    font-size: 15px;
-    font-family: PingFang SC;
-    font-weight: 400;
-    line-height: 13px;
-    color: #0a1a33;
-    position: relative;
-    padding: 8px;
-  }
-  .active {
-    &:after {
-      position: absolute;
-      content: "";
-      width: 20px;
-      height: 4px;
-      border-radius: 3px;
-      background-color: #498ef5;
-      bottom: 0;
-      left: 50%;
-      transform: translateX(-50%);
-      z-index: 100;
+.header {
+  width: 100%;
+  border-bottom: 2rpx solid #dddddd;
+  padding-bottom: 15rpx;
+  .title {
+    display: flex;
+    width: 260rpx;
+    margin: 0 auto;
+    justify-content: space-between;
+    align-items: center;
+    span {
+      font-size: 15px;
+      font-family: PingFang SC;
+      font-weight: 400;
+      line-height: 13px;
+      color: #0a1a33;
+      position: relative;
+      padding: 8px;
+    }
+    .active {
+      &:after {
+        position: absolute;
+        content: "";
+        width: 20px;
+        height: 4px;
+        border-radius: 3px;
+        background-color: #498ef5;
+        bottom: 0;
+        left: 50%;
+        transform: translateX(-50%);
+        z-index: 100;
+      }
     }
   }
 }

+ 82 - 0
src/otherPages/exercise/components/navBar.vue

@@ -0,0 +1,82 @@
+<template>
+  <div
+    :style="{
+      height: (menuButton.height+8) + 'px',
+    }"
+    class="header"
+  >
+
+    <div class="header-title">
+      <text> {{title}}</text>
+    </div>
+  </div>
+</template>
+
+<script>
+
+export default {
+  data() {
+    return {
+      menuButton: {
+        bottom: 0,
+        height: 0,
+        left: 0,
+        right: 0,
+        top: 0,
+        width: 0,
+      },
+    };
+  },
+  props: {
+      title: {
+          type: String,
+          default:''
+      },
+      size:{
+          type:String,
+          default:'16px'
+      }
+  },
+  mounted() {
+    this.menuButton = uni.getMenuButtonBoundingClientRect();
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.header {
+  width: 100%;
+  overflow: hidden;
+  display: flex;
+  align-content: center;
+  align-items: center;
+  position: relative;
+  background: #fff;
+  .header-title {
+    width: 100%;
+    height: 100%;
+    text-align: center;
+    justify-content: center;
+    vertical-align: baseline;
+    display: flex;
+    align-content: center;
+    align-items: center;
+    text {
+      vertical-align: text-top;
+    }
+  }
+  .header-left {
+    position: absolute;
+    left: 0;
+    padding-left: 24rpx;
+    height: 100%;
+    display: flex;
+    align-content: center;
+    align-items: center;
+    .arrow-left {
+      color: #1989fa;
+      vertical-align: middle;
+    }
+  }
+}
+</style>

+ 515 - 0
src/otherPages/exercise/index.vue

@@ -0,0 +1,515 @@
+<template>
+  <view class="box">
+    <nav-bar :title="navTitle"> </nav-bar>
+    <!-- <view style="text-align:center;">
+      <van-count-down :time="time"></van-count-down>
+    </view> -->
+    <view class="divider"></view>
+    <view class="problem-box">
+      <span class="problem-type">{{
+        problemList[problemListIndex].questionType | questionType
+      }}</span>
+      <!-- <text>{{ problemListIndex + 1 }}、</text> -->
+      <text class="">{{ problemList[problemListIndex].issue }}</text>
+      <view v-if="problemList[problemListIndex].image" class="problem-img">
+        <image
+          mode="widthFix"
+          :src="problemList[problemListIndex].image"
+        ></image>
+      </view>
+      <!-- 单选 -->
+      <view
+        v-if="
+          problemList[problemListIndex].questionType < 3 &&
+          !problemList[problemListIndex].isCompleted
+        "
+        class="problem-ops"
+      >
+        <van-radio-group
+          :value="problemList[problemListIndex].userAnswer"
+          :max="1"
+          @change="changeGroup"
+        >
+          <van-radio
+            @change="changeCheckbox"
+            :value="
+              problemList[problemListIndex].userAnswer.includes(
+                problemList[problemListIndex].answer
+              )
+            "
+            class="problem-checkbox"
+            use-icon-slot
+            v-for="(item, index) in problemList[problemListIndex].optsArr"
+            :key="index"
+            :name="item"
+          >
+            <text class="">{{ item }}</text>
+            <view
+              class="problem-op"
+              :class="{
+                'problem-op_selected':
+                  problemList[problemListIndex].userAnswer.includes(item),
+              }"
+              slot="icon"
+              >{{ numberToLetter(index) }}</view
+            >
+          </van-radio>
+        </van-radio-group>
+      </view>
+      <view
+        v-if="
+          problemList[problemListIndex].questionType < 3 &&
+          problemList[problemListIndex].isCompleted
+        "
+      >
+        <view
+          v-for="(item, index) in problemList[problemListIndex].optsArr"
+          :key="index"
+          class="problem-select"
+        >
+          <icon class="icon-box-img" type="success" size="75rpx"></icon>
+          <text class="problem-opAnswer">{{ numberToLetter(index) }}</text>
+        </view>
+      </view>
+      <!-- 多选 -->
+      <view
+        v-if="
+          problemList[problemListIndex].questionType == 3 &&
+          !problemList[problemListIndex].isCompleted
+        "
+        class="problem-ops"
+      >
+        <van-checkbox-group
+          :value="problemList[problemListIndex].userAnswer"
+          :max="4"
+          @change="changeGroup"
+        >
+          <van-checkbox
+            @change="changeCheckbox"
+            :value="
+              problemList[problemListIndex].userAnswer.includes(
+                problemList[problemListIndex].answer
+              )
+            "
+            class="problem-checkbox"
+            use-icon-slot
+            v-for="(item, index) in problemList[problemListIndex].optsArr"
+            :key="index"
+            :name="item"
+          >
+            <text>{{ item }}</text>
+            <view
+              class="problem-op"
+              :class="{
+                'problem-op_selected':
+                  problemList[problemListIndex].userAnswer.includes(item),
+              }"
+              slot="icon"
+              >{{ numberToLetter(index) }}</view
+            >
+          </van-checkbox>
+        </van-checkbox-group>
+      </view>
+      <view class="function-list">
+        <div class="function-item">
+          <van-icon name="star-o" size="25px" />
+          <span>收藏</span>
+        </div>
+        <!-- <div class="function-item" @click="answerAudioPlay">
+      <m-icon type="a-dtda" size="25px" />
+      <span>读题+答案</span>
+    </div> -->
+        <div
+          @click="readQuestion(problemList[problemListIndex].issuemp3)"
+          class="function-item"
+        >
+          <van-icon name="bullhorn-o" size="25px" />
+          <span>读题</span>
+        </div>
+        <!-- <div class="function-item" @click="currentAnswerIndexBack">
+      <m-icon type="shangyiti" size="25px" />
+      <span>上一题</span>
+    </div>
+    <div class="function-item" @click="skillsShow = true">
+      <m-icon type="zongtishu" size="25px" />
+      <span>1/100</span>
+    </div>
+    <div class="function-item" @click="currentAnswerIndexGo">
+      <m-icon type="xiayiti" size="25px" />
+      <span>下一题</span>
+    </div> -->
+      </view>
+      <view
+        v-if="problemList[problemListIndex].isCompleted"
+        class="look-answer"
+      >
+        <view>答案是:{{ problemList[problemListIndex].answer }}</view>
+      </view>
+    </view>
+
+    <van-tabbar>
+      <van-tabbar-item @click="goBeforeTopics"
+        ><van-icon
+          slot="icon"
+          custom-style="transform: rotate(90deg);"
+          custom-class="last-subject"
+          name="down"
+          size="18px"
+        />上一题
+      </van-tabbar-item>
+      <van-tabbar-item
+        ><van-icon slot="icon" size="18px" name="description" />{{
+          problemListIndex + 1
+        }}/{{ problemListTotal }}
+      </van-tabbar-item>
+      <van-tabbar-item @click="submitExam"
+        ><van-icon slot="icon" size="18px" name="records" />交卷
+      </van-tabbar-item>
+      <van-tabbar-item @click="goNextTopics"
+        ><van-icon
+          slot="icon"
+          custom-style="transform: rotate(-90deg);"
+          custom-class="last-subject"
+          name="down"
+          size="18px"
+        />下一题
+      </van-tabbar-item>
+    </van-tabbar>
+  </view>
+</template>
+<script>
+import navBar from "./components/navBar.vue";
+import api from "@/api/index";
+import utils from "@/utils/index";
+export default {
+  data() {
+    return {
+      query: {
+        cert: "",
+        vehicle: "",
+        subject: "",
+        title: "",
+      },
+      currentAnswer: [
+        {
+          selected: false,
+          value: "",
+        },
+      ],
+      time: 45 * 60 * 1000,
+      problemListTotal: 1,
+      problemList: [
+        {
+          answer: "×",
+          answerkeyword: "",
+          answermp3:
+            "https://t1-1305573081.file.myqcloud.com/kt/answer_mp3/answer1389.mp3",
+          classIssue: "54",
+          classIssueName: "车内开关/装置",
+          classSort: 16,
+          createTime: "2022-04-21 13:33:46",
+          excellIssue: "23",
+          excellIssueName: "必学题三",
+          excellSort: 4,
+          explainGif:
+            "https://t1-1305573081.file.myqcloud.com/kt/explain_gif/explain1389.gif",
+          explainJq:
+            "看图答题:红色圆圈套在杆子中间.答对;不在中间或没有圆圈的.答错。",
+          explainJs:
+            "图中所示为左右转向灯开关转向灯操作:上提是右转向灯亮起,下压是左转向灯。",
+          explainMp3:
+            "https://t1-1305573081.file.myqcloud.com/kt/explain_mp3/explain1389.mp3",
+          explainjsmp3:
+            "https://t1-1305573081.file.myqcloud.com/kt/explain_js_mp3/explainJS1389.mp3",
+          id: 831,
+          idKt: 1389,
+          idYdt: 950,
+          image:
+            "https://t1-1305573081.file.myqcloud.com/kt/image/image1389.png",
+          imageYdt:
+            "https://t1-1305573081.file.myqcloud.com/kt/image_ydt/5eb4d75agw1e291vmniovj.jpg",
+          issue: "将转向灯开关向上提,左转向灯亮。",
+          issuemp3:
+            "https://t1-1305573081.file.myqcloud.com/kt/issue_mp3/issue1389.mp3",
+          liceBus: "1",
+          liceCar: "1",
+          liceMoto: null,
+          liceTruck: "1",
+          number: 831,
+          opts: "√-×",
+          optsArr: ["√", "×"],
+          placeIssue: null,
+          placeIssueName: null,
+          placeSort: null,
+          questionType: 1,
+          sequeIssue: "7",
+          sequeIssueName: "机械仪表",
+          sequeSort: 25,
+          skillkeyword: "没有圆圈-答错",
+          subject: 1,
+          titlekeyword: "",
+          updateTime: "2022-04-22 13:43:07",
+          userAnswer: [],
+        },
+      ],
+      problemListIndex: 0,
+    };
+  },
+  filters: {
+    questionType: function (value) {
+      let question = "";
+      switch (value) {
+        case 1:
+        case "1":
+          question = "判断题";
+          break;
+        case 2:
+        case "2":
+          question = "单选题";
+          break;
+        case 3:
+        case "3":
+          question = "多选题";
+          break;
+      }
+      return question;
+    },
+  },
+  methods: {
+    isRightAnswer(item) {
+      if (
+        typeof item.userAnswer == "object" &&
+        Array.isArray(item.userAnswer)
+      ) {
+        let answerArr = item.answer.split("-");
+        answerArr.sort((a, b) => {
+          return a - b;
+        });
+        item.userAnswer.sort((a, b) => {
+          return a - b;
+        });
+        return answerArr.join("-") === item.userAnswer.join("-");
+      } else if (typeof item.userAnswer == "string") {
+        return item.answer === item.userAnswer;
+      }
+    },
+    submitExam(e) {
+      let score = 0;
+      let query = this.query;
+      this.problemList.forEach((item, index) => {
+        if (
+          typeof item.userAnswer == "object" &&
+          Array.isArray(item.userAnswer)
+        ) {
+          let answerArr = item.answer.split("-");
+          answerArr.sort((a, b) => {
+            return a - b;
+          });
+          item.userAnswer.sort((a, b) => {
+            return a - b;
+          });
+          if (answerArr.join("-") === item.userAnswer.join("-")) {
+            score = score + 1;
+          }
+        } else if (typeof item.userAnswer == "string") {
+          item.answer === item.userAnswer ? (score = score + 1) : "";
+        }
+      });
+      uni.showModal({
+        title: "是否交卷",
+        content: "交卷后不可再修改了",
+        success() {
+          uni.navigateTo({
+            url:
+              "/otherPages/mockExamEnd/index?" +
+              utils.mapToUrlQuery({
+                score,
+                ...query,
+              }),
+          });
+        },
+        fail() {},
+      });
+    },
+    goBeforeTopics() {
+      if (this.problemListIndex <= 0) {
+        uni.showToast({
+          title: "到底了",
+          icon: "none",
+        });
+        return;
+      }
+      this.problemListIndex = this.problemListIndex - 1;
+    },
+    goNextTopics() {
+      if (this.problemListIndex >= this.problemList.length - 1) {
+        uni.showToast({
+          title: "到底了",
+          icon: "none",
+        });
+        return;
+      }
+      this.problemListIndex = this.problemListIndex + 1;
+    },
+    readQuestion(e) {
+      let globalAudio = utils.wxUtils.getGlobAudio();
+      if (globalAudio) {
+        globalAudio.src = e;
+        globalAudio.stop();
+        globalAudio.play();
+      }
+    },
+    changeGroup(e) {
+      this.$set(
+        this.problemList[this.problemListIndex],
+        "userAnswer",
+        e.detail
+      );
+    },
+    changeCheckbox(e) {
+      console.log(e);
+    },
+    numberToLetter(index) {
+      index = Number(index);
+      return String.fromCharCode(index + 65);
+    },
+  },
+  onLoad(query) {
+    let that = this;
+    this.query = query;
+    api.exam
+      .studentQuestionInfoList({
+        ...this.query,
+      })
+      .then((res) => {
+        res.rows.forEach((element) => {
+          element.optsArr = element.opts.split("-");
+          element.isCompleted = true;
+          element.userAnswer = [];
+        });
+        that.problemListTotal = res.total;
+        that.problemList = res.rows;
+      });
+  },
+  computed: {
+    //liceCar=1&liceTruck=&liceBus=&liceMoto=&name=科目一&cert=C1/C2/C3&vehicle=轿车&subject=1&title=顺序练习&sort=3
+    navTitle() {
+      let subjectName = this.query.subject == 1 ? "科目一" : "科目四";
+      return `(${this.query.cert})/${subjectName}/${this.query.title}/${
+        this.query.classIssueName ||
+        this.query.placeIssueName ||
+        this.query.excellIssueName ||
+        this.query.sequeIssueName
+      }`;
+    },
+  },
+
+  components: {
+    navBar,
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.divider {
+  width: 100%;
+  height: 24rpx;
+  background-color: #f2f3f5;
+}
+
+.box {
+  width: 100%;
+  height: 100vh;
+  background: #fff;
+  .look-answer {
+    margin-top: 30rpx;
+    padding: 0 12rpx;
+    background: #f2f3f5;
+    font-size: 36rpx;
+    line-height: 62rpx;
+  }
+  .last-subject {
+    transform: rotate(90deg);
+  }
+  .function-list {
+    width: 100%;
+    font-size: 13px;
+    display: flex;
+    justify-content: space-around;
+    flex-wrap: wrap;
+    padding: 15px;
+    box-sizing: border-box;
+    .function-item {
+      margin-bottom: 20px;
+      width: 30%;
+      display: flex;
+      flex-direction: column;
+      align-items: center;
+      font-size: 13px;
+      font-weight: 400;
+      color: #8a9099;
+      span {
+        margin-top: 5px;
+      }
+    }
+  }
+  .problem-select {
+    display: flex;
+    align-content: center;
+    align-items: center;
+    margin-top: 15rpx;
+    padding-left: 30rpx;
+  }
+  .problem-box {
+    padding: 15rpx;
+    background: #fff;
+    /deep/ .van-checkbox {
+      padding-bottom: 15rpx;
+    }
+    /deep/ .van-radio {
+      padding-bottom: 15rpx;
+    }
+    .problem-type {
+      padding-left: 10rpx;
+      padding-right: 10rpx;
+      padding-top: 4rpx;
+      padding-bottom: 4rpx;
+      font-size: 24rpx;
+      border-radius: 16rpx 16rpx 0 16rpx;
+      background: #498ef5;
+      margin-right: 10rpx;
+    }
+    .problem-ops {
+      margin-top: 30rpx;
+      padding-left: 30rpx;
+      .problem-checkbox {
+        height: 100rpx;
+      }
+    }
+    .problem-op {
+      width: 75rpx;
+      height: 75rpx;
+      line-height: 75rpx;
+      border-radius: 50%;
+      text-align: center;
+      overflow: hidden;
+      background: #fff;
+      box-shadow: 0px 4rpx 12rpx rgba(0, 0, 0, 0.16);
+    }
+    .problem-opAnswer {
+      font-size: 40rpx;
+      margin-left: 12rpx;
+    }
+    .problem-op_selected {
+      background: #498ef5;
+    }
+    .problem-img {
+      width: 100%;
+      margin-top: 20rpx;
+      image {
+        margin: 0 auto;
+      }
+    }
+  }
+}
+</style>

+ 82 - 0
src/otherPages/mockExam/components/navBar.vue

@@ -0,0 +1,82 @@
+<template>
+  <div
+    :style="{
+      height: (menuButton.height+8) + 'px',
+    }"
+    class="header"
+  >
+
+    <div class="header-title">
+      <text> {{title}}</text>
+    </div>
+  </div>
+</template>
+
+<script>
+
+export default {
+  data() {
+    return {
+      menuButton: {
+        bottom: 0,
+        height: 0,
+        left: 0,
+        right: 0,
+        top: 0,
+        width: 0,
+      },
+    };
+  },
+  props: {
+      title: {
+          type: String,
+          default:''
+      },
+      size:{
+          type:String,
+          default:'16px'
+      }
+  },
+  mounted() {
+    this.menuButton = uni.getMenuButtonBoundingClientRect();
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.header {
+  width: 100%;
+  overflow: hidden;
+  display: flex;
+  align-content: center;
+  align-items: center;
+  position: relative;
+  background: #fff;
+  .header-title {
+    width: 100%;
+    height: 100%;
+    text-align: center;
+    justify-content: center;
+    vertical-align: baseline;
+    display: flex;
+    align-content: center;
+    align-items: center;
+    text {
+      vertical-align: text-top;
+    }
+  }
+  .header-left {
+    position: absolute;
+    left: 0;
+    padding-left: 24rpx;
+    height: 100%;
+    display: flex;
+    align-content: center;
+    align-items: center;
+    .arrow-left {
+      color: #1989fa;
+      vertical-align: middle;
+    }
+  }
+}
+</style>

+ 450 - 0
src/otherPages/mockExam/index.vue

@@ -0,0 +1,450 @@
+<template>
+  <view class="box">
+    <nav-bar :title="navTitle"> </nav-bar>
+    <view style="text-align: center">
+      <van-count-down :time="time"></van-count-down>
+    </view>
+    <view class="divider"></view>
+    <view class="problem-box">
+      <span class="problem-type">{{
+        problemList[problemListIndex].questionType | questionType
+      }}</span>
+      <!-- <text>{{ problemListIndex + 1 }}、</text> -->
+      <text class="">{{ problemList[problemListIndex].issue }}</text>
+      <view v-if="problemList[problemListIndex].image" class="problem-img">
+        <image
+          mode="widthFix"
+          :src="problemList[problemListIndex].image"
+        ></image>
+      </view>
+      <!-- 单项选择 -->
+      <view
+        v-if="
+          problemList[problemListIndex].questionType < 3
+        "
+        class="problem-ops"
+      >
+        <van-radio-group
+          :value="problemList[problemListIndex].userAnswer"
+          :max="1"
+          @change="changeGroup"
+        >
+          <van-radio
+            @change="changeCheckbox"
+            :value="
+              problemList[problemListIndex].userAnswer.includes(
+                problemList[problemListIndex].answer
+              )
+            "
+            class="problem-checkbox"
+            use-icon-slot
+            v-for="(item, index) in problemList[problemListIndex].optsArr"
+            :key="index"
+            :name="item"
+          >
+            <text>{{ item }}</text>
+            <view
+              class="problem-op"
+              :class="{
+                'problem-op_selected':
+                  problemList[problemListIndex].userAnswer.includes(item),
+              }"
+              slot="icon"
+              >{{ numberToLetter(index) }}</view
+            >
+          </van-radio>
+        </van-radio-group>
+      </view>
+
+      <!-- 多项选择 -->
+      <view
+        v-if="
+          problemList[problemListIndex].questionType == 3
+        "
+        class="problem-ops"
+      >
+        <van-checkbox-group
+          :value="problemList[problemListIndex].userAnswer"
+          :max="4"
+          @change="changeGroup"
+        >
+          <van-checkbox
+            @change="changeCheckbox"
+            :value="
+              problemList[problemListIndex].userAnswer.includes(
+                problemList[problemListIndex].answer
+              )
+            "
+            class="problem-checkbox"
+            use-icon-slot
+            v-for="(item, index) in problemList[problemListIndex].optsArr"
+            :key="index"
+            :name="item"
+          >
+            <text>{{ item }}</text>
+            <view
+              class="problem-op"
+              :class="{
+                'problem-op_selected':
+                  problemList[problemListIndex].userAnswer.includes(item),
+              }"
+              slot="icon"
+              >{{ numberToLetter(index) }}</view
+            >
+          </van-checkbox>
+        </van-checkbox-group>
+      </view>
+      <view class="function-list">
+        <div class="function-item">
+          <van-icon name="star-o" size="25px" />
+          <span>收藏</span>
+        </div>
+        <!-- <div class="function-item" @click="answerAudioPlay">
+      <m-icon type="a-dtda" size="25px" />
+      <span>读题+答案</span>
+    </div> -->
+        <div
+          @click="readQuestion(problemList[problemListIndex].issuemp3)"
+          class="function-item"
+        >
+          <van-icon name="bullhorn-o" size="25px" />
+          <span>读题</span>
+        </div>
+        <!-- <div class="function-item" @click="currentAnswerIndexBack">
+      <m-icon type="shangyiti" size="25px" />
+      <span>上一题</span>
+    </div>
+    <div class="function-item" @click="skillsShow = true">
+      <m-icon type="zongtishu" size="25px" />
+      <span>1/100</span>
+    </div>
+    <div class="function-item" @click="currentAnswerIndexGo">
+      <m-icon type="xiayiti" size="25px" />
+      <span>下一题</span>
+    </div> -->
+      </view>
+    </view>
+
+    <van-tabbar>
+      <van-tabbar-item @click="goBeforeTopics"
+        ><van-icon
+          slot="icon"
+          custom-style="transform: rotate(90deg);"
+          custom-class="last-subject"
+          name="down"
+          size="18px"
+        />上一题
+      </van-tabbar-item>
+      <van-tabbar-item
+        ><van-icon slot="icon" size="18px" name="description" />{{
+          problemListIndex + 1
+        }}/{{ problemListTotal }}
+      </van-tabbar-item>
+      <van-tabbar-item @click="submitExam"
+        ><van-icon slot="icon" size="18px" name="records" />交卷
+      </van-tabbar-item>
+      <van-tabbar-item @click="goNextTopics"
+        ><van-icon
+          slot="icon"
+          custom-style="transform: rotate(-90deg);"
+          custom-class="last-subject"
+          name="down"
+          size="18px"
+        />下一题
+      </van-tabbar-item>
+    </van-tabbar>
+  </view>
+</template>
+
+<script>
+import navBar from "./components/navBar.vue";
+import api from "@/api/index";
+import utils from "@/utils/index";
+export default {
+  data() {
+    return {
+      query: {
+        cert: "",
+        vehicle: "",
+        subject: "",
+        title: "",
+      },
+      time: 45 * 60 * 1000,
+      problemListTotal: 1,
+      problemList: [
+        {
+          answer: "×",
+          answerkeyword: "",
+          answermp3:
+            "https://t1-1305573081.file.myqcloud.com/kt/answer_mp3/answer1389.mp3",
+          classIssue: "54",
+          classIssueName: "车内开关/装置",
+          classSort: 16,
+          createTime: "2022-04-21 13:33:46",
+          excellIssue: "23",
+          excellIssueName: "必学题三",
+          excellSort: 4,
+          explainGif:
+            "https://t1-1305573081.file.myqcloud.com/kt/explain_gif/explain1389.gif",
+          explainJq:
+            "看图答题:红色圆圈套在杆子中间.答对;不在中间或没有圆圈的.答错。",
+          explainJs:
+            "图中所示为左右转向灯开关转向灯操作:上提是右转向灯亮起,下压是左转向灯。",
+          explainMp3:
+            "https://t1-1305573081.file.myqcloud.com/kt/explain_mp3/explain1389.mp3",
+          explainjsmp3:
+            "https://t1-1305573081.file.myqcloud.com/kt/explain_js_mp3/explainJS1389.mp3",
+          id: 831,
+          idKt: 1389,
+          idYdt: 950,
+          image:
+            "https://t1-1305573081.file.myqcloud.com/kt/image/image1389.png",
+          imageYdt:
+            "https://t1-1305573081.file.myqcloud.com/kt/image_ydt/5eb4d75agw1e291vmniovj.jpg",
+          issue: "将转向灯开关向上提,左转向灯亮。",
+          issuemp3:
+            "https://t1-1305573081.file.myqcloud.com/kt/issue_mp3/issue1389.mp3",
+          liceBus: "1",
+          liceCar: "1",
+          liceMoto: null,
+          liceTruck: "1",
+          number: 831,
+          opts: "√-×",
+          optsArr: ["√", "×"],
+          placeIssue: null,
+          placeIssueName: null,
+          placeSort: null,
+          questionType: 1,
+          sequeIssue: "7",
+          sequeIssueName: "机械仪表",
+          sequeSort: 25,
+          skillkeyword: "没有圆圈-答错",
+          subject: 1,
+          titlekeyword: "",
+          updateTime: "2022-04-22 13:43:07",
+          userAnswer: [],
+        },
+      ],
+      problemListIndex: 0,
+    };
+  },
+  filters: {
+    questionType: function (value) {
+      let question = "";
+      switch (value) {
+        case 1:
+        case "1":
+          question = "判断题";
+          break;
+        case 2:
+        case "2":
+          question = "单选题";
+          break;
+        case 3:
+        case "3":
+          question = "多选题";
+          break;
+      }
+      return question;
+    },
+  },
+  methods: {
+    submitExam(e) {
+      let score = 0;
+      let query = this.query;
+      this.problemList.forEach((item, index) => {
+        if (
+          typeof item.userAnswer == "object" &&
+          Array.isArray(item.userAnswer)
+        ) {
+          let answerArr = item.answer.split("-");
+          answerArr.sort((a, b) => {
+            return a - b;
+          });
+          item.userAnswer.sort((a, b) => {
+            return a - b;
+          });
+          if (answerArr.join("-") === item.userAnswer.join("-")) {
+            score = score + 1;
+          }
+        } else if (typeof item.userAnswer == "string") {
+          item.answer === item.userAnswer ? (score = score + 1) : "";
+        }
+      });
+      uni.showModal({
+        title: "是否交卷",
+        content: "交卷后不可再修改了",
+        success(res) {
+          if (res.confirm) {
+            uni.navigateTo({
+              url:
+                "/otherPages/mockExamEnd/index?" +
+                utils.mapToUrlQuery({
+                  score,
+                  ...query,
+                }),
+            });
+          }
+        },
+        fail() {},
+      });
+    },
+    goBeforeTopics() {
+      if (this.problemListIndex <= 0) {
+        uni.showToast({
+          title: "到底了",
+          icon: "none",
+        });
+        return;
+      }
+      this.problemListIndex = this.problemListIndex - 1;
+    },
+    goNextTopics() {
+      if (this.problemListIndex >= this.problemList.length - 1) {
+        uni.showToast({
+          title: "到底了",
+          icon: "none",
+        });
+        return;
+      }
+      this.problemListIndex = this.problemListIndex + 1;
+    },
+    readQuestion(e) {
+      let globalAudio = utils.wxUtils.getGlobAudio();
+      if (globalAudio) {
+        globalAudio.src = e;
+        globalAudio.stop();
+        globalAudio.play();
+      }
+    },
+    changeGroup(e) {
+      this.$set(
+        this.problemList[this.problemListIndex],
+        "userAnswer",
+        e.detail
+      );
+    },
+    changeCheckbox(e) {
+      console.log(e);
+    },
+    numberToLetter(index) {
+      index = Number(index);
+      return String.fromCharCode(index + 65);
+    },
+  },
+  onLoad(query) {
+    let that = this;
+    this.query = query;
+    api.exam
+      .studentQuestionInfoSelectTestQuestionInfo({
+        ...this.query,
+      })
+      .then((res) => {
+        res.rows.forEach((element) => {
+          element.optsArr = element.opts.split("-");
+
+          element.userAnswer = [];
+        });
+        that.problemListTotal = res.total;
+        that.problemList = res.rows;
+      });
+  },
+  computed: {
+    //liceCar=1&liceTruck=&liceBus=&liceMoto=&name=科目一&cert=C1/C2/C3&vehicle=轿车&subject=1&title=顺序练习&sort=3
+    navTitle() {
+      let subjectName = this.query.subject == 1 ? "科目一" : "科目四";
+      return `(${this.query.cert})/${subjectName}/${this.query.title}`;
+    },
+  },
+
+  components: {
+    navBar,
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.divider {
+  width: 100%;
+  height: 24rpx;
+  background-color: #f2f3f5;
+}
+
+.box {
+  width: 100%;
+  height: 100vh;
+  background: #fff;
+  .last-subject {
+    transform: rotate(90deg);
+  }
+  .function-list {
+    width: 100%;
+    font-size: 13px;
+    display: flex;
+    justify-content: space-around;
+    flex-wrap: wrap;
+    padding: 15px;
+    box-sizing: border-box;
+    .function-item {
+      margin-bottom: 20px;
+      width: 30%;
+      display: flex;
+      flex-direction: column;
+      align-items: center;
+      font-size: 13px;
+      font-weight: 400;
+      color: #8a9099;
+      span {
+        margin-top: 5px;
+      }
+    }
+  }
+  .problem-box {
+    padding: 15rpx;
+    background: #fff;
+    /deep/ .van-checkbox {
+      padding-bottom: 15rpx;
+    }
+    /deep/ .van-radio {
+      padding-bottom: 15rpx;
+    }
+    .problem-type {
+      padding-left: 10rpx;
+      padding-right: 10rpx;
+      padding-top: 4rpx;
+      padding-bottom: 4rpx;
+      font-size: 24rpx;
+      border-radius: 16rpx 16rpx 0 16rpx;
+      background: #498ef5;
+      margin-right: 10rpx;
+    }
+    .problem-ops {
+      margin-top: 30rpx;
+      padding-left: 30rpx;
+      .problem-checkbox {
+        height: 100rpx;
+      }
+    }
+    .problem-op {
+      width: 75rpx;
+      height: 75rpx;
+      line-height: 75rpx;
+      border-radius: 50%;
+      text-align: center;
+      overflow: hidden;
+      background: #fff;
+      box-shadow: 0px 4rpx 12rpx rgba(0, 0, 0, 0.16);
+    }
+    .problem-op_selected {
+      background: #498ef5;
+    }
+    .problem-img {
+      width: 100%;
+      margin-top: 20rpx;
+      image {
+        margin: 0 auto;
+      }
+    }
+  }
+}
+</style>

+ 131 - 0
src/otherPages/mockExamEnd/index.vue

@@ -0,0 +1,131 @@
+<template>
+  <view>
+    <div class="result-box" v-if="score>=90">
+      <img class="img" src="./考试合格.png" />
+      <span class="text">恭喜你,测试通过~</span>
+      <div class="fraction-box">
+        <span class="fraction">{{ score }}</span
+        >分
+      </div>
+      <span class="hint">(满分:100;合格:90)</span>
+      <span class="time">用时:{{ useTime }}</span>
+      <span class="evaluation"
+        >天赋异禀、骨骼惊奇,想来是百年难得一见的考试奇才。</span
+      >
+    </div>
+    <div class="result-box" v-else>
+      <img class="img" src="./考试不合格.png" />
+      <span class="text">抱歉,测试未通过~</span>
+      <div class="fraction-box">
+        <span class="fraction">{{ score }}</span
+        >分
+      </div>
+      <span class="hint">(满分:100;合格:90)</span>
+      <span class="time">用时:{{ useTime }}</span>
+      <span class="evaluation"
+        >学车之路,任重而道远!路漫漫其修远兮,吾将上下而求索。</span
+      >
+    </div>
+    <div class="btn-box">
+      <m-button width="180rpx" height="60rpx" @click="goWrongPreview" class="btn1" text="错题重做" />
+      <m-button width="180rpx" height="60rpx" @click="againTest" class="btn2" text="重新测试" />
+    </div>
+  </view>
+</template>
+
+<script>
+export default {
+    data() {
+        return {
+            score: 0,
+            useTime:""
+
+        }
+    },
+    onLoad(op){
+      this.score = op.score
+      this.useTime = op.useTime
+    }
+}
+//提交考试成绩
+// createTestScores({
+// 	type: query.vehicle as string,
+// 	kskm: query.name as string,
+// 	score: props.userTestData.testScores,
+// });
+</script>
+
+<style lang="scss" scoped>
+.result-box {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  padding: 60rpx 30rpx;
+  .img {
+    width: 246px;
+    height: 216px;
+  }
+  .text {
+    margin-top: 23px;
+    font-size: 15px;
+    font-family: PingFang SC;
+    font-weight: 400;
+    color: #5c6066;
+    line-height: 23px;
+  }
+  .fraction-box {
+    font-size: 15px;
+    font-family: PingFang SC;
+    font-weight: bold;
+    color: #8a9099;
+    line-height: 23px;
+    margin-top: 30px;
+    .fraction {
+      font-size: 60px;
+      font-family: PingFang SC;
+      font-weight: bold;
+      color: #ff4d53;
+    }
+  }
+  .hint {
+    font-size: 13px;
+    font-family: PingFang SC;
+    font-weight: 400;
+    color: #8a9099;
+    line-height: 23px;
+  }
+  .time {
+    font-size: 13px;
+    font-family: PingFang SC;
+    font-weight: 400;
+    color: #498ef5;
+    line-height: 23px;
+  }
+  .evaluation {
+    margin-top: 30px;
+    font-size: 15px;
+    font-family: PingFang SC;
+    font-weight: 400;
+    color: #5c6066;
+    line-height: 23px;
+  }
+}
+.btn-box {
+  margin: 45px auto;
+  width: 230px;
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  color: #ffffff;
+  font-size: 15px;
+  font-family: PingFang SC;
+  font-weight: 400;
+  line-height: 23px;
+  .btn1 {
+    background-color: #498ef5;
+  }
+  .btn2 {
+    background-color: #01c18d;
+  }
+}
+</style>

BIN
src/otherPages/mockExamEnd/考试不合格.png


BIN
src/otherPages/mockExamEnd/考试合格.png


+ 71 - 8
src/pages.json

@@ -212,27 +212,46 @@
         },
         {
           "path": "classifyOrder/index",
-          "styles": {}
+          "style": {
+            "navigationBarTitleText": "顺序练习",
+            "enablePullDownRefresh": false
+          }
         },
         {
           "path": "classifyKind/index",
-          "styles": {}
+          "style": {
+            "navigationBarTitleText": "分类练习",
+            "enablePullDownRefresh": false
+          }
         },
         {
           "path": "classifyArea/index",
-          "styles": {}
+          "style": {
+            "navigationBarTitleText": "区域练习",
+            "enablePullDownRefresh": false
+          }
         },
         {
           "path": "classifyChoose/index",
-          "styles": {}
+          "styles": {
+            "navigationBarTitleText": "精选练习",
+            "enablePullDownRefresh": false
+          }
         },
         {
           "path": "testScores/index",
-          "styles": {}
+          "style": {
+            "navigationBarTitleText": "模拟考试分数",
+            "enablePullDownRefresh": false
+
+          }
         },
         {
           "path":"beforeMockExam/index",
-          "styles": {}
+          "styles": {
+            "navigationBarTitleText": "模拟考试",
+            "enablePullDownRefresh": false
+          }
         },
         {
           "path":"collection/index",
@@ -240,10 +259,37 @@
         },
         {
           "path": "buyVip/index",
-          "styles": {
+          "style": {
             "navigationBarTitleText": "购买vip",
             "enablePullDownRefresh": false
           }
+        },
+        {
+          "path":"mockExam/index",
+          "style": {
+            "navigationBarTitleText": "模拟考试",
+            "enablePullDownRefresh": false
+        
+          }
+
+        },
+        {
+          "path":"mockExamEnd/index",
+          "style": {
+            "navigationBarTitleText": "模拟考试结果",
+            "enablePullDownRefresh": false
+        
+          }
+
+        },
+        {
+          "path":"exercise/index",
+          "style": {
+            "navigationBarTitleText": "练习",
+            "enablePullDownRefresh": false
+        
+          }
+
         }
       ]
     }
@@ -319,7 +365,8 @@
       "van-sidebar": "wxcomponents/vant/sidebar/index",
       "van-sidebar-item": "wxcomponents/vant/sidebar-item/index",
       "van-grid": "wxcomponents/vant/grid/index",
-      "van-grid-item": "wxcomponents/vant/grid-item/index"
+      "van-grid-item": "wxcomponents/vant/grid-item/index",
+      "van-nav-bar":"wxcomponents/vant/nav-bar/index"
     }
   },
   "condition": {
@@ -347,7 +394,23 @@
       {
         "name": "购买vip",
         "path": "otherPages/buyVip/index"
+      },
+      {
+        "name": "模拟考试仿真题目",
+        "path": "otherPages/mockExam/index",
+        "query":"liceCar=1&liceTruck=&liceBus=&liceMoto=&name=科目一&cert=C1/C2/C3&vehicle=轿车&subject=1&title=模拟考试&sort=3"
+      },
+      {
+        "name": "模拟考试结果",
+        "path": "otherPages/mockExamEnd/index",
+        "query":"liceCar=1&liceTruck=&liceBus=&liceMoto=&name=科目一&cert=C1/C2/C3&vehicle=轿车&subject=1&title=模拟考试&sort=3"
+      },
+      {
+        "name": "练习",
+        "path": "otherPages/exercise/index",
+        "query":"liceCar=1&liceTruck=&liceBus=&liceMoto=&name=科目一&cert=C1/C2/C3&vehicle=轿车&subject=1&title=顺序练习&sort=3&sequeIssueName=练习一"
       }
+      
     ]
   }
 }

+ 1 - 0
src/pages/carVideo/components/tabCenter.vue

@@ -11,6 +11,7 @@
 import utils from "@/utils/index";
 export default {
   data() {
+    //exercise
     return {};
   },
   methods: {