Vue development evaluation system ideas and pitfalls

Recently, the company made an evaluation system. Because the time was very short, I thought it would be very simple, but I didn't expect to step on a lot of pitfalls.

Let's take a look at some of the renderings first.

 

 

 

 Then talk about the needs 

1: All answers are dynamic (for example, if you choose yes, it will be the second question, if you choose no, it will be the fifth question)

2: The question that has not been answered does not display the next question button, and the question that has been answered displays the previous question button

3: For questions that have been answered, return to the previous question to display the buttons for the previous question and the next question (except for the first and last questions)

4: The last question shows the previous question and answer analysis button

5: Automatically jump to the next question when selecting

6: After changing the questions that have been answered, the questions that have been answered after this question will be cleared (the demand is to return to the previous question, and after clicking, the following questions will be cleared regardless of whether there is a change. I feel unreasonable)

It seems very simple, but in fact it is not very easy to deal with, but when the thinking is clear, it is easy to do 

Let’s take a look at the train of thought first, nothing more than three operations, previous question, next question, and answer question, and three button states Previous question Next question Check the answer

Then start the split function

First is the answer

1. Determine if it is the last question

  1.1 is:

        1.1.1 Show previous question button 

        1.1.2 Display answer analysis button

  1.2 is not:

         1.2.1 Display the next question button

         1.2.2 Show previous question button

          1.2.3 Compared with the previous changes, is the current question worthwhile?

          1.2.3.1 Yes == "Which question starts to be cleared

           1.2.3.2 No ===》Clear

   2. Choose the timing of assignment

   3. When the current question is clicked, it is judged whether it is the last question (the question that has already been answered)

    3.1 Which question is the current question = "Find the index from all the answers

    3.2 Determine whether the current question has been answered

         Answered: The answer to the current question matches the current question of the question that has already been typed

         Determine whether the next question has 

        Yes == "Do not process

       Five == "Show the button to view the answer

2. Next question

 2.1 Show previous question

2.2 Filter the questions that have been answered = "find the index of the current question

2.3 Determine whether the next question of the current question exists

    2.3.1 does not exist

     Determine whether to display the button to view the answer

    Yes = "Show answer parsing button

    No = "Show the next question

    2.3.2 Presence

    show next question

    Judging whether the last question is judged is based on the following

    1 Find the current question from all the questions

    2 Find the corresponding index from the already answered questions'

    3 The answer of the current question matches the answer of the answered item

    4. Determine whether there is a next question in the answer to the current question

     Yes == "Do not process

     None == "Show answer analysis button 

 3 previous question

  3.1 Show the next question button 

  3.2 Determine whether the previous question button is displayed

  3.3 Show previous question

  3.4 Record answers

    Take a look at the complete code (vue3+vant)

<template>
  <div class="main">
    <template v-for="(item, i) in vDate.dataList" :key="i">
      <div class="item_list" v-show="item.questionId == vDate.questionId">
        <div class="item_title">
          {
   
   { item.question }}
        </div>
        <van-radio-group
          v-model="vDate.answerList[i].questionOptionId"
        >
          <van-radio
            @click="radioClick(i,item,key)"
            v-for="(key, v) in item.optionList"
            :key="v"
            :name="key.questionOptionId"
            >{
   
   { key.questionOption }}</van-radio
          >
        </van-radio-group>
      </div>
    </template>
		<div class="operate">
			<div>
        <van-button size="small" v-if="vDate.press>0" @click="press">上一题</van-button>
        <span v-else></span>
      </div>
			<div>
        <div v-if="vDate.next>0">
          <van-button type="primary" size="small" @click="lookAnswer" v-if="vDate.isAnswer">查看答案</van-button>
          <van-button type="primary" size="small" @click="next" v-else>下一题</van-button>
        </div>
			  <div v-else>
        </div>
      </div>
		</div>
  </div>
  <div>
    <van-overlay :show="vDate.show">
      <div class="wrapper" @click.stop>
        <van-cell-group inset>
         <div class="label">手机号</div>
          <van-field
            v-model="vDate.phone"
            center
            type="digit"
            :maxlength="11"
            placeholder="请输入手机号"
          >
            <template #button>
              <van-button type="primary" @click="vDate.flag && obtain()">{
   
   {vDate.content}}</van-button>
            </template>
          </van-field>
          <div class="input_control">
            <van-field v-model="vDate.pwdVal" :maxlength="4" type="digit" ref="verification" />
          </div>
          <div class="label">验证码</div>
          <div class='input_row' @click='getFocus'>
            <div class='pwd_item' v-for="(item,i) in 4" :key='i'>
                <span v-if="vDate.pwdVal.length>i">{
   
   {vDate.pwdVal[i]}}</span>
            </div>
          </div>
          <div class="operation">
            <van-button type="primary" block @click="toDetail">查看答案</van-button>
          </div>
        </van-cell-group>
      </div>
    </van-overlay>
  </div>
