Forráskód Böngészése

修复有时候组件无法获取题目的bug

zhangyujun 3 éve
szülő
commit
98e5100cca
50 módosított fájl, 5768 hozzáadás és 385 törlés
  1. 38 9
      src/api/modules/exam.js
  2. 19 3
      src/api/modules/open.js
  3. 2 2
      src/api/request.js
  4. 0 0
      src/assets/img/buhege.png
  5. 0 0
      src/assets/img/hege.png
  6. 682 103
      src/components/m-do-topic/m-do-topic.vue
  7. 99 0
      src/otherPages/classifyFree/index.vue
  8. 1 0
      src/otherPages/classifyKind/index.vue
  9. 16 2
      src/otherPages/classifyOrder/index.vue
  10. 50 44
      src/otherPages/collection/index.vue
  11. 30 30
      src/otherPages/exercise/index.vue
  12. 0 0
      src/otherPages/exerciseCollect/components/checkbox.vue
  13. 0 0
      src/otherPages/exerciseCollect/components/explainJs.vue
  14. 0 0
      src/otherPages/exerciseCollect/components/navBar.vue
  15. 0 0
      src/otherPages/exerciseCollect/components/tabbar.vue
  16. 681 0
      src/otherPages/exerciseCollect/index.vue
  17. 23 0
      src/otherPages/exerciseExam/components/checkbox.vue
  18. 160 0
      src/otherPages/exerciseExam/components/explainJs.vue
  19. 42 0
      src/otherPages/exerciseExam/components/m-checkbox-group.vue
  20. 62 0
      src/otherPages/exerciseExam/components/m-checkbox.vue
  21. 42 0
      src/otherPages/exerciseExam/components/m-radio-group.vue
  22. 62 0
      src/otherPages/exerciseExam/components/m-radio.vue
  23. 83 0
      src/otherPages/exerciseExam/components/navBar.vue
  24. 47 0
      src/otherPages/exerciseExam/components/tabbar.vue
  25. 765 0
      src/otherPages/exerciseExam/index.vue
  26. 23 0
      src/otherPages/exerciseFree/components/checkbox.vue
  27. 160 0
      src/otherPages/exerciseFree/components/explainJs.vue
  28. 42 0
      src/otherPages/exerciseFree/components/m-checkbox-group.vue
  29. 62 0
      src/otherPages/exerciseFree/components/m-checkbox.vue
  30. 42 0
      src/otherPages/exerciseFree/components/m-radio-group.vue
  31. 62 0
      src/otherPages/exerciseFree/components/m-radio.vue
  32. 83 0
      src/otherPages/exerciseFree/components/navBar.vue
  33. 47 0
      src/otherPages/exerciseFree/components/tabbar.vue
  34. 762 0
      src/otherPages/exerciseFree/index.vue
  35. 23 0
      src/otherPages/exerciseSpecify/components/checkbox.vue
  36. 160 0
      src/otherPages/exerciseSpecify/components/explainJs.vue
  37. 82 0
      src/otherPages/exerciseSpecify/components/navBar.vue
  38. 45 0
      src/otherPages/exerciseSpecify/components/tabbar.vue
  39. 681 0
      src/otherPages/exerciseSpecify/index.vue
  40. 23 0
      src/otherPages/exerciseWrong/components/checkbox.vue
  41. 160 0
      src/otherPages/exerciseWrong/components/explainJs.vue
  42. 82 0
      src/otherPages/exerciseWrong/components/navBar.vue
  43. 45 0
      src/otherPages/exerciseWrong/components/tabbar.vue
  44. 0 1
      src/otherPages/exerciseWrong/index.vue
  45. 2 0
      src/otherPages/mockExam/index.vue
  46. 47 21
      src/otherPages/mockExamEnd/index.vue
  47. 36 4
      src/pages.json
  48. 190 161
      src/pages/carVideo/components/videoListBox.vue
  49. 4 4
      src/pages/carVideo/index.vue
  50. 1 1
      src/pages/carVideo/play.vue

+ 38 - 9
src/api/modules/exam.js

@@ -67,14 +67,7 @@ const exam = {
 			params
 		})
 	},
-	//查询免费的题库
-	studentQuestionInfoSelectFreeQuestionInfo(params) {
-		return request({
-			url: "student/question/info/selectFreeQuestionInfo",
-			method: 'get',
-			params
-		})
-	},
+
 	//新增模拟考成绩
 	studentScoreInfo(data) {
 		return request({
@@ -133,7 +126,7 @@ const exam = {
 			data
 		})
 	},
-	//根据ids获取多个问
+	//批量取
 	studentQuestionInfoGetQuestionInfoByIds(params) {
 		return request({
 			url: "student/question/info/getQuestionInfoByIds",
@@ -141,7 +134,43 @@ const exam = {
 			params
 		})
 
+	},
+	//根据用户获取错题数
+	studentQuestionWrongWrongCountByUser(params) {
+		return request({
+			url: "student/question/wrong/wrongCountByUser",
+			method: "get",
+			params
+		})
+
+	},
+	//根据用户获取收藏数
+	studentQuestionCollectionCollectionCountByUser(params) {
+		return request({
+			url: "student/question/collection/collectionCountByUser",
+			method: "get",
+			params
+		})
+	},
+	//根据用户获取错题列表
+	studentQuestionWrongWrongByUser(params) {
+		return request({
+			url: "student/question/wrong/wrongByUser",
+			method: "get",
+			params
+		})
+
+	},
+	//根据用户获取收藏列表
+	studentQuestionCollectionCollectionByUser(params) {
+		return request({
+			url: "student/question/collection/collectionByUser",
+			method: "get",
+			params
+		})
+
 	}
+
 }
 
 export default exam

+ 19 - 3
src/api/modules/open.js

@@ -3,10 +3,19 @@ import request from '../request'
 const openApi = process.env.NODE_ENV === 'development' ? 'https://jpcj-admin1.zzxcx.net/stage-api' : 'https://jpcj-admin.zzxcx.net/prod-api'
 const open = {
     //open-api/teachingVideo/info/treeList
+    //获取免费的题库
+    questionInfoSelectFreeQuestionInfo(params) {
+        return request({
+            url: openApi + "/open-api/question/info/selectFreeQuestionInfo",
+            params
+        })
+
+
+    },
     //获取视频列表
-    teachingVideoInfoTreeList(params){
+    teachingVideoInfoTreeList(params) {
         return request({
-            url:"open-api/teachingVideo/info/treeList",
+            url: "open-api/teachingVideo/info/treeList",
             params
         })
 
@@ -31,11 +40,18 @@ const open = {
             method: "GET",
         })
     },
-    lightingItemList(){
+    lightingItemList() {
         return request({
             url: `${openApi}/open-api/lighting/item/list`,
             method: "GET",
         })
+    },
+    //批量取题
+    questionInfoGetQuestionInfoByIds(params){
+        return request({
+            url: "open-api/question/info/getQuestionInfoByIds",
+            params
+        })
     }
 }
 export default open

+ 2 - 2
src/api/request.js

@@ -58,10 +58,10 @@ service.interceptors.response.use(
 					title: 'code' + code + ':系统错误',
 					icon: 'none'
 				})
-			} else {
+			} else if(code!==502){
 				console.log('code' + code + ':' + msg)
 				wx.showToast({
-					title: 'code' + code + ':' + msg,
+					title: msg,
 					icon: 'none'
 				})
 			}

+ 0 - 0
src/otherPages/mockExamEnd/buhege.png → src/assets/img/buhege.png


+ 0 - 0
src/otherPages/mockExamEnd/hege.png → src/assets/img/hege.png


+ 682 - 103
src/components/m-do-topic/m-do-topic.vue

@@ -41,10 +41,15 @@
         >背题模式</view
       >
       <view
-        style="opacity: 0"
         :class="{
-          'mode-item_select': mode == 3,
+          'mode-item_select': isAutoReadTopics,
         }"
+        @click="
+          () => {
+            isAutoReadTopics = !isAutoReadTopics;
+            isAutoReadTopics ? playCurrentIssue() : stopAudio();
+          }
+        "
         class="mode-item"
         >自动读题</view
       >
@@ -175,7 +180,7 @@
             >
           </van-checkbox>
         </van-checkbox-group>
-        <view class="flex-center mt30">
+        <view class="flex-center mt30 pb16">
           <van-button
             @click="confirmMult"
             color="#498ef5"
@@ -374,7 +379,7 @@
           >
           </m-checkbox>
         </m-checkbox-group>
-        <view class="flex-center">
+        <view class="flex-center pb16">
           <van-button
             @click="confirmMult"
             color="#498ef5"
@@ -422,6 +427,28 @@
           <text class="problem-opAnswer">{{ item.value }}</text>
         </view>
       </view>
+
+      <view
+        v-if="problemList[problemListIndex].isCompleted && !hiddenAnswer"
+        class="answer"
+      >
+        <view
+          v-if="
+            problemList[problemListIndex].questionType == 1 &&
+            problemList[problemListIndex].isCompleted
+          "
+        >
+          答案:{{ judgMap[problemList[problemListIndex].answer] }}
+        </view>
+        <view
+          v-if="
+            problemList[problemListIndex].questionType > 1 &&
+            problemList[problemListIndex].isCompleted
+          "
+        >
+          答案: {{ problemList[problemListIndex].answer }}
+        </view>
+      </view>
       <funList
         :midFunc="midFunc"
         v-if="!hiddenFunction"
@@ -432,6 +459,7 @@
         "
         :problemListItem="problemList[problemListIndex]"
       ></funList>
+
       <!-- #endif -->
       <!-- <view v-if="!hiddenFunction" class="function-list">
       <div @click="collectTopics" class="function-item">
