Browse Source

优化LandTemp逻辑:统一处理土地变更和状态变更

- 扩展LandChangeTempDto支持所有类型的土地变更
- 添加changeType字段区分变更类型(type/status)
- 统一使用game:land:changes:缓存键前缀
- 更新事件处理方法使用统一存储逻辑
- 简化服务层接口,提供过滤方法
- 保持向后兼容性,原有接口标记为deprecated
- 更新相关文档说明新的统一架构
notfff 7 months ago
parent
commit
735694038e

+ 85 - 37
app/Module/Game/Docs/土地暂存系统.md

@@ -1,11 +1,21 @@
 # 土地暂存系统
 
-> 最后更新时间:2024年5月
+> 最后更新时间:2024年12月
+
+## 重要更新 (2024年12月)
+
+**系统已优化为统一处理所有类型的土地变更**:
+- 不再区分土地类型变更和土地状态变更,统一使用 `LandChangeTempDto`
+- 使用统一的缓存键前缀 `game:land:changes:`
+- 提供新的过滤接口:`getUserTypeChanges()` 和 `getUserStatusChanges()`
+- 保持向后兼容性,原有接口仍可使用但标记为 deprecated
 
 ## 1. 概述
 
 土地暂存系统是 Game 模块提供的一个用于跟踪和记录用户土地变更的临时存储机制,主要用于优化前端UI更新和提高用户体验。当用户土地状态发生变化(如创建、升级、状态变更等)时,系统会将变更信息暂时存储,前端可以通过API获取这些变更信息,从而实现土地变更的实时反馈。
 
+系统现已优化为统一处理所有类型的土地变更,简化了架构并提高了性能。
+
 ## 2. 系统架构
 
 土地暂存系统由以下几个部分组成:
@@ -18,8 +28,8 @@
 
 ### 2.2 DTO 类
 
-- **LandChangeTempDto**: 土地变更临时数据传输对象,用于存储和传输土地变更临时数据。
-- **LandStatusTempDto**: 土地状态临时数据传输对象,用于存储和传输土地状态变更的临时数据
+- **LandChangeTempDto**: 统一的土地变更临时数据传输对象,用于存储和传输所有类型的土地变更临时数据(包括类型变更和状态变更)
+- **LandStatusTempDto**: 土地状态临时数据传输对象(向后兼容,已标记为 deprecated)
 
 ### 2.3 监听器(在 Game 模块中实现)
 
@@ -29,11 +39,11 @@
 
 ### 2.4 逻辑层
 
-- **LandTemp**: 土地临时数据逻辑类,负责处理土地变更事件的临时数据存储逻辑。
+- **LandTemp**: 土地临时数据逻辑类,负责处理土地变更事件的临时数据存储逻辑。统一处理所有类型的土地变更,使用统一的缓存键和数据结构。
 
 ### 2.5 服务层
 
-- **LandTempService**: 土地临时数据服务类,提供土地临时数据相关的服务方法,用于外部调用。
+- **LandTempService**: 土地临时数据服务类,提供土地临时数据相关的服务方法,用于外部调用。提供统一的接口和便捷的过滤方法。
 
 ## 3. 工作流程
 
@@ -49,38 +59,51 @@
 
 ## 4. 暂存数据结构
 
-### 4.1 土地变更临时数据 (LandChangeTempDto)
+### 4.1 统一的土地变更临时数据 (LandChangeTempDto)
 
 ```php
 class LandChangeTempDto
 {
-    public int $landId;         // 土地ID
-    public int $position;       // 土地位置
-    public int $oldType;        // 旧土地类型
-    public int $newType;        // 新土地类型
-    public int $updatedAt;      // 更新时间戳
+    public int $landId;           // 土地ID
+    public int $position;         // 土地位置
+    public int $landType;         // 土地类型
+    public ?int $oldType;         // 旧土地类型(仅在类型变更时有值)
+    public ?int $newType;         // 新土地类型(仅在类型变更时有值)
+    public ?int $oldStatus;       // 旧状态(仅在状态变更时有值)
+    public ?int $newStatus;       // 新状态(仅在状态变更时有值)
+    public ?int $cropId;          // 作物ID(如果有)
+    public ?int $seedId;          // 种子配置ID(如果有)
+    public string $changeType;    // 变更类型:'type'=类型变更,'status'=状态变更
+    public int $updatedAt;        // 更新时间戳
+
+    // 便捷方法
+    public function isTypeChange(): bool;    // 判断是否为类型变更
+    public function isStatusChange(): bool;  // 判断是否为状态变更
 }
 ```
 
