JXDS18FUJT 1 年之前
父节点
当前提交
e7fd9ffd43

+ 163 - 3
src/components/m-do-topic/m-do-topic.vue

@@ -67,6 +67,17 @@
         <view v-if="midFunc.includes('collect')" @click="collectTopics" :class="!problemList[problemListIndex].isCollect
       ? 'funcicon-item'
       : 'funcicon-item funcicon-item_select'
+      ">
+          <van-icon style="margin-right: 8rpx" v-if="!problemList[problemListIndex].isCollect" name="star-o"
+            size="10px" />
+          <van-icon style="margin-right: 8rpx" color="#ffde00ff" v-if="problemList[problemListIndex].isCollect"
+            name="star" size="10px" />
+          <span>收藏</span>
+        </view>
+
+        <view v-if="midFunc.includes('threeCollect')" @click="threeCollectTopics" :class="!problemList[problemListIndex].isCollect
+      ? 'funcicon-item'
+      : 'funcicon-item funcicon-item_select'
       ">
           <van-icon style="margin-right: 8rpx" v-if="!problemList[problemListIndex].isCollect" name="star-o"
             size="10px" />
@@ -277,6 +288,12 @@
           <van-icon color="#ffde00ff" v-if="problemList[problemListIndex].isCollect" name="star" size="25px" />
           <span>收藏</span>
         </div>
+
+        <div v-if="midFunc.includes('threeCollect')" @click="threeCollectTopics" class="function-item">
+          <van-icon v-if="!problemList[problemListIndex].isCollect" name="star-o" size="25px" />
+          <van-icon color="#ffde00ff" v-if="problemList[problemListIndex].isCollect" name="star" size="25px" />
+          <span>收藏</span>
+        </div>
         <div v-if="midFunc.includes('readQuestionAndAnswer')" @click="
       readQuestionAndAnswer();
     completeQuestion();
@@ -355,7 +372,7 @@
               size="18px" /><text style="font-size: 24rpx">下一题</text>
           </view>
         </view>
-        <view v-if="type == 'exam' || 'singleTest'" class="submit">
+        <view v-if="type == 'exam' || type == 'singleTest'" class="submit">
           <view @click="submitExam" class="submit-button">交卷</view>
         </view>
       </view>
@@ -772,6 +789,54 @@ export default {
         fail() { },
       });
     },
+    threeCollectTopics(e) {
+      let storageName =
+        uni.getStorageSync("userInfo").xcxOpenid +
+        "_userThreeIds_" +
+        9;
+      let userThreeIds = uni.getStorageSync(storageName) || [];
+
+      if (!this.problemList[this.problemListIndex].isCollect) {
+        if (
+          !userThreeIds.some((item) => {
+            return item.id === this.problemList[this.problemListIndex].id;
+          })
+        ) {
+          userThreeIds.push({
+            id: this.problemList[this.problemListIndex].id,
+            timestamp: +new Date(),
+          });
+          uni.setStorageSync(storageName, userThreeIds);
+        }
+        this.$set(this.problemList[this.problemListIndex], "isCollect", true);
+        uni.showToast({
+          title: "收藏成功",
+        });
+      } else {
+        if (
+          userThreeIds.some((item) => {
+            return item.id === this.problemList[this.problemListIndex].id;
+          })
+        ) {
+
+          userThreeIds.splice(
+            userThreeIds.findIndex((item) => {
+              return item.id == this.problemList[this.problemListIndex].id
+
+            }),
+            1
+          );
+          uni.setStorageSync(storageName, userThreeIds);
+        }
+
+        this.$set(this.problemList[this.problemListIndex], "isCollect", false);
+        uni.showToast({
+          title: "取消收藏",
+          icon: "fail",
+        });
+      }
+
+    },
     collectTopics(e) {
       let storageName =
         uni.getStorageSync("userInfo").xcxOpenid +
@@ -804,7 +869,7 @@ export default {
 
           userCollectionIds.splice(
             userCollectionIds.findIndex(item => {
-              return item.id ===  this.problemList[this.problemListIndex].id
+              return item.id === this.problemList[this.problemListIndex].id
 
 
             }),
@@ -1351,6 +1416,41 @@ export default {
             uni.hideLoading();
           });
 
+        break;
+      case "color":
+        api.exam.studentQuestionSeList().then((res) => {
+          if (Array.isArray(res.rows) && res.rows.length > 0) {
+
+            res.rows.forEach((element) => {
+              element.optsArr = [];
+              element.opts.split("-").forEach((item, index) => {
+                if (element.questionType == 3) {
+                  element.optsArr.push({
+                    selected: false,
+                    value: item,
+                    index: index,
+                    isAnswer: element.answer.split("-").includes(item),
+                  });
+                } else {
+                  element.optsArr.push({
+                    selected: false,
+                    value: item,
+                    index: index,
+                    isAnswer: item === element.answer,
+                  });
+                }
+              });
+              element.isCompleted = false;
+              element.isCollect = false;
+              element.userAnswer = [];
+            });
+            that.problemListTotal = res.total;
+            that.problemList = res.rows;
+          }
+          uni.hideLoading();
+        })
+
+
         break;
       case "collect":
         storageName =
@@ -1415,6 +1515,65 @@ export default {
             uni.hideLoading();
           });
 
+        break;
+      case "three":
+        api.exam.studentQuestion2InfoList({
+          subject: 9
+        }).then((res) => {
+          if (Array.isArray(res.rows) && res.rows.length > 0) {
+            res.rows.forEach((element) => {
+              element.optsArr = [];
+              element.opts.split("-").forEach((item, index) => {
+                if (element.questionType == 3) {
+                  element.optsArr.push({
+                    selected: false,
+                    value: item,
+                    index: index,
+                    isAnswer: element.answer.split("-").includes(item),
+                  });
+                } else {
+                  element.optsArr.push({
+                    selected: false,
+                    value: item,
+                    index: index,
+                    isAnswer: item === element.answer,
+                  });
+                }
+              });
+              element.isCompleted = false;
+              element.isCollect = false;
+              element.userAnswer = [];
+            });
+            this.problemList = res.rows;
+            let key = `${uni.getStorageSync("userInfo").xcxOpenid}_threeExam_${this.query.subject}`
+            if (uni.getStorageSync(key)) {
+              uni.showModal({
+                title: "回到上次的题目",
+                content: `你上次做到第${uni.getStorageSync(key) + 1
+                  }题,是否前往`,
+                success: (res) => {
+                  if (res.confirm) {
+                    this.problemListIndex = Number(uni.getStorageSync(key))
+                    // this.$emit(
+                    //   "update:problemListIndex",
+                    //   uni.getStorageSync(key)
+                    // );
+                  } else {
+                    uni.setStorageSync(key, 0);
+                  }
+                },
+              });
+            }
+          } else {
+            uni.showToast({
+              icon: "error",
+              title: "加载失败",
+            });
+          }
+          uni.hideLoading();
+        });
+
+
         break;
       case "mi":
         api.exam
@@ -1457,7 +1616,7 @@ export default {
           });
 
         break;