@@ -736,6 +764,7 @@ export default {
     return {
       //topic
       //isCollect
+      isAutoReadTopics: false,
       mode: 0,
       problemList: [
         {
@@ -809,128 +838,409 @@ export default {
       explainJsVisible: false,
       trueNum: 0,
       falseNum: 0,
+      errQuestionIds: [],
     };
   },
   watch: {
+    //specify
     query(newValue, oldValue) {
       let that = this;
       uni.showLoading({
         title: "加载题目中",
         mask: true,
       });
-      if (this.type == "wrong") {
-        api.exam
-          .studentQuestionInfoGetQuestionInfoByIds({
-            ids: newValue.questionIds,
-          })
-          .then((res) => {
-            res.rows.forEach((element) => {
-              element.optsArr = [];
-              element.isCollect = false;
-              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,
-                  });
-                }
+      switch (that.type) {
+        case "specify":
+          api.open
+            .questionInfoGetQuestionInfoByIds({
+              ids: newValue.questionIds,
+            })
+            .then((res) => {
+              res.rows.forEach((element) => {
+                element.optsArr = [];
+                element.isCollect = false;
+                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.userAnswer = [];
               });
-              element.isCompleted = false;
-              element.userAnswer = [];
+              that.problemListTotal = res.total;
+              origProblemList = JSON.parse(JSON.stringify(res.rows));
+
+              that.problemList = res.rows;
+
+              that.$emit("update:problemListTotal", res.total);
+              uni.hideLoading();
             });
-            that.problemListTotal = res.total;
-            origProblemList = JSON.parse(JSON.stringify(res.rows));
 
-            that.problemList = res.rows;
+          break;
+        case "exam":
+          api.exam
+            .studentQuestionInfoSelectTestQuestionInfo({
+              gs: "xc",
+              subject: 1,
+            })
+            .then((res) => {
+              res.rows.forEach((element) => {
+                element.optsArr = [];
+                element.isCollect = false;
+                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.userAnswer = [];
+              });
+              that.problemListTotal = res.total;
+              origProblemList = JSON.parse(JSON.stringify(res.rows));
 
-            that.$emit("update:problemListTotal", res.total);
-            uni.hideLoading();
-          });
-      } else if (this.type === "exam") {
-        api.exam
-          .studentQuestionInfoSelectTestQuestionInfo({
-            gs: "xc",
-            subject: 1,
-          })
-          .then((res) => {
-            res.rows.forEach((element) => {
-              element.optsArr = [];
-              element.isCollect = false;
-              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,
-                  });
-                }
+              that.problemList = res.rows;
+
+              that.$emit("update:problemListTotal", res.total);
+              uni.hideLoading();
+            });
+
+          break;
+        case "free":
+          api.open
+            .questionInfoSelectFreeQuestionInfo({
+              ...this.query,
+            })
+            .then((res) => {
+              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.userAnswer = [];
               });
-              element.isCompleted = false;
-              element.userAnswer = [];
+              that.problemList = res.rows;
+              origProblemList = JSON.parse(JSON.stringify(res.rows));
+              that.problemListTotal = res.total;
+              uni.hideLoading();
             });
-            that.problemListTotal = res.total;
-            origProblemList = JSON.parse(JSON.stringify(res.rows));
 
-            that.problemList = res.rows;
+          break;
+        case "wrong":
+          api.exam
+            .studentQuestionWrongWrongByUser({
+              carType: this.gsMap[this.query.gs],
+              km: this.query.subject === "1" ? "科目一" : "科目四",
+            })
+            .then((res) => {
+              res.data.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.userAnswer = [];
+              });
+              that.problemListTotal = res.total;
+              that.problemList = res.data;
+              origProblemList = JSON.parse(JSON.stringify(res.data));
+              that.$emit("update:problemListTotal", res.data.length);
 
-            that.$emit("update:problemListTotal", res.total);
-            uni.hideLoading();
-          });
-      } else {
-        api.exam
-          .studentQuestionInfoList({
-            ...this.query,
-          })
-          .then((res) => {
-            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,
-                  });
-                }
+              uni.hideLoading();
+              uni.hideLoading();
+            });
+
+          break;
+        case "collect":
+          api.exam
+            .studentQuestionCollectionCollectionByUser({
+              carType: this.gsMap[this.query.gs],
+              km: this.query.subject === "1" ? "科目一" : "科目四",
+            })
+            .then((res) => {
+              res.data.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.userAnswer = [];
               });
-              element.isCompleted = false;
-              element.userAnswer = [];
+              that.problemListTotal = res.total;
+              that.problemList = res.data;
+              origProblemList = JSON.parse(JSON.stringify(res.data));
+              that.$emit("update:problemListTotal", res.data.length);
+
+              uni.hideLoading();
             });
-            that.problemListTotal = res.total;
-            that.problemList = res.rows;
-            origProblemList = JSON.parse(JSON.stringify(res.rows));
-            that.$emit("update:problemListTotal", res.total);
-            uni.hideLoading();
-          });
+
+          break;
+        default:
+          api.exam
+            .studentQuestionInfoList({
+              ...this.query,
+            })
+            .then((res) => {
+              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.userAnswer = [];
+              });
+              that.problemListTotal = res.total;
+              that.problemList = res.rows;
+              origProblemList = JSON.parse(JSON.stringify(res.rows));
+              that.$emit("update:problemListTotal", res.total);
+              uni.hideLoading();
+            });
+          break;
+      }
+      // if (this.type == "specify") {
+      //   api.open
+      //     .questionInfoGetQuestionInfoByIds({
+      //       ids: newValue.questionIds,
+      //     })
+      //     .then((res) => {
+      //       res.rows.forEach((element) => {
+      //         element.optsArr = [];
+      //         element.isCollect = false;
+      //         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.userAnswer = [];
+      //       });
+      //       that.problemListTotal = res.total;
+      //       origProblemList = JSON.parse(JSON.stringify(res.rows));
+
+      //       that.problemList = res.rows;
+
+      //       that.$emit("update:problemListTotal", res.total);
+      //       uni.hideLoading();
+      //     });
+      // } else if (this.type === "exam") {
+      //   api.exam
+      //     .studentQuestionInfoSelectTestQuestionInfo({
+      //       gs: "xc",
+      //       subject: 1,
+      //     })
+      //     .then((res) => {
+      //       res.rows.forEach((element) => {
+      //         element.optsArr = [];
+      //         element.isCollect = false;
+      //         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.userAnswer = [];
+      //       });
+      //       that.problemListTotal = res.total;
+      //       origProblemList = JSON.parse(JSON.stringify(res.rows));
+
+      //       that.problemList = res.rows;
+
+      //       that.$emit("update:problemListTotal", res.total);
+      //       uni.hideLoading();
+      //     });
+      // } else if (this.type === "free") {
+      //   api.open
+      //     .questionInfoSelectFreeQuestionInfo({
+      //       ...this.query,
+      //     })
+      //     .then((res) => {
+      //       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.userAnswer = [];
+      //       });
+      //       that.problemList = res.rows;
+      //       origProblemList = JSON.parse(JSON.stringify(res.rows));
+      //       that.problemListTotal = res.total;
+      //       uni.hideLoading();
+      //     });
+      // } else {
+      //   api.exam
+      //     .studentQuestionInfoList({
+      //       ...this.query,
+      //     })
+      //     .then((res) => {
+      //       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.userAnswer = [];
+      //       });
+      //       that.problemListTotal = res.total;
+      //       that.problemList = res.rows;
+      //       origProblemList = JSON.parse(JSON.stringify(res.rows));
+      //       that.$emit("update:problemListTotal", res.total);
+      //       uni.hideLoading();
+      //     });
+      // }
+    },
+    problemListIndex(newValue, oldValue) {
+      if (this.isAutoReadTopics) {
+        let audio = utils.wxUtils.getGlobAudio();
+        audio.stop();
+        audio.src = this.problemList[this.problemListIndex].issuemp3;
+        audio.play();
       }
     },
   },
   methods: {
+    stopAudio() {
+      let audio = utils.wxUtils.getGlobAudio();
+      audio.stop();
+    },
+    playCurrentIssue() {
+      let audio = utils.wxUtils.getGlobAudio();
+      audio.stop();
+      audio.src = this.problemList[this.problemListIndex].issuemp3;
+      audio.play();
+    },
     createCompleteProblemList() {
       if (this.mode == 2) {
         return;
@@ -1039,6 +1349,8 @@ export default {
                 utils.mapToUrlQuery({
                   score,
                   useTime,
+                  questionIds: that.errQuestionIds.join(","),
+                  type: that.type,
                   ...that.query,
                 }),
             });
@@ -1119,6 +1431,12 @@ export default {
       } else {
         this.falseNum++;
         this.$emit("update:falseNum", this.falseNum);
+        this.errQuestionIds.includes(this.problemList[this.problemListIndex].id)
+          ? ""
+          : this.errQuestionIds.push(
+              this.problemList[this.problemListIndex].id
+            );
+
         api.exam.studentQuestionWrong({
           questionId: this.problemList[this.problemListIndex].id,
           carType: this.gsMap[this.query.gs],
@@ -1181,6 +1499,7 @@ export default {
       //   this.falseNum = this.falseNum + 1;
       //   this.$emit("update:falseNum", this.falseNum);
       // }
+      //score=1&useTime=NaN%3ANaN&questionIds=&type=&cert=C1%2FC2%2FC3&vehicle=%E8%BD%BF%E8%BD%A6&subject=1&title=%E9%A1%BA%E5%BA%8F%E7%BB%83%E4%B9%A0&liceCar=1&liceTruck=&liceBus=&liceMoto=&name=%E7%A7%91%E7%9B%AE%E4%B8%80&gs=xc&sort=3&sequeIssueName=%E7%BB%83%E4%B9%A0%E4%B8%80&__id__=3
     },
     changeRadioGroup(e) {
       console.log(e, "changeRadioGroup");
@@ -1197,6 +1516,12 @@ export default {
           km: this.query.subject === "4" ? "科目四" : "科目一",
         });
         this.$emit("update:falseNum", this.falseNum);
+        this.errQuestionIds.includes(this.problemList[this.problemListIndex].id)
+          ? ""
+          : this.errQuestionIds.push(
+              this.problemList[this.problemListIndex].id
+            );
+        console.log(this.errQuestionIds);
       }
       this.$set(
         this.problemList[this.problemListIndex],
@@ -1245,6 +1570,11 @@ export default {
       } else {
         this.falseNum = this.falseNum + 1;
         this.$emit("update:falseNum", this.falseNum);
+        this.errQuestionIds.includes(this.problemList[this.problemListIndex].id)
+          ? ""
+          : this.errQuestionIds.push(
+              this.problemList[this.problemListIndex].id
+            );
         api.exam.studentQuestionWrong({
           questionId: this.problemList[this.problemListIndex].id,
           carType: this.gsMap[this.query.gs],
@@ -1299,6 +1629,10 @@ export default {
         return [];
       },
     },
+    hiddenAnswer: {
+      type: Boolean,
+      default: false,
+    },
     hiddenFunction: {
       type: Boolean,
       default: false,
@@ -1326,10 +1660,255 @@ export default {
       default: 0,
     },
   },
+  mounted() {
+    let that =this
+    switch (that.type) {
+      case "specify":
+        api.open
+          .questionInfoGetQuestionInfoByIds({
+            ids: newValue.questionIds,
+          })
+          .then((res) => {
+            res.rows.forEach((element) => {
+              element.optsArr = [];
+              element.isCollect = false;
+              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.userAnswer = [];
+            });
+            that.problemListTotal = res.total;
+            origProblemList = JSON.parse(JSON.stringify(res.rows));
+
+            that.problemList = res.rows;
+
+            that.$emit("update:problemListTotal", res.total);
+            uni.hideLoading();
+          });
+
+        break;
+      case "exam":
+        api.exam
+          .studentQuestionInfoSelectTestQuestionInfo({
+            gs: "xc",
+            subject: 1,
+          })
+          .then((res) => {
+            res.rows.forEach((element) => {
+              element.optsArr = [];
+              element.isCollect = false;
+              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.userAnswer = [];
+            });
+            that.problemListTotal = res.total;
+            origProblemList = JSON.parse(JSON.stringify(res.rows));
+
+            that.problemList = res.rows;
+
+            that.$emit("update:problemListTotal", res.total);
+            uni.hideLoading();
+          });
+
+        break;
+      case "free":
+        api.open
+          .questionInfoSelectFreeQuestionInfo({
+            ...this.query,
+          })
+          .then((res) => {
+            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.userAnswer = [];
+            });
+            that.problemList = res.rows;
+            origProblemList = JSON.parse(JSON.stringify(res.rows));
+            that.problemListTotal = res.total;
+            uni.hideLoading();
+          });
+
+        break;
+      case "wrong":
+        api.exam
+          .studentQuestionWrongWrongByUser({
+            carType: this.gsMap[this.query.gs],
+            km: this.query.subject === "1" ? "科目一" : "科目四",
+          })
+          .then((res) => {
+            res.data.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.userAnswer = [];
+            });
+            that.problemListTotal = res.total;
+            that.problemList = res.data;
+            origProblemList = JSON.parse(JSON.stringify(res.data));
+            that.$emit("update:problemListTotal", res.data.length);
+
+            uni.hideLoading();
+            uni.hideLoading();
+          });
+
+        break;
+      case "collect":
+        api.exam
+          .studentQuestionCollectionCollectionByUser({
+            carType: this.gsMap[this.query.gs],
+            km: this.query.subject === "1" ? "科目一" : "科目四",
+          })
+          .then((res) => {
+            res.data.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.userAnswer = [];
+            });
+            that.problemListTotal = res.total;
+            that.problemList = res.data;
+            origProblemList = JSON.parse(JSON.stringify(res.data));
+            that.$emit("update:problemListTotal", res.data.length);
+
+            uni.hideLoading();
+          });
+
+        break;
+      default:
+        api.exam
+          .studentQuestionInfoList({
+            ...this.query,
+          })
+          .then((res) => {
+            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.userAnswer = [];
+            });
+            that.problemListTotal = res.total;
+            that.problemList = res.rows;
+            origProblemList = JSON.parse(JSON.stringify(res.rows));
+            that.$emit("update:problemListTotal", res.total);
+            uni.hideLoading();
+          });
+        break;
+    }
+  },
 };
 </script>
 
 <style lang="scss" scoped>
