一、业务背景:最近在开发一个微信小程序试题“顺序练习”模块,该模块里有一定数量的试题集合,包括单选题、多选题、判断题、简答题和应用题,每个登录用户可以进入该模块进行顺序练习,同时在做题的过程中,会对试题是否做对/做错,是否做过,用户答案进行记录,和相关数量的统计。简单来说,就是针对该模块,每个用户都有个完成情况记录,以便每次进入的时候都会在上次的完成的情况下,继续进行练习,这样每次进入就会知道上次练习到哪里。
二、功能需求描述:操作用户每次进入该模块,都会根据查询到的自己该模块的完成情况记录把已经做过的试题进行默认选中和变成不可选的状态,只有没有做过的试题是可选的状态,这样用户就知道那些题之前已经做过了,那些试题还没有做过。以下给出单选题和多选题做过和未做过效果图:
三、实现思路:不管切换到那道题,都遍历一次该用户在该模块的试题完成记录,通过判断当前题是否之前做过,如何做过,即从记录中拿到做过的答案,进行赋值并设置相关属性为不可选择状态,没有则反之,是可以选择答题的。
四、关键代码如下:
A.单选题和多选题标签代码:
<view v-for="(items, indexs) in optionList">
<!-- 单选题 questionType:试题类型 optionItems:当前试题的选项集合 prefix:选项前缀,例如:A/B/C/D -->
<!-- disabled: 是否可选状态值 correct:试题正确答案 content:选项对象的内容值-->
<!-- optionAnswer:为该用户之前做过的答案,与选项进行匹配,如何相等即默认上该选项 -->
<radio-group v-if="items.questionType == 1">
<label v-for="(item, index) in items.optionItems" :key="index" class="options-label" @click="itemClickChe(indexs, items, index, item)">
<radio style="transform:scale(0.95)"
:value="item.prefix"
:checked="item.prefix === items.optionAnswer"
:color="item.prefix == items.correct ? '#07c160' : '#ff0000'"
:disabled="items.disabled"/>
<view class="options-rich-text">
<rich-text :nodes="item.prefix"></rich-text>
<text>.</text>
<rich-text :nodes="item.content"></rich-text>
</view>
</label>
</radio-group>
<!-- 多选题 showCheckbox:提交按钮控制值 其他值和单选题代表涵义一样 -->
<!-- :value="items.result":用于存放用户选择的选项值,如果一开始就存放值,就会默认选中相关选项 -->
<view v-if="items.questionType == 2">
<van-checkbox-group :value="items.result" @change="onCheckbox(items.id, indexs, $event)">
<van-checkbox shape="square" :disabled="items.disabled" class="options-label" v-for="(item, index) in items.optionItems" :key="index" :name="items.id + item.prefix" :checked-color="'#07c160'">
<view class="options-rich-text">
<rich-text :nodes="item.prefix"></rich-text>
<text>.</text>
<rich-text :nodes="item.content"></rich-text>
</view>
</van-checkbox>
</van-checkbox-group>
<view class="checkbox-options-btn" v-show="items.showCheckbox == 'false'"><button form-type="submit" @click="formCheckBoxSubmit(indexs, items)">提交</button></view>
</view>
</view>
B.JS中相关代码:
data() {
return {
//试题集合
optionList: [],
};
},
methods: {
//根据试题Id查询该试题信息,index当前试题在试题集合中的下标
async wxGetQuestionById(id, index){
await wxGetQuestionById(id).then(res=>{
//拿到当前试题详细信息
let getQuesIndetail = res.response;
if(getQuesIndetail != null){
//循环改用户顺序练习记录,拿到当前题的用户答案和判定该题是否做过
this.questionFinishDetail.specialFinishDetail.forEach((item,index)=>{
if(item.questionId == getQuesIndetail.id){
//获取用户答案
getQuesIndetail.optionAnswer = item.optionAnswer;
//用户答案和正确答案不符合 即显示答案和解析
if(getQuesIndetail.correct == item.optionAnswer || item.optionAnswer == ''){
//试题答案和解析不显示设置
getQuesIndetail.answerShow = 'false';
}else{
//试题答案和解析显示设置
getQuesIndetail.answerShow = 'true';
}
//isFirstClick 是否做过标志,1代表没做过,2代表已做过
//如果练习记录中查询到该题做过,即设置相关值为不可选状态
if(item.isFirstClick == 2){
getQuesIndetail.disabled = true;
}else{
getQuesIndetail.disabled = false;
}
}
});
//此处后台拿到的多选题答案是逗号隔开的字符串,然而:value="items.result"需要是数组格式,需做格式转换
if (getQuesIndetail.questionType == 2) {
if(getQuesIndetail.disabled = false){
//提交按钮显示
getQuesIndetail.showCheckbox = 'false';
}else{
//提交按钮不显示
getQuesIndetail.showCheckbox = 'true';
}
const changeCorrect = getQuesIndetail.correct;
const arrayCorrect = changeCorrect.split(',');
getQuesIndetail.correct = arrayCorrect;
getQuesIndetail.result = new Array();
//如果做过,遍历把每个选项答案上带id, 重新放入数组,再赋值给result,这样做是区分其他多选题,以免选择过程影响其他试题
if(getQuesIndetail.optionAnswer != ''){
getQuesIndetail.optionAnswer.forEach((itemx,indexs)=>{
getQuesIndetail.result.push(getQuesIndetail.id + itemx)
})
}else{
getQuesIndetail.result = new Array(0);
}
}
}
this.optionList[index] = getQuesIndetail;
//此方法主要使用主要解决赋值后页面值不能及时刷新的问题
this.$set(this.optionList, index, this.optionList[index]);
});
//调取收藏列表
this.selectByFavoriteType();
},
//单选题点击事件,可拿到当前索引和试题信息
itemClickChe(indexs, items, index, item){
//进行相关业务逻辑处理.........
},
//多选题选择事件,可拿到当前索引和选择的答案集合
onCheckbox(id, index, event){
//进行相关业务逻辑处理.........
},
//多选题提交按钮,和获取当前索引和试题信息
formCheckBoxSubmit(indexs, items){
//进行相关业务逻辑处理.........
}
}
五、欢迎提问和指正!