vue开发测评系统思路及踩坑

news/2024/5/9 5:09:21/文章来源:https://blog.csdn.net/xy19950125/article/details/128112616

最近公司做了一个测评系统,因为时间很短,本以为会很简单,没有想到踩了很多坑。

先看下部分效果图吧

 

 

 

 然后在说下需求 

1:所有的答案都是动态的(例如选择是出来的是第二题,选择否出来的是第五题)

2:没有答过的题不显示下一题按钮,答过的题显示上一题按钮

3:答过的题,返回上一题 显示上一题和下一题按钮(第一题和最后一题例外)

4:最后一题显示上一题和答案解析按钮

5:选择的时候 自动跳转到下一题

6:已经答过的题,更改后,从此题开始 后面答过的题清除(需求则是返回上一题,点击后不管有无更改 后面的题都清除,自己感觉不合理)

看似很简单,其实并不是很好处理 但是当思路捋清楚了 就很好做了 

先捋一捋思路 无非三种操作 上一题、下一题、和答题和三种按钮状态 上一题 下一题 查看答案

然后开始拆分功能

首先是答题

1.判断是不是最后一题

  1.1是:

        1.1.1 显示上一题按钮 

        1.1.2显示答案解析按钮

  1.2不是:

         1.2.1显示下一题按钮

         1.2.2 显示上一题按钮

          1.2.3对比和之前的变化 当前题是否有值

          1.2.3.1是  ==》哪一题开始清空

           1.2.3.2否  ===》清空

   2.选择赋值的时机

   3. 当前题点击的时候 判断是不是最后一题 (已经答过的题)

    3.1 当前题是第几题  =》从全部答案里面找 得到索引

    3.2 判断当前提是否答过

         答过:当前题的答案去匹配已经打过的题的当前题

         判断下一题是否有 

        有==》不处理

       五 ==》显示查看答案按钮

2.下一题

 2.1 显示上一题

2.2过滤已经答过的题目 =》找到当前题的索引

2.3判断当前题的下一题是否存在

    2.3.1不存在

     判断是否显示查看答案的按钮

    是  =》显示答案解析按钮

    否 =》 显示下一题

    2.3.2存在

    显示下一题

    判断是否最后一题 判断依据如下

    1从全部题里面找到当前题

    2从已经答过的题里面找到对应的索引‘

    3当前题的题目答案中匹配已答项的答案

    4判断当前题答案中是否有下一题

     有==》不处理

     无==》显示答案解析按钮 

 3 上一题

  3.1 显示下一题按钮 

  3.2 判断上一题按钮是否显示

  3.3 显示上一题

  3.4 记录答案

    看一下完整代码吧(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-groupv-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-fieldv-model="vDate.phone"centertype="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 = 1vDate.isAnswer = falselet answerList = vDate.answerList.filter((item:any)=>item.questionId)let length = answerList.length-1let index = answerList.findIndex((item:any)=>item.questionId==vDate.questionId)if(index==-1){vDate.press = answerList.length-1vDate.questionId = answerList[length].questionId}else{vDate.press = index-1vDate.questionId = answerList[index-1].questionId}vDate.answerLists = JSON.parse(JSON.stringify(vDate.answerList))
}
function next(){vDate.press = 1let 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].questionIdlet 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 = truevDate.next = 1}}else{if(!vDate.isNext){vDate.isAnswer = true}else{vDate.next = -1vDate.questionId = vDate.isNextconsole.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 = 2vDate.flag = falseif (!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.relationQuestionIdvDate.press = i+1vDate.next = -1vDate.isNext = val.relationQuestionIdlet 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 = truevDate.next = 1vDate.isNext = null}vDate.answerList[i].questionId = item.questionIdconsole.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].questionIdif(flag){let arr = nextArr.optionList.filter((item:any)=>item.questionOptionId == vDate.answerList[index].questionOptionId)if(!arr[0].relationQuestionId){vDate.isAnswer = truevDate.next = 1}}}},500)}
//获取题目
const queryList = ()=>{let params = {questionGroup:1}getQuestionList(params).then((res:any)=>{vDate.dataList = res.datares.data.forEach((item:any)=>{vDate.idList.push(item.questionId)vDate.answerList.push({questionId:'',questionOptionId:''})})vDate.questionId = res.data[0].questionIdvDate.answerLists = JSON.parse(JSON.stringify(vDate.answerList))})  
}
onMounted(()=>{queryList()
})
</script>