+.answer {
+  padding-left: 16rpx;
+  padding-bottom: 16rpx;
+  padding-top: 16rpx;
+  > view {
+    padding-left: 16rpx;
+    background: #d8d8d8;
+    padding-bottom: 8rpx;
+    padding-top: 8rpx;
+  }
+}
+.pb16 {
+  padding-bottom: 16rpx;
+}
 .mode {
   display: flex;
   padding: 20rpx 30rpx;

+ 99 - 0
src/otherPages/classifyFree/index.vue

@@ -0,0 +1,99 @@
+<template>
+  <view class="box">
+    <view class="top">
+      <view @click="goExerciseFree(1)" class="top-item mb30">
+        <image
+          class="top-item-img1"
+          src="https://t1-1305573081.file.myqcloud.com/wxapp/static/imgs/classifyFree/subject1Bg.png"
+        ></image>
+        <image mode="widthFix" class="goArrow top-item-img2" :src="goArrow" />
+        <text class="top-item-text">科目一体验</text>
+      </view>
+      <view @click="goExerciseFree(4)" class="top-item">
+        <image
+          class="top-item-img1"
+          src="https://t1-1305573081.file.myqcloud.com/wxapp/static/imgs/classifyFree/subject4Bg.png"
+        ></image>
+        <image mode="widthFix" class="goArrow top-item-img2" :src="goArrow" />
+        <text class="top-item-text">科目四体验</text>
+      </view>
+    </view>
+    <view class="bottom">
+        <image src="https://t1-1305573081.file.myqcloud.com/wxapp/static/imgs/classifyFree/bottomBg.png"></image>
+    </view>
+  </view>
+</template>
+
+<script>
+import goArrow from "@/assets/img/goArrow.png";
+import utils from '@/utils/index'
+export default {
+  data() {
+    return {
+      goArrow,
+      query:{
+
+      }
+    };
+  },
+  onLoad(query){
+      this.query = query
+
+  },
+  methods: {
+    goExerciseFree(subject){
+        uni.navigateTo({
+            url:"/otherPages/exerciseFree/index?"+utils.mapToUrlQuery(this.query)
+        })
+    }
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.goArrow {
+  width: 146rpx;
+}
+.mb30{
+    margin-bottom: 30rpx;
+}
+.box{
+    display: flex;
+    flex-direction: column;
+    justify-content: space-between;
+    height: 100vh;
+}
+.top {
+  width: 100%;
+  padding: 0 30rpx;
+  .top-item {
+    width: 100%;
+    height: 332rpx;
+    position: relative;
+    .top-item-text {
+      font-size: 50rpx;
+      color: white;
+      position: absolute;
+      left: 40rpx;
+      top: 38rpx;
+    }
+    .top-item-img1 {
+      width: 100%;
+      height: 332rpx;
+    }
+    .top-item-img2 {
+      top: 236rpx;
+      position: absolute;
+      left: 40rpx;
+    }
+  }
+}
+.bottom{
+    width: 100%;
+    display: flex;
+    image{
+        width: 100%;
+        height: 588rpx;
+    }
+}
+</style>

+ 1 - 0
src/otherPages/classifyKind/index.vue

@@ -61,6 +61,7 @@ export default {
       api.exam
         .studentQuestionInfoSelectFlQuestionInfo(this.query)
         .then((res) => {
+          res.data.shift()
           this.classData = res.data;
         });
     },

+ 16 - 2
src/otherPages/classifyOrder/index.vue

@@ -30,7 +30,7 @@
             <div
               @click="
                 () => {
-                  goExercise({
+                  goExerciseExam({
                     sequeIssueName: item.sequeIssueName,
                   });
                 }
@@ -60,7 +60,7 @@ export default {
   data() {
     return {
       classData: [],
-      classifyTip:['软件题库已同步更新至车管所最新'],
+      classifyTip: ["软件题库已同步更新至车管所最新"],
       query: {
         title: "",
         vehicle: "",
@@ -82,6 +82,20 @@ export default {
         url: "/otherPages/exercise/index?" + utils.mapToUrlQuery(query),
       });
     },
+    goExerciseExam(extraQuery) {
+      let query = Object.assign({}, this.query);
+      if (extraQuery) {
+        query = {
+          ...query,
+          ...extraQuery,
+        };
+      } else {
+      }
+
+      uni.navigateTo({
+        url: "/otherPages/exerciseExam/index?" + utils.mapToUrlQuery(query),
+      });
+    },
   },
   onLoad(op) {
     this.query = op;

+ 50 - 44
src/otherPages/collection/index.vue

@@ -4,31 +4,35 @@
       <img class="collectionHeader" mode="widthFix" :src="collectionHeader" />
     </div>
     <div class="choose">
-      <div class="choose-img" @click="goSpecifyExercise('wrong')">
+      <div class="choose-img" @click="goExercise('wrong')">
         <span class="choose-text1"> 做错题 </span>
-        <span class="choose-text2"> 共 {{ wrongList.length }} 题 </span>
+        <span class="choose-text2"> 共 {{ wrongListCount }} 题 </span>
         <image mode="widthFix" class="bg" :src="wrongBg" />
         <image mode="widthFix" class="goArrow" :src="goArrow" />
-        <button
-          @click="clearTopics('wrong')"
+        <view
+          :hover-stop-propagation="true"
+          data-type="wrong"
+          @touchend.stop="clearTopics('wrong')"
           style="color: #498ef5"
           class="clear"
         >
           清空错题
-        </button>
+        </view>
       </div>
-      <div class="choose-img" @click="goSpecifyExercise('collection')">
+      <div class="choose-img" @click="goExercise('collect')">
         <span class="choose-text1">收藏题</span>
-        <span class="choose-text2"> 共 {{ collectionList.length }} 题 </span>
+        <span class="choose-text2"> 共 {{ collectionListCount }} 题 </span>
         <image mode="widthFix" class="bg" :src="collectionBg" />
         <image mode="widthFix" class="goArrow" :src="goArrow" />
-        <button
-          @click="clearTopics('collection')"
+        <view
+          :hover-stop-propagation="true"
+          data-type="collect"
+          @touchend.stop="clearTopics('collect')"
           style="color: #01c18d"
           class="clear"
         >
           清空收藏
-        </button>
+        </view>
       </div>
     </div>
     <div class="bottom">
@@ -42,18 +46,21 @@
 </template>
 
 <script>
-
 import goArrow from "@/assets/img/goArrow.png";
 import api from "@/api/index";
 import utils from "@/utils/index";
 export default {
   data() {
     return {
-      wrongBg:"https://t1-1305573081.file.myqcloud.com/wxapp/static/imgs/collection/wrongBg.png",
-      collectionBottomBg:"https://t1-1305573081.file.myqcloud.com/wxapp/static/imgs/collection/collectionBottomBg.png",
+      wrongBg:
+        "https://t1-1305573081.file.myqcloud.com/wxapp/static/imgs/collection/wrongBg.png",
+      collectionBottomBg:
+        "https://t1-1305573081.file.myqcloud.com/wxapp/static/imgs/collection/collectionBottomBg.png",
       goArrow,
-      collectionBg:"https://t1-1305573081.file.myqcloud.com/wxapp/static/imgs/collection/collectionBg.png",
-      collectionHeader:"https://t1-1305573081.file.myqcloud.com/wxapp/static/imgs/collection/collectionHeader.png",
+      collectionBg:
+        "https://t1-1305573081.file.myqcloud.com/wxapp/static/imgs/collection/collectionBg.png",
+      collectionHeader:
+        "https://t1-1305573081.file.myqcloud.com/wxapp/static/imgs/collection/collectionHeader.png",
       query: {
         questionIds: "",
       },
@@ -64,66 +71,63 @@ export default {
         kc: "客车",
       },
       wrongList: [],
+      wrongListCount: 1,
       collectionList: [],
+      collectionListCount: 1,
     };
   },
   onLoad(query) {
     this.query = query;
     api.exam
-      .studentQuestionWrongList({
+      .studentQuestionWrongWrongCountByUser({
         carType: this.gsMap[query.gs],
         km: query.subject === "1" ? "科目一" : "科目四",
         pageNum: 1,
         pageSize: 10000,
       })
       .then((res) => {
-        this.wrongList = res.rows;
+        this.wrongListCount = res.data;
       });
     api.exam
-      .studentQuestionCollectionList({
+      .studentQuestionCollectionCollectionCountByUser({
         carType: this.gsMap[query.gs],
         km: query.subject === "1" ? "科目一" : "科目四",
         pageNum: 1,
         pageSize: 10000,
       })
       .then((res) => {
-        this.collectionList = res.rows;
+        this.collectionListCount = res.data;
       });
   },
   methods: {
-    goSpecifyExercise(type) {
+    goExercise(type) {
       let query = Object.assign({}, this.query);
-      if (type == "wrong" && this.wrongList.length == 0) {
+      if (type == "wrong" && this.wrongListCount == 0) {
         uni.showToast({
           title: "没有题目了",
-          icon: "error",
+          icon: "fail",
         });
         return;
       }
-      if (type == "collection" && this.collectionList.length == 0) {
+      if (type == "collect" && this.collectionListCount == 0) {
         uni.showToast({
           title: "没有题目了",
-          icon: "error",
+          icon: "fail",
         });
         return;
       }
 
       if (type == "wrong") {
-        query.questionIds = this.wrongList
-          .map((item) => {
-            return item.questionId;
-          })
-          .join(",");
-      } else if (type === "collection") {
-        query.questionIds = this.collectionList
-          .map((item) => {
-            return item.questionId;
-          })
-          .join(",");
+        uni.navigateTo({
+          url: "/otherPages/exerciseWrong/index?" + utils.mapToUrlQuery(query),
+        });
+      }
+      if (type === "collect") {
+        uni.navigateTo({
+          url:
+            "/otherPages/exerciseCollect/index?" + utils.mapToUrlQuery(query),
+        });
       }
-      uni.navigateTo({
-        url: "/otherPages/specifyExercise/index?" + utils.mapToUrlQuery(query),
-      });
     },
     clearTopics(type) {
       let that = this;
@@ -139,20 +143,20 @@ export default {
                 })
                 .then((res) => {
                   api.exam
-                    .studentQuestionWrongList({
+                    .studentQuestionWrongWrongCountByUser({
                       carType: that.gsMap[that.query.gs],
                       km: that.query.subject === "1" ? "科目一" : "科目四",
                       pageNum: 1,
                       pageSize: 10000,
                     })
                     .then((res) => {
-                      that.wrongList = res.rows;
+                      that.wrongListCount = res.data;
                     });
                 });
             }
           },
         });
-      } else if (type === "collection") {
+      } else if (type === "collect") {
         uni.showModal({
           title: "是否清空收藏题",
           success(res) {
@@ -164,14 +168,14 @@ export default {
                 })
                 .then((res) => {
                   api.exam
-                    .studentQuestionCollectionList({
-                      carType: that.gsMap[that.query.gs],
+                    .studentQuestionCollectionCollectionCountByUser({
+                      carType:  that.gsMap[that.query.gs],
                       km: that.query.subject === "1" ? "科目一" : "科目四",
                       pageNum: 1,
                       pageSize: 10000,
                     })
                     .then((res) => {
-                      that.collectionList = res.rows;
+                      that.collectionListCount = res.data;
                     });
                 });
             }
@@ -217,6 +221,8 @@ export default {
       bottom: 40rpx;
       border: 0;
       font-size: 26rpx;
+      line-height: 60rpx;
+      text-align: center;
     }
     .goArrow {
       position: absolute;

+ 30 - 30
src/otherPages/exercise/index.vue

@@ -499,36 +499,36 @@ export default {
   onLoad(query) {
     let that = this;
     this.query = query;
-    api.exam
-      .studentQuestionInfoList({
-        ...this.query,
-      })
-      .then((res) => {
-        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.userAnswer = [];
-        });
-        that.problemListTotal = res.total;
-        that.problemList = res.rows;
-      });
+    // api.exam
+    //   .studentQuestionInfoList({
+    //     ...this.query,
+    //   })
+    //   .then((res) => {
+    //     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.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

+ 0 - 0
src/otherPages/specifyExercise/components/checkbox.vue → src/otherPages/exerciseCollect/components/checkbox.vue


+ 0 - 0
src/otherPages/specifyExercise/components/explainJs.vue → src/otherPages/exerciseCollect/components/explainJs.vue


+ 0 - 0
src/otherPages/specifyExercise/components/navBar.vue → src/otherPages/exerciseCollect/components/navBar.vue


+ 0 - 0
src/otherPages/specifyExercise/components/tabbar.vue → src/otherPages/exerciseCollect/components/tabbar.vue


+ 681 - 0
src/otherPages/exerciseCollect/index.vue

@@ -0,0 +1,681 @@
+<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
+      type="collect"
+      :trueNum.sync="trueNum"
+      :falseNum.sync="falseNum"
+      :query="query"
+      :problemListTotal.sync="problemListTotal"
+      :problemListIndex="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,
+        },
+        {},
+      ],
+      explainJsVisible: false,
+      time: 45 * 60 * 1000,
+      problemListTotal: 1,
+      touchx: 0,
+      touchy: 0,
+      problemList: [
+        {
+          questionType: 2,
+          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: {
+    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.problemList.length - 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;
+  },
+  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 ||
+        ""
+      }`;
+    },
+  },
+  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>

+ 23 - 0
src/otherPages/exerciseExam/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/exerciseExam/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>

+ 42 - 0
src/otherPages/exerciseExam/components/m-checkbox-group.vue

@@ -0,0 +1,42 @@
+<template>
+  <view class="checkboxGroup">
+    <view @tap.native="changeCheckboxGroup">
+      <slot></slot>
+    </view>
+  </view>
+</template>
+
+<script>
+export default {
+  data() {
+    return {};
+  },
+  methods: {
+    changeCheckboxGroup(e) {
+      console.log(e);
+      e.detail = e.target.dataset.item;
+      this.$emit("update:value", e.target.dataset.value);
+      this.$emit("change", e);
+    },
+  },
+  props: {
+    useIconSlot: {
+      type: Boolean,
+      default: false,
+    },
+    name: {
+      type: String,
+      default: "",
+    },
+    value: {
+      type: String,
+      default: "",
+    },
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.checkboxGroup {
+}
+</style>

+ 62 - 0
src/otherPages/exerciseExam/components/m-checkbox.vue

@@ -0,0 +1,62 @@
+<template>
+  <view @tap.native="clickCheckbox" :data-item="item" class="checkbox">
+    <view :data-item="item" class="custom-icon" v-if="useIconSlot">{{
+      name
+    }}</view>
+    <view :data-item="item" style="width: 8px"></view>
+    <text :data-item="item">{{ item.value }}</text>
+  </view>
+</template>
+
+<script>
+export default {
+  data() {
+    return {};
+  },
+  methods: {
+    stopClick(e) {
+      e.stopPropagation();
+    },
+    clickCheckbox(e) {
+      console.log(e);
+      this.$emit("clickcheckbox", e);
+      e.stopPropagation();
+    },
+  },
+  props: {
+    useIconSlot: {
+      type: Boolean,
+      default: false,
+    },
+    name: {
+      type: String,
+      default: "",
+    },
+    item: {
+      type: Object,
+      default: () => {
+        return {};
+      },
+    },
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.checkbox {
+  display: flex;
+  align-content: center;
+  align-items: center;
+  padding: 8px 0;
+}
+.custom-icon {
+  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);
+}
+</style>

+ 42 - 0
src/otherPages/exerciseExam/components/m-radio-group.vue

@@ -0,0 +1,42 @@
+<template>
+  <view class="radioGroup">
+    <view @tap.native="changeRadioGroup">
+      <slot></slot>
+    </view>
+  </view>
+</template>
+
+<script>
+export default {
+  data() {
+    return {};
+  },
+  methods: {
+    changeRadioGroup(e) {
+      console.log(e);
+      e.detail = e.target.dataset.item;
+      this.$emit("update:value", e.target.dataset.value);
+      this.$emit("change", e);
+    },
+  },
+  props: {
+    useIconSlot: {
+      type: Boolean,
+      default: false,
+    },
+    name: {
+      type: String,
+      default: "",
+    },
+    value: {
+      type: String,
+      default: "",
+    },
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.radioGroup {
+}
+</style>

+ 62 - 0
src/otherPages/exerciseExam/components/m-radio.vue

@@ -0,0 +1,62 @@
+<template>
+  <view @tap.native="clickRadio" :data-item="item" class="radio">
+    <view :data-item="item" class="custom-icon" v-if="useIconSlot">{{
+      name
+    }}</view>
+    <view :data-item="item" style="width: 8px"></view>
+    <text :data-item="item">{{ item.value }}</text>
+  </view>
+</template>
+
+<script>
+export default {
+  data() {
+    return {};
+  },
+  methods: {
+    stopClick(e) {
+      e.stopPropagation();
+    },
+    clickRadio(e) {
+      console.log(e);
+      this.$emit("clickRadio", e);
+      e.stopPropagation();
+    },
+  },
+  props: {
+    useIconSlot: {
+      type: Boolean,
+      default: false,
+    },
+    name: {
+      type: String,
+      default: "",
+    },
+    item: {
+      type: Object,
+      default: () => {
+        return {};
+      },
+    },
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.radio {
+  display: flex;
+  align-content: center;
+  align-items: center;
+  padding: 8px 0;
+}
+.custom-icon {
+  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);
+}
+</style>

+ 83 - 0
src/otherPages/exerciseExam/components/navBar.vue

@@ -0,0 +1,83 @@
+<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 {
+    font-size: 32rpx;
+    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>

+ 47 - 0
src/otherPages/exerciseExam/components/tabbar.vue

@@ -0,0 +1,47 @@
+<template>
+  <view
+    class="box"
+    :style="{
+      height: 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;
+    padding:0 30rpx;
+    border-top: 2rpx solid #d8d8d8;
+    padding-top: 5rpx;
+
+
+}
+
+
+</style>

+ 765 - 0
src/otherPages/exerciseExam/index.vue

@@ -0,0 +1,765 @@
+<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> -->
+    <view style="text-align: center">
+      <van-count-down :time="time"></van-count-down>
+    </view>
+
+    <m-do-topic
+      :hiddenAnswer="true"
+      :hiddenMode="true"
+      :bottomFunc="['previous', 'next', 'selectCatalogue', 'submitExam']"
+      :midFunc="['collect', 'readQuestion', 'readQuestionAndAnswer']"
+      :trueNum.sync="trueNum"
+      :falseNum.sync="falseNum"
+      :query="query"
+      :problemListIndex.sync="problemListIndex"
+    ></m-do-topic>
+    <!-- <view class="function-list">
+      <div class="function-item">
+        <van-icon name="star-o" size="25px" />
+        <span>收藏</span>
+      </div>
+      <div
+        @click="readQuestion(problemList[problemListIndex].issuemp3)"
+        class="function-item"
+      >
+        <van-icon name="bullhorn-o" size="25px" />
+        <span>读题</span>
+      </div>
+    </view> -->
+
+    <van-overlay
+      @click-overlay="
+        () => {
+          selectProblemListVisible = false;
+        }
+      "
+      :show="selectProblemListVisible"
+    >
+      <view class="select-problem">
+        <view class="problem-index">
+          <view class="problem-header">
+            <view class="problem-header-left">
+              <view class="problem-dui">
+                <icon
+                  class="icon-box-img"
+                  color="#06c05f"
+                  type="success"
+                  size="18"
+                ></icon>
+                <text
+                  style="color: #06c05f; font-size: 14px; margin-left: 8rpx"
+                  >{{ trueNum }}</text
+                >
+              </view>
+              <view class="problem-cuo" style="margin-left: 16rpx">
+                <icon class="icon-box-img" type="clear" size="18"></icon>
+                <text style="color: red; font-size: 14px; margin-left: 8rpx">{{
+                  falseNum
+                }}</text>
+              </view>
+            </view>
+            <view class="problem-header-right">
+              <van-icon size="18px" name="description" />
+              <view style="font-size: 14px; display: flex; align-items: center"
+                >{{ problemListIndex + 1 }}/{{ problemListTotal }}</view
+              >
+            </view>
+          </view>
+          <view class="problem-body">
+            <view class="problem-listBody">
+              <view
+                class="problem-listItem"
+                :key="index"
+                v-for="(item, index) in problemList"
+                :class="{
+                  'problem-listItem_dui':
+                    item.userAnswer.length && item.userAnswer == item.answer,
+                  'problem-listItem_cuo':
+                    item.userAnswer.length && item.userAnswer !== item.answer,
+                }"
+              >
+                {{ index + 1 }}
+              </view>
+            </view>
+          </view>
+          <view class="problem-bottom">
+            <view
+              @click="
+                () => {
+                  selectProblemListVisible = false;
+                }
+              "
+              class="problem-bottom-sure"
+              >确定
+            </view>
+            <view
+              @click="
+                () => {
+                  selectProblemListVisible = false;
+                }
+              "
+              class="problem-bottom-close"
+            >
+              关闭</view
+            >
+          </view>
+        </view>
+      </view>
+    </van-overlay>
+  </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 mRadio from "@/components/m-radio/m-radio.vue";
+import mRadioGroup from "@/components/m-radio-group/m-radio-group.vue";
+import mCheckbox from "@/components/m-checkbox/m-checkbox.vue";
+import mCheckboxGroup from "@/components/m-checkbox-group/m-checkbox-group.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,
+        },
+        {},
+      ],
+      explainJsVisible: false,
+      selectProblemListVisible: false,
+      time: 45 * 60 * 1000,
+      problemListTotal: 1,
+      touchx: 0,
+      touchy: 0,
+      problemList: [
+        {
+          questionType: 2,
+          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: {
+    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.problemList.length - 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.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();
+      }
+    },
+    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;
+  },
+  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}`;
+    },
+  },
+  watch: {
+    problemListIndex: {
+      handler(newValue, oldValue) {},
+      immediate: true,
+    },
+  },
+
+  components: {
+    mDoTopic,
+    navBar,
+    explainJs,
+    tabbar,
+    mRadio,
+    mRadioGroup,
+    mCheckbox,
+    mCheckboxGroup,
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.select-problem {
+  display: flex;
+  width: 100vw;
+  height: 100vh;
+  align-content: flex-end;
+  align-items: flex-end;
+  .problem-index {
+    width: 100vw;
+    height: 650rpx;
+    background: #fff;
+    border-radius: 16rpx;
+    padding-top: 50rpx;
+  }
+  .problem-bottom {
+    width: 100%;
+    display: flex;
+    height: 80rpx;
+    .problem-bottom-sure {
+      width: 50%;
+      height: 100%;
+      border-right: 2rpx solid #d8d8d8;
+      border-top: 2rpx solid #d8d8d8;
+      text-align: center;
+      color: #498ef5;
+      line-height: 80rpx;
+    }
+    .problem-bottom-close {
+      width: 50%;
+      height: 100%;
+      color: red;
+      text-align: center;
+      border-top: 2rpx solid #d8d8d8;
+      line-height: 80rpx;
+    }
+  }
+  .problem-header {
+    display: flex;
+    justify-content: space-between;
+    align-content: center;
+    align-items: center;
+    padding: 0rpx 30rpx;
+    .problem-header-left {
+      display: flex;
+
+      .problem-dui {
+        display: flex;
+        align-content: center;
+        align-items: center;
+      }
+      .problem-cuo {
+        display: flex;
+        align-content: center;
+        align-items: center;
+      }
+    }
+    .problem-header-right {
+      display: flex;
+      align-content: center;
+    }
+  }
+  .problem-body {
+    height: 480rpx;
+    padding-top: 30rpx;
+    overflow-y: scroll;
+
+    .problem-listBody {
+      display: inline-block;
+      overflow: hidden;
+      .problem-listItem {
+        display: inline-block;
+        width: 99rpx;
+        height: 99rpx;
+        line-height: 100rpx;
+        text-align: center;
+        border-radius: 50%;
+        border: 2rpx #d8d8d8 solid;
+        margin-bottom: 15rpx;
+        margin-left: 13rpx;
+        margin-right: 13rpx;
+      }
+      .problem-listItem_dui {
+        background: #01c18d;
+      }
+      .problem-listItem_cuo {
+        background: red;
+      }
+    }
+  }
+}
+.tabbar-item {
+  display: flex;
+  flex-wrap: wrap;
+  justify-content: center;
+  text-align: center;
+  align-content: space-around;
+  align-items: space-around;
+}
+.divider {
+  width: 100%;
+  height: 24rpx;
+  background-color: #f2f3f5;
+}
+.h-full {
+  height: 100%;
+}
+.inline-block {
+  display: inline-block;
+}
+.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>

+ 23 - 0
src/otherPages/exerciseFree/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/exerciseFree/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>

+ 42 - 0
src/otherPages/exerciseFree/components/m-checkbox-group.vue

@@ -0,0 +1,42 @@
+<template>
+  <view class="checkboxGroup">
+    <view @tap.native="changeCheckboxGroup">
+      <slot></slot>
+    </view>
+  </view>
+</template>
+
+<script>
+export default {
+  data() {
+    return {};
+  },
+  methods: {
+    changeCheckboxGroup(e) {
+      console.log(e);
+      e.detail = e.target.dataset.item;
+      this.$emit("update:value", e.target.dataset.value);
+      this.$emit("change", e);
+    },
+  },
+  props: {
+    useIconSlot: {
+      type: Boolean,
+      default: false,
+    },
+    name: {
+      type: String,
+      default: "",
+    },
+    value: {
+      type: String,
+      default: "",
+    },
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.checkboxGroup {
+}
+</style>

+ 62 - 0
src/otherPages/exerciseFree/components/m-checkbox.vue

@@ -0,0 +1,62 @@
+<template>
+  <view @tap.native="clickCheckbox" :data-item="item" class="checkbox">
+    <view :data-item="item" class="custom-icon" v-if="useIconSlot">{{
+      name
+    }}</view>
+    <view :data-item="item" style="width: 8px"></view>
+    <text :data-item="item">{{ item.value }}</text>
+  </view>
+</template>
+
+<script>
+export default {
+  data() {
+    return {};
+  },
+  methods: {
+    stopClick(e) {
+      e.stopPropagation();
+    },
+    clickCheckbox(e) {
+      console.log(e);
+      this.$emit("clickcheckbox", e);
+      e.stopPropagation();
+    },
+  },
+  props: {
+    useIconSlot: {
+      type: Boolean,
+      default: false,
+    },
+    name: {
+      type: String,
+      default: "",
+    },
+    item: {
+      type: Object,
+      default: () => {
+        return {};
+      },
+    },
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.checkbox {
+  display: flex;
+  align-content: center;
+  align-items: center;
+  padding: 8px 0;
+}
+.custom-icon {
+  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);
+}
+</style>

+ 42 - 0
src/otherPages/exerciseFree/components/m-radio-group.vue

@@ -0,0 +1,42 @@
+<template>
+  <view class="radioGroup">
+    <view @tap.native="changeRadioGroup">
+      <slot></slot>
+    </view>
+  </view>
+</template>
+
+<script>
+export default {
+  data() {
+    return {};
+  },
+  methods: {
+    changeRadioGroup(e) {
+      console.log(e);
+      e.detail = e.target.dataset.item;
+      this.$emit("update:value", e.target.dataset.value);
+      this.$emit("change", e);
+    },
+  },
+  props: {
+    useIconSlot: {
+      type: Boolean,
+      default: false,
+    },
+    name: {
+      type: String,
+      default: "",
+    },
+    value: {
+      type: String,
+      default: "",
+    },
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.radioGroup {
+}
+</style>

+ 62 - 0
src/otherPages/exerciseFree/components/m-radio.vue

@@ -0,0 +1,62 @@
+<template>
+  <view @tap.native="clickRadio" :data-item="item" class="radio">
+    <view :data-item="item" class="custom-icon" v-if="useIconSlot">{{
+      name
+    }}</view>
+    <view :data-item="item" style="width: 8px"></view>
+    <text :data-item="item">{{ item.value }}</text>
+  </view>
+</template>
+
+<script>
+export default {
+  data() {
+    return {};
+  },
+  methods: {
+    stopClick(e) {
+      e.stopPropagation();
+    },
+    clickRadio(e) {
+      console.log(e);
+      this.$emit("clickRadio", e);
+      e.stopPropagation();
+    },
+  },
+  props: {
+    useIconSlot: {
+      type: Boolean,
+      default: false,
+    },
+    name: {
+      type: String,
+      default: "",
+    },
+    item: {
+      type: Object,
+      default: () => {
+        return {};
+      },
+    },
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.radio {
+  display: flex;
+  align-content: center;
+  align-items: center;
+  padding: 8px 0;
+}
+.custom-icon {
+  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);
+}
+</style>

+ 83 - 0
src/otherPages/exerciseFree/components/navBar.vue

@@ -0,0 +1,83 @@
+<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 {
+    font-size: 32rpx;
+    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>

+ 47 - 0
src/otherPages/exerciseFree/components/tabbar.vue

@@ -0,0 +1,47 @@
+<template>
+  <view
+    class="box"
+    :style="{
+      height: 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;
+    padding:0 30rpx;
+    border-top: 2rpx solid #d8d8d8;
+    padding-top: 5rpx;
+
+
+}
+
+
+</style>

+ 762 - 0
src/otherPages/exerciseFree/index.vue

@@ -0,0 +1,762 @@
+<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
+      type="free"
+      :bottomFunc="['previous', 'next', 'score', 'explain', 'selectCatalogue']"
+      :midFunc="['collect', 'readQuestion', 'readQuestionAndAnswer', 'skill']"
+      :trueNum.sync="trueNum"
+      :falseNum.sync="falseNum"
+      :query="query"
+      :problemListIndex.sync="problemListIndex"
+    ></m-do-topic>
+    <!-- <view class="function-list">
+      <div class="function-item">
+        <van-icon name="star-o" size="25px" />
+        <span>收藏</span>
+      </div>
+      <div
+        @click="readQuestion(problemList[problemListIndex].issuemp3)"
+        class="function-item"
+      >
+        <van-icon name="bullhorn-o" size="25px" />
+        <span>读题</span>
+      </div>
+    </view> -->
+
+    <van-overlay
+      @click-overlay="
+        () => {
+          selectProblemListVisible = false;
+        }
+      "
+      :show="selectProblemListVisible"
+    >
+      <view class="select-problem">
+        <view class="problem-index">
+          <view class="problem-header">
+            <view class="problem-header-left">
+              <view class="problem-dui">
+                <icon
+                  class="icon-box-img"
+                  color="#06c05f"
+                  type="success"
+                  size="18"
+                ></icon>
+                <text
+                  style="color: #06c05f; font-size: 14px; margin-left: 8rpx"
+                  >{{ trueNum }}</text
+                >
+              </view>
+              <view class="problem-cuo" style="margin-left: 16rpx">
+                <icon class="icon-box-img" type="clear" size="18"></icon>
+                <text style="color: red; font-size: 14px; margin-left: 8rpx">{{
+                  falseNum
+                }}</text>
+              </view>
+            </view>
+            <view class="problem-header-right">
+              <van-icon size="18px" name="description" />
+              <view style="font-size: 14px; display: flex; align-items: center"
+                >{{ problemListIndex + 1 }}/{{ problemListTotal }}</view
+              >
+            </view>
+          </view>
+          <view class="problem-body">
+            <view class="problem-listBody">
+              <view
+                class="problem-listItem"
+                :key="index"
+                v-for="(item, index) in problemList"
+                :class="{
+                  'problem-listItem_dui':
+                    item.userAnswer.length && item.userAnswer == item.answer,
+                  'problem-listItem_cuo':
+                    item.userAnswer.length && item.userAnswer !== item.answer,
+                }"
+              >
+                {{ index + 1 }}
+              </view>
+            </view>
+          </view>
+          <view class="problem-bottom">
+            <view
+              @click="
+                () => {
+                  selectProblemListVisible = false;
+                }
+              "
+              class="problem-bottom-sure"
+              >确定
+            </view>
+            <view
+              @click="
+                () => {
+                  selectProblemListVisible = false;
+                }
+              "
+              class="problem-bottom-close"
+            >
+              关闭</view
+            >
+          </view>
+        </view>
+      </view>
+    </van-overlay>
+  </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 mRadio from "@/components/m-radio/m-radio.vue";
+import mRadioGroup from "@/components/m-radio-group/m-radio-group.vue";
+import mCheckbox from "@/components/m-checkbox/m-checkbox.vue";
+import mCheckboxGroup from "@/components/m-checkbox-group/m-checkbox-group.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,
+        },
+        {},
+      ],
+      explainJsVisible: false,
+      selectProblemListVisible: false,
+      time: 45 * 60 * 1000,
+      problemListTotal: 1,
+      touchx: 0,
+      touchy: 0,
+      problemList: [
+        {
+          questionType: 2,
+          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: {
+    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.problemList.length - 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.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();
+      }
+    },
+    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;
+  
+  },
+  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}`;
+    },
+  },
+  watch: {
+    problemListIndex: {
+      handler(newValue, oldValue) {},
+      immediate: true,
+    },
+  },
+
+  components: {
+    mDoTopic,
+    navBar,
+    explainJs,
+    tabbar,
+    mRadio,
+    mRadioGroup,
+    mCheckbox,
+    mCheckboxGroup,
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.select-problem {
+  display: flex;
+  width: 100vw;
+  height: 100vh;
+  align-content: flex-end;
+  align-items: flex-end;
+  .problem-index {
+    width: 100vw;
+    height: 650rpx;
+    background: #fff;
+    border-radius: 16rpx;
+    padding-top: 50rpx;
+  }
+  .problem-bottom {
+    width: 100%;
+    display: flex;
+    height: 80rpx;
+    .problem-bottom-sure {
+      width: 50%;
+      height: 100%;
+      border-right: 2rpx solid #d8d8d8;
+      border-top: 2rpx solid #d8d8d8;
+      text-align: center;
+      color: #498ef5;
+      line-height: 80rpx;
+    }
+    .problem-bottom-close {
+      width: 50%;
+      height: 100%;
+      color: red;
+      text-align: center;
+      border-top: 2rpx solid #d8d8d8;
+      line-height: 80rpx;
+    }
+  }
+  .problem-header {
+    display: flex;
+    justify-content: space-between;
+    align-content: center;
+    align-items: center;
+    padding: 0rpx 30rpx;
+    .problem-header-left {
+      display: flex;
+
+      .problem-dui {
+        display: flex;
+        align-content: center;
+        align-items: center;
+      }
+      .problem-cuo {
+        display: flex;
+        align-content: center;
+        align-items: center;
+      }
+    }
+    .problem-header-right {
+      display: flex;
+      align-content: center;
+    }
+  }
+  .problem-body {
+    height: 480rpx;
+    padding-top: 30rpx;
+    overflow-y: scroll;
+
+    .problem-listBody {
+      display: inline-block;
+      overflow: hidden;
+      .problem-listItem {
+        display: inline-block;
+        width: 99rpx;
+        height: 99rpx;
+        line-height: 100rpx;
+        text-align: center;
+        border-radius: 50%;
+        border: 2rpx #d8d8d8 solid;
+        margin-bottom: 15rpx;
+        margin-left: 13rpx;
+        margin-right: 13rpx;
+      }
+      .problem-listItem_dui {
+        background: #01c18d;
+      }
+      .problem-listItem_cuo {
+        background: red;
+      }
+    }
+  }
+}
+.tabbar-item {
+  display: flex;
+  flex-wrap: wrap;
+  justify-content: center;
+  text-align: center;
+  align-content: space-around;
+  align-items: space-around;
+}
+.divider {
+  width: 100%;
+  height: 24rpx;
+  background-color: #f2f3f5;
+}
+.h-full {
+  height: 100%;
+}
+.inline-block {
+  display: inline-block;
+}
+.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>

+ 23 - 0
src/otherPages/exerciseSpecify/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/exerciseSpecify/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/exerciseSpecify/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/exerciseSpecify/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>

+ 681 - 0
src/otherPages/exerciseSpecify/index.vue

@@ -0,0 +1,681 @@
+<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
+      type="specify"
+      :trueNum.sync="trueNum"
+      :falseNum.sync="falseNum"
+      :query="query"
+      :problemListTotal.sync="problemListTotal"
+      :problemListIndex="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,
+        },
+        {},
+      ],
+      explainJsVisible: false,
+      time: 45 * 60 * 1000,
+      problemListTotal: 1,
+      touchx: 0,
+      touchy: 0,
+      problemList: [
+        {
+          questionType: 2,
+          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: {
+    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.problemList.length - 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;
+
+  },
+  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||""
+      }`;
+    },
+  },
+  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>

+ 23 - 0
src/otherPages/exerciseWrong/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/exerciseWrong/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/exerciseWrong/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/exerciseWrong/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>

+ 0 - 1
src/otherPages/specifyExercise/index.vue → src/otherPages/exerciseWrong/index.vue

@@ -4,7 +4,6 @@
     <!-- <view style="text-align:center;">
       <van-count-down :time="time"></van-count-down>
     </view> -->
-    <view class="divider"></view>
     <m-do-topic
       type="wrong"
       :trueNum.sync="trueNum"

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

@@ -9,6 +9,7 @@
       :bottomFunc="['previous', 'next', 'submitExam', 'catalogue']"
       :midFunc="['collect', 'readQuestion', 'readQuestionAndAnswer']"
       :hiddenMode="true"
+      :hiddenAnswer="true"
       :trueNum.sync="trueNum"
       :falseNum.sync="falseNum"
       :query="query"
@@ -187,6 +188,7 @@ export default {
     },
   },
   methods: {
+    
     confirmMult() {
       this.$set(this.problemList[this.problemListIndex], "isCompleted", true);
       if (

+ 47 - 21
src/otherPages/mockExamEnd/index.vue

@@ -30,25 +30,25 @@
       <m-button
         width="180rpx"
         height="60rpx"
-        @click="goWrongPreview"
+        @tap="goExerciseSpecify"
         class="btn1"
         text="错题重做"
       />
       <m-button
         width="180rpx"
         height="60rpx"
-        @click="againTest"
+        @tap="refreshTest"
         class="btn2"
         text="重新测试"
       />
     </div>
   </view>
 </template>
-
 <script>
-import hege from "./hege.png";
-import buhege from "./buhege.png";
-import api from '@/api/index'
+import hege from "@/assets/img/hege.png";
+import buhege from "@/assets/img/buhege.png";
+import api from "@/api/index";
+import utils from "@/utils/index";
 export default {
   data() {
     return {
@@ -58,27 +58,53 @@ export default {
       useTime: "",
       subject: 1,
       query: {},
-      gs:"",
-      gsMap:{
-        xc:"小车",
-        hc:"货车",
-        kc:"客车",
-        mtc:"摩托车"
-      }
-
+      gs: "",
+      gsMap: {
+        xc: "小车",
+        hc: "货车",
+        kc: "客车",
+        mtc: "摩托车",
+      },
     };
   },
+  methods: {
+    refreshTest() {
+      let routes = getCurrentPages();
+      if (routes.length < 2) {
+        uni.showToast({
+          title: "无法重新测试",
+          icon: "fail",
+        });
+        return;
+      }
+      let prePage = routes[routes.length - 2];
+      console.log(prePage);
+      uni.redirectTo({
+        url: decodeURIComponent(prePage.$page.fullPath),
+      });
+    },
+    goExerciseSpecify() {
+      uni.navigateTo({
+        url:
+          "/otherPages/exerciseSpecify/index?" +
+          utils.mapToUrlQuery(this.query),
+      });
+    },
+  },
   onLoad(query) {
+    this.query = query;
+    // console.log(getCurrentPages())
     this.score = query.score;
     this.useTime = query.useTime;
     this.subject = query.subject;
-    this.gs = query.gs
-    api.exam.studentScoreInfo({
-      score:Number(this.score),
-      kskm:this.subject==1?'科目一':'科目四',
-      type:this.gsMap[this.gs]
-    })
-
+    this.gs = query.gs;
+    if (query.type === "exam") {
+      api.exam.studentScoreInfo({
+        score: Number(this.score),
+        kskm: this.subject == 1 ? "科目一" : "科目四",
+        type: this.gsMap[this.gs],
+      });
+    }
   },
 };
 //提交考试成绩

+ 36 - 4
src/pages.json

@@ -188,8 +188,26 @@
           "styles": {}
         },
         {
-          "path": "specifyExercise/index",
-          "styles": {}
+          "path": "exerciseSpecify/index",
+          "style": {}
+        },
+        {
+          "path": "exerciseFree/index",
+          "style": {
+            "navigationBarTitleText":"免费练习"
+          }
+        },
+        {
+          "path": "exerciseWrong/index",
+          "style": {
+            "navigationBarTitleText":"错题练习"
+          }
+        },
+        {
+          "path": "exerciseCollect/index",
+          "style": {
+            "navigationBarTitleText":"收藏题练习"
+          }
         },
         {
           "path": "code/index",
@@ -239,7 +257,14 @@
         },
         {
           "path": "collection/index",
-          "styles": {}
+          "style": {}
+        },
+        {
+          "path": "classifyFree/index",
+          "style": {
+            "navigationBarTitleText": "免费体验",
+            "enablePullDownRefresh": false
+          }
         },
         {
           "path": "buyVip/index",
@@ -268,6 +293,13 @@
             "navigationBarTitleText": "练习",
             "enablePullDownRefresh": false
           }
+        },
+        {
+          "path": "exerciseExam/index",
+          "style": {
+            "navigationBarTitleText": "单选测试",
+            "enablePullDownRefresh": false
+          }
         }
       ]
     }
@@ -404,7 +436,7 @@
       },
       {
         "name": "指定的练习",
-        "path": "otherPages/specifyExercise/index",
+        "path": "otherPages/exerciseSpecify/index",
         "query": "liceCar=1&liceTruck=&liceBus=&liceMoto=&name=%E7%A7%91%E7%9B%AE%E4%B8%80&gs=xc&cert=C1%2FC2%2FC3&vehicle=%E8%BD%BF%E8%BD%A6&subject=1&title=%E7%B2%BE%E9%80%89%E8%80%83%E9%A2%98&sort=3&__id__=1"
       }
     ]

+ 190 - 161
src/pages/carVideo/components/videoListBox.vue

@@ -1,181 +1,210 @@
 <template>
-	<view class="list-box">
-		<van-cell @click='clickCell' :title="carVideoList.chapterName" />
-		<view class="tabs-box">
-			<view class="video-item" @click="gotoPaly(currentItem.list[0])">
-				<view class="image-box">
-					<view class="img-box">
-						<image  class="image"  :src="currentItem.list[0].cover" mode="aspectFill"></image>
-					</view>
-					<image v-if="currentItem.list[0].permission==1" class="img-tip" :src="shikan"></image>
-					<image v-if="currentItem.list[0].permission==2" class="img-tip" :src="vip"></image>
-					<text>{{currentItem.list[0].duration}}</text>
-					<m-icon class="icon" type="bofangshipin"></m-icon>
-				</view>
-			</view>
-			<scroll-view class="tabs-bfc">
-				<view class="tabs">
-					<view class="tab" :class="{'tab-active':active===index}" @click="active=index" v-for="(item,index) in carVideoList.children"
-					 :key='index'>
-						{{item.chapterName}}
-					</view>
-				</view>
-			</scroll-view>
-			
-		</view>
-	</view>
+  <view class="list-box">
+    <van-cell @click="clickCell" :title="carVideoList.chapterName" />
+    <view class="tabs-box">
+      <view class="video-item" @click="gotoPaly(currentItem.list[0])">
+        <view class="image-box">
+          <view class="img-box">
+            <image
+              class="image"
+              :src="currentItem.list[0].cover"
+              mode="aspectFill"
+            ></image>
+          </view>
+          <image
+            v-if="currentItem.list[0].permission == 1"
+            class="img-tip"
+            :src="shikan"
+          ></image>
+          <image
+            v-if="currentItem.list[0].permission == 2"
+            class="img-tip"
+            :src="vip"
+          ></image>
+          <text>{{ currentItem.list[0].duration }}</text>
+          <m-icon class="icon" type="bofangshipin"></m-icon>
+        </view>
+      </view>
+	  <!-- catch阻止事件冒泡,这样让不会让上层发生滑动 -->
+      <view catchtouchmove="scrollTabsfc" class="tabs-bfc">
+        <scroll-view
+		  :hover-stop-propagation="true"
+          :scroll-x="true"
+          catchscrolltoupper="scrollTabsfc"
+          catchscrolltolower="scrollTabsfc"
+          class="tabs"
+        >
+          <view
+            class="tab"
+            :class="{ 'tab-active': active === index }"
+            @click="active = index"
+            v-for="(item, index) in carVideoList.children"
+            :key="index"
+          >
+            {{ item.chapterName }}
+          </view>
+        </scroll-view>
+      </view>
+    </view>
+  </view>
 </template>
 
 <script>
 import shikan from "@/assets/img/shikan.png";
 import vip from "@/assets/img/vip.png";
-	export default {
-		name: "video-listBox",
-		props: {
-			carVideoList: {
-				type: Object,
-				default: ()=>{
-					return {}
-				}
-			},
-		},
-		data() {
-			return {
-				active: 0,
-				shikan,
-				vip
-			};
-		},
-		computed: {
-			currentItem() {
-				console.log(this.carVideoList,'this.carVideoList')
-				return this.carVideoList.children[this.active]
-			}
-		},
-		methods: {
-			gotoPaly(item) {
-				this.$utils.route.goPage('/pages/carVideo/play', null, {
-					carVideoItem: item
-				})
-			}
-		}
-	}
+export default {
+  name: "video-listBox",
+  props: {
+    carVideoList: {
+      type: Object,
+      default: () => {
+        return {};
+      },
+    },
+  },
+  data() {
+    return {
+      active: 0,
+      shikan,
+      vip,
+    };
+  },
+  computed: {
+    currentItem() {
+      console.log(this.carVideoList, "this.carVideoList");
+      return this.carVideoList.children[this.active];
+    },
+  },
+  methods: {
+    scrollTabsfc(e) {
+      e.stopPropagation();
+
+      e.preventDefault();
+      console.log(e);
+    },
+    gotoPaly(item) {
+      this.$utils.route.goPage("/pages/carVideo/play", null, {
+        carVideoItem: item,
+      });
+    },
+  },
+};
 </script>
 
 <style lang="scss" scoped>
-	.list-box {
-		margin-bottom: 10px;
-		background-color: #FFFFFF;
+.list-box {
+  margin-bottom: 10px;
+  background-color: #ffffff;
+
+  .tabs-box {
+    padding: 5px 15px;
+    border-radius: 10px;
+    overflow: hidden;
+    width: 100%;
+  }
+
+  .tabs-bfc {
+    overflow: auto;
+  }
 
-		.tabs-box {
-			padding: 5px 15px;
-			border-radius: 10px;
-			overflow: hidden;
-			width: 100%;
-		}
-		
-		.tabs-bfc{
-			overflow: auto;
-		}
-		
-		.tabs {
-			background-color: #0A1A33;
-			overflow: auto;
-			white-space: nowrap;
+  .tabs {
+    background-color: #0a1a33;
+    overflow-x: scroll;
+    white-space: nowrap;
 
-			.tab {
-				display: inline-flex;
-				justify-content: center;
-				align-items: center;
-				text-align: center;
-				width: auto;
-				height: 37px;
-				background: #5C6066;
-				border-radius: 3px;
-				margin: 3px;
-				font-size: 11px;
-				font-family: PingFang SC;
-				font-weight: 500;
-				color: #FFFFFF;
-				letter-spacing: 0.2800000011920929px;
-				padding: 0 30rpx;
-			}
+    .tab {
+      display: inline-flex;
+      justify-content: center;
+      align-items: center;
+      text-align: center;
+      width: auto;
+      height: 37px;
+      background: #5c6066;
+      border-radius: 3px;
+      margin: 3px;
+      font-size: 11px;
+      font-family: PingFang SC;
+      font-weight: 500;
+      color: #ffffff;
+      letter-spacing: 0.2800000011920929px;
+      padding: 0 30rpx;
+    }
 
-			.tab-active {
-				background-color: #498EF5;
-				position: relative;
-				&::after{
-					content: '';
-					width: 5px;
-					height: 5px;
-					position: absolute;
-					top: 0;
-					left: 50%;
-					transform: translate(-50%,-50%) rotate(45deg);
-					background-color: #498EF5;
-					z-index: 1;
-				}
-			}
-		}
+    .tab-active {
+      background-color: #498ef5;
+      position: relative;
+      &::after {
+        content: "";
+        width: 5px;
+        height: 5px;
+        position: absolute;
+        top: 0;
+        left: 50%;
+        transform: translate(-50%, -50%) rotate(45deg);
+        background-color: #498ef5;
+        z-index: 1;
+      }
+    }
+  }
 
-		.video-item {
-			position: relative;
-			background-color: #ffffff;
-			display: flex;
-			flex-direction: column;
-			justify-content: center;
-			text-align: center;
+  .video-item {
+    position: relative;
+    background-color: #ffffff;
+    display: flex;
+    flex-direction: column;
+    justify-content: center;
+    text-align: center;
 
-			.image-box {
-				position: relative;
-				.img-tip{
-					position: absolute;
-					right: 10rpx;
-					top: 10rpx;
-					width: 50rpx;
-					height: 28rpx;
-				}
+    .image-box {
+      position: relative;
+      .img-tip {
+        position: absolute;
+        right: 10rpx;
+        top: 10rpx;
+        width: 50rpx;
+        height: 28rpx;
+      }
 
-				.img-box {
-					width: 100%;
-					padding-bottom: 64%;
-					position: relative;
+      .img-box {
+        width: 100%;
+        padding-bottom: 64%;
+        position: relative;
 
-					.image {
-						position: absolute;
-						left: 0;
-						top: 0;
-						width: 100%;
-						height: 100%;
-					}
-				}
+        .image {
+          position: absolute;
+          left: 0;
+          top: 0;
+          width: 100%;
+          height: 100%;
+        }
+      }
 
-				text {
-					position: absolute;
-					color: red;
-					right: 8rpx;
-					bottom: 8rpx;
-					color: #8A9099;
-				}
+      text {
+        position: absolute;
+        color: red;
+        right: 8rpx;
+        bottom: 8rpx;
+        color: #8a9099;
+      }
 
-				.icon {
-					width: 44rpx;
-					position: absolute;
-					left: 50%;
-					top: 50%;
-					transform: translate(-50%, -50%);
-				}
-			}
+      .icon {
+        width: 44rpx;
+        position: absolute;
+        left: 50%;
+        top: 50%;
+        transform: translate(-50%, -50%);
+      }
+    }
 
-			text {
-				font-size: 30rpx;
-				font-weight: 400;
-				line-height: 39rpx;
-				color: #0F0404;
-				white-space: nowrap;
-				text-overflow: ellipsis;
-				overflow: hidden;
-			}
-		}
-	}
+    text {
+      font-size: 30rpx;
+      font-weight: 400;
+      line-height: 39rpx;
+      color: #0f0404;
+      white-space: nowrap;
+      text-overflow: ellipsis;
+      overflow: hidden;
+    }
+  }
+}
 </style>

+ 4 - 4
src/pages/carVideo/index.vue

@@ -365,8 +365,8 @@ export default {
       },
       {
         img: "https://t1-1305573081.file.myqcloud.com/wxapp/static/imgs/home/RealExaminationRoomSimulation@2x.png",
-        text: "真实模拟考试",
-        path: "/pages/mockExam/begin",
+        text: "免费试用",
+        path: "/otherPages/classifyFree/index",
       },
 
       {
@@ -423,8 +423,8 @@ export default {
       },
       {
         img: "https://t1-1305573081.file.myqcloud.com/wxapp/static/imgs/home/RealExaminationRoomSimulation@2x.png",
-        text: "真实模拟考试",
-        path: "/pages/mockExam/begin",
+        text: "免费试用",
+       path: "/otherPages/classifyFree/index",
       },
 
       {

+ 1 - 1
src/pages/carVideo/play.vue

@@ -40,7 +40,7 @@
         v-if="!videoVisible && carVideoItem.permission == 2"
       >
         <text class="video-tip-text1" style="font-size: 32rpx"
-          >只有vip可以观看</text
+          >开通会员即可观看该视频</text
         >
         <button @click="goBuyVip" class="video-tip-open">立即开通</button>
         <image