廢話不多說,先上完成的結果圖,如果覺得,功能跟你的相似,或者覺得有幫助,那麼就繼續閱讀,copy
代碼,如果覺得有出入,也可以看看思路。
完成的功能:
- 根據後端返回值,渲染問卷題目及題目對應的選項,可以是單選,可以是輸入框。
- 禁止用戶用手向左向右滑動問卷調查
- 點擊上一題跳轉上一題,點擊下一題,跳轉下一題,最後一項是提交
- 展示完成的進度
- 當用戶尚未選擇或者輸入,則彈出彈框,提示用戶先輸入
- 用戶選擇後高亮對應item
- 用戶選擇後,將選擇的結果保存,最後提交最終的結果數組
後端返回的問卷數據格式如下圖所示:
最後點擊提交向端發送的數據格式如下:
整體不難,代碼註釋也寫的比較清楚,有需要的自取:
wxml
:
<view class="question-con">
<view class="line">
<view class="active" style="width:{{activeWidth}}rpx;background-color: #37C2BC;"></view>
</view>
<view class='qs-con'>
<swiper class='sheet' current='{{curId}}'>
<block wx:for="{{questions}}" wx:key="id" wx:for-index="i">
<swiper-item catchtouchmove="forbid">
<view class="title">{{item.question}}</view>
<view class="option-con" wx:if="{{item.type===2}}">
<block wx:for="{{item.options}}" wx:for-item="option" wx:key="id">
<view class="option {{survey_result[i].value===option.id?'select-active':''}}" bindtap="handleSelect" data-id="{{item.id}}" data-value="{{option.id}}" data-index="{{i}}">
{{option.text}}
</view>
</block>
</view>
<view wx:else>
<input data-id="{{item.id}}" data-index="{{i}}" placeholder="{{item.placeholder}}" class="range" type="number" placeholder-style="color:#C7C7C7;font-size:36rpx;" bindinput="handleInput" />
</view>
</swiper-item>
</block>
</swiper>
</view>
<view class='button-group'>
<view class='button' hover-class='none' bindtap='handleLast' disabled='{{curId==0}}'>
上一題
</view>
<view wx:if="{{curId<count-1}}" class='button' hover-class='none' form-type='submit' bindtap='handleNext'>
下一題
</view>
<view wx:else class='button' hover-class='none' form-type='submit' bindtap='handleNext'>
提交
</view>
</view>
</view>
js
文件:
// import request from '../../servers/request'
import { showToast } from '../../utils/util'
Page({
data: {
questions: [],
// 有幾項問卷
count: 0,
// 問卷目前正在哪項
curId: 0,
// 藍色進度條寬度
activeWidth: 0,
// 向後端返回的數據
survey_result: []
},
onLoad() {
// 問卷後端返回數組
const questions = [
{
question: '問題一:今年高考題難嗎',
type: 2,
id: 1,
options: [
{
id: 1,
text: '非常困難'
},
{
id: 2,
text: '有點難'
},
{
id: 3,
text: '正常'
},
{
id: 4,
text: '比較簡單'
},
{
id: 5,
text: '非常非常簡單'
}
]
},
{
question: '2. 我覺得比平時容易緊張或着急',
type: 2,
id: 2,
options: [
{
id: 6,
text: '非常困難2'
},
{
id: 7,
text: '有點難2'
},
{
id: 8,
text: '正常2'
},
{
id: 9,
text: '比較簡單2'
},
{
id: 10,
text: '非常非常簡單2'
}
]
},
{
question: '3. 我覺得比平時容易緊張或着急',
type: 2,
id: 3,
options: [
{
id: 11,
text: '非常困難3'
},
{
id: 12,
text: '有點難3'
},
{
id: 13,
text: '正常3'
},
{
id: 14,
text: '比較簡單3'
},
{
id: 15,
text: '非常非常簡單3'
}
]
},
{
question: '4. 高三最差一次年級排名是',
type: 1,
id: 4,
placeholder: '請輸入最差一次年級排名'
},
{
question: '5. 高三最好一次年級排名是',
type: 1,
id: 5,
placeholder: '請輸入最好一次年級排名'
}
]
this.setData({
questions: questions,
count: questions.length,
// 最終的問卷調查結果
survey_result: Array(questions.length).fill(0)
})
},
// 點擊問卷某個選項進行下一步問卷
handleNext() {
const { curId, count, survey_result } = this.data
if (!survey_result[curId].value) {
showToast('請先選擇', 'none', true)
return
}
const step = 670 / count
this.setData({
curId: curId + 1,
activeWidth: step * (curId + 1)
})
},
// 上一步
handleLast() {
const { curId, count } = this.data
if (this.data.curId !== 0) {
this.setData({
curId: curId - 1
})
}
const step = 670 / count
this.setData({
activeWidth: step * (curId - 1)
})
},
// 用戶選擇了某項
handleSelect(e) {
console.log('e:', e)
const { id, value, index } = e.currentTarget.dataset
const { survey_result } = this.data
survey_result.splice(index, 1, { id, value })
this.setData({
survey_result
})
console.log('survey_result:', this.data.survey_result)
},
// 如果有是輸入框,則輸入
handleInput(e) {
const { value } = e.detail
const { id, index } = e.currentTarget.dataset
const { survey_result } = this.data
survey_result.splice(index, 1, { id, value })
this.setData({
survey_result
})
console.log('survey_result:', this.data.survey_result)
},
// 靜止用手左右滑動
forbid() {
return false
}
})
css
文件:
page {
height: 100%;
}
.question-con {
display: flex;
flex-direction: column;
align-items: center;
padding: 0 40rpx;
height: 100%;
}
.line {
box-sizing: border-box;
margin-top: 70rpx;
width: 670rpx;
height: 8rpx;
background: rgba(245, 245, 245, 1);
border-radius: 60rpx;
}
.active {
box-sizing: border-box;
background-color: #37C2BC;
height: 8rpx;
border-radius: 60rpx;
}
.qs-con {
width: 100%;
margin-top: 48rpx;
flex: 1;
}
.sheet {
display: flex;
flex-direction: column;
height: 100%;
}
.title {
font-size: 36rpx;
font-weight: 600;
line-height: 50rpx;
color: rgba(33, 33, 33, 1);
}
.option-con {
margin-top: 84rpx;
display: flex;
flex-direction: column;
align-items: center;
font-size: 32rpx;
font-weight: 400;
color: rgba(0, 0, 0, 1);
}
.option {
width: 400rpx;
line-height: 100rpx;
background: rgba(245, 245, 245, 1);
border-radius: 60rpx;
text-align: center;
}
.option-con :not(:first-child) {
margin-top: 30rpx;
}
.range {
margin-top: 16rpx;
color: #37C2BC;
}
.button-group {
display: flex;
flex-direction: row;
width: 80%;
height: 150rpx;
margin: auto;
justify-content: space-between;
align-items: center;
}
.button {
background: #37C2BC;
border-radius: 8rpx;
font-size: 32rpx;
line-height: 88rpx;
height: 88rpx;
width: 172rpx;
font-weight: bold;
text-align: center;
color: #fff;
}
.button::after {
border: 0;
}
.select-active {
background-color: #37C2BC;
color: #fff;
}
註釋比較清楚了,多看幾遍就懂了,關鍵字高亮的思想就是,將需要展示的文本,根據關鍵字進行拆成數組,然後再根據關鍵字判斷是否需要高亮。如果有不懂的可以加我微信qdw1370336125相互交流。