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


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

    先看下部分效果图吧

     

     

     

     然后在说下需求 

    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)

    1. <template>
    2. <div class="main">
    3. <template v-for="(item, i) in vDate.dataList" :key="i">
    4. <div class="item_list" v-show="item.questionId == vDate.questionId">
    5. <div class="item_title">
    6. {{ item.question }}
    7. </div>
    8. <van-radio-group
    9. v-model="vDate.answerList[i].questionOptionId"
    10. >
    11. <van-radio
    12. @click="radioClick(i,item,key)"
    13. v-for="(key, v) in item.optionList"
    14. :key="v"
    15. :name="key.questionOptionId"
    16. >{{ key.questionOption }}</van-radio
    17. >
    18. </van-radio-group>
    19. </div>
    20. </template>
    21. <div class="operate">
    22. <div>
    23. <van-button size="small" v-if="vDate.press>0" @click="press">上一题</van-button>
    24. <span v-else></span>
    25. </div>
    26. <div>
    27. <div v-if="vDate.next>0">
    28. <van-button type="primary" size="small" @click="lookAnswer" v-if="vDate.isAnswer">查看答案</van-button>
    29. <van-button type="primary" size="small" @click="next" v-else>下一题</van-button>
    30. </div>
    31. <div v-else>
    32. </div>
    33. </div>
    34. </div>
    35. </div>
    36. <div>
    37. <van-overlay :show="vDate.show">
    38. <div class="wrapper" @click.stop>
    39. <van-cell-group inset>
    40. <div class="label">手机号</div>
    41. <van-field
    42. v-model="vDate.phone"
    43. center
    44. type="digit"
    45. :maxlength="11"
    46. placeholder="请输入手机号"
    47. >
    48. <template #button>
    49. <van-button type="primary" @click="vDate.flag && obtain()">{{vDate.content}}</van-button>
    50. </template>
    51. </van-field>
    52. <div class="input_control">
    53. <van-field v-model="vDate.pwdVal" :maxlength="4" type="digit" ref="verification" />
    54. </div>
    55. <div class="label">验证码</div>
    56. <div class='input_row' @click='getFocus'>
    57. <div class='pwd_item' v-for="(item,i) in 4" :key='i'>
    58. <span v-if="vDate.pwdVal.length>i">{{vDate.pwdVal[i]}}</span>
    59. </div>
    60. </div>
    61. <div class="operation">
    62. <van-button type="primary" block @click="toDetail">查看答案</van-button>
    63. </div>
    64. </van-cell-group>
    65. </div>
    66. </van-overlay>
    67. </div>
    68. </template>
    69. <script setup lang="ts">
    70. import { nextTick, reactive, ref,onMounted } from "vue";
    71. const verification = ref()
    72. import {useRouter} from "vue-router"
    73. import { Toast } from 'vant';
    74. import {getQuestionList,submitQuestionList} from "@/api/index"
    75. const router = useRouter()
    76. const vDate:any = reactive({
    77. type:0,
    78. phone:'',
    79. show:false,
    80. flag:true,
    81. input:false,
    82. pwdVal:"",
    83. count:'',
    84. content:'获取验证码',
    85. countNumber:1,
    86. timer:null,
    87. dataList: [
    88. ],
    89. answerList:[
    90. ],
    91. questionId:'',
    92. isAnswer:false,
    93. idList:[],
    94. press:0,
    95. isNext:'',
    96. next:0,
    97. index:0,
    98. answerLists:[]
    99. })
    100. const phoneReg= /^1[3-9][0-9]{9}$/
    101. // 上一题
    102. function press(){
    103. vDate.next = 1
    104. vDate.isAnswer = false
    105. let answerList = vDate.answerList.filter((item:any)=>item.questionId)
    106. let length = answerList.length-1
    107. let index = answerList.findIndex((item:any)=>item.questionId==vDate.questionId)
    108. if(index==-1){
    109. vDate.press = answerList.length-1
    110. vDate.questionId = answerList[length].questionId
    111. }else{
    112. vDate.press = index-1
    113. vDate.questionId = answerList[index-1].questionId
    114. }
    115. vDate.answerLists = JSON.parse(JSON.stringify(vDate.answerList))
    116. }
    117. function next(){
    118. vDate.press = 1
    119. let answerList = vDate.answerList.filter((item:any)=>item.questionId)
    120. let index = answerList.findIndex((item:any)=>item.questionId == vDate.questionId )
    121. if(answerList[index+1]){
    122. vDate.questionId = answerList[index+1].questionId
    123. let nextArr = vDate.dataList.filter((item:any)=>item.questionId == vDate.questionId) //当前页项
    124. let indexs = vDate.answerList.findIndex((item:any)=>item.questionId == vDate.questionId)
    125. console.log(vDate.questionId,vDate.answerList[indexs],999,nextArr[0],"===========")
    126. let arr = nextArr[0].optionList.filter((item:any)=>item.questionOptionId == vDate.answerList[indexs].questionOptionId)
    127. if(!arr[0].relationQuestionId){
    128. vDate.isAnswer = true
    129. vDate.next = 1
    130. }
    131. }else{
    132. if(!vDate.isNext){
    133. vDate.isAnswer = true
    134. }else{
    135. vDate.next = -1
    136. vDate.questionId = vDate.isNext
    137. console.log(vDate.questionId,"22")
    138. }
    139. }
    140. }
    141. // 查看答案
    142. const lookAnswer = ()=>{
    143. vDate.show = true
    144. }
    145. // 输入验证码
    146. const getFocus = ()=>{
    147. nextTick(()=>{
    148. verification.value.focus()
    149. })
    150. }
    151. //答案
    152. const toDetail = ()=>{
    153. if(!vDate.phone){
    154. return Toast('请输入手机号');
    155. }
    156. if(!phoneReg.test(vDate.phone)){
    157. return Toast('请输入正确手机号');
    158. }
    159. if(vDate.countNumber==1&&!vDate.pwdVal){
    160. return Toast('请获取验证码');
    161. }
    162. if(vDate.countNumber==2&&!vDate.pwdVal){
    163. return Toast('请输入验证码');
    164. }
    165. let userAnswerRequestList = vDate.answerList.filter((item:any)=>item.questionId)
    166. let params = {
    167. questionGroup:1,
    168. userAnswerRequestList
    169. }
    170. submitQuestionList(params).then((res:any)=>{
    171. localStorage.setItem("answerBatchNo",res.data)
    172. router.push("/answerDetail")
    173. })
    174. }
    175. //获取验证码
    176. const obtain = ()=>{
    177. if(!vDate.phone){
    178. return Toast('请输入手机号');
    179. }
    180. if(!phoneReg.test(vDate.phone)){
    181. return Toast('请输入正确手机号');
    182. }
    183. setTimeoutInfo()
    184. }
    185. //定时器
    186. const setTimeoutInfo = ()=>{
    187. const TIME_COUNT = 60;
    188. vDate.countNumber = 2
    189. vDate.flag = false
    190. if (!vDate.timer) {
    191. vDate.count = TIME_COUNT;
    192. vDate.timer = setInterval(() => {
    193. if (vDate.count > 0 && vDate.count <= TIME_COUNT) {
    194. vDate.count--;
    195. vDate.content = vDate.count+' s后获取';
    196. } else {
    197. vDate.content = '获取验证码';
    198. vDate.flag = true;
    199. clearInterval(vDate.timer);
    200. vDate.timer = null;
    201. }
    202. }, 1000)
    203. }
    204. }
    205. const radioClick = (i:number,item:any,val:any)=>{
    206. if(val.relationQuestionId!=null){
    207. setTimeout(()=>{
    208. vDate.questionId = val.relationQuestionId
    209. vDate.press = i+1
    210. vDate.next = -1
    211. vDate.isNext = val.relationQuestionId
    212. let index = vDate.answerList.findIndex((item:any)=>item.questionId == val.relationQuestionId)
    213. if(index==-1){
    214. vDate.answerList.forEach((item:any,v:number)=>{
    215. if(v>i){
    216. item.questionId = ""
    217. item.questionOptionId = ""
    218. }
    219. })
    220. }else{
    221. let arr = vDate.answerList.map((item:any,i:number)=>{
    222. return vDate.answerList[i].questionOptionId!=vDate.answerLists[i].questionOptionId
    223. })
    224. let indexs = arr.findIndex((item:any)=>item==true)
    225. if(indexs!=-1){
    226. vDate.answerList.forEach((item:any,v:number)=>{
    227. if(v>indexs){
    228. item.questionId = ""
    229. item.questionOptionId = ""
    230. }
    231. })
    232. }
    233. }
    234. clearTimeout()
    235. },300)
    236. }else{
    237. vDate.isAnswer = true
    238. vDate.next = 1
    239. vDate.isNext = null
    240. }
    241. vDate.answerList[i].questionId = item.questionId
    242. console.log(vDate.answerList,"vDate.answerList111")
    243. setTimeout(()=>{
    244. let index = vDate.dataList.findIndex(((item:any)=>item.questionId == val.relationQuestionId))
    245. if(index!=-1){
    246. let nextArr = vDate.dataList[index] //当前页项
    247. let flag = vDate.answerList[index].questionId
    248. if(flag){
    249. let arr = nextArr.optionList.filter((item:any)=>item.questionOptionId == vDate.answerList[index].questionOptionId)
    250. if(!arr[0].relationQuestionId){
    251. vDate.isAnswer = true
    252. vDate.next = 1
    253. }
    254. }
    255. }
    256. },500)
    257. }
    258. //获取题目
    259. const queryList = ()=>{
    260. let params = {
    261. questionGroup:1
    262. }
    263. getQuestionList(params).then((res:any)=>{
    264. vDate.dataList = res.data
    265. res.data.forEach((item:any)=>{
    266. vDate.idList.push(item.questionId)
    267. vDate.answerList.push({
    268. questionId:'',
    269. questionOptionId:''
    270. })
    271. })
    272. vDate.questionId = res.data[0].questionId
    273. vDate.answerLists = JSON.parse(JSON.stringify(vDate.answerList))
    274. })
    275. }
    276. onMounted(()=>{
    277. queryList()
    278. })
    279. </script>

    看下题目的数据结构

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

  • 相关阅读:
    Log4j additivity属性简介说明
    lv11 嵌入式开发 计算机硬件基础 1
    面试突击30:线程池是如何执行的?拒绝策略有哪些?
    Python的内置函数(十七)、replace()
    代码随想录51——动态规划:309最大买卖股票时机含冷冻期、714买卖股票的最大时机含手续费、300最长递增子序列
    POI.5.2.4常用操作-数据导入导出常规操作
    Django的简单介绍
    [附源码]Python计算机毕业设计Django校园订餐系统
    121. 买卖股票的最佳时机
    记docker部署logstash的一次报错
  • 原文地址:https://blog.csdn.net/xy19950125/article/details/128112616