Sfoglia il codice sorgente

refactor(farm): 重构土地升级逻辑

- 移除 UpHandler 中的升级逻辑,改为调用 LandService
- 重构 LandLogic 中的 upgradeLand 方法,优化事务处理
- 新增 checkUpgradePath 方法,用于检查升级路径和条件
- 更新 ConsumeGroupService,增加消耗项转换方法
- 调整 CONSUME_TYPE 枚举,更新币种和账户种类的顺序
notfff 7 mesi fa
parent
commit
7192fbdb2d

+ 3 - 0
UCore/Db/Helper.php

@@ -4,6 +4,9 @@ namespace UCore\Db;
 
 use Illuminate\Support\Facades\DB;
 
+/**
+ * 数据库助手类
+ */
 class Helper
 {
 

+ 4 - 1
UCore/Dto/Res.php

@@ -5,17 +5,20 @@ namespace UCore\Dto;
 /**
  * 动作型 返回结果
  * 不适用于查询型处理
- * 
+ *
  */
 class Res
 {
 
     public bool   $success = true;
+    public bool   $error   = false;
     public string $message = '';
     public array  $data;
 
     public function __construct($success, $message, $data = [])
     {
+        $this->error   = !$success;
+
         $this->success = $success;
         $this->data    = $data;
         $this->message = $message;

+ 1 - 44
app/Module/AppGame/Handler/Land/UpHandler.php

@@ -65,43 +65,19 @@ class UpHandler extends BaseHandler
             $upgradePath = $upgradePaths[0];
             $targetType = $upgradePath['to_type_id'];
 
-            // 获取升级所需材料
-            $materials = $upgradePath['materials'] ?? 0;
 
-            // 检查用户是否拥有足够的材料
 
-            $check = ConsumeService::checkConsume($userId, $materials);
 
-            // 开启事务
-            DB::beginTransaction();
 
-            // 消耗材料
-            foreach ($materials as $material) {
-                $itemId = $material['item_id'];
-                $quantity = $material['amount'];
 
-                ItemService::consumeItem($userId, $itemId, null, $quantity, [
-                    'source_type' => 'land_upgrade',
-                    'source_id' => $landId,
-                    'details' => [
-                        'land_id' => $landId,
-                        'target_type' => $targetType
-                    ]
-                ]);
-            }
 
             // 升级土地
-            $result = LandService::upgradeLand($userId, $landId, $targetType, $materials);
+            $result = LandService::upgradeLand($userId, $landId, $targetType);
             if (!$result) {
                 throw new LogicException("升级土地失败");
             }
 
-            // 提交事务
-            DB::commit();
 
-            // 设置响应状态
-            $this->response->setCode(0);
-            $this->response->setMsg('土地升级成功');
 
             Log::info('用户土地升级成功', [
                 'user_id' => $userId,
@@ -111,10 +87,6 @@ class UpHandler extends BaseHandler
             ]);
 
         } catch (LogicException $e) {
-            // 回滚事务
-            if (DB::transactionLevel() > 0) {
-                DB::rollBack();
-            }
 
             // 设置错误响应
             $this->response->setCode(400);
@@ -125,21 +97,6 @@ class UpHandler extends BaseHandler
                 'error' => $e->getMessage(),
                 'trace' => $e->getTraceAsString()
             ]);
-        } catch (\Exception $e) {
-            // 回滚事务
-            if (DB::transactionLevel() > 0) {
-                DB::rollBack();
-            }
-
-            // 设置错误响应
-            $this->response->setCode(500);
-            $this->response->setMsg('系统错误,请稍后再试');
-
-            Log::error('土地升级操作异常', [
-                'user_id' => $this->user_id,
-                'error' => $e->getMessage(),
-                'trace' => $e->getTraceAsString()
-            ]);
         }
 
         return $response;

+ 190 - 87
app/Module/Farm/Logics/LandLogic.php

@@ -12,15 +12,22 @@ use App\Module\Farm\Models\FarmLandType;
 use App\Module\Farm\Models\FarmLandUpgradeConfig;
 use App\Module\Farm\Models\FarmUpgradeLog;
 use App\Module\Farm\Models\FarmUser;
+use App\Module\Game\Services\ConsumeService;
 use Illuminate\Support\Collection;
 use Illuminate\Support\Facades\DB;
 use Illuminate\Support\Facades\Log;