-      case "three":
+      case "threeCollect":
         storageName =
           uni.getStorageSync("userInfo").xcxOpenid +
           "_userThreeIds_" +
@@ -1515,6 +1674,7 @@ export default {
               });
               element.isCompleted = false;
               element.userAnswer = [];
+              element.isCollect = true;
             });
             that.problemListTotal = res.total;
             that.problemList = res.rows;

+ 1 - 1
src/otherPages/beforeColorExam/index.vue

@@ -61,7 +61,7 @@
                 </navigator>
 
 
-                <navigator url="/otherPages/colorExam/index?showSubmit=0">
+                <navigator url="/otherPages/exerciseColor/index">
                     <view class="mid1-submit-continue">
                         <view style="width: 300rpx;">
                             <view class="mid1-submit-continue-line1">

+ 1 - 1
src/otherPages/beforeThreeExam/index.vue

@@ -59,7 +59,7 @@
           </view>
         </view>
 
-        <navigator url="/otherPages/threeExam/index?showSubmit=0">
+        <navigator url="/otherPages/exerciseThree/index?subject=9">
           <view class="mid1-submit-continue">
             <view style="width: 300rpx;">
               <view class="mid1-submit-continue-line1">

+ 1 - 1
src/otherPages/collection/index.vue

@@ -711,7 +711,7 @@ export default {
         // }).join(','):'';
         uni.navigateTo({
           url:
-            "/otherPages/exerciseThree/index?" + utils.mapToUrlQuery({...query,subject:9}),
+            "/otherPages/exercisethreeCollect/index?" + utils.mapToUrlQuery({...query,subject:9}),
         });
       }
     },

+ 21 - 1
src/otherPages/colorExam/index.vue

@@ -206,6 +206,13 @@
           />
           <view>收藏</view>
       </view> -->
+      <view style="display: flex;align-items: center;align-content: center;">
+
+        <view @click="readQuestion()" class="problem-read">
+          <m-jp-icon type="duti" size="25px" />
+          <span>读题</span>
+        </view>
+      </view>
 
     </view>
     <view class="bottom">
@@ -273,7 +280,7 @@
           <view @click="() => {
 
         submitExamVisible = false;
-        goPath('/otherPages/colorExamScore/index?trueNum=' + trueNum+'&falseNum='+falseNum)
+        goPath('/otherPages/colorExamScore/index?trueNum=' + trueNum + '&falseNum=' + falseNum)
       }
         " class="right">现在交卷</view>
         </view>
