diff --git a/application/api/model/BlindBoxTurntableGift.php b/application/api/model/BlindBoxTurntableGift.php index beeb1f7..9e8c221 100644 --- a/application/api/model/BlindBoxTurntableGift.php +++ b/application/api/model/BlindBoxTurntableGift.php @@ -45,12 +45,10 @@ class BlindBoxTurntableGift extends Model $xlh_ext = json_decode($xlh_box['ext'],true); $xlh = []; if($xlh_ext['inlet_bag_id'] == $box['id']){ -// $room = db::name('vs_room')->field('id,xlh_periods,xlh_periods_num')->where(['id'=>$room_id])->find(); $is_xlh = 1; $xlh['waiting_start_num'] = $xlh_ext['open_condition']['waiting_start_num'];//等待开奖次数 $xlh['start_num'] = $xlh_ext['open_condition']['start_num'];//开始开奖次数 //当前抽奖次数 -// $xlh['current_num'] = $room['xlh_periods_num']; $xlh['current_num'] = Cache::get("xlh_periods_num") ?? 0; //状态 if($xlh['current_num'] >= $xlh_ext['open_condition']['start_num']){ @@ -72,559 +70,6 @@ class BlindBoxTurntableGift extends Model return ['code' => 1, 'msg' => '获取成功', 'data' => $result_data]; } - /* - * 抽奖 - */ - public function draw_gift($gift_bag_id, $user_id, $gift_user_ids,$num=1,$room_id=0,$heart_id=0) - { - // 合并配置查询 - $bag_data = db::name("vs_gift_bag") - ->field('id,name,ext') - ->where('id',$gift_bag_id) - ->find(); - - if (!$bag_data) { - return ['code' => 0, 'msg' => '盲盒配置不存在', 'data' => null]; - } - - $ext = json_decode($bag_data['ext'],true); - - // 合并盲盒和礼物信息查询 - $bag_gift = db::name("vs_gift") - ->where(['gid'=>$ext['gift_id']]) - ->find(); - - if (!$bag_gift) { - return ['code' => 0, 'msg' => '盲盒礼物不存在', 'data' => null]; - } - - // 合并巡乐会配置查询 - $xlh_box = db::name('vs_gift_bag') - ->where('id',13) - ->find(); - - $xlh_ext = $xlh_box ? json_decode($xlh_box['ext'],true) : []; - - $xlh_is_piao_ping = 0; - - // 处理收礼用户数组(多个) - $toarray = explode(',',$gift_user_ids); - - // 合并房间信息查询 - $room = db::name('vs_room') - ->field('id,room_name,xlh_periods,xlh_periods_num,is_open_blind_box_turntable') - ->where(['id'=>$room_id]) - ->find(); - - if (!$room) { - return ['code' => 0, 'msg' => '房间不存在', 'data' => null]; - } - - $this_xlh_periods_num = $room['xlh_periods_num'];//本期当前抽奖次数(巡乐会出发条件) - - // 判断是否有足够的金币 - $user_waller = db::name('user_wallet') - ->where(['user_id'=>$user_id]) - ->find(); - - if (!$user_waller) { - return ['code' => 0, 'msg' => '用户钱包不存在', 'data' => null]; - } - - // 抽奖总消耗金币 - $bag_gift_price = $bag_gift['gift_price'] * $num; - if ($user_waller['coin'] < $bag_gift_price) { - return ['code' => 0, 'msg' => '用户金币不足', 'data' => null]; - } - if ($room['is_open_blind_box_turntable'] != 1) { - return ['code' => 0, 'msg' => '该房间未开启盲盒转盘', 'data' => null]; - } - - // 预计算抽奖结果,减少数据库事务中的查询 - // 计算期数和抽奖次数 - // 合并奖池总抽奖次数和房间奖池信息查询 - $room_pan_info = db::name("vs_gift_bag_detail") - ->alias('a') - ->join('vs_room_pan b', 'b.gift_bag_detail_id = a.id AND b.room_id = ' . $room_id) - ->where(['a.gift_bag_id' => $gift_bag_id]) - ->field('SUM(a.quantity) as total_quantity, SUM(b.remaining_number) as total_remaining, MAX(b.periods) as periods') - ->find(); - - $total_quantity = $room_pan_info['total_quantity'] ?: 0; - $total_remaining = $room_pan_info['total_remaining'] ?: 0; - $periods = $room_pan_info['periods'] ?: 0; - - // 本期当前第多少次后抽奖 总的抽奖次数- 剩余数量 - $total_draw_times = $total_quantity - $total_remaining; - if($total_draw_times<0){ - $total_draw_times = 0; - } - // 预计算所有抽奖结果 - $precomputed_results = []; - $current_draw_times = $total_draw_times; - $current_periods = $periods; - $current_xlh_periods_num = $this_xlh_periods_num; - - // 生成缓存键 - $available_cache_key = 'blindbox_available_gifts_' . $gift_bag_id . '_' . $room_id; - $last_remaining_cache_key = 'blindbox_last_remaining_' . $gift_bag_id . '_' . $room_id; - - // 获取所有可用礼物用于预计算 - $available_gifts = $this->get_available_gifts_for_precompute($gift_bag_id, $room_id, $current_draw_times); - if (empty($available_gifts)) { - return ['code' => 0, 'msg' => '当前盲盒无可用礼物', 'data' => null]; - } - - $should_reset_all_gifts = false; // 标记是否需要重置所有礼物 - //如果本期奖池数量小于抽奖次数,则重置奖池,并把上期剩余数量加到本期奖池中 - //接收礼物人数 - $receive_num = count($toarray); - //需要的礼物数量 - $need_gift_num = $receive_num * $num; - $last_periods_remaining = []; - if ($total_remaining - $need_gift_num <= 0 ) { - //上期剩余礼物 - $last_periods_remaining = $available_gifts; - //加入缓存 - cache($last_remaining_cache_key, $last_periods_remaining); - // 重置奖池 - $current_periods++; - $this->reset_gift_pool($room_id, $gift_bag_id, $current_periods); - //补充上期剩余数量 - foreach ($available_gifts as $gift_data) { - db::name("vs_room_pan") - ->where(['room_id'=>$room_id,'gift_bag_id'=>$gift_bag_id,'gift_bag_detail_id'=>$gift_data['id']]) - ->setInc('remaining_number', $gift_data['remaining_number']); - } - // 重新获取可用礼物 - $current_draw_times = 0; - $available_gifts = $this->get_available_gifts_for_precompute($gift_bag_id, $room_id, $current_draw_times); - $should_reset_all_gifts = false; // 重置标记 - } - //加入缓存 - cache($available_cache_key, $available_gifts); - // 预计算所有抽奖结果 - foreach ($toarray as $gift_user_id) { - if($user_id == $gift_user_id){ - return ['code' => 0, 'msg' => "收礼人不能包含自己", 'data' => null]; - } - - for($i = 0; $i < $num; $i++){ - // 使用加权随机算法预计算单次抽奖结果 - //从缓存中取出可用礼物 - if(cache($available_cache_key)){ - $available_gifts = cache($available_cache_key); - } - if(cache($last_remaining_cache_key)){ - $last_periods_remaining = cache($last_remaining_cache_key); - } - $draw_result = $this->precompute_single_draw($gift_bag_id,$room_id,$available_gifts,$last_periods_remaining); - - if (!$draw_result) { - return ['code' => 0, 'msg' => '预计算抽奖失败', 'data' => null]; - } - - $precomputed_results[] = [ - 'gift_user_id' => $gift_user_id, - 'gift_bag_detail' => $draw_result['gift_bag_detail'], - 'gift' => $draw_result['gift'], - 'draw_times' => $current_draw_times, - 'periods' => $current_periods - ]; - - $current_draw_times++; - - // 判断巡乐会飘屏判断 - $current_xlh_periods_num++; - if(!empty($xlh_ext) && $xlh_ext['inlet_bag_id'] == $gift_bag_id && $current_xlh_periods_num == $xlh_ext['open_condition']['waiting_start_num']){ - $xlh_is_piao_ping = 1; - } - if(!empty($xlh_ext) && $xlh_ext['inlet_bag_id'] == $gift_bag_id && $current_xlh_periods_num == $xlh_ext['open_condition']['start_num']){ - $xlh_is_piao_ping = 2; - } - - // 更新可用礼物数量(模拟数据库更新) - $total_remaining_after_update = 0; - foreach ($available_gifts as &$gift) { - if ($gift['id'] == $draw_result['gift_bag_detail']['id']) { - $gift['remaining_number']--; - } - - // 计算更新后的总剩余数量 - $total_remaining_after_update += $gift['remaining_number']; - } - - // 检查是否需要重置所有礼物 - if ($total_remaining_after_update <= 0) { - $should_reset_all_gifts = true; - $current_periods++; // 增加期数 - } - } - } - // 清除相关缓存 - cache($available_cache_key, null); - cache($last_remaining_cache_key, null); - - // 开始数据库事务处理 - db::startTrans(); - try{ - // 盲盒转盘抽奖记录 - $box_turntable_log = db::name('vs_blind_box_turntable_log')->insertGetId([ - 'user_id' => $user_id, - 'gift_bag_id' => $gift_bag_id, - 'num' => $num, - 'room_id' => $room_id, - 'bag_price' => $bag_gift['gift_price'], - 'createtime' => time() - ]); - if (!$box_turntable_log) { - db::rollback(); - return ['code' => 0, 'msg' => '添加盲盒转盘记录失败', 'data' => null]; - } - - // 处理预计算的抽奖结果 - $result_draw_gift = []; - $gift_counts = []; // 统计每个礼物的数量 - $gift_user_counts = []; // 统计每个用户每个礼物的数量 - - foreach ($precomputed_results as $result) { - $gift_user_id = $result['gift_user_id']; - $gift_bag_detail = $result['gift_bag_detail']; - $gift = $result['gift']; - - $pan_data = db::name("vs_room_pan") - ->where(['room_id'=>$room_id,'gift_bag_detail_id'=>$gift_bag_detail['id']])->value("remaining_number"); - if($pan_data < 1){ - db::rollback(); - return ['code' => 0, 'msg' => '礼物数量不足', 'data' => null]; - } - // 构造返回数据 - $result_data = [ - 'user_id' => $user_id, - 'gift_user_id' => $gift_user_id, - 'gift_id' => $gift_bag_detail['foreign_id'], - 'gift_price' => $gift['gift_price'], - 'is_public_screen' => $gift['is_public_screen'], - 'periods' => $result['periods'], - ]; - $result_draw_gift[] = $result_data; - - // 统计礼物数量 - $gift_id = $gift_bag_detail['foreign_id']; - if (!isset($gift_counts[$gift_id])) { - $gift_counts[$gift_id] = [ - 'gift_id' => $gift_id, - 'count' => 0, - 'gift_price' => $gift['gift_price'] - ]; - } - $gift_counts[$gift_id]['count']++; - - // 统计用户礼物数量 - $user_gift_key = $gift_user_id . '_' . $gift_id; - if (!isset($gift_user_counts[$user_gift_key])) { - $gift_user_counts[$user_gift_key] = [ - 'gift_user_id' => $gift_user_id, - 'gift_id' => $gift_id, - 'count' => 0, - 'gift_price' => $gift['gift_price'] - ]; - } - $gift_user_counts[$user_gift_key]['count']++; - - // 处理礼包发放记录表 - $data = []; - $data['user_id'] = $user_id; - $data['gift_user_id'] = $gift_user_id; - $data['parent_id'] = $box_turntable_log; - $data['gift_bag_id'] = $gift_bag_id; - $data['gift_id'] = $gift_bag_detail['foreign_id']; - $data['periods'] = $result['periods']; - $data['room_id'] = $room_id; - $data['gift_price'] = $gift['gift_price']; - $data['bag_price'] = $bag_gift['gift_price']; - $data['createtime'] = time(); - $insert_result = db::name("vs_gift_bag_receive_log")->insert($data); - if(!$insert_result){ - db::rollback(); - return ['code' => 0, 'msg' => '插入礼包发放记录失败', 'data' => []]; - } - - // 减去盲盒包礼物数量 - $ret = db::name("vs_room_pan") - ->where(['room_id'=>$room_id,'gift_bag_detail_id'=>$gift_bag_detail['id'],"remaining_number"=>["<>",0]]) - ->setDec('remaining_number',1); - - if(!$ret){ - db::rollback(); - return ['code' => 0, 'msg' => '更新礼物剩余数量失败', 'data' => []]; - } - } - - // 扣除抽奖消耗的金币 - // 扣除用户金币并记录日志 - $wallet_update = model('GiveGift')->change_user_cion_or_earnings_log($user_id,$bag_gift_price,$room_id,1,10,'盲盒转盘抽奖消耗'); - if(!$wallet_update){ - Db::rollback(); - return ['code' => 0, 'msg' => '扣除用户金币失败', 'data' => null]; - } - // 用户财富等级更新 - $user_level = model('Level')->user_level_data_update($user_id,$bag_gift_price,1,$room_id); - if(!$user_level){ - Db::rollback(); - return ['code' => 0, 'msg' => '用户等级更新失败', 'data' => null]; - } - - db::commit(); - } catch(\Exception $e) { - db::rollback(); - return V(0,$e->getMessage()); - } - - // 批量插入盲盒转盘结果记录 - foreach ($gift_user_counts as $user_gift) { - $ret = db::name('vs_blind_box_turntable_results_log')->insert([ - 'tid' => $box_turntable_log, - 'gift_user_id' => $user_gift['gift_user_id'], - 'gift_id' => $user_gift['gift_id'], - 'count' => $user_gift['count'], - 'gift_price' => $user_gift['gift_price'], - 'all_gift_price' => $user_gift['gift_price'] * $user_gift['count'], - 'createtime' => time(), - 'heart_id' => $heart_id - ]); - if (!$ret) { - return ['code' => 0, 'msg' => '添加盲盒转盘结果记录失败', 'data' => null]; - } - - //给接收礼物的人送礼物 - $give_gift_ext['gift_id'] = $user_gift['gift_id']; - $give_gift_ext['count'] = $user_gift['count']; - $give_gift_ext['gift_price'] = $user_gift['gift_price']; - $give_gift_ext['all_gift_price'] = $user_gift['gift_price'] * $user_gift['count']; - $give_gift_ext['is_draw_gift'] = 1; - $res = model('Room')->room_gift($user_id, $user_gift['gift_user_id'], $user_gift['gift_id'], $user_gift['count'], 1, $room_id, 0,$heart_id,$give_gift_ext); - if (isset($res) && $res['code'] != 1) { - db::rollback(); - return ['code' => 0, 'msg' => $res['msg'], 'data' => null]; - } - } - - // 巡乐会 - $xlh = []; - if(!empty($xlh_ext) && $xlh_ext['inlet_bag_id'] == $gift_bag_id){ - // 巡乐会飘屏 - db::name("vs_room")->where('id',$room_id)->update([ - 'xlh_periods_num' => $current_xlh_periods_num - ]);//加巡乐会条件次数 - if($xlh_is_piao_ping == 1){ - // 即将开始推送飘屏 - $text = $room['room_name']."的巡乐会即将开始,请大家尽快参与哦!"; - // 推送礼物横幅 - $push = new Push(UID, $room_id); - $text_list_new = [ - 'text' => $text, - 'room_id' => $room_id, - 'from_type' => 1 - ]; - $push->xunlehui($text_list_new); - } - if($xlh_is_piao_ping == 2){ - // 正式开始推送飘屏 - $text = $room['room_name']."的巡乐会正式开始,请大家尽快参与哦!"; - // 推送礼物横幅 - $push = new Push(UID, $room_id); - $text_list_new = [ - 'text' => $text, - 'room_id' => $room_id, - 'from_type' => 2 - ]; - $push->xunlehui($text_list_new); - // 巡乐会正式开始 - $this_xlh_periods = db::name('vs_room')->where('id',$room_id)->value('xlh_periods'); - $pan_xlh_id = db::name('vs_room_pan_xlh')->insertGetId([ - 'room_id' => $room_id, - 'gift_id' => $xlh_ext['locking_condition']['locking_gift_id'], - 'homeowner_gift_id' => $xlh_ext['locking_condition']['give_homeowner_gift_id'], - 'periods' => $this_xlh_periods+1, - 'num' => 0, - 'end_time' => time() + $xlh_ext['locking_time']['end_time'] * 60, - 'createtime' => time() - ]); - if(!$pan_xlh_id){ - return ['code' => 0, 'msg' => '创建巡乐会失败!', 'data' => []]; - } - db::name("vs_room")->where('id',$room_id)->setInc('xlh_periods');//修改巡乐会期数 - } - - $xlh['waiting_start_num'] = $xlh_ext['open_condition']['waiting_start_num'];//等待开奖次数 - $xlh['start_num'] = $xlh_ext['open_condition']['start_num'];//开始开奖次数 - // 当前抽奖次数 - $xlh['current_num'] = $current_xlh_periods_num; - // 状态 - if($xlh['current_num'] >= $xlh_ext['open_condition']['start_num']){ - $xlh['status'] = 1;//状态 1:巡乐会开始 2:即将开始开始 0:等待开始 - } elseif($xlh['current_num'] >= $xlh_ext['open_condition']['waiting_start_num'] && $xlh['current_num'] < $xlh_ext['open_condition']['start_num']){ - $xlh['status'] = 2;//状态 1:巡乐会开始 2:即将开始开始 0:等待开始 - }else{ - $xlh['status'] = 0; - } - // 推送 - $text = [ - 'xlh_data' => $xlh, - 'text' => "" - ]; - // 聊天室推送系统消息 - model('Chat')->sendMsg(1056,$room_id,$text); - } - - // 整理返回结果 - $result_list = []; - foreach ($gift_counts as $gift) { - $result_list[] = [ - 'gift_id' => $gift['gift_id'], - 'count' => $gift['count'] - ]; - } - $reslut = []; - $reslut['blind_box_turntable_id'] = $box_turntable_log; - $reslut['reslut_list'] = $result_list; - return V(1,"成功", $reslut); - } - - /** - * 重置奖池 - * @param int $room_id 房间ID - * @param int $gift_bag_id 礼物包ID - * @param int $periods 期数 - */ - private function reset_gift_pool($room_id, $gift_bag_id, $periods) { - // 重置奖池中所有礼物数量 - db::name("vs_room_pan") - ->where(['room_id'=>$room_id,'gift_bag_id'=>$gift_bag_id]) - ->update([ - 'remaining_number' => db::raw('(SELECT quantity FROM fa_vs_gift_bag_detail WHERE id = fa_vs_room_pan.gift_bag_detail_id)'), - 'periods' => $periods - ]); - - // 更新总期数 - db::name("vs_gift_bag") - ->where('id', $gift_bag_id) - ->setInc('periods'); - } - - /* - * 获取可用礼物用于预计算 - */ - private function get_available_gifts_for_precompute($gift_bag_id, $room_id, $total_draw_times) { - $where = [ - 'a.gift_bag_id' => $gift_bag_id, - 'a.quantity' => ['>',0], - 'b.remaining_number' => ['>',0], - 'b.room_id' => $room_id, - 'a.weight' => ['<=', $total_draw_times], - ]; - - return db::name("vs_gift_bag_detail") - ->field('a.id,a.quantity,b.remaining_number,a.weight,a.foreign_id') - ->alias('a') - ->join('vs_room_pan b','b.gift_bag_detail_id = a.id','left') - ->where($where) - ->select(); - } - - /* - * 预计算单次抽奖结果 - */ - private function precompute_single_draw($gift_bag_id, $room_id, $available_gifts, $last_periods_remaining = []) { - // 生成缓存键 - $available_cache_key = 'blindbox_available_gifts_' . $gift_bag_id . '_' . $room_id; - $last_remaining_cache_key = 'blindbox_last_remaining_' . $gift_bag_id . '_' . $room_id; - - // 保证有可用礼物 - if (empty($available_gifts)) { - return false; - } - - $last_remaining_all = array_sum(array_column($last_periods_remaining, 'remaining_number')); - if ($last_remaining_all == 0) { - $last_periods_remaining = []; - cache($last_remaining_cache_key, null); - } - - $last_periods_remaining_flag = 0; - if (!empty($last_periods_remaining)) { - $available_gifts = $last_periods_remaining; - $last_periods_remaining_flag = 1; - } - - // 循环尝试直到抽中有效礼物 - $max_attempts = 5; // 最大尝试次数,防止无限循环 - $attempt = 0; - $selected_gift = null; - - while ($attempt < $max_attempts && !$selected_gift) { - // 实现加权随机算法:剩余数量越多,被抽中的概率越大 - $remaining = 0; - foreach ($available_gifts as $gift) { - $remaining += $gift['remaining_number']; - } - - if ($remaining <= 0) { - break; // 如果没有剩余数量,跳出循环 - } - - $rand_value = mt_rand(1, $remaining); - $current_sum = 0; - - foreach ($available_gifts as $gift) { - if ($gift['remaining_number'] <= 0) { - continue; - } - $current_sum += $gift['remaining_number']; - if ($rand_value <= $current_sum) { - $selected_gift = $gift; - break; - } - } - $attempt++; - } - if (!$selected_gift) { - return false; - } - - // 获取开出礼物的信息 - $gift = db::name("vs_gift") - ->where(['gid' => $selected_gift['foreign_id']]) - ->find(); - - if (!$gift) { - return false; - } - - // 操作缓存,减去缓存中对应数据数量 - foreach ($available_gifts as &$available_gifts_gift) { - if ($selected_gift['id'] == $available_gifts_gift['id']) { - $available_gifts_gift['remaining_number'] -= 1; - } - } - if ($available_gifts_gift['remaining_number'] == 0) { - unset($available_gifts_gift); - } - - if ($last_periods_remaining_flag == 1) { - // 操作上一轮奖池 - cache($last_remaining_cache_key, $available_gifts); - } else { - cache($available_cache_key, $available_gifts); - } - - return [ - 'gift_bag_detail' => $selected_gift, - 'gift' => $gift - ]; - } - /* * 礼物特效播放 */ @@ -792,11 +237,11 @@ class BlindBoxTurntableGift extends Model //巡乐会主礼物 $xlh_main_gift = db::name('vs_gift')->where('gid',$xlh_ext['locking_condition']['locking_gift_id'])->find(); //中奖用户 - $xlh_periods = $xlh_box['periods']??0; - $pan_xlh = db::name('vs_room_pan_xlh')->where(['periods'=>$xlh_periods,'send_time'=>0])->find(); + $pan_xlh = db::name('vs_room_pan_xlh')->where(['send_time'=>0,'end_time'=>['>',time()]])->order('id desc')->find(); $xlh_periods_num = Cache::get("xlh_periods_num") ?? 0; if(empty($pan_xlh)){ if($xlh_periods_num >= $xlh_ext['open_condition']['start_num']){ + $xlh_periods = Cache::get("this_xlh_periods") ?? 0; $pan_xlh_id = db::name('vs_room_pan_xlh')->insertGetId([ 'room_id' => $room_id, 'gift_id' => $xlh_ext['locking_condition']['locking_gift_id'], @@ -806,7 +251,7 @@ class BlindBoxTurntableGift extends Model 'end_time' => time() + $xlh_ext['locking_time']['end_time'] * 60, 'createtime' => time() ]); - db::name("vs_room")->where('id',$room_id)->setInc('xlh_periods');//修改巡乐会期数 + Cache::set("this_xlh_periods", $xlh_periods+1, 0);//修改巡乐会期数 $pan_xlh = db::name('vs_room_pan_xlh')->where(['id'=>$pan_xlh_id])->find(); }else{ return ['code' => 0, 'msg' => '未开始', 'data' => null]; @@ -855,255 +300,6 @@ class BlindBoxTurntableGift extends Model return ['code' => 1, 'msg' => '获取成功', 'data' => $result_data]; } - /* - * 巡乐会抽奖 - */ - public function xlh_draw_gift($user_id,$num,$room_id){ - $gift_bag_id = 13; - //获取盲盒配置 - $bag_data = db::name("vs_gift_bag")->field('id,name,ext,periods')->where('id',$gift_bag_id)->find(); - $ext = json_decode($bag_data['ext'],true); - //判断是否有足够的金币 - $bag_gift_price = $ext['xlh_box_price'] * $num; - $user_waller = db::name('user_wallet')->where(['user_id'=>$user_id])->find(); - if ($user_waller['coin'] < $bag_gift_price) { - return ['code' => 0, 'msg' => '用户金币不足', 'data' => null]; - } - $room = db::name('vs_room')->where(['id'=>$room_id])->find(); - if ($room['is_open_blind_box_turntable'] != 1) { - return ['code' => 0, 'msg' => '该房间未开启盲盒转盘', 'data' => null]; - } - //开始抽奖 - $pan_xlh = db::name('vs_room_pan_xlh')->where(['room_id'=>$room_id,'periods'=>$room['xlh_periods']])->find(); - if(empty($pan_xlh)){ - return ['code' => 0, 'msg' => '未开始', 'data' => null]; - } - if($pan_xlh['end_time']<=time()){ - return ['code' => 0, 'msg' => '本轮已结束', 'data' => null]; - } - if($pan_xlh['send_time']!=0){ - return ['code' => 0, 'msg' => '本轮已结束,礼物已发放', 'data' => null]; - } - $is_zhong_jiang = 0; - $pan_xlh_num = $pan_xlh['num']; - //奖池总的抽奖次数 - $total_quantity = db::name("vs_gift_bag_detail")->where(['gift_bag_id' => $gift_bag_id])->sum('quantity'); - - db::startTrans(); - try{ - //扣除抽奖消耗的金币 - //扣除用户金币并记录日志 - $wallet_update = model('GiveGift')->change_user_cion_or_earnings_log($user_id,$bag_gift_price,$room_id,1,10,'巡乐会抽奖消耗'); - if(!$wallet_update){ - Db::rollback(); - return ['code' => 0, 'msg' => '扣除用户金币失败', 'data' => null]; - } - //用户财富等级更新 - $user_level = model('Level')->user_level_data_update($user_id,$bag_gift_price,1,$room_id); - if(!$user_level){ - Db::rollback(); - return ['code' => 0, 'msg' => '用户等级更新失败', 'data' => null]; - } - - //开始抽奖 - for($i = 0; $i < $num; $i++){ - //本期当前第多少次后抽奖 总的抽奖次数- 剩余数量 - $room_pan = db::name("vs_room_pan")->where(['room_id'=>$room_id,'gift_bag_id'=>$gift_bag_id])->field('remaining_number,periods')->find(); - if(empty($room_pan)){ - return ['code' => 0, 'msg' => '当前房间未配置抽奖礼物,请联系管理员', 'data' => []]; - } - $total_remaining = db::name("vs_room_pan")->where(['room_id'=>$room_id,'gift_bag_id'=>$gift_bag_id])->sum('remaining_number'); - $total_draw_times = $total_quantity - $total_remaining; - //随机获取一个礼物 - $where = [ - 'a.gift_bag_id' => $gift_bag_id, - 'b.room_id' => $room_id, - 'a.quantity' => ['>',0], - 'b.remaining_number' => ['>',0], - 'a.weight' => ['<=', $total_draw_times], - ]; - // 使用闭包条件来处理复杂的 weight 逻辑 -// $where['a.weight'] = ['exp', Db::raw('= 0 OR a.weight < '.$total_draw_times)]; - // 优化:基于剩余数量的加权随机选择 - $gift_bag_details = db::name("vs_gift_bag_detail") - ->field('a.id,a.quantity,b.remaining_number,a.weight,a.foreign_id') - ->alias('a') - ->join('vs_room_pan b','b.gift_bag_detail_id = a.id','left') - ->where($where) - ->select(); - if (empty($gift_bag_details)) { - return ['code' => 0, 'msg' => '当前盲盒无可用礼物', 'data' => []]; - } - // 实现加权随机算法:剩余数量越多,被抽中的概率越大 - $remaining = 0; - foreach ($gift_bag_details as $gift) { - $remaining += $gift['remaining_number']; - } - $rand_value = mt_rand(1, $remaining); - $current_sum = 0; - $gift_bag_detail = null; - foreach ($gift_bag_details as $gift) { - if($gift['remaining_number'] <= 0){ - continue; - } - $current_sum += $gift['remaining_number']; - if ($rand_value <= $current_sum) { - $gift_bag_detail = $gift; - break; - } - } - if($gift_bag_detail){ - //获取开出礼物的信息 - $gift = db::name("vs_gift")->where(['gid'=>$gift_bag_detail['foreign_id']])->find(); - //抽中礼物落包 - $res = model('UserGiftPack')->change_user_gift_pack($user_id,$gift_bag_detail['foreign_id'],1,model('UserGiftPack')::XLH_DRAW_GIFT_GET,$bag_data['name']."抽奖所得"); - if ($res['code'] != 1) { - db::rollback(); - return ['code' => 0, 'msg' => $res['msg'], 'data' => null]; - } - //处理抽中礼物命中主奖品逻辑 - if($gift_bag_detail['foreign_id'] == $ext['locking_condition']['selected_gift_id']){ - //中奖 - $pan_xlh_num = $pan_xlh_num+1; - $cache_key = 'selected_gift_id_'.$room_id.$gift_bag_detail['foreign_id']; - if($pan_xlh_num <= 1){ - $add_end_time = $ext['locking_time']['tow_no_locking_time'] * 60; - Cache::set($cache_key,$add_end_time,$add_end_time); - }else{ -// $add_end_time = ($ext['locking_time']['tow_no_locking_time']-$ext['locking_time']['next_time']) * 60; - if(Cache::get($cache_key)){ - $erci_xlh_num = Cache::get($cache_key); - $add_end_time = ($erci_xlh_num-$ext['locking_time']['next_time'] *60); - Cache::set($cache_key,$add_end_time,$add_end_time); - }else{ - $add_end_time = ($ext['locking_time']['tow_no_locking_time']-$ext['locking_time']['next_time']) * 60; - } - } - if($add_end_time <= 30){ - Cache::set($cache_key,30,30); - $add_end_time = 30; - } - $end_time = time() + $add_end_time; - db::name('vs_room_pan_xlh')->where('id',$pan_xlh['id'])->update([ - 'user_id' => $user_id, - 'pay_price' =>$ext['xlh_box_price'], - 'locking_gift_id' =>$gift_bag_detail['foreign_id'], - 'num' => $pan_xlh_num, - 'end_time' => $end_time, - 'updatetime' => time() - ]); - db::name('vs_room_pan_xlh_log')->insertGetId([ - 'xlh_id' => $pan_xlh['id'], - 'user_id' => $user_id, - 'num' => $pan_xlh_num, - 'locking_end_time' => $end_time, - 'createtime' => time() - ]); - $is_zhong_jiang = 1; - } - //减去盲盒包礼物数量 - $ret = db::name("vs_room_pan")->where(['room_id'=>$room_id,'gift_bag_detail_id'=>$gift_bag_detail['id']])->setDec('remaining_number',1); - if(!$ret){ - db::rollback(); - return ['code' => 0, 'msg' => '失败.', 'data' => []]; - } - //判断剩余数量是否为0 为0重置,进入下一期 - $gift_bag_num = db::name("vs_room_pan")->where(['room_id'=>$room_id,'gift_bag_id'=>$gift_bag_id])->sum('remaining_number'); - if($gift_bag_num <= 0){ - db::name("vs_room_pan")->where(['room_id'=>$room_id,'gift_bag_id'=>$gift_bag_id])->setInc('periods'); - db::name("vs_room_pan")->where(['room_id'=>$room_id,'gift_bag_id'=>$gift_bag_id])->update( - ['remaining_number' => db::raw('(SELECT quantity FROM fa_vs_gift_bag_detail WHERE id = fa_vs_room_pan.gift_bag_detail_id)')]); - } - }else{ - db::rollback(); - return ['code' => 0, 'msg' => '失败!', 'data' => []]; - } - $result_data[] = [ - 'user_id' => $user_id, - 'gift_id'=>$gift_bag_detail['foreign_id'], - 'gift_price'=>$gift['gift_price'], - 'gift_name'=>$gift['gift_name'], - 'base_image'=>$gift['base_image'], - - ]; - } - $reslut_data = []; - foreach ($result_data as $key => $value) { - $gift_id = $value['gift_id']; - if (!isset($reslut_data[$gift_id])) { - $reslut_data[$gift_id] = [ - 'gift_id' => $gift_id, - 'gift_price'=>$value['gift_price'], - 'gift_name'=>$value['gift_name'], - 'base_image'=>$value['base_image'], - 'count' => 1 - ]; - }else { - $reslut_data[$gift_id]['count']++; - } - } - $result_list = []; - foreach ($reslut_data as $key => $value) { - //处理礼包发放记录表 - $data = []; - $data['user_id'] = $user_id; - $data['parent_id'] = $pan_xlh['id']; - $data['gift_bag_id'] = $gift_bag_id; - $data['gift_id'] = $value['gift_id']; - $data['periods'] = $room_pan['periods']; - $data['room_id'] = $room_id; - $data['num'] = $value['count']; - $data['gift_price'] = $value['gift_price']; - $data['bag_price'] = $ext['xlh_box_price']; - $data['createtime'] = time(); - $result = db::name("vs_gift_bag_receive_log")->insert($data); - if(!$result){ - db::rollback(); - return ['code' => 0, 'msg' => '失败,', 'data' => []]; - } - $result_list[]=[ - 'gift_id'=>$value['gift_id'], - 'gift_name'=>$value['gift_name'], - 'base_image' =>$value['base_image'], - 'gift_price'=>$value['gift_price'], - 'count'=>$value['count'], - ]; - } - // 添加活动记录 - $reslut = Db::name('vs_activities_receive')->insert([ - 'user_id' => $user_id, - 'activities_id' => 6, - 'room_id' => $room_id, - 'createtime' => time(), - 'updatetime' => time() - ]); - db::commit(); - } catch(\Exception $e) { - db::rollback(); - return V(0,$e->getMessage()); - } - if($is_zhong_jiang == 1){ - //推送 - $FromUserInfo = db::name('user')->field('nickname,avatar')->where(['id'=>$user_id])->find(); - $room_name = db::name('vs_room')->where(['id'=>$room_id])->value('room_name'); - $gift_name = db::name('vs_gift')->where(['gid'=>$value['gift_id']])->value('gift_name'); - $text = $FromUserInfo['nickname'] . ' 用户在 ' . $room_name.' 房间巡乐会中 ' .$gift_name.'礼物 x ' .$value['count']." 已收入背包"; - $text = [ - 'gift_num' => $pan_xlh_num, - 'FromUserInfo' => $FromUserInfo, - 'end_time' => $end_time, - 'text' => $text - ]; - //聊天室推送系统消息 - model('Chat')->sendMsg(1057,$room_id,$text); - } - //返回结果排序 - usort($result_list, function($a, $b) { - return $b['gift_price'] <=> $a['gift_price']; - }); - return ['code' => 1, 'msg' => '成功', 'data' => $result_list]; - } - /* * 巡乐会抽奖记录 */ @@ -1159,16 +355,7 @@ class BlindBoxTurntableGift extends Model $gift_bag_id = 13; $xlh_box = db::name('vs_gift_bag')->where('id',$gift_bag_id)->find(); $xlh_ext = json_decode($xlh_box['ext'],true); - $room_data = db('vs_room') - ->where(['id'=>$room_id]) - ->field('id,room_name,xlh_periods,xlh_periods_num') - ->find(); -// $room_data['xlh_periods'] = $room_data['xlh_periods'] ?? 0; -// $xlh_data = db('vs_room_pan_xlh') -// ->where(["room_id"=>$room_id,"periods"=>$room_data['xlh_periods']]) -// ->field('id,room_id,periods,end_time') -// ->find(); - $xlh_data = db('vs_room_pan_xlh')->where(["send_time"=>0])->field('id,room_id,periods,end_time')->order('periods desc')->find(); + $xlh_data = db('vs_room_pan_xlh')->where(["send_time"=>0,"end_time"=>[">",time()]])->field('id,room_id,periods,end_time')->order('periods desc')->find(); //寻乐会状态 $xlh_status = 0; // 状态 @@ -1196,7 +383,7 @@ class BlindBoxTurntableGift extends Model $gift_bag_id = 13; $xlh_box = db::name('vs_gift_bag')->where('id',$gift_bag_id)->find(); $xlh_ext = json_decode($xlh_box['ext'],true); - $pan_xlh = db::name('vs_room_pan_xlh')->where(['room_id'=>$room_id]) + $pan_xlh = db::name('vs_room_pan_xlh') ->order('id desc') ->page($page,$page_size) ->select(); diff --git a/application/api/model/BlindBoxTurntableGiftDrawWorld.php b/application/api/model/BlindBoxTurntableGiftDrawWorld.php index 57a5b09..67ca1a7 100644 --- a/application/api/model/BlindBoxTurntableGiftDrawWorld.php +++ b/application/api/model/BlindBoxTurntableGiftDrawWorld.php @@ -749,7 +749,7 @@ class BlindBoxTurntableGiftDrawWorld extends Model ]; $push->xunlehui($text_list_new); // 巡乐会正式开始 - $this_xlh_periods = db::name('vs_room')->where('id',$room_id)->value('xlh_periods'); + $this_xlh_periods = $this->getCachedXlhPeriods('get'); $pan_xlh_id = db::name('vs_room_pan_xlh')->insertGetId([ 'room_id' => $room_id, 'gift_id' => $xlh_ext['locking_condition']['locking_gift_id'], @@ -762,7 +762,7 @@ class BlindBoxTurntableGiftDrawWorld extends Model if(!$pan_xlh_id){ return ['code' => 0, 'msg' => '创建巡乐会失败!', 'data' => []]; } - db::name("vs_gift_bag")->where('id',13)->setInc('periods');//修改巡乐会期数 + $this->getCachedXlhPeriods('set', $this_xlh_periods+1);//修改巡乐会期数 } } private function updateAndPushXlhStatus($room_id, $xlh_ext, $currentXlhPeriodsNum){ @@ -934,6 +934,18 @@ class BlindBoxTurntableGiftDrawWorld extends Model } return $xlh_periods_num; } + /** + * 获取缓存的巡乐会期数 + */ + private function getCachedXlhPeriods($type="get",$periods=1) { + $cacheKey = "this_xlh_periods"; + $xlh_periods_num = Cache::get($cacheKey) ?? 0; + if($type=="set"){ + $xlh_periods_num = $periods; + Cache::set($cacheKey, $xlh_periods_num, 0); + } + return $xlh_periods_num; + } /** * 重置奖池 @@ -990,7 +1002,7 @@ class BlindBoxTurntableGiftDrawWorld extends Model // 3. 检查巡乐会状态 $pan_xlh = db::name('vs_room_pan_xlh') - ->where(['periods' => $bag_data['periods']]) + ->order('id', 'desc') ->find(); if (empty($pan_xlh)) { return ['code' => 0, 'msg' => '未开始', 'data' => null]; @@ -1001,7 +1013,6 @@ class BlindBoxTurntableGiftDrawWorld extends Model if ($pan_xlh['send_time'] != 0) { return ['code' => 0, 'msg' => '本轮已结束,礼物已发放', 'data' => null]; } - // 4. 预加载必要数据 $gift_bag_detail = db::name("vs_gift_bag_detail") ->field('id,quantity,remaining_number,weight,foreign_id,gift_bag_id')