Просмотр исходного кода

修复宠物自动收获技能中铲除枯萎作物功能

问题分析:
1. 原逻辑通过土地状态查找枯萎作物,但收获后土地状态可能不会立即更新为枯萎状态
2. 应该直接检查作物的growth_stage状态,而不是依赖土地状态

修复内容:
1. 修改autoClearWitheredCropAfterHarvest方法,直接检查作物状态而不是土地状态
2. 修改clearAllWitheredCrops方法,使用whereHas关联查询直接查找枯萎状态的作物
3. 优化错误信息,显示当前作物状态便于调试

测试验证:
- 收获作物后自动进入枯萎期
- 宠物自动铲除功能正常工作
- 土地状态正确更新为空闲,可继续种植
Your Name 5 месяцев назад
Родитель
Сommit
4b0e775ece

+ 0 - 168
AiWork/202507/200202-修复宠物自动收获技能铲除枯萎作物功能.md

@@ -1,168 +0,0 @@
-# 修复宠物自动收获技能铲除枯萎作物功能
-
-**时间**: 2025年07月20日 02:02  
-**任务类型**: Bug修复  
-**相关模块**: Pet模块 - 宠物自动技能系统  
-
-## 问题描述
-
-用户反馈宠物自动收获技能中的铲除枯萎作物功能不生效,收获后枯萎的作物仍然存在。
-
-## 问题分析
-
-通过代码分析发现以下问题:
-
-### 1. 事务管理问题
-- **问题**: 逻辑层方法中有`\UCore\Db\Helper::check_tr()`事务检查,但Job中没有开启事务
-- **影响**: 导致事务检查失败,方法无法正常执行
-- **根本原因**: 违反了项目规范 - "逻辑层不能开启事务,需要事务进行事务开启检查"
-
-### 2. 返回值处理问题
-- **问题**: `processAutoHarvest`方法返回`void`,但Job期望获取统计数据
-- **影响**: 无法记录详细的处理统计信息
-- **表现**: 处理日志中只有简单的`skill_type`信息
-
-### 3. Job中方法调用不一致
-- **问题**: 对不同返回类型的方法使用了错误的处理方式
-- **影响**: 部分技能的统计数据丢失
-
-## 解决方案
-
-### 1. 修复事务管理
-**遵循项目规范**: 在Job中开启事务,逻辑层检查事务
-
-**修改文件**: `app/Module/Pet/Jobs/ProcessActiveSkillsJob.php`
-
-```php
-try {
-    // 开启事务,因为逻辑层需要事务支持
-    DB::beginTransaction();
-
-    switch ($activeSkill->skill_name) {
-        case \App\Module\Pet\Enums\PET_SKILL_NAME::AUTO_HARVESTING->value:
-            $result = $autoSkillLogic->processAutoHarvest($activeSkill);
-            $processData = $this->extractProcessData($result, 'auto_harvest');
-            break;
-        // ... 其他技能处理
-    }
-
-    // 如果执行成功,提交事务
-    if ($processStatus === 'success') {
-        DB::commit();
-    }
-
-} catch (\Exception $e) {
-    // 发生异常时回滚事务
-    DB::rollBack();
-    // ... 错误处理
-}
-```
-
-### 2. 修复processAutoHarvest返回值
-**修改文件**: `app/Module/Pet/Logic/PetAutoSkillLogic.php`
-
-```php
-public function processAutoHarvest(PetActiveSkill $activeSkill): array
-{
-    // ... 处理逻辑 ...
-
-    // 返回统计数据
-    return [
-        'harvest_count' => $harvestCount,
-        'auto_cleared_count' => $autoClearedCount,
-        'withered_cleared_count' => $witheredClearCount,
-        'total_lands_checked' => $harvestableLands->count(),
-        'harvest_results' => $harvestResults
-    ];
-}
-```
-
-### 3. 修复Job中的方法调用
-区分返回`array`和`void`的方法,使用正确的处理方式:
-
-```php
-// 返回array的方法
-case \App\Module\Pet\Enums\PET_SKILL_NAME::AUTO_HARVESTING->value:
-    $result = $autoSkillLogic->processAutoHarvest($activeSkill);
-    $processData = $this->extractProcessData($result, 'auto_harvest');
-    break;
-
-// 返回void的方法
-case \App\Module\Pet\Enums\PET_SKILL_NAME::AUTO_WEEDING->value:
-    $autoSkillLogic->processAutoWeeding($activeSkill);
-    $processData = [
-        'skill_type' => 'auto_weeding',
-        'processed_at' => now()->toDateTimeString()
-    ];
-    break;
-```
-
-## 铲除枯萎作物的实现机制
-
-### 负责技能
-**"自动收获"技能** (`AUTO_HARVESTING`) 负责铲除枯萎期作物
-
-### 实现方式
-1. **预先清理**: 在开始收获前,调用`clearAllWitheredCrops`方法清理所有枯萎状态的土地
-2. **收获后清理**: 每次收获后,调用`autoClearWitheredCrop`方法自动铲除新产生的枯萎作物
-
-### 关键方法
-- `clearAllWitheredCrops()`: 批量清理所有枯萎状态的土地
-- `autoClearWitheredCrop()`: 自动铲除单个土地上的枯萎作物
-
-### 铲除逻辑
-- 不使用道具,直接调用`CropService::removeCrop($userId, $landId, 0)`
-- 软删除作物记录(设置`deleted_at`字段)
-- 更新土地状态从枯萎(4)变为空闲(0)
-- 更新土地的`has_crop`字段为0
-
-## 测试验证
-
-### 测试场景
-创建测试用户(user_id=2)的枯萎作物:
-- 土地ID: 2436
-- 作物ID: 14820
-- 作物状态: growth_stage=50(枯萎期)
-- 土地状态: status=4(枯萎状态)
-
-### 测试结果
-✅ **功能正常工作**:
-- 土地状态从4(枯萎)变为0(空闲)
-- 土地的`has_crop`从1变为0
-- 作物被软删除(`deleted_at`有值)
-
-### 验证命令
-```bash
-php artisan pet:process-active-skills --sync
-php artisan queue:work --once
-```
-
-## 修改文件列表
-
-1. **app/Module/Pet/Logic/PetAutoSkillLogic.php**
-   - 修复`processAutoHarvest`方法返回类型和返回值
-   - 保持事务检查逻辑不变(符合项目规范)
-
-2. **app/Module/Pet/Jobs/ProcessActiveSkillsJob.php**
-   - 添加事务管理逻辑
-   - 修复不同返回类型方法的处理方式
-   - 添加DB facade引用
-
-## 提交信息
-
-```
-修复宠物自动收获技能中的铲除枯萎作物功能
-
-- 修复Job中的事务管理问题:在Job中开启事务,逻辑层检查事务(符合项目规范)
-- 修复processAutoHarvest方法返回值:让方法返回详细统计数据
-- 修复Job中对不同返回类型方法的处理:区分返回array和void的方法
-- 验证铲除枯萎作物功能正常工作:土地状态从枯萎变为空闲,作物被软删除
-
-自动收获技能现在可以正确铲除枯萎期作物:
-1. 预先清理所有枯萎状态的土地
-2. 收获后自动铲除新产生的枯萎作物
-```
-
-## 总结
-
-通过修复事务管理和返回值处理问题,宠物自动收获技能中的铲除枯萎作物功能现在可以正常工作。该功能通过两种方式处理枯萎作物:预先清理和收获后清理,确保农场中的枯萎作物能够被及时清理,为用户提供更好的游戏体验。

