一.需求
1.需要记录用户登录的openid,刮奖的时候记录刮奖的ID,次数并返回展示数据
2.需要可配置大奖图片,大奖最多出现次数,大奖概率,每个id可抽取免费次数以及分享可抽取次数,常规展示图片。常规图片需要随机出现且不重复,并返回给前端。
3.需要记录每天刮奖的次数,什么人刮奖,刮到大奖的人数,分享的点击次数
4.需要登记刮到大奖的信息
5.需要每天更新刮到大奖的次数
二.云函数
1.获取基本数据
1.1 配置基本数据
使用config表,配置对应的刮刮乐相应的数据,每次需要的时候从中获取。包含最大次数,奖品图数据(这里使用云存储,对应的fid,name等),大奖概率,免费次数,最大次数等。
每次获取对应的数据
const scratchConfig = await db.collection('config').where({type:'scratch'}).get()
const { scratch_maxTimes ,scratch_limitTimes,priceRate,maxPrice,pricePic} = scratchConfig.data[0]
1.2 获取数据
微信云函数直接用 wxContext.OPENID获取到对应的openid,不需要做处理,先判定是否存在数据,是的话更新对应数据,否则直接新增。
const wxContext = cloud.getWXContext()
const scratchInfo = await db.collection('scratch').where({
_openid: wxContext.OPENID,
}).get()
如果没有,直接新增,使用云函数add,event里面包含的是自己传入的参数。
await db.collection('scratch').add({
data:{
_openid: wxContext.OPENID,
unionid: wxContext.UNIONID,
createTime: db.serverDate(),
avatarUrl:event.avatarUrl,
nickName:event.nickName,
limitTimes: scratch_limitTimes,//限制自由可使用次数
maxTimes: scratch_maxTimes,//最大可刮次数
useTimes: 0,//已使用次数
scratchArr:[],
shareTimes: 0,//分享次数
clickTimes: 0,
showType:showType,//显示第几个图
pricePic:pricePic,//奖励可能有几个。
isSumbit: false,
}
})
2.更新数据
2.1 更新刮奖
只要刮奖了就直接发起云函数请求,更新次数,并且记录刮了哪个奖励,刮的次数要更新。 useTimes: _.inc(1),inc是自增函数,记录对应次数+1,不会因为其他的影响,数据本身会增加1。传入部分字段就更新对应字段。
let params = {
// data 传入需要局部更新的数据
data: {
useTimes: _.inc(1),
scratchArr:_.push([event.scratchIndex]),
showType:showType,
}
}
需要更新状态,还需要重新随机新的刮奖图,并且需要判定是否是大奖,是否还有次数。
需要注意每个人随机的刮奖图不能重复,这里用两个数组比对,得出结果来随机。
let bigPriceIndex = scratchData.data[0].pricePic.findIndex((x)=>x.isBigPirce) + 1
let numArr = []
scratchData.data[0].pricePic.filter((v,index)=>{
if(scratchData.data[0].scratchArr.indexOf(index+1) == -1){
numArr.push(index + 1)
}
return v
})
let showType = 1
let random = Math.random();
if (random >= 0 && random < priceRate && maxPrice > 0) {
showType = bigPriceIndex
} else {
let idx =Math.floor((Math.random()*numArr.length))
showType = numArr[idx]
}
如果是分享按钮,还需要对应处理分享次数
if(typeArr[event.updateType] === 'share'){
params = {
data: {
shareTimes: _.inc(1),
}
}
}
之后需要更新到表格,使用update
data = await db.collection('scratch').where({_openid: wxContext.OPENID}).update(params)
2.2 记录刮奖次数跟openid
每次更新的时候,记录一下次数跟日期还有openid到scratch_daily表。
先获取到日期,并设置
let date = new Date()
date = new Date(date);
let y = date.getFullYear();
let m = date.getMonth() + 1;
m = m < 10 ? ('0' + m) : m;
let d = date.getDate();
d = d < 10 ? ('0' + d) : d;
let dateStr = y + '-' + m + '-' + d;
let scratchDailyInfo = await db.collection('scratch_daily').where({
_openid: wxContext.OPENID,
scratchTime:dateStr
}).get()
判定当天日期是否有对应用户数据,是的话只是数据+1,否则新增。
2.3 更新大奖
2.3.1 更新次数
在更新刮奖的时候,也要更新一下配置中的大奖最大次数,这里inc()可以使用负数
if(showType === bigPriceIndex && maxPrice > 0){
await db.collection('config').where({type:'scratch'}).update({
// data 传入需要局部更新的数据
data: {
maxPrice: _.inc(-1)
}
})
}
2.3.2 每天重置大奖可抽取次数
新建一个云函数updateDaily,需要在config里面配置触发名字,类型跟触发方式。方式就是秒,分,时...可对应查找配置,如*表示每天
{
"permissions": {
"openapi": [
]
},
"triggers": [
{
"name": "scratchSumTrigger",
"type": "timer",
"config": "0 0 0 * * * *"
}
]
}
设置重置为10次,每次需要修改,或者是配置里面新增一个字段,用于每次重置次数,然后这里10次改成对应字段。
await db.collection('config').where({type:'scratch'}).update({
// data 传入需要局部更新的数据
data: {
maxPrice: 10
}
})
上传部署之后,还要选择上传触发器,否则不会触发。
2.4 记录次数
触发器每天更新的时候,获取全部刮奖数据,并且计算次数
const wxContext = cloud.getWXContext()
const countResult = await db.collection('scratch').count()
const total = countResult.total
// 计算需分几次取
const batchTimes = Math.ceil(total / 100)
// 承载所有读操作的 promise 的数组
const tasks = []
for (let i = 0; i < batchTimes; i++) {
const promise = db.collection('scratch') .where({
useTimes: _.gt(0),
}).orderBy('createTime','desc').skip(i * MAX_LIMIT).limit(MAX_LIMIT).get()
tasks.push(promise)
}
if(batchTimes<=0){
return {
data: [],
errMsg: 'ok',
}
}
// 等待所有
let summary = 0
let list = (await Promise.all(tasks)).reduce((acc, cur) => {
return {
data: acc.data.concat(cur.data),
errMsg: acc.errMsg,
}
})
list.data && list.data.map((item)=>{
summary += item.useTimes
})
await db.collection('scratchSum').add({
data:{
createTime: db.serverDate(),
summary:summary,
}
})
2.5 提交大奖用户信息
2.5.1 提交大奖信息
用常规的add,并保存对应数据即可,但是要先判定是否已经存在,如果已经提交,就不再更新了
前端不应该出现按钮了。添加到奖励信息表reward里面之后,需要更新isSubmit字段给前端去判定。
await db.collection('reward').add({
data:{
_openid: wxContext.OPENID,
unionid: wxContext.UNIONID,
createTime: db.serverDate(),
avatarUrl:event.avatarUrl,
nickName:event.nickName,
address: event.address,
name: event.name,
phone: event.phone,
region: event.region,
wechat: event.wechat,
}
})
await db.collection('scratch').where({_openid: wxContext.OPENID}).update({
data: {
isSumbit: true,
}
})