</template>
<script setup lang="ts">
import { nextTick, reactive, ref,onMounted } from "vue";
const verification = ref()
import {useRouter} from "vue-router"
import { Toast } from 'vant';
import {getQuestionList,submitQuestionList} from "@/api/index"
const router = useRouter()
const vDate:any = reactive({
	type:0,
  phone:'',
  show:false,
  flag:true,
  input:false,
  pwdVal:"",
  count:'',
  content:'获取验证码',
  countNumber:1,
  timer:null,
  dataList: [
  ],
  answerList:[
  ],
  questionId:'',
  isAnswer:false,
  idList:[],
  press:0,
  isNext:'',
  next:0,
  index:0,
  answerLists:[]
})
const phoneReg= /^1[3-9][0-9]{9}$/ 
// 上一题
function press(){
  vDate.next = 1
  vDate.isAnswer = false
  let answerList = vDate.answerList.filter((item:any)=>item.questionId)
  let length = answerList.length-1
  let index = answerList.findIndex((item:any)=>item.questionId==vDate.questionId)
  if(index==-1){
    vDate.press = answerList.length-1
    vDate.questionId = answerList[length].questionId
  }else{
    vDate.press = index-1
    vDate.questionId = answerList[index-1].questionId
  }
  vDate.answerLists = JSON.parse(JSON.stringify(vDate.answerList))
}
function next(){
  vDate.press = 1
	let answerList = vDate.answerList.filter((item:any)=>item.questionId)
  let index = answerList.findIndex((item:any)=>item.questionId == vDate.questionId )
  if(answerList[index+1]){
    vDate.questionId = answerList[index+1].questionId
      let nextArr = vDate.dataList.filter((item:any)=>item.questionId == vDate.questionId) //当前页项
      let indexs = vDate.answerList.findIndex((item:any)=>item.questionId == vDate.questionId)
      console.log(vDate.questionId,vDate.answerList[indexs],999,nextArr[0],"===========")

      let arr = nextArr[0].optionList.filter((item:any)=>item.questionOptionId == vDate.answerList[indexs].questionOptionId)
      if(!arr[0].relationQuestionId){
        vDate.isAnswer = true
        vDate.next = 1
      }
  }else{
    if(!vDate.isNext){
      vDate.isAnswer = true
    }else{
      vDate.next = -1
      vDate.questionId = vDate.isNext
      console.log(vDate.questionId,"22")
    }
  }
}
// 查看答案
const lookAnswer = ()=>{
  vDate.show = true
}
// 输入验证码
const getFocus = ()=>{
  nextTick(()=>{
    verification.value.focus()
  })
}
//答案
const toDetail = ()=>{
  if(!vDate.phone){
    return Toast('请输入手机号');
  }
  if(!phoneReg.test(vDate.phone)){
    return Toast('请输入正确手机号');
  }
  if(vDate.countNumber==1&&!vDate.pwdVal){
    return Toast('请获取验证码');
  }
  if(vDate.countNumber==2&&!vDate.pwdVal){
    return Toast('请输入验证码');
  }
  let userAnswerRequestList = vDate.answerList.filter((item:any)=>item.questionId)
  let params = {
    questionGroup:1,
    userAnswerRequestList
  }
  submitQuestionList(params).then((res:any)=>{
    localStorage.setItem("answerBatchNo",res.data)
    router.push("/answerDetail")
  })
 
}
//获取验证码
const obtain = ()=>{
  if(!vDate.phone){
    return Toast('请输入手机号');
  }
  if(!phoneReg.test(vDate.phone)){
    return Toast('请输入正确手机号');
  }
  setTimeoutInfo()
}
//定时器
const setTimeoutInfo = ()=>{
  const TIME_COUNT = 60;
  vDate.countNumber = 2
  vDate.flag = false
  if (!vDate.timer) {
    vDate.count = TIME_COUNT;
    vDate.timer = setInterval(() => {
    if (vDate.count > 0 && vDate.count <= TIME_COUNT) {
      vDate.count--;
      vDate.content = vDate.count+' s后获取';
      } else {
          vDate.content = '获取验证码';
          vDate.flag = true;
          clearInterval(vDate.timer);
          vDate.timer = null;
      }
      }, 1000)
  }
}
const radioClick = (i:number,item:any,val:any)=>{
  if(val.relationQuestionId!=null){
    setTimeout(()=>{
      vDate.questionId = val.relationQuestionId
      vDate.press = i+1
      vDate.next = -1
      vDate.isNext = val.relationQuestionId
      let index = vDate.answerList.findIndex((item:any)=>item.questionId == val.relationQuestionId)
      if(index==-1){
        vDate.answerList.forEach((item:any,v:number)=>{
          if(v>i){
            item.questionId = ""
            item.questionOptionId = ""
          }
        })
      }else{
        let arr = vDate.answerList.map((item:any,i:number)=>{
          return vDate.answerList[i].questionOptionId!=vDate.answerLists[i].questionOptionId
        })
        let indexs = arr.findIndex((item:any)=>item==true)
        if(indexs!=-1){
          vDate.answerList.forEach((item:any,v:number)=>{
            if(v>indexs){
              item.questionId = ""
              item.questionOptionId = ""
            }
          })
        }
      }
      clearTimeout()
    },300)
  }else{
    vDate.isAnswer = true
    vDate.next = 1
    vDate.isNext = null
  }
  vDate.answerList[i].questionId = item.questionId
  console.log(vDate.answerList,"vDate.answerList111")
  setTimeout(()=>{
    let index = vDate.dataList.findIndex(((item:any)=>item.questionId == val.relationQuestionId))
    if(index!=-1){
      let nextArr = vDate.dataList[index] //当前页项
      let flag = vDate.answerList[index].questionId
      if(flag){
        let arr = nextArr.optionList.filter((item:any)=>item.questionOptionId == vDate.answerList[index].questionOptionId)
        if(!arr[0].relationQuestionId){
          vDate.isAnswer = true
          vDate.next = 1
        }
      }
    }
  },500)

}
//获取题目
const queryList = ()=>{
  let params = {
    questionGroup:1
  }
  getQuestionList(params).then((res:any)=>{
    vDate.dataList = res.data
    res.data.forEach((item:any)=>{
      vDate.idList.push(item.questionId)
      vDate.answerList.push({
        questionId:'',
        questionOptionId:''
      })
    })
    vDate.questionId = res.data[0].questionId
    vDate.answerLists = JSON.parse(JSON.stringify(vDate.answerList))
  })  
}
onMounted(()=>{
  queryList()
})
</script>

Look at the data structure of the topic

 Interested partners can try it out by themselves. There are many pitfalls in the seemingly simple things. If you need it, you can private message me to get all the codes for free.

Guess you like

Origin blog.csdn.net/xy19950125/article/details/128112616