最近项目有个需求,需要实现连续签到奖励不同积分,中间断签则重新计算的功能,弄了一晚上,写了一个雏形demo,记下开发思路。
需要考虑部分:
1,会员基数大,如果每个人的签到记录都存入数据库,每次签到查询会造成较大的查询和写入压力
2,签到不同天数积分的获取问题
初步设定优化方案:每次会员签到,触发删除签到记录,删除掉该会员数据两天前的签到数据,保留前一天的签到作为签到存档
开发思路:会员表增加连续签到天数字段,每次签到优先判断昨天是否有签到,如果有,则根据会员签到天数表去获取对应的奖励,同时需更新会员表连续签到次数;如果没有,则表示今天第一天敲到,则更新对应奖励和设置会员连续签到字段值为1.
数据库设计:user 表增加continuity_day(连续签到天数),jifen(积分)字段,签到记录表:member_id,aword_jifen,create_time 三个字段。
前端:
js:
$("#LAY_signin").click(function(){{
$have_session = $("#have_session").val();
if($have_session == 'no'){
layer.msg('请先登录');
}else{
$.post('{:url("index/user/qiandao")}',{}, function(data){
console.log(data);
if(data.code==200){
var icon = 6;
}else{
var icon = 2;
}
layer.alert(data.msg, {icon: 6,title:'温馨提示'});
}, 'json');
}
}})
php用到的公共函数
//验证数组是否存在
function havedata($array){
if(isset($array) && !empty($array)){
return true;
}else{
return false;
}
}
//获取指定时间间隔的是时间戳
function getLastTime($day,$type="before"){
$data = array();
if($type == "before"){
$str = date("Y-m-d",strtotime("-{$day} day"))." 0:0:0";
$data["star"] = strtotime($str);
$str = date("Y-m-d",strtotime("-{$day} day"))." 24:00:00";
$data["end"] = strtotime($str);
}else{
$str = date("Y-m-d",strtotime("+{$day} day"))." 0:0:0";
$data["star"] = strtotime($str);
$str = date("Y-m-d",strtotime("+{$day} day"))." 24:00:00";
$data["end"] = strtotime($str);
}
return $data;
}
控制器:
//用户签到
public function qiandao(){
$qiandao_effect = Loader::model('Member')->qiandao();
return $qiandao_effect;
}
模型:
//用户签到
public function qiandao(){
if(!Session::has('member_info')){
return info("您还没有登录",4001);
}else{
$member_session = Session::get("member_info");
$this->del_qiandao($member_session['member_id']);
$now_time = strtotime(date("Y-m-d 0:0:0",time()));
$check_qiandao = Db::name("qiandao")->where("create_time",">=",$now_time)->where('member_id',$member_session['member_id'])->find();
if(havedata($check_qiandao)){
return info("您今天已经签到过了",4002);
}else{
//检查昨天是否有签到过,如果有,则为连续签到,根据签到规则,设置相对应积分
$qiandao_array = [5,6,7,8,9,10,15]; //签到积分奖励
$yestaday = getLastTime(1,'before');
$check_before_qiandao = $this->check_qiandao($yestaday['star'],$yestaday['end']);
$member_info = $this->member_info($member_session['member_id']);
if($check_before_qiandao){
//说明昨天有签到,则获取连续签到天数
if($member_info['continuity_day'] >= 7){
$aword_jifen = 15;
}else{
$aword_jifen = $qiandao_array[$member_info['continuity_day']];
}
$first_qian = "no";
}else{
//昨天没有签到,则今天算是第一个签到
$aword_jifen = $qiandao_array[0]; //没有连续签到,则从开始计算
$first_qian = "yes";
}
//更新账户积分余额和签到次数
if($first_qian == "yes"){
$update_data = [
'jifen' => $member_info['jifen']+$aword_jifen,
'continuity_day' => 1
];
}else{
$update_data = [
'jifen' => $member_info['jifen']+$aword_jifen,
'continuity_day' => $member_info['continuity_day']+1
];
}
//更新会员数据
$update_member = Db::name("member")->where("member_id",$member_session['member_id'])->update($update_data);
//增加签到记录
$insert_qiandao = [
'member_id' => $member_info['member_id'],
'aword_jifen' => $aword_jifen,
'create_time' => time(),
];
$insert_effect = Db::name("qiandao")->insert($insert_qiandao);
if($insert_effect){
return info('签到成功',200);
}else{
return info('签到失败',4001);
}
}
}
}
//清除掉用户两天前的登录记录,防止用户登录数据过大,同时为连续签到保存依据
public function del_qiandao($member_id){
$two_days_before = getLastTime(2,'before');
Db::name('qiandao')->where("create_time","<=",$two_days_before['star'])->where('member_id',$member_id)->delete();
}