基于thinkphp5的抽奖实现,支持后台设置抽奖概率、奖品排序

请输入图片描述

<?php
namespace app\index\controller;
use think\Controller;
class Lottery extends Base
{
    //奖品配置信息
    protected $prize;

    //用户id
    protected $uid;

    /**
     * 初始化奖品配置信息
     */
    public function _initialize()
    {
        //从数据库读取奖品信息
        /**
         * 数据表结构
         * id
         * name 奖品名称
         * type 类型,用来标识奖品的类型,比如实物、积分(需要自动充值到用户账户)、谢谢惠顾(不需要做任何处理)
         * points_num  如果是积分、金额这种需要自动充值到账户的,需要填写该字段
         * thumb 缩略图,可在大转盘显示
         * rate  中奖概率,小数表示
         * num   奖品总数
         * overplus_num  剩余奖品数量
         * status 状态  0禁止,1正常
         * sort  排序 奖品出现在转盘或者跑马灯上的顺序
         * addtime  添加时间
         * edittime 修改时间 
         */
        $this->prize = db('prize')->where('status',1)->order('sort')->select();

        //获取登录用户的id,写中奖纪录、查询是否有抽奖条件等
        $this->uid = session('uid');
    }

    /**
     * 抽奖
     */
    public function lottery() {

        if(!$this->uid) {
            return json(['status'=>0,'msg'=>'登录之后才能抽奖']);
        }

        //给奖品数组添加数字范围,随机数落到这个范围,就表示抽中该奖品
        $this->addRange();

        //抽奖,得到本次抽奖的奖品信息
        $prize = $this->getPrize();

        //检查这个奖品数量是否被抽完,如果抽完,重新抽奖返回奖品信息,直到抽到有存量奖品;所有奖品都抽完,返回false
        $prize = $this->checkPrizeNum($prize);
        if(false === $prize) {
            return json(['status' => 0,'msg' => '来晚了!奖品已被洗劫一空!']);
        }

        //减少奖品剩余数量
        $this->decreaseNum($prize);

        //写抽奖记录,得到记录id 
        $log_id = $this->addLog($prize);

        //抽奖结果是积分,需要充值到用户账户
        if($prize['type'] == 2) {
            $this->handlePoint($prize,$log_id);
        }

        //返回抽奖结果给前台
        // return json(['status' => 1,'msg'=>'抽奖结果:'.$prize['name']]);

        //返回全部奖品信息给前台 $prize中包含所有奖品配置信息,$log_id抽奖记录的id
        return json(['status'=>1,'msg'=>'','data' => $prize,'log_id' => $log_id]);

    }

    /**
     * 增加随机数范围到奖品列表数组中,抽奖的概率精确到千分之一,如果需要更精确的区分,调整基数即可!
     */
    private function addRange()
    {
        $current_number = 0;

        foreach($this->prize as $key=>$item) {

            if($item['rate'] == 0.001) {
                $this->prize[$key]['range_start'] = 1000 * $item['rate'] +  $current_number;
                $this->prize[$key]['range_end'] = $this->prize[$key]['range_start'];

                $current_number = $this->prize[$key]['range_end'];

            } else if ($item['rate'] == 0) {

                $this->prize[$key]['range_start'] = 0;
                $this->prize[$key]['range_end'] = 0;

            } else  {

                $this->prize[$key]['range_start'] = $current_number + 1 ;
                $this->prize[$key]['range_end'] = 1000*$item['rate'] +  $current_number ;

                $current_number = $this->prize[$key]['range_end'];
            }
        }
    }

    /**
     *  抽奖实现,获取奖品
     */
    private function getPrize()
    {
        //生成一个随机数
        $random = mt_rand(1,1000);
        // echo $random;
        foreach($this->prize as $key=>$item) {
            if($item['range_start'] <= $random && $random <= $item['range_end']) {
                return $item;
            }
        }
    }

    /**
     * 检查奖品是否抽完
     */
    private function checkPrizeNum($prize)
    {
        //剩余奖品数量
        $overplus_num = db('prize')->where('status',1)->sum('overplus_num');

        if( 0 >= $overplus_num ) {
            return false;
        }

        if( 0 >= $prize['num'] )
        {
            $prize = $this->getPrize();
            $this->checkPrizeNum($prize);
        }

        return $prize;
    }

    /**
     * 修改y_prize表中的剩余奖品数量--1
     */
    private function decreaseNum($prize)
    {
        db('prize')->where('id',$prize['id'])->setDec('overplus_num',1);
    }

    /**
     * 写入奖品记录到lottery表,返回记录的id
     */
    private function addLog($prize)
    {
        $data = [];
        $data['uid'] = $this->uid;
        $data['prize_id'] = $prize['id'];
        $data['prize_name'] = $prize['name'];
        $data['addtime'] = time();

        if(3 == $prize['type']) {
            $data['status'] = 1; //不需要发奖品,也不需要自动到账的状态写为1,不需要后台处理
        } else {
            $data['status'] = 0; //需要处理的,在后续处理过程中更改状态
        }

        $id = db('lottery_log')->insertGetId($data);

        return $id;
    }

    /**
     * 处理积分问题
     */
    private function handlePoint($prize,$log_id)
    {

        //给用户账户增加积分
        db('user_wallet')->where('uid',$this->uid)->setInc('points',$prize['points_num']);

        //把之前抽奖日志的状态从0改成1,表示该奖品已经处理完毕
        db('lottery_log')->where('id',$log_id)->update(['status'=>1]);

    }

    /**
     * 中奖用户提交领奖信息
     */
    public function addInfo()
    {
        $data['name'] = input('post.name');  
        $data['tel'] = input('post.tel');  
        $data['address'] = input('post.address');
        $data['edittime'] = time();
        $id = input('post.log_id');

        //用户提交数据验证逻辑
        /*some verify code*/

        $res = db('lottery_log')->where('id',$id)->where('uid',$this->uid)->update($data);
        if(!$res) {
            return json(['status' => 0,'msg' => '领奖信息提交失败']);
        } 
        return json(['status' => 1,'msg' => '领奖信息提交成功']);
    }
}
滇ICP备16003699号-2
最后修改:2018 年 11 月 04 日
如果觉得我的文章对你有用,请随意赞赏