From 423452241ea4fe97ada14c143453f6b6fa36d85f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B5=B5=E9=92=8A?= Date: Fri, 19 Sep 2025 10:25:18 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=9A=E7=89=88=E4=B9=8B=E5=90=8Ebug?= =?UTF-8?q?=E4=BF=AE=E6=94=B9----=E6=8A=BD=E5=A5=96=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../adminapi/controller/Activities.php | 4 +- application/adminapi/controller/Underage.php | 8 +- .../api/controller/BlindBoxTurntable.php | 4 +- .../api/model/BlindBoxTurntableGiftDraw.php | 1470 +++++++++++++++++ 4 files changed, 1477 insertions(+), 9 deletions(-) create mode 100644 application/api/model/BlindBoxTurntableGiftDraw.php diff --git a/application/adminapi/controller/Activities.php b/application/adminapi/controller/Activities.php index 09ae280..e02c7cc 100644 --- a/application/adminapi/controller/Activities.php +++ b/application/adminapi/controller/Activities.php @@ -593,10 +593,10 @@ class Activities extends adminApi $lists[$key]['gift_id'] = $value['foreign_id']; $lists[$key]['gift_name'] = $value['name']; $gift_data = db::name('vs_gift')->where(['gid' => $value['foreign_id']])->find(); - $lists[$key]['base_image'] = $gift_data['base_image']; + $lists[$key]['base_image'] = $gift_data['base_image']??""; $lists[$key]['quantity'] = $value['quantity']; $lists[$key]['quantity_str'] = $value['quantity']."个"; - $lists[$key]['gift_price'] = $gift_data['gift_price']; + $lists[$key]['gift_price'] = $gift_data['gift_price']?? ""; }elseif ($value['type'] == 3){ $lists[$key]['gift_id'] = $value['foreign_id']; $lists[$key]['gift_name'] = $value['name']; diff --git a/application/adminapi/controller/Underage.php b/application/adminapi/controller/Underage.php index 937e1d5..78114b3 100644 --- a/application/adminapi/controller/Underage.php +++ b/application/adminapi/controller/Underage.php @@ -159,7 +159,7 @@ class Underage extends adminApi */ public function content_List(){ $page = input('page', 1); - $page_limit = input('pageSize', 30); + $page_limit = input('page_limit', 10); $search_name = input('search_name', ''); $where = []; if($search_name){ @@ -167,6 +167,7 @@ class Underage extends adminApi } $list = DB::name('vs_underage_mode_content')->where($where)->order('sort,id', 'asc')->page($page, $page_limit)->select(); $count = DB::name('vs_underage_mode_content')->where($where)->count(); + $return_lists = []; foreach ($list as $key => $value) { $return_lists[$key]['id'] = $value['id']; $return_lists[$key]['type_id'] = $value['type_id']; @@ -266,7 +267,7 @@ class Underage extends adminApi $type_id = input('type_id', ''); $title = input('title', ''); $introduced = input('introduced', ''); - $content = input('content', ''); + $content = $_POST['content']??""; $url = input('url', ''); $img = input('img', ''); $from = input('from', 1); @@ -303,9 +304,6 @@ class Underage extends adminApi $data['content'] = $content; } $result = db::name('vs_underage_mode_content')->where(['id'=>$id])->update($data); - if(!$result){ - return V(0,"修改失败"); - } return V(1,"成功", ['id'=>$id]); } } \ No newline at end of file diff --git a/application/api/controller/BlindBoxTurntable.php b/application/api/controller/BlindBoxTurntable.php index 0887ae7..e1d83b1 100644 --- a/application/api/controller/BlindBoxTurntable.php +++ b/application/api/controller/BlindBoxTurntable.php @@ -39,7 +39,7 @@ class BlindBoxTurntable extends BaseCom $gift_user_ids = input('gift_user_ids',0); $num = input('num',1); $heart_id = input('heart_id',0); - $reslut = model('BlindBoxTurntableGift')->draw_gift($gift_bag_id, $user_id, $gift_user_ids,$num,$room_id,$heart_id); + $reslut = model('BlindBoxTurntableGiftDraw')->draw_gift($gift_bag_id, $user_id, $gift_user_ids,$num,$room_id,$heart_id); return v($reslut['code'], $reslut['msg'], $reslut['data']); } /* @@ -92,7 +92,7 @@ class BlindBoxTurntable extends BaseCom $user_id = $this->uid; $room_id = input('room_id',0); $num = input('num',1); - $reslut = model('BlindBoxTurntableGift')->xlh_draw_gift($user_id,$num,$room_id); + $reslut = model('BlindBoxTurntableGiftDraw')->xlh_draw_gift($user_id,$num,$room_id); return v($reslut['code'], $reslut['msg'], $reslut['data']); } /* diff --git a/application/api/model/BlindBoxTurntableGiftDraw.php b/application/api/model/BlindBoxTurntableGiftDraw.php new file mode 100644 index 0000000..7ee0d6d --- /dev/null +++ b/application/api/model/BlindBoxTurntableGiftDraw.php @@ -0,0 +1,1470 @@ +validateDrawParameters($gift_bag_id, $user_id, $gift_user_ids, $room_id); + if ($validationResult !== true) { + return $validationResult; + } + + // 2. 预加载必要数据 + $loadResult = $this->loadDrawData($gift_bag_id, $user_id, $room_id); + if ($loadResult['code'] !== 1) { + return $loadResult; + } + ['bag_data' => $bag_data, 'room' => $room, 'xlh_ext' => $xlh_ext] = $loadResult['data']; + + // 3. 预计算抽奖结果 + $precomputeResult = $this->precomputeDrawResults( + $bag_data, + $room, + $gift_user_ids, + $num, + $room_id + ); + if ($precomputeResult['code'] !== 1) { + return $precomputeResult; + } + $precomputedResults = $precomputeResult['data']['results']; + $availableGiftss = $precomputeResult['data']['availableGifts']; + $currentXlhPeriodsNum = $precomputeResult['data']['current_xlh_periods_num']; + $xlhIsPiaoPing = $precomputeResult['data']['xlh_is_piao_ping']; + + // 4. 执行抽奖事务(核心操作) + $transactionResult = $this->executeDrawTransaction( + $bag_data, + $user_id, + $room_id, + $num, + $precomputedResults, + $availableGiftss + ); + if ($transactionResult['code'] !== 1) { + return $transactionResult; + } + $boxTurntableLog = $transactionResult['data']['log_id']; + $giftCounts = $transactionResult['data']['gift_counts']; + + // 5. 处理后续操作(非事务性操作) + $this->handlePostDrawOperations( + $precomputedResults, + $boxTurntableLog, + $room_id, + $xlh_ext, + $xlhIsPiaoPing, + $currentXlhPeriodsNum, + $room + ); + + // 6. 构建并返回结果 + return $this->buildDrawResult($boxTurntableLog, $giftCounts); + } + /** + * 验证抽奖参数 + */ + private function validateDrawParameters($gift_bag_id, $user_id, $gift_user_ids, $room_id) + { + // 提前验证收礼人 + $toarray = explode(',', $gift_user_ids); + if (in_array($user_id, $toarray)) { + return ['code' => 0, 'msg' => "收礼人不能包含自己", 'data' => null]; + } + + // 验证房间ID + if (empty($room_id)) { + return ['code' => 0, 'msg' => '房间ID不能为空', 'data' => null]; + } + + // 验证用户ID + if (empty($user_id)) { + return ['code' => 0, 'msg' => '用户ID不能为空', 'data' => null]; + } + + // 验证盲盒ID + if (empty($gift_bag_id)) { + return ['code' => 0, 'msg' => '盲盒ID不能为空', 'data' => null]; + } + + return true; + } + /** + * 预加载必要数据 + */ + private function loadDrawData($gift_bag_id, $user_id, $room_id) + { + // 1. 合并查询盲盒配置和礼物信息 + $bag_data = db::name("vs_gift_bag") + ->alias('bag') + ->join('vs_gift gift', 'gift.gid = JSON_UNQUOTE(JSON_EXTRACT(bag.ext, "$.gift_id"))', 'LEFT') + ->field('bag.id,bag.name,bag.ext,gift.gid as gift_id,gift.gift_price') + ->where('bag.id', $gift_bag_id) + ->find(); + + if (!$bag_data || !$bag_data['gift_price']) { + return ['code' => 0, 'msg' => '盲盒配置不存在或盲盒礼物不存在', 'data' => null]; + } + + // 2. 获取房间信息 + $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]; + } + + if ($room['is_open_blind_box_turntable'] != 1) { + return ['code' => 0, 'msg' => '该房间未开启盲盒转盘', 'data' => null]; + } + + // 3. 检查用户金币 + $user_waller = db::name('user_wallet') + ->where(['user_id' => $user_id]) + ->find(); + + if (!$user_waller) { + return ['code' => 0, 'msg' => '用户钱包不存在', 'data' => null]; + } + + // 4. 获取巡乐会配置(使用缓存) + $xlh_ext = $this->getCachedXlhConfig(); + + return [ + 'code' => 1, + 'msg' => '数据加载成功', + 'data' => [ + 'bag_data' => $bag_data, + 'room' => $room, + 'xlh_ext' => $xlh_ext, + 'user_waller' => $user_waller + ] + ]; + } + /** + * 预计算抽奖结果 + */ + private function precomputeDrawResults($bag_data, $room, $gift_user_ids, $num, $room_id) + { + $toarray = explode(',', $gift_user_ids); + $ext = json_decode($bag_data['ext'], true); + $xlh_ext = $this->getCachedXlhConfig(); + $xlh_is_piao_ping = 0; + $current_xlh_periods_num = $room['xlh_periods_num']; + + // 1. 计算奖池信息 + $poolInfo = $this->calculatePoolInfo($bag_data['id'], $room_id); + if ($poolInfo['code'] !== 1) { + return $poolInfo; + } + $totalQuantity = $poolInfo['data']['total_quantity']; + $totalRemaining = $poolInfo['data']['total_remaining']; + $periods = $poolInfo['data']['periods']; + $totalDrawTimes = $poolInfo['data']['total_draw_times']; + + // 2. 获取可用礼物 + $availableGifts = $this->getAvailableGifts($bag_data['id'], $room_id, $totalDrawTimes); + if (empty($availableGifts)) { + return ['code' => 0, 'msg' => '当前盲盒无可用礼物', 'data' => null]; + } + + // 3. 预加载礼物信息(减少后续查询) + $giftInfoMap = $this->preloadGiftInfo($availableGifts); + + // 4. 处理奖池重置逻辑 + $needGiftNum = count($toarray) * $num; + $remaining_available_gifts=[]; + if ($totalRemaining - $needGiftNum <= 0) { + $remaining_available_gifts = $availableGifts; + $availableGifts = $this->resetPoolAndReload($bag_data['id'], $room_id, $periods + 1, 0); + if (empty($availableGifts)) { + return ['code' => 0, 'msg' => '重置奖池后仍无可用礼物', 'data' => null]; + } + $totalDrawTimes = 0; + $num = abs($totalRemaining - $num); + } + + // 5. 使用Alias Method预计算抽奖结果(O(1)复杂度) + $precomputedResults = $this->precomputeResultsWithAliasMethod( + $toarray, + $num, + $availableGifts, + $giftInfoMap, + $totalDrawTimes, + $periods, + $current_xlh_periods_num, + $xlh_ext, + $bag_data['id'], + $room_id, + $remaining_available_gifts + ); + if (empty($precomputedResults['precomputedResults'])) { + return ['code' => 0, 'msg' => '预计算抽奖结果失败', 'data' => null]; + } + + return [ + 'code' => 1, + 'msg' => '预计算成功', + 'data' => [ + 'results' => $precomputedResults['precomputedResults'], + 'current_xlh_periods_num' => $current_xlh_periods_num, + 'xlh_is_piao_ping' => $xlh_is_piao_ping, + 'availableGifts' => $precomputedResults['precomputedResultss'], + ] + ]; + } + + /** + * 使用Alias Method预计算抽奖结果(O(1)复杂度) + */ + private function precomputeResultsWithAliasMethod( + $toarray, + $num, + $availableGifts, + $giftInfoMap, + &$totalDrawTimes, + &$periods, + &$currentXlhPeriodsNum, + $xlhExt, + $giftBagId, + $roomId, + $remaining_available_gifts + ) { + $precomputedResults = []; + $precomputedResultss = []; + $giftBagIdToGift = []; + + // 构建Alias表 + $aliasTable = $this->buildAliasTable($availableGifts); + $remaining_num = 0; + foreach ($toarray as $giftUserId) { + if (!empty($remaining_available_gifts)) { + foreach ($remaining_available_gifts as $key=>$value) { + $remaining_num += $value['remaining_number']; + $gift = $giftInfoMap[$value['foreign_id']] ?? null; + for ($j = 0; $j < $value['remaining_number']; $j++) { + $precomputedResults[] = [ + 'gift_user_id' => $giftUserId, + 'gift_bag_detail' => $value, + 'gift' => $gift, + 'draw_times' => $totalDrawTimes, + 'periods' => $periods, + 'j' => $j, + ]; + $totalDrawTimes++; + $currentXlhPeriodsNum++; + + } + unset($remaining_available_gifts[$key]); + } + $numm = $num; +// echo "好好玩"; + }else{ + $numm = $num+$remaining_num; + } +// echo $numm."---"; + for ($i = 0; $i < $numm; $i++) { +// echo "好好呀"; + // 使用Alias Method选择礼物(O(1)复杂度) + $selectedGift = $this->selectGiftWithAliasMethod($aliasTable); + if (!$selectedGift) { + return []; + } + + // 获取礼物信息(从预加载的map中获取,避免查询) + $giftId = $selectedGift['foreign_id']; + $gift = $giftInfoMap[$giftId] ?? null; +// if (!$gift) { +// continue; +// } + + $precomputedResults[] = [ + 'gift_user_id' => $giftUserId, + 'gift_bag_detail' => $selectedGift, + 'gift' => $gift, + 'draw_times' => $totalDrawTimes, + 'periods' => $periods, + 'i' => $i, + ]; + $precomputedResultss[] = [ + 'gift_user_id' => $giftUserId, + 'gift_bag_detail' => $selectedGift, + 'gift' => $gift, + 'draw_times' => $totalDrawTimes, + 'periods' => $periods, + 'i' => $i, + ]; + + $totalDrawTimes++; + $currentXlhPeriodsNum++; + + // 更新Alias表(模拟库存减少) + $this->updateAliasTable($aliasTable, $selectedGift['id']); + + // 检查巡乐会状态 + if (!empty($xlhExt) && $xlhExt['inlet_bag_id'] == $giftBagId) { + if ($currentXlhPeriodsNum == $xlhExt['open_condition']['waiting_start_num']) { + $xlh_is_piao_ping = 1; + } + if ($currentXlhPeriodsNum == $xlhExt['open_condition']['start_num']) { + $xlh_is_piao_ping = 2; + } + } + } + } + + return ['precomputedResults' => $precomputedResults,'precomputedResultss' => $precomputedResultss]; + } + + /** + * 构建Alias表(O(n)复杂度,只执行一次) + */ + private function buildAliasTable($gifts) + { + $n = count($gifts); + if ($n === 0) return null; + + $totalRemaining = array_sum(array_column($gifts, 'remaining_number')); + if ($totalRemaining <= 0) return null; + + // 初始化Alias表 + $small = []; + $large = []; + $prob = []; + $alias = []; + $indexMap = []; + + // 归一化概率并填充索引映射 + foreach ($gifts as $i => $gift) { + $indexMap[$i] = $gift; + $prob[$i] = $gift['remaining_number'] * $n / $totalRemaining; + if ($prob[$i] < 1.0) { + $small[] = $i; + } else { + $large[] = $i; + } + } + + // 构建Alias表 + while (!empty($small) && !empty($large)) { + $s = array_pop($small); + $l = array_pop($large); + $alias[$s] = $l; + $prob[$l] = ($prob[$l] + $prob[$s]) - 1.0; + + if ($prob[$l] < 1.0) { + $small[] = $l; + } else { + $large[] = $l; + } + } + + return [ + 'n' => $n, + 'prob' => $prob, + 'alias' => $alias, + 'index_map' => $indexMap, + 'gifts' => $gifts + ]; + } + + /** + * 使用Alias Method选择礼物(O(1)复杂度) + */ + private function selectGiftWithAliasMethod($aliasTable) + { + if (!$aliasTable) return null; + + $n = $aliasTable['n']; + $k = mt_rand(0, $n - 1); + + // 随机选择 + if (mt_rand() / mt_getrandmax() < $aliasTable['prob'][$k]) { + return $aliasTable['index_map'][$k]; + } else { + return $aliasTable['index_map'][$aliasTable['alias'][$k]] ?? null; + } + } + + /** + * 更新Alias表(模拟库存减少) + */ + private function updateAliasTable(&$aliasTable, $giftId) + { + // 查找礼物在Alias表中的位置 + $gifts = &$aliasTable['gifts']; + $indexMap = &$aliasTable['index_map']; + + foreach ($gifts as &$gift) { + if ($gift['id'] == $giftId) { + $gift['remaining_number']--; + break; + } + } + + // 重新构建Alias表(当剩余数量变化较大时) + // 这里可以根据实际情况调整重建频率 + $totalRemaining = array_sum(array_column($gifts, 'remaining_number')); + if ($totalRemaining <= 0) { + $aliasTable = null; + } + } + /** + * 执行抽奖事务(核心操作) + */ + private function executeDrawTransaction($bag_data, $user_id, $room_id, $num, $precomputedResults,$availableGiftss) + { + $bagGiftPrice = $bag_data['gift_price'] * $num; + + db::startTrans(); + try { + // 1. 创建抽奖记录 + $boxTurntableLog = db::name('vs_blind_box_turntable_log')->insertGetId([ + 'user_id' => $user_id, + 'gift_bag_id' => $bag_data['id'], + 'num' => $num, + 'room_id' => $room_id, + 'bag_price' => $bag_data['gift_price'], + 'createtime' => time() + ]); + + if (!$boxTurntableLog) { + throw new \Exception('添加盲盒转盘记录失败'); + } + + // 2. 批量更新库存 + $this->batchUpdateGiftInventory($availableGiftss, $room_id); + + // 3. 批量插入礼包发放记录 + $this->batchInsertGiftBagReceiveLog($user_id, $boxTurntableLog, $bag_data, $room_id, $precomputedResults); + + // 4. 扣除用户金币 + $this->deductUserCoins($user_id, $bagGiftPrice, $room_id); + + db::commit(); + + // 5. 统计礼物数量 + $giftCounts = $this->countGifts($precomputedResults); + + return [ + 'code' => 1, + 'msg' => '事务执行成功', + 'data' => [ + 'log_id' => $boxTurntableLog, + 'gift_counts' => $giftCounts + ] + ]; + } catch (\Exception $e) { + db::rollback(); + return ['code' => 0, 'msg' => $e->getMessage(), 'data' => null]; + } + } + + /** + * 批量更新礼物库存 + */ + private function batchUpdateGiftInventory($precomputedResults, $room_id) + { + // 按礼物ID分组统计需要减少的数量 + $inventoryUpdates = []; + foreach ($precomputedResults as $result) { + $giftId = $result['gift_bag_detail']['gift_bag_detail_id']; + $inventoryUpdates[$giftId] = ($inventoryUpdates[$giftId] ?? 0) + 1; + } + + // 批量更新 + foreach ($inventoryUpdates as $giftId => $count) { + $ret = db::name("vs_room_pan") + ->where([ + 'room_id' => $room_id, + 'gift_bag_detail_id' => $giftId, + 'remaining_number' => ['>=', $count] + ]) + ->setDec('remaining_number', $count); + + if (!$ret) { + throw new \Exception('更新礼物剩余数量失败'); + } + } + } + + /** + * 批量插入礼包发放记录 + */ + private function batchInsertGiftBagReceiveLog($user_id, $boxTurntableLog, $bag_data, $room_id, $precomputedResults) + { + $batchInsertData = []; + + foreach ($precomputedResults as $result) { + $batchInsertData[] = [ + 'user_id' => $user_id, + 'gift_user_id' => $result['gift_user_id'], + 'parent_id' => $boxTurntableLog, + 'gift_bag_id' => $bag_data['id'], + 'gift_id' => $result['gift_bag_detail']['foreign_id'], + 'periods' => $result['periods'], + 'room_id' => $room_id, + 'gift_price' => $result['gift']['gift_price'], + 'bag_price' => $bag_data['gift_price'], + 'createtime' => time() + ]; + } + + if (!empty($batchInsertData)) { + $insertResult = db::name("vs_gift_bag_receive_log")->insertAll($batchInsertData); + if (!$insertResult) { + throw new \Exception('插入礼包发放记录失败'); + } + } + } + + /** + * 扣除用户金币 + */ + private function deductUserCoins($user_id, $bagGiftPrice, $room_id) + { + $walletUpdate = model('GiveGift')->change_user_cion_or_earnings_log( + $user_id, + $bagGiftPrice, + $room_id, + 1, + 10, + '盲盒转盘抽奖消耗' + ); + + if (!$walletUpdate) { + throw new \Exception('扣除用户金币失败'); + } + + $userLevel = model('Level')->user_level_data_update( + $user_id, + $bagGiftPrice, + 1, + $room_id + ); + + if (!$userLevel) { + throw new \Exception('用户等级更新失败'); + } + } + /** + * 处理抽奖后的后续操作(非事务性) + */ + private function handlePostDrawOperations( + $precomputedResults, + $boxTurntableLog, + $room_id, + $xlh_ext, + $xlhIsPiaoPing, + $currentXlhPeriodsNum, + $room + ) { + // 1. 批量插入盲盒转盘结果记录 + $this->batchInsertBlindBoxResults($precomputedResults, $boxTurntableLog, $room_id); + + // 2. 发送礼物给接收者 + $this->sendGiftsToRecipients($precomputedResults, $boxTurntableLog, $room_id); + + // 3. 处理巡乐会相关操作 + if (!empty($xlh_ext) && $xlh_ext['inlet_bag_id'] == $precomputedResults[0]['gift_bag_detail']['gift_bag_id']) { + $this->handleXlhOperations($room_id, $xlh_ext, $xlhIsPiaoPing, $currentXlhPeriodsNum,$room); + } + } + + /** + * 批量插入盲盒转盘结果记录 + */ + private function batchInsertBlindBoxResults($precomputedResults, $boxTurntableLog, $room_id) + { + // 统计每个用户每个礼物的数量 + $giftUserCounts = []; + foreach ($precomputedResults as $result) { + $key = $result['gift_user_id'] . '_' . $result['gift_bag_detail']['foreign_id']; + if (!isset($giftUserCounts[$key])) { + $giftUserCounts[$key] = [ + 'gift_user_id' => $result['gift_user_id'], + 'gift_id' => $result['gift_bag_detail']['foreign_id'], + 'count' => 0, + 'gift_price' => $result['gift']['gift_price'] + ]; + } + $giftUserCounts[$key]['count']++; + } + + // 批量插入 + $batchInsertData = []; + foreach ($giftUserCounts as $userGift) { + $batchInsertData[] = [ + 'tid' => $boxTurntableLog, + 'gift_user_id' => $userGift['gift_user_id'], + 'gift_id' => $userGift['gift_id'], + 'count' => $userGift['count'], + 'gift_price' => $userGift['gift_price'], + 'all_gift_price' => $userGift['gift_price'] * $userGift['count'], + 'createtime' => time(), + 'heart_id' => 0 + ]; + } + + if (!empty($batchInsertData)) { + db::name('vs_blind_box_turntable_results_log')->insertAll($batchInsertData); + } + } + + /** + * 发送礼物给接收者 + */ + private function sendGiftsToRecipients($precomputedResults, $boxTurntableLog, $room_id) + { + // 统计每个用户每个礼物的数量 + $giftUserCounts = []; + foreach ($precomputedResults as $result) { + $key = $result['gift_user_id'] . '_' . $result['gift_bag_detail']['foreign_id']; + if (!isset($giftUserCounts[$key])) { + $giftUserCounts[$key] = [ + 'gift_user_id' => $result['gift_user_id'], + 'gift_id' => $result['gift_bag_detail']['foreign_id'], + 'count' => 0, + 'gift_price' => $result['gift']['gift_price'] + ]; + } + $giftUserCounts[$key]['count']++; + } + + // 批量发送礼物 + foreach ($giftUserCounts as $userGift) { + $giveGiftExt = [ + 'gift_id' => $userGift['gift_id'], + 'count' => $userGift['count'], + 'gift_price' => $userGift['gift_price'], + 'all_gift_price' => $userGift['gift_price'] * $userGift['count'], + 'is_draw_gift' => 1 + ]; + + $res = model('Room')->room_gift( + $precomputedResults[0]['gift_user_id'], + $userGift['gift_user_id'], + $userGift['gift_id'], + $userGift['count'], + 1, + $room_id, + 0, + 0, + $giveGiftExt + ); + + if (isset($res) && $res['code'] != 1) { + return ['code' => 0, 'msg' => $res['msg'], 'data' => null]; +// \think\facade\Log::error('发送礼物失败: ' . $res['msg']); + } + } + } + + /** + * 处理巡乐会相关操作 + */ + private function handleXlhOperations($room_id, $xlh_ext, $xlhIsPiaoPing, $currentXlhPeriodsNum,$room) + { + if($room['xlh_periods_num'] < $xlh_ext['open_condition']['waiting_start_num'] && $currentXlhPeriodsNum >= $xlh_ext['open_condition']['waiting_start_num']){ + $xlhIsPiaoPing = 1; + } + if($room['xlh_periods_num'] < $xlh_ext['open_condition']['start_num'] && $currentXlhPeriodsNum >= $xlh_ext['open_condition']['start_num']){ + $xlhIsPiaoPing = 2; + } + + // 更新房间巡乐会次数 + db::name("vs_room")->where('id', $room_id)->update([ + 'xlh_periods_num' => $currentXlhPeriodsNum + ]); + + // 处理飘屏 + if ($xlhIsPiaoPing == 1 || $xlhIsPiaoPing == 2) { + $this->handleXlhPiaoPing($room_id, $xlh_ext, $xlhIsPiaoPing,$room); + } + + // 更新巡乐会状态并推送 + $this->updateAndPushXlhStatus($room_id, $xlh_ext, $currentXlhPeriodsNum); + } + private function handleXlhPiaoPing($room_id, $xlh_ext, $xlhIsPiaoPing,$room){ + if($xlhIsPiaoPing == 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($xlhIsPiaoPing == 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');//修改巡乐会期数 + } + } + private function updateAndPushXlhStatus($room_id, $xlh_ext, $currentXlhPeriodsNum){ + $xlh['waiting_start_num'] = $xlh_ext['open_condition']['waiting_start_num'];//等待开奖次数 + $xlh['start_num'] = $xlh_ext['open_condition']['start_num'];//开始开奖次数 + // 当前抽奖次数 + $xlh['current_num'] = $currentXlhPeriodsNum; + // 状态 + 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); + } + /** + * 统计礼物数量 + */ + private function countGifts($precomputedResults) + { + $giftCounts = []; + foreach ($precomputedResults as $result) { + $giftId = $result['gift_bag_detail']['foreign_id']; + if (!isset($giftCounts[$giftId])) { + $giftCounts[$giftId] = [ + 'gift_id' => $giftId, + 'count' => 0, + 'gift_price' => $result['gift']['gift_price'] + ]; + } + $giftCounts[$giftId]['count']++; + } + return $giftCounts; + } + + /** + * 构建抽奖结果 + */ + private function buildDrawResult($boxTurntableLog, $giftCounts) + { + $resultList = []; + foreach ($giftCounts as $gift) { + $resultList[] = [ + 'gift_id' => $gift['gift_id'], + 'count' => $gift['count'] + ]; + } + + return [ + 'code' => 1, + 'msg' => '成功', + 'data' => [ + 'blind_box_turntable_id' => $boxTurntableLog, + 'reslut_list' => $resultList + ] + ]; + } + /** + * 计算奖池信息 + */ + private function calculatePoolInfo($gift_bag_id, $room_id) + { + $roomPanInfo = 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(); + + $totalQuantity = $roomPanInfo['total_quantity'] ?: 0; + $totalRemaining = $roomPanInfo['total_remaining'] ?: 0; + $periods = $roomPanInfo['periods'] ?: 0; + $totalDrawTimes = max(0, $totalQuantity - $totalRemaining); + + return [ + 'code' => 1, + 'msg' => '计算成功', + 'data' => [ + 'total_quantity' => $totalQuantity, + 'total_remaining' => $totalRemaining, + 'periods' => $periods, + 'total_draw_times' => $totalDrawTimes + ] + ]; + } + + /** + * 获取可用礼物 + */ + private function getAvailableGifts($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('b.id,a.quantity,b.remaining_number,a.weight,a.foreign_id,a.gift_bag_id,b.gift_bag_detail_id') + ->alias('a') + ->join('vs_room_pan b', 'b.gift_bag_detail_id = a.id', 'left') + ->where($where) + ->select(); + } + + /** + * 预加载礼物信息 + */ + private function preloadGiftInfo($available_gifts) + { + $giftIds = array_unique(array_column($available_gifts, 'foreign_id')); + if (empty($giftIds)) return []; + + $gifts = db::name('vs_gift') + ->where('gid', 'in', $giftIds) + ->select(); + + return array_column($gifts, null, 'gid'); + } + + /** + * 重置奖池并重新加载 + */ + private function resetPoolAndReload($gift_bag_id, $room_id, $periods, $total_draw_times) + { + $this->reset_gift_pool($room_id, $gift_bag_id, $periods); + return $this->getAvailableGifts($gift_bag_id, $room_id, $total_draw_times); + } + + /** + * 获取缓存的巡乐会配置 + */ + private function getCachedXlhConfig() { + $cacheKey = 'xlh_config_13'; + return Cache::remember($cacheKey, function() { + $xlh_box = db::name('vs_gift_bag')->where('id', 13)->find(); + $return_data = $xlh_box ? json_decode($xlh_box['ext'], true) : []; + if($xlh_box){ + $return_data['gift_bag_name'] = $xlh_box['gift_bag_name']; + } + return $return_data; + }, 3600); // 缓存1小时 + } + + /** + * 重置奖池 + * @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,$remaining_available_gifts=[]) { + // 重置奖池中所有礼物数量 + 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 + ]); + if(!empty($remaining_available_gifts)){ + foreach ($remaining_available_gifts as $gift) { + db::name("vs_room_pan")->where('id', $gift['id'])->setInc('remaining_number',$gift['remaining_number']); + } + } + + // 更新总期数 + 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 + ]; + } + + /* + * 寻乐会抽奖----------------------------------------------------------------------------------------- + */ + /* + * 巡乐会抽奖 + */ + /* + * 巡乐会抽奖(优化版) + */ + public function xlh_draw_gift($user_id, $num, $room_id) + { + $gift_bag_id = 13; + + // 1. 获取并缓存盲盒配置 + $cacheKey = "xlh_config_{$gift_bag_id}"; + $ext = Cache::get($cacheKey); + if (!$ext) { + $bag_data = db::name("vs_gift_bag") + ->field('id,name,ext,periods') + ->where('id', $gift_bag_id) + ->find(); + if (!$bag_data) { + return ['code' => 0, 'msg' => '盲盒配置不存在', 'data' => null]; + } + $ext = json_decode($bag_data['ext'], true); + $ext['gift_bag_name'] = $bag_data['name']; + Cache::set($cacheKey, $ext, 3600); // 缓存1小时 + } + + // 2. 检查用户金币和房间状态 + $bag_gift_price = $ext['xlh_box_price'] * $num; + $user_waller = db::name('user_wallet')->where(['user_id' => $user_id])->find(); + if (!$user_waller || $user_waller['coin'] < $bag_gift_price) { + return ['code' => 0, 'msg' => '用户金币不足', 'data' => null]; + } + + $room = db::name('vs_room') + ->field('id,room_name,is_open_blind_box_turntable,xlh_periods') + ->where(['id' => $room_id]) + ->find(); + if (!$room || $room['is_open_blind_box_turntable'] != 1) { + return ['code' => 0, 'msg' => '该房间未开启盲盒转盘', 'data' => null]; + } + + // 3. 检查巡乐会状态 + $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]; + } + + // 4. 预加载必要数据 + $room_pan_data = db::name("vs_room_pan")->alias('a') + ->join('vs_gift_bag_detail b', 'a.gift_bag_detail_id = b.id') + ->where(['a.room_id' => $room_id, 'a.gift_bag_id' => $gift_bag_id]) + ->field('a.id, a.gift_bag_detail_id, a.remaining_number, a.periods,b.weight,b.foreign_id') + ->select(); + + if (empty($room_pan_data)) { + return ['code' => 0, 'msg' => '当前房间未配置抽奖礼物,请联系管理员', 'data' => []]; + } + + // 计算总数量和剩余数量 + $total_quantity = db::name("vs_gift_bag_detail") + ->where(['gift_bag_id' => $gift_bag_id]) + ->sum('quantity'); + + $total_remaining = array_sum(array_column($room_pan_data, 'remaining_number')); + $total_draw_times = $total_quantity - $total_remaining; + if ($total_draw_times < 0) $total_draw_times = 0; + + // 5. 获取可用礼物(提前过滤无效礼物) + $available_gifts = []; + foreach ($room_pan_data as $pan) { + if ($pan['remaining_number'] > 0 && $pan['weight'] < $total_draw_times) { + $available_gifts[] = $pan; + } + } + + if (empty($available_gifts)) { + return ['code' => 0, 'msg' => '当前盲盒无可用礼物', 'data' => []]; + } + + // 6. 预计算抽奖结果 + $drawn_gifts = []; // 用于统计抽中结果 + $main_prize_updates = []; // 用于记录主奖品更新 + $is_zhong_jiang = 0; + $pan_xlh_num = $pan_xlh['num']; + + // 批量处理配置 + $batch_size = min(10, $num); // 每批次处理10次 + $total_processed = 0; + $all_results = []; // 存储所有抽奖结果 + + while ($total_processed < $num) { + $current_batch = min($batch_size, $num - $total_processed); + db::startTrans(); + try { + // 批量扣除金币(只在第一次事务中处理) + if ($total_processed == 0) { + $wallet_update = model('GiveGift')->change_user_cion_or_earnings_log( + $user_id, + $bag_gift_price, + $room_id, + 1, + 10, + $ext['gift_bag_name'].'抽奖消耗' + ); + if (!$wallet_update) { + throw new \Exception('扣除用户金币失败'); + } + + $user_level = model('Level')->user_level_data_update( + $user_id, + $bag_gift_price, + 1, + $room_id + ); + if (!$user_level) { + throw new \Exception('用户等级更新失败'); + } + } + + // 处理当前批次的抽奖 + $inventory_updates = []; // 用于记录库存变化 + $gift_details_map = []; // 礼物详情映射 + $remaining_available_gifts = $available_gifts; + for ($i = 0; $i < $current_batch; $i++) { + // 从可用礼物中选择 + $selected_gift = $this->selectGiftFromAvailable($available_gifts); + if (!$selected_gift) { + throw new \Exception('预计算抽奖失败'); + } + + // 记录库存变化 + $inventory_updates[$selected_gift['id']] = + ($inventory_updates[$selected_gift['id']] ?? 0) + 1; + + // 记录抽中结果 + $gift_id = $selected_gift['foreign_id']; + $drawn_gifts[$gift_id] = ($drawn_gifts[$gift_id] ?? 0) + 1; + + // 处理主奖品 + if ($gift_id == $ext['locking_condition']['selected_gift_id']) { + $pan_xlh_num++; + $main_prize_updates[] = [ + 'num' => $pan_xlh_num, + 'user_id' => $user_id, + 'gift_id' => $gift_id + ]; + + // 计算延长时间 + $add_end_time = $this->calculateEndTime($pan_xlh_num, $ext, $room_id); + $end_time = time() + $add_end_time; + + // 记录主奖品更新 + $main_prize_updates[count($main_prize_updates) - 1]['end_time'] = $end_time; + } + + // 记录完整结果 + $all_results[] = [ + 'gift_id' => $gift_id, + 'gift_detail_id' => $selected_gift['id'], + 'gift_bag_detail' => $selected_gift + ]; + + // 更新可用礼物缓存 + foreach ($available_gifts as &$gift) { + if ($gift['id'] == $selected_gift['id']) { + $gift['remaining_number']--; + break; + } + } + unset($gift); + + // 移除已无剩余数量的礼物 + $available_gifts = array_filter($available_gifts, function($gift) { + return $gift['remaining_number'] > 0; + }); + + // 检查是否需要重置奖池 + $total_remaining = array_sum(array_column($available_gifts, 'remaining_number')); + if ($total_remaining <= 0 && $total_processed + $i + 1 < $num) { + $this->reset_gift_pool($room_id, $gift_bag_id, $room_pan_data[0]['periods'] + 1,$remaining_available_gifts); + $available_gifts = $this->reloadGiftPool($room_id, $gift_bag_id); + if (empty($available_gifts)) { + throw new \Exception('重置奖池后仍无可用礼物'); + } + } + } + + // 批量更新库存 + foreach ($inventory_updates as $detail_id => $count) { + db::name("vs_room_pan") + ->where(['id' => $detail_id]) + ->setDec('remaining_number', $count); + } + + // 处理主奖品更新 + if (!empty($main_prize_updates)) { + $last_update = end($main_prize_updates); + db::name('vs_room_pan_xlh')->where('id', $pan_xlh['id'])->update([ + 'user_id' => $last_update['user_id'], + 'pay_price' => $ext['xlh_box_price'], + 'locking_gift_id' => $last_update['gift_id'], + 'num' => $last_update['num'], + 'end_time' => $last_update['end_time'], + 'updatetime' => time() + ]); + + db::name('vs_room_pan_xlh_log')->insert([ + 'xlh_id' => $pan_xlh['id'], + 'user_id' => $last_update['user_id'], + 'num' => $last_update['num'], + 'locking_end_time' => $last_update['end_time'], + 'createtime' => time() + ]); + $is_zhong_jiang = 1; + } + + db::commit(); + $total_processed += $current_batch; + } catch (\Exception $e) { + db::rollback(); + return ['code' => 0, 'msg' => $e->getMessage(), 'data' => null]; + } + } + + // 7. 批量处理结果记录 + try { + db::startTrans(); + + // 批量插入礼包发放记录 + $gift_records = []; + $periods = $room_pan_data[0]['periods'] ?? 0; + foreach ($drawn_gifts as $gift_id => $count) { + $gift_records[] = [ + 'user_id' => $user_id, + 'parent_id' => $pan_xlh['id'], + 'gift_bag_id' => $gift_bag_id, + 'gift_id' => $gift_id, + 'periods' => $periods, + 'room_id' => $room_id, + 'num' => $count, + 'gift_price' => $this->getGiftPrice($gift_id), + 'bag_price' => $ext['xlh_box_price'], + 'createtime' => time() + ]; + } + + if (!empty($gift_records)) { + db::name("vs_gift_bag_receive_log")->insertAll($gift_records); + } + + // 批量处理用户礼物包 + foreach ($drawn_gifts as $gift_id => $count) { + $res = model('UserGiftPack')->change_user_gift_pack( + $user_id, + $gift_id, + $count, + model('UserGiftPack')::XLH_DRAW_GIFT_GET, + "巡乐会抽奖所得" + ); + if ($res['code'] != 1) { + throw new \Exception($res['msg']); + } + } + + // 添加活动记录 + 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 ['code' => 0, 'msg' => $e->getMessage(), 'data' => null]; + } + + // 8. 处理推送消息 + if ($is_zhong_jiang == 1) { + $this->handlePrizeNotification($user_id,$gift_id, $room_id, $pan_xlh_num, $end_time, $room['room_name']); + } + + // 9. 构建返回结果 + return $this->buildResult($drawn_gifts); + } + + /** + * 巡乐会抽奖-从可用礼物中选择一个 + */ + private function selectGiftFromAvailable(array &$available_gifts) + { + $remaining = array_sum(array_column($available_gifts, 'remaining_number')); + if ($remaining <= 0) { + return null; + } + + $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) { + return $gift; + } + } + + return null; + } + + /** + * 巡乐会抽奖-计算结束时间 + */ + private function calculateEndTime($pan_xlh_num, $ext, $room_id) + { + $cache_key = 'selected_gift_id_' . $room_id . $ext['locking_condition']['selected_gift_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); + return $add_end_time; + } + + 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); + return 30; + } + + return $add_end_time; + } + + /** + * 巡乐会抽奖-重新加载奖池 + */ + private function reloadGiftPool($room_id, $gift_bag_id) + { + return db::name("vs_room_pan")->alias('a') + ->join('vs_gift_bag_detail b', 'a.gift_bag_detail_id = b.id') + ->where(['a.room_id' => $room_id, 'a.gift_bag_id' => $gift_bag_id]) + ->field('a.id, a.gift_bag_detail_id, a.remaining_number, a.periods,b.weight,b.foreign_id') + ->select(); + } + + /** + * 巡乐会抽奖-获取礼物价格 + */ + private function getGiftPrice($gift_id) + { + static $gift_prices = []; + + if (!isset($gift_prices[$gift_id])) { + $gift_prices[$gift_id] = db::name("vs_gift") + ->where(['gid' => $gift_id]) + ->value('gift_price'); + } + + return $gift_prices[$gift_id]; + } + + /** + * 巡乐会抽奖-处理中奖通知 + */ + private function handlePrizeNotification($user_id,$gift_id, $room_id, $pan_xlh_num, $end_time, $room_name) + { + $FromUserInfo = db::name('user')->field('nickname,avatar')->where(['id' => $user_id])->find(); + $gift_info = db::name('vs_gift')->field('gift_name')->where(['gid' => $gift_id])->find(); + + $text = [ + 'gift_num' => $pan_xlh_num, + 'FromUserInfo' => $FromUserInfo, + 'end_time' => $end_time, + 'text' => $FromUserInfo['nickname'] . ' 用户在 ' . $room_name . ' 房间巡乐会中 ' . $gift_info['gift_name'] . '礼物 x 1 已收入背包' + ]; + + model('Chat')->sendMsg(1057, $room_id, $text); + } + + /** + * 巡乐会抽奖-构建返回结果 + */ + private function buildResult($drawn_gifts) + { + $result_list = []; + $gift_info_cache = []; + + foreach ($drawn_gifts as $gift_id => $count) { + if (!isset($gift_info_cache[$gift_id])) { + $gift_info = db::name('vs_gift') + ->where(['gid' => $gift_id]) + ->find(); + $gift_info_cache[$gift_id] = $gift_info; + } else { + $gift_info = $gift_info_cache[$gift_id]; + } + + $result_list[] = [ + 'gift_id' => $gift_id, + 'gift_name' => $gift_info['gift_name'], + 'base_image' => $gift_info['base_image'], + 'gift_price' => $gift_info['gift_price'], + 'count' => $count, + ]; + } + + // 按价格降序排序 + usort($result_list, function($a, $b) { + return $b['gift_price'] <=> $a['gift_price']; + }); + + return ['code' => 1, 'msg' => '成功', 'data' => $result_list]; + } + +}