diff --git a/application/api/model/Lottery.php b/application/api/model/Lottery.php index 287ca324..84c715fc 100644 --- a/application/api/model/Lottery.php +++ b/application/api/model/Lottery.php @@ -47,7 +47,6 @@ class Lottery extends Model //送礼 开启事务 Db::startTrans(); //扣除用户金币并记录日志 -// $wallet_update = model('api/GiveGift')->change_user_cion_or_earnings_log($send_uid,$all_gift_price,$room_id,1,10,'用户金币购买幸运币礼物'); $wallet_update = model('api/UserWallet')->change_user_cion_log($send_uid, $all_gift_price, $room_id, 10, '用户金币购买幸运币礼物'); if(!$wallet_update){ Db::rollback(); @@ -62,7 +61,10 @@ class Lottery extends Model //送给一人礼物的总价格(扣除用户的数额) $gift_price = $gift_info['gift_price'] * $num; - + //幸运币收益率 + $lucky_rate = db::name('bb_lottery_config')->where(['key' => 'lucky_rate'])->value('value'); + $recv_coin = round($gift_price * $lucky_rate / 100, 2); + $small_pool = $gift_price - $recv_coin; foreach ($toarray as $k => $to_id){ // 1. 记录礼物赠送 $giftRecord = [ @@ -70,30 +72,24 @@ class Lottery extends Model 'recv_uid' => $to_id, 'gift_id' => $gift_id, 'gift_gold' => $gift_price, - 'recv_gold' => $gift_price /2 , - 'small_pool_add' => $gift_price /2 , - 'create_time' => time() + 'recv_gold' => $recv_coin, + 'small_pool_add' => $small_pool, + 'create_time' => time(), + 'remark' => '幸运币收益率'.$lucky_rate.'%' ]; $giftId = Db::name('bb_lottery_gift_record')->insertGetId($giftRecord); //收礼记录行为日志 - $give_gift = model('api/SendGift')->change_user_give_gift_log($send_uid,$gift_id,$gift_price,$num,$to_id,2,1,0,'送幸运币'); + $give_gift = model('api/SendGift')->change_user_give_gift_logs($send_uid,$gift_id,$gift_price,$num,$to_id,2,1,0,'送幸运币'); if(!$give_gift){ Db::rollback(); return ['code' => 0, 'msg' => '送礼失败', 'data' => null]; } //计算收礼人得益 - $receiver_earnings = $gift_price /2/get_system_config_value('rmb_coin_ratio'); + $receiver_earnings = $recv_coin/get_system_config_value('rmb_coin_ratio'); //增加收益并记录日志 -// $receiver = model('api/GiveGift') -> change_user_cion_or_earnings_log($to_id,$receiver_earnings,$room_id,2,11,'收幸运币礼增加收益'); - $receiver = model('api/UserWallet')->change_user_earnings_log($to_id,$receiver_earnings,$room_id,11,'收幸运币礼增加收益'); + $receiver = model('api/UserWallet')->change_user_earnings_log($to_id,$receiver_earnings,$room_id,11,'收幸运币礼物增加收益'); -// //用户魅力等级更新 -// $user_level = model('api/Level')->user_level_data_update($to_id,$gift_price,2,$room_id); -// if(!$user_level){ -// Db::rollback(); -// return ['code' => 0, 'msg' => '用户等级更新失败', 'data' => null]; -// } //增加房间幸运值 db::name('vs_room')->where(['id' => $room_id])->setInc('luck_value',$gift_price); db::name('vs_room_luck_value')->insert( [ @@ -134,8 +130,63 @@ class Lottery extends Model } - //抽奖 + //抽奖(不带大奖池) public function lottery($send_uid,$gift_price,$num,$room_id,$giftId,$fromUserInfo=null,$gift_info=null) + { + $small_prize_play_image = db::name('bb_lottery_config')->where(['key' => 'small_prize_play_image'])->value('value'); + try { + $gift_gold = $gift_price; + $service = new LotteryService(); + for($i=0;$i<$num;$i++){ + $reslut = $service->handleGift($send_uid, $gift_gold, $giftId); + if ($reslut['code'] == 1) { + $result = $reslut['data']; + //(未开奖时) + if ($result['is_small_prize'] == 0) { + //不做处理 + } else {//开奖 + $beilv = floor($result['small_prize_amount'] / $gift_price); + $wallet_update = model('api/UserWallet')->change_user_cion_log($send_uid,$result['small_prize_amount'],$room_id,58,'参与幸运币活动获得'.$beilv.'倍'); + if(!$wallet_update){ + return ['code' => 0, 'msg' => '流水记录失败', 'data' => null]; + } + + $tet['text'] = '恭喜用户'.$fromUserInfo['nickname'].'在幸运币活动中获得幸运币'.$beilv.'倍'; + $tet['type'] = 2; + $tet['beilv'] = $beilv; + $tet['play_image'] = $small_prize_play_image; + $tet['FromUserInfo'] = $fromUserInfo; + $tet['user_id'] = $send_uid; + model('api/Chat')->sendMsg(1100,$room_id,$tet); + + $push = new Push($send_uid, $room_id); + $room_name = Db::name('vs_room')->where(['id' => $room_id, 'apply_status' => 2])->value('room_name'); + $text = '恭喜'.$fromUserInfo['nickname'] . '在' . $room_name . '房间获得幸运币'. $beilv . '倍'; + $text_list_new[] = [ + 'text' => $text, + 'gift_picture' => $gift_info['base_image'], + 'room_id' => $room_id, + 'fromUserName' => $fromUserInfo['nickname'], + 'toUserName' => '', + 'giftName' => '', + 'roomId' => $room_id, + 'number' => 1, + ]; + $push->giftBanner($text_list_new); + } + } + } + return ['code' => 1, 'msg' => '送礼成功', 'data' => null]; + } catch (Exception $e) { + Log::error('抽奖处理失败:' . $e->getMessage()); + return ['code' => 0, 'msg' => $e->getMessage(), 'data' => null]; + } + } + + + + //抽奖(带大奖池) + public function lotterys($send_uid,$gift_price,$num,$room_id,$giftId,$fromUserInfo=null,$gift_info=null) { $big_prize_play_image = db::name('bb_lottery_config')->where(['key' => 'big_prize_play_image'])->value('value'); $small_prize_play_image = db::name('bb_lottery_config')->where(['key' => 'small_prize_play_image'])->value('value'); @@ -143,7 +194,7 @@ class Lottery extends Model for($i=0;$i<$num;$i++){ $gift_gold = $gift_price; $service = new LotteryService(); - $reslut = $service->handleGift($send_uid, $gift_gold, $giftId); + $reslut = $service->handleGifts($send_uid, $gift_gold, $giftId); if ($reslut['code'] == 1) { $result = $reslut['data']; //(未开奖时) diff --git a/application/common/library/LotteryGiftLua.php b/application/common/library/LotteryGiftLua.php index d39bcf59..9bf9b1fc 100644 --- a/application/common/library/LotteryGiftLua.php +++ b/application/common/library/LotteryGiftLua.php @@ -8,39 +8,26 @@ class LotteryGiftLua public static function getLotteryLuaScript() { return <<= small_trigger_times then result.is_small_prize = 1 -- 小奖随机比例 - local small_ratio = math.random(2, 99) + local small_ratio = math.random(2, lottery_rate) result.small_prize_amount = math.floor(small_total_gold * small_ratio / 100 * 100) / 100 - -- 小奖剩余金额(划入大奖池当前轮次) - result.small_remain_amount = math.floor((small_total_gold - result.small_prize_amount) * 100) / 100 - + -- 重置小奖池,小轮次+1 redis.call('set', small_total_times_key, 0) redis.call('set', small_total_gold_key, 0) small_round = small_round + 1 redis.call('set', small_round_key, small_round) result.small_round = small_round - - -- 6. 小奖剩余划入大奖池当前轮次 - big_total_gold = math.floor((big_total_gold + result.small_remain_amount) * 100) / 100 - redis.call('set', big_total_gold_key, big_total_gold) - result.big_total_gold = big_total_gold - - -- 7. 大奖池开奖判断(大轮次+1) - if big_total_gold >= big_threshold then - result.is_big_prize = 1 - -- 大奖比例权重 - local weight_sum = 20 + 50 + 30 - local random_weight = math.random(1, weight_sum) - local big_ratio = random_weight <= 20 and 60 or (random_weight <= 70 and 70 or 80) - -- 大奖金额 - result.big_prize_amount = math.floor(big_total_gold * big_ratio / 100 * 100) / 100 - result.big_release_amount = math.floor((big_total_gold - result.big_prize_amount) * 100) / 100 - - -- 原有逻辑:重置大奖池,大轮次+1 - redis.call('set', big_total_gold_key, 0) - big_round = big_round + 1 - redis.call('set', big_round_key, big_round) - -- 强制保证小轮次≥大轮次 - if small_round < big_round then - small_round = big_round - redis.call('set', small_round_key, small_round) - result.small_round = small_round - end - result.big_round = big_round - result.big_total_gold = 0 - - -- ===================== 新增核心逻辑 ===================== - -- 小奖开奖金额累加到大奖池下一轮次(新的big_round) - result.small_prize_to_big_next_round = result.small_prize_amount - -- 原子性更新大奖池下一轮次金额 - local new_big_total_gold = math.floor(result.small_prize_amount * 100) / 100 - redis.call('set', big_total_gold_key, new_big_total_gold) - result.big_total_gold = new_big_total_gold - -- ====================================================== - end + end -- 返回结果 @@ -132,6 +71,8 @@ LUA; } + + // 获取Lua脚本 public static function getLotteryLuaScripts() { diff --git a/application/common/service/LotteryService.php b/application/common/service/LotteryService.php index 1e1bf602..8a8feea6 100644 --- a/application/common/service/LotteryService.php +++ b/application/common/service/LotteryService.php @@ -104,6 +104,99 @@ class LotteryService throw new Exception('参数错误'); } + // 读取配置+独立轮次 + $small_trigger_times = intval($this->config['small_pool_trigger_times'] ?? 200);//触发抽奖次数 + $small_round = intval($this->redis->get('lottery:small_pool:round') ?: 1);//小奖轮次 + $lucky_rate = db::name('bb_lottery_config')->where(['key' => 'lucky_rate'])->value('value');//收益率 + $lottery_rate = db::name('bb_lottery_config')->where(['key' => 'lottery_rate'])->value('value');//爆币率 + + + // 加载Lua脚本 + $luaSha = LotteryGiftLua::getLotteryLuaScript(); + + // 执行Lua脚本(入参:small_round + big_round) + $result = $this->redis->eval($luaSha, [ + $send_uid, + $gift_gold, + $small_trigger_times, + $small_round, + $lucky_rate, + $lottery_rate + ], 0); + + $result = json_decode($result, true); + if (json_last_error() !== JSON_ERROR_NONE) { + throw new Exception('Lua脚本执行失败'); + } + + // 开启数据库事务 + Db::startTrans(); + try { + // . 1记录小奖池累计流水(未开奖时) + if ($result['is_small_prize'] == 0) { + $this->addPoolFlow( + 1, // 小奖池 + 1, // 累计 + $result['small_pool_add'], + $result['small_total_gold'] - $result['small_pool_add'], + $result['small_total_gold'], + $giftId, + $result['small_round'], // 新增:传入轮次 + "小奖池累计:用户{$send_uid}送礼,轮次{$result['small_round']}" + ); + } else { + $winnerUid = $send_uid; // 奖默认给当前送礼用户 + //2.开小奖剩余划入大奖后 大奖够开奖 + // 小奖中奖记录 + $this->addWinnerRecord( + $winnerUid, + 1, // 小奖 + $result['small_prize_amount'],//中奖金额 + $result['small_total_gold'],//奖池总金额 + $this->getSmallRatio($result['small_prize_amount'], $result['small_total_gold']),//中奖比例 + 0 //释放金额 + ); + // 3. 小奖池开奖流水 + $this->addPoolFlow( + 1, // 小奖池 + 2, // 开奖扣除 + $result['small_prize_amount'], + $result['small_total_gold'], + $result['small_total_gold'] - $result['small_prize_amount'], + $giftId, + $result['small_round'] - 1, // 开奖轮次为当前轮次-1(已结束的轮次) + "小奖池开奖:轮次" . ($result['small_round'] - 1).",中奖金额:{$result['small_prize_amount']}金币" + ); + } + + Db::commit(); + return [ + 'code' => 1, + 'msg' => '处理成功', + 'data' => $result + ]; + } catch (Exception $e) { + Db::rollback(); + throw new Exception($e->getMessage()); + } + } + + + /** + * 处理送礼抽奖逻辑 (带大奖池) + * @param int $send_uid 送礼用户ID + * @param float $gift_gold 礼物金币数 + * @param int $giftId 礼物ID + * @return array 处理结果 + * @throws Exception + */ + public function handleGifts($send_uid, $gift_gold, $giftId) + { + // 参数校验 + if ($gift_gold <= 0 || !$send_uid) { + throw new Exception('参数错误'); + } + // 读取配置+独立轮次+大奖池金额 $small_trigger_times = intval($this->config['small_pool_trigger_times'] ?? 200); $big_threshold = floatval($this->config['big_pool_threshold'] ?? 1000);