diff --git a/application/api/model/BlindBoxTurntableGiftDrawWorld.php b/application/api/model/BlindBoxTurntableGiftDrawWorld.php index 342f002..173ba7f 100644 --- a/application/api/model/BlindBoxTurntableGiftDrawWorld.php +++ b/application/api/model/BlindBoxTurntableGiftDrawWorld.php @@ -236,24 +236,24 @@ class BlindBoxTurntableGiftDrawWorld extends Model // 2. 获取可用礼物 $availableGifts = $this->getAvailableGifts($bag_data['id'], $totalDrawTimes); -// if (empty($availableGifts)) { -// $availableGifts = $this->resetPoolAndReload($bag_data['id']); //重置奖池并重新加载 -// if (empty($availableGifts)) { -// throw new \Exception('重置奖池后仍无可用礼物'); -// } -// $totalDrawTimes = 0;//总抽奖次数重置 -// } + if (empty($availableGifts)) { + $availableGifts = $this->resetPoolAndReload($bag_data['id']); //重置奖池并重新加载 + if (empty($availableGifts)) { + throw new \Exception('重置奖池后仍无可用礼物'); + } + $totalDrawTimes = 0;//总抽奖次数重置 + } // 在处理奖池重置逻辑之前添加检查 -// if (!is_array($availableGifts)) { -// throw new \Exception('可用礼物数据格式错误'); -// } + if (!is_array($availableGifts)) { + throw new \Exception('可用礼物数据格式错误'); + } // 3. 预加载礼物信息(减少后续查询) $giftInfoMap = $this->preloadGiftInfo($availableGifts); // 4. 处理奖池重置逻辑 - 优化版本 $needGiftNum = count($toarray) * $num; //总需要的礼物数 $remaining_available_gifts = []; - $remainingGiftCount = array_sum(array_column($availableGifts, 'remaining_number')) ?? 0; + $remainingGiftCount = array_sum(array_column($availableGifts, 'remaining_number')); if ($remainingGiftCount < $needGiftNum) { // 如果当前奖池礼物不足以满足需求 @@ -335,34 +335,35 @@ class BlindBoxTurntableGiftDrawWorld extends Model } for ($i = 0; $i < $userRemainingAllocation; $i++) { - if(!empty($remaining_available_gifts)){ - $randomKey = array_rand($remaining_available_gifts); - $selectedGift = $remaining_available_gifts[$randomKey]; - --$remaining_available_gifts[$randomKey]['remaining_number']; - if($remaining_available_gifts[$randomKey]['remaining_number'] <=0){ - unset($remaining_available_gifts[$randomKey]); - } - if ($selectedGift) { - $gift = $giftInfoMap[$selectedGift['foreign_id']]; - $precomputedResults[] = [ - 'gift_user_id' => $giftUserId, - 'gift_bag_detail' => $selectedGift, - 'gift' => $gift, - 'draw_times' => $totalDrawTimes, - 'periods' => $periods, - ]; -// $totalDrawTimes++; - $currentXlhPeriodsNum++; - $addcurrentXlhPeriodsNum++; + $selectedGift = $this->selectGiftWithAliasMethod($aliasTableForRemaining); + if ($selectedGift) { + $gift = $giftInfoMap[$selectedGift['foreign_id']]; + $precomputedResults[] = [ + 'gift_user_id' => $giftUserId, + 'gift_bag_detail' => $selectedGift, + 'gift' => $gift, + 'draw_times' => $totalDrawTimes, + 'periods' => $periods, + ]; +// $precomputedResultss[] = [ +// 'gift_user_id' => $giftUserId, +// 'gift_bag_detail' => $selectedGift, +// 'gift' => $gift, +// 'draw_times' => $totalDrawTimes, +// 'periods' => $periods, +// ]; +// $totalDrawTimes++; + $currentXlhPeriodsNum++; + $addcurrentXlhPeriodsNum++; - // 更新Alias表 - $this->updateAliasTable($aliasTableForRemaining, $selectedGift['id']); - } + // 更新Alias表 + $this->updateAliasTable($aliasTableForRemaining, $selectedGift['id']); } } } $totalDrawTimes = 0; } + // 再从新奖池中分配剩余所需礼物 if ($newGiftsNeeded > 0 && !empty($availableGifts)) { $aliasTableForNew = $this->buildAliasTable($availableGifts); @@ -380,52 +381,34 @@ class BlindBoxTurntableGiftDrawWorld extends Model for ($i = 0; $i < $userNewAllocation; $i++) { $selectedGift = $this->selectGiftWithAliasMethod($aliasTableForNew); if ($selectedGift) { - // 检查实际库存是否足够 - if ($selectedGift['remaining_number'] <= 0) { - // 如果库存不足,重新构建 Alias 表 - $aliasTableForNew = $this->buildAliasTable($availableGifts); - $selectedGift = $this->selectGiftWithAliasMethod($aliasTableForNew); - } - // 更新内存中的礼物库存 - foreach ($availableGifts as &$gift) { - if ($gift['id'] == $selectedGift['id']) { - $gift['remaining_number']--; - if($gift['remaining_number'] ==0){ - unset($gift); - } - break; - } - } - unset($gift); // 清除引用 - $giftInfoMap = $this->preloadGiftInfo($availableGifts); $gift = $giftInfoMap[$selectedGift['foreign_id']]; - if($gift){ - $precomputedResults[] = [ - 'gift_user_id' => $giftUserId, - 'gift_bag_detail' => $selectedGift, - 'gift' => $gift, - 'draw_times' => $totalDrawTimes, - 'periods' => $periods, - ]; - $precomputedResultss[] = [ - 'gift_user_id' => $giftUserId, - 'gift_bag_detail' => $selectedGift, - 'gift' => $gift, - 'draw_times' => $totalDrawTimes, - 'periods' => $periods, - ]; - $totalDrawTimes++; - $currentXlhPeriodsNum++; - $addcurrentXlhPeriodsNum++; + if($gift) + $precomputedResults[] = [ + 'gift_user_id' => $giftUserId, + 'gift_bag_detail' => $selectedGift, + 'gift' => $gift, + 'draw_times' => $totalDrawTimes, + 'periods' => $periods, + ]; + $precomputedResultss[] = [ + 'gift_user_id' => $giftUserId, + 'gift_bag_detail' => $selectedGift, + 'gift' => $gift, + 'draw_times' => $totalDrawTimes, + 'periods' => $periods, + ]; + $totalDrawTimes++; + $currentXlhPeriodsNum++; + $addcurrentXlhPeriodsNum++; - // 更新Alias表 - $this->updateAliasTable($aliasTableForNew, $selectedGift['id']); - } + // 更新Alias表 + $this->updateAliasTable($aliasTableForNew, $selectedGift['id']); } } } } + return ['precomputedResults' => $precomputedResults, 'precomputedResultss' => $precomputedResultss, 'addcurrentXlhPeriodsNum' => $addcurrentXlhPeriodsNum]; } @@ -552,7 +535,7 @@ class BlindBoxTurntableGiftDrawWorld extends Model } // 3. 批量更新库存(按ID排序避免死锁) - $this->batchUpdateGiftInventory($availableGiftss,$bag_data['id']); + $this->batchUpdateGiftInventory($availableGiftss, $room_id); // 4. 批量插入礼包发放记录 $this->batchInsertGiftBagReceiveLog($user_id, $boxTurntableLog, $bag_data, $room_id, $precomputedResults); @@ -578,14 +561,14 @@ class BlindBoxTurntableGiftDrawWorld extends Model ]; } catch (\Exception $e) { db::rollback(); - throw new \Exception($e->getMessage()); + return ['code' => 0, 'msg' => $e->getMessage(), 'data' => null]; } } /** * 批量更新礼物库存 */ - private function batchUpdateGiftInventory($precomputedResults,$gift_bag_id) + private function batchUpdateGiftInventory($precomputedResults, $room_id) { // 按礼物ID分组统计需要减少的数量 $inventoryUpdates = []; @@ -599,33 +582,13 @@ class BlindBoxTurntableGiftDrawWorld extends Model // 批量更新 foreach ($inventoryUpdates as $giftId => $count) { - // 使用 FOR UPDATE 锁定记录 - $giftBagDetail = Db::name("vs_gift_bag_detail") - ->where('id', $giftId) - ->find(); - if (!$giftBagDetail) { - throw new \Exception("礼物详情不存在,ID: " . $giftId); - } - - // 检查库存是否足够 - if ($giftBagDetail['remaining_number'] < $count) { - $this->redis->setex('blind_box_draw_world_errors_' . date('Y-m-d-H-i-s'), 86400 * 7, "礼物库存不足 礼物ID:".$giftId.' 数量:'.$count.' 预处理结果:'.json_encode($precomputedResults).'礼物数量详情:'.json_encode($inventoryUpdates)); - throw new \Exception("礼物库存不足,ID: " . $giftId); - } - // 执行更新 $ret = db::name("vs_gift_bag_detail")->where('id',$giftId) ->setDec('remaining_number', $count); if (!$ret) { - $this->redis->setex('blind_box_draw_world_errors_' . date('Y-m-d-H-i-s'), 86400 * 7, "更新礼物剩余数量失败 礼物ID:".$giftId.' 数量:'.$count.' 预处理结果:'.json_encode($precomputedResults)); + Log::record('巡乐会更新礼物剩余数量: ' . $room_id."【数据】".var_export($precomputedResults, true),"info"); throw new \Exception('更新礼物剩余数量失败'); } } - $total_remaining_number = db::name("vs_gift_bag_detail") - ->where(['gift_bag_id' => $gift_bag_id]) - ->sum('remaining_number'); - if($total_remaining_number <= 0){ - $this->reset_gift_pool($gift_bag_id); - } } /** @@ -715,7 +678,7 @@ class BlindBoxTurntableGiftDrawWorld extends Model // 3. 处理巡乐会相关操作 if (!empty($xlh_ext) && $xlh_ext['inlet_bag_id'] == $precomputedResults[0]['gift_bag_detail']['gift_bag_id']) { - $this->handleXlhOperations($room_id, $xlh_ext, $currentXlhPeriodsNum,$addcurrentXlhPeriodsNum); + $this->handleXlhOperations($room_id, $xlh_ext, $currentXlhPeriodsNum,$addcurrentXlhPeriodsNum,$room); } } @@ -816,7 +779,7 @@ class BlindBoxTurntableGiftDrawWorld extends Model /** * 处理巡乐会相关操作 */ - private function handleXlhOperations($room_id, $xlh_ext, $currentXlhPeriodsNum,$addcurrentXlhPeriodsNum) + private function handleXlhOperations($room_id, $xlh_ext, $currentXlhPeriodsNum,$addcurrentXlhPeriodsNum,$room) { $xlhIsPiaoPing = 0; $xlhPeriodsNum = $this->getCachedXlhPeriodsNum("get"); @@ -860,27 +823,21 @@ class BlindBoxTurntableGiftDrawWorld extends Model 'from_type' => 102 ]; $push->xunlehui($text_list_new); - $pan_xlh = db::name('vs_room_pan_xlh') - ->where(['send_time' => 0]) - ->order('id', 'desc') - ->find(); - if (empty($pan_xlh)) { - // 巡乐会正式开始 - $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'], - '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' => []]; - } - $this->getCachedXlhPeriods('set', $this_xlh_periods + 1);//修改巡乐会期数 + // 巡乐会正式开始 + $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'], + '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' => []]; } + $this->getCachedXlhPeriods('set', $this_xlh_periods+1);//修改巡乐会期数 } } private function updateAndPushXlhStatus($room_id, $xlh_ext, $currentXlhPeriodsNum){ @@ -1085,21 +1042,21 @@ class BlindBoxTurntableGiftDrawWorld extends Model * @param int $gift_bag_id 礼物包ID */ private function reset_gift_pool($gift_bag_id,$remaining_available_gifts=[]) { -// $bag_detail = db::name("vs_gift_bag_detail")->where('gift_bag_id',$gift_bag_id)->select(); + $bag_detail = db::name("vs_gift_bag_detail")->where('gift_bag_id',$gift_bag_id)->select(); db::name("vs_gift_bag")->where('id',$gift_bag_id)->setInc('periods'); //更新期数 db::name("vs_gift_bag_detail")->where('gift_bag_id',$gift_bag_id)->update(['remaining_number'=>db::raw('quantity')]);//重置奖池 //防止并发,上把如果件数小于0,则加上 -// foreach ($bag_detail as $pan) { -// if($pan['remaining_number']<0){ -// db::name("vs_gift_bag_detail")->where('id', $pan['id'])->setInc('remaining_number', $pan['remaining_number']); -// } -// } + foreach ($bag_detail as $pan) { + if($pan['remaining_number']<0){ + db::name("vs_gift_bag_detail")->where('id', $pan['id'])->setInc('remaining_number', $pan['remaining_number']); + } + } //补充上把礼物有剩余 -// if(!empty($remaining_available_gifts)){ -// foreach ($remaining_available_gifts as $gift) { -// db::name("vs_gift_bag_detail")->where('id', $gift['id'])->setInc('remaining_number',$gift['remaining_number']); -// } -// } + if(!empty($remaining_available_gifts)){ + foreach ($remaining_available_gifts as $gift) { + db::name("vs_gift_bag_detail")->where('id', $gift['id'])->setInc('remaining_number',$gift['remaining_number']); + } + } } /* @@ -1274,10 +1231,6 @@ class BlindBoxTurntableGiftDrawWorld extends Model // 批量更新库存 ksort($inventory_updates); // 按ID排序 foreach ($inventory_updates as $detail_id => $count) { - $bag_detail = db::name("vs_gift_bag_detail")->field('remaining_number') ->where('id',$detail_id)->find(); - if($bag_detail['remaining_number'] < $count){ - throw new \Exception('库存不足'); - } db::name("vs_gift_bag_detail")->where('id',$detail_id)->setDec('remaining_number', $count); }