Vue3:一页多题答案校正及radio和checkbox混合使用

一页多题,类型包括单选,判断多选,涉及radio和checkbox同时使用,答案校正数据匹配,正确答案格式化,答案提交数据格式化,数据提交。

效果:

数据获取:

数据提交:

HTML:

html 复制代码
<template>

<!--其他HTML结构-->

<ul class="question f16">
  <li v-for="(list,index) in questionData" :key="index">
    <h5>{{list.type}}题</h5>
    <h6 v-if="list.scoreTxt !=undefined">
      <b :class="{daanErr:list.scoreTxt !='正确'}" v-if="list.scoreTxt !='正确'">正确选项是:{{list.scoreTxt}}</b>
      <b v-else>{{list.scoreTxt}}</b>
    </h6>
    
    <!--单选及判断-->
    <dl v-if="list.type != '多选'">
      <dt v-html="list.title"></dt>
      <dd>
        <label v-for="(radio,id) in list.xuanxiang" :key="id">
          <input type="radio" :name="list.id" :value="list.id+'_'+radio.name" v-model="radioData[list.id]">
          <span><b>{{radio.name}}</b>{{radio.content}}</span>
        </label>
      </dd>
    </dl>

    <!--多选-->
    <dl v-else>
      <dt v-html="list.title"></dt>
      <dd>
        <label v-for="(checkbox,checkboxIndex) in list.xuanxiang" :key="checkboxIndex">
          <input type="checkbox" :value="list.id+'_'+checkbox.name" v-model="checkData">
          <span><b>{{checkbox.name}}</b>{{checkbox.content}}</span>
      </label>
    </dd>
    </dl>
  </li>
</ul>
<div class="checkEnterBt f18 sysmt40">
  <button @click="checkEnter">提交答案</button>
  <button @click="checkChange">换题再测试</button>
</div>

<!--其他HTML结构-->

</template>

JS:

html 复制代码
<script setup>
import { defineComponent, getCurrentInstance, ref, reactive, computed, onBeforeMount, onMounted, onBeforeUpdate, onUpdated, onBeforeUnmount, onUnmounted, onErrorCaptured, onRenderTracked, onRenderTriggered, onActivated, onDeactivated, onServerPrefetch, watch,toRaw } from 'vue';
import {useRoute, onBeforeRouteUpdate} from 'vue-router'
import { useStore } from 'vuex';

//vantUl的showToast请提示
import { showToast } from 'vant';

//使用vue的getCurrentInstance 方法获取当前组件实例
const { proxy } = getCurrentInstance()

//获取vuex数据
let store = useStore();

//使用router
const route = useRoute()


//获取题目列表数据
let questionData = ref([]) //答题数据
let answerData = ref([]) //格式化后答案
const getQuestion = () => {

    /*axois获取题目数据*/

    console.log(response.data.data.data)

    questionData.value = response.data.data.data

    //格式化数据答案为[id,选项],单选[id,A],多选[id,A],[id,C]
    for(let i=0;i<response.data.data.data.length;i++){
      for(let n=0;n<response.data.data.data[i].daan.length;n++){
        if(response.data.data.data[i].daan[n] != "_"){
          answerData.value.push([response.data.data.data[i].id,response.data.data.data[i].daan[n]])
        }
      }
    }

  /*其他代码*/

}


//答案选择
let radioData= ref([]) //单选
let checkData = ref([]) //多选
let selectData = ref([]) //单选和多选合集



