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;}
相关推荐
也无晴也无风雨42 分钟前
深入剖析输入URL按下回车,浏览器做了什么
前端·后端·计算机网络
Martin -Tang1 小时前
Vue 3 中,ref 和 reactive的区别
前端·javascript·vue.js
FakeOccupational3 小时前
nodejs 020: React语法规则 props和state
前端·javascript·react.js
放逐者-保持本心,方可放逐3 小时前
react 组件应用
开发语言·前端·javascript·react.js·前端框架
曹天骄4 小时前
next中服务端组件共享接口数据
前端·javascript·react.js
阮少年、4 小时前
java后台生成模拟聊天截图并返回给前端
java·开发语言·前端
郝晨妤6 小时前
鸿蒙ArkTS和TS有什么区别?
前端·javascript·typescript·鸿蒙
AvatarGiser6 小时前
《ElementPlus 与 ElementUI 差异集合》Icon 图标 More 差异说明
前端·vue.js·elementui
喝旺仔la6 小时前
vue的样式知识点
前端·javascript·vue.js
别忘了微笑_cuicui6 小时前
elementUI中2个日期组件实现开始时间、结束时间(禁用日期面板、控制开始时间不能超过结束时间的时分秒)实现方案
前端·javascript·elementui