@@ -487,6 +494,14 @@ export default {
     }
   },
   methods: {
+    readQuestion() {
+      let globalAudio = utils.wxUtils.getGlobAudio();
+      if (globalAudio) {
+        globalAudio.src = this.problemList[this.problemListIndex].issuemp3;
+        globalAudio.stop();
+        globalAudio.play();
+      }
+    },
     collectTopics() {
       let storageName =
         uni.getStorageSync("userInfo").xcxOpenid +
@@ -849,6 +864,11 @@ export default {
     text-align: center;
     padding-top: 15rpx;
   }
+  .problem-read{
+    width: 100rpx;
+    text-align: center;
+    padding-top: 15rpx;
+  }
 }
 
 .bottom {

+ 23 - 0
src/otherPages/exerciseColor/components/checkbox.vue

@@ -0,0 +1,23 @@
+<template>
+  <view>
+    <slot v-if="useIconSlot" name="icon" />
+    <icon  v-else></icon>
+  </view>
+</template>
+
+<script>
+export default {
+  data() {
+    return {};
+  },
+  props: {
+    useIconSlot: {
+      type: Boolean,
+      default: false,
+    },
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+</style>

+ 160 - 0
src/otherPages/exerciseColor/components/explainJs.vue

@@ -0,0 +1,160 @@
+<template>
+  <van-overlay z-index="10" :show="show">
+    <div class="skills-box">
+      <div class="skills">
+        <div class="title">官方解释</div>
+        <div class="text">{{ explainJs }}</div>
+        <div class="btn">
+          <span
+            @click="
+              () => {
+                $emit('close');
+              }
+            "
+          >
+            关闭
+          </span>
+          <span
+            @click="
+              () => {
+                playExplainjsmp3();
+              }
+            "
+          >
+            语音重播
+          </span>
+        </div>
+      </div>
+    </div>
+  </van-overlay>
+</template>
+
+<script>
+import utils from "@/utils/index";
+export default {
+  data() {
+    return {};
+  },
+  methods: {
+    playExplainjsmp3() {
+      let audio = utils.wxUtils.getGlobAudio();
+      audio.stop();
+      audio.src = this.explainjsmp3;
+      audio.onCanplay(() => {
+        console.log("onCanplay");
+      });
+      audio.onPlay(() => {
+        console.log("onPlay");
+      });
+      audio.onError((res) => {
+        console.log(res);
+      });
+      //体验比较好
+      setTimeout(() => {
+        audio.play();
+      }, 1000);
+    },
+  },
+  watch: {
+    show(newValue, oldValue) {
+      let audio = utils.wxUtils.getGlobAudio();
+      if (newValue) {
+        audio.src = this.explainjsmp3;
+        audio.play();
+      } else {
+        audio.stop();
+      }
+    },
+  },
+  props: {
+    show: {
+      type: Boolean,
+      default: false,
+    },
+    explainJs: {
+      type: String,
+      default: "",
+    },
+    explainjsmp3: {
+      type: String,
+      default: "",
+    },
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.skills-box {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  height: 100%;
+  .skills {
+    width: 290px;
+    background: #ffffff;
+    box-shadow: 0px 0px 8px rgba(124, 129, 136, 0.16);
+    border-radius: 10px;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    padding: 20px 16px;
+    box-sizing: border-box;
+    .title {
+      font-size: 15px;
+      font-family: PingFang SC;
+      font-weight: bold;
+      line-height: 21px;
+      color: #0a1a33;
+    }
+    .img {
+      width: 258px;
+      height: 129px;
+      border: 1px solid #e8e8e8;
+      margin-top: 16px;
+    }
+    .divider {
+      margin-top: 20px;
+      color: #0a1a33;
+      background: #ffffff;
+    }
+    .text {
+      font-size: 13px;
+      font-family: PingFang SC;
+      font-weight: 400;
+      line-height: 19px;
+      color: #5c6066;
+      margin-top: 10px;
+    }
+    .btn {
+      width: 100%;
+      display: flex;
+      justify-content: space-between;
+      padding: 0 40px;
+      box-sizing: border-box;
+      margin-top: 20px;
+      span {
+        width: 76px;
+        height: 30px;
+        border-radius: 15px;
+        font-size: 13px;
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        &:active {
+          background-color: #afaaaa;
+          filter: brightness(50%);
+        }
+        &:nth-of-type(1) {
+          border: 1px solid #707070;
+          color: #5c6066;
+        }
+        &:nth-of-type(2) {
+          background: #498ef5;
+          border: 1px solid #498ef5;
+          color: #ffffff;
+        }
+      }
+    }
+  }
+}
+</style>

+ 82 - 0
src/otherPages/exerciseColor/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>

+ 45 - 0
src/otherPages/exerciseColor/components/tabbar.vue

@@ -0,0 +1,45 @@
+<template>
+  <view
+    class="box"
+    :style="{
+      height: height,
+      lineHeight:height
+    }"
+  >
+    <slot></slot>
+  </view>
+</template>
+
+<script>
+export default {
+  data() {
+    return {};
+  },
+  methods: {
+    name() {},
+  },
+  props: {
+    height: {
+      type: String,
+      default: "0rpx",
+    },
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.box{
+    width: 100%;
+    display:flex;
+    justify-content: space-between;
+    overflow: scroll;
+    position: fixed;
+    bottom: 0;
+    font-size: 14px;
+    background: #fff;
+
+
+}
+
+
+</style>

+ 682 - 0
src/otherPages/exerciseColor/index.vue

@@ -0,0 +1,682 @@
+<template>
+    <view @touchstart="touchStart" @touchend="touchEnd" class="box">
+      <nav-bar :title="navTitle"> </nav-bar>
+      <!-- <view style="text-align:center;">
+        <van-count-down :time="time"></van-count-down>
+      </view> -->
+      <m-do-topic
+        v-if="isGetQuery"
+        hiddenMode
+        type="color"
+        :bottomFunc="['previous', 'next', 'score', 'explain', 'skill']"
+        :midFunc="['readQuestion','readQuestionAndAnswer']"
+        :trueNum.sync="trueNum"
+        :falseNum.sync="falseNum"
+        :query="query"
+        :problemListTotal.sync="problemListTotal"
+        :problemListIndex.sync="problemListIndex"
+      ></m-do-topic>
+  
+      <explainJs
+        @close="
+          () => {
+            explainJsVisible = false;
+          }
+        "
+        :explainJs="problemList[problemListIndex].explainJs"
+        :explainjsmp3="problemList[problemListIndex].explainjsmp3"
+        :show="explainJsVisible"
+      ></explainJs>
+      <!-- #ifdef MP-WEIXIN -->
+      <!-- <van-tabbar height="20px">
+        <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>
+          <icon slot="icon" class="icon-box-img" type="success" size="18px"></icon
+          >{{ trueNum }}</van-tabbar-item
+        >
+        <van-tabbar-item
+          ><icon
+            slot="icon"
+            class="icon-box-img"
+            type="cancel"
+            size="18px"
+          ></icon>
+          {{ falseNum }}
+        </van-tabbar-item>
+        <van-tabbar-item
+          ><van-icon slot="icon" size="18px" name="description" />{{
+            problemListIndex + 1
+          }}/{{ problemListTotal }}
+        </van-tabbar-item>
+        <van-tabbar-item
+          @click="
+            () => {
+              explainJsVisible = true;
+            }
+          "
+          ><icon slot="icon" type="warn" size="18px" />解释
+        </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> -->
+      <!-- #endif -->
+      <!-- #ifdef MP-TOUTIAO -->
+      <tabbar height="35px">
+        <view @click="goBeforeTopics" class="flex-all-center h-full">
+          <van-icon
+            slot="icon"
+            custom-style="transform: rotate(90deg);"
+            custom-class="last-subject"
+            name="down"
+            size="18px"
+          /><text> 上一题 </text>
+        </view>
+        <view class="flex-all-center h-full">
+          <icon
+            class="icon-box-img"
+            color="#06c05f"
+            type="success"
+            size="18px"
+          ></icon
+          ><text style="margin-left: 5rpx">{{ trueNum }}</text>
+        </view>
+        <view class="flex-all-center h-full">
+          <icon class="icon-box-img" type="clear" size="18px"></icon>
+          <text style="margin-left: 5rpx">{{ falseNum }}</text>
+        </view>
+        <view class="flex-all-center h-full">
+          <van-icon size="18px" name="description" />{{ problemListIndex + 1 }}/{{
+            problemListTotal
+          }}
+        </view>
+  
+        <view
+          @click="
+            () => {
+              explainJsVisible = true;
+            }
+          "
+          class="flex-all-center h-full"
+        >
+          <icon type="warn" size="18px" /><text style="margin-left: 5rpx"
+            >解释</text
+          >
+        </view>
+  
+        <view @click="goNextTopics" class="flex-all-center h-full">
+          下一题
+          <van-icon
+            custom-style="transform: rotate(-90deg);"
+            custom-class="last-subject"
+            name="down"
+            size="18px"
+          />
+        </view>
+      </tabbar>
+      <!-- #endif -->
+    </view>
+  </template>
+  <script>
+  import navBar from "./components/navBar.vue";
+  import api from "@/api/index";
+  import utils from "@/utils/index";
+  import explainJs from "./components/explainJs.vue";
+  import tabbar from "./components/tabbar.vue";
+  import mDoTopic from "@/components/m-do-topic/m-do-topic.vue";
+  export default {
+    data() {
+      return {
+        query: {
+          cert: "",
+          vehicle: "",
+          subject: "",
+          title: "",
+        },
+        gsMap: {
+          xc: "小车",
+          hc: "货车",
+          mtc: "摩托车",
+          kc: "客车",
+        },
+        trueNum: 0,
+        falseNum: 0,
+        currentOptions: [
+          {
+            selected: false,
+            value: "",
+            isAnswer: false,
+          },
+          {},
+        ],
+        isGetQuery: false,
+        explainJsVisible: false,
+        time: 45 * 60 * 1000,
+        problemListTotal: 1,
+        touchx: 0,
+        touchy: 0,
+        problemList: [
+          {
+            questionType: 2,
+            answer: "×",
+            answerkeyword: "",
+            answermp3:
+              "https://ndata.zzxcx.net/kt/answer_mp3/answer1389.mp3",
+            classIssue: "54",
+            classIssueName: "车内开关/装置",
+            classSort: 16,
+            createTime: "2022-04-21 13:33:46",
+            excellIssue: "23",
+            excellIssueName: "必学题三",
+            excellSort: 4,
+            explainGif:
+              "https://ndata.zzxcx.net/kt/explain_gif/explain1389.gif",
+            explainJq:
+              "看图答题:红色圆圈套在杆子中间.答对;不在中间或没有圆圈的.答错。",
+            explainJs:
+              "图中所示为左右转向灯开关转向灯操作:上提是右转向灯亮起,下压是左转向灯。",
+            explainMp3:
+              "https://ndata.zzxcx.net/kt/explain_mp3/explain1389.mp3",
+            explainjsmp3:
+              "https://ndata.zzxcx.net/kt/explain_js_mp3/explainJS1389.mp3",
+            id: 831,
+            idKt: 1389,
+            idYdt: 950,
+            image:
+              "https://ndata.zzxcx.net/kt/image/image1389.png",
+            imageYdt:
+              "https://ndata.zzxcx.net/kt/image_ydt/5eb4d75agw1e291vmniovj.jpg",
+            issue: "将转向灯开关向上提,左转向灯亮。",
+            issuemp3:
+              "https://ndata.zzxcx.net/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: {
+      touchStart(e) {
+        var that = this;
+        (this.touchx = e.changedTouches[0].clientX),
+          (this.touchy = e.changedTouches[0].clientY);
+      },
+      touchEnd(e) {
+        console.log(e);
+        var that = this;
+        let x = e.changedTouches[0].clientX;
+        let y = e.changedTouches[0].clientY;
+        let turn = "";
+        if (x - that.touchx > 50 && Math.abs(y - that.touchy) < 50) {
+          //右滑
+          turn = "right";
+          this.problemListIndex <= 0
+            ? uni.showToast({
+                title: "到底了",
+                icon: "none",
+              })
+            : this.problemListIndex--;
+        } else if (x - that.touchx < -50 && Math.abs(y - that.touchy) < 50) {
+          //左滑
+          turn = "left";
+          this.problemListIndex >= this.problemListTotal - 1
+            ? uni.showToast({
+                title: "到底了",
+                icon: "none",
+              })
+            : this.problemListIndex++;
+        }
+        if (y - that.touchy > 50 && Math.abs(x - that.touchx) < 50) {
+          //下滑
+          turn = "down";
+        } else if (y - that.touchy < -50 && Math.abs(x - that.touchx) < 50) {
+          //上滑
+          turn = "up";
+        }
+        //根据方向进行操作
+        if (turn == "down") {
+          //下滑触发操作
+        }
+        console.log(turn);
+      },
+      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.problemListTotal - 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();
+        }
+      },
+      confirmMult(e) {
+        this.$set(this.problemList[this.problemListIndex], "isCompleted", true);
+        if (
+          JSON.stringify(
+            this.problemList[this.problemListIndex].answer.split("-").sort()
+          ) ===
+          JSON.stringify(
+            this.problemList[this.problemListIndex].userAnswer.sort()
+          )
+        ) {
+          this.trueNum++;
+        } else {
+          this.falseNum++;
+          api.exam.studentQuestionWrong({
+            questionId: this.problemList[this.problemListIndex].id,
+            carType: this.gsMap[this.query.gs],
+            km: this.query.subject === "4" ? "科目四" : "科目一",
+          });
+        }
+        // this.problemList[this.problemListIndex]
+      },
+      changeCheckboxGroup(e) {
+        //console.log(e);
+        // this.$set()
+        // #ifdef MP-WEIXIN
+        this.$set(
+          this.problemList[this.problemListIndex],
+          "userAnswer",
+          e.detail
+        );
+        this.problemList[this.problemListIndex].optsArr.forEach((item) => {
+          if (e.detail.includes(item.value)) {
+            item.selected = true;
+          } else {
+            item.selected = false;
+          }
+        });
+        //#endif
+        // #ifdef MP-TOUTIAO
+        this.$set(
+          this.problemList[this.problemListIndex],
+          "userAnswer",
+          e.detail
+        );
+        this.problemList[this.problemListIndex].optsArr.forEach((item, index) => {
+          if (e.detail.includes(item.value)) {
+            item.selected = true;
+            this.$set(
+              this.problemList[this.problemListIndex].optsArr[index],
+              "selected",
+              true
+            );
+          } else {
+            item.selected = false;
+            this.$set(
+              this.problemList[this.problemListIndex].optsArr[index],
+              "selected",
+              false
+            );
+          }
+        });
+        //#endif
+        if (
+          this.problemList[this.problemListIndex].answer
+            .split("-")
+            .sort()
+            .toString() ===
+          this.problemList[this.problemListIndex].userAnswer.sort().toString()
+        ) {
+          this.trueNum = this.trueNum + 1;
+        } else {
+          this.falseNum = this.falseNum + 1;
+        }
+      },
+      changeRadioGroup(e) {
+        console.log(e, "changeRadioGroup");
+        // #ifdef MP-WEIXIN
+        this.$set(this.problemList[this.problemListIndex], "isCompleted", true);
+        this.$set(
+          this.problemList[this.problemListIndex],
+          "userAnswer",
+          e.detail.value
+        );
+        e.detail.selected = true;
+        this.$set(
+          this.problemList[this.problemListIndex].optsArr,
+          e.detail.index,
+          e.detail
+        );
+        e.detail.value === this.problemList[this.problemListIndex].answer
+          ? (this.trueNum = this.trueNum + 1)
+          : (this.falseNum = this.falseNum + 1);
+        //#endif
+  
+        // #ifdef MP-TOUTIAO
+        this.$set(this.problemList[this.problemListIndex], "isCompleted", true);
+        this.$set(
+          this.problemList[this.problemListIndex],
+          "userAnswer",
+          e.detail
+        );
+        this.problemList[this.problemListIndex].optsArr.forEach((item, index) => {
+          if (e.detail === item.value) {
+            item.selected = true;
+            this.$set(
+              this.problemList[this.problemListIndex].optsArr[index],
+              "selected",
+              true
+            );
+          } else {
+            item.selected = false;
+            this.$set(
+              this.problemList[this.problemListIndex].optsArr[index],
+              "selected",
+              false
+            );
+          }
+        });
+        if (e.detail.value === this.problemList[this.problemListIndex].answer) {
+          this.trueNum = this.trueNum + 1;
+        } else {
+          this.falseNum = this.falseNum + 1;
+          api.exam.studentQuestionWrong({
+            questionId: this.problemList[this.problemListIndex].id,
+            carType: this.gsMap[this.query.gs],
+            km: this.query.subject === "4" ? "科目四" : "科目一",
+          });
+        }
+  
+        //#endif
+      },
+      changeCheckbox(e) {
+        //specify
+        // console.log(e);
+      },
+      numberToLetter(index) {
+        index = Number(index);
+        return String.fromCharCode(index + 65);
+      },
+    },
+    onLoad(query) {
+      let that = this;
+      this.query = query;
+      // 获取到参数再进行渲染
+      this.isGetQuery = true;
+    },
+    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 `色盲测试/全部题目`;
+      },
+    },
+    watch: {
+      problemListIndex: {
+        handler(newValue, oldValue) {},
+        immediate: true,
+      },
+    },
+  
+    components: {
+      mDoTopic,
+      navBar,
+      explainJs,
+      tabbar,
+    },
+  };
+  </script>
+  
+  <style lang="scss" scoped>
+  .divider {
+    width: 100%;
+    height: 24rpx;
+    background-color: #f2f3f5;
+  }
+  .h-full {
+    height: 100%;
+  }
+  .flex-all-center {
+    display: flex;
+    justify-content: center;
+    align-content: center;
+    align-items: center;
+  }
+  .flex-center {
+    display: flex;
+    justify-content: center;
+    width: 100%;
+  }
+  .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;
+      }
+    }
+  }
+  .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);
+    }
+  
+    .problem-select {
+      display: flex;
+      align-content: center;
+      align-items: center;
+      margin-top: 15rpx;
+      padding-left: 30rpx;
+    }
+    .problem-box {
+      padding: 15rpx;
+      padding-bottom: 70rpx;
+      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;
+        color: #fff;
+        font-size: 32rpx;
+      }
+      .problem-issue {
+        font-size: 42rpx;
+        font-weight: 600;
+      }
+      .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_green {
+        width: 75rpx;
+        height: 75rpx;
+        line-height: 75rpx;
+        border-radius: 50%;
+        text-align: center;
+        overflow: hidden;
+        background: #01c18d;
+  
+        box-shadow: 0px 4rpx 12rpx rgba(0, 0, 0, 0.16);
+      }
+      .problem-opAnswer {
+        font-size: 16px;
+        margin-left: 12rpx;
+      }
+      .problem-op_selected {
+        background: #498ef5;
+      }
+      .problem-img {
+        width: 100%;
+        margin-top: 20rpx;
+        display: flex;
+        justify-content: center;
+        image {
+          margin: 0 auto;
+        }
+      }
+    }
+  }
+  </style>

