Browse Source

feat(farm): 实现土地配置表设计并更新相关文档

- 新增土地配置表设计文档,详细说明土地类型和升级配置的数据表结构
- 更新土地系统文档,添加对土地配置表的引用
- 修改事件系统文档,增加事件列表和监听器列表
- 更新数据库结构文档,添加新的土地类型配置表和土地升级配置表
- 修改枚举定义文档,更新土地类型枚举,添加对土地配置表的引用
Your Name 8 months ago
parent
commit
2591904180

+ 5 - 0
app/Module/Farm/Docs/README.md

@@ -16,6 +16,7 @@
 ### 2. 功能领域文档
 
 - [土地系统](土地系统.md) - 土地类型、状态和升级机制
+- [土地配置表设计](土地配置表设计.md) - 土地类型和升级配置的数据表设计
 - [房屋系统](房屋系统.md) - 房屋等级、升级和降级机制
 - [种子与作物系统](种子与作物系统.md) - 种子类型、作物生长周期和收获机制
 - [神灵加持系统](神灵加持系统.md) - 神灵加持类型、效果和实现机制
@@ -54,6 +55,10 @@
 | 2023-05-07 | 团队系统 | 新增团队系统文档 |
 | 2023-05-07 | 文档结构 | 更新文档索引,添加团队系统文档 |
 | 2023-05-11 | 文档结构 | 更新模块集成文档,添加团队模块集成链接 |
+| 2023-05-12 | 土地配置表设计 | 新增土地配置表设计文档 |
+| 2023-05-12 | 土地系统 | 更新土地系统文档,添加对土地配置表的引用 |
+| 2023-05-12 | 数据库设计 | 添加土地类型表和土地升级配置表结构 |
+| 2023-05-12 | 枚举定义 | 更新土地类型枚举,添加对土地配置表的引用 |
 
 ## 文档规范
 

+ 235 - 77
app/Module/Farm/Docs/事件系统.md

@@ -23,22 +23,22 @@ class CropPlantedEvent
      * @var int 用户ID
      */
     public $userId;
-    
+
     /**
      * @var int 土地ID
      */
     public $landId;
-    
+
     /**
      * @var int 种子ID
      */
     public $seedId;
-    
+
     /**
      * @var int 作物ID
      */
     public $cropId;
-    
+
     /**
      * 构造函数
      */
@@ -65,27 +65,27 @@ class CropHarvestedEvent
      * @var int 用户ID
      */
     public $userId;
-    
+
     /**
      * @var int 土地ID
      */
     public $landId;
-    
+
     /**
      * @var int 作物ID
      */
     public $cropId;
-    
+
     /**
      * @var int 种子ID
      */
     public $seedId;
-    
+
     /**
      * @var int 产出数量
      */
     public $outputAmount;
-    
+
     /**
      * 构造函数
      */
@@ -113,22 +113,22 @@ class LandUpgradedEvent
      * @var int 用户ID
      */
     public $userId;
-    
+
     /**
      * @var int 土地ID
      */
     public $landId;
-    
+
     /**
      * @var int 旧土地类型
      */
     public $oldType;
-    
+
     /**
      * @var int 新土地类型
      */
     public $newType;
-    
+
     /**
      * 构造函数
      */
@@ -155,17 +155,17 @@ class HouseUpgradedEvent
      * @var int 用户ID
      */
     public $userId;
-    
+
     /**
      * @var int 旧等级
      */
     public $oldLevel;
-    
+
     /**
      * @var int 新等级
      */
     public $newLevel;
-    
+
     /**
      * 构造函数
      */
@@ -191,17 +191,17 @@ class DisasterOccurredEvent
      * @var int 用户ID
      */
     public $userId;
-    
+
     /**
      * @var int 作物ID
      */
     public $cropId;
-    
+
     /**
      * @var int 灾害类型
      */
     public $disasterType;
-    
+
     /**
      * 构造函数
      */
@@ -232,27 +232,27 @@ class ItemChangedEvent
      * @var int 用户ID
      */
     public $userId;
-    
+
     /**
      * @var int 物品ID
      */
     public $itemId;
-    
+
     /**
      * @var string 变更类型 (add/remove)
      */
     public $changeType;
-    
+
     /**
      * @var int 变更数量
      */
     public $amount;
-    
+
     /**
      * @var string 变更原因
      */
     public $reason;
-    
+
     /**
      * 构造函数
      */
@@ -281,22 +281,22 @@ class PetSkillUsedEvent
      * @var int 用户ID
      */
     public $userId;
-    
+
     /**
      * @var int 宠物ID
      */
     public $petId;
-    
+
     /**
      * @var int 技能ID
      */
     public $skillId;
-    
+
     /**
      * @var array 技能参数
      */
     public $params;
-    
+
     /**
      * 构造函数
      */
