在getVoteStatus的云函数目录下的index.js补充上篇文章的三个函数,代码如下:
function?checkAlreadyVoted(voteList,?openid){
???//?检查用户是否已经参与过投票了
??let?alreadyVoted?=?false?//?默认用户没有参与投票
??voteList.map(voteItem?=>?{?//?遍历所有的用户投票,将数组中的每个元素执行一次下面的代码
????if(voteItem.openid?==?openid){?//?如果某个投票记录的openid与用户openid相同
??????alreadyVoted?=?true?//?那么用户显然参与了本次投票
????}
??})
??return?alreadyVoted
}
function?getTotalVoteCount(voteList){
??//?计算得到所有选项投票的总数量
??let?totalVoteCount?=?0?//初始数量为0
??voteList.map(voteItem?=>?{?//遍历所有用户投票
????totalVoteCount?+=?voteItem.pickedOption.length?//将总数加上每一次的投票的数量
??})
??return?totalVoteCount
}
function?getOptionStatus(voteList,?openid,?optionLength){
???//?计算得到每个选项的投票数量,以及用户是否选择了该选项
???let?optionStatus?=?new?Array(optionLength)?//?新建一个与选项长度一样的数组
???for(let?i?=?0;?i?<?optionStatus.length;?i++)?{
?????optionStatus[i]?=?{?//?初始化数组中的每个元素
???????count:?0,?//?默认每个选项的投票数量为0
???????vote:?false?//?默认用户没有投这个选项
?????}
???}
???voteList.map(voteItem?=>?{??//?遍历所有的用户投票
?????const?userVoteThis?=?(voteItem.openid?==?openid)??//?如果openid一致,那么这个投票时该用户投的,反之则不是
?????voteItem.pickedOption.map(pickedIndex?=>?{??//?遍历这个投票的选项
??????optionStatus[pickedIndex].count++?//?对应选项的数量加1
??????if?(userVoteThis)?{??//?只有当这个投票是该用户投时,更新vote属性
????????optionStatus[pickedIndex].vote?=?true
??????}
?????})
???})
???return?optionStatus
}
用户投票时需要修改vote集合中的投票记录,但是这条记录时属于投票的创建者的,其他用户没有权限修改该数据。但在云函数使用服务端的数据库API不受数据库权限设置的限制,因此使用云函数实现投票功能,从而绕开小程序端API的权限限制。
新建云函数vote,在vote文件夹下的index.js文件中实现投票的功能,代码如下:
//?云函数入口文件
const?cloud?=?require('wx-server-sdk')
cloud.init({?env:?cloud.DYNAMIC_CURRENT_ENV?})?//?使用当前云环境
const?db?=?cloud.database()
//?云函数入口函数
exports.main?=?async?(event,?context)?=>?{
??const?wxContext?=?cloud.getWXContext()
??const?openid?=?wxContext.OPENID?//?获取用户的openid
??//?从postData中获取3个属性的值
??const?{?voteID,?pickedOption,?userInfo?}?=?event.postData
??//?将openid,pickedOption和,userInfo保存到voteItem对象中(匿名投票没有userInfo
??const?voteItem?=?userInfo????{
????openid,
????pickedOption,
????userInfo
??}?:?{
????openid,
????pickedOption,
??}
??//?在votes集合中,对该投票的voteList字段插入一条数据
??return?await?db.collection('votes').doc(voteID).update({
????voteList:?db.command.push(voteItem)
??})
}
------
上传云函数vote。
在小程序端的pages/vote/vote.js,onTapVlue函数实现调用云函数的逻辑,代码如下:
??onTapVote(){
????if(this.data.isAnonymous)?{//匿名投票的情况
??????const?postData?=?{//需要提交的数据
????????voteID:?this.data.voteID,
????????pickedOption:?this.data.pickedOption
??????}
??????//?将postData数据上传到服务器端
??????wx.cloud.callFunction({
????????name:?'vote',
????????data:?{
??????????postData
????????}
??????}).then(res?=>?{
????????console.log(res)
????????this.getVoteStatusFromServer(this.data.voteID)?//从服务器端获取投票情况??
??????}).catch(res?=>?{
????????console.error(res)
????????wx.showToast({
??????????title:?'投票失败',
??????????icon:?'none'
????????})
??????})
????}?else?{?//实名投票的情况
????????const?_this?=?this?//在API接口的函数中,this会被改变,因此需要提前获取this的值到_this中
????????wx.getUserProfile({
??????????desc:?'desc',
??????????success:(res)?=>?{??//授权成功后,调用wx.getUserProfile接口时会回调这个函数
????????????const?postData?=?{
??????????????voteID:?_this.data.voteID,
??????????????userInfo:?res.userInfo,?//获取用户信息
??????????????pickedOption:?_this.data.pickedOption
????????????}
????????????//?将postData数据上传到服务器端?
????????????wx.cloud.callFunction({
??????????????name:?'vote',
??????????????data:?{
????????????????postData
??????????????}
????????????}).then(res?=>?{
??????????????console.log(res)
??????????????_this.getVoteStatusFromServer(_this.data.voteID)?//从服务器端获取投票情况??
????????????}).catch(res?=>?{
??????????????console.error(res)
??????????????wx.showToast({
????????????????title:?'投票失败',
????????????????icon:?'none'
??????????????})
????????????})
??????????}
????????})
????}
??}
完成。