效果图:
页面:
@if(!empty($id))
@foreach($LuckyDrawDatas as $key => $item)
请输入奖品
请选择类型
{{--
数量
中奖概率
+
@if($key>0)
-
@endif
@if (!empty( $id ))
@endif
@endforeach
@else
请输入奖品
请选择类型
数量
中奖概率
+
@endif
js:
//添加奖品项
$(document).on('click', '.add_prize', function() {
// layer.msg('响应点击事件');
var str = '\n' +
' 请输入奖品 \n' +
' \n' +
' \n' +
' \n' +
'\n' +
' 请选择类型 \n' +
' \n' +
' \n' +
' \n' +
' \n' +
' \n' +
' \n' +
' \n' +
'\n' +
' 数量 \n' +
' \n' +
' \n' +
' \n' +
'\n' +
' 中奖概率 \n' +
' \n' +
' \n' +
' \n' +
'\n' +
' + \n' +
' - \n' +
' ';
$("#goods_div>div:last").append(str);
form.render('select');
});
//减少奖品项
$(document).on('click', '.delete_prize', function() {
$(this).parent().remove();
});
控制器:
//新增或者编辑活动
//数据写入活动奖品表
// $data['goods_info'] = [['goods_name'=>'饮水机', 'quantity'=>10], ['goods_name'=>'净水器', 'quantity'=>20]];
foreach ($data['name'] as $k=>$v){
$data['goods_info'][] = ['goods_name'=>$v, 'quantity'=>$data['quantity'][$k], 'rate'=>$data['rate'][$k], 'id'=>isset($data['prize_id'][$k])?$data['prize_id'][$k]:''];
}
if(isset($data['goods_info'])){
//当编辑时减少了奖品项
$oldPrizeIds = $LuckyDraw::where('draw_id', $id)->pluck('id')->toArray();
$diff = array_diff($oldPrizeIds, $data['prize_id']);
if($diff){
foreach ($diff as $m){
$flag = $LuckyDraw->deleteLuckyDraw($m);
}
}
foreach ($data['goods_info'] as $key=>$val){
$data['name'] = $val['goods_name'];
$data['quantity'] = $val['quantity'];
$data['rate'] = $val['rate'];
$data['draw_id'] = $draw_id;
$flag = $LuckyDraw->saveLuckyDraw($data, $val['id']);
if(!$flag){
$msg = '添加失败';
throw new AdminException($msg,-1);
}
}
}else{
$flag = $LuckyDraw->saveLuckyDraw($data);
}
模型:
public function saveLuckyDraw($data,$id) {
if($item = $this->fill($data)->toArray()){
if($id){
return LuckyDraw::where('id', $id)->update($item);
}else{
return LuckyDraw::insert($item);
}
}
}
public function updateData($data) {
LuckyDraw::where('id',$data['id'])->decrement('quantity');// 已中奖,库存自减 1
//当奖品库存为0,从原奖品数组中剔除已经中奖礼品 将库存为0奖品设为删除状态。
$quantity = LuckyDraw::where('id',$data['id']) -> value('quantity');
if($quantity <= 0){
$this->deleteLuckyDraw($data['id']);
}
}
public function deleteLuckyDraw($id) {
$item['status'] = 1;
LuckyDraw::where('id',$id)->update($item);
}
ps:抽奖代码
//抽奖管理 -- 开始抽奖
public function beganToDraw (Request $request) {
//获取用户登录等信息
global $_U;
$user = $_U["user"];
//从数据库中获取用户是否已经参加抽奖
$user_id = $user['id'];
$DrawInfo = new DrawInfo();
if($DrawInfo->where("user_id", $user_id)->count()>0){
return json_encode(array('code'=>0,'msg'=>'您的抽奖机会已经用完'));
}
//高并发情况,先将用户进入抽奖前置集合,
//判断用户是否已在抽奖前置集合,如果在则已抽奖,否则未抽奖
// 用户抽奖前置集合,为了避免重复抽奖,做一个判断
$isExist = Redis::sAdd('user_set',$user_id);
if(!$isExist){
return json_encode(array('code'=>0,'msg'=>'正在抽奖中,请等待结果。'));
}
//初始化奖品池,7个奖品,满概率100,最小概率为1
$model = new LuckyDraw();
$list = $model -> where('status',0) -> get() -> toArray();
/* 抽奖操作,抽奖前判断redis队列库存量 */
$count=Redis::lpop('goods_store:1');//lpop是移除并返回列表的第一个元素。
if(!$count) return '已经抢光了哦';
/* 下面处理抽奖成功流程 */
//下标存储数组,按概率分配对应的数量
$indexArr = array();
for($i=0;$i $prizeInfo['id']);
$model -> updateData($quantity);
//生成一个用户抽奖的数据,用来记录到数据库
$data=array(
'id'=>'',
'user_name'=>$user['name'],
'user_id'=>$user_id,
'content'=>$prizeInfo['name'],//中奖信息
'created_at'=>date('Y-m-d H:i:s')
);
//将用户抽奖信息数组写入数据库
$DrawInfo->saveDate($data);
$data['code'] = 1;
$data['msg'] = array(
'pnum' => $prize_index,//对应前端奖品编号
'pid' => $prizeInfo['id'],
'pname' => $prizeInfo['name']
);
// dd($data);
return json_encode($data);
}
//往redis的goods_store列表中存入库存
public function addRedis(){
$model = new LuckyDraw();
// $num = $model -> where('status',0) -> sum('quantity');//奖品库存
$num=10; //库存
$len=Redis::llen('goods_store:1'); //检查库存,goods_store:1 定义为健名
$count = $num-$len; //实际库存-被抢购的库存 = 剩余可用库存
for($i=0;$i<$count;$i++) Redis::lpush('goods_store:1',1);//往goods_store列表中存入库存,未抢购之前这里应该是默认滴push10个库存数了
// echo Redis::llen('goods_store:1');//未抢购之前这里就是10了
}
参考链接:
redis实现高并发下的抢购/秒杀功能:https://www.cnblogs.com/phpper/p/7085663.html
php 抽奖算法(适合九宫格和大转盘):https://www.jianshu.com/p/78dbd20a1f10
PHP抽奖功能实例:https://www.php.cn/php-weizijiaocheng-383400.html