+ 2 - 2
src/otherPages/exerciseThree/index.vue

@@ -9,7 +9,7 @@
       hiddenMode
       type="three"
       :bottomFunc="['previous', 'next', 'score', 'explain', 'skill']"
-      :midFunc="[]"
+      :midFunc="['threeCollect', 'readQuestion','readQuestionAndAnswer']"
       :trueNum.sync="trueNum"
       :falseNum.sync="falseNum"
       :query="query"
@@ -524,7 +524,7 @@ export default {
     //liceCar=1&liceTruck=&liceBus=&liceMoto=&name=科目一&cert=C1/C2/C3&vehicle=轿车&subject=1&title=顺序练习&sort=3
     navTitle() {
       let subjectName = this.query.subject == 1 ? "科目一" : "科目四";
-      return `三力测试/收藏`;
+      return `三力测试/全部题目`;
     },
   },
   watch: {

+ 23 - 0
src/otherPages/exercisethreeCollect/components/checkbox.vue

@@ -0,0 +1,23 @@
+<template>
+  <view>
+    <slot v-if="useIconSlot" name="icon" />
+    <icon  v-else></icon>
+  </view>
+</template>
+
+<script>
+export default {
+  data() {
+    return {};
+  },
+  props: {
+    useIconSlot: {
+      type: Boolean,
+      default: false,
+    },
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+</style>

+ 160 - 0
src/otherPages/exercisethreeCollect/components/explainJs.vue

@@ -0,0 +1,160 @@
+<template>
+  <van-overlay z-index="10" :show="show">
+    <div class="skills-box">
+      <div class="skills">
+        <div class="title">官方解释</div>
+        <div class="text">{{ explainJs }}</div>
+        <div class="btn">
+          <span
+            @click="
+              () => {
+                $emit('close');
+              }
+            "
+          >
+            关闭
+          </span>
+          <span
+            @click="
+              () => {
+                playExplainjsmp3();
+              }
+            "
+          >
+            语音重播
+          </span>
+        </div>
+      </div>
+    </div>
+  </van-overlay>
+</template>
+
+<script>
+import utils from "@/utils/index";
+export default {
+  data() {
+    return {};
+  },
+  methods: {
+    playExplainjsmp3() {
+      let audio = utils.wxUtils.getGlobAudio();
+      audio.stop();
+      audio.src = this.explainjsmp3;
+      audio.onCanplay(() => {
+        console.log("onCanplay");
+      });
+      audio.onPlay(() => {
+        console.log("onPlay");
+      });
+      audio.onError((res) => {
+        console.log(res);
+      });
+      //体验比较好
+      setTimeout(() => {
+        audio.play();
+      }, 1000);
+    },
+  },
+  watch: {
+    show(newValue, oldValue) {
+      let audio = utils.wxUtils.getGlobAudio();
+      if (newValue) {
+        audio.src = this.explainjsmp3;
+        audio.play();
+      } else {
+        audio.stop();
+      }
+    },
+  },
+  props: {
+    show: {
+      type: Boolean,
+      default: false,
+    },
+    explainJs: {
+      type: String,
+      default: "",
+    },
+    explainjsmp3: {
+      type: String,
+      default: "",
+    },
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.skills-box {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  height: 100%;
+  .skills {
+    width: 290px;
+    background: #ffffff;
+    box-shadow: 0px 0px 8px rgba(124, 129, 136, 0.16);
+    border-radius: 10px;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    padding: 20px 16px;
+    box-sizing: border-box;
+    .title {
+      font-size: 15px;
+      font-family: PingFang SC;
+      font-weight: bold;
+      line-height: 21px;
+      color: #0a1a33;
+    }
+    .img {
+      width: 258px;
+      height: 129px;
+      border: 1px solid #e8e8e8;
+      margin-top: 16px;
+    }
+    .divider {
+      margin-top: 20px;
+      color: #0a1a33;
+      background: #ffffff;
+    }
+    .text {
+      font-size: 13px;
+      font-family: PingFang SC;
+      font-weight: 400;
+      line-height: 19px;
+      color: #5c6066;
+      margin-top: 10px;
+    }
+    .btn {
+      width: 100%;
+      display: flex;
+      justify-content: space-between;
+      padding: 0 40px;
+      box-sizing: border-box;
+      margin-top: 20px;
+      span {
+        width: 76px;
+        height: 30px;
+        border-radius: 15px;
+        font-size: 13px;
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        &:active {
+          background-color: #afaaaa;
+          filter: brightness(50%);
+        }
+        &:nth-of-type(1) {
+          border: 1px solid #707070;
+          color: #5c6066;
+        }
+        &:nth-of-type(2) {
+          background: #498ef5;
+          border: 1px solid #498ef5;
+          color: #ffffff;
+        }
+      }
+    }
+  }
+}
+</style>

+ 82 - 0
src/otherPages/exercisethreeCollect/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>

+ 45 - 0
src/otherPages/exercisethreeCollect/components/tabbar.vue

@@ -0,0 +1,45 @@
+<template>
+  <view
+    class="box"
+    :style="{
+      height: height,
+      lineHeight:height
+    }"
+  >
+    <slot></slot>
+  </view>
+</template>
+
+<script>
+export default {
+  data() {
+    return {};
+  },
+  methods: {
+    name() {},
+  },
+  props: {
+    height: {
+      type: String,
+      default: "0rpx",
+    },
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.box{
+    width: 100%;
+    display:flex;
+    justify-content: space-between;
+    overflow: scroll;
+    position: fixed;
+    bottom: 0;
+    font-size: 14px;
+    background: #fff;
+
+
+}
+
+
+</style>

+ 682 - 0
src/otherPages/exercisethreeCollect/index.vue

@@ -0,0 +1,682 @@
+<template>
+    <view @touchstart="touchStart" @touchend="touchEnd" class="box">
+      <nav-bar :title="navTitle"> </nav-bar>
+      <!-- <view style="text-align:center;">
+        <van-count-down :time="time"></van-count-down>
+      </view> -->
+      <m-do-topic
+        v-if="isGetQuery"
+        hiddenMode
+        type="threeCollect"
+        :bottomFunc="['previous', 'next', 'score', 'explain', 'skill']"
+        :midFunc="[]"
+        :trueNum.sync="trueNum"
+        :falseNum.sync="falseNum"
+        :query="query"
+        :problemListTotal.sync="problemListTotal"
+        :problemListIndex.sync="problemListIndex"
+      ></m-do-topic>
+  
+      <explainJs
+        @close="
+          () => {
+            explainJsVisible = false;
+          }
+        "
+        :explainJs="problemList[problemListIndex].explainJs"
+        :explainjsmp3="problemList[problemListIndex].explainjsmp3"
+        :show="explainJsVisible"
+      ></explainJs>
+      <!-- #ifdef MP-WEIXIN -->
+      <!-- <van-tabbar height="20px">
+        <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>
+          <icon slot="icon" class="icon-box-img" type="success" size="18px"></icon
+          >{{ trueNum }}</van-tabbar-item
+        >
+        <van-tabbar-item
+          ><icon
+            slot="icon"
+            class="icon-box-img"
+            type="cancel"
+            size="18px"
+          ></icon>
+          {{ falseNum }}
+        </van-tabbar-item>
+        <van-tabbar-item
+          ><van-icon slot="icon" size="18px" name="description" />{{
+            problemListIndex + 1
+          }}/{{ problemListTotal }}
+        </van-tabbar-item>
+        <van-tabbar-item
+          @click="
+            () => {
+              explainJsVisible = true;
+            }
+          "
+          ><icon slot="icon" type="warn" size="18px" />解释
+        </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> -->
+      <!-- #endif -->
+      <!-- #ifdef MP-TOUTIAO -->
+      <tabbar height="35px">
+        <view @click="goBeforeTopics" class="flex-all-center h-full">
+          <van-icon
+            slot="icon"
+            custom-style="transform: rotate(90deg);"
+            custom-class="last-subject"
+            name="down"
+            size="18px"
+          /><text> 上一题 </text>
+        </view>
+        <view class="flex-all-center h-full">
+          <icon
+            class="icon-box-img"
+            color="#06c05f"
+            type="success"
+            size="18px"
+          ></icon
+          ><text style="margin-left: 5rpx">{{ trueNum }}</text>
+        </view>
+        <view class="flex-all-center h-full">
+          <icon class="icon-box-img" type="clear" size="18px"></icon>
+          <text style="margin-left: 5rpx">{{ falseNum }}</text>
+        </view>
+        <view class="flex-all-center h-full">
+          <van-icon size="18px" name="description" />{{ problemListIndex + 1 }}/{{
+            problemListTotal
+          }}
+        </view>
+  
+        <view
+          @click="
+            () => {
+              explainJsVisible = true;
+            }
+          "
+          class="flex-all-center h-full"
+        >
+          <icon type="warn" size="18px" /><text style="margin-left: 5rpx"
+            >解释</text
+          >
+        </view>
+  
+        <view @click="goNextTopics" class="flex-all-center h-full">
+          下一题
+          <van-icon
+            custom-style="transform: rotate(-90deg);"
+            custom-class="last-subject"
+            name="down"
+            size="18px"
+          />
+        </view>
+      </tabbar>
+      <!-- #endif -->
+    </view>
+  </template>
+  <script>
+  import navBar from "./components/navBar.vue";
+  import api from "@/api/index";
+  import utils from "@/utils/index";
+  import explainJs from "./components/explainJs.vue";
+  import tabbar from "./components/tabbar.vue";
+  import mDoTopic from "@/components/m-do-topic/m-do-topic.vue";
+  export default {
+    data() {
+      return {
+        query: {
+          cert: "",
+          vehicle: "",
+          subject: "",
+          title: "",
+        },
+        gsMap: {
+          xc: "小车",
+          hc: "货车",
+          mtc: "摩托车",
+          kc: "客车",
+        },
+        trueNum: 0,
+        falseNum: 0,
+        currentOptions: [
+          {
+            selected: false,
+            value: "",
+            isAnswer: false,
+          },
+          {},
+        ],
+        isGetQuery: false,
+        explainJsVisible: false,
+        time: 45 * 60 * 1000,
+        problemListTotal: 1,
+        touchx: 0,
+        touchy: 0,
+        problemList: [
+          {
+            questionType: 2,
+            answer: "×",
+            answerkeyword: "",
+            answermp3:
+              "https://ndata.zzxcx.net/kt/answer_mp3/answer1389.mp3",
+            classIssue: "54",
+            classIssueName: "车内开关/装置",
+            classSort: 16,
+            createTime: "2022-04-21 13:33:46",
+            excellIssue: "23",
+            excellIssueName: "必学题三",
+            excellSort: 4,
+            explainGif:
+              "https://ndata.zzxcx.net/kt/explain_gif/explain1389.gif",
+            explainJq:
+              "看图答题:红色圆圈套在杆子中间.答对;不在中间或没有圆圈的.答错。",
+            explainJs:
+              "图中所示为左右转向灯开关转向灯操作:上提是右转向灯亮起,下压是左转向灯。",
+            explainMp3:
+              "https://ndata.zzxcx.net/kt/explain_mp3/explain1389.mp3",
+            explainjsmp3:
+              "https://ndata.zzxcx.net/kt/explain_js_mp3/explainJS1389.mp3",
+            id: 831,
+            idKt: 1389,
+            idYdt: 950,
+            image:
+              "https://ndata.zzxcx.net/kt/image/image1389.png",
+            imageYdt:
+              "https://ndata.zzxcx.net/kt/image_ydt/5eb4d75agw1e291vmniovj.jpg",
+            issue: "将转向灯开关向上提,左转向灯亮。",
+            issuemp3:
+              "https://ndata.zzxcx.net/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: {
+      touchStart(e) {
+        var that = this;
+        (this.touchx = e.changedTouches[0].clientX),
+          (this.touchy = e.changedTouches[0].clientY);
+      },
+      touchEnd(e) {
+        console.log(e);
+        var that = this;
+        let x = e.changedTouches[0].clientX;
+        let y = e.changedTouches[0].clientY;
+        let turn = "";
+        if (x - that.touchx > 50 && Math.abs(y - that.touchy) < 50) {
+          //右滑
+          turn = "right";
+          this.problemListIndex <= 0
+            ? uni.showToast({
+                title: "到底了",
+                icon: "none",
+              })
+            : this.problemListIndex--;
+        } else if (x - that.touchx < -50 && Math.abs(y - that.touchy) < 50) {
+          //左滑
+          turn = "left";
+          this.problemListIndex >= this.problemListTotal - 1
+            ? uni.showToast({
+                title: "到底了",
+                icon: "none",
+              })
+            : this.problemListIndex++;
+        }
+        if (y - that.touchy > 50 && Math.abs(x - that.touchx) < 50) {
+          //下滑
+          turn = "down";
+        } else if (y - that.touchy < -50 && Math.abs(x - that.touchx) < 50) {
+          //上滑
+          turn = "up";
+        }
+        //根据方向进行操作
+        if (turn == "down") {
+          //下滑触发操作
+        }
+        console.log(turn);
+      },
+      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.problemListTotal - 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();
+        }
+      },
+      confirmMult(e) {
+        this.$set(this.problemList[this.problemListIndex], "isCompleted", true);
+        if (
+          JSON.stringify(
+            this.problemList[this.problemListIndex].answer.split("-").sort()
+          ) ===
+          JSON.stringify(
+            this.problemList[this.problemListIndex].userAnswer.sort()
+          )
+        ) {
+          this.trueNum++;
+        } else {
+          this.falseNum++;
+          api.exam.studentQuestionWrong({
+            questionId: this.problemList[this.problemListIndex].id,
+            carType: this.gsMap[this.query.gs],
+            km: this.query.subject === "4" ? "科目四" : "科目一",
+          });
+        }
+        // this.problemList[this.problemListIndex]
+      },
+      changeCheckboxGroup(e) {
+        //console.log(e);
+        // this.$set()
+        // #ifdef MP-WEIXIN
+        this.$set(
+          this.problemList[this.problemListIndex],
+          "userAnswer",
+          e.detail
+        );
+        this.problemList[this.problemListIndex].optsArr.forEach((item) => {
+          if (e.detail.includes(item.value)) {
+            item.selected = true;
+          } else {
+            item.selected = false;
+          }
+        });
+        //#endif
+        // #ifdef MP-TOUTIAO
+        this.$set(
+          this.problemList[this.problemListIndex],
+          "userAnswer",
+          e.detail
+        );
+        this.problemList[this.problemListIndex].optsArr.forEach((item, index) => {
+          if (e.detail.includes(item.value)) {
+            item.selected = true;
+            this.$set(
+              this.problemList[this.problemListIndex].optsArr[index],
+              "selected",
+              true
+            );
+          } else {
+            item.selected = false;
+            this.$set(
+              this.problemList[this.problemListIndex].optsArr[index],
+              "selected",
+              false
+            );
+          }
+        });
+        //#endif
+        if (
+          this.problemList[this.problemListIndex].answer
+            .split("-")
+            .sort()
+            .toString() ===
+          this.problemList[this.problemListIndex].userAnswer.sort().toString()
+        ) {
+          this.trueNum = this.trueNum + 1;
+        } else {
+          this.falseNum = this.falseNum + 1;
+        }
+      },
+      changeRadioGroup(e) {
+        console.log(e, "changeRadioGroup");
+        // #ifdef MP-WEIXIN
+        this.$set(this.problemList[this.problemListIndex], "isCompleted", true);
+        this.$set(
+          this.problemList[this.problemListIndex],
+          "userAnswer",
+          e.detail.value
+        );
+        e.detail.selected = true;
+        this.$set(
+          this.problemList[this.problemListIndex].optsArr,
+          e.detail.index,
+          e.detail
+        );
+        e.detail.value === this.problemList[this.problemListIndex].answer
+          ? (this.trueNum = this.trueNum + 1)
+          : (this.falseNum = this.falseNum + 1);
+        //#endif
+  
+        // #ifdef MP-TOUTIAO
+        this.$set(this.problemList[this.problemListIndex], "isCompleted", true);
+        this.$set(
+          this.problemList[this.problemListIndex],
+          "userAnswer",
+          e.detail
+        );
+        this.problemList[this.problemListIndex].optsArr.forEach((item, index) => {
+          if (e.detail === item.value) {
+            item.selected = true;
+            this.$set(
+              this.problemList[this.problemListIndex].optsArr[index],
+              "selected",
+              true
+            );
+          } else {
+            item.selected = false;
+            this.$set(
+              this.problemList[this.problemListIndex].optsArr[index],
+              "selected",
+              false
+            );
+          }
+        });
+        if (e.detail.value === this.problemList[this.problemListIndex].answer) {
+          this.trueNum = this.trueNum + 1;
+        } else {
+          this.falseNum = this.falseNum + 1;
+          api.exam.studentQuestionWrong({
+            questionId: this.problemList[this.problemListIndex].id,
+            carType: this.gsMap[this.query.gs],
+            km: this.query.subject === "4" ? "科目四" : "科目一",
+          });
+        }
+  
+        //#endif
+      },
+      changeCheckbox(e) {
+        //specify
+        // console.log(e);
+      },
+      numberToLetter(index) {
+        index = Number(index);
+        return String.fromCharCode(index + 65);
+      },
+    },
+    onLoad(query) {
+      let that = this;
+      this.query = query;
+      // 获取到参数再进行渲染
+      this.isGetQuery = true;
+    },
+    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 `三力测试/收藏`;
+      },
+    },
+    watch: {
+      problemListIndex: {
+        handler(newValue, oldValue) {},
+        immediate: true,
+      },
+    },
+  
+    components: {
+      mDoTopic,
+      navBar,
+      explainJs,
+      tabbar,
+    },
+  };
+  </script>
+  
+  <style lang="scss" scoped>
+  .divider {
+    width: 100%;
+    height: 24rpx;
+    background-color: #f2f3f5;
+  }
+  .h-full {
+    height: 100%;
+  }
+  .flex-all-center {
+    display: flex;
+    justify-content: center;
+    align-content: center;
+    align-items: center;
+  }
+  .flex-center {
+    display: flex;
+    justify-content: center;
+    width: 100%;
+  }
+  .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;
+      }
+    }
+  }
+  .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);
+    }
+  
+    .problem-select {
+      display: flex;
+      align-content: center;
+      align-items: center;
+      margin-top: 15rpx;
+      padding-left: 30rpx;
+    }
+    .problem-box {
+      padding: 15rpx;
+      padding-bottom: 70rpx;
+      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;
+        color: #fff;
+        font-size: 32rpx;
+      }
+      .problem-issue {
+        font-size: 42rpx;
+        font-weight: 600;
+      }
+      .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_green {
+        width: 75rpx;
+        height: 75rpx;
+        line-height: 75rpx;
+        border-radius: 50%;
+        text-align: center;
+        overflow: hidden;
+        background: #01c18d;
+  
+        box-shadow: 0px 4rpx 12rpx rgba(0, 0, 0, 0.16);
+      }
+      .problem-opAnswer {
+        font-size: 16px;
+        margin-left: 12rpx;
+      }
+      .problem-op_selected {
+        background: #498ef5;
+      }
+      .problem-img {
+        width: 100%;
+        margin-top: 20rpx;
+        display: flex;
+        justify-content: center;
+        image {
+          margin: 0 auto;
+        }
+      }
+    }
+  }
+  </style>