-### 4.2 土地状态临时数据 (LandStatusTempDto)
+### 4.2 土地状态临时数据 (LandStatusTempDto) - 向后兼容
 
 ```php
-class LandStatusTempDto
+class LandStatusTempDto  // @deprecated 使用 LandChangeTempDto 替代
 {
     public int $landId;         // 土地ID
     public int $position;       // 土地位置
     public int $landType;       // 土地类型
     public int $oldStatus;      // 旧状态
     public int $newStatus;      // 新状态
-    public int $cropId;         // 作物ID(如果有)
+    public ?int $cropId;        // 作物ID(如果有)
+    public ?int $seedId;        // 种子配置ID(如果有)
     public int $updatedAt;      // 更新时间戳
 }
 ```
 
 ## 5. 暂存键和过期时间
 
-- **土地变更暂存键前缀**:`game:land:changed:`,后接用户ID,如 `game:land:changed:123`。
-- **土地状态变更暂存键前缀**:`game:land:status:`,后接用户ID,如 `game:land:status:123`。
+- **统一的土地变更暂存键前缀**:`game:land:changes:`,后接用户ID,如 `game:land:changes:123`。
+- **向后兼容的键前缀**:
+  - `game:land:changed:` (deprecated,现在指向统一键)
+  - `game:land:status:` (deprecated,现在指向统一键)
 - **暂存过期时间**:默认为3600秒(1小时)。
 
 ## 6. 使用示例
