微信小程序做問卷——前端部分(回答問卷)


生成問卷的部分參考微信小程序做問卷——前端部分(生成問卷)

實現效果

界面如下,分別展示了三種題型,單選題,多選題,簡答題。
界面
單選只可以選擇一個,多選可以選擇多個,問答題寫在<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多個值,比如第二題OKC++,那麼該值是[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);
  },
})
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章