+ 49 - 37
src/otherPages/threeExam/index.vue

@@ -165,8 +165,7 @@
         <van-radio-group v-if="problemList[problemListIndex].isComplete"
           :value="problemList[problemListIndex].userAnswer">
           <view :key="index" v-for="(item, index) in problemList[problemListIndex].optsArr">
-            <van-radio  label-class="pl0" custom-class="mt40"
-              use-icon-slot :name="item">
+            <van-radio label-class="pl0" custom-class="mt40" use-icon-slot :name="item">
               <view class="problem-radio-flex">
                 <view class="problem-radio-icon">
                   <icon type="clear" v-if="item ==
@@ -193,21 +192,20 @@
           </view>
         </van-radio-group>
       </view>
-      <view  v-if="query.showSubmit == '0'" @click="collectTopics" class="problem-collect">
-        <van-icon
-            v-if="!problemList[problemListIndex].isCollect"
-            name="star-o"
-            size="25px"
-          />
-          <van-icon
-            color="#ffde00ff"
-            v-if="problemList[problemListIndex].isCollect"
-            name="star"
-            size="25px"
-          />
+      <view style="display: flex;align-items: center;align-content: center;">
+        <view v-if="query.showSubmit == '0'" @click="collectTopics" class="problem-collect">
+          <van-icon v-if="!problemList[problemListIndex].isCollect" name="star-o" size="25px" />
+          <van-icon color="#ffde00ff" v-if="problemList[problemListIndex].isCollect" name="star" size="25px" />
           <view>收藏</view>