看下题目的数据结构

 感兴趣的小伙伴可以自己动手试一试 看似简单的东西 里面很有多坑  有需求的可以私信我 免费获取全部代码

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_39201.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何用蓝牙实现无线定位(二)--信号塔设置

1. 配置BLE4.0模块 根据三点定位原理&#xff0c;本项目需要使用3个信号塔。3个信号塔的主体均为BLE4.0模块&#xff0c;需要把BLE4.0模块的AT指令设置为“从设备”。 方法为&#xff1a; &#xff08;1&#xff09;给控制板刷一套空的程序。初始打开arduino IDE或新建&#x…

React+Electron快速创建并打包成桌面应用

一、创建react项目 首先使用creat-react-app脚手架来创建一个react项目 # 安装 create-react-app 命令,如果已将安装请忽略 npm install -g create-react-app # 创建 react项目 create-react-app react-electron # 启动项目( create-react-app 真的超级方便啊) cd react-elec…

【电力运维】浅谈电力通信与泛在电力物联网技术的应用与发展

摘要&#xff1a;随着我国社会经济的快速发展&#xff0c;我国科技实力得到了巨大的提升&#xff0c;当前互联网通信技术在社会中得到了广泛的应用。随着电力通信技术的快速发展与更新&#xff0c;泛在电力物联网建设成为电力通讯发展的重要方向。本文已泛在电力物联网系统为核…

医院用故障电弧探测器AAFD 安科瑞 时丽花

摘 要&#xff1a; 医院运行中对于用电方面的要求越来越高&#xff0c;为了更好地体现用电价值&#xff0c;首先应该确保用电的安全性&#xff0c;尤其是对 于越来越繁杂的医院用电系统。基于此&#xff0c;在未来医院用电过程中应该加大关注力度&#xff0c;切实做好相关管理工…

Mysql:sql去重的几种方式(大数据hive也可参考)

文章目录前言准备创建表测试数据目标探索distinct 去重group by 去重实现方案方案一方案二方案三前言 我们做数据分析的时候经常会遇到去重问题&#xff0c;下面总结 sql 去重的几种方式&#xff0c;后续如果还有再补充&#xff0c;大数据分析层面包括 hive、clickhouse 也可参…

Python——变量以及基础数据类型练习题

要求&#xff1a;注意变量名的命名规范问题&#xff01;&#xff01;&#xff01;不能再出现没有意义的变量名&#xff01;&#xff01;&#xff01;一行一注释&#xff0c;用下划线命名法。 请使用相对应的数据类型&#xff0c;不能全部使用字符串&#xff01;&#xff01;&a…

Codeforces Round #574 (Div. 2) C. Basketball Exercise

翻译&#xff1a; 最后&#xff0c;SIS已经开放了一个篮球场&#xff0c;所以Demid决定举办一个篮球训练课程。有2个⋅&#x1d45b;的学生参加了Demid的练习课&#xff0c;他将他们排成两排&#xff0c;大小相同(每排正好有&#x1d45b;人)。学生按从左到右的顺序&#xff0…

数字化门店| 美业/医美门店管理系统 | 医美小程序

近些年来&#xff0c;随着人们消费升级和颜值经济的不断驱动&#xff0c;美业发展非常迅速&#xff0c;而医美行业也顺势规模增长。 当今互联网时代&#xff0c;各行业都在开展门店数字化转型&#xff0c;而这也让不少医美医院愿意构建基于门店会员管理的O2O闭环&#xff0c;并…

Web进阶

目录 DOM节点操作&#xff08;上&#xff09; 一、任务目标 二、任务背景 三、任务内容 1、DOM结构及节点 DOM节点操作&#xff08;下&#xff09; 一、任务目标 二、任务背景 三、任务内容 1、DOM修改 DOM控制CSS样式 一、任务目标 二、任务背景 三、任务内容 …

element实现el-progress线形进度条渐变色

