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

Merge remote-tracking branch 'origin/master'

notfff 7 сар өмнө
parent
commit
0ab881fbd8

+ 116 - 0
AiWork/202506/201449-修复神秘种子灾害产量显示错误.md

@@ -0,0 +1,116 @@
+# 修复神秘种子灾害产量显示错误
+
+**时间**: 2025年06月20日 14:49  
+**任务**: 修复后台土地类型列表中神秘种子灾害产量显示错误的问题
+
+## 问题描述
+
+用户反馈后台 `/admin/farm-land-types` 页面中,神秘种子的灾害产量显示为 200-300,但数据库配置的是 100-200,与期望不一致。
+
+## 问题分析
+
+通过检查发现问题的根源:
+
+1. **数据库配置正确**:种子产出配置表中,神秘种子的灾害产量确实配置为 100-200
+2. **普通种子显示正确**:普通种子的灾害产量正确显示为 100-200
+3. **神秘种子显示错误**:神秘种子的灾害产量错误显示为 200-300
+
+## 根本原因
+
+问题出现在 `MysterySeeLLogic::calculateAdjustedProbabilities()` 方法中,该方法返回的数据结构缺少了 `disaster_min_amount` 和 `disaster_max_amount` 字段,导致后台代码使用 fallback 逻辑,错误地使用了正常产量作为灾害产量。
+
+## 架构问题
+
+用户指出了一个重要的架构问题:**后台编写了独立的产出逻辑计算,这是错误的,应该使用服务层/逻辑层的现有逻辑**。
+
+这违反了项目的架构设计原则:
+- 后台应该使用服务层逻辑,而不是重复实现计算逻辑
+- 如果逻辑层不完善,说明逻辑层有问题,应该修复逻辑层
+
+## 解决方案
+
+### 1. 修复逻辑层
+
+修复 `app/Module/Farm/Logics/MysterySeeLLogic.php` 中的两个方法:
+
+#### calculateAdjustedProbabilities() 方法
+```php
+$adjustedOutputs[] = [
+    'item_id' => $output->item_id,
+    'min_amount' => $output->min_amount,
+    'max_amount' => $output->max_amount,
+    'disaster_min_amount' => $output->disaster_min_amount,  // 新增
+    'disaster_max_amount' => $output->disaster_max_amount,  // 新增
+    'original_probability' => $baseProbability,
+    'adjusted_probability' => $adjustedProbability,
+    'adjustment_type' => $adjustmentType,
+    'is_default' => $output->is_default
+];
+```
+
+#### getDefaultOutputConfig() 方法
+```php
+return [[
+    'item_id' => $seed->item_id,
+    'min_amount' => $seed->min_output,
+    'max_amount' => $seed->max_output,
+    'disaster_min_amount' => $seed->disaster_min_output,  // 新增
+    'disaster_max_amount' => $seed->disaster_max_output,  // 新增
+    'original_probability' => 100,
+    'adjusted_probability' => 100,
+    'adjustment_type' => 'default',
+    'is_default' => true
+]];
+```
+
+### 2. 更新后台代码注释
+
+更新 `app/Module/Farm/AdminControllers/Helper/GridHelperTrait.php` 中的注释,明确说明使用服务层逻辑:
+
+```php
+/**
+ * 渲染神秘种子的产出详情
+ * 
+ * 使用服务层逻辑计算神秘种子在该土地类型上的产出概率和产量
+ *
+ * @param \App\Module\Farm\Models\FarmLandType $landType
+ * @return string
+ */
+```
+
+## 测试验证
+
+修复后通过浏览器访问后台土地类型列表页面,验证结果:
+
+### 修复前
+- **神秘种子灾害产量**:200-300(错误)
+- **普通种子灾害产量**:100-200(正确)
+
+### 修复后
+- **神秘种子灾害产量**:100-200(正确)
+- **普通种子灾害产量**:100-200(正确)
+
+现在两者都与数据库配置一致。
+
+## 代码提交
+
+```bash
+git add app/Module/Farm/AdminControllers/Helper/GridHelperTrait.php app/Module/Farm/Logics/MysterySeeLLogic.php
+git commit -m "修复农场模块:神秘种子灾害产量显示错误问题
+
+- 修复MysterySeeLLogic::calculateAdjustedProbabilities()方法缺少disaster_min_amount和disaster_max_amount字段的问题
+- 修复getDefaultOutputConfig()方法缺少灾害产量字段的问题
+- 更新后台GridHelperTrait注释,明确使用服务层逻辑而非独立计算
+- 现在神秘种子和普通种子的灾害产量都正确显示为100-200,与数据库配置一致
+- 遵循架构设计原则:后台使用服务层逻辑,避免重复实现计算逻辑"
+git push
+```
+
+## 总结
+
+这次修复解决了两个层面的问题:
+
+1. **技术问题**:修复了逻辑层缺少灾害产量字段的bug
+2. **架构问题**:强调了后台应该使用服务层逻辑,而不是重复实现计算逻辑的原则
+
+通过修复逻辑层的数据结构,确保了后台显示与数据库配置的一致性,同时遵循了项目的架构设计原则。