+        </view>
+
+        <view @click="readQuestion()" class="problem-read">
+          <m-jp-icon type="duti" size="25px" />
+          <span>读题</span>
+        </view>
       </view>
 
+
     </view>
     <view class="bottom">
       <view class="switch">
@@ -430,7 +428,7 @@ export default {
     this.query = query;
     if (this.query.showSubmit == "1") {
       api.exam.studentThreeForceSelectTestQuestionInfoNewList({
-       
+
       }).then((res) => {
         if (Array.isArray(res.rows) && res.rows.length > 0) {
           res.rows.forEach((element) => {
@@ -464,24 +462,23 @@ export default {
           this.problemList = res.rows;
           let key = `${uni.getStorageSync("userInfo").xcxOpenid}_threeExam_${this.query.subject}`
           if (uni.getStorageSync(key)) {
-              uni.showModal({
-                title: "回到上次的题目",
-                content: `你上次做到第${
-                  uni.getStorageSync(key) + 1
+            uni.showModal({
+              title: "回到上次的题目",
+              content: `你上次做到第${uni.getStorageSync(key) + 1
                 }题,是否前往`,
-                success: (res) => {
-                  if (res.confirm) {
-                    this.problemListIndex =Number(uni.getStorageSync(key)) 
-                    // this.$emit(
-                    //   "update:problemListIndex",
-                    //   uni.getStorageSync(key)
-                    // );
-                  } else {
-                    uni.setStorageSync(key, 0);
-                  }
-                },
-              });
-            }
+              success: (res) => {
+                if (res.confirm) {
+                  this.problemListIndex = Number(uni.getStorageSync(key))
+                  // this.$emit(
+                  //   "update:problemListIndex",
+                  //   uni.getStorageSync(key)
+                  // );
+                } else {
+                  uni.setStorageSync(key, 0);
+                }
+              },
+            });
+          }
         } else {
           uni.showToast({
             icon: "error",
@@ -492,7 +489,15 @@ export default {
     }
   },
   methods: {
-    collectTopics(){
+    readQuestion() {
+      let globalAudio = utils.wxUtils.getGlobAudio();
+      if (globalAudio) {
+        globalAudio.src = this.problemList[this.problemListIndex].issuemp3;
+        globalAudio.stop();
+        globalAudio.play();
+      }
+    },
+    collectTopics() {
       let storageName =
         uni.getStorageSync("userInfo").xcxOpenid +
         "_userThreeIds_" +
@@ -521,9 +526,9 @@ export default {
             return item.id === this.problemList[this.problemListIndex].id;
           })
         ) {
-      
+
           userThreeIds.splice(
-            userThreeIds.findIndex((item)=>{
+            userThreeIds.findIndex((item) => {
               return item.id == this.problemList[this.problemListIndex].id
 
             }),
@@ -607,7 +612,7 @@ export default {
       this.problemList[this.problemListIndex].userAnswer = e.detail
       this.problemList[this.problemListIndex].isComplete = true;
       this.problemList[this.problemListIndex].userAnswer == this.problemList[this.problemListIndex].answer ? this.trueNum++ : this.falseNum++;
-      uni.setStorageSync(key,this.problemListIndex)
+      uni.setStorageSync(key, this.problemListIndex)
       // this.problemList[this.problemListIndex].userAnswerIndex ==
       //   this.problemList[this.problemListIndex].answertrue
       //   ? this.trueNum++
@@ -850,11 +855,18 @@ export default {
       width: 100%;
     }
   }
-  .problem-collect{
+
+  .problem-collect {
     width: 100rpx;
     text-align: center;
     padding-top: 15rpx;
   }
+
+  .problem-read {
+    width: 100rpx;
+    text-align: center;
+    padding-top: 20rpx;
+  }
 }
 
 .bottom {

+ 8 - 0
src/pages.json

@@ -337,10 +337,18 @@
           "path": "exerciseSpecify/index",
           "style": {}
         },
+        {
+          "path": "exerciseColor/index",
+          "style": {}
+        },
         {
           "path": "exerciseThree/index",
           "style": {}
         },
+        {
+          "path": "exercisethreeCollect/index",
+          "style": {}
+        },
         {
           "path": "exerciseMi/index",
           "style": {}