Explorar o código

错题回顾页面添加

JXDS18FUJT %!s(int64=2) %!d(string=hai) anos
pai
achega
f7265c4b44

+ 44 - 9
src/api/question/question.ts

@@ -47,11 +47,11 @@ export default {
         })
     },
     //合并本机和云端的错题
-    questionWrongWrongs(data:{
-        km:number
-        wrongs:{id:number,timestamp:number}[]
+    questionWrongWrongs(data: {
+        km: number
+        wrongs: { id: number, timestamp: number }[]
 
-    }){
+    }) {
         return request({
             data,
             url: "/question/wrong/wrongs",
@@ -59,10 +59,22 @@ export default {
 
         })
     },
+    //合并本机和云端错题(三力测试)
+    questionthreeWrongWrongs(data: {
+        wrongs: { id: number, timestamp: number }[]
+
+    }) {
+        return request({
+            data,
+            url: "/question/threeWrong/wrongs",
+            method: 'delete',
+
+        })
+    },
     //获取用户的错题
-    questionWrongWrongByUser(params:{
-        km:number
-    }){
+    questionWrongWrongByUser(params: {
+        km: number
+    }): Promise<{data:{ id: number, timestamp: number }[]}> {
         return request({
             params,
             url: "/question/wrong/wrongByUser",
@@ -70,12 +82,35 @@ export default {
 
         })
     },
-    //恢复云端错题到本机(根据用户获取错题)
-    questionThreeWrongWrongByUser(){
+    //(三力测试)恢复云端错题到本机(根据用户获取错题)
+    questionThreeWrongWrongByUser(): Promise<{data:{ id: number, timestamp: number }[]}> {
         return request({
             url: "/question/threeWrong/wrongByUser",
             method: 'get',
 
+        })
+    },
+    //获取题库详细信息批量取题
+    questionInfoGetQuestionInfoByIds(params: {
+        ids: string
+    }): Promise<questionApi.selectTestK14QuestionInfoList> {
+        return request({
+            url: "/pc/question/info/getQuestionInfoByIds",
+            method: 'get',
+            params
+
+        })
+
+    },
+    //(三力测试)获取题库详细信息批量取题
+    threeForceGetThreeForceListIds(params: {
+        ids: string
+    }): Promise<questionApi.selectTestK14QuestionInfoList>{
+        return request({
+            url: "/three/force/getThreeForceListIds",
+            method: 'get',
+            params
+
         })
     }
 }

+ 12 - 1
src/api/three/three.ts

@@ -14,6 +14,17 @@ export default {
             url: "/three/force/selectTestQuestionInfoList",
             method: 'get'
         })
-    }
+    },
+        //(三力测试)获取题库详细信息批量取题
+        threeForceGetThreeForceListIds(params: {
+            ids: string
+        }): Promise<threeApi.threeForceList>{
+            return request({
+                url: "/three/force/getThreeForceListIds",
+                method: 'get',
+                params
+    
+            })
+        }
 
 }

+ 25 - 5
src/hooks/exam/driverExam.ts

@@ -747,12 +747,32 @@ export const useDriverExam = (requestFn: Promise<openApi.selectFreeQuestionInfoR
         wrongListRes.push(String(userAnswerIndex))
       }
     })