+ 193 - 0
app/Module/Farm/AdminControllers/FarmFruitGrowthCycleController.php

@@ -0,0 +1,193 @@
+<?php
+
+namespace App\Module\Farm\AdminControllers;
+
+use App\Module\Farm\AdminControllers\Helper\FormHelper;
+use App\Module\Farm\AdminControllers\Helper\GridHelper;
+use App\Module\Farm\AdminControllers\Helper\ShowHelper;
+use App\Module\Farm\Repositories\FarmFruitGrowthCycleRepository;
+use Dcat\Admin\Form;
+use Dcat\Admin\Grid;
+use Dcat\Admin\Show;
+use UCore\DcatAdmin\AdminController;
+use Spatie\RouteAttributes\Attributes\Resource;
+
+/**
+ * 果实生长周期配置管理控制器
+ */
+#[Resource('farm-fruit-growth-cycles', names: 'dcat.admin.farm-fruit-growth-cycles')]
+class FarmFruitGrowthCycleController extends AdminController
+{
+    /**
+     * 页面标题
+     *
+     * @var string
+     */
+    protected $title = '果实生长周期配置管理';
+
+    /**
+     * 页面描述
+     *
+     * @var string
+     */
+    protected $description = '管理特定果实的生长周期配置信息';
+
+    /**
+     * 构建表格
+     *
+     * @return Grid
+     */
+    protected function grid()
+    {
+        return Grid::make(new FarmFruitGrowthCycleRepository(['fruitItem']), function (Grid $grid) {
+            $helper = new GridHelper($grid, $this);
+            
+            $grid->column('id', 'ID')->sortable();
+            $grid->column('fruit_item_id', '果实物品ID')->sortable();
+            
+            // 显示果实物品名称
+            $grid->column('fruitItem.name', '果实名称')->sortable();
+            
+            $grid->column('sprout_time', '发芽期时间(秒)')->sortable()->display(function ($value) {
+                return $value . ' (' . gmdate('H:i:s', $value) . ')';
+            });
+            
+            $grid->column('growth_time', '生长期时间(秒)')->sortable()->display(function ($value) {
+                return $value . ' (' . gmdate('H:i:s', $value) . ')';
+            });
+            
+            $grid->column('mature_time', '成熟期时间(秒)')->sortable()->display(function ($value) {
+                if ($value == 0) {
+                    return '0 (无限)';
+                }
+                return $value . ' (' . gmdate('H:i:s', $value) . ')';
+            });
+            
+            $grid->column('wither_time', '枯萎期时间(秒)')->sortable()->display(function ($value) {
+                if ($value == 0) {
+                    return '0 (无限)';
+                }
+                return $value . ' (' . gmdate('H:i:s', $value) . ')';
+            });
+            
+            $grid->column('created_at', '创建时间')->sortable();
+            $grid->column('updated_at', '更新时间')->sortable();
+
+            $grid->filter(function (Grid\Filter $filter) {
+                $filter->equal('id', 'ID');
+                $filter->equal('fruit_item_id', '果实物品ID');
+                $filter->between('created_at', '创建时间')->datetime();
+            });
+
+            $grid->tools(function (Grid\Tools $tools) {
+                $tools->batch(function (Grid\Tools\BatchActions $batch) {
+                    $batch->disableDelete();
+                });
+            });
+
+            $grid->actions(function (Grid\Displayers\Actions $actions) {
+                $actions->disableDelete();
+            });
+        });
+    }
+
+    /**
+     * 构建详情页
+     *
+     * @param mixed $id
+     * @return Show
+     */
+    protected function detail($id)
+    {
+        return Show::make($id, new FarmFruitGrowthCycleRepository(['fruitItem']), function (Show $show) {
+            $helper = new ShowHelper($show, $this);
+            
+            $show->field('id', 'ID');
+            $show->field('fruit_item_id', '果实物品ID');
+            $show->field('fruitItem.name', '果实名称');
+            
+            $show->field('sprout_time', '发芽期时间(秒)')->as(function ($value) {
+                return $value . ' (' . gmdate('H:i:s', $value) . ')';
+            });
+            
+            $show->field('growth_time', '生长期时间(秒)')->as(function ($value) {
+                return $value . ' (' . gmdate('H:i:s', $value) . ')';
+            });
+            
+            $show->field('mature_time', '成熟期时间(秒)')->as(function ($value) {
+                if ($value == 0) {
+                    return '0 (无限)';
+                }
+                return $value . ' (' . gmdate('H:i:s', $value) . ')';
+            });
+            
+            $show->field('wither_time', '枯萎期时间(秒)')->as(function ($value) {
+                if ($value == 0) {
+                    return '0 (无限)';
+                }
+                return $value . ' (' . gmdate('H:i:s', $value) . ')';
+            });
+            
+            $show->field('created_at', '创建时间');
+            $show->field('updated_at', '更新时间');
+        });
+    }
+
+    /**
+     * 构建表单
+     *
+     * @return Form
+     */
+    protected function form()
+    {
+        return Form::make(new FarmFruitGrowthCycleRepository(['fruitItem']), function (Form $form) {
+            $helper = new FormHelper($form, $this);
+            
+            $form->display('id', 'ID');
+            
+            $form->number('fruit_item_id', '果实物品ID')
+                ->min(1)
+                ->required()
+                ->help('对应的果实物品ID,必须是有效的物品ID');
+            
+            $form->number('sprout_time', '发芽期时间(秒)')
+                ->min(0)
+                ->required()
+                ->help('发芽期持续时间,单位:秒');
+            
+            $form->number('growth_time', '生长期时间(秒)')
+                ->min(0)
+                ->required()
+                ->help('生长期持续时间,单位:秒');
+            
+            $form->number('mature_time', '成熟期时间(秒)')
+                ->min(0)
+                ->default(0)
+                ->help('成熟期持续时间,单位:秒。设置为0表示无限时间,直到收获');
+            
+            $form->number('wither_time', '枯萎期时间(秒)')
+                ->min(0)
+                ->default(0)
+                ->help('枯萎期持续时间,单位:秒。设置为0表示无限时间,不会自动消失');
+
+            $form->display('created_at', '创建时间');
+            $form->display('updated_at', '更新时间');
+            
+            // 验证果实物品ID的唯一性
+            $form->saving(function (Form $form) {
+                $fruitItemId = $form->fruit_item_id;
+                $id = $form->model()->id ?? null;
+                
+                $exists = \App\Module\Farm\Models\FarmFruitGrowthCycle::where('fruit_item_id', $fruitItemId)
+                    ->when($id, function ($query) use ($id) {
+                        return $query->where('id', '!=', $id);
+                    })
+                    ->exists();
+                
+                if ($exists) {
+                    return $form->error('该果实物品ID已存在生长周期配置');
+                }
+            });
+        });
+    }
+}

