Эх сурвалжийг харах

修复Handler中的问题:移除LastData处理、修复try-catch块、移除ValidateException捕获、修复灾害状态更新错误

notfff 7 сар өмнө
parent
commit
f9a0d59adc

+ 0 - 11
app/Module/AppGame/Handler/God/OpenHandler.php

@@ -69,17 +69,6 @@ class OpenHandler extends BaseHandler
             $this->response->setCode(0);
             $this->response->setMsg($result['message']);
 
-        } catch (\UCore\Exception\ValidateException $e) {
-            // 验证失败,此时可能还没有开启事务
-            $this->response->setCode(400);
-            $this->response->setMsg($e->getMessage());
-
-            Log::warning('用户神像激活验证失败', [
-                'user_id' => $this->user_id,
-                'god_id' => $godId ?? null,
-                'item_id' => $itemId ?? null,
-                'error' => $e->getMessage()
-            ]);
         } catch (LogicException $e) {
             // 业务逻辑异常,需要回滚事务
             if (DB::transactionLevel() > 0) {

+ 35 - 7
app/Module/AppGame/Handler/Land/FertilizerHandler.php

@@ -34,6 +34,9 @@ class FertilizerHandler extends BaseHandler
      */
     public function handle(Message $data): Message
     {
+        // 创建响应对象
+        $response = new ResponseLandFertilizer();
+
         // 获取请求参数
         $landId = $data->getLandId();
         $itemId = $data->getItemId();
@@ -45,7 +48,7 @@ class FertilizerHandler extends BaseHandler
             'item_id' => $itemId,
         ]);
 
-        // 使用FertilizerValidation进行数据验证
+        // 先进行验证,避免不必要的事务开销
         Log::info('FertilizerHandler: 开始验证', [
             'user_id' => $userId,
             'land_id' => $landId,
@@ -62,6 +65,7 @@ class FertilizerHandler extends BaseHandler
         $validation->validated();  // 这个方法会在验证失败时抛出异常
 
         try {
+            // 验证通过后,开启事务
             DB::beginTransaction();
 
             // 从验证结果中获取数据,避免重复查询
@@ -80,6 +84,7 @@ class FertilizerHandler extends BaseHandler
                 'details'     => ['land_id' => $landId]
             ]);
 
+            // 提交事务
             DB::commit();
 
             Log::info('施肥操作成功', [
@@ -89,22 +94,45 @@ class FertilizerHandler extends BaseHandler
                 'crop_growth_time' => $cropGrowthTime,
             ]);
 
-            // 更新作物生长阶段
+            // 更新作物生长阶段(在事务外执行)
             CropService::updateGrowthStage($result->data['crop_id']);
 
+        } catch (LogicException $e) {
+            // 业务逻辑异常,需要回滚事务
+            if (DB::transactionLevel() > 0) {
+                DB::rollBack();
+            }
+
+            // 设置错误响应
+            $this->response->setCode(400);
+            $this->response->setMsg($e->getMessage());
+
+            Log::warning('用户施肥失败', [
+                'user_id' => $userId,
+                'land_id' => $landId,
+                'item_id' => $itemId,
+                'error' => $e->getMessage(),
+                'trace' => $e->getTraceAsString()
+            ]);
         } catch (\Exception $e) {
-            DB::rollBack();
-            Log::error('施肥操作失败', [
+            // 系统异常,需要回滚事务
+            if (DB::transactionLevel() > 0) {
+                DB::rollBack();
+            }
+
+            // 设置错误响应
+            $this->response->setCode(500);
+            $this->response->setMsg('系统错误,请稍后再试');
+
+            Log::error('施肥操作异常', [
                 'user_id' => $userId,
                 'land_id' => $landId,
                 'item_id' => $itemId,
                 'error' => $e->getMessage(),
+                'trace' => $e->getTraceAsString()
             ]);
-            throw $e;
         }
 
-        // 创建响应对象
-        $response = new ResponseLandFertilizer();
         return $response;
     }
 

+ 0 - 11
app/Module/AppGame/Handler/Land/WateringHandler.php

@@ -72,17 +72,6 @@ class WateringHandler extends BaseHandler
             $this->response->setCode(0);
             $this->response->setMsg($result['message']);
 
-        } catch (\UCore\Exception\ValidateException $e) {
-            // 验证失败,此时可能还没有开启事务
-            $this->response->setCode(400);
-            $this->response->setMsg($e->getMessage());
-
-            Log::warning('用户浇水验证失败', [
-                'user_id' => $this->user_id,
-                'land_id' => $landId ?? null,
-                'item_id' => $userItemId ?? null,
-                'error' => $e->getMessage()
-            ]);
         } catch (LogicException $e) {
             // 业务逻辑异常,需要回滚事务
             if (DB::transactionLevel() > 0) {

+ 0 - 11
app/Module/AppGame/Handler/Land/WeedicideHandler.php

@@ -72,17 +72,6 @@ class WeedicideHandler extends BaseHandler
             $this->response->setCode(0);
             $this->response->setMsg($result['message']);
 
-        } catch (\UCore\Exception\ValidateException $e) {
-            // 验证失败,此时可能还没有开启事务
-            $this->response->setCode(400);
-            $this->response->setMsg($e->getMessage());
-
-            Log::warning('用户除草验证失败', [
-                'user_id' => $this->user_id,
-                'land_id' => $landId ?? null,
-                'item_id' => $userItemId ?? null,
-                'error' => $e->getMessage()
-            ]);
         } catch (LogicException $e) {
             // 业务逻辑异常,需要回滚事务
             if (DB::transactionLevel() > 0) {

+ 1 - 35
app/Module/AppGame/Handler/Pet/GetHandler.php

@@ -66,21 +66,6 @@ class GetHandler extends BaseHandler
             $this->response->setCode(0);
             $this->response->setMsg($result['message']);
 
-            // 设置LastData
-            if (isset($result['last_data'])) {
-                $this->response->setLastData($result['last_data']);
-            }
-
-        } catch (\UCore\Exception\ValidateException $e) {
-            // 验证失败,此时可能还没有开启事务
-            $this->response->setCode(400);
-            $this->response->setMsg($e->getMessage());
-
-            Log::warning('用户获取宠物验证失败', [
-                'user_id' => $userId ?? $this->user_id,
-                'item_id' => $itemId ?? null,
-                'error' => $e->getMessage()
-            ]);
         } catch (LogicException $e) {
             // 业务逻辑异常,需要回滚事务
             if (DB::transactionLevel() > 0) {
@@ -165,23 +150,6 @@ class GetHandler extends BaseHandler
             throw new LogicException("宠物创建失败: " . ($result['message'] ?? '未知错误'));
         }
 
-        // 创建LastData对象,用于返回宠物信息
-        $lastData = new \Uraus\Kku\Common\LastData();
-
-        // 获取创建的宠物详细信息(用于日志记录和返回数据)
-        try {
-            $petData = PetService::getPetStatus($userId, $result['pet_id']);
-            // 设置宠物数据到LastData(这里需要根据实际的LastData结构调整)
-            // $lastData->setPets([$petData]);
-        } catch (\Exception $e) {
-            Log::warning('获取宠物详细信息失败,但继续执行', [
-                'user_id' => $userId,
-                'pet_id' => $result['pet_id'],
-                'error' => $e->getMessage()
-            ]);
-            $petData = null;
-        }
-
         // 记录日志
         Log::info('用户通过物品获取宠物成功', [
             'user_id' => $userId,
@@ -189,13 +157,11 @@ class GetHandler extends BaseHandler
             'pet_type' => $petType,
             'pet_id' => $result['pet_id'],
             'pet_name' => $petName,
-            'pet_grade' => $result['grade'],
-            'pet_data_loaded' => $petData !== null
+            'pet_grade' => $result['grade']
         ]);
 
         return [
             'message' => '恭喜您获得了新宠物:' . $petName,
-            'last_data' => $lastData,
             'pet_id' => $result['pet_id'],
             'pet_name' => $petName,
             'pet_type' => $petType,

+ 0 - 13
app/Module/AppGame/Handler/Pet/LifeSkillUseHandler.php

@@ -133,19 +133,6 @@ class LifeSkillUseHandler extends BaseHandler
                 'failed_skills' => $failedSkills
             ]);
 
-        } catch (\UCore\Exception\ValidateException $e) {
-            // 验证失败
-            DB::rollBack();
-
-            Log::warning('宠物生活技能使用验证失败', [
-                'user_id' => $this->user_id,
-                'pet_id' => $petId ?? null,
-                'skill_id' => $skillId ?? null,
-                'error' => $e->getMessage()
-            ]);
-
-            throw $e;
-
         } catch (LogicException $e) {
             // 业务逻辑异常
             if (DB::transactionLevel() > 0) {

+ 0 - 18
app/Module/AppGame/Handler/Shop/BuyHandler.php

@@ -11,8 +11,6 @@ use App\Module\Shop\Validations\ShopBuyValidation;
 use Google\Protobuf\Internal\Message;
 use Illuminate\Support\Facades\DB;
 use Illuminate\Support\Facades\Log;
-use Uraus\Kku\Common\DataItem;
-use Uraus\Kku\Common\LastData;
 use Uraus\Kku\Request\RequestShopBuy;
 use Uraus\Kku\Response\ResponseShopBuy;
 use UCore\Exception\LogicException;
@@ -99,22 +97,6 @@ class BuyHandler extends BaseHandler
             // 提交事务
             DB::commit();
 
-            // 创建LastData对象,用于返回物品信息
-            $lastData = new LastData();
-            $itemList = [];
-
-            // 创建物品数据
-            $dataItem = new DataItem();
-            $dataItem->setItemId($shopItem->item_id);
-            $dataItem->setQuantity($number * $shopItem->item_quantity);
-            $itemList[] = $dataItem;
-
-            // 设置物品列表到LastData
-            $lastData->setItems($itemList);
-
-            // 设置LastData到响应
-            $this->response->setLastData($lastData);
-
             // 设置响应状态
             $this->response->setCode(0);
             $this->response->setMsg('购买成功');

+ 4 - 4
app/Module/Farm/Commands/FixCropFinalOutputCommand.php

@@ -10,7 +10,7 @@ use Illuminate\Support\Facades\Log;
 
 /**
  * 修复作物final_output_item_id的命令
- * 
+ *
  * 这个命令用于修复那些应该有final_output_item_id但没有设置的作物
  */
 class FixCropFinalOutputCommand extends Command
@@ -37,7 +37,7 @@ class FixCropFinalOutputCommand extends Command
     public function handle()
     {
         $isDryRun = $this->option('dry-run');
-        
+
         if ($isDryRun) {
             $this->info('执行干运行模式,只显示需要修复的数据...');
         } else {
@@ -69,7 +69,7 @@ class FixCropFinalOutputCommand extends Command
                         $crop->user_id,
                         $crop->land_id,
                         $crop->seed_id,
-                        GROWTH_STAGE::getName($crop->growth_stage),
+                        GROWTH_STAGE::getName($crop->growth_stage->value()),
                         $crop->plant_time
                     ];
                 })->toArray()
@@ -110,7 +110,7 @@ class FixCropFinalOutputCommand extends Command
 
                 } catch (\Exception $e) {
                     $errorCount++;
-                    
+
                     Log::error('修复作物final_output_item_id失败', [
                         'crop_id' => $crop->id,
                         'user_id' => $crop->user_id,

+ 9 - 70
app/Module/Farm/Commands/UpdateCropGrowthCommand.php

@@ -3,7 +3,6 @@
 namespace App\Module\Farm\Commands;
 
 use App\Module\Farm\Enums\GROWTH_STAGE;
-use App\Module\Farm\Events\CropGrowthStageChangedEvent;
 use App\Module\Farm\Logics\CropLogic;
 use App\Module\Farm\Models\FarmCrop;
 use Illuminate\Console\Command;
@@ -55,25 +54,16 @@ class UpdateCropGrowthCommand extends Command
                 $userId = $crop->user_id;
                 $oldStage = $crop->growth_stage;
 
-                // 计算新的生长阶段
-                $newStage = $this->calculateNextStage($crop);
+                // 使用CropLogic的updateGrowthStage方法,确保所有逻辑都正确执行
+                $cropLogic = new CropLogic();
+                $updated = $cropLogic->updateGrowthStage($crop->id);
 
-                // 计算新阶段的结束时间
-                $stageEndTime = $this->calculateStageEndTime($crop, $newStage);
-
-                // 更新作物信息
-                $crop->growth_stage = $newStage;
-                $crop->stage_start_time = now(); // 设置新阶段的开始时间
-                $crop->stage_end_time = $stageEndTime;
-                $crop->fertilized = false; // 重置施肥状态
-                $crop->save();
-
-                // 触发生长阶段变更事件
-                event(new CropGrowthStageChangedEvent($userId, $crop, $oldStage->value, $newStage));
-
-                $updatedCount++;
-
-                $this->info("作物 ID: {$crop->id}, 用户 ID: {$userId}, 阶段: {$oldStage} -> {$newStage}");
+                if ($updated) {
+                    $updatedCount++;
+                    // 重新获取作物信息以显示更新后的状态
+                    $crop->refresh();
+                    $this->info("作物 ID: {$crop->id}, 用户 ID: {$userId}, 阶段: {$oldStage} -> {$crop->growth_stage}");
+                }
             }
 
             $this->info("成功更新 {$updatedCount} 个作物的生长状态");
@@ -96,56 +86,5 @@ class UpdateCropGrowthCommand extends Command
         }
     }
 
-    /**
-     * 计算下一个生长阶段
-     *
-     * @param FarmCrop $crop
-     * @return int
-     */
-    private function calculateNextStage(FarmCrop $crop): int
-    {
-        $logic = new CropLogic();
-        return $logic->calculateNextStage($crop);
-
-    }
-
-    /**
-     * 计算阶段结束时间
-     *
-     * @param FarmCrop $crop
-     * @param int $stage
-     * @return \Carbon\Carbon|null
-     */
-    private function calculateStageEndTime(FarmCrop $crop, int $stage)
-    {
-        $seed = $crop->seed;
-
-        if (!$seed) {
-            return null;
-        }
-
-        $now = now();
-
-        switch ($stage) {
-            case GROWTH_STAGE::SEED->valueInt():
-                return $now->addSeconds($seed->seed_time);
 
-            case GROWTH_STAGE::SPROUT->valueInt():
-                return $now->addSeconds($seed->sprout_time);
-
-            case GROWTH_STAGE::GROWTH->valueInt():
-                return $now->addSeconds($seed->growth_time);
-
-            case GROWTH_STAGE::MATURE->valueInt():
-                // 成熟期持续24小时后进入枯萎期
-                return $now->addHours(24);
-
-            case GROWTH_STAGE::WITHERED->valueInt():
-                // 枯萎期没有结束时间
-                return null;
-
-            default:
-                return null;
-        }
-    }
 }

+ 2 - 1
app/Module/Farm/Dtos/CropInfoDto.php

@@ -115,7 +115,8 @@ class CropInfoDto
         $dto->userId = $crop->user_id;
         $dto->seedId = $crop->seed_id;
         $dto->seedName = $crop->seed->name ?? '';
-//        dd($crop);
+
+        //        dd($crop);
         $dto->plantTime = $crop->plant_time;
 
         $dto->growthStage = $crop->growth_stage->value();

+ 5 - 5
app/Module/Farm/Listeners/GenerateDisasterListener.php

@@ -27,7 +27,7 @@ class GenerateDisasterListener
             $crop = $event->crop;
 
             // 根据新的生长阶段设置是否可以产生灾害
-            if (in_array($event->newStage, [GROWTH_STAGE::SPROUT, GROWTH_STAGE::GROWTH])) {
+            if (in_array($event->newStage, [GROWTH_STAGE::SPROUT->value, GROWTH_STAGE::GROWTH->value])) {
                 // 进入发芽期或生长期,允许产生灾害并重置检查时间
                 $crop->can_disaster = true;
                 $crop->last_disaster_check_time = null;
@@ -35,8 +35,8 @@ class GenerateDisasterListener
                 Log::info('作物进入可产生灾害阶段', [
                     'user_id' => $event->userId,
                     'crop_id' => $crop->id,
-                    'old_stage' => $event->oldStage->value,
-                    'new_stage' => $event->newStage->value
+                    'old_stage' => $event->oldStage,
+                    'new_stage' => $event->newStage
                 ]);
             } else {
                 // 其他阶段不能产生灾害
@@ -45,8 +45,8 @@ class GenerateDisasterListener
                 Log::info('作物离开可产生灾害阶段', [
                     'user_id' => $event->userId,
                     'crop_id' => $crop->id,
-                    'old_stage' => $event->oldStage->value,
-                    'new_stage' => $event->newStage->value
+                    'old_stage' => $event->oldStage,
+                    'new_stage' => $event->newStage
                 ]);
             }
 

+ 59 - 23
app/Module/Farm/Logics/CropLogic.php

@@ -265,27 +265,38 @@ class CropLogic
             $harvestLog->created_at = now();
             $harvestLog->save();
 
-            // 删除作物记录
-            $crop->delete();
+            // 收获后作物进入枯萎期,而不是直接删除
+            $oldStage = $crop->growth_stage;
+            $crop->growth_stage = GROWTH_STAGE::WITHERED;
+            $crop->stage_start_time = now();
+            $crop->stage_end_time = null; // 枯萎期没有结束时间
+            $crop->fertilized = false; // 重置施肥状态
+            $crop->save();
 
-            // 更新土地状态
-            $land->status = LAND_STATUS::IDLE;
+            // 更新土地状态为枯萎状态
+            $land->status = LAND_STATUS::WITHERED;
             $land->save();
 
+            // 触发作物生长阶段变更事件(从成熟期到枯萎期)
+            event(new CropGrowthStageChangedEvent($userId, $crop, $oldStage->value, GROWTH_STAGE::WITHERED->value));
+
 
 
 
             // 触发作物收获事件
             event(new CropHarvestedEvent($userId, $land, $crop, $harvestLog, $outputItemId, $outputAmount));
 
-            Log::info('作物收获成功', [
+            Log::info('作物收获成功,进入枯萎期', [
                 'user_id' => $userId,
                 'land_id' => $landId,
                 'crop_id' => $crop->id,
                 'seed_id' => $seed->id,
                 'output_item_id' => $outputItemId,
                 'output_amount' => $outputAmount,
-                'harvest_log_id' => $harvestLog->id
+                'harvest_log_id' => $harvestLog->id,
+                'old_stage' => $oldStage->value,
+                'new_stage' => GROWTH_STAGE::WITHERED->value,
+                'land_status' => LAND_STATUS::WITHERED->value
             ]);
             // 物品入包
             ItemService::addItem($userId, $outputItemId, $outputAmount,[
@@ -643,21 +654,51 @@ class CropLogic
             $crop->stage_end_time = $stageEndTime;
             $crop->fertilized = false; // 重置施肥状态
 
-            // 如果进入发芽期,确定最终产出果实ID
-            if ($newStage === GROWTH_STAGE::SPROUT->value && !$crop->final_output_item_id) {
-                $outputInfo = $this->getRandomOutput($crop->seed_id);
-                $crop->final_output_item_id = $outputInfo['item_id'];
+            // 如果进入发芽期,必须确定最终产出果实ID
+            if ($newStage === GROWTH_STAGE::SPROUT->value) {
+                if (!$crop->final_output_item_id) {
+                    $outputInfo = $this->getRandomOutput($crop->seed_id);
+                    $crop->final_output_item_id = $outputInfo['item_id'];
+
+                    Log::info('作物进入发芽期,确定最终产出果实', [
+                        'crop_id' => $crop->id,
+                        'user_id' => $crop->user_id,
+                        'seed_id' => $crop->seed_id,
+                        'final_output_item_id' => $crop->final_output_item_id
+                    ]);
+                }
+            }
 
-                Log::info('作物进入发芽期,确定最终产出果实', [
+            // 验证:如果进入成熟期但没有final_output_item_id,这是一个严重错误
+            if ($newStage === GROWTH_STAGE::MATURE->value && !$crop->final_output_item_id) {
+                Log::error('严重错误:作物进入成熟期但没有确定最终产出果实ID', [
                     'crop_id' => $crop->id,
                     'user_id' => $crop->user_id,
                     'seed_id' => $crop->seed_id,
-                    'final_output_item_id' => $crop->final_output_item_id
+                    'current_stage' => $oldStage,
+                    'new_stage' => $newStage
                 ]);
+
+                throw new \Exception("作物ID {$crop->id} 进入成熟期但没有确定最终产出果实ID,这是系统错误");
             }
 
             $crop->save();
 
+            // 如果进入枯萎期,需要更新土地状态
+            if ($newStage === GROWTH_STAGE::WITHERED->value) {
+                $land = $crop->land;
+                if ($land) {
+                    $land->status = LAND_STATUS::WITHERED;
+                    $land->save();
+
+                    Log::info('作物进入枯萎期,更新土地状态', [
+                        'crop_id' => $crop->id,
+                        'land_id' => $land->id,
+                        'land_status' => LAND_STATUS::WITHERED->value
+                    ]);
+                }
+            }
+
             // 触发生长阶段变更事件
             event(new CropGrowthStageChangedEvent($crop->user_id, $crop, $oldStage->value, $newStage));
 
@@ -691,20 +732,15 @@ class CropLogic
     {
         $currentStage = $crop->growth_stage;
 
-        // 如果当前是成熟期,且超过一定时间,则进入枯萎期
+        // 如果当前是成熟期,检查是否应该进入枯萎期
         $currentStageValue = is_object($currentStage) ? $currentStage->value : $currentStage;
         if ($currentStageValue === GROWTH_STAGE::MATURE->value) {
-            // 成熟期持续时间,默认为24小时
-            $matureDuration = 24 * 60 * 60;
-
-            // 如果成熟期已经超过指定时间,则进入枯萎期
-            if ($crop->stage_end_time && $crop->stage_end_time instanceof \Carbon\Carbon) {
-                $endTimeMinusDuration = $crop->stage_end_time->copy()->subSeconds($matureDuration);
-                if (now()->diffInSeconds($endTimeMinusDuration) > $matureDuration) {
-                    return GROWTH_STAGE::WITHERED->value;
-                }
+            // 如果成熟期已经超过结束时间,则进入枯萎期
+            if ($crop->stage_end_time && now() >= $crop->stage_end_time) {
+                return GROWTH_STAGE::WITHERED->value;
             }
 
+            // 否则保持成熟期
             return GROWTH_STAGE::MATURE->value;
         }
 
@@ -768,7 +804,7 @@ class CropLogic
      * @param int $seedId
      * @return array
      */
-    private function getRandomOutput(int $seedId): array
+    public function getRandomOutput(int $seedId): array
     {
         // 获取种子的所有产出配置
         $outputs = FarmSeedOutput::where('seed_id', $seedId)->get();

+ 1 - 0
app/Module/Farm/Providers/FarmServiceProvider.php

@@ -51,6 +51,7 @@ class FarmServiceProvider extends ServiceProvider
         // 注册命令
         $this->commands([
             Commands\UpdateCropGrowthCommand::class,
+            Commands\FixCropFinalOutputCommand::class,
             Commands\GenerateDisastersCommand::class,
             Commands\CheckHouseDowngradeCommand::class,
             Commands\CleanExpiredLogsCommand::class,

+ 69 - 1
app/Module/Game/AdminControllers/FarmUserSummaryController.php

@@ -325,7 +325,7 @@ class FarmUserSummaryController extends AdminController
         // 创建土地详情表格
         $headers = [
             'ID', '位置', '土地类型', '状态', '种植作物', '种植时间', '生长阶段', '本阶段开始时间', '本阶段结束时间(剩余)',
-            '灾害情况'
+            '果实信息', '灾害情况'
         ];
         $rows    = [];
 
@@ -339,6 +339,7 @@ class FarmUserSummaryController extends AdminController
             $growthStage    = '';
             $stageStartTime = '';
             $stageEndTime   = '';
+            $fruitInfo      = '无';
             $disasterInfo   = '无';
 
             if ($crop) {
@@ -349,6 +350,16 @@ class FarmUserSummaryController extends AdminController
                 $stageStartTime = $crop->stage_start_time;
                 $stageEndTime   = $this->formatRelativeTime($crop->stage_end_time);
 
+                // 处理果实信息
+                if ($crop->final_output_item_id) {
+                    $fruitInfo = $this->getFruitInfo($crop->final_output_item_id);
+                } else {
+                    // 如果还没有确定最终产出,显示种子的可能产出
+                    if ($crop->seed && $crop->seed->outputs) {
+                        $fruitInfo = $this->getSeedPossibleOutputs($crop->seed);
+                    }
+                }
+
                 // 处理灾害信息
                 if (!empty($crop->disasters)) {
                     $disasterInfo = $this->formatDisasterInfo($crop->disasters);
@@ -365,6 +376,7 @@ class FarmUserSummaryController extends AdminController
                 $growthStage,
                 $stageStartTime,
                 $stageEndTime,
+                $fruitInfo,
                 $disasterInfo,
             ];
         }
@@ -1283,4 +1295,60 @@ class FarmUserSummaryController extends AdminController
         });
     }
 
+    /**
+     * 获取果实信息
+     *
+     * @param int $itemId 物品ID
+     * @return string
+     */
+    protected function getFruitInfo($itemId)
+    {
+        try {
+            // 查询物品信息
+            $item = \App\Module\GameItems\Models\Item::find($itemId);
+
+            if ($item) {
+                return "<span class='text-success'><strong>{$item->name}</strong></span><br><small class='text-muted'>ID: {$itemId}</small>";
+            } else {
+                return "<span class='text-warning'>物品ID: {$itemId}</span><br><small class='text-muted'>物品不存在</small>";
+            }
+        } catch (\Exception $e) {
+            return "<span class='text-danger'>获取失败</span><br><small class='text-muted'>ID: {$itemId}</small>";
+        }
+    }
+
+    /**
+     * 获取种子可能的产出信息
+     *
+     * @param \App\Module\Farm\Models\FarmSeed $seed 种子对象
+     * @return string
+     */
+    protected function getSeedPossibleOutputs($seed)
+    {
+        try {
+            $outputs = $seed->outputs;
+
+            if ($outputs->isEmpty()) {
+                return '<span class="text-muted">无产出配置</span>';
+            }
+
+            $outputInfo = [];
+            foreach ($outputs as $output) {
+                try {
+                    $item = \App\Module\GameItems\Models\Item::find($output->item_id);
+                    $itemName = $item ? $item->name : "物品{$output->item_id}";
+                    $probability = $output->probability ?? 0;
+
+                    $outputInfo[] = "<span class='text-info'>{$itemName}</span> <small class='text-muted'>({$probability}%)</small>";
+                } catch (\Exception $e) {
+                    $outputInfo[] = "<span class='text-warning'>物品{$output->item_id}</span>";
+                }
+            }
+
+            return '<small>可能产出:<br>' . implode('<br>', $outputInfo) . '</small>';
+        } catch (\Exception $e) {
+            return '<span class="text-muted">获取产出信息失败</span>';
+        }
+    }
+
 }

+ 421 - 2
app/Module/Pet/Logic/PetAutoSkillLogic.php

@@ -8,6 +8,7 @@ use App\Module\Farm\Services\LandService;
 use App\Module\GameItems\Services\ItemService;
 use Illuminate\Support\Facades\DB;
 use Illuminate\Support\Facades\Log;
+use UCore\Dto\Res;
 
 /**
  * 宠物自动技能处理逻辑
@@ -55,11 +56,12 @@ class PetAutoSkillLogic
                     // 调用收获服务
                     $result = CropService::harvestCrop($userId, $land->id);
 
-                    if ($result && !$result->error) {
+                    if ($result instanceof Res && !$result->error) {
                         $harvestCount++;
                         $harvestResults[] = [
                             'land_id' => $land->id,
-                            'result' => $result->data
+                            'success' => true,
+                            'auto_cleared' => false
                         ];
 
                         Log::info('自动收菜成功', [
@@ -67,6 +69,18 @@ class PetAutoSkillLogic
                             'pet_id' => $pet->id,
                             'land_id' => $land->id
                         ]);
+
+                        // 收获后自动铲除枯萎的作物
+                        $clearResult = $this->autoClearWitheredCrop($userId, $land->id);
+                        if ($clearResult) {
+                            $harvestResults[count($harvestResults) - 1]['auto_cleared'] = true;
+
+                            Log::info('自动铲除枯萎作物成功', [
+                                'user_id' => $userId,
+                                'pet_id' => $pet->id,
+                                'land_id' => $land->id
+                            ]);
+                        }
                     }
 
                     DB::commit();
@@ -82,9 +96,13 @@ class PetAutoSkillLogic
                 }
             }
 
+            // 统计自动铲除的数量
+            $autoClearedCount = array_sum(array_column($harvestResults, 'auto_cleared'));
+
             // 记录统计信息
             $this->recordSkillStatistics($activeSkill, 'auto_harvest', [
                 'harvest_count' => $harvestCount,
+                'auto_cleared_count' => $autoClearedCount,
                 'total_lands_checked' => $harvestableLands->count(),
                 'harvest_results' => $harvestResults
             ]);
@@ -94,6 +112,7 @@ class PetAutoSkillLogic
                 'pet_id' => $pet->id,
                 'user_id' => $userId,
                 'harvest_count' => $harvestCount,
+                'auto_cleared_count' => $autoClearedCount,
                 'total_lands' => $harvestableLands->count()
             ]);
 
@@ -486,6 +505,344 @@ class PetAutoSkillLogic
         ];
     }
 
+    /**
+     * 处理自动除草技能
+     *
+     * @param PetActiveSkill $activeSkill 激活的技能
+     * @return void
+     */
+    public function processAutoWeeding(PetActiveSkill $activeSkill): void
+    {
+        try {
+            $pet = $activeSkill->pet;
+            $userId = $pet->user_id;
+
+            Log::info('开始处理自动除草技能', [
+                'active_skill_id' => $activeSkill->id,
+                'pet_id' => $pet->id,
+                'user_id' => $userId
+            ]);
+
+            // 获取用户所有有作物的土地
+            $landsWithCrops = LandService::getLandsWithCrops($userId);
+
+            if ($landsWithCrops->isEmpty()) {
+                Log::info('没有种植作物的土地', [
+                    'user_id' => $userId,
+                    'pet_id' => $pet->id
+                ]);
+                return;
+            }
+
+            $weedingCount = 0;
+            $disasterType = \App\Module\Farm\Enums\DISASTER_TYPE::WEED->value;
+
+            foreach ($landsWithCrops as $land) {
+                try {
+                    // 检查土地是否有杂草灾害
+                    $hasWeedDisaster = $this->checkSpecificDisaster($land, $disasterType);
+
+                    if ($hasWeedDisaster) {
+                        // 自动清除杂草灾害
+                        $cleared = $this->autoClearSpecificDisaster($userId, $land, $disasterType);
+
+                        if ($cleared) {
+                            $weedingCount++;
+                            Log::info('自动除草成功', [
+                                'user_id' => $userId,
+                                'pet_id' => $pet->id,
+                                'land_id' => $land->id
+                            ]);
+                        }
+                    }
+
+                } catch (\Exception $e) {
+                    Log::warning('自动除草处理失败', [
+                        'user_id' => $userId,
+                        'pet_id' => $pet->id,
+                        'land_id' => $land->id,
+                        'error' => $e->getMessage()
+                    ]);
+                }
+            }
+
+            // 记录统计信息
+            $this->recordSkillStatistics($activeSkill, 'auto_weeding', [
+                'weeding_count' => $weedingCount,
+                'total_lands_checked' => $landsWithCrops->count()
+            ]);
+
+            Log::info('自动除草技能处理完成', [
+                'active_skill_id' => $activeSkill->id,
+                'pet_id' => $pet->id,
+                'user_id' => $userId,
+                'weeding_count' => $weedingCount,
+                'total_lands' => $landsWithCrops->count()
+            ]);
+
+        } catch (\Exception $e) {
+            Log::error('处理自动除草技能失败', [
+                'active_skill_id' => $activeSkill->id,
+                'error' => $e->getMessage(),
+                'trace' => $e->getTraceAsString()
+            ]);
+        }
+    }
+
+    /**
+     * 处理自动浇水技能
+     *
+     * @param PetActiveSkill $activeSkill 激活的技能
+     * @return void
+     */
+    public function processAutoWatering(PetActiveSkill $activeSkill): void
+    {
+        try {
+            $pet = $activeSkill->pet;
+            $userId = $pet->user_id;
+
+            Log::info('开始处理自动浇水技能', [
+                'active_skill_id' => $activeSkill->id,
+                'pet_id' => $pet->id,
+                'user_id' => $userId
+            ]);
+
+            // 获取用户所有有作物的土地
+            $landsWithCrops = LandService::getLandsWithCrops($userId);
+
+            if ($landsWithCrops->isEmpty()) {
+                Log::info('没有种植作物的土地', [
+                    'user_id' => $userId,
+                    'pet_id' => $pet->id
+                ]);
+                return;
+            }
+
+            $wateringCount = 0;
+            $disasterType = \App\Module\Farm\Enums\DISASTER_TYPE::DROUGHT->value;
+
+            foreach ($landsWithCrops as $land) {
+                try {
+                    // 检查土地是否有干旱灾害
+                    $hasDroughtDisaster = $this->checkSpecificDisaster($land, $disasterType);
+
+                    if ($hasDroughtDisaster) {
+                        // 自动清除干旱灾害
+                        $cleared = $this->autoClearSpecificDisaster($userId, $land, $disasterType);
+
+                        if ($cleared) {
+                            $wateringCount++;
+                            Log::info('自动浇水成功', [
+                                'user_id' => $userId,
+                                'pet_id' => $pet->id,
+                                'land_id' => $land->id
+                            ]);
+                        }
+                    }
+
+                } catch (\Exception $e) {
+                    Log::warning('自动浇水处理失败', [
+                        'user_id' => $userId,
+                        'pet_id' => $pet->id,
+                        'land_id' => $land->id,
+                        'error' => $e->getMessage()
+                    ]);
+                }
+            }
+
+            // 记录统计信息
+            $this->recordSkillStatistics($activeSkill, 'auto_watering', [
+                'watering_count' => $wateringCount,
+                'total_lands_checked' => $landsWithCrops->count()
+            ]);
+
+            Log::info('自动浇水技能处理完成', [
+                'active_skill_id' => $activeSkill->id,
+                'pet_id' => $pet->id,
+                'user_id' => $userId,
+                'watering_count' => $wateringCount,
+                'total_lands' => $landsWithCrops->count()
+            ]);
+
+        } catch (\Exception $e) {
+            Log::error('处理自动浇水技能失败', [
+                'active_skill_id' => $activeSkill->id,
+                'error' => $e->getMessage(),
+                'trace' => $e->getTraceAsString()
+            ]);
+        }
+    }
+
+    /**
+     * 处理自动杀虫技能
+     *
+     * @param PetActiveSkill $activeSkill 激活的技能
+     * @return void
+     */
+    public function processAutoPestControl(PetActiveSkill $activeSkill): void
+    {
+        try {
+            $pet = $activeSkill->pet;
+            $userId = $pet->user_id;
+
+            Log::info('开始处理自动杀虫技能', [
+                'active_skill_id' => $activeSkill->id,
+                'pet_id' => $pet->id,
+                'user_id' => $userId
+            ]);
+
+            // 获取用户所有有作物的土地
+            $landsWithCrops = LandService::getLandsWithCrops($userId);
+
+            if ($landsWithCrops->isEmpty()) {
+                Log::info('没有种植作物的土地', [
+                    'user_id' => $userId,
+                    'pet_id' => $pet->id
+                ]);
+                return;
+            }
+
+            $pestControlCount = 0;
+            $disasterType = \App\Module\Farm\Enums\DISASTER_TYPE::PEST->value;
+
+            foreach ($landsWithCrops as $land) {
+                try {
+                    // 检查土地是否有虫害灾害
+                    $hasPestDisaster = $this->checkSpecificDisaster($land, $disasterType);
+
+                    if ($hasPestDisaster) {
+                        // 自动清除虫害灾害
+                        $cleared = $this->autoClearSpecificDisaster($userId, $land, $disasterType);
+
+                        if ($cleared) {
+                            $pestControlCount++;
+                            Log::info('自动杀虫成功', [
+                                'user_id' => $userId,
+                                'pet_id' => $pet->id,
+                                'land_id' => $land->id
+                            ]);
+                        }
+                    }
+
+                } catch (\Exception $e) {
+                    Log::warning('自动杀虫处理失败', [
+                        'user_id' => $userId,
+                        'pet_id' => $pet->id,
+                        'land_id' => $land->id,
+                        'error' => $e->getMessage()
+                    ]);
+                }
+            }
+
+            // 记录统计信息
+            $this->recordSkillStatistics($activeSkill, 'auto_pest_control', [
+                'pest_control_count' => $pestControlCount,
+                'total_lands_checked' => $landsWithCrops->count()
+            ]);
+
+            Log::info('自动杀虫技能处理完成', [
+                'active_skill_id' => $activeSkill->id,
+                'pet_id' => $pet->id,
+                'user_id' => $userId,
+                'pest_control_count' => $pestControlCount,
+                'total_lands' => $landsWithCrops->count()
+            ]);
+
+        } catch (\Exception $e) {
+            Log::error('处理自动杀虫技能失败', [
+                'active_skill_id' => $activeSkill->id,
+                'error' => $e->getMessage(),
+                'trace' => $e->getTraceAsString()
+            ]);
+        }
+    }
+
+    /**
+     * 检查特定类型的灾害
+     *
+     * @param mixed $land 土地对象
+     * @param int $disasterType 灾害类型
+     * @return bool
+     */
+    protected function checkSpecificDisaster($land, int $disasterType): bool
+    {
+        // 检查土地状态是否为灾害状态
+        if ($land->status !== \App\Module\Farm\Enums\LAND_STATUS::DISASTER->value) {
+            return false;
+        }
+
+        // 获取土地上的作物
+        $crop = $land->crop;
+        if (!$crop) {
+            return false;
+        }
+
+        // 检查作物是否有指定类型的活跃灾害
+        $disasters = $crop->disasters ?? [];
+
+        foreach ($disasters as $disaster) {
+            if (($disaster['status'] ?? '') === 'active' && ($disaster['type'] ?? 0) == $disasterType) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * 自动清除特定类型的灾害
+     *
+     * @param int $userId 用户ID
+     * @param mixed $land 土地对象
+     * @param int $disasterType 灾害类型
+     * @return bool
+     */
+    protected function autoClearSpecificDisaster(int $userId, $land, int $disasterType): bool
+    {
+        try {
+            // 获取对应的清除道具
+            $clearItem = $this->getDisasterClearItem($userId, $disasterType);
+
+            if (!$clearItem) {
+                return false;
+            }
+
+            // 调用农场服务清除灾害
+            $result = \App\Module\Farm\Services\CropService::clearDisaster($userId, $land->id, $disasterType);
+
+            if ($result) {
+                // 消耗道具
+                \App\Module\GameItems\Services\ItemService::consumeItem(
+                    $userId,
+                    $clearItem['item_id'],
+                    null,
+                    1,
+                    ['source' => 'pet_auto_specific_disaster_clear']
+                );
+
+                Log::info('宠物自动清除特定灾害成功', [
+                    'user_id' => $userId,
+                    'land_id' => $land->id,
+                    'disaster_type' => $disasterType,
+                    'item_id' => $clearItem['item_id']
+                ]);
+
+                return true;
+            }
+
+            return false;
+        } catch (\Exception $e) {
+            Log::warning('宠物自动清除特定灾害失败', [
+                'user_id' => $userId,
+                'land_id' => $land->id,
+                'disaster_type' => $disasterType,
+                'error' => $e->getMessage()
+            ]);
+
+            return false;
+        }
+    }
+
     /**
      * 记录技能统计信息
      *
@@ -516,4 +873,66 @@ class PetAutoSkillLogic
         $activeSkill->config = $config;
         $activeSkill->save();
     }
+
+    /**
+     * 自动铲除枯萎的作物
+     *
+     * @param int $userId 用户ID
+     * @param int $landId 土地ID
+     * @return bool 是否成功铲除
+     */
+    protected function autoClearWitheredCrop(int $userId, int $landId): bool
+    {
+        try {
+            // 获取土地信息
+            $land = \App\Module\Farm\Models\FarmLand::where('id', $landId)
+                ->where('user_id', $userId)
+                ->first();
+
+            if (!$land) {
+                return false;
+            }
+
+            // 检查土地状态是否为枯萎状态
+            if ($land->status !== \App\Module\Farm\Enums\LAND_STATUS::WITHERED->value) {
+                return false;
+            }
+
+            // 获取土地上的作物
+            $crop = \App\Module\Farm\Models\FarmCrop::where('land_id', $landId)->first();
+            if (!$crop) {
+                // 如果没有作物但土地状态是枯萎,修正土地状态为空闲
+                $land->status = \App\Module\Farm\Enums\LAND_STATUS::IDLE->value;
+                $land->save();
+                return true;
+            }
+
+            // 检查作物是否为枯萎状态
+            if ($crop->growth_stage !== \App\Module\Farm\Enums\GROWTH_STAGE::WITHERED->value) {
+                return false;
+            }
+
+            // 调用农场服务铲除作物
+            $result = \App\Module\Farm\Services\CropService::removeCrop($userId, $landId);
+
+            if ($result) {
+                Log::info('宠物自动铲除枯萎作物成功', [
+                    'user_id' => $userId,
+                    'land_id' => $landId,
+                    'crop_id' => $crop->id
+                ]);
+                return true;
+            }
+
+            return false;
+        } catch (\Exception $e) {
+            Log::warning('宠物自动铲除枯萎作物失败', [
+                'user_id' => $userId,
+                'land_id' => $landId,
+                'error' => $e->getMessage()
+            ]);
+
+            return false;
+        }
+    }
 }

+ 196 - 3
app/Module/Pet/Logic/PetLogic.php

@@ -637,9 +637,16 @@ class PetLogic
 
             case '灾害防护':
                 return $this->activateDisasterProtectionSkill($pet, $skill, $params);
-            //自动除草
-            //自动浇水
-            //自动杀虫
+
+            case '自动除草':
+                return $this->activateAutoWeedingSkill($pet, $skill, $params);
+
+            case '自动浇水':
+                return $this->activateAutoWateringSkill($pet, $skill, $params);
+
+            case '自动杀虫':
+                return $this->activateAutoPestControlSkill($pet, $skill, $params);
+
             default:
                 return [
                     'success' => false,
@@ -960,4 +967,190 @@ class PetLogic
 
         return (int)$power;
     }
+
+    /**
+     * 激活自动除草技能
+     *
+     * @param PetUser $pet 宠物对象
+     * @param PetSkill $skill 技能对象
+     * @param array $params 技能参数
+     * @return array 激活结果
+     */
+    protected function activateAutoWeedingSkill(PetUser $pet, PetSkill $skill, array $params): array
+    {
+        // 检查是否已有相同技能在激活中
+        $existingActiveSkill = \App\Module\Pet\Models\PetActiveSkill::where('pet_id', $pet->id)
+            ->where('skill_name', $skill->skill_name)
+            ->where('status', 'active')
+            ->where('end_time', '>', now())
+            ->first();
+
+        if ($existingActiveSkill) {
+            return [
+                'success' => false,
+                'message' => '该技能已经在激活中,无法重复激活'
+            ];
+        }
+
+        // 技能持续时间(默认3小时)
+        $duration = $params['duration'] ?? 10800; // 3小时
+        $endTime = now()->addSeconds($duration);
+
+        // 创建技能激活记录
+        $activeSkill = \App\Module\Pet\Models\PetActiveSkill::create([
+            'pet_id' => $pet->id,
+            'skill_id' => $skill->id,
+            'skill_name' => $skill->skill_name,
+            'start_time' => now(),
+            'end_time' => $endTime,
+            'status' => 'active',
+            'config' => json_encode([
+                'auto_weeding' => true,
+                'disaster_type' => \App\Module\Farm\Enums\DISASTER_TYPE::WEED->value, // 专门处理杂草灾害
+                'check_interval' => 300, // 每5分钟检查一次
+                'last_check_time' => now()->toDateTimeString(),
+                'auto_use_items' => $params['auto_use_items'] ?? true // 是否自动使用除草道具
+            ])
+        ]);
+
+        Log::info('自动除草技能激活成功', [
+            'pet_id' => $pet->id,
+            'skill_id' => $skill->id,
+            'duration' => $duration,
+            'end_time' => $endTime->toDateTimeString(),
+            'active_skill_id' => $activeSkill->id
+        ]);
+
+        return [
+            'success' => true,
+            'skill_type' => 'auto_weeding',
+            'duration' => $duration,
+            'end_time' => $endTime->toDateTimeString(),
+            'message' => "自动除草技能已激活,持续时间:{$duration}秒"
+        ];
+    }
+
+    /**
+     * 激活自动浇水技能
+     *
+     * @param PetUser $pet 宠物对象
+     * @param PetSkill $skill 技能对象
+     * @param array $params 技能参数
+     * @return array 激活结果
+     */
+    protected function activateAutoWateringSkill(PetUser $pet, PetSkill $skill, array $params): array
+    {
+        // 检查是否已有相同技能在激活中
+        $existingActiveSkill = \App\Module\Pet\Models\PetActiveSkill::where('pet_id', $pet->id)
+            ->where('skill_name', $skill->skill_name)
+            ->where('status', 'active')
+            ->where('end_time', '>', now())
+            ->first();
+
+        if ($existingActiveSkill) {
+            return [
+                'success' => false,
+                'message' => '该技能已经在激活中,无法重复激活'
+            ];
+        }
+
+        // 技能持续时间(默认4小时)
+        $duration = $params['duration'] ?? 14400; // 4小时
+        $endTime = now()->addSeconds($duration);
+
+        // 创建技能激活记录
+        $activeSkill = \App\Module\Pet\Models\PetActiveSkill::create([
+            'pet_id' => $pet->id,
+            'skill_id' => $skill->id,
+            'skill_name' => $skill->skill_name,
+            'start_time' => now(),
+            'end_time' => $endTime,
+            'status' => 'active',
+            'config' => json_encode([
+                'auto_watering' => true,
+                'disaster_type' => \App\Module\Farm\Enums\DISASTER_TYPE::DROUGHT->value, // 专门处理干旱灾害
+                'check_interval' => 300, // 每5分钟检查一次
+                'last_check_time' => now()->toDateTimeString(),
+                'auto_use_items' => $params['auto_use_items'] ?? true // 是否自动使用浇水道具
+            ])
+        ]);
+
+        Log::info('自动浇水技能激活成功', [
+            'pet_id' => $pet->id,
+            'skill_id' => $skill->id,
+            'duration' => $duration,
+            'end_time' => $endTime->toDateTimeString(),
+            'active_skill_id' => $activeSkill->id
+        ]);
+
+        return [
+            'success' => true,
+            'skill_type' => 'auto_watering',
+            'duration' => $duration,
+            'end_time' => $endTime->toDateTimeString(),
+            'message' => "自动浇水技能已激活,持续时间:{$duration}秒"
+        ];
+    }
+
+    /**
+     * 激活自动杀虫技能
+     *
+     * @param PetUser $pet 宠物对象
+     * @param PetSkill $skill 技能对象
+     * @param array $params 技能参数
+     * @return array 激活结果
+     */
+    protected function activateAutoPestControlSkill(PetUser $pet, PetSkill $skill, array $params): array
+    {
+        // 检查是否已有相同技能在激活中
+        $existingActiveSkill = \App\Module\Pet\Models\PetActiveSkill::where('pet_id', $pet->id)
+            ->where('skill_name', $skill->skill_name)
+            ->where('status', 'active')
+            ->where('end_time', '>', now())
+            ->first();
+
+        if ($existingActiveSkill) {
+            return [
+                'success' => false,
+                'message' => '该技能已经在激活中,无法重复激活'
+            ];
+        }
+
+        // 技能持续时间(默认3小时)
+        $duration = $params['duration'] ?? 10800; // 3小时
+        $endTime = now()->addSeconds($duration);
+
+        // 创建技能激活记录
+        $activeSkill = \App\Module\Pet\Models\PetActiveSkill::create([
+            'pet_id' => $pet->id,
+            'skill_id' => $skill->id,
+            'skill_name' => $skill->skill_name,
+            'start_time' => now(),
+            'end_time' => $endTime,
+            'status' => 'active',
+            'config' => json_encode([
+                'auto_pest_control' => true,
+                'disaster_type' => \App\Module\Farm\Enums\DISASTER_TYPE::PEST->value, // 专门处理虫害灾害
+                'check_interval' => 300, // 每5分钟检查一次
+                'last_check_time' => now()->toDateTimeString(),
+                'auto_use_items' => $params['auto_use_items'] ?? true // 是否自动使用杀虫道具
+            ])
+        ]);
+
+        Log::info('自动杀虫技能激活成功', [
+            'pet_id' => $pet->id,
+            'skill_id' => $skill->id,
+            'duration' => $duration,
+            'end_time' => $endTime->toDateTimeString(),
+            'active_skill_id' => $activeSkill->id
+        ]);
+
+        return [
+            'success' => true,
+            'skill_type' => 'auto_pest_control',
+            'duration' => $duration,
+            'end_time' => $endTime->toDateTimeString(),
+            'message' => "自动杀虫技能已激活,持续时间:{$duration}秒"
+        ];
+    }
 }