+use UCore\Dto\Res;
+
+use UCore\Exception\LogicException;
+
+use function Laravel\Prompts\select;
 
 /**
  * 土地管理逻辑
  */
 class LandLogic
 {
+
     /**
      * 获取用户的所有土地
      *
@@ -33,6 +40,7 @@ class LandLogic
             $lands = FarmLand::where('user_id', $userId)
                 ->orderBy('position')
                 ->get();
+
 //            dd($lands);
             return $lands->map(function ($land) {
                 return LandInfoDto::fromModel($land);
@@ -40,8 +48,8 @@ class LandLogic
         } catch (\Exception $e) {
             Log::error('获取用户土地失败', [
                 'user_id' => $userId,
-                'error' => $e->getMessage(),
-                'trace' => $e->getTraceAsString()
+                'error'   => $e->getMessage(),
+                'trace'   => $e->getTraceAsString()
             ]);
 
             return collect();
@@ -69,10 +77,10 @@ class LandLogic
             return LandInfoDto::fromModel($land);
         } catch (\Exception $e) {
             Log::error('获取用户指定位置土地失败', [
-                'user_id' => $userId,
+                'user_id'  => $userId,
                 'position' => $position,
-                'error' => $e->getMessage(),
-                'trace' => $e->getTraceAsString()
+                'error'    => $e->getMessage(),
+                'trace'    => $e->getTraceAsString()
             ]);
 
             return null;
@@ -100,28 +108,28 @@ class LandLogic
             }
 
             // 创建新土地
-            $land = new FarmLand();
-            $land->user_id = $userId;
-            $land->position = $position;
+            $land            = new FarmLand();
+            $land->user_id   = $userId;
+            $land->position  = $position;
             $land->land_type = $landType;
-            $land->status = LAND_STATUS::IDLE->value;
+            $land->status    = LAND_STATUS::IDLE->value;
             $land->save();
 
             Log::info('创建土地成功', [
-                'user_id' => $userId,
-                'position' => $position,
+                'user_id'   => $userId,
+                'position'  => $position,
                 'land_type' => $landType,
-                'land_id' => $land->id
+                'land_id'   => $land->id
             ]);
 
             return $land;
         } catch (\Exception $e) {
             Log::error('创建土地失败', [
-                'user_id' => $userId,
-                'position' => $position,
+                'user_id'   => $userId,
+                'position'  => $position,
                 'land_type' => $landType,
-                'error' => $e->getMessage(),
-                'trace' => $e->getTraceAsString()
+                'error'     => $e->getMessage(),
+                'trace'     => $e->getTraceAsString()
             ]);
 
             return null;
@@ -130,6 +138,7 @@ class LandLogic
 
     /**
      * 升级土地
+     * 调用前已经检查,确保用户有足够的材料,且已经检查了升级路径
      *
      * @param int $userId
      * @param int $landId
@@ -137,24 +146,43 @@ class LandLogic
      * @param array $materials 消耗的材料
      * @return bool
      */
-    public function upgradeLand(int $userId, int $landId, int $targetType, array $materials): bool
+    public function upgradeLand(int $userId, int $landId, int $targetType): bool
     {
         try {
+
+
             // 开启事务
             DB::beginTransaction();
 
+
+
+
             // 获取土地信息
+            /**
+             * @var FarmLand $land
+             */
             $land = FarmLand::where('id', $landId)
                 ->where('user_id', $userId)
                 ->first();
 
             if (!$land) {
-                throw new \Exception('土地不存在');
+                throw new LogicException('土地不存在');
             }
 
+            // 检查路径可用
+            $check = self::checkUpgradePath($userId, $land->land_type, $targetType);
+            if ($check->error) {
+                throw new LogicException('升级路径检查不通过!');
+            }
+            /**
+             *
+             * @var FarmLandUpgradeConfig $config
+             */
+            $config = $check->data['config'];
+
             // 检查土地状态
             if ($land->status !== LAND_STATUS::IDLE->value) {
-                throw new \Exception('土地状态不允许升级');
+                throw new LogicException('土地状态不允许升级');
             }
 
             // 获取当前土地类型
@@ -162,56 +190,34 @@ class LandLogic
 
             // 检查是否已经是目标类型
             if ($currentType === $targetType) {
-                throw new \Exception('土地已经是目标类型');
-            }
-
-            // 获取升级配置
-            $upgradeConfig = FarmLandUpgradeConfig::where('from_type_id', $currentType)
-                ->where('to_type_id', $targetType)
-                ->first();
-
-            if (!$upgradeConfig) {
-                throw new \Exception('不支持的升级路径');
+                throw new LogicException('土地已经是目标类型');
             }
 
-            // 检查用户房屋等级是否满足要求
-            $targetLandType = FarmLandType::find($targetType);
-            $farmUser = FarmUser::where('user_id', $userId)->first();
-
-            if (!$farmUser || $farmUser->house_level < $targetLandType->unlock_house_level) {
-                throw new \Exception('房屋等级不足,无法升级到该土地类型');
-            }
-
-            // 检查特殊土地数量限制
-            if ($targetLandType->is_special) {
-                $specialLandCount = FarmLand::where('user_id', $userId)
-                    ->whereIn('land_type', [LAND_TYPE::GOLD->value, LAND_TYPE::BLUE->value, LAND_TYPE::PURPLE->value])
-                    ->count();
-
-                $houseConfig = $farmUser->houseConfig;
-
-                if ($specialLandCount >= $houseConfig->special_land_limit) {
-                    throw new \Exception('特殊土地数量已达上限');
-                }
-            }
 
             // 更新土地类型
-            $oldType = $land->land_type;
+            $oldType         = $land->land_type;
             $land->land_type = $targetType;
             $land->save();
 
+
             // 创建升级记录
-            $upgradeLog = new FarmUpgradeLog();
-            $upgradeLog->user_id = $userId;
+            $upgradeLog               = new FarmUpgradeLog();
+            $upgradeLog->user_id      = $userId;
             $upgradeLog->upgrade_type = UPGRADE_TYPE::LAND->value;
-            $upgradeLog->target_id = $landId;
-            $upgradeLog->old_level = $oldType;
-            $upgradeLog->new_level = $targetType;
-            $upgradeLog->materials_consumed = $materials;
+            $upgradeLog->target_id    = $landId;
+            $upgradeLog->old_level    = $oldType;
+            $upgradeLog->new_level    = $targetType;
+            $upgradeLog->materials_consumed = [];
             $upgradeLog->upgrade_time = now();
-            $upgradeLog->created_at = now();
+            $upgradeLog->created_at   = now();
+            $upgradeLog->save();
+            // 进行消耗
+            $ec = ConsumeService::executeConsume($userId, $config->materials, 'land_upgrade', $upgradeLog->id, false);
+            if ($ec->error) {
+                throw new LogicException('消耗失败');
+            }
+            $upgradeLog->materials_consumed = $ec->data['list'];
             $upgradeLog->save();
-
             // 提交事务
             DB::commit();
 
@@ -219,10 +225,10 @@ class LandLogic
             event(new LandUpgradedEvent($userId, $land, $oldType, $targetType, $upgradeLog));
 
             Log::info('土地升级成功', [
-                'user_id' => $userId,
-                'land_id' => $landId,
-                'old_type' => $oldType,
-                'new_type' => $targetType,
+                'user_id'        => $userId,
+                'land_id'        => $landId,
+                'old_type'       => $oldType,
+                'new_type'       => $targetType,
                 'upgrade_log_id' => $upgradeLog->id
             ]);
 
@@ -232,17 +238,124 @@ class LandLogic
             DB::rollBack();
 
             Log::error('土地升级失败', [
-                'user_id' => $userId,
-                'land_id' => $landId,
+                'user_id'     => $userId,
+                'land_id'     => $landId,
                 'target_type' => $targetType,
-                'error' => $e->getMessage(),
-                'trace' => $e->getTraceAsString()
+                'error'       => $e->getMessage(),
+                'trace'       => $e->getTraceAsString()
             ]);
 
             return false;
         }
     }
 
+    /**
+     * 检查升级路径
+     *
+     * @param $userId
+     * @param $currentType
+     * @param $targetType
+     * @param bool $checkM 是否检查消耗
+     * @return Res
+     * @throws \Exception
+     */
+    static public function checkUpgradePath(int $userId, int $currentType, int $targetType, bool $checkM = true): Res
+    {
+
+        // 获取升级配置
+        /**
+         * @var FarmLandUpgradeConfig $upgradeConfig
+         */
+        $upgradeConfig = FarmLandUpgradeConfig::where('from_type_id', $currentType)
+            ->where('to_type_id', $targetType)
+            ->first();
+
+        if (!$upgradeConfig) {
+            Log::error('升级路径不存在', [
+                'user_id'      => $userId,
+                'current_type' => $currentType,
+                'target_type'  => $targetType
+            ]);
+            return Res::error('升级路径不存在', [
+                'user_id'      => $userId,
+                'current_type' => $currentType,
+                'target_type'  => $targetType
+            ]);
+
+        }
+
+        // 检查用户房屋等级是否满足要求
+        $targetLandType = FarmLandType::find($targetType);
+        $farmUser       = FarmUser::where('user_id', $userId)->first();
+
+        if (!$farmUser || $farmUser->house_level < $targetLandType->unlock_house_level) {
+            Log::error('房屋等级不足,无法升级到该土地类型', [
+                'user_id'            => $userId,
+                'current_type'       => $currentType,
+                'target_type'        => $targetType,
+                'house_level'        => $farmUser->house_level,
+                'unlock_house_level' => $targetLandType->unlock_house_level
+            ]);
+            return Res::error('房屋等级不足,无法升级到该土地类型', [
+                'user_id'            => $userId,
+                'current_type'       => $currentType,
+                'target_type'        => $targetType,
+                'house_level'        => $farmUser->house_level,
+                'unlock_house_level' => $targetLandType->unlock_house_level
+            ]);
+
+        }
+
+        // 检查特殊土地数量限制
+        if ($targetLandType->is_special) {
+            $specialLandCount = FarmLand::where('user_id', $userId)
+                ->whereIn('land_type', [ LAND_TYPE::GOLD->value, LAND_TYPE::BLUE->value, LAND_TYPE::PURPLE->value ])
+                ->count();
+
+            $houseConfig = $farmUser->houseConfig;
+
+            if ($specialLandCount >= $houseConfig->special_land_limit) {
+                Log::error('特殊土地数量已达上限', [
+                    'user_id'            => $userId,
+                    'current_type'       => $currentType,
+                    'target_type'        => $targetType,
+                    'special_land_count' => $specialLandCount,
+                    'special_land_limit' => $houseConfig->special_land_limit
+                ]);
+                return Res::error('特殊土地数量已达上限', [
+                    'user_id'            => $userId,
+                    'current_type'       => $currentType,
+                    'target_type'        => $targetType,
+                    'special_land_count' => $specialLandCount,
+                    'special_land_limit' => $houseConfig->special_land_limit
+                ]);
+
+
+            }
+        }
+
+        // 检查消耗
+        if ($checkM) {
+            $res = ConsumeService::checkConsume($userId, $upgradeConfig->materials);
+            if ($res->error) {
+                Log::error('当前路径资源不足', [
+                    'user_id'      => $userId,
+                    'current_type' => $currentType,
+                    'target_type'  => $targetType,
+                    'error'        => $res->message
+                ]);
+                return Res::error('当前路径资源不足', [
+                    'msg' => $res->message
+                ]);
+            }
+
+        }
+
+        return Res::success('升级路径可用', [
+            'config' => $upgradeConfig
+        ]);
+    }
+
     /**
      * 获取升级所需材料
      *
@@ -267,9 +380,9 @@ class LandLogic
         } catch (\Exception $e) {
             Log::error('获取升级所需材料失败', [
                 'current_type' => $currentType,
-                'target_type' => $targetType,
-                'error' => $e->getMessage(),
-                'trace' => $e->getTraceAsString()
+                'target_type'  => $targetType,
+                'error'        => $e->getMessage(),
+                'trace'        => $e->getTraceAsString()
             ]);
 
             return [];
@@ -277,12 +390,13 @@ class LandLogic
     }
 
     /**
-     * 获取可用的升级路径
+     * 获取可用的升级路径(不进行消耗检查)
      *
      * @param int $userId 用户ID
      * @param int $landId 土地ID
      * @param int|null $toType 目标土地类型ID(可选)
-     * @return array
+     * @return FarmLandUpgradeConfig[]
+     *
      */
     public function getAvailableUpgradePaths(int $userId, int $landId, ?int $toType = null): array
     {
@@ -330,7 +444,7 @@ class LandLogic
 
             // 检查特殊土地数量限制
             $specialLandCount = FarmLand::where('user_id', $userId)
-                ->whereIn('land_type', [LAND_TYPE::GOLD->value, LAND_TYPE::BLUE->value, LAND_TYPE::PURPLE->value])
+                ->whereIn('land_type', [ LAND_TYPE::GOLD->value, LAND_TYPE::BLUE->value, LAND_TYPE::PURPLE->value ])
                 ->count();
 
             $houseConfig = $farmUser->houseConfig;
@@ -346,28 +460,17 @@ class LandLogic
             }
 
             // 格式化返回结果
-            return $availablePaths->map(function ( FarmLandUpgradeConfig $path) use ($userId) {
-
-
-
-                return [
-                    'from_type_id' => $path->from_type_id,
-                    'to_type_id' => $path->to_type_id,
-                    'to_type_name' => $path->toType->name,
-                    'materials_group_id' => $path->materials,
-                    'conditions_group_id' => $path->conditions,
-
-                ];
-            })->values()->toArray();
+            return $availablePaths->toArray();
         } catch (\Exception $e) {
             Log::error('获取可用升级路径失败', [
                 'user_id' => $userId,
                 'land_id' => $landId,
-                'error' => $e->getMessage(),
-                'trace' => $e->getTraceAsString()
+                'error'   => $e->getMessage(),
+                'trace'   => $e->getTraceAsString()
             ]);
 
             return [];
         }
     }