@@ -310,9 +310,46 @@ class PetSkillUsedEvent
 }
 ```
 
-## 3. 事件监听器
+## 3. 事件列表
+
+以下是农场模块中所有事件的完整列表,包括发出的事件和监听的事件。
+
+### 3.1 发出的事件列表
+
+| 事件名称 | 事件类 | 触发条件 | 包含数据 | 用途 |
+|---------|-------|---------|---------|------|
+| 作物种植事件 | CropPlantedEvent | 用户种植作物 | userId, landId, seedId, cropId | 通知其他模块用户种植了作物 |
+| 作物收获事件 | CropHarvestedEvent | 用户收获作物 | userId, landId, cropId, seedId, outputAmount | 通知其他模块用户收获了作物,用于计算团队收益等 |
+| 土地升级事件 | LandUpgradedEvent | 用户升级土地 | userId, landId, oldType, newType | 通知其他模块用户升级了土地 |
+| 房屋升级事件 | HouseUpgradedEvent | 用户升级房屋 | userId, oldLevel, newLevel | 通知其他模块用户升级了房屋 |
+| 灾害发生事件 | DisasterOccurredEvent | 作物遭遇灾害 | userId, cropId, disasterType | 通知其他模块作物遭遇了灾害 |
+| 作物生长阶段变更事件 | CropGrowthStageChangedEvent | 作物生长阶段变更 | userId, cropId, oldStage, newStage | 通知其他模块作物生长阶段发生变化 |
+| 土地状态变更事件 | LandStatusChangedEvent | 土地状态变更 | userId, landId, oldStatus, newStatus | 通知其他模块土地状态发生变化 |
+| 神灵加持激活事件 | GodBuffActivatedEvent | 用户激活神灵加持 | userId, buffType, expireTime | 通知其他模块用户激活了神灵加持 |
+| 神灵加持过期事件 | GodBuffExpiredEvent | 神灵加持过期 | userId, buffType | 通知其他模块用户的神灵加持已过期 |
+| 灾害处理事件 | DisasterHandledEvent | 用户处理灾害 | userId, cropId, disasterType, toolId | 通知其他模块用户处理了灾害 |
 
-### 3.1 物品变更事件监听器
+### 3.2 监听的事件列表
+
+| 事件名称 | 事件类 | 来源模块 | 监听目的 | 处理逻辑 |
+|---------|-------|---------|---------|---------|
+| 物品变更事件 | ItemChangedEvent | GameItems | 处理与农场相关的物品变更 | 处理种子、化肥、工具等物品的变更 |
+| 宠物技能使用事件 | PetSkillUsedEvent | Pet | 处理与农场相关的宠物技能 | 处理自动收菜、自动播种、除草等宠物技能 |
+| 用户注册事件 | UserRegisteredEvent | User | 初始化用户农场 | 为新注册用户创建农场记录和初始土地 |
+| 每日重置事件 | DailyResetEvent | System | 处理农场每日重置 | 重置每日限制、检查房屋降级等 |
+
+### 3.3 事件与监听器对应关系
+
+| 事件类 | 监听器类 | 处理方法 |
+|-------|---------|---------|
+| ItemChangedEvent | ItemChangedListener | handle() |
+| PetSkillUsedEvent | PetSkillUsedListener | handle() |
+| UserRegisteredEvent | UserRegisteredListener | handle() |
+| DailyResetEvent | DailyResetListener | handle() |
+
+## 4. 事件监听器
+
+### 4.1 物品变更事件监听器
 
 监听物品变更事件,处理与农场相关的物品变更。
 
@@ -329,12 +366,12 @@ class ItemChangedListener
      * @var SeedService
      */
     protected $seedService;
-    
+
     /**
      * @var CropService
      */
     protected $cropService;
-    
+
     /**
      * 构造函数
      */
@@ -343,7 +380,7 @@ class ItemChangedListener
         $this->seedService = $seedService;
         $this->cropService = $cropService;
     }
-    
+
     /**
      * 处理事件
      */
@@ -354,23 +391,23 @@ class ItemChangedListener
         $itemId = $event->itemId;
         $changeType = $event->changeType;
         $amount = $event->amount;
-        
+
         // 处理种子物品变更
         if ($this->isSeedItem($itemId)) {
             $this->handleSeedItemChanged($userId, $itemId, $changeType, $amount);
         }
-        
+
         // 处理化肥物品变更
         if ($this->isFertilizerItem($itemId)) {
             $this->handleFertilizerItemChanged($userId, $itemId, $changeType, $amount);
         }
-        
+
         // 处理工具物品变更
         if ($this->isToolItem($itemId)) {
             $this->handleToolItemChanged($userId, $itemId, $changeType, $amount);
         }
     }
-    
+
     /**
      * 判断物品是否为种子
      */
@@ -379,7 +416,7 @@ class ItemChangedListener
         // 判断逻辑
         return $this->seedService->isSeedItem($itemId);
     }
-    
+
     /**
      * 处理种子物品变更
      */
@@ -387,12 +424,12 @@ class ItemChangedListener
     {
         // 处理逻辑
     }
-    
+
     // 其他辅助方法...
 }
 ```
 
-### 3.2 宠物技能使用事件监听器
+### 4.2 宠物技能使用事件监听器
 
 监听宠物技能使用事件,处理与农场相关的宠物技能。
 
@@ -409,12 +446,12 @@ class PetSkillUsedListener
      * @var CropService
      */
     protected $cropService;
-    
+
     /**
      * @var LandService
      */
     protected $landService;
-    
+
     /**
      * 构造函数
      */
@@ -423,7 +460,7 @@ class PetSkillUsedListener
         $this->cropService = $cropService;
         $this->landService = $landService;
     }
-    
+
     /**
      * 处理事件
      */
@@ -434,23 +471,23 @@ class PetSkillUsedListener
         $petId = $event->petId;
         $skillId = $event->skillId;
         $params = $event->params;
-        
+
         // 处理自动收菜技能
         if ($this->isAutoHarvestSkill($skillId)) {
             $this->handleAutoHarvest($userId, $params);
         }
-        
+
         // 处理自动播种技能
         if ($this->isAutoPlantSkill($skillId)) {
             $this->handleAutoPlant($userId, $params);
         }
-        
+
         // 处理除草技能
         if ($this->isWeedRemovalSkill($skillId)) {
             $this->handleWeedRemoval($userId, $params);
         }
     }
-    
+
     /**
      * 判断技能是否为自动收菜技能
      */
@@ -459,7 +496,7 @@ class PetSkillUsedListener
         // 判断逻辑
         return $skillId == 1001;
     }
-    
+
     /**
      * 处理自动收菜技能
      */
@@ -467,18 +504,18 @@ class PetSkillUsedListener
     {
         // 获取用户所有可收获的作物
         $harvestableCrops = $this->cropService->getUserHarvestableCrops($userId);
-        
+
         // 自动收获作物
         foreach ($harvestableCrops as $crop) {
             $this->cropService->harvestCrop($crop->id);
         }
     }