实现效果&#xff1a; 实现前&#xff1a; 网上查progress找到的方法都是环形进度条的&#xff0c;且实现得贼复杂&#xff0c;要么封装一个新组件要么修改一串svg&#xff0c;其实线形进度条改成渐变色的方法非常简单&#xff0c;直接在css上修改就行了&#xff1a; <div…

5-UI自动化-三大切换,iframe如何定位,窗口新开、alert弹窗如何进行元素定位

5-UI自动化-三大切换&#xff0c;iframe如何定位&#xff0c;窗口新开、alert弹窗如何进行元素定位新开一个窗口如何定位元素switch_to方法iframe定位元素alert弹窗如何定位元素上篇介绍4-UI自动化-selenium三大等待操作 web测试过程中有没有遇到以下问题&#xff1a; 1、测试…

使用 Hibernate Envers 进行实体审计

业务应用程序中的常见要求是在特定数据更改时存储版本控制信息;当某事发生变化时&#xff0c;谁改变了它&#xff0c;改变了什么。在这篇博文中&#xff0c;我们将介绍Hibernate Envers&#xff0c;它是Hibernate JPA库的一个组件&#xff0c;它为实体类提供了一个简单的审计/版…

期中考试【Verilog】

期中考试【Verilog】前言推荐期中考试一. 单选题&#xff08;共10题&#xff09;二. 填空题&#xff08;共5题&#xff09;三. 简答题&#xff08;共3题&#xff09;四. 其它&#xff08;共4题&#xff09;最后前言 编写于2022/11/30 13:30 以下内容源自Verilog期中试题 仅供…

GeoServer服务迁移出现 EncryptionOperationNotPossibleException 错误的解决方案

目录1.前言2.GeoServer服务迁移一般流程3.遇到问题4.原因分析5.解决办法6.根本原因分析7.总结1.前言 这几天我在迁移 GeoServer 服务的时候发现&#xff0c;报了一个错&#xff0c;EncryptionOperationNotPossibleException &#xff0c;这个错误的大概意思是加密操作不可用异常…

Faster RCNN全文翻译

Abstract—State-of-the-art【最先进的】 object detection networks depend on region proposal algorithms to hypothesize【假设、推测】 object locations.Advances like SPPnet [1] and Fast R-CNN [2] have reduced the running time of these detection networks, expos…

Redis集群方案备忘录

文章目录哨兵模式官方Redis ClusterJedis&#xff08;客户端分片&#xff09;Codis&#xff08;代理分片&#xff09;哨兵模式 优点 哨兵模式是基于主从模式的&#xff0c;解决可主从模式中master故障不可以自动切换故障的问题。缺点 &#xff08;1&#xff09;是一种中心化的…

一些跨平台技术方案的经验参考

今天就站在一个小开发的视角分享一下一个小项目是如何进行跨平台方案选型的 本系列文章先站在公司的的角度对产品技术选型进行分析&#xff0c;然后再根据我们项目实际开发经验进行汇总&#xff0c;供大家参考。 目前大前端技术也非常丰富&#xff0c;可以实现&#xff0c;一…

【uniapp】利用Vuex实现购物车功能

实战项目名称&#xff1a;实现购物车功能 文章目录一、实战步骤1. 先编辑store.js文件2. 定义方法和基本的结构3. 编写SETSHPPING二、在项目中调用1. 触发相应的mutations2. 利用computed计算数量和总价的方法提示&#xff1a;本实战内容大部分为具体实现的思路&#xff0c;界面…

FRED应用:激光二极管的模拟

简介 当提及模拟激光二极管时&#xff0c;FRED软件具有极大的灵活性。在这篇应用笔记中&#xff0c;将会描述简单到详细的激光光源模型。最基本的模型是高斯TEM0,0模。更高级的模型包括在束腰上偏移和发散中的像散光束。激光也可以使用其M2因子表示。最后&#xff0c;可以创…

猿如意开发工具|Sublime Text(4126)

文章目录 一、猿如意是什么&#xff1f; 二、如何使用猿如意下载安装Sublime Text 三、总结 一、猿如意是什么&#xff1f; 猿如意是一款面向开发者的辅助开发工具箱&#xff0c;包含了效率工具、开发工具下载&#xff0c;教程文档&#xff0c;代码片段搜索&#xff0c;全网搜…