+
 }

+ 4 - 4
app/Module/Farm/Services/LandService.php

@@ -5,6 +5,7 @@ namespace App\Module\Farm\Services;
 use App\Module\Farm\Dtos\LandInfoDto;
 use App\Module\Farm\Logics\LandLogic;
 use App\Module\Farm\Models\FarmLand;
+use App\Module\Farm\Models\FarmLandUpgradeConfig;
 use Illuminate\Support\Collection;
 use Illuminate\Support\Facades\Log;
 
@@ -97,14 +98,13 @@ class LandService
      * @param int $userId
      * @param int $landId
      * @param int $targetType
-     * @param array $materials 消耗的材料
      * @return bool
      */
-    public static function upgradeLand(int $userId, int $landId, int $targetType, array $materials): bool
+    public static function upgradeLand(int $userId, int $landId, int $targetType ): bool
     {
         try {
             $landLogic = new LandLogic();
-            return $landLogic->upgradeLand($userId, $landId, $targetType, $materials);
+            return $landLogic->upgradeLand($userId, $landId, $targetType);
         } catch (\Exception $e) {
             Log::error('升级土地失败', [
                 'user_id' => $userId,
@@ -124,7 +124,7 @@ class LandService
      * @param int $userId 用户ID
      * @param int $landId 土地ID
      * @param int|null $toType 目标土地类型ID(可选)
-     * @return array
+     * @return FarmLandUpgradeConfig[]
      */
     public static function getAvailableUpgradePaths(int $userId, int $landId, ?int $toType = null): array
     {

+ 13 - 10
app/Module/Game/Enums/CONSUME_TYPE.php

@@ -13,7 +13,8 @@ use UCore\Enum\EnumToInt;
  */
 enum CONSUME_TYPE: int
 {
-    use EnumCore, EnumToInt,EnumExpression;
+
+    use EnumCore, EnumToInt, EnumExpression;
 
     /**
      * 物品消耗
@@ -21,19 +22,20 @@ enum CONSUME_TYPE: int
      */
     case ITEM = 1;
 
-    /**
-     * 账户种类消耗
-     * 消耗用户特定账户种类的资金
-     * 注意:这里的target_id指向fund_config表的id(账户种类ID)
-     */
-    case FUND_CONFIG = 2;
 
     /**
      * 币种消耗
      * 消耗用户特定币种的资金
      * 注意:这里的target_id指向fund_currency表的id(币种ID)
      */
-    case CURRENCY = 3;
+    case CURRENCY = 2;
+
+    /**
+     * 账户种类消耗
+     * 消耗用户特定账户种类的资金
+     * 注意:这里的target_id指向fund_config表的id(账户种类ID)
+     */
+    case FUND_CONFIG = 3;
 
 
     /**
@@ -44,9 +46,9 @@ enum CONSUME_TYPE: int
     public static function getAll(): array
     {
         return [
-            self::ITEM->value => '物品',
+            self::ITEM->value        => '物品',
             self::FUND_CONFIG->value => '账户种类',
-            self::CURRENCY->value => '币种',
+            self::CURRENCY->value    => '币种',
         ];
     }
 
@@ -71,4 +73,5 @@ enum CONSUME_TYPE: int
     {
         return isset(self::getAll()[$type]);
     }
+
 }

+ 4 - 2
app/Module/Game/Models/GameConsumeGroup.php

@@ -8,7 +8,7 @@ use UCore\ModelCore;
 /**
  * 消耗组
  *
- * field start 
+ * field start
  * @property  int  $id  主键
  * @property  string  $name  消耗组名称
  * @property  string  $code  消耗组编码(唯一)
@@ -16,6 +16,8 @@ use UCore\ModelCore;
  * @property  \Carbon\Carbon  $created_at  创建时间
  * @property  \Carbon\Carbon  $updated_at  更新时间
  * field end
+ *
+ * @property-read GameConsumeItem[] $consumeItems 消耗组中的所有消耗项
  */
 class GameConsumeGroup extends ModelCore
 {
@@ -26,7 +28,7 @@ class GameConsumeGroup extends ModelCore
      */
     protected $table = 'game_consume_groups';
 
-    // attrlist start 
+    // attrlist start
     protected $fillable = [
         'id',
         'name',

+ 46 - 35
app/Module/Game/Services/ConsumeGroupService.php

@@ -6,6 +6,7 @@ use App\Module\Fund\Models\FundConfigModel;
 use App\Module\Fund\Models\FundCurrencyModel;
 use App\Module\Game\Enums\CONSUME_TYPE;
 use App\Module\Game\Models\GameConsumeGroup;
+use App\Module\Game\Models\GameConsumeItem;
 use App\Module\GameItems\Models\Item;
 use Illuminate\Support\Facades\Log;
 
@@ -56,41 +57,7 @@ class ConsumeGroupService
                 return [];
             }
 
-            $materials = [];
-
-            // 处理每个消耗项
-            foreach ($consumeGroup->consumeItems as $item) {
-                if ($item->consume_type == CONSUME_TYPE::ITEM->value) {
-                    // 获取物品信息
-                    $itemInfo = Item::find($item->target_id);
-                    $materials[] = [
-                        'type' => $item->consume_type,
-                        'item_id' => $item->target_id,
-                        'item_name' => $itemInfo ? $itemInfo->name : "物品 {$item->target_id}",
-                        'amount' => $item->quantity
-                    ];
-                } elseif ($item->consume_type == CONSUME_TYPE::CURRENCY->value) {
-                    // 获取货币信息
-                    $currencyInfo = FundCurrencyModel::find($item->target_id);
-                    $materials[] = [
-                        'type' => $item->consume_type,
-                        'currency_id' => $item->target_id,
-                        'currency_name' => $currencyInfo ? $currencyInfo->name : "货币 {$item->target_id}",
-                        'amount' => $item->quantity
-                    ];
-                } elseif ($item->consume_type == CONSUME_TYPE::FUND->value) {
-                    // 获取代币账户信息
-                    $fundInfo = FundConfigModel::find($item->target_id);
-                    $materials[] = [
-                        'type' => $item->consume_type,
-                        'fund_id' => $item->target_id,
-                        'fund_name' => $fundInfo ? $fundInfo->name : "代币账户 {$item->target_id}",
-                        'amount' => $item->quantity
-                    ];
-                }
-            }
-
-            return $materials;
+            return self::consumeItems2Array($consumeGroup->consumeItems);
         } catch (\Exception $e) {
             Log::error('获取消耗组材料失败', [
                 'consume_group' => $consumeGroupCode,
@@ -100,4 +67,48 @@ class ConsumeGroupService
             return [];
         }
     }
+
+    /**
+     * 消耗组材料数组
+     * @param array|GameConsumeItem[] $consumeGroup 消耗组
+     * @return array 消耗组材料
+     */
+    static public function consumeItems2Array( $consumeItems )
+    {
+        $materials = [];
+
+        // 处理每个消耗项
+        foreach ($consumeItems as $item) {
+            if ($item->consume_type == CONSUME_TYPE::ITEM->value) {
+                // 获取物品信息
+                $itemInfo = Item::find($item->target_id);
+                $materials[] = [
+                    'type' => $item->consume_type,
+                    'item_id' => $item->target_id,
+                    'item_name' => $itemInfo ? $itemInfo->name : "物品 {$item->target_id}",
+                    'amount' => $item->quantity
+                ];
+            } elseif ($item->consume_type == CONSUME_TYPE::CURRENCY->value) {
+                // 获取货币信息
+                $currencyInfo = FundCurrencyModel::find($item->target_id);
+                $materials[] = [
+                    'type' => $item->consume_type,
+                    'currency_id' => $item->target_id,
+                    'currency_name' => $currencyInfo ? $currencyInfo->name : "货币 {$item->target_id}",
+                    'amount' => $item->quantity
+                ];
+            } elseif ($item->consume_type == CONSUME_TYPE::FUND_CONFIG->value) {
+                // 获取代币账户信息
+                $fundInfo = FundConfigModel::find($item->target_id);
+                $materials[] = [
+                    'type' => $item->consume_type,
+                    'fund_id' => $item->target_id,
+                    'fund_name' => $fundInfo ? $fundInfo->name : "代币账户 {$item->target_id}",
+                    'amount' => $item->quantity
+                ];
+            }
+        }
+
+        return $materials;
+    }
 }

+ 104 - 83
app/Module/Game/Services/ConsumeService.php

@@ -10,6 +10,7 @@ use App\Module\Game\Models\GameConsumeItem;
 use App\Module\GameItems\Services\ItemService;
 use Illuminate\Support\Facades\DB;
 use Illuminate\Support\Facades\Log;
+use UCore\Db\Helper;
 use UCore\Dto\Res;
 
 /**
@@ -19,6 +20,7 @@ use UCore\Dto\Res;
  */
 class ConsumeService
 {
+
     /**
      * 检查用户是否满足消耗组的条件
      *
@@ -30,6 +32,9 @@ class ConsumeService
     {
         try {
             // 获取消耗组
+            /**
+             * @var GameConsumeGroup $consumeGroup
+             */
             $consumeGroup = is_numeric($consumeGroupCode)
                 ? GameConsumeGroup::find($consumeGroupCode)
                 : GameConsumeGroup::where('code', $consumeGroupCode)->first();
@@ -48,18 +53,23 @@ class ConsumeService
             // 检查每个消耗项
             foreach ($consumeItems as $item) {
                 $checkResult = self::checkConsumeItem($userId, $item);
+
                 if (!$checkResult['success']) {
                     return Res::error($checkResult['message'], $checkResult);
                 }
             }
 
-            return Res::success();
+            // 所有条件都满足,返回成功; 返回消耗组信息
+            return Res::success('',
+                                ConsumeGroupService::consumeItems2Array($consumeItems)
+            );
         } catch (\Exception $e) {
             Log::error('检查消耗条件失败', [
-                'user_id' => $userId,
+                'user_id'       => $userId,
                 'consume_group' => $consumeGroupCode,
-                'error' => $e->getMessage()
+                'error'         => $e->getMessage()
             ]);
+
             return Res::error('检查消耗条件时发生错误: ' . $e->getMessage());
 
         }
@@ -74,16 +84,22 @@ class ConsumeService
      * @param int $sourceId 消耗来源ID
      * @return Res 执行结果
      */
-    public static function executeConsume(int $userId, $consumeGroupCode, string $source, int $sourceId = 0): Res
+    public static function executeConsume(int $userId, $consumeGroupCode, string $source, int $sourceId = 0, $check = true): Res
     {
-        // 先检查是否满足消耗条件
-        $checkResult = self::checkConsume($userId, $consumeGroupCode);
-        if (!$checkResult->success) {
-            return $checkResult;
+        if ($check) {
+            // 先检查是否满足消耗条件
+            $checkResult = self::checkConsume($userId, $consumeGroupCode);
+            if (!$checkResult->success) {
+                return $checkResult;
+            }
         }
 
         try {
+            Helper::check_tr();
             // 获取消耗组
+            /**
+             * @var GameConsumeGroup $consumeGroup
+             */
             $consumeGroup = is_numeric($consumeGroupCode)
                 ? GameConsumeGroup::find($consumeGroupCode)
                 : GameConsumeGroup::where('code', $consumeGroupCode)->first();
@@ -92,37 +108,35 @@ class ConsumeService
             $consumeItems = $consumeGroup->consumeItems;
 
             // 开始事务
-            DB::beginTransaction();
+
 
             // 执行每个消耗项
             foreach ($consumeItems as $item) {
                 $consumeResult = self::executeConsumeItem($userId, $item, $source, $sourceId);
                 if (!$consumeResult['success']) {
                     DB::rollBack();
+
                     return Res::error($consumeResult['message'], $consumeResult);
                 }
             }
 
-            // 提交事务
-            DB::commit();
 
             return Res::success('消耗执行成功', [
                 'consume_group' => [
-                    'id' => $consumeGroup->id,
+                    'id'   => $consumeGroup->id,
                     'code' => $consumeGroup->code,
                     'name' => $consumeGroup->name
-                ]
+                ],
+                'list'          => ConsumeGroupService::consumeItems2Array($consumeItems)
             ]);
         } catch (\Exception $e) {
-            // 回滚事务
-            DB::rollBack();
 
             Log::error('执行消耗失败', [
-                'user_id' => $userId,
+                'user_id'       => $userId,
                 'consume_group' => $consumeGroupCode,
-                'source' => $source,
-                'source_id' => $sourceId,
-                'error' => $e->getMessage()
+                'source'        => $source,
+                'source_id'     => $sourceId,
+                'error'         => $e->getMessage()
             ]);
 
             return Res::error('执行消耗时发生错误: ' . $e->getMessage());
@@ -141,24 +155,26 @@ class ConsumeService
         switch ($consumeItem->consume_type) {
             case CONSUME_TYPE::ITEM->value:
                 $result = self::checkItemConsume($userId, $consumeItem);
+
                 // 将 Res 对象转换为数组格式
                 return [
-                    'success' => $result->success,
-                    'message' => $result->message,
-                    'item_id' => $result->data['item_id'] ?? null,
+                    'success'  => $result->success,
+                    'message'  => $result->message,
+                    'item_id'  => $result->data['item_id'] ?? null,
                     'required' => $result->data['required'] ?? null,
-                    'actual' => $result->data['actual'] ?? null
+                    'actual'   => $result->data['actual'] ?? null
                 ];
 
             case CONSUME_TYPE::FUND_CONFIG->value:
                 $result = self::checkFundConfigConsume($userId, $consumeItem);
+
                 // 将 Res 对象转换为数组格式
                 return [
-                    'success' => $result->success,
-                    'message' => $result->message,
+                    'success'        => $result->success,
+                    'message'        => $result->message,
                     'fund_config_id' => $result->data['fund_config_id'] ?? null,
-                    'required' => $result->data['required'] ?? null,
-                    'actual' => $result->data['actual'] ?? null
+                    'required'       => $result->data['required'] ?? null,
+                    'actual'         => $result->data['actual'] ?? null
                 ];
 
             case CONSUME_TYPE::CURRENCY->value:
@@ -186,22 +202,24 @@ class ConsumeService
         switch ($consumeItem->consume_type) {
             case CONSUME_TYPE::ITEM->value:
                 $result = self::executeItemConsume($userId, $consumeItem, $source, $sourceId);
+
                 // 将 Res 对象转换为数组格式
                 return [
-                    'success' => $result->success,
-                    'message' => $result->message,
-                    'item_id' => $result->data['item_id'] ?? null,
+                    'success'  => $result->success,
+                    'message'  => $result->message,
+                    'item_id'  => $result->data['item_id'] ?? null,
                     'quantity' => $result->data['quantity'] ?? null
                 ];
 
             case CONSUME_TYPE::FUND_CONFIG->value:
                 $result = self::executeFundConfigConsume($userId, $consumeItem, $source, $sourceId);
+
                 // 将 Res 对象转换为数组格式
                 return [
-                    'success' => $result->success,
-                    'message' => $result->message,
+                    'success'        => $result->success,
+                    'message'        => $result->message,
                     'fund_config_id' => $result->data['fund_config_id'] ?? null,
-                    'amount' => $result->data['amount'] ?? null
+                    'amount'         => $result->data['amount'] ?? null
                 ];
 
             case CONSUME_TYPE::CURRENCY->value:
@@ -224,11 +242,11 @@ class ConsumeService
      */
     protected static function checkItemConsume(int $userId, GameConsumeItem $consumeItem): Res
     {
-        $itemId = $consumeItem->target_id;
+        $itemId   = $consumeItem->target_id;
         $quantity = $consumeItem->quantity;
 
         // 获取用户物品
-        $userItems = ItemService::getUserItems($userId, ['item_id' => $itemId]);
+        $userItems = ItemService::getUserItems($userId, [ 'item_id' => $itemId ]);
 
         // 计算用户拥有的物品总数
         $totalQuantity = 0;
@@ -239,9 +257,9 @@ class ConsumeService
         // 检查数量是否足够
         if ($totalQuantity < $quantity) {
             return Res::error("物品数量不足,需要 {$quantity},实际 {$totalQuantity}", [
-                'item_id' => $itemId,
+                'item_id'  => $itemId,
                 'required' => $quantity,
-                'actual' => $totalQuantity
+                'actual'   => $totalQuantity
             ]);
         }
 
@@ -260,7 +278,7 @@ class ConsumeService
     protected static function checkFundConfigConsume(int $userId, GameConsumeItem $consumeItem): Res
     {
         $fundConfigId = $consumeItem->target_id;
-        $amount = $consumeItem->quantity;
+        $amount       = $consumeItem->quantity;
 
         // 获取用户账户
         $account = FundLogic::get_account($userId, $fundConfigId);
@@ -276,8 +294,8 @@ class ConsumeService
         if ($account->balance < $amount) {
             return Res::error("账户余额不足,需要 {$amount},实际 {$account->balance}", [
                 'fund_config_id' => $fundConfigId,
-                'required' => $amount,
-                'actual' => $account->balance
+                'required'       => $amount,
+                'actual'         => $account->balance
             ]);
         }
 
@@ -299,7 +317,7 @@ class ConsumeService
         try {
             // 获取用户代币账户
             $fundService = new \App\Module\Fund\Services\FundService($userId, $fundId);
-            $account = $fundService->getAccount();
+            $account     = $fundService->getAccount();
 
             // 检查账户是否存在
             if (!$account) {
@@ -314,11 +332,11 @@ class ConsumeService
             $balance = $account->balance;
             if ($balance < $amount) {
                 return [
-                    'success' => false,
-                    'message' => "代币账户余额不足,需要 {$amount},实际 {$balance}",
-                    'fund_id' => $fundId,
+                    'success'  => false,
+                    'message'  => "代币账户余额不足,需要 {$amount},实际 {$balance}",
+                    'fund_id'  => $fundId,
                     'required' => $amount,
-                    'actual' => $balance
+                    'actual'   => $balance
                 ];
             }
 
@@ -346,28 +364,28 @@ class ConsumeService
      */
     protected static function executeItemConsume(int $userId, GameConsumeItem $consumeItem, string $source, int $sourceId): Res
     {
-        $itemId = $consumeItem->target_id;
+        $itemId   = $consumeItem->target_id;
         $quantity = $consumeItem->quantity;
 
         // 消耗物品
         $result = ItemService::consumeItem($userId, $itemId, null, $quantity, [
             'source_type' => $source,
-            'source_id' => $sourceId,
-            'details' => [
-                'consume_item_id' => $consumeItem->id,
+            'source_id'   => $sourceId,
+            'details'     => [
+                'consume_item_id'  => $consumeItem->id,
                 'consume_group_id' => $consumeItem->group_id
             ]
         ]);
 
         if (!$result['success']) {
             return Res::error($result['message'] ?? '物品消耗失败', [
-                'item_id' => $itemId,
+                'item_id'  => $itemId,
                 'quantity' => $quantity
             ]);
         }
 
         return Res::success('物品消耗成功', [
-            'item_id' => $itemId,
+            'item_id'  => $itemId,
             'quantity' => $quantity
         ]);
     }
@@ -386,7 +404,7 @@ class ConsumeService
     protected static function executeFundConfigConsume(int $userId, GameConsumeItem $consumeItem, string $source, int $sourceId): Res
     {
         $fundConfigId = $consumeItem->target_id;
-        $amount = -$consumeItem->quantity; // 负数表示消耗
+        $amount       = -$consumeItem->quantity; // 负数表示消耗
 
         // 构建备注
         $remark = "消耗组:{$consumeItem->group_id},来源:{$source}";
@@ -406,15 +424,16 @@ class ConsumeService
 
         if ($result !== true) {
             $errorMessage = is_string($result) ? $result : '账户资金消耗失败';
+
             return Res::error($errorMessage, [
                 'fund_config_id' => $fundConfigId,
-                'amount' => abs($amount)
+                'amount'         => abs($amount)
             ]);
         }
 
         return Res::success('账户资金消耗成功', [
             'fund_config_id' => $fundConfigId,
-            'amount' => abs($amount)
+            'amount'         => abs($amount)
         ]);
     }
 
@@ -431,7 +450,7 @@ class ConsumeService
     protected static function checkCurrencyConsume(int $userId, GameConsumeItem $consumeItem): array
     {
         $currencyId = $consumeItem->target_id;
-        $amount = $consumeItem->quantity;
+        $amount     = $consumeItem->quantity;
 
         try {
             // 获取该币种的所有账户种类
@@ -439,22 +458,22 @@ class ConsumeService
 
             if ($fundConfigs->isEmpty()) {
                 return [
-                    'success' => false,
-                    'message' => "币种不存在或没有关联的账户种类",
+                    'success'     => false,
+                    'message'     => "币种不存在或没有关联的账户种类",
                     'currency_id' => $currencyId
                 ];
             }
 
             // 获取用户所有与该币种相关的账户
             $fundConfigIds = $fundConfigs->pluck('id')->toArray();
-            $accounts = \App\Module\Fund\Models\FundModel::where('user_id', $userId)
+            $accounts      = \App\Module\Fund\Models\FundModel::where('user_id', $userId)
                 ->whereIn('fund_id', $fundConfigIds)
                 ->get();
 
             if ($accounts->isEmpty()) {
                 return [
-                    'success' => false,
-                    'message' => "用户没有该币种的账户",
+                    'success'     => false,
+                    'message'     => "用户没有该币种的账户",
                     'currency_id' => $currencyId
                 ];
             }
@@ -465,23 +484,23 @@ class ConsumeService
             // 检查余额是否足够
             if ($totalBalance < $amount) {
                 return [
-                    'success' => false,
-                    'message' => "币种总余额不足,需要 {$amount},实际 {$totalBalance}",
+                    'success'     => false,
+                    'message'     => "币种总余额不足,需要 {$amount},实际 {$totalBalance}",
                     'currency_id' => $currencyId,
-                    'required' => $amount,
-                    'actual' => $totalBalance
+                    'required'    => $amount,
+                    'actual'      => $totalBalance
                 ];
             }
 
             return [
-                'success' => true,
-                'message' => '币种总余额足够',
+                'success'  => true,
+                'message'  => '币种总余额足够',
                 'accounts' => $accounts->toArray()
             ];
         } catch (\Exception $e) {
             return [
-                'success' => false,
-                'message' => '检查币种消耗异常: ' . $e->getMessage(),
+                'success'     => false,
+                'message'     => '检查币种消耗异常: ' . $e->getMessage(),
                 'currency_id' => $currencyId
             ];
         }
@@ -502,7 +521,7 @@ class ConsumeService
     protected static function executeCurrencyConsume(int $userId, GameConsumeItem $consumeItem, string $source, int $sourceId): array
     {
         // todo 需要优化,迁移到Fund中
-        $currencyId = $consumeItem->target_id;
+        $currencyId      = $consumeItem->target_id;
         $amountToConsume = $consumeItem->quantity;
 
         try {
@@ -513,7 +532,7 @@ class ConsumeService
             }
 
             // 获取该币种的所有账户种类
-            $fundConfigs = \App\Module\Fund\Models\FundConfigModel::where('currency_id', $currencyId)->get();
+            $fundConfigs   = \App\Module\Fund\Models\FundConfigModel::where('currency_id', $currencyId)->get();
             $fundConfigIds = $fundConfigs->pluck('id')->toArray();
 
             // 获取用户所有与该币种相关的账户
@@ -525,7 +544,7 @@ class ConsumeService
             // 开始事务
             \Illuminate\Support\Facades\DB::beginTransaction();
 
-            $remainingAmount = $amountToConsume;
+            $remainingAmount  = $amountToConsume;
             $consumedAccounts = [];
 
             // 依次从各个账户中扣除
@@ -556,18 +575,19 @@ class ConsumeService
 
                     if ($result !== true) {
                         \Illuminate\Support\Facades\DB::rollBack();
+
                         return [
-                            'success' => false,
-                            'message' => is_string($result) ? $result : "从账户 {$account->fund_id} 扣除失败",
-                            'currency_id' => $currencyId,
+                            'success'        => false,
+                            'message'        => is_string($result) ? $result : "从账户 {$account->fund_id} 扣除失败",
+                            'currency_id'    => $currencyId,
                             'fund_config_id' => $account->fund_id,
-                            'amount' => $amountToDeduct
+                            'amount'         => $amountToDeduct
                         ];
                     }
 
                     $consumedAccounts[] = [
                         'fund_config_id' => $account->fund_id,
-                        'amount' => $amountToDeduct
+                        'amount'         => $amountToDeduct
                     ];
 
                     $remainingAmount -= $amountToDeduct;
@@ -578,10 +598,10 @@ class ConsumeService
             \Illuminate\Support\Facades\DB::commit();
 
             return [
-                'success' => true,
-                'message' => '币种消耗成功',
-                'currency_id' => $currencyId,
-                'amount' => $amountToConsume,
+                'success'           => true,
+                'message'           => '币种消耗成功',
+                'currency_id'       => $currencyId,
+                'amount'            => $amountToConsume,
                 'consumed_accounts' => $consumedAccounts
             ];
         } catch (\Exception $e) {
@@ -591,11 +611,12 @@ class ConsumeService
             }
 
             return [
-                'success' => false,
-                'message' => '币种消耗异常: ' . $e->getMessage(),
+                'success'     => false,
+                'message'     => '币种消耗异常: ' . $e->getMessage(),
                 'currency_id' => $currencyId,
-                'amount' => $amountToConsume
+                'amount'      => $amountToConsume
             ];
         }
     }
+
 }