-    
+
     // 其他辅助方法...
 }
 ```
 
-## 4. 事件注册
+## 5. 事件注册
 
 在 `FarmServiceProvider` 中注册事件和监听器:
 
@@ -506,30 +543,30 @@ class FarmServiceProvider extends ServiceProvider
             PetSkillUsedListener::class,
         ],
     ];
-    
+
     /**
      * 注册服务提供者
      */
     public function register()
     {
         parent::register();
-        
+
         // 注册服务
     }
-    
+
     /**
      * 启动服务提供者
      */
     public function boot()
     {
         parent::boot();
-        
+
         // 启动服务
     }
 }
 ```
 
-## 5. 事件触发
+## 6. 事件触发
 
 在服务层中触发事件:
 
@@ -548,10 +585,10 @@ class CropService
     {
         // 种植作物的业务逻辑
         // ...
-        
+
         // 触发作物种植事件
         event(new CropPlantedEvent($userId, $landId, $seedId, $crop->id));
-        
+
         return [
             'crop_id' => $crop->id,
             'land_id' => $landId,
@@ -560,7 +597,7 @@ class CropService
             'stage_end_time' => $crop->stage_end_time,
         ];
     }
-    
+
     /**
      * 收获作物
      */
@@ -568,10 +605,10 @@ class CropService
     {
         // 收获作物的业务逻辑
         // ...
-        
+
         // 触发作物收获事件
         event(new CropHarvestedEvent($userId, $land->id, $crop->id, $seedConfig->id, $outputAmount));
-        
+
         return [
             'output_item_id' => $seedConfig->output_item_id,
             'amount' => $outputAmount
@@ -580,25 +617,25 @@ class CropService
 }
 ```
 
-## 6. 事件处理流程
+## 7. 事件处理流程
 
-### 6.1 发出事件流程
+### 7.1 发出事件流程
 
 1. 在服务层方法中执行业务逻辑
 2. 业务逻辑执行成功后,使用 `event()` 函数触发事件
 3. Laravel 事件系统将事件分发给注册的监听器
 4. 监听器执行相应的处理逻辑
 
-### 6.2 监听事件流程
+### 7.2 监听事件流程
 
 1. 在 `FarmServiceProvider` 中注册监听器
 2. 当其他模块触发事件时,Laravel 事件系统将事件分发给注册的监听器
 3. 监听器的 `handle()` 方法被调用,接收事件对象作为参数
 4. 监听器根据事件数据执行相应的处理逻辑
 
-## 7. 事件系统扩展
+## 8. 事件系统扩展
 
-### 7.1 添加新事件
+### 8.1 添加新事件
 
 如需添加新事件,请按照以下步骤操作:
 
@@ -617,22 +654,22 @@ class CropGrowthStageChangedEvent
      * @var int 用户ID
      */
     public $userId;
-    
+
     /**
      * @var int 作物ID
      */
     public $cropId;
-    
+
     /**
      * @var int 旧生长阶段
      */
     public $oldStage;
-    
+
     /**
      * @var int 新生长阶段
      */
     public $newStage;
-    
+
     /**
      * 构造函数
      */
@@ -646,7 +683,7 @@ class CropGrowthStageChangedEvent
 }
 ```
 
-### 7.2 添加新监听器
+### 8.2 添加新监听器
 
 如需添加新监听器,请按照以下步骤操作:
 
@@ -668,7 +705,7 @@ class UserRegisteredListener
      * @var FarmService
      */
     protected $farmService;
-    
+
     /**
      * 构造函数
      */
@@ -676,7 +713,7 @@ class UserRegisteredListener
     {
         $this->farmService = $farmService;
     }
-    
+
     /**
      * 处理事件
      */
@@ -684,7 +721,7 @@ class UserRegisteredListener
     {
         // 获取事件数据
         $userId = $event->userId;
-        
+
         // 初始化用户农场
         $this->farmService->initUserFarm($userId);
     }
@@ -707,8 +744,129 @@ protected $listen = [
 ];
 ```
 
-## 8. 总结
+## 9. 模块间服务调用
+
+除了事件系统外,模块间还通过直接的服务调用进行交互,特别是对于核心业务流程。
+
+### 9.1 被其他模块调用的服务
+
+农场模块提供以下服务接口供其他模块调用:
+
+| 服务方法 | 调用模块 | 用途 | 参数 | 返回值 |
+|---------|---------|------|------|-------|
+| unlockFeature | Quest | 解锁农场功能 | userId, featureType | bool |
+| addReward | Quest | 发放农场奖励 | userId, rewardType, amount | bool |
+| checkFarmCondition | Quest | 检查农场条件 | userId, conditionType | bool |
+
+### 9.2 调用示例
+
+```php
+// 在任务模块中调用农场服务
+public function completeQuest(int $userId, int $questId)
+{
+    // 任务完成逻辑
+    // ...
+
+    // 根据任务类型调用相应的农场服务
+    if ($quest->type == QuestType::FARM_RELATED) {
+        $this->farmService->unlockFeature($userId, $quest->reward_feature_type);
+    }
+
+    return true;
+}
+```
+
+### 9.3 服务接口声明
+
+```php
+/**
+ * 农场服务接口
+ *
+ * 提供给其他模块调用的农场功能接口
+ */
+interface FarmServiceInterface
+{
+    /**
+     * 解锁农场功能
+     *
+     * @param int $userId 用户ID
+     * @param int $featureType 功能类型(参考FarmFeatureType枚举)
+     * @return bool 是否成功
+     */
+    public function unlockFeature(int $userId, int $featureType): bool;
+
+    /**
+     * 发放农场奖励
+     *
+     * @param int $userId 用户ID
+     * @param int $rewardType 奖励类型(参考FarmRewardType枚举)
+     * @param int $amount 奖励数量
+     * @return bool 是否成功
+     */
+    public function addReward(int $userId, int $rewardType, int $amount): bool;
+
+    /**
+     * 检查农场条件
+     *
+     * @param int $userId 用户ID
+     * @param int $conditionType 条件类型(参考FarmConditionType枚举)
+     * @return bool 是否满足条件
+     */
+    public function checkFarmCondition(int $userId, int $conditionType): bool;
+}
+```
+
+### 9.4 服务调用伪代码
+
+```php
+// 在任务系统中调用农场服务的伪代码
+class QuestService
+{
+    // 依赖注入农场服务
+    public function __construct(FarmServiceInterface $farmService)
+    {
+        // 初始化
+    }
+
+    // 完成任务
+    public function completeQuest(int $userId, int $questId): bool
+    {
+        // 任务完成逻辑
+
+        // 根据任务类型调用相应的农场服务
+        if (/* 任务与农场相关 */) {
+            // 解锁农场功能
+            $this->farmService->unlockFeature($userId, /* 功能类型 */);
+
+            // 发放农场奖励
+            $this->farmService->addReward($userId, /* 奖励类型 */, /* 奖励数量 */);
+        }
+
+        // 任务完成后的其他处理...
+
+        return true;
+    }
+}
+```
+
+### 9.5 服务接口设计原则
+
+1. **职责明确**:每个服务方法应该有明确的职责,避免一个方法做多件事情
+2. **参数简洁**:参数应该简洁明了,避免过多的参数
+3. **返回值清晰**:返回值应该清晰表达操作结果,必要时使用异常处理错误情况
+4. **文档完善**:每个服务方法都应该有完善的文档,包括参数说明、返回值说明和异常说明
+5. **版本控制**:服务接口的变更应该遵循版本控制原则,避免破坏向后兼容性
+
+## 10. 总结
+
+农场模块通过两种方式与其他模块交互:事件系统和服务调用。
+
+**事件系统**用于处理非核心业务流程,如通知、日志、统计等。模块发出的事件包括作物种植事件、作物收获事件、土地升级事件、房屋升级事件和灾害发生事件;模块监听的事件包括物品变更事件和宠物技能使用事件。
 
-农场模块的事件系统通过发布和订阅事件,实现了模块间的松耦合通信。模块发出的事件包括作物种植事件、作物收获事件、土地升级事件、房屋升级事件和灾害发生事件;模块监听的事件包括物品变更事件和宠物技能使用事件。
+**服务调用**用于处理核心业务流程,如任务系统调用农场系统的服务来解锁功能或发放奖励。这种方式保持了代码流程的清晰和可控,同时减少了模块间的耦合
 
-事件系统的使用使得模块间的交互更加灵活,降低了模块间的耦合度,提高了代码的可维护性和可扩展性。在开发过程中,应该合理使用事件系统,避免过度使用导致代码流程难以追踪。
+在开发过程中,应该根据具体需求选择合适的交互方式:
+- 对于核心业务流程,优先使用服务调用
+- 对于非核心业务流程,优先使用事件系统
+- 避免过度使用事件系统导致代码流程难以追踪
+- 避免过度使用服务调用导致模块间的强耦合

+ 71 - 2
app/Module/Farm/Docs/土地系统.md

@@ -92,7 +92,9 @@ enum LAND_STATUS: int {
 
 - 普通→红土地:木材x10
 - 红→黑土地:石材x10
-- 黑→特殊土地:钢材x10+钻石x5
+- 黑→特殊土地(金/蓝/紫):钢材x10+钻石x5
+
+> 注:升级材料配置存储在 farm_land_upgrade_configs 表中,可通过后台配置修改。详细设计请参考 [土地配置表设计](土地配置表设计.md) 文档。
 
 ## 6. 数据结构
 
@@ -108,7 +110,35 @@ enum LAND_STATUS: int {
 | created_at | timestamp | 创建时间 |
 | updated_at | timestamp | 更新时间 |
 
-### 6.2 索引设计
+### 6.2 土地类型配置表 (farm_land_types)
+
+| 字段名 | 类型 | 说明 |
+|--------|------|------|
+| id | tinyint | 土地类型ID |
+| name | varchar | 土地类型名称 |
+| code | varchar | 土地类型编码 |
+| output_bonus | decimal | 产量加成 |
+| disaster_resistance | decimal | 灾害抵抗 |
+| unlock_house_level | tinyint | 解锁所需房屋等级 |
+| is_special | tinyint | 是否为特殊土地 |
+| icon | varchar | 图标路径 |
+| description | text | 描述 |
+| created_at | timestamp | 创建时间 |
+| updated_at | timestamp | 更新时间 |
+
+### 6.3 土地升级配置表 (farm_land_upgrade_configs)
+
+| 字段名 | 类型 | 说明 |
+|--------|------|------|
+| id | int | 主键ID |
+| from_type_id | tinyint | 起始土地类型ID |
+| to_type_id | tinyint | 目标土地类型ID |
+| materials | json | 升级所需材料 |
+| conditions | json | 其他升级条件 |
+| created_at | timestamp | 创建时间 |
+| updated_at | timestamp | 更新时间 |
+
+### 6.4 索引设计
 
 - 主键索引:`id`
 - 复合索引:`user_id, position`(确保每个用户的土地位置唯一)
@@ -223,6 +253,45 @@ public function calculateDisasterResistance(FarmLand $land): float
 public function canHaveMoreSpecialLand(int $userId, int $landType): bool
 ```
 
+### 8.4 获取升级所需材料
+
+```php
+/**
+ * 获取升级所需材料
+ *
+ * @param int $currentType 当前土地类型
+ * @param int $targetType 目标土地类型
+ * @return array 升级所需材料
+ */
+public function getUpgradeMaterials(int $currentType, int $targetType): array
+{
+    // 普通→红土地:木材x10
+    if ($currentType == LAND_TYPE::NORMAL && $targetType == LAND_TYPE::RED) {
+        return [
+            ['item_id' => 1001, 'amount' => 10]  // 木材x10
+        ];
+    }
+
+    // 红→黑土地:石材x10
+    if ($currentType == LAND_TYPE::RED && $targetType == LAND_TYPE::BLACK) {
+        return [
+            ['item_id' => 1002, 'amount' => 10]  // 石材x10
+        ];
+    }
+
+    // 黑→特殊土地(金/蓝/紫):钢材x10+钻石x5
+    if ($currentType == LAND_TYPE::BLACK &&
+        in_array($targetType, [LAND_TYPE::GOLD, LAND_TYPE::BLUE, LAND_TYPE::PURPLE])) {
+        return [
+            ['item_id' => 1003, 'amount' => 10],  // 钢材x10
+            ['item_id' => 1004, 'amount' => 5]    // 钻石x5
+        ];
+    }
+
+    return [];
+}
+```
+
 ## 9. 前端交互
 
 ### 9.1 土地展示

+ 306 - 0
app/Module/Farm/Docs/土地配置表设计.md

@@ -0,0 +1,306 @@
+# 土地配置表设计
+
+为了将土地类型属性和升级材料从硬编码改为数据表配置,我们设计了以下两个表:
+
+## 1. 土地类型配置表 (farm_land_types)
+
+存储不同土地类型的属性,如产量加成、灾害抵抗等。
+
+```sql
+CREATE TABLE `farm_land_types` (
+  `id` tinyint(3) unsigned NOT NULL AUTO_INCREMENT COMMENT '土地类型ID',
+  `name` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '土地类型名称',
+  `code` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '土地类型编码',
+  `output_bonus` decimal(5,2) NOT NULL DEFAULT '0.00' COMMENT '产量加成',
+  `disaster_resistance` decimal(5,2) NOT NULL DEFAULT '0.00' COMMENT '灾害抵抗',
+  `unlock_house_level` tinyint(3) unsigned NOT NULL DEFAULT '1' COMMENT '解锁所需房屋等级',
+  `is_special` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否为特殊土地',
+  `icon` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '图标路径',
+  `description` text COLLATE utf8mb4_unicode_ci COMMENT '描述',
+  `created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+  `updated_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `idx_code` (`code`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='土地类型配置表';
+```
+
+### 1.1 初始数据
+
+```sql
+INSERT INTO `farm_land_types` (`id`, `name`, `code`, `output_bonus`, `disaster_resistance`, `unlock_house_level`, `is_special`) VALUES
+(1, '普通土地', 'NORMAL', 0.00, 0.00, 1, 0),
+(2, '红土地', 'RED', 0.10, 0.05, 1, 0),
+(3, '黑土地', 'BLACK', 0.25, 0.10, 1, 0),
+(4, '金色特殊土地', 'GOLD', 0.50, 0.15, 7, 1),
+(5, '蓝色特殊土地', 'BLUE', 0.40, 0.25, 7, 1),
+(6, '紫色特殊土地', 'PURPLE', 0.60, 0.10, 7, 1);
+```
+
+## 2. 土地升级配置表 (farm_land_upgrade_configs)
+
+存储土地升级路径和所需材料。
+
+```sql
+CREATE TABLE `farm_land_upgrade_configs` (
+  `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID',
+  `from_type_id` tinyint(3) unsigned NOT NULL COMMENT '起始土地类型ID',
+  `to_type_id` tinyint(3) unsigned NOT NULL COMMENT '目标土地类型ID',
+  `materials` json NOT NULL COMMENT '升级所需材料',
+  `conditions` json DEFAULT NULL COMMENT '其他升级条件',
+  `created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+  `updated_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `idx_from_to` (`from_type_id`,`to_type_id`),
+  KEY `idx_from_type` (`from_type_id`),
+  KEY `idx_to_type` (`to_type_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='土地升级配置表';
+```
+
+### 2.1 初始数据
+
+```sql
+INSERT INTO `farm_land_upgrade_configs` (`from_type_id`, `to_type_id`, `materials`, `conditions`) VALUES
+(1, 2, '{"materials": [{"item_name": "木材", "amount": 10}]}', NULL),
+(2, 3, '{"materials": [{"item_name": "石材", "amount": 10}]}', NULL),
+(3, 4, '{"materials": [{"item_name": "钢材", "amount": 10}, {"item_name": "钻石", "amount": 5}]}', '{"house_level_min": 7, "special_land_check": true}'),
+(3, 5, '{"materials": [{"item_name": "钢材", "amount": 10}, {"item_name": "钻石", "amount": 5}]}', '{"house_level_min": 7, "special_land_check": true}'),
+(3, 6, '{"materials": [{"item_name": "钢材", "amount": 10}, {"item_name": "钻石", "amount": 5}]}', '{"house_level_min": 7, "special_land_check": true}');
+```
+
+### 2.2 条件字段说明
+
+`conditions` 字段是一个JSON对象,可以包含以下属性:
+
+1. **house_level_min**: 最低房屋等级要求
+2. **special_land_check**: 是否检查特殊土地数量限制
+3. **user_level_min**: 最低用户等级要求(可选)
+4. **quest_completed**: 需要完成的任务ID(可选)
+5. **time_limited**: 时间限制配置(可选)
+   - start_time: 开始时间
+   - end_time: 结束时间
+
+示例:
+```json
+{
+  "house_level_min": 7,
+  "special_land_check": true,
+  "user_level_min": 10,
+  "quest_completed": [101, 102],
+  "time_limited": {
+    "start_time": "2023-01-01 00:00:00",
+    "end_time": "2023-12-31 23:59:59"
+  }
+}
+```
+
+## 3. 与现有数据库的关系
+
+### 3.1 关系图更新
+
+```
+                                    farm_user_referrals
+                                           ^
+                                           |
+                                           |
+farm_users (1) ------ (N) farm_lands      |
+     |                    |                |
+     |                    |                |
+     |                    |                |
+     |                    |                |
+     v                    v                |
+farm_house_configs    farm_crops           |
+                          |                |
+                          |                |
+                          |                |
+                          v                |
+                      farm_seeds           |
+                          |                |
+                          |                |
+                          v                |
+                    farm_harvest_logs -----+
+                          |
+                          |
+                          v
+                   farm_team_profits
+
+farm_land_types <---- farm_lands
+     ^
+     |
+     v
+farm_land_upgrade_configs
+```
+
+### 3.2 关系说明
+
+1. **土地与土地类型**:土地表中的 land_type 字段关联到 farm_land_types 表的 id 字段
+2. **土地升级配置**:farm_land_upgrade_configs 表通过 from_type_id 和 to_type_id 字段关联到 farm_land_types 表
+
+## 4. 代码修改
+
+### 4.1 修改 LandLogic 类中的 getUpgradeMaterials 方法
+
+```php
+/**
+ * 获取升级所需材料
+ *
+ * @param int $currentType 当前土地类型
+ * @param int $targetType 目标土地类型
+ * @return array 升级所需材料
+ */
+public function getUpgradeMaterials(int $currentType, int $targetType): array
+{
+    // 从数据库中获取升级配置
+    $upgradeConfig = $this->landUpgradeConfigRepository->findByFromAndToType($currentType, $targetType);
+
+    if (!$upgradeConfig) {
+        return [];
+    }
+
+    return json_decode($upgradeConfig->materials, true)['materials'] ?? [];
+}
+```
+
+### 4.2 修改 LandLogic 类中的 isValidUpgradePath 方法
+
+```php
+/**
+ * 验证升级路径是否有效
+ *
+ * @param int $currentType 当前土地类型
+ * @param int $targetType 目标土地类型
+ * @return bool 是否有效
+ */
+public function isValidUpgradePath(int $currentType, int $targetType): bool
+{
+    // 从数据库中检查是否存在升级配置
+    return $this->landUpgradeConfigRepository->existsByFromAndToType($currentType, $targetType);
+}
+```
+
+### 4.3 添加 LandLogic 类中的 checkUpgradeConditions 方法
+
+```php
+/**
+ * 检查升级条件是否满足
+ *
+ * @param int $userId 用户ID
+ * @param int $currentType 当前土地类型
+ * @param int $targetType 目标土地类型
+ * @return array ['success' => bool, 'message' => string] 检查结果和消息
+ */
+public function checkUpgradeConditions(int $userId, int $currentType, int $targetType): array
+{
+    // 从数据库中获取升级配置
+    $upgradeConfig = $this->landUpgradeConfigRepository->findByFromAndToType($currentType, $targetType);
+
+    if (!$upgradeConfig) {
+        return ['success' => false, 'message' => '无效的升级路径'];
+    }
+
+    // 解析条件
+    $conditions = json_decode($upgradeConfig->conditions, true);
+    if (empty($conditions)) {
+        return ['success' => true, 'message' => ''];
+    }
+
+    // 检查房屋等级条件
+    if (isset($conditions['house_level_min'])) {
+        $houseLevel = $this->farmUserRepository->findByUserId($userId)->house_level;
+        if ($houseLevel < $conditions['house_level_min']) {
+            return [
+                'success' => false,
+                'message' => "房屋等级不足,需要{$conditions['house_level_min']}级房屋"
+            ];
+        }
+    }
+
+    // 检查特殊土地数量限制
+    if (isset($conditions['special_land_check']) && $conditions['special_land_check']) {
+        $landType = $this->landTypeRepository->find($targetType);
+        if ($landType && $landType->is_special) {
+            if (!$this->canHaveMoreSpecialLand($userId, $targetType)) {
+                return [
+                    'success' => false,
+                    'message' => '已达到特殊土地上限'
+                ];
+            }
+        }
+    }
+
+    // 检查用户等级条件
+    if (isset($conditions['user_level_min'])) {
+        $userLevel = $this->userRepository->findById($userId)->level;
+        if ($userLevel < $conditions['user_level_min']) {
+            return [
+                'success' => false,
+                'message' => "用户等级不足,需要达到{$conditions['user_level_min']}级"
+            ];
+        }
+    }
+
+    // 检查任务完成条件
+    if (isset($conditions['quest_completed']) && !empty($conditions['quest_completed'])) {
+        $questIds = $conditions['quest_completed'];
+        foreach ($questIds as $questId) {
+            if (!$this->questService->isQuestCompleted($userId, $questId)) {
+                return [
+                    'success' => false,
+                    'message' => "需要完成指定任务"
+                ];
+            }
+        }
+    }
+
+    // 检查时间限制条件
+    if (isset($conditions['time_limited'])) {
+        $now = time();
+        $startTime = strtotime($conditions['time_limited']['start_time']);
+        $endTime = strtotime($conditions['time_limited']['end_time']);
+
+        if ($now < $startTime || $now > $endTime) {
+            return [
+                'success' => false,
+                'message' => "不在升级开放时间内"
+            ];
+        }
+    }
+
+    return ['success' => true, 'message' => ''];
+}
+```
+
+### 4.4 修改 LandLogic 类中的 isSpecialLandType 方法
+
+```php
+/**
+ * 判断是否为特殊土地类型
+ *
+ * @param int $landType 土地类型
+ * @return bool 是否为特殊土地
+ */
+public function isSpecialLandType(int $landType): bool
+{
+    // 从数据库中获取土地类型配置
+    $landTypeConfig = $this->landTypeRepository->find($landType);
+
+    if (!$landTypeConfig) {
+        return false;
+    }
+
+    return (bool)$landTypeConfig->is_special;
+}
+```
+
+## 5. 优势
+
+1. **灵活配置**:可以通过后台管理界面修改土地类型属性和升级材料,无需修改代码
+2. **易于扩展**:可以轻松添加新的土地类型和升级路径
+3. **数据一致性**:避免硬编码导致的数据不一致问题
+4. **便于管理**:集中管理所有土地相关配置
+
+## 6. 注意事项
+
+1. **数据迁移**:实施此方案需要编写数据迁移脚本,将现有的枚举值转换为数据表记录
+2. **代码修改**:需要修改相关的业务逻辑代码,使用数据库配置替代硬编码
+3. **缓存策略**:由于配置数据频繁访问但很少修改,应实施适当的缓存策略
+4. **前端适配**:前端代码可能需要调整,以适应新的数据结构

+ 108 - 10
app/Module/Farm/Docs/数据库设计.md

@@ -10,11 +10,13 @@
 4. **farm_crops** - 作物信息表
 5. **farm_seeds** - 种子配置表
 6. **farm_house_configs** - 房屋等级配置表
-7. **farm_harvest_logs** - 收获记录表
-8. **farm_upgrade_logs** - 升级记录表
-9. **farm_user_referrals** - 用户推荐关系表
-10. **farm_user_talents** - 达人等级表
-11. **farm_team_profits** - 团队收益记录表
+7. **farm_land_types** - 土地类型配置表
+8. **farm_land_upgrade_configs** - 土地升级配置表
+9. **farm_harvest_logs** - 收获记录表
+10. **farm_upgrade_logs** - 升级记录表
+11. **farm_user_referrals** - 用户推荐关系表
+12. **farm_user_talents** - 达人等级表
+13. **farm_team_profits** - 团队收益记录表
 
 ## 2. 表结构详细设计
 
@@ -143,7 +145,49 @@ CREATE TABLE `farm_house_configs` (
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='房屋等级配置表';
 ```
 
-### 2.7 收获记录表 (farm_harvest_logs)
+### 2.7 土地类型配置表 (farm_land_types)
+
+存储不同土地类型的属性,如产量加成、灾害抵抗等。
+
+```sql
+CREATE TABLE `farm_land_types` (
+  `id` tinyint(3) unsigned NOT NULL AUTO_INCREMENT COMMENT '土地类型ID',
+  `name` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '土地类型名称',
+  `code` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '土地类型编码',
+  `output_bonus` decimal(5,2) NOT NULL DEFAULT '0.00' COMMENT '产量加成',
+  `disaster_resistance` decimal(5,2) NOT NULL DEFAULT '0.00' COMMENT '灾害抵抗',
+  `unlock_house_level` tinyint(3) unsigned NOT NULL DEFAULT '1' COMMENT '解锁所需房屋等级',
+  `is_special` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否为特殊土地',
+  `icon` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '图标路径',
+  `description` text COLLATE utf8mb4_unicode_ci COMMENT '描述',
+  `created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+  `updated_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `idx_code` (`code`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='土地类型配置表';
+```
+
+### 2.8 土地升级配置表 (farm_land_upgrade_configs)
+
+存储土地升级路径和所需材料。
+
+```sql
+CREATE TABLE `farm_land_upgrade_configs` (
+  `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID',
+  `from_type_id` tinyint(3) unsigned NOT NULL COMMENT '起始土地类型ID',
+  `to_type_id` tinyint(3) unsigned NOT NULL COMMENT '目标土地类型ID',
+  `materials` json NOT NULL COMMENT '升级所需材料',
+  `conditions` json DEFAULT NULL COMMENT '其他升级条件',
+  `created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+  `updated_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `idx_from_to` (`from_type_id`,`to_type_id`),
+  KEY `idx_from_type` (`from_type_id`),
+  KEY `idx_to_type` (`to_type_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='土地升级配置表';
+```
+
+### 2.9 收获记录表 (farm_harvest_logs)
 
 记录作物收获的历史数据。
 
@@ -205,7 +249,7 @@ CREATE TABLE `farm_user_referrals` (
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户推荐关系表';
 ```
 
-### 2.10 达人等级表 (farm_user_talents)
+### 2.11 达人等级表 (farm_user_talents)
 
 存储用户的达人等级信息,包括直推人数和团队总人数。
 
@@ -224,7 +268,7 @@ CREATE TABLE `farm_user_talents` (
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='达人等级表';
 ```
 
-### 2.11 团队收益记录表 (farm_team_profits)
+### 2.12 团队收益记录表 (farm_team_profits)
 
 记录团队成员收获作物时产生的分成收益。
 
@@ -273,6 +317,12 @@ farm_house_configs    farm_crops           |
                           |
                           v
                    farm_team_profits
+
+farm_land_types <---- farm_lands
+     ^
+     |
+     v
+farm_land_upgrade_configs
 ```
 
 ### 3.2 关系说明
@@ -285,6 +335,8 @@ farm_house_configs    farm_crops           |
 6. **用户与推荐关系**:一个用户可以有多个推荐人和被推荐人(M:N)
 7. **用户与达人等级**:一个用户有一个达人等级记录(1:1)
 8. **收获与团队收益**:一次收获可以产生多条团队收益记录(1:N)
+9. **土地与土地类型**:土地表中的 land_type 字段关联到 farm_land_types 表的 id 字段(N:1)
+10. **土地升级配置**:farm_land_upgrade_configs 表通过 from_type_id 和 to_type_id 字段关联到 farm_land_types 表(M:N)
 
 ## 4. 索引设计
 
@@ -298,15 +350,19 @@ farm_house_configs    farm_crops           |
 - `farm_lands`: `user_id, position`(确保每个用户的土地位置唯一)
 - `farm_crops`: `land_id`(确保一块土地只有一个作物)
 - `farm_house_configs`: `level`(确保等级唯一)
+- `farm_land_types`: `code`(确保土地类型编码唯一)
+- `farm_land_upgrade_configs`: `from_type_id, to_type_id`(确保升级路径唯一)
 - `farm_user_referrals`: `user_id, referrer_id`(确保推荐关系不重复)
 - `farm_user_talents`: `user_id`(确保每个用户只有一条达人记录)
 
 ### 4.3 普通索引
 
 - `farm_users`: `house_level`, `last_upgrade_time`
-- `farm_lands`: `user_id`, `status`
+- `farm_lands`: `user_id`, `status`, `land_type`
 - `farm_crops`: `user_id`, `seed_id`, `growth_stage`, `stage_end_time`
 - `farm_seeds`: `type`
+- `farm_land_types`: `is_special`, `unlock_house_level`
+- `farm_land_upgrade_configs`: `from_type_id`, `to_type_id`
 - `farm_harvest_logs`: `user_id`, `harvest_time`, `seed_id`
 - `farm_upgrade_logs`: `user_id`, `upgrade_time`, `upgrade_type`
 
@@ -360,6 +416,21 @@ farm_house_configs    farm_crops           |
 }
 ```
 
+### 5.5 土地升级条件JSON (conditions)
+
+```json
+{
+  "house_level_min": 7,
+  "special_land_check": true,
+  "user_level_min": 10,
+  "quest_completed": [101, 102],
+  "time_limited": {
+    "start_time": "2023-01-01 00:00:00",
+    "end_time": "2023-12-31 23:59:59"
+  }
+}
+```
+
 ## 6. 数据初始化
 
 ### 6.1 种子数据
@@ -370,7 +441,34 @@ farm_house_configs    farm_crops           |
 
 初始化12级房屋的配置数据,包括产出加成、特殊土地上限、升级材料和降级天数。
 
-### 6.3 新用户初始化
+### 6.3 土地类型配置数据
+
+初始化土地类型配置数据:
+
+```sql
+INSERT INTO `farm_land_types` (`id`, `name`, `code`, `output_bonus`, `disaster_resistance`, `unlock_house_level`, `is_special`) VALUES
+(1, '普通土地', 'NORMAL', 0.00, 0.00, 1, 0),
+(2, '红土地', 'RED', 0.10, 0.05, 1, 0),
+(3, '黑土地', 'BLACK', 0.25, 0.10, 1, 0),
+(4, '金色特殊土地', 'GOLD', 0.50, 0.15, 7, 1),
+(5, '蓝色特殊土地', 'BLUE', 0.40, 0.25, 7, 1),
+(6, '紫色特殊土地', 'PURPLE', 0.60, 0.10, 7, 1);
+```
+
+### 6.4 土地升级配置数据
+
+初始化土地升级配置数据:
+
+```sql
+INSERT INTO `farm_land_upgrade_configs` (`from_type_id`, `to_type_id`, `materials`, `conditions`) VALUES
+(1, 2, '{"materials": [{"item_name": "木材", "amount": 10}]}', NULL),
+(2, 3, '{"materials": [{"item_name": "石材", "amount": 10}]}', NULL),
+(3, 4, '{"materials": [{"item_name": "钢材", "amount": 10}, {"item_name": "钻石", "amount": 5}]}', '{"house_level_min": 7, "special_land_check": true}'),
+(3, 5, '{"materials": [{"item_name": "钢材", "amount": 10}, {"item_name": "钻石", "amount": 5}]}', '{"house_level_min": 7, "special_land_check": true}'),
+(3, 6, '{"materials": [{"item_name": "钢材", "amount": 10}, {"item_name": "钻石", "amount": 5}]}', '{"house_level_min": 7, "special_land_check": true}');
+```
+
+### 6.5 新用户初始化
 
 新用户注册时,需要:
 1. 创建用户农场记录,设置房屋等级为1

+ 19 - 2
app/Module/Farm/Docs/枚举定义.md

@@ -23,8 +23,12 @@ enum LAND_TYPE: int {
 }
 ```
 
+> 注:土地类型的属性(产量加成、灾害抵抗等)现在存储在 farm_land_types 表中,可通过后台配置修改。详细设计请参考 [土地配置表设计](土地配置表设计.md) 文档。
+
 #### 土地类型属性表
 
+下表为默认配置,实际值以数据库配置为准:
+
 | 土地类型 | 值 | 产量加成 | 灾害抵抗 | 解锁条件 | 升级材料 |
 |---------|---|---------|---------|---------|---------|
 | 普通土地 | 1 | 0% | 0% | 默认 | - |
@@ -198,8 +202,8 @@ enum GOD_BUFF_TYPE: int {
 ### 6.1 土地类型判断
 
 ```php
-// 判断土地是否为特殊土地
-public function isSpecialLandType(int $landType): bool
+// 判断土地是否为特殊土地(旧版本,硬编码)
+public function isSpecialLandType_old(int $landType): bool
 {
     return in_array($landType, [
         LAND_TYPE::GOLD,
@@ -207,6 +211,19 @@ public function isSpecialLandType(int $landType): bool
         LAND_TYPE::PURPLE
     ]);
 }
+
+// 判断土地是否为特殊土地(新版本,使用数据库配置)
+public function isSpecialLandType(int $landType): bool
+{
+    // 从数据库中获取土地类型配置
+    $landTypeConfig = $this->landTypeRepository->find($landType);
+
+    if (!$landTypeConfig) {
+        return false;
+    }
+
+    return (bool)$landTypeConfig->is_special;
+}
 ```
 
 ### 6.2 土地状态更新

+ 2 - 0
noai.md

@@ -57,3 +57,5 @@ apply_diff
 
 改进 GenerateModelAnnotation ,在 模块 的 `Databases/createsql` 目录下生成每一个表的创建sql,一个表一个文件
 
+AppGame模块,增加登陆成功事件
+