+ 24 - 5
app/Module/Farm/Logics/CropLogic.php

@@ -12,6 +12,7 @@ use App\Module\Farm\Events\CropPlantedEvent;
 use App\Module\Farm\Events\DisasterClearedEvent;
 use App\Module\Farm\Events\LandStatusChangedEvent;
 use App\Module\Farm\Models\FarmCrop;
+use App\Module\Farm\Models\FarmFruitGrowthCycle;
 use App\Module\Farm\Models\FarmHarvestLog;
 use App\Module\Farm\Models\FarmLand;
 use App\Module\Farm\Models\FarmSeed;
@@ -972,23 +973,41 @@ class CropLogic
 
         $now = now();
 
+        // 优先检查是否有果实生长周期配置
+        $fruitGrowthCycle = null;
+        if ($crop->final_output_item_id) {
+            $fruitGrowthCycle = FarmFruitGrowthCycle::where('fruit_item_id', $crop->final_output_item_id)->first();
+        }
+
         switch ($stage) {
             case GROWTH_STAGE::SEED->value:
+                // 种子期始终使用种子配置的时间
                 return $now->addSeconds($seed->seed_time);
 
             case GROWTH_STAGE::SPROUT->value:
-                return $now->addSeconds($seed->sprout_time);
+                // 发芽期:优先使用果实生长周期配置,否则使用种子配置
+                $sproutTime = $fruitGrowthCycle ? $fruitGrowthCycle->sprout_time : $seed->sprout_time;
+                return $now->addSeconds($sproutTime);
 
             case GROWTH_STAGE::GROWTH->value:
-                return $now->addSeconds($seed->growth_time);
+                // 生长期:优先使用果实生长周期配置,否则使用种子配置
+                $growthTime = $fruitGrowthCycle ? $fruitGrowthCycle->growth_time : $seed->growth_time;
+                return $now->addSeconds($growthTime);
 
             case GROWTH_STAGE::MATURE->value:
-                // 成熟期没有 时间限制
-//                return $now->addHours(24);
+                // 成熟期:检查果实生长周期配置
+                if ($fruitGrowthCycle && $fruitGrowthCycle->mature_time > 0) {
+                    return $now->addSeconds($fruitGrowthCycle->mature_time);
+                }
+                // 默认成熟期没有时间限制
                 return null;
 
             case GROWTH_STAGE::WITHERED->value:
-                // 枯萎期没有结束时间
+                // 枯萎期:检查果实生长周期配置
+                if ($fruitGrowthCycle && $fruitGrowthCycle->wither_time > 0) {
+                    return $now->addSeconds($fruitGrowthCycle->wither_time);
+                }
+                // 默认枯萎期没有结束时间
                 return null;
 
             default:

+ 22 - 0
app/Module/Farm/Repositories/FarmFruitGrowthCycleRepository.php

@@ -0,0 +1,22 @@
+<?php
+
+namespace App\Module\Farm\Repositories;
+
+use App\Module\Farm\Models\FarmFruitGrowthCycle;
+use Dcat\Admin\Repositories\EloquentRepository;
+
+/**
+ * 果实生长周期配置仓库
+ *
+ * 提供果实生长周期配置数据的访问和操作功能。
+ * 该类是果实生长周期配置模块与后台管理系统的桥梁,用于处理果实生长周期配置数据的CRUD操作。
+ */
+class FarmFruitGrowthCycleRepository extends EloquentRepository
+{
+    /**
+     * 模型类名
+     *
+     * @var string
+     */
+    protected $eloquentClass = FarmFruitGrowthCycle::class;
+}