秘地新的需求池更新版本-需求更改

This commit is contained in:
2025-10-21 09:56:36 +08:00
parent 14af58889f
commit cca261410f
4 changed files with 222 additions and 159 deletions

View File

@@ -379,8 +379,8 @@ class Guild extends adminApi
$page = input('page', 1); $page = input('page', 1);
$page_limit = input('page_limit', 30); $page_limit = input('page_limit', 30);
$guild_id = input('guild_id', 0); $guild_id = input('guild_id', 0);
$search_stime = input('search_stime',''); $search_stime_str = input('search_stime','');
$search_etime = input('search_etime',''); $search_etime_str = input('search_etime','');
$room_id = input('room_id', 0); $room_id = input('room_id', 0);
$where=['a.status'=>1]; $where=['a.status'=>1];
$where=['a.room_id'=>['>',0]]; $where=['a.room_id'=>['>',0]];
@@ -399,23 +399,37 @@ class Guild extends adminApi
->where(['a.guild_id'=>$guild_id])->where($where)->count(); ->where(['a.guild_id'=>$guild_id])->where($where)->count();
$list = db::name($this->table_guild_user)->alias('a') $list = db::name($this->table_guild_user)->alias('a')
->join('vs_room b', 'a.room_id = b.id', 'left') ->join('vs_room b', 'a.room_id = b.id', 'left')
->where(['a.guild_id'=>$guild_id])->where($where)->page($page, $page_limit)->select(); ->where(['a.guild_id'=>$guild_id])->where($where)
// ->page($page, $page_limit)
->select();
if(!$list){ if(!$list){
return V(0,"暂无数据"); return V(0,"暂无数据");
} }
$rum_lists = []; $rum_lists = [];
foreach ($list as $k=>$v){ foreach ($list as $k=>$v){
if($search_stime!="" && $v['createtime'] < strtotime($search_stime)){ $search_stime = $search_stime_str;
$search_stime = $search_stime; $search_etime = $search_etime_str;
}else{ if($search_stime!=""){
$search_stime = date('Y-m-d H:i:s',$v['createtime']) ; if($search_stime!="" && $v['createtime'] < strtotime($search_stime)){
} $search_stime = $search_stime;
if($v['quit_time']){
if($search_etime!="" && $v['quit_time'] > strtotime($search_etime)){
$search_etime = $search_etime;
}else{ }else{
$search_etime = date('Y-m-d H:i:s',$v['quit_time']); $search_stime = date('Y-m-d H:i:s',$v['createtime']) ;
} }
}else{
$search_stime = $search_stime;
}
if($search_etime!=""){
if($v['quit_time']){
if($search_etime!="" && $v['quit_time'] > strtotime($search_etime)){
$search_etime = $search_etime;
}else{
$search_etime = date('Y-m-d H:i:s',$v['quit_time']);
}
}else{
$search_etime = $search_etime;
}
}else{
$search_etime = $search_etime;
} }
$room_info = db::name('vs_room')->where(['id'=>$v['room_id']])->find(); $room_info = db::name('vs_room')->where(['id'=>$v['room_id']])->find();
@@ -428,6 +442,11 @@ class Guild extends adminApi
$rum_lists[$k]['consumption']= model('Room')->getRoomFlow($v['room_id'],$search_stime,$search_etime); $rum_lists[$k]['consumption']= model('Room')->getRoomFlow($v['room_id'],$search_stime,$search_etime);
$rum_lists[$k]['add_time'] = date('Y-m-d H:i:s',$v['createtime']); $rum_lists[$k]['add_time'] = date('Y-m-d H:i:s',$v['createtime']);
} }
usort($rum_lists, function($a, $b) {
return $b['consumption'] - $a['consumption'];
});
//分页
$rum_lists = array_slice($rum_lists, ($page-1)*$page_limit, $page_limit);
$return_data = [ $return_data = [
'page' =>$page, 'page' =>$page,
'page_limit' => $page_limit, 'page_limit' => $page_limit,
@@ -661,7 +680,7 @@ class Guild extends adminApi
$lists_data = db::name($this->table_guild_subsidy)->alias('a') $lists_data = db::name($this->table_guild_subsidy)->alias('a')
->join('vs_guild b','a.guild_id = b.id') ->join('vs_guild b','a.guild_id = b.id')
->where($where) ->where($where)
->order('a.id desc') ->order('a.total_transaction desc')
->field('a.*,b.guild_name,b.user_id,b.guild_special_id') ->field('a.*,b.guild_name,b.user_id,b.guild_special_id')
->page($page,$page_limit) ->page($page,$page_limit)
->select(); ->select();

View File

@@ -436,7 +436,15 @@ class User extends adminApi
$page = input('page',1); $page = input('page',1);
$page_limit = input('page_limit',10); $page_limit = input('page_limit',10);
$type = input('type',''); $type = input('type','');
$return = model('UserWallet')->money_change_log($user_id,$type,$page,$page_limit); $stime = input('stime','');
$etime = input('etime','');
$change_type = input('change_type','');
$seach = [
'stime' => $stime,
'etime' => $etime,
'change_type' => $change_type
];
$return = model('UserWallet')->money_change_log($user_id,$seach,$type,$page,$page_limit);
$list = []; $list = [];
foreach($return['list'] as $k=>$v){ foreach($return['list'] as $k=>$v){
$list[$k] = [ $list[$k] = [
@@ -456,6 +464,14 @@ class User extends adminApi
return V(1,"操作成功", $return_data); return V(1,"操作成功", $return_data);
} }
/*
* 获取用户资金类型
*/
public function get_money_type(){
$reslut = model('UserWallet')->getChangeTypeLableList();
return V(1,"操作成功", $reslut);
}
/* /*
* 相册列表 * 相册列表
*/ */

View File

@@ -37,98 +37,116 @@ class BlindBoxTurntableGiftDrawWorld extends Model
public function draw_gift($gift_bag_id, $user_id, $gift_user_ids, $num = 1, $room_id = 0, $heart_id = 0,$auction_id = 0) public function draw_gift($gift_bag_id, $user_id, $gift_user_ids, $num = 1, $room_id = 0, $heart_id = 0,$auction_id = 0)
{ {
// 最大重试次数 // 最大重试次数
$maxRetries = 3; try {
for ($attempt = 0; $attempt < $maxRetries; $attempt++) { // 1. 验证参数并提前处理错误
try { $validationResult = $this->validateDrawParameters($gift_bag_id, $user_id, $gift_user_ids);
// 1. 验证参数并提前处理错误 if ($validationResult !== true) {
$validationResult = $this->validateDrawParameters($gift_bag_id, $user_id, $gift_user_ids); return $validationResult;
if ($validationResult !== true) { }
return $validationResult; // 2. 预加载必要数据
} $loadResult = $this->loadDrawData($gift_bag_id, $user_id, $room_id, $num, $gift_user_ids);
// 2. 预加载必要数据 if ($loadResult['code'] !== 1) {
$loadResult = $this->loadDrawData($gift_bag_id, $user_id, $room_id, $num, $gift_user_ids); return $loadResult;
if ($loadResult['code'] !== 1) { }
return $loadResult; // 添加以下检查以防止 null 错误
} if (!isset($loadResult['data']) || !is_array($loadResult['data'])) {
// 添加以下检查以防止 null 错误 return ['code' => 0, 'msg' => '数据加载失败', 'data' => null];
if (!isset($loadResult['data']) || !is_array($loadResult['data'])) { }
return ['code' => 0, 'msg' => '数据加载失败', 'data' => null]; ['bag_data' => $bag_data, 'room' => $room, 'xlh_ext' => $xlh_ext] = $loadResult['data'];
}
['bag_data' => $bag_data, 'room' => $room, 'xlh_ext' => $xlh_ext] = $loadResult['data'];
// 3. 预计算抽奖结果 // 3. 预计算抽奖结果
$precomputeResult = $this->precomputeDrawResults( $precomputeResult = $this->precomputeDrawResults(
$bag_data, $bag_data,
$gift_user_ids, $gift_user_ids,
$num $num
); );
if ($precomputeResult['code'] !== 1) { if ($precomputeResult['code'] !== 1) {
return $precomputeResult; return $precomputeResult;
}
$precomputedResults = $precomputeResult['data']['results'];
$availableGiftss = $precomputeResult['data']['availableGifts'];
$currentXlhPeriodsNum = $precomputeResult['data']['current_xlh_periods_num'];
$addcurrentXlhPeriodsNum = $precomputeResult['data']['addcurrentXlhPeriodsNum'];
$expectedCount = count(explode(',', $gift_user_ids)) * $num;
if (count($precomputedResults) != $expectedCount) {
// 记录错误到Redis
$this->recordDrawErrorToRedis($expectedCount, count($precomputedResults), $room_id, $user_id, $gift_bag_id, $num, $gift_user_ids, $precomputedResults);
return ['code' => 0, 'msg' => '网络加载失败,请重试!', 'data' => null];
}
foreach ($precomputedResults as $result) {
$key = $result['gift_user_id'] . '_' . $result['gift_bag_detail']['foreign_id'];
if (!isset($giftUserCountsJianCha[$key])) {
$giftUserCountsJianCha[$key] = [
'gift_user_id' => $result['gift_user_id'],
'gift_id' => $result['gift_bag_detail']['foreign_id'],
'count' => 0,
'gift_price' => $result['gift']['gift_price'],
'quantity' => $result['gift_bag_detail']['quantity'],
];
} }
$precomputedResults = $precomputeResult['data']['results']; $giftUserCountsJianCha[$key]['count']++;
$availableGiftss = $precomputeResult['data']['availableGifts']; if($giftUserCountsJianCha[$key]['count'] > $result['gift_bag_detail']['quantity']){
$currentXlhPeriodsNum = $precomputeResult['data']['current_xlh_periods_num'];
$addcurrentXlhPeriodsNum = $precomputeResult['data']['addcurrentXlhPeriodsNum'];
$expectedCount = count(explode(',', $gift_user_ids)) * $num;
if (count($precomputedResults) != $expectedCount) {
// 记录错误到Redis // 记录错误到Redis
$this->recordDrawErrorToRedis($expectedCount, count($precomputedResults), $room_id, $user_id, $gift_bag_id, $num, $gift_user_ids, $precomputedResults); // 使用正确的Redis方法存储数据
$key = 'blind_box_draw_world_errors_' . date('Y-m-d-H-i-s');
$errorData = [
'gift_bag_id' => $gift_bag_id,
'user_id' => $user_id,
'gift_user_ids' => $gift_user_ids,
'num' => $num,
'giftUserCountsJianCha' => $giftUserCountsJianCha,
];
$this->redis->setex($key, 86400 * 7, "礼物数量超出限制 ".json_encode($errorData));
return ['code' => 0, 'msg' => '网络加载失败,请重试!', 'data' => null]; return ['code' => 0, 'msg' => '网络加载失败,请重试!', 'data' => null];
} }
// 4. 执行抽奖事务(核心操作)
$transactionResult = $this->executeDrawTransaction(
$bag_data,
$user_id,
$room_id,
$num,
$precomputedResults,
$availableGiftss,
$gift_user_ids,
$heart_id,
$auction_id
);
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,
$currentXlhPeriodsNum,
$addcurrentXlhPeriodsNum,
$room
);
// 6. 构建并返回结果
return $this->buildDrawResult($boxTurntableLog, $giftCounts);
} catch (\Exception $e) {
$key = 'blind_box_draw_errors_' . date('Y-m-d-H-i-s');
$errorData = [
'gift_bag_id' => $gift_bag_id,
'user_id' => $user_id,
'gift_user_ids' => $gift_user_ids,
'num' => $num,
'room_id' => $room_id,
'heart_id' => $heart_id,
'auction_id' => $auction_id,
];
if ($this->redis) {
$this->redis->setex($key, 86400 * 7, $e->getMessage() . ' ' . json_encode($errorData));
}
// 如果是死锁且还有重试机会
if (strpos($e->getMessage(), 'Deadlock') !== false && $attempt < $maxRetries - 1) {
// 随机延迟后重试
usleep(rand(50000, 200000)); // 50-200ms
continue;
}
return ['code' => 0, 'msg' => "网络加载失败,请重试!", 'data' => null];
} }
// 4. 执行抽奖事务(核心操作)
$transactionResult = $this->executeDrawTransaction(
$bag_data,
$user_id,
$room_id,
$num,
$precomputedResults,
$availableGiftss,
$gift_user_ids,
$heart_id,
$auction_id
);
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,
$currentXlhPeriodsNum,
$addcurrentXlhPeriodsNum,
$room
);
// 6. 构建并返回结果
return $this->buildDrawResult($boxTurntableLog, $giftCounts);
} catch (\Exception $e) {
$key = 'blind_box_draw_errors_' . date('Y-m-d-H-i-s');
$errorData = [
'gift_bag_id' => $gift_bag_id,
'user_id' => $user_id,
'gift_user_ids' => $gift_user_ids,
'num' => $num,
'room_id' => $room_id,
'heart_id' => $heart_id,
'auction_id' => $auction_id,
];
if ($this->redis) {
$this->redis->setex($key, 86400 * 7, $e->getMessage() . ' ' . json_encode($errorData));
}
return ['code' => 0, 'msg' => "网络加载失败,请重试!", 'data' => null];
} }
} }
/** /**
@@ -495,65 +513,55 @@ class BlindBoxTurntableGiftDrawWorld extends Model
$bagGiftPrice = $bag_data['gift_price'] * $num * $gift_user_num; $bagGiftPrice = $bag_data['gift_price'] * $num * $gift_user_num;
// 增加重试机制 // 增加重试机制
$maxRetries = 3; try {
for ($retry = 0; $retry < $maxRetries; $retry++) { db::startTrans();
try { // 按照固定顺序处理事务步骤
db::startTrans(); // 1. 扣除用户金币(优先处理)
// 按照固定顺序处理事务步骤 $this->deductUserCoins($user_id, $bagGiftPrice, $room_id);
// 1. 扣除用户金币(优先处理)
$this->deductUserCoins($user_id, $bagGiftPrice, $room_id);
// 2. 创建抽奖记录 // 2. 创建抽奖记录
$boxTurntableLog = db::name('vs_blind_box_turntable_log')->insertGetId([ $boxTurntableLog = db::name('vs_blind_box_turntable_log')->insertGetId([
'user_id' => $user_id, 'user_id' => $user_id,
'gift_bag_id' => $bag_data['id'], 'gift_bag_id' => $bag_data['id'],
'num' => $num, 'num' => $num,
'room_id' => $room_id, 'room_id' => $room_id,
'bag_price' => $bag_data['gift_price'], 'bag_price' => $bag_data['gift_price'],
'createtime' => time() 'createtime' => time()
]); ]);
if (!$boxTurntableLog) { if (!$boxTurntableLog) {
throw new \Exception('添加盲盒转盘记录失败'); throw new \Exception('添加盲盒转盘记录失败');
}
// 3. 批量更新库存按ID排序避免死锁
$this->batchUpdateGiftInventory($availableGiftss, $room_id);
// 4. 批量插入礼包发放记录
$this->batchInsertGiftBagReceiveLog($user_id, $boxTurntableLog, $bag_data, $room_id, $precomputedResults);
// 5. 发送礼物
$result = $this->sendGiftsToRecipients($precomputedResults, $room_id,$user_id,$heart_id,$auction_id);
if (isset($result['code']) && $result['code'] !== 1) {
throw new \Exception($result['msg']);
}
db::commit();
// 统计礼物数量
$giftCounts = $this->countGifts($precomputedResults);
return [
'code' => 1,
'msg' => '事务执行成功',
'data' => [
'log_id' => $boxTurntableLog,
'gift_counts' => $giftCounts
]
];
} catch (\Exception $e) {
db::rollback();
// 检查是否是死锁错误
if (strpos($e->getMessage(), 'Deadlock') !== false && $retry < $maxRetries - 1) {
// 等待随机时间后重试
usleep(rand(10000, 100000)); // 10-100ms
continue;
}
return ['code' => 0, 'msg' => $e->getMessage(), 'data' => null];
} }
// 3. 批量更新库存按ID排序避免死锁
$this->batchUpdateGiftInventory($availableGiftss, $room_id);
// 4. 批量插入礼包发放记录
$this->batchInsertGiftBagReceiveLog($user_id, $boxTurntableLog, $bag_data, $room_id, $precomputedResults);
// 5. 发送礼物
$result = $this->sendGiftsToRecipients($precomputedResults, $room_id,$user_id,$heart_id,$auction_id);
if (isset($result['code']) && $result['code'] !== 1) {
throw new \Exception($result['msg']);
}
db::commit();
// 统计礼物数量
$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];
} }
return ['code' => 0, 'msg' => '操作超时,请重试', 'data' => null];
} }
/** /**
@@ -692,7 +700,6 @@ class BlindBoxTurntableGiftDrawWorld extends Model
} }
$giftUserCounts[$key]['count']++; $giftUserCounts[$key]['count']++;
} }
// 批量插入 // 批量插入
$batchInsertData = []; $batchInsertData = [];
foreach ($giftUserCounts as $userGift) { foreach ($giftUserCounts as $userGift) {

View File

@@ -125,7 +125,7 @@ class UserWallet extends Model
return isset($status[$value]) ? $status[$value] : ''; return isset($status[$value]) ? $status[$value] : '';
} }
public static function ChangeTypeLable($type) public static function ChangeTypeLable($type="")
{ {
$status = [ $status = [
self::OPERATION_SYSTEM => '系统调节', self::OPERATION_SYSTEM => '系统调节',
@@ -163,7 +163,12 @@ class UserWallet extends Model
self::RED_PACKET_LEFT_COIN => '红包剩余退回(金币)', self::RED_PACKET_LEFT_COIN => '红包剩余退回(金币)',
self::RED_PACKET_LEFT_DIAMOND => '红包剩余退回(钻石)', self::RED_PACKET_LEFT_DIAMOND => '红包剩余退回(钻石)',
]; ];
return $status[$type] ?? ''; if($type){
return $status[$type] ?? '';
}else{
return $status;
}
} }
/** /**
@@ -269,10 +274,19 @@ class UserWallet extends Model
/* /*
* 用户资金变动日志 * 用户资金变动日志
*/ */
public function money_change_log($user_id, $money_type=0, $page=0,$page_limit=30){ public function money_change_log($user_id,$seach, $money_type=0, $page=0,$page_limit=30){
if($money_type){ if($money_type){
$where['money_type'] =$money_type; $where['money_type'] =$money_type;
} }
if($seach['stime']){
$where['createtime'] = ['>=',strtotime($seach['stime'])];
}
if($seach['etime']){
$where['createtime'] = ['<=',strtotime($seach['etime'])];
}
if($seach['change_type']){
$where['change_type'] =$seach['change_type'];
}
$log['count'] = Db::name('vs_user_money_log')->where($where)->where('user_id',$user_id)->count(); $log['count'] = Db::name('vs_user_money_log')->where($where)->where('user_id',$user_id)->count();
$log_select = Db::name('vs_user_money_log') $log_select = Db::name('vs_user_money_log')
->where($where) ->where($where)
@@ -306,4 +320,11 @@ class UserWallet extends Model
} }
return $log; return $log;
} }
/*
* 获取用户资金类型
*/
public function getChangeTypeLableList(){
return $this->ChangeTypeLable();
}
} }