-    window.sessionStorage.setItem('driverExam_temp_wrong_list', JSON.stringify(wrongList))
+    //保存临时错题
+    window.sessionStorage.setItem('driverExam_temp_wrong_list', JSON.stringify(wrongList || '[]'))
+    //同步全部的错题
+    api.question.questionWrongWrongs({
+      km: Number(route.query.subject),
+      wrongs: wrongList.map(item => {
+        return {
+          id: item.id,
+          timestamp: + new Date()
+        }
+      })
+
+    }).then(res => {
+      if (Number(route.query.subject == '1')) {
+        store.dispatch('AsyncDriver1WrongList')
+      }
+      if (Number(route.query.subject == '4')) {
+        store.dispatch('AsyncDriver4WrongList')
+      }
+
+    })
     router.push({
-      path:'/driverExamAnaly',
-      query:{
-        wrongListRes:JSON.stringify(wrongListRes),
-        score:score
+      path: '/driverExamAnaly',
+      query: {
+        wrongListRes: JSON.stringify(wrongListRes),
+        score: score
       }
     })
 

+ 14 - 0
src/hooks/exam/threeExam.ts

@@ -6,6 +6,7 @@ import { useStore } from "vuex";
 import { message } from "ant-design-vue";
 import { threeApi } from "@/api/three/type";
 import router from "@/router";
+import api from "@/api";
 export const useThreeExam = (requestFn: Promise<threeApi.threeForceList>, config = {
     countDown: true,
     autoAnswer: true
@@ -625,6 +626,19 @@ export const useThreeExam = (requestFn: Promise<threeApi.threeForceList>, config
         })
         //保存临时错题
         window.sessionStorage.setItem('threeExam_temp_wrong_list',JSON.stringify(wrongList))
+        //同步全部的错题
+        api.question.questionthreeWrongWrongs({
+       
+             wrongs:wrongList.map(item=>{
+              return {
+                id:item.id,
+                timestamp:+ new Date()
+              }
+             })
+          
+          }).then(res=>{
+           store.dispatch('AsyncThreeWrongList')
+          })
         router.push({
             path:'/threeExamAnaly',
             query:{

+ 8 - 0
src/router/index.ts

@@ -50,6 +50,14 @@ const routes: Array<RouteRecordRaw> = [
     path: '/markLine',
     component: () => import('../views/markLine/index.vue')
   },
+  {
+    path: '/reviewDriverError',
+    component: () => import('../views/reviewDriverError/index.vue')
+  },
+  {
+    path: '/reviewThreeError',
+    component: () => import('../views/reviewThreeError/index.vue')
+  },
   {
     path: '/home',
     name: 'home',

+ 20 - 0
src/store/index.ts

@@ -1,3 +1,4 @@
+import api from '@/api';
 import { createStore } from 'vuex'
 import createPersistedState from "vuex-persistedstate";
 export default createStore({
@@ -28,6 +29,25 @@ export default createStore({
   actions: {
     LoginOut() {
       localStorage.setItem('token', '')
+    },
+    AsyncDriver4WrongList(){
+      api.question.questionWrongWrongByUser({
+        km:4
+      }).then(res=>{
+        window.localStorage.setItem('driverExam4_local_wrong_list',JSON.stringify(res.data||'[]'))
+      })
+    },
+    AsyncDriver1WrongList() {
+      api.question.questionWrongWrongByUser({
+        km:1
+      }).then(res=>{
+        window.localStorage.setItem('driverExam1_local_wrong_list',JSON.stringify(res.data||'[]'))
+      })
+    },
+    AsyncThreeWrongList(){
+      api.question.questionThreeWrongWrongByUser().then(result=>{
+        window.localStorage.setItem('threeExam_local_wrong_list',JSON.stringify(result.data||'[]'))
+    })
     }
   },
   modules: {

+ 25 - 3
src/views/driverExamAnaly/index.vue

@@ -34,7 +34,11 @@
           :key="index"
           class="round10 pt30 pr30 pl30 pb30 text-left round10 gray-border mb20"
         >
-          <div>{{ index + 1 }}、{{ list[index].issue }}</div>
+          <div
+           
+          >
+            {{ index + 1 }}、{{ list[index].issue }}
+          </div>
           <div
             :class="{
               'text-red-500': userAnswerList[index] == '0',
@@ -42,8 +46,20 @@
             v-for="(_item, _index) in list[index].optsArr"
             :key="_index"
           >
-            <span v-if="userAnswerList[index] == _index + 1&&userAnswerList[index] != '0'">x</span>
-            <span v-if="userAnswerList[index] != _index + 1&&userAnswerList[index] != '0'">√</span>
+            <span
+              v-if="
+                userAnswerList[index].includes(_index + 1 + '') &&
+                userAnswerList[index] != '0'
+              "
+              >x</span
+            >
+            <span
+              v-if="
+                userAnswerList[index].includes(_index + 1 + '') &&
+                userAnswerList[index] != '0'
+              "
+              >√</span
+            >
             {{ switchIndexBySelect(_index) }} . {{ _item }}
           </div>
 
@@ -135,4 +151,10 @@ export default defineComponent({
 .bg-primary-yellow {
   background: #f9de5b;
 }
+.yes::before {
+  content: "√";
+}
+.no::before {
+  content: "ⅹ";
+}
 </style>

+ 8 - 5
src/views/login/index.vue

@@ -95,7 +95,8 @@ import api from "@/api";
 import router from "@/router";
 import Cookies from "js-cookie";
 import { defineComponent, reactive, toRefs } from "vue";
-import { encrypt, decrypt } from '@/utils/jsencrypt'
+import { encrypt, decrypt } from "@/utils/jsencrypt";
+import store from "@/store";
 export default defineComponent({
   setup() {
     const state = reactive({
@@ -114,7 +115,7 @@ export default defineComponent({
     };
   },
   mounted() {
-    this.getCookie()
+    this.getCookie();
     this.getCaptchaImage();
   },
   methods: {
@@ -123,8 +124,8 @@ export default defineComponent({
       const password = Cookies.get("password");
       const rememberMe = Cookies.get("rememberMe");
       this.loginForm = {
-        uuid:"",
-        code:'',
+        uuid: "",
+        code: "",
         username: username === undefined ? this.loginForm.username : username,
         password:
           password === undefined ? this.loginForm.password : decrypt(password),
@@ -136,6 +137,9 @@ export default defineComponent({
       api.login.login(this.loginForm).then((res) => {
         window.localStorage.setItem("token", res.data.token);
         router.push("/home/sysconfig");
+        store.dispatch("AsyncDriver4WrongList");
+        store.dispatch("AsyncDriver1WrongList");
+        store.dispatch("AsyncThreeWrongList")
         console.log(res.data.token);
       });
     },
@@ -316,5 +320,4 @@ export default defineComponent({
 .bg-primary-darkyellow {
   background-color: #f2c900;
 }
-
 </style>

+ 353 - 0
src/views/reviewDriverError/index.vue

@@ -0,0 +1,353 @@
+<template>
+  <div class="bg-gray w-full min-h-screen">
+    <div class="pt30 pr30 pl30 pb30 w-full">
+      <div class="w-full gray-border flex flex-wrap">
+        <div class="pt30 pl30 text-left font26 pb50 bg-white flex-1">
+          <span
+            >{{ listIndex + 1 }}.<span v-html="issueAutoRead()"></span
+          ></span>
+          <div v-if="list[listIndex].questionType === 1">
+            <div v-for="(item, index) in list[listIndex].optsArr" :key="index">
+              {{ switchIndexBySelect(index) }}.{{
+                item == "√" ? "正确" : "错误"
+              }}
+            </div>
+          </div>
+          <div v-if="list[listIndex].questionType !== 1">
+            <div v-for="(item, index) in list[listIndex].optsArr" :key="index">
+              {{ switchIndexBySelect(index) }}.{{ item }}
+            </div>
+          </div>
+
+          <div
+            v-if="list[listIndex].isComplete && !list[listIndex].isError"
+            class="inline-block pl15 pr5 mt15"
+            style="background-color: #d9ffeb"
+          >
+            <img
+              class="inline-block w42 h42"
+              src="@/assets/img/studySkill/smile_express.png"
+            />
+            <span style="color: #21a65f" class="lh60"> 恭喜!回答正确!</span>
+          </div>
+          <div
+            v-if="list[listIndex].isComplete && list[listIndex].isError"
+            class="inline-block pl15 pr15 mt15"
+            style="background-color: rgba(255, 220, 217, 1)"
+          >
+            <img
+              class="inline-block w42 h42"
+              src="@/assets/img/studySkill/cry_express.png"
+            />
+            <span
+              v-if="list[listIndex].questionType !== 3"
+              style="color: rgba(239, 54, 41, 1)"
+              class="lh60"
+            >
+              正确答案是:{{
+                switchAnswerBySelect(list[listIndex].answer, listIndex)
+              }}</span
+            >
+            <span
+              v-if="list[listIndex].questionType === 3"
+              style="color: rgba(239, 54, 41, 1)"
+              class="lh60"
+            >
+              正确答案是:{{
+                switchAnswerBySelect(
+                  list[listIndex].answer.split("-"),
+                  listIndex
+                )
+              }}</span
+            >
+          </div>
+          <div>
+            <div
+              @click="playIssueAudio"
+              class="mt30 w88 items-center bottom-button flex h40 justify-center"
+            >
+              <img
+                class="w18 h18 inline-block mr10"
+                src="@/assets/img/studySkill/voice_icon.png"
+              />
+              <span class="font16">读题</span>
+            </div>
+          </div>
+          <div v-if="list[listIndex].questionType === 1" class="flex mt15">
+            <div
+              @click="setUserAnswerAndRes(item)"
+              v-for="(item, index) in list[listIndex].optsArr"
+              :key="index"
+              class="w57 lh46 bottom-button mr15"
+            >
+              {{ item }}
+            </div>
+          </div>
+          <div v-if="list[listIndex].questionType == 2" class="flex mt15">
+            <div
+              @click="setUserAnswerAndRes(item)"
+              v-for="(item, index) in list[listIndex].optsArr"
+              :key="index"
+              class="w57 lh46 bottom-button mr15"
+            >
+              {{ switchIndexBySelect(index) }}
+            </div>
+          </div>
+        </div>
+        <div class="w430 pr30 flex items-center bg-white">
+          <img
+            class="w400"
+            v-if="list[listIndex].image"
+            :src="list[listIndex].image"
+          />
+        </div>
+      </div>
+      <div class="w-full pt30">
+        <div class="w1200 flex justify-between mr-auto ml-auto">
+          <div
+            @click="preProblem()"
+            @keydown.up="preProblem()"
+            class="w120 lh46 bottom-button lh46"
+          >
+            上一题
+          </div>
+          <div
+            @click="nextProblem()"
+            @keydown.down="nextProblem()"
+            class="w120 lh46 bottom-button lh46"
+          >
+            下一题
+          </div>
+          <div
+            @click="
+              () => {
+                alertVisible = true;
+              }
+            "
+            class="w120 lh46 bottom-button lh46"
+          >
+            本题解析
+          </div>
+          <div @click="playIssueAudio()" class="w120 lh46 bottom-button lh46">
+            语音播报
+          </div>
+          <div class="w120 lh46 bottom-button lh46">不设为错题</div>
+          <div
+            @click="
+              () => {
+                dialogVisible = true;
+              }
+            "
+            class="w120 lh46 bottom-button lh46"
+          >
+            交卷
+          </div>
+        </div>
+      </div>
+      <div class="w-full mt20">
+        <div
+          class="flex w1200 mr-auto ml-auto h30 items-center content-center justify-around"
+        >
+          <div class="flex items-center">
+            <div class="pr2 pl2">转到</div>
+            <input
+              class="outline-none input-border w35 h30 text-center"
+              type="text"
+              :value="listPageNum"
+            />
+            <div class="pr2 pl2">题</div>
+          </div>
+
+          <div>
+            共 <span class="font-semibold">{{ list.length }}</span> 题
+          </div>
+          <div class="align-baseline">
+            <input
+              v-model="sysConfig.autoNext"
+              class=""
+              @change="changeSysConfig"
+              type="checkbox"
+            />
+            <span>答对自动跳转到下一题</span>
+          </div>
+          <div>
+            <div class="mr15 inline-block tracking5">
+              答对<span style="color: #21a65f">{{ trueNum }}</span
+              >题
+            </div>
+            <div class="inline-block tracking5">
+              答错<span style="color: #ef3629">{{ falseNum }}</span
+              >题
+            </div>
+          </div>
+          <div class=""><span class="text-black font16">正确率100%</span></div>
+          <div class="">
+            <span class="text-black font16"
+              >进度{{
+                fixedNumber(((trueNum + falseNum) * 100) / list.length, 2)
+              }}%</span
+            >
+          </div>
+          <div class="flex items-center content-center">
+            <div class="mr15">
+              <input
+                class=""
+                v-model="sysConfig.autoRead"
+                type="checkbox"
+                @change="changeSysConfig"
+              />
+              <span>自动播放</span>
+            </div>
+            <div>
+              <input
+                class=""
+                v-model="sysConfig.autoRed"
+                type="checkbox"
+                @change="changeSysConfig"
+              />
+              <span>提示红字</span>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+    <mProblemAlert
+      v-model:visible="alertVisible"
+      :content="list[listIndex].explainJs"
+      title="题目解析"
+    ></mProblemAlert>
+    <mProblemDialog
+      v-model:visible="dialogVisible"
+      title="提示"
+      content="是否真的要交卷(按确定键交卷,按取消键继续答题)"
+    ></mProblemDialog>
+  </div>
+</template>
+
+<script lang="ts">
+import { defineComponent, ref } from "vue";
+import api from "@/api";
+import { useRoute } from "vue-router";
+import { useDriverExam } from "@/hooks/exam/driverExam";
+import mProblemAlert from "@/components/mProblemAlert/index.vue";
+import mProblemDialog from "@/components/mProblemDialog/index.vue";
+import { useStore } from "vuex";
+import { message } from "ant-design-vue";
+import { Item } from "ant-design-vue/es/menu";
+export default defineComponent({
+  name: "studySkill",
+  setup() {
+    let route = useRoute();
+    let store = useStore();
+    let sysConfig = ref({
+      autoRed: store.state.sysConfig.autoRed,
+      autoRead: store.state.sysConfig.autoRead,
+      autoNext: store.state.sysConfig.autoNext,
+    });
+    const changeSysConfig = (event: any) => {
+      console.log(sysConfig.value);
+      store.commit("SET_SYSCONFIG", sysConfig.value);
+    };
+    const fixedNumber = (decimal: number, digit: number) => {
+      return decimal.toFixed(digit);
+    };
+    let wrongList = JSON.parse(window.localStorage.getItem(route.query.subject=='4'?'driverExam4_local_wrong_list':'driverExam1_local_wrong_list')||'[]') as {id:number,timestamp:number}[]
+
+  
+    return {
+      sysConfig,
+      alertVisible: ref(false),
+      dialogVisible: ref(false),
+      ...useDriverExam(
+        api.question.questionInfoGetQuestionInfoByIds({
+        ids:wrongList.map(item=>item.id).join(',')
+        }),
+        {
+          autoAnswer: false,
+          countDown: false,
+        }
+      ),
+      changeSysConfig,
+      fixedNumber,
+    };
+  },
+  components: {
+    mProblemAlert,
+    mProblemDialog,
+  },
+});
+</script>
+
+<style scoped>
+input[type="checkbox"] {
+  margin-right: 5px;
+
+  cursor: pointer;
+
+  font-size: 14px;
+
+  width: 15px;
+
+  height: 12px;
+
+  position: relative;
+}
+
+input[type="checkbox"]:after {
+  position: absolute;
+
+  width: 16px;
+
+  height: 16px;
+
+  top: 0;
+  left: 0px;
+
+  content: " ";
+
+  background-color: #f9de5b;
+
+  color: #fff;
+
+  display: inline-block;
+
+  visibility: visible;
+
+  border-radius: 3px;
+}
+
+input[type="checkbox"]:checked:after {
+  width: 16px;
+  height: 16px;
+  background-size: 100%;
+  background-image: url("./../../assets/img/login/checked_icon.png");
+}
+.input-border {
+  border: 1px solid #707070;
+}
+.bg-gray {
+  background: #f5f5f5;
+}
+.gray-border {
+  border: 1px solid #d8d8d8;
+}
+.bg-primary-yellow {
+  background: #f9de5b;
+}
+.bottom-button {
+  text-align: center;
+  border: 1px solid #f9de5b;
+  cursor: pointer;
+}
+.bottom-button:focus {
+  background: #f9de5b;
+  border: 1px solid #f9de5b;
+  outline: none;
+}
+.bottom-button:hover {
+  background: #fff7cc;
+}
+.w1200 {
+  width: 1200px;
+}
+</style>

+ 422 - 0
src/views/reviewThreeError/index.vue

@@ -0,0 +1,422 @@
+<template>
+  <div class="bg-gray w-full min-h-screen">
+    <div class="pt30 pr30 pl30 pb30 w-full">
+      <div class="w-full gray-border flex flex-wrap">
+        <div class="pt30 pl30 text-left font26 pb50 bg-white flex-1">
+          <span
+            >{{ listIndex + 1 }}.<span v-html="list[listIndex].question"></span
+          ></span>
+          <div v-if="list[listIndex].type !== 1" class="mt30 text-left pl20">
+            <div class="" v-if="list[listIndex]['an1']">
+              A.&nbsp;&nbsp;{{ list[listIndex]["an1"] }}
+            </div>
+            <div class="" v-if="list[listIndex]['an2']">
+              B.&nbsp;&nbsp;{{ list[listIndex]["an2"] }}
+            </div>
+            <div class="" v-if="list[listIndex]['an3']">
+              C.&nbsp;&nbsp;{{ list[listIndex]["an3"] }}
+            </div>
+            <div class="" v-if="list[listIndex]['an4']">
+              D.&nbsp;&nbsp;{{ list[listIndex]["an4"] }}
+            </div>
+          </div>
+
+          <div
+            v-if="list[listIndex].isComplete && !list[listIndex].isError"
+            class="inline-block pl15 pr5 mt15"
+            style="background-color: #d9ffeb"
+          >
+            <img
+              class="inline-block w42 h42"
+              src="@/assets/img/studySkill/smile_express.png"
+            />
+            <span style="color: #21a65f" class="lh60"> 恭喜!回答正确!</span>
+          </div>
+          <div
+            v-if="list[listIndex].isComplete && list[listIndex].isError"
+            class="inline-block pl15 pr15 mt15"
+            style="background-color: rgba(255, 220, 217, 1)"
+          >
+            <img
+              class="inline-block w42 h42"
+              src="@/assets/img/studySkill/cry_express.png"
+            />
+            <span
+              v-if="list[listIndex].type !== 3"
+              style="color: rgba(239, 54, 41, 1)"
+              class="lh60"
+            >
+              正确答案是:{{
+                switchPageNumBySelect(list[listIndex].answertrue)
+              }}</span
+            >
+           
+          </div>
+          <div>
+            <div
+              @click="playIssueAudio"
+              class="mt30 w88 items-center bottom-button flex h40 justify-center"
+            >
+              <img
+                class="w18 h18 inline-block mr10"
+                src="@/assets/img/studySkill/voice_icon.png"
+              />
+              <span class="font16">读题</span>
+            </div>
+          </div>
+          <div class="flex cursor-pointer mt20">
+            <div
+              v-if="list[listIndex]['an1']"
+              @click="
+                list[listIndex].isComplete
+                  ? ''
+                  : setUserAnswerAndRes(list[listIndex]['an1'])
+              "
+              class="w46 lh46 h46 answer-select font20 font-bold mr15 flex-grow-0 bottom-button"
+            >
+              <span v-if="list[listIndex].type == 1">{{ "√" }}</span>
+              <span v-if="list[listIndex].type !== 1">{{
+                switchIndexBySelect(0)
+              }}</span>
+            </div>
+
+            <div
+              v-if="list[listIndex]['an2']"
+              @click="
+                list[listIndex].isComplete
+                  ? ''
+                  : setUserAnswerAndRes(list[listIndex]['an2'])
+              "
+              class="w46 lh46 h46 answer-select font20 font-bold mr15 flex-grow-0 bottom-button"
+            >
+              <span v-if="list[listIndex].type == 1">{{ "×" }}</span>
+              <span v-if="list[listIndex].type !== 1">{{
+                switchIndexBySelect(1)
+              }}</span>
+            </div>
+            <div
+              v-if="list[listIndex]['an3']"
+              @click="
+                list[listIndex].isComplete
+                  ? ''
+                  : setUserAnswerAndRes(list[listIndex]['an3'])
+              "
+              class="w46 lh46 h46 answer-select font20 font-bold mr15 flex-grow-0 bottom-button"
+            >
+              <span v-if="list[listIndex].type == 1">{{ "×" }}</span>
+              <span v-if="list[listIndex].type !== 1">{{
+                switchIndexBySelect(2)
+              }}</span>
+            </div>
+
+            <div
+              v-if="list[listIndex]['an4']"
+              @click="
+                list[listIndex].isComplete
+                  ? ''
+                  : setUserAnswerAndRes(list[listIndex]['an4'])
+              "
+              class="w46 lh46 h46 answer-select font20 font-bold mr15 flex-grow-0 bottom-button"
+            >
+              <span v-if="list[listIndex].type == 1">{{ "×" }}</span>
+              <span v-if="list[listIndex].type !== 1">{{
+                switchIndexBySelect(3)
+              }}</span>
+            </div>
+          </div>
+          <div v-if="list[listIndex].questionType === 1" class="flex mt15">
+            <div
+              @click="setUserAnswerAndRes(item)"
+              v-for="(item, index) in list[listIndex].optsArr"
+              :key="index"
+              class="w57 lh46 bottom-button mr15"
+            >
+              {{ item }}
+            </div>
+          </div>
+          <div v-if="list[listIndex].questionType !== 1" class="flex mt15">
+            <div
+              @click="setUserAnswerAndRes(item)"
+              v-for="(item, index) in list[listIndex].optsArr"
+              :key="index"
+              class="w57 lh46 bottom-button mr15"
+            >
+              {{ switchIndexBySelect(index) }}
+            </div>
+          </div>
+        </div>
+        <div class="w430 pr30 flex items-center bg-white">
+          <img
+            class="w400"
+            v-if="isImageUrl(list[listIndex].mediaUrl)"
+            :src="list[listIndex].mediaUrl"
+          />
+          <video
+            class="w400"
+            autoplay
+            loop
+            v-if="isVideoUrl(list[listIndex].mediaUrl)"
+            :src="list[listIndex].mediaUrl"
+          ></video>
+        </div>
+      </div>
+      <div class="w-full pt30">
+        <div class="w1200 flex justify-between mr-auto ml-auto">
+          <div
+            @click="preProblem()"
+            @keydown.up="preProblem()"
+            class="w120 lh46 bottom-button lh46"
+          >
+            上一题
+          </div>
+          <div
+            @click="nextProblem()"
+            @keydown.down="nextProblem()"
+            class="w120 lh46 bottom-button lh46"
+          >
+            下一题
+          </div>
+          <div
+            @click="
+              () => {
+                alertVisible = true;
+              }
+            "
+            class="w120 lh46 bottom-button lh46"
+          >
+            本题解析
+          </div>
+          <div @click="playIssueAudio()" class="w120 lh46 bottom-button lh46">
+            语音播报
+          </div>
+          <div class="w120 lh46 bottom-button lh46">不设为错题</div>
+          <div
+            @click="
+              () => {
+                dialogVisible = true;
+              }
+            "
+            class="w120 lh46 bottom-button lh46"
+          >
+            交卷
+          </div>
+        </div>
+      </div>
+      <div class="w-full mt20">
+        <div
+          class="flex w1200 mr-auto ml-auto h30 items-center content-center justify-around"
+        >
+          <div class="flex items-center">
+            <div class="pr2 pl2">转到</div>
+            <input
+              class="outline-none input-border w35 h30 text-center"
+              type="text"
+              :value="listPageNum"
+            />
+            <div class="pr2 pl2">题</div>
+          </div>
+
+          <div>
+            共 <span class="font-semibold">{{ list.length }}</span> 题
+          </div>
+          <div class="align-baseline">
+            <input
+              v-model="sysConfig.autoNext"
+              class=""
+              @change="changeSysConfig"
+              type="checkbox"
+            />
+            <span>答对自动跳转到下一题</span>
+          </div>
+          <div>
+            <div class="mr15 inline-block tracking5">
+              答对<span style="color: #21a65f">{{ trueNum }}</span
+              >题
+            </div>
+            <div class="inline-block tracking5">
+              答错<span style="color: #ef3629">{{ falseNum }}</span
+              >题
+            </div>
+          </div>
+          <div class=""><span class="text-black font16">正确率100%</span></div>
+          <div class="">
+            <span class="text-black font16"
+              >进度{{
+                fixedNumber(((trueNum + falseNum) * 100) / list.length, 2)
+              }}%</span
+            >
+          </div>
+          <div class="flex items-center content-center">
+            <!-- <div class="mr15">
+              <input
+                class=""
+                v-model="sysConfig.autoRead"
+                type="checkbox"
+                @change="changeSysConfig"
+              />
+              <span>自动播放</span>
+            </div> -->
+            <!-- <div>
+              <input
+                class=""
+                v-model="sysConfig.autoRed"
+                type="checkbox"
+                @change="changeSysConfig"
+              />
+              <span>提示红字</span>
+            </div> -->
+          </div>
+        </div>
+      </div>
+    </div>
+    <mProblemAlert
+      v-model:visible="alertVisible"
+      :content="list[listIndex].explainJs"
+      title="题目解析"
+    ></mProblemAlert>
+    <mProblemDialog
+      v-model:visible="dialogVisible"
+      title="提示"
+      content="是否真的要交卷(按确定键交卷,按取消键继续答题)"
+    ></mProblemDialog>
+  </div>
+</template>
+
+<script lang="ts">
+import { defineComponent, ref } from "vue";
+import api from "@/api";
+import { useRoute } from "vue-router";
+import { useDriverExam } from "@/hooks/exam/driverExam";
+import mProblemAlert from "@/components/mProblemAlert/index.vue";
+import mProblemDialog from "@/components/mProblemDialog/index.vue";
+import { useStore } from "vuex";
+import { message } from "ant-design-vue";
+import { useThreeExam } from "@/hooks/exam/threeExam";
+export default defineComponent({
+  name: "studySkill",
+  setup() {
+    let route = useRoute();
+    let store = useStore();
+    let sysConfig = ref({
+      autoRed: store.state.sysConfig.autoRed,
+      autoRead: store.state.sysConfig.autoRead,
+      autoNext: store.state.sysConfig.autoNext,
+    });
+    const changeSysConfig = (event: any) => {
+      console.log(sysConfig.value);
+      store.commit("SET_SYSCONFIG", sysConfig.value);
+    };
+    const fixedNumber = (decimal: number, digit: number) => {
+      return decimal.toFixed(digit);
+    };
+    const isImageUrl = (url: string) => {
+      var reg = /\.(png|jpg|gif|jpeg|webp)$/;
+      return reg.test(url);
+    };
+    const isVideoUrl = (url: string) => {
+      var reg = /\.(mp4|rmvb|3gp|flv|avi)$/;
+      return reg.test(url);
+    };
+    let wrongList:{id:number,timestamp:number}[] = []
+    wrongList = JSON.parse(window.localStorage.getItem('threeExam_local_wrong_list')||'[]') as {id:number,timestamp:number}[]
+    return {
+      sysConfig,
+      alertVisible: ref(false),
+      dialogVisible: ref(false),
+      ...useThreeExam(api.three.threeForceGetThreeForceListIds({
+        ids:wrongList.map(item=>item.id).join(',')
+      }), {
+        autoAnswer: false,
+        countDown: false,
+      }),
+      changeSysConfig,
+      fixedNumber,
+      isImageUrl,
+      isVideoUrl,
+    };
+  },
+  components: {
+    mProblemAlert,
+    mProblemDialog,
+  },
+});
+</script>
+
+<style scoped>
+.bottom-button {
+  text-align: center;
+  border: 1px solid #f9de5b;
+  cursor: pointer;
+}
+input[type="checkbox"] {
+  margin-right: 5px;
+
+  cursor: pointer;
+
+  font-size: 14px;
+
+  width: 15px;
+
+  height: 12px;
+
+  position: relative;
+}
+
+input[type="checkbox"]:after {
+  position: absolute;
+
+  width: 16px;
+
+  height: 16px;
+
+  top: 0;
+  left: 0px;
+
+  content: " ";
+
+  background-color: #f9de5b;
+
+  color: #fff;
+
+  display: inline-block;
+
+  visibility: visible;
+
+  border-radius: 3px;
+}
+
+input[type="checkbox"]:checked:after {
+  width: 16px;
+  height: 16px;
+  background-size: 100%;
+  background-image: url("./../../assets/img/login/checked_icon.png");
+}
+.input-border {
+  border: 1px solid #707070;
+}
+.bg-gray {
+  background: #f5f5f5;
+}
+.gray-border {
+  border: 1px solid #d8d8d8;
+}
+.bg-primary-yellow {
+  background: #f9de5b;
+}
+.bottom-button {
+  text-align: center;
+  border: 1px solid #f9de5b;
+  cursor: pointer;
+}
+.bottom-button:focus {
+  background: #f9de5b;
+  border: 1px solid #f9de5b;
+  outline: none;
+}
+.bottom-button:hover {
+  background: #fff7cc;
+}
+.w1200 {
+  width: 1200px;
+}
+</style>