@@ -98,49 +121,70 @@ $event = new LandUpgradedEvent(
 Event::dispatch($event);
 ```
 
-### 6.2 获取用户的土地变更暂存数据
+### 6.2 获取用户的所有土地变更暂存数据(推荐)
+
+```php
+// 获取所有土地变更
+$allChanges = LandTempService::getUserLandChanges($userId);
+
+// 使用统一的DTO对象
+foreach ($allChanges as $landId => $change) {
+    if ($change->isTypeChange()) {
+        echo "土地ID: {$change->landId}, 类型从 {$change->oldType} 变更为 {$change->newType}\n";
+    } elseif ($change->isStatusChange()) {
+        echo "土地ID: {$change->landId}, 状态从 {$change->oldStatus} 变更为 {$change->newStatus}\n";
+    }
+}
+```
+
+### 6.3 获取特定类型的变更数据
 
 ```php
-$landTempService = new LandTempService();
-$landChanges = $landTempService->getUserLandChanges($userId);
+// 只获取类型变更
+$typeChanges = LandTempService::getUserTypeChanges($userId);
+foreach ($typeChanges as $change) {
+    echo "土地类型变更: {$change->oldType} -> {$change->newType}\n";
+}
 
-// 使用DTO对象的属性
-foreach ($landChanges as $landId => $changeDto) {
-    echo "土地ID: {$changeDto->landId}, 从类型 {$changeDto->oldType} 升级到 {$changeDto->newType}\n";
+// 只获取状态变更
+$statusChanges = LandTempService::getUserStatusChanges($userId);
+foreach ($statusChanges as $change) {
+    echo "土地状态变更: {$change->oldStatus} -> {$change->newStatus}\n";
 }
 ```
 
-### 6.3 获取用户特定土地的变更暂存数据
+### 6.4 获取用户特定土地的变更暂存数据
 
 ```php
-$landTempService = new LandTempService();
-$landChange = $landTempService->getUserLandChange($userId, $landId);
+$landChange = LandTempService::getUserLandChange($userId, $landId);
 
-// 判断土地是否存在
 if ($landChange !== null) {
-    $oldType = $landChange->oldType;
-    $newType = $landChange->newType;
-    $updatedAt = $landChange->updatedAt;
+    if ($landChange->isTypeChange()) {
+        echo "类型变更: {$landChange->oldType} -> {$landChange->newType}";
+    } elseif ($landChange->isStatusChange()) {
+        echo "状态变更: {$landChange->oldStatus} -> {$landChange->newStatus}";
+    }
 }
 ```
 
-### 6.4 获取用户的土地状态变更暂存数据
+### 6.5 向后兼容的使用方式(不推荐,但仍可用)
 
 ```php
-$landTempService = new LandTempService();
-$landStatusChanges = $landTempService->getUserLandStatusChanges($userId);
-
-// 使用DTO对象的属性
+// 这些方法仍然可用,但已标记为 deprecated
+$landStatusChanges = LandTempService::getUserLandStatusChanges($userId); // deprecated
 foreach ($landStatusChanges as $landId => $statusDto) {
     echo "土地ID: {$statusDto->landId}, 状态从 {$statusDto->oldStatus} 变为 {$statusDto->newStatus}\n";
 }
 ```
 
-### 6.5 清除用户的土地变更暂存数据
+### 6.6 清除用户的土地变更暂存数据
 
 ```php
-$landTempService = new LandTempService();
-$landTempService->clearUserLandChanges($userId);
+// 清除所有土地变更数据
+LandTempService::clearUserLandChanges($userId);
+
+// 或者清除所有临时数据
+LandTempService::clearUserAllLandTemp($userId);
 ```
 
 ## 7. 优势和应用场景
@@ -151,6 +195,10 @@ $landTempService->clearUserLandChanges($userId);
 - **提高用户体验**:前端可以实时获取土地变更信息,提供更好的用户反馈。
 - **优化性能**:使用临时存储机制存储数据,减轻了数据库负担,提高了系统性能。
 - **简化前端逻辑**:前端只需要获取暂存数据,无需自行计算土地变更。
+- **统一管理**:所有土地变更都在一个地方管理,简化了系统架构。
+- **减少重复代码**:消除了类型变更和状态变更的重复处理逻辑。
+- **易于扩展**:新增变更类型只需要添加 `changeType` 值,无需修改存储结构。
+- **向后兼容**:现有代码无需修改即可继续工作,平滑升级。
 
 ### 7.2 应用场景
 

+ 82 - 10
app/Module/Game/Dtos/LandChangeTempDto.php

@@ -7,7 +7,9 @@ use UCore\Dto\BaseDto;
 /**
  * 土地变更临时数据传输对象
  *
- * 用于存储和传输土地变更的临时数据
+ * 用于存储和传输所有类型的土地变更临时数据,包括:
+ * - 土地类型变更(创建、升级)
+ * - 土地状态变更(种植、收获等)
  */
 class LandChangeTempDto extends BaseDto
 {
@@ -26,18 +28,60 @@ class LandChangeTempDto extends BaseDto
     public int $position;
 
     /**
-     * 土地类型
+     * 土地类型
      *
      * @var int
      */
-    public int $oldType;
+    public int $landType;
 
     /**
-     * 新土地类型
+     * 旧土地类型(仅在类型变更时有值)
      *
-     * @var int
+     * @var int|null
+     */
+    public ?int $oldType = null;
+
+    /**
+     * 新土地类型(仅在类型变更时有值)
+     *
+     * @var int|null
      */
-    public int $newType;
+    public ?int $newType = null;
+
+    /**
+     * 旧状态(仅在状态变更时有值)
+     *
+     * @var int|null
+     */
+    public ?int $oldStatus = null;
+
+    /**
+     * 新状态(仅在状态变更时有值)
+     *
+     * @var int|null
+     */
+    public ?int $newStatus = null;
+
+    /**
+     * 作物ID(如果有)
+     *
+     * @var int|null
+     */
+    public ?int $cropId = null;
+
+    /**
+     * 种子配置ID(如果有)
+     *
+     * @var int|null
+     */
+    public ?int $seedId = null;
+
+    /**
+     * 变更类型:type=类型变更,status=状态变更
+     *
+     * @var string
+     */
+    public string $changeType;
 
     /**
      * 更新时间戳
@@ -64,8 +108,14 @@ class LandChangeTempDto extends BaseDto
                 $dto = new self();
                 $dto->landId = $data['land_id'] ?? $landId;
                 $dto->position = $data['position'] ?? 0;
-                $dto->oldType = $data['old_type'] ?? 0;
-                $dto->newType = $data['new_type'] ?? 0;
+                $dto->landType = $data['land_type'] ?? 0;
+                $dto->oldType = $data['old_type'] ?? null;
+                $dto->newType = $data['new_type'] ?? null;
+                $dto->oldStatus = $data['old_status'] ?? null;
+                $dto->newStatus = $data['new_status'] ?? null;
+                $dto->cropId = $data['crop_id'] ?? null;
+                $dto->seedId = $data['seed_id'] ?? null;
+                $dto->changeType = $data['change_type'] ?? 'type';
                 $dto->updatedAt = $data['updated_at'] ?? time();
                 $result[$landId] = $dto;
             } elseif ($data instanceof self) {
@@ -85,13 +135,35 @@ class LandChangeTempDto extends BaseDto
         return [
             'land_id' => $this->landId,
             'position' => $this->position,
+            'land_type' => $this->landType,
             'old_type' => $this->oldType,
             'new_type' => $this->newType,
+            'old_status' => $this->oldStatus,
+            'new_status' => $this->newStatus,
+            'crop_id' => $this->cropId,
+            'seed_id' => $this->seedId,
+            'change_type' => $this->changeType,
             'updated_at' => $this->updatedAt,
         ];
     }
 
+    /**
+     * 判断是否为类型变更
+     *
+     * @return bool
+     */
+    public function isTypeChange(): bool
+    {
+        return $this->changeType === 'type';
+    }
 
-
-
+    /**
+     * 判断是否为状态变更
+     *
+     * @return bool
+     */
+    public function isStatusChange(): bool
+    {
+        return $this->changeType === 'status';
+    }
 }

+ 106 - 57
app/Module/Game/Logics/LandTemp.php

@@ -20,24 +20,55 @@ use UCore\Helper\Cache;
  * 3. 将土地状态变更数据临时存储
  * 4. 按照用户进行存储
  * 5. 同一土地多次变更进行数据覆盖
+ * 6. 统一处理所有类型的土地变更,不再区分类型变更和状态变更
  */
 class LandTemp
 {
     /**
-     * 临时数据键前缀 - 土地变更
+     * 临时数据键前缀 - 统一的土地变更
      */
-    const TEMP_KEY_CHANGED_PREFIX = 'game:land:changed:';
+    const TEMP_KEY_PREFIX = 'game:land:changes:';
 
     /**
-     * 临时数据键前缀 - 土地状态变更
+     * 临时数据键前缀 - 土地变更(向后兼容)
+     * @deprecated 使用 TEMP_KEY_PREFIX 替代
      */
-    const TEMP_KEY_STATUS_PREFIX = 'game:land:status:';
+    const TEMP_KEY_CHANGED_PREFIX = 'game:land:changes:';
+
+    /**
+     * 临时数据键前缀 - 土地状态变更(向后兼容)
+     * @deprecated 使用 TEMP_KEY_PREFIX 替代
+     */
+    const TEMP_KEY_STATUS_PREFIX = 'game:land:changes:';
 
     /**
      * 临时数据过期时间(秒)
      */
     const TEMP_TTL = 3600; // 1小时
 
+    /**
+     * 统一存储土地变更数据
+     *
+     * @param int $userId 用户ID
+     * @param int $landId 土地ID
+     * @param array $landData 土地变更数据
+     * @return void
+     */
+    private static function storeLandChange(int $userId, int $landId, array $landData): void
+    {
+        // 构建统一的临时数据键
+        $tempKey = self::TEMP_KEY_PREFIX . $userId;
+
+        // 获取当前用户的土地变更临时数据
+        $userLandsTemp = Cache::get($tempKey, []);
+
+        // 使用土地ID作为键,实现同一土地多次变更的数据覆盖
+        $userLandsTemp[$landId] = $landData;
+
+        // 将更新后的数据存回临时存储
+        Cache::put($tempKey, $userLandsTemp, self::TEMP_TTL);
+    }
+
     /**
      * 处理土地创建事件
      *
@@ -57,26 +88,23 @@ class LandTemp
                 return;
             }
 
-            // 构建临时数据键,按用户ID进行存储
-            $tempKey = self::TEMP_KEY_CHANGED_PREFIX . $event->userId;
-
-            // 获取当前用户的土地变更临时数据
-            $userLandsTemp = Cache::get($tempKey, []);
-
-            // 构建土地变更数据
+            // 构建统一的土地变更数据
             $landData = [
                 'land_id' => $event->landId,
                 'position' => $land->position,
+                'land_type' => $land->landType,
                 'old_type' => 0, // 新创建的土地,旧类型为0
                 'new_type' => $land->landType,
+                'old_status' => null,
+                'new_status' => null,
+                'crop_id' => null,
+                'seed_id' => null,
+                'change_type' => 'type',
                 'updated_at' => time(),
             ];
 
-            // 使用土地ID作为键,实现同一土地多次变更的数据覆盖
-            $userLandsTemp[$event->landId] = $landData;
-
-            // 将更新后的数据存回临时存储
-            Cache::put($tempKey, $userLandsTemp, self::TEMP_TTL);
+            // 存储到统一的土地变更缓存
+            self::storeLandChange($event->userId, $event->landId, $landData);
 
             Log::info('土地创建数据已临时存储', [
                 'user_id' => $event->userId,
@@ -112,26 +140,23 @@ class LandTemp
                 return;
             }
 
-            // 构建临时数据键,按用户ID进行存储
-            $tempKey = self::TEMP_KEY_CHANGED_PREFIX . $event->userId;
-
-            // 获取当前用户的土地变更临时数据
-            $userLandsTemp = Cache::get($tempKey, []);
-
-            // 构建土地变更数据
+            // 构建统一的土地变更数据
             $landData = [
                 'land_id' => $land->id,
                 'position' => $land->position,
+                'land_type' => $land->landType,
                 'old_type' => $event->oldType,
                 'new_type' => $event->newType,
+                'old_status' => null,
+                'new_status' => null,
+                'crop_id' => null,
+                'seed_id' => null,
+                'change_type' => 'type',
                 'updated_at' => time(),
             ];
 
-            // 使用土地ID作为键,实现同一土地多次变更的数据覆盖
-            $userLandsTemp[$land->id] = $landData;
-
-            // 将更新后的数据存回临时存储
-            Cache::put($tempKey, $userLandsTemp, self::TEMP_TTL);
+            // 存储到统一的土地变更缓存
+            self::storeLandChange($event->userId, $land->id, $landData);
 
             Log::info('土地升级数据已临时存储', [
                 'user_id' => $event->userId,
@@ -145,7 +170,7 @@ class LandTemp
                 'user_id' => $event->userId,
                 'land_id' => $event->land->id ?? 'unknown',
             ]);
-        } 
+        }
     }
 
     /**
@@ -167,12 +192,6 @@ class LandTemp
                 return;
             }
 
-            // 构建临时数据键,按用户ID进行存储
-            $tempKey = self::TEMP_KEY_STATUS_PREFIX . $event->userId;
-
-            // 获取当前用户的土地状态变更临时数据
-            $userLandsStatusTemp = Cache::get($tempKey, []);
-
             // 获取土地上的作物ID和种子ID(如果有)
             $cropId = null;
             $seedId = null;
@@ -181,23 +200,23 @@ class LandTemp
                 $seedId = $land->crop->seedId; // 获取种子配置ID
             }
 
-            // 构建土地状态变更数据
-            $statusData = [
+            // 构建统一的土地变更数据
+            $landData = [
                 'land_id' => $event->landId,
                 'position' => $land->position,
                 'land_type' => $land->landType,
+                'old_type' => null,
+                'new_type' => null,
                 'old_status' => $event->oldStatus,
                 'new_status' => $event->newStatus,
                 'crop_id' => $cropId,
                 'seed_id' => $seedId, // 添加种子配置ID
+                'change_type' => 'status',
                 'updated_at' => time(),
             ];
 
-            // 使用土地ID作为键,实现同一土地多次变更的数据覆盖
-            $userLandsStatusTemp[$event->landId] = $statusData;
-
-            // 将更新后的数据存回临时存储
-            Cache::put($tempKey, $userLandsStatusTemp, self::TEMP_TTL);
+            // 存储到统一的土地变更缓存
+            self::storeLandChange($event->userId, $event->landId, $landData);
 
             Log::info('土地状态变更数据已临时存储', [
                 'user_id' => $event->userId,
@@ -215,14 +234,14 @@ class LandTemp
     }
 
     /**
-     * 获取用户的土地变更临时数据
+     * 获取用户的所有土地变更临时数据(统一接口)
      *
      * @param int $userId 用户ID
      * @return array|LandChangeTempDto[] 用户的土地变更数据
      */
     public static function getUserLandChanges(int $userId): array
     {
-        $tempKey = self::TEMP_KEY_CHANGED_PREFIX . $userId;
+        $tempKey = self::TEMP_KEY_PREFIX . $userId;
         $cachedData = Cache::get($tempKey, []);
 
         return LandChangeTempDto::fromCache($cachedData);
@@ -242,54 +261,85 @@ class LandTemp
     }
 
     /**
-     * 获取用户的土地状态变更临时数据
+     * 获取用户的土地状态变更临时数据(向后兼容)
      *
      * @param int $userId 用户ID
      * @return array 用户的土地状态变更数据
+     * @deprecated 使用 getUserLandChanges() 替代,然后过滤 changeType === 'status'
      */
     public static function getUserLandStatusChanges(int $userId): array
     {
-        $tempKey = self::TEMP_KEY_STATUS_PREFIX . $userId;
-        $cachedData = Cache::get($tempKey, []);
+        $allChanges = self::getUserLandChanges($userId);
+        $statusChanges = [];
+
+        foreach ($allChanges as $landId => $change) {
+            if ($change->isStatusChange()) {
+                // 为了向后兼容,转换为LandStatusTempDto格式
+                $statusChanges[$landId] = new LandStatusTempDto([
+                    'landId' => $change->landId,
+                    'position' => $change->position,
+                    'landType' => $change->landType,
+                    'oldStatus' => $change->oldStatus,
+                    'newStatus' => $change->newStatus,
+                    'cropId' => $change->cropId,
+                    'seedId' => $change->seedId,
+                    'updatedAt' => $change->updatedAt,
+                ]);
+            }
+        }
 
-        return LandStatusTempDto::fromCache($cachedData);
+        return $statusChanges;
     }
 
     /**
-     * 获取用户特定土地的状态变更临时数据
+     * 获取用户特定土地的状态变更临时数据(向后兼容)
      *
      * @param int $userId 用户ID
      * @param int $landId 土地ID
      * @return LandStatusTempDto|null 土地状态变更数据,不存在时返回null
+     * @deprecated 使用 getUserLandChange() 替代,然后检查 isStatusChange()
      */
     public static function getUserLandStatusChange(int $userId, int $landId): ?LandStatusTempDto
     {
-        $userLandStatusChanges = self::getUserLandStatusChanges($userId);
-        return $userLandStatusChanges[$landId] ?? null;
+        $change = self::getUserLandChange($userId, $landId);
+        if ($change && $change->isStatusChange()) {
+            return new LandStatusTempDto([
+                'landId' => $change->landId,
+                'position' => $change->position,
+                'landType' => $change->landType,
+                'oldStatus' => $change->oldStatus,
+                'newStatus' => $change->newStatus,
+                'cropId' => $change->cropId,
+                'seedId' => $change->seedId,
+                'updatedAt' => $change->updatedAt,
+            ]);
+        }
+        return null;
     }
 
     /**
-     * 清除用户的土地变更临时数据
+     * 清除用户的所有土地变更临时数据(统一接口)
      *
      * @param int $userId 用户ID
      * @return void
      */
     public static function clearUserLandChanges(int $userId): void
     {
-        $tempKey = self::TEMP_KEY_CHANGED_PREFIX . $userId;
+        $tempKey = self::TEMP_KEY_PREFIX . $userId;
         Cache::put($tempKey, [], 0);
     }
 
     /**
-     * 清除用户的土地状态变更临时数据
+     * 清除用户的土地状态变更临时数据(向后兼容)
      *
      * @param int $userId 用户ID
      * @return void
+     * @deprecated 使用 clearUserLandChanges() 替代
      */
     public static function clearUserLandStatusChanges(int $userId): void
     {
-        $tempKey = self::TEMP_KEY_STATUS_PREFIX . $userId;
-        Cache::put($tempKey, [], 0);
+        // 现在统一存储,所以清除所有数据
+        self::clearUserLandChanges($userId);
     }
 
     /**
@@ -301,6 +351,5 @@ class LandTemp
     public static function clearUserAllLandTemp(int $userId): void
     {
         self::clearUserLandChanges($userId);
-        self::clearUserLandStatusChanges($userId);
     }
 }

+ 37 - 5
app/Module/Game/Services/LandTempService.php

@@ -10,11 +10,12 @@ use App\Module\Game\Logics\LandTemp;
  * 土地临时数据服务类
  *
  * 提供土地临时数据相关的服务方法,用于外部调用
+ * 统一处理所有类型的土地变更,不再区分类型变更和状态变更
  */
 class LandTempService
 {
     /**
-     * 获取用户的土地变更临时数据
+     * 获取用户的所有土地变更临时数据(统一接口)
      *
      * @param int $userId 用户ID
      * @return array 用户的土地变更数据,键为土地ID,值为LandChangeTempDto对象
@@ -37,10 +38,39 @@ class LandTempService
     }
 
     /**
-     * 获取用户的土地状态变更临时数据
+     * 获取用户的类型变更数据
+     *
+     * @param int $userId 用户ID
+     * @return array 过滤后的类型变更数据
+     */
+    public static function getUserTypeChanges(int $userId): array
+    {
+        $allChanges = self::getUserLandChanges($userId);
+        return array_filter($allChanges, function($change) {
+            return $change->isTypeChange();
+        });
+    }
+
+    /**
+     * 获取用户的状态变更数据
+     *
+     * @param int $userId 用户ID
+     * @return array 过滤后的状态变更数据
+     */
+    public static function getUserStatusChanges(int $userId): array
+    {
+        $allChanges = self::getUserLandChanges($userId);
+        return array_filter($allChanges, function($change) {
+            return $change->isStatusChange();
+        });
+    }
+
+    /**
+     * 获取用户的土地状态变更临时数据(向后兼容)
      *
      * @param int $userId 用户ID
      * @return array 用户的土地状态变更数据,键为土地ID,值为LandStatusTempDto对象
+     * @deprecated 使用 getUserStatusChanges() 替代
      */
     public static function getUserLandStatusChanges(int $userId): array
     {
@@ -48,11 +78,12 @@ class LandTempService
     }
 
     /**
-     * 获取用户特定土地的状态变更临时数据
+     * 获取用户特定土地的状态变更临时数据(向后兼容)
      *
      * @param int $userId 用户ID
      * @param int $landId 土地ID
      * @return LandStatusTempDto|null 土地状态变更数据,不存在时返回null
+     * @deprecated 使用 getUserLandChange() 替代,然后检查 isStatusChange()
      */
     public static function getUserLandStatusChange(int $userId, int $landId): ?LandStatusTempDto
     {
@@ -60,7 +91,7 @@ class LandTempService
     }
 
     /**
-     * 清除用户的土地变更临时数据
+     * 清除用户的所有土地变更临时数据(统一接口)
      *
      * @param int $userId 用户ID
      * @return void
@@ -71,10 +102,11 @@ class LandTempService
     }
 
     /**
-     * 清除用户的土地状态变更临时数据
+     * 清除用户的土地状态变更临时数据(向后兼容)
      *
      * @param int $userId 用户ID
      * @return void
+     * @deprecated 使用 clearUserLandChanges() 替代
      */
     public static function clearUserLandStatusChanges(int $userId): void
     {