//提交答案
let scoreEnter = [] //按提服务器要求格式化选择答案组
const checkEnter = ()=>{
  let newSelect = [] //单选+多选
  newSelect = Object.values({...checkData.value,...radioData.value})
  //格式化单选多选合并后的数据为[id,选项] 单选[id,A],多选[id,A],[id,C]
  for(let y=0;y<newSelect.length;y++){
    selectData.value.push(newSelect[y].split("_"))
  }
  //将格式化数据查找验证对错并格式化
  //校正提示格式 [id,选项] 单选[id,A] 多选[id,ABC]
  //提交数据格式 单选[id-A] 多选[id-A_B_C]
  for(let s=0;s<selectData.value.length;s++){
    let selectID =  selectData.value[s][0] //用户答题id
    let selectTxt = '' //用户选择答案
    let daanTxt = '' //正确答案
    let enterTxt = '' //按后端要求格式化用户每次选择答案
    let find=0 //查找次数
    for(let i=0;i<selectData.value.length;i++){
      if(selectData.value[i][0] == selectID){
        selectTxt += selectData.value[i][1]
        enterTxt += selectData.value[i][1]+'_'
      }
    }
    for(let a=0;a<answerData.value.length;a++){
      if(answerData.value[a][0] == selectID){
        daanTxt += answerData.value[a][1]
      }
    }
    for(let x=0;x<scoreEnter.length;x++){
      if(selectID == scoreEnter[x][0]){
        find=1
      }
    }
    if(find ==0){
      let enter = [selectID,'-'+enterTxt]
      scoreEnter.push(enter)
      let index = '' //查找对应id的下标
      for(let q=0;q<questionData.value.length;q++){
        index = questionData.value.findIndex(item => item.id == selectID)
      }
      //判断答题是否正确 并将格式化后的答案(多选题题的答案按英文字母表升序排列.sort())写入questionData数据中
      if(selectTxt.split("").sort().join("") == daanTxt.split("").sort().join("")){
        questionData.value[index].scoreTxt="正确"
      }else{
        questionData.value[index].scoreTxt=daanTxt
      }
    }
  }
   
  //检测是否全部答题及答题完毕数据提交
  if(scoreEnter.length == questionData.value.length){
    let enterData = []
    for(let u=0;u<scoreEnter.length;u++){
      enterData.push(scoreEnter[u].join("").slice(0,-1))
    }
    let params = {
      /*其他参数 category_id:proxy.$route.params.category_id,*/
      ti_str:enterData.toString(),
    }
   
    /*将数据提交*/

      if(response.data.status == 1){
        showToast("答题提交成功!");
      }
 
    /*将数据提交*/

  }else{
    showToast("回答完全部问题再提交答案哦!");
  }
}


//换题再测试
const checkChange = ()=>{
  questionData.value = undefined
  answerData.value = []
  radioData.value = []
  checkData.value = []
  selectData.value = []
  scoreEnter=[]
  getQuestion()

}


onBeforeMount(() => {
  getQuestion()

})

</script>

CSS:

css 复制代码
.question li{background:#fff;padding:30px 20px 20px 20px;border-radius:10px;box-shadow:0 0 7px #ccc;border:1px solid #eaeaea;margin-bottom:40px;position:relative;}
.question li h6{position:absolute;right:20px;top:30px;}
.question li h6 b.daanErr{color:#e60000;}
.question li h6 b{color:#018407;}
.question li h5{border-left:4px solid #ff6e52;font-size:20px;font-weight:bold;padding-left:15px;margin-bottom:20px;}
.question li dt{padding:0 0 20px 20px;}
.question li dd{padding-right:50px;}
.question li label{display:line-block;position:relative;margin:0 20px 20px 0;padding-left:20px;}
.question li label span{border:1px solid #d0d0d0;border-radius:10px;padding:7px 20px;box-sizing:border-box;display:inline-block;line-height:26px;}
.question li label input{display:none;}
.question li label input:checked+span{background:#fffafa;z-index:2;color:#b80000;border:1px solid #b80000;border-radius:10px;}
.question li label span b{display:inline-block;font-weight:normal;margin-right:5px;}


.checkEnterBt{display:flex;justify-content:space-around;align-items:center;}
.checkEnterBt button{width:40%;background:#e60000;color:#fff;border:none;padding:20px 0;border-radius:10px;}
.checkEnterBt button:nth-child(2){background:#007ce6;}
相关推荐
山河木马3 分钟前
前端学C++可太简单了:双冒号 :: 操作符
前端·javascript·c++
3Katrina4 分钟前
前端面试之防抖节流(二)
前端·javascript·面试
前端进阶者10 分钟前
天地图编辑支持删除编辑点
前端·javascript
江号软件分享19 分钟前
无接触服务的关键:二维码生成识别技术详解
前端
江号软件分享20 分钟前
如何利用取色器实现跨平台色彩一致性
前端
灰海23 分钟前
封装WebSocket
前端·网络·websocket·网络协议·vue
前端小巷子34 分钟前
深入理解TCP协议
前端·javascript·面试
万少35 分钟前
鸿蒙外包的十大生存法则
前端·后端·面试
顽疲1 小时前
从零用java实现 小红书 springboot vue uniapp(13)模仿抖音视频切换
java·vue.js·spring boot
开开心心就好1 小时前
电脑息屏工具,一键黑屏超方便
开发语言·javascript·电脑·scala·erlang·perl