生成问卷的部分参考
微信小程序做问卷——前端部分(生成问卷)
实现效果
界面如下,分别展示了三种题型,单选题,多选题,简答题。
单选只可以选择一个,多选可以选择多个,问答题写在
<textarea>
中,点击完成会打印出整个表的数据。
比如下面是默认的数据
现在勾选单选和多选,以及改变回答部分再看一下数据
可以看到数据是匹配的,所以最后只要把生成好的数据提交到后端,那么一份问卷就算是完成了。
实现
因为是先写的
微信小程序做问卷——前端部分(生成问卷)
,所以重复的部分不再赘述了,建议先看生成问卷部分,回答问卷比生成问卷的逻辑简单一些。
数据结构还是一样的,先是生成问卷,然后再填写生成好的问卷,所以两者的数据结构是一致的。
questionnaireArray: [
{
"type": "SCQ",
"content": {
"description": "Which fruit do you like best?",
"options":
[
{ "id": 1, "name": "Lua", "isSelected": false },
{ "id": 2, "name": "Java", "isSelected": false },
{ "id": 3, "name": "C++", "isSelected": false }
]
}
},
{
"type": "MCQ",
"content": {
"description": "Which fruit do you like?",
"options":
[
{ "id": 1, "name": "OK", "isSelected": false },
{ "id": 2, "name": "Java", "isSelected": false },
{ "id": 3, "name": "C++", "isSelected": false }
]
}
},
{
"type": "SAQ",
"content": {
"description": "What's your name?",
"answer": "i dont know"
}
}
],
单选部分
<block wx:if="{{item.type === 'SCQ'}}">
<view class = 'SCQ' data-id='{{fatherIndex}}'>
<view class='SCQTitle'>
<view class='SCQQ'>Q</view>
<view class='SCQindex'>{{fatherIndex+1}}</view>
<view class='SCQquto'>:</view>
<text class='SCQDiscription' data-id='{{fatherIndex}}'>{{item.content.description}}</text>
</view>
<radio-group class="SCQOption" bindchange="radioChangeSCQ">
<label class="SCQText" wx:for="{{item.content.options}}" wx:key="SCQID" data-id='{{fatherIndex}}' bindtouchstart='getTempFatherIndex'>
<radio value="{{item.name}}" checked="{{item.isSelected}}"/>{{item.name}}
</label>
</radio-group>
</view>
</block>
用的结构还是和之前的一样,不一样的是用的
<radio-group>
,在这个里面申明
<radio>
会自动生成单选按钮,以及实现逻辑,即在众多选项中只可以有一个处于被勾选的状态。
但是他并不能改变js中的数据,所以还是要在
radioChangeSCQ
里面自己写逻辑(这部分可能有API会直接得到,但是由于我是先写生成部分,所以逻辑可以直接拿来用)
radioChangeSCQ:function(input){
var tempFatherIndex = this.data.currentFatherIndex;
var tempArray = this.data.questionnaireArray;
for (var i in tempArray[tempFatherIndex].content.options){
if (tempArray[tempFatherIndex].content.options[i].name == input.detail.value){
tempArray[tempFatherIndex].content.options[i].isSelected = true;
}
else{
tempArray[tempFatherIndex].content.options[i].isSelected = false;
}
}
this.setData({
questionnaireArray: tempArray,
});
},
其中
input.detail.value
就是
一个
object
,比如上图展示的第一题点击
Java
的时候,
Java
被勾选,那么该值就是
Java
这部分主要是在页面变更的时候,也可以改变js中的数据。首先拿到父节点的索引,再取得子节点的索引,然后再选项中遍历一遍,所以选项是和自己点击的
input.detail.value
一致的话,就把数据的选择改成选中状态,那么其他的选项都可以设置为没有被选中的状态。
多选部分
<block wx:if="{{item.type === 'MCQ'}}">
<view class = 'MCQ' data-id='{{fatherIndex}}'>
<view class='MCQTitle'>
<view class='MCQQ'>Q</view>
<view class='MCQindex'>{{fatherIndex+1}}</view>
<view class='MCQquto'>:</view>
<text class='MCQDiscription' data-id='{{fatherIndex}}'>{{item.content.description}}</text>
</view>
<checkbox-group class="MCQOption" bindchange="checkboxChangeMCQ">
<label class="MCQText" wx:for="{{item.content.options}}" wx:key="MCQID" data-id='{{fatherIndex}}' bindtouchstart='getTempFatherIndex'>
<checkbox value="{{item.name}}" checked="{{item.isSelected}}" data-id='{{index}}'/>{{item.name}}
</label>
</checkbox-group>
</view>
</block>
这里的
input.detail.value
是
多个
值,比如第二题
OK
和
C++
,那么该值是
[OK,C++]
这是和单选有区别的地方
这里用的是
<checkbox-group>
,在里面使用
<checkbox>
属性会自动生成多选界面以及逻辑,同样数据的改变还是需要在
checkboxChangeMCQ
中
checkboxChangeMCQ:function(input){
// console.log(input.detail.value);
var flag = false;
var tempFatherIndex = this.data.currentFatherIndex;
var tempArray = this.data.questionnaireArray;
for (var i in tempArray[tempFatherIndex].content.options) {
flag = false;
for(var j in input.detail.value){
if (tempArray[tempFatherIndex].content.options[i].name == input.detail.value[j]){
flag = true;
}
}
if(flag == true){
tempArray[tempFatherIndex].content.options[i].isSelected = true;
}
else{
tempArray[tempFatherIndex].content.options[i].isSelected = false;
}
}
this.setData({
questionnaireArray: tempArray,
});
},
这里的逻辑就是对每个选项进行判断,判断是否处在被选中的选项之后,是就勾选,设置了
flag
,是只要满足有一个相同就可以了。
问答部分
<block wx:if="{{item.type === 'SAQ'}}">
<view class = 'SAQ' data-id='{{fatherIndex}}'>
<view class='SAQTitle'>
<view class='SAQQ'>Q</view>
<view class='SAQindex'>{{fatherIndex+1}}</view>
<view class='SAQquto'>:</view>
<text class='SAQDiscription' data-id='{{fatherIndex}}'>{{item.content.description}}</text>
</view>
<textarea auto-height='true' class = "SAQAnswer" value='{{item.content.answer}}' bindblur='bindblurAnswerOfSAQ' data-id='{{fatherIndex}}'></textarea>
</view>
</block>
和生成问卷的时候一致,为了完整性写在这里,但是不再解释了。
bindblurAnswerOfSAQ: function (input) {
var tempIndex = input.currentTarget.dataset.id;
var tempArray = this.data.questionnaireArray;
tempArray[tempIndex].content.answer = input.detail.value;
// console.log(tempArray[tempIndex].content);
this.setData({
questionnaireArray: tempArray,
});
},
全部代码
item.wxml
<view id="title">
<view class='titleContent'>问卷</view>
<image class='titlePriceIcon' src='{{priceIcon}}' mode='widthFix'></image>
<view class='priceContent'>25</view>
<view class='priceUnit'>元</view>
</view>
<view id = 'body' wx:for="{{questionnaireArray}}" wx:key="id" wx:for-index='fatherIndex'>
<block wx:if="{{item.type === 'SCQ'}}">
<view class = 'SCQ' data-id='{{fatherIndex}}'>
<view class='SCQTitle'>
<view class='SCQQ'>Q</view>
<view class='SCQindex'>{{fatherIndex+1}}</view>
<view class='SCQquto'>:</view>
<text class='SCQDiscription' data-id='{{fatherIndex}}'>{{item.content.description}}</text>
</view>
<radio-group class="SCQOption" bindchange="radioChangeSCQ">
<label class="SCQText" wx:for="{{item.content.options}}" wx:key="SCQID" data-id='{{fatherIndex}}' bindtouchstart='getTempFatherIndex'>
<radio value="{{item.name}}" checked="{{item.isSelected}}"/>{{item.name}}
</label>
</radio-group>
</view>
</block>
<block wx:if="{{item.type === 'MCQ'}}">
<view class = 'MCQ' data-id='{{fatherIndex}}'>
<view class='MCQTitle'>
<view class='MCQQ'>Q</view>
<view class='MCQindex'>{{fatherIndex+1}}</view>
<view class='MCQquto'>:</view>
<text class='MCQDiscription' data-id='{{fatherIndex}}'>{{item.content.description}}</text>
</view>
<checkbox-group class="MCQOption" bindchange="checkboxChangeMCQ">
<label class="MCQText" wx:for="{{item.content.options}}" wx:key="MCQID" data-id='{{fatherIndex}}' bindtouchstart='getTempFatherIndex'>
<checkbox value="{{item.name}}" checked="{{item.isSelected}}" data-id='{{index}}'/>{{item.name}}
</label>
</checkbox-group>
</view>
</block>
<block wx:if="{{item.type === 'SAQ'}}">
<view class = 'SAQ' data-id='{{fatherIndex}}'>
<view class='SAQTitle'>
<view class='SAQQ'>Q</view>
<view class='SAQindex'>{{fatherIndex+1}}</view>
<view class='SAQquto'>:</view>
<text class='SAQDiscription' data-id='{{fatherIndex}}'>{{item.content.description}}</text>
</view>
<textarea auto-height='true' class = "SAQAnswer" value='{{item.content.answer}}' bindblur='bindblurAnswerOfSAQ' data-id='{{fatherIndex}}'></textarea>
</view>
</block>
</view>
<button class="weui-btn" type="primary" bindtap='complete'>完成</button>
item.wxss
.arrow{
width: 10px;
height: 10px;
border-top: 2px solid #999;
border-right: 2px solid #999;
transform: rotate(-135deg);
margin-top:60rpx;
margin-left: 60rpx;
}
.backContent{
margin-top:40rpx;
margin-bottom: 20rpx;
}
#back{
display: flex;
flex-direction: row;
border: 2px solid #999;
}
#title{
display: flex;
flex-direction: row;
background-color: #E3E3E3;
padding: 30rpx;
}
.titlePriceIcon{
width: 60rpx;
position: absolute;
right: 120rpx;
}
.titleContent{
margin-left: 50rpx;
}
.priceContent{
position: absolute;
right: 70rpx;
}
.priceUnit{
position: absolute;
right: 20rpx;
}
.SCQselectIcon{
width: 60rpx;
}
.SCQOption{
display: flex;
flex-direction:column;
margin-top: 20rpx;
}
.MCQselectIcon{
width: 60rpx;
}
.SCQ{
padding: 20rpx;
border: 2rpx solid #999;
}
.SCQText{
margin-left: 20rpx;
/* color: #E3E3E3; */
/* border: 2rpx solid #999; */
width: 90%;
word-break: keep-all;
word-wrap: break-word;
}
.MCQ{
padding: 20rpx;
border: 2rpx solid #999;
}
.MCQText{
margin-left: 20rpx;
/* color: #E3E3E3; */
/* border: 2rpx solid #999; */
width: 90%;
word-break: keep-all;
word-wrap: break-word;
}
.SAQ{
padding: 20rpx;
border: 2rpx solid #999;
}
.SCQTitle{
display: flex;
flex-direction: row;
}
.MCQTitle{
display: flex;
flex-direction: row;
}
.SAQTitle{
display: flex;
flex-direction: row;
}
.MCQOption{
display: flex;
flex-direction: column;
margin-top: 20rpx;
}
.SAQAnswer{
border: 2px solid #999;
}
.SCQDiscription{
/* border: 2rpx solid #999; */
width: 90%;
word-break: keep-all;
word-wrap: break-word;
}
.MCQDiscription{
/* border: 2rpx solid #999; */
width: 90%;
word-break: keep-all;
word-wrap: break-word;
}
.SAQDiscription{
/* border: 2rpx solid #999; */
width: 90%;
word-break: keep-all;
word-wrap: break-word;
}
.SCQdeleteIcon{
width: 80rpx;
margin-left: 20rpx;
}
.MCQdeleteIcon{
width: 80rpx;
margin-left: 20rpx;
}
.SCQdeleteIcon1{
width: 60rpx;
margin-left: 20rpx;
}
.MCQdeleteIcon1{
width: 60rpx;
margin-left: 20rpx;
}
.SAQdeleteIcon{
width: 60rpx;
margin-left: 50rpx;
}
.SCQaddIcon1{
width:60rpx;
margin-left: 20rpx;
}
.MCQaddIcon1{
width:60rpx;
margin-left: 20rpx;
}
#body{
margin-top: 100rpx;
}
.weui-btn{
width: 50%;
margin-bottom: 20rpx;
}
item.js
// pages/yaoxh6/item/item.js
Page({
/**
* 页面的初始数据
*/
data: {
priceIcon: "../../../images/price.png",
currentFatherIndex: 0,
questionnaireArray: [
{
"type": "SCQ",
"content": {
"description": "Which fruit do you like best?",
"options":
[
{ "id": 1, "name": "Lua", "isSelected": false },
{ "id": 2, "name": "Java", "isSelected": false },
{ "id": 3, "name": "C++", "isSelected": false }
]
}
},
{
"type": "MCQ",
"content": {
"description": "Which fruit do you like?",
"options":
[
{ "id": 1, "name": "OK", "isSelected": false },
{ "id": 2, "name": "Java", "isSelected": false },
{ "id": 3, "name": "C++", "isSelected": false }
]
}
},
{
"type": "SAQ",
"content": {
"description": "What's your name?",
"answer": "i dont know"
}
}
],
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
console.log(options.id)
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide: function () {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function () {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function () {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage: function () {
},
// fun : function(){
// var q = {
// test: this.data.test,
// test2: this.data.test2
// }
// wx.cloud.callFunction({
// name: 'release_questionnaire',
// data: {
// content: JSON.stringify(q)
// },
// success: res => {
// // test = JSON.stringify(res)
// // this.setData({
// // test : JSON.stringify(res.result.results.data[0].description)
// // })
// console.log('success')
// }
// })
// },
// fun2 : function(){
// wx.cloud.callFunction({
// name: 'get_all_questionnaire',
// success: res => {
// console.log(res)
// var last = res.result.results.data[8].content
// this.setData({
// test: JSON.parse(last).test
// })
// console.log('success')
// }
// })
// }
goBack : function(){
console.log('to task page')
wx.switchTab({
url: '../task/task',
})
},
getTempFatherIndex: function (input) {
var tempFatherIndex = input.currentTarget.dataset.id;
//console.log('currentFatherIndex: ' + tempFatherIndex);
this.setData({
currentFatherIndex: tempFatherIndex,
});
},
radioChangeSCQ:function(input){
var tempFatherIndex = this.data.currentFatherIndex;
var tempArray = this.data.questionnaireArray;
for (var i in tempArray[tempFatherIndex].content.options){
if (tempArray[tempFatherIndex].content.options[i].name == input.detail.value){
tempArray[tempFatherIndex].content.options[i].isSelected = true;
}
else{
tempArray[tempFatherIndex].content.options[i].isSelected = false;
}
}
this.setData({
questionnaireArray: tempArray,
});
},
checkboxChangeMCQ:function(input){
// console.log(input.detail.value);
var flag = false;
var tempFatherIndex = this.data.currentFatherIndex;
var tempArray = this.data.questionnaireArray;
for (var i in tempArray[tempFatherIndex].content.options) {
flag = false;
for(var j in input.detail.value){
if (tempArray[tempFatherIndex].content.options[i].name == input.detail.value[j]){
flag = true;
}
}
if(flag == true){
tempArray[tempFatherIndex].content.options[i].isSelected = true;
}
else{
tempArray[tempFatherIndex].content.options[i].isSelected = false;
}
}
this.setData({
questionnaireArray: tempArray,
});
},
bindblurAnswerOfSAQ: function (input) {
var tempIndex = input.currentTarget.dataset.id;
var tempArray = this.data.questionnaireArray;
tempArray[tempIndex].content.answer = input.detail.value;
// console.log(tempArray[tempIndex].content);
this.setData({
questionnaireArray: tempArray,
});
},
complete :function(){
console.log(this.data.questionnaireArray);
},
})