+ 1 - 1
app/Module/Pet/Console/ProcessActiveSkillsCommand.php

@@ -1,4 +1,4 @@
- <?php
+<?php
 
 namespace App\Module\Pet\Console;
 

+ 98 - 18
app/Module/Pet/Logic/PetAutoSkillLogic.php

@@ -39,13 +39,14 @@ class PetAutoSkillLogic
             'user_id' => $userId
         ]);
 
-        // 首先清理所有枯萎作物(不使用道具)
+        // 首先清理所有已存在的枯萎作物(不使用道具)
         $witheredClearCount = $this->clearAllWitheredCrops($userId);
 
         // 获取用户所有可收获的土地
         $harvestableLands = LandService::getHarvestableLands($userId);
 
         $harvestCount = 0;
+        $autoClearedCount = 0;
         $harvestResults = [];
 
         if (!$harvestableLands->isEmpty()) {
@@ -67,15 +68,24 @@ class PetAutoSkillLogic
                         'land_id' => $land->id
                     ]);
 
-                    // 收获后自动铲除枯萎的作物
-                    $clearResult = $this->autoClearWitheredCrop($userId, $land->id);
-                    if ($clearResult) {
+                    // 收获后该土地的作物会自动变成枯萎状态,立即铲除
+                    $clearResult = $this->autoClearWitheredCropAfterHarvest($userId, $land->id);
+                    if ($clearResult['success']) {
                         $harvestResults[count($harvestResults) - 1]['auto_cleared'] = true;
+                        $autoClearedCount++;
 
-                        Log::info('自动铲除枯萎作物成功', [
+                        Log::info('自动铲除收获后枯萎作物成功', [
                             'user_id' => $userId,
                             'pet_id' => $pet->id,
-                            'land_id' => $land->id
+                            'land_id' => $land->id,
+                            'crop_id' => $clearResult['crop_id']
+                        ]);
+                    } else {
+                        Log::warning('自动铲除收获后枯萎作物失败', [
+                            'user_id' => $userId,
+                            'pet_id' => $pet->id,
+                            'land_id' => $land->id,
+                            'reason' => $clearResult['reason']
                         ]);
                     }
                 } else {
@@ -89,9 +99,6 @@ class PetAutoSkillLogic
             }
         }
 
-        // 统计自动铲除的数量
-        $autoClearedCount = array_sum(array_column($harvestResults, 'auto_cleared'));
-
         // 记录统计信息
         $this->recordSkillStatistics($activeSkill, 'auto_harvest', [
             'harvest_count' => $harvestCount,
@@ -784,6 +791,8 @@ class PetAutoSkillLogic
     /**
      * 清理所有枯萎的作物(不使用道具)
      *
+     * 直接查找枯萎状态的作物,而不是通过土地状态
+     *
      * @param int $userId 用户ID
      * @return int 清理的数量
      * @throws \Exception
@@ -793,25 +802,29 @@ class PetAutoSkillLogic
         // 检查事务是否已开启
         \UCore\Db\Helper::check_tr();
 
-        // 获取所有枯萎状态的土地
-        $witheredLands = \App\Module\Farm\Models\FarmLand::where('user_id', $userId)
-            ->where('status', \App\Module\Farm\Enums\LAND_STATUS::WITHERED->value)
+        // 直接查找所有枯萎状态的作物
+        $witheredCrops = \App\Module\Farm\Models\FarmCrop::whereHas('land', function($query) use ($userId) {
+                $query->where('user_id', $userId);
+            })
+            ->where('growth_stage', \App\Module\Farm\Enums\GROWTH_STAGE::WITHERED->value)
             ->get();
 
         $clearedCount = 0;
 
-        foreach ($witheredLands as $land) {
-            $cleared = $this->autoClearWitheredCrop($userId, $land->id);
-            if ($cleared) {
+        foreach ($witheredCrops as $crop) {
+            $clearResult = $this->autoClearWitheredCrop($userId, $crop->land_id);
+            if ($clearResult) {
                 $clearedCount++;
                 Log::info('自动清理枯萎作物成功', [
                     'user_id' => $userId,
-                    'land_id' => $land->id
+                    'land_id' => $crop->land_id,
+                    'crop_id' => $crop->id
                 ]);
             } else {
                 Log::warning('自动清理枯萎作物失败', [
                     'user_id' => $userId,
-                    'land_id' => $land->id,
+                    'land_id' => $crop->land_id,
+                    'crop_id' => $crop->id,
                     'error' => '清理操作返回失败'
                 ]);
             }
@@ -821,7 +834,7 @@ class PetAutoSkillLogic
             Log::info('批量清理枯萎作物完成', [
                 'user_id' => $userId,
                 'cleared_count' => $clearedCount,
-                'total_withered_lands' => $witheredLands->count()
+                'total_withered_crops' => $witheredCrops->count()
             ]);
         }
 
@@ -1080,4 +1093,71 @@ class PetAutoSkillLogic
 
         return null;
     }
+
+    /**
+     * 收获后自动铲除枯萎的作物
+     *
+     * 收获后作物会自动变成枯萎状态,此方法专门处理收获后的枯萎作物铲除
+     * 直接检查作物状态,而不是土地状态
+     *
+     * @param int $userId 用户ID
+     * @param int $landId 土地ID
+     * @return array 返回操作结果 ['success' => bool, 'reason' => string, 'crop_id' => int|null]
+     */
+    protected function autoClearWitheredCropAfterHarvest(int $userId, int $landId): array
+    {
+        try {
+            // 获取土地信息
+            $land = \App\Module\Farm\Models\FarmLand::where('id', $landId)
+                ->where('user_id', $userId)
+                ->first();
+
+            if (!$land) {
+                return ['success' => false, 'reason' => '土地不存在', 'crop_id' => null];
+            }
+
+            // 获取土地上的作物(直接检查作物状态,不依赖土地状态)
+            $crop = \App\Module\Farm\Models\FarmCrop::where('land_id', $landId)->first();
+            if (!$crop) {
+                return ['success' => false, 'reason' => '土地上没有作物', 'crop_id' => null];
+            }
+
+            // 检查作物是否为枯萎状态
+            $cropStageValue = is_object($crop->growth_stage) ? $crop->growth_stage->value : $crop->growth_stage;
+            if ($cropStageValue !== \App\Module\Farm\Enums\GROWTH_STAGE::WITHERED->value) {
+                return ['success' => false, 'reason' => '作物不是枯萎状态,当前状态: ' . $cropStageValue, 'crop_id' => $crop->id];
+            }
+
+            // 调用农场服务铲除作物(宠物自动铲除,工具ID为0)
+            $result = \App\Module\Farm\Services\CropService::removeCrop($userId, $landId, 0);
+
+            if ($result['success']) {
+                return [
+                    'success' => true,
+                    'reason' => '宠物自动铲除枯萎作物成功',
+                    'crop_id' => $crop->id
+                ];
+            } else {
+                return [
+                    'success' => false,
+                    'reason' => '铲除作物失败',
+                    'crop_id' => $crop->id
+                ];
+            }
+
+        } catch (\Exception $e) {
+            Log::error('宠物自动铲除收获后枯萎作物失败', [
+                'user_id' => $userId,
+                'land_id' => $landId,
+                'error' => $e->getMessage(),
+                'trace' => $e->getTraceAsString()
+            ]);
+
+            return [
+                'success' => false,
+                'reason' => '铲除作物异常: ' . $e->getMessage(),
+                'crop_id' => null
+            ];
+        }
+    }
 }