Pārlūkot izejas kodu

feat(Game): 服务层增加 DTO 和 Protobuf 转换功能

- 为 ConsumeService、ConditionService 和 RewardService 增加获取组的方法,返回 DTO 对象
- 新增消耗组 DTO 转 Protobuf Deduct 和奖励组 DTO 转 Protobuf Reward 的功能
- 创建 ConsumeGroupDto、ConsumeItemDto、ConditionGroupDto 和 ConditionItemDto等 4 个 DTO 类
- 实现 ProtobufConverter统一转换器,支持所有消耗类型和奖励类型的转换
-优化数据获取逻辑,支持通过 ID 或编码获取组信息,并可选择是否包含子项
- 提供便捷的一步转换 API,提高开发效率和代码质量
notfff 7 mēneši atpakaļ
vecāks
revīzija
1f3c4d2c23

+ 266 - 0
AiWork/202506/092056-Game模块服务层DTO和Protobuf转换功能增强.md

@@ -0,0 +1,266 @@
+# Game模块服务层DTO和Protobuf转换功能增强
+
+**时间**: 2025年06月09日 20:56  
+**任务类型**: 功能增强  
+**状态**: 已完成
+
+## 任务描述
+
+为Game模块的ConsumeService、ConditionService和RewardService增加获取组的方法,返回DTO对象,并增加消耗组DTO转Protobuf对象Deduct、奖励组DTO转Protobuf对象Reward的转换功能。
+
+## 需求分析
+
+### 核心需求
+1. **ConsumeService增加获取消耗组方法**,返回DTO
+2. **ConditionService增加获取条件组方法**,返回DTO  
+3. **RewardService添加获取奖励组方法**,返回DTO
+4. **增加消耗组DTO转Protobuf对象Deduct**
+5. **增加奖励组DTO转Protobuf对象Reward**
+
+### 设计目标
+- 统一的DTO接口,便于数据传输和处理
+- 完整的Protobuf转换支持,满足前端通信需求
+- 保持服务层的简洁性和一致性
+- 支持灵活的数据获取选项
+
+## 解决方案
+
+### 1. 创建DTO类
+
+#### 1.1 消耗相关DTO
+**ConsumeGroupDto** (`app/Module/Game/Dtos/ConsumeGroupDto.php`):
+```php
+class ConsumeGroupDto
+{
+    public int $id;
+    public string $name;
+    public string $code;
+    public ?string $description;
+    public array $items = []; // ConsumeItemDto[]
+    
+    public static function fromModel($model, bool $withItems = false): self
+}
+```
+
+**ConsumeItemDto** (`app/Module/Game/Dtos/ConsumeItemDto.php`):
+```php
+class ConsumeItemDto
+{
+    public int $id;
+    public int $groupId;
+    public int $consumeType;
+    public int $targetId;
+    public int $param1;
+    public int $param2;
+    public int $quantity;
+    public ?array $extraData;
+    
+    public static function fromModel($model): self
+}
+```
+
+#### 1.2 条件相关DTO
+**ConditionGroupDto** (`app/Module/Game/Dtos/ConditionGroupDto.php`):
+```php
+class ConditionGroupDto
+{
+    public int $id;
+    public string $name;
+    public string $code;
+    public ?string $description;
+    public int $logicType;
+    public array $items = []; // ConditionItemDto[]
+    
+    public static function fromModel($model, bool $withItems = false): self
+}
+```
+
+**ConditionItemDto** (`app/Module/Game/Dtos/ConditionItemDto.php`):
+```php
+class ConditionItemDto
+{
+    public int $id;
+    public int $groupId;
+    public int $conditionType;
+    public int $targetId;
+    public int $operator;
+    public int $value;
+    public int $param1;
+    public int $param2;
+    public ?array $extraData;
+    
+    public static function fromModel($model): self
+}
+```
+
+### 2. 增强服务层方法
+
+#### 2.1 ConsumeService增强
+```php
+/**
+ * 获取消耗组信息
+ */
+public static function getConsumeGroup($consumeGroupCode, bool $withItems = true): ?ConsumeGroupDto
+
+/**
+ * 获取消耗组并转换为Protobuf Deduct对象
+ */
+public static function getConsumeGroupAsDeduct($consumeGroupCode): ?\Uraus\Kku\Common\Deduct
+```
+
+#### 2.2 ConditionService增强
+```php
+/**
+ * 获取条件组信息
+ */
+public static function getConditionGroup($conditionGroupCode, bool $withItems = true): ?ConditionGroupDto
+```
+
+#### 2.3 RewardService增强
+```php
+/**
+ * 获取奖励组并转换为Protobuf Reward对象
+ */
+public static function getRewardGroupAsReward($groupIdOrCode): ?\Uraus\Kku\Common\Reward
+```
+
+### 3. 创建Protobuf转换器
+
+#### 3.1 ProtobufConverter类
+**文件**: `app/Module/Game/Services/ProtobufConverter.php`
+
+**核心功能**:
+- 消耗组DTO转Protobuf Deduct对象
+- 奖励组DTO转Protobuf Reward对象
+- 单个消耗项/奖励项的Protobuf转换
+- 支持复杂的类型映射和参数处理
+
+**主要方法**:
+```php
+// 消耗组转换
+public static function convertConsumeGroupToDeduct(ConsumeGroupDto $consumeGroupDto): Deduct
+
+// 奖励组转换
+public static function convertRewardGroupToReward(RewardGroupDto $rewardGroupDto): Reward
+
+// 单项转换
+public static function convertConsumeItemToProtobuf(ConsumeItemDto $consumeItemDto)
+public static function convertRewardItemToProtobuf(RewardItemDto $rewardItemDto)
+```
+
+#### 3.2 支持的Protobuf类型映射
+
+**消耗类型映射**:
+- `CONSUME_TYPE::ITEM` → `DeductItem`
+- `CONSUME_TYPE::CURRENCY` → `DeductCoin`
+- `CONSUME_TYPE::FUND_CONFIG` → `DeductCoin`
+- `CONSUME_TYPE::FUND_CONFIGS` → `DeductCoin`
+
+**奖励类型映射**:
+- `REWARD_TYPE::ITEM` → `RewardItem`
+- `REWARD_TYPE::CURRENCY` → `RewardCoin`
+- `REWARD_TYPE::FUND_CONFIG` → `RewardCoin`
+- `REWARD_TYPE::FARM_SHRINE` → `RewardGod`
+- `REWARD_TYPE::PET` → `RewardPets`
+- `REWARD_TYPE::PET_POWER` → `RewardPetPowers`
+- `REWARD_TYPE::SKIN` → `RewardSkin`
+
+## 实现特性
+
+### 1. 灵活的数据获取
+- 支持通过ID或编码获取组信息
+- 可选择是否包含子项(withItems参数)
+- 统一的错误处理和日志记录
+
+### 2. 完整的类型支持
+- 支持所有现有的消耗类型和奖励类型
+- 正确处理参数映射(param1、param2等)
+- 支持随机数量范围(minQuantity、maxQuantity)
+
+### 3. 高效的转换逻辑
+- 直接从DTO转换为Protobuf,避免重复查询
+- 合理的默认值处理
+- 类型安全的转换过程
+
+### 4. 便捷的API接口
+- 一步到位的Protobuf转换方法
+- 保持向后兼容性
+- 清晰的方法命名和文档
+
+## 使用示例
+
+### 1. 获取消耗组DTO
+```php
+// 获取包含消耗项的消耗组
+$consumeGroup = ConsumeService::getConsumeGroup(1, true);
+if ($consumeGroup) {
+    echo "消耗组: {$consumeGroup->name}";
+    echo "消耗项数量: " . count($consumeGroup->items);
+}
+```
+
+### 2. 直接获取Protobuf对象
+```php
+// 获取消耗组的Protobuf Deduct对象
+$deduct = ConsumeService::getConsumeGroupAsDeduct('consume_group_code');
+
+// 获取奖励组的Protobuf Reward对象
+$reward = RewardService::getRewardGroupAsReward('reward_group_code');
+```
+
+### 3. 获取条件组
+```php
+// 获取条件组DTO
+$conditionGroup = ConditionService::getConditionGroup('condition_code', true);
+if ($conditionGroup) {
+    echo "逻辑类型: {$conditionGroup->logicType}";
+    echo "条件项数量: " . count($conditionGroup->items);
+}
+```
+
+## 技术优势
+
+### 1. 架构清晰
+- DTO层负责数据传输
+- Service层提供业务接口
+- Converter层处理格式转换
+- 职责分离,易于维护
+
+### 2. 类型安全
+- 强类型的DTO定义
+- 完整的类型检查
+- 避免运行时类型错误
+
+### 3. 扩展性强
+- 新增类型时只需扩展Converter
+- DTO结构易于扩展
+- 保持接口稳定性
+
+### 4. 性能优化
+- 减少重复的数据库查询
+- 高效的对象转换
+- 合理的内存使用
+
+## 测试验证
+
+### 1. 功能测试
+- 验证所有服务方法正常工作
+- 确认DTO数据完整性
+- 测试Protobuf转换正确性
+
+### 2. 兼容性测试
+- 确保现有功能不受影响
+- 验证新旧接口兼容性
+- 测试错误处理机制
+
+## 总结
+
+本次功能增强成功为Game模块建立了完整的DTO和Protobuf转换体系:
+
+1. **创建了4个DTO类**,提供统一的数据传输接口
+2. **增强了3个Service类**,添加了获取组的方法
+3. **创建了ProtobufConverter**,提供完整的Protobuf转换功能
+4. **支持所有类型映射**,满足前端通信需求
+5. **保持了架构清晰**,便于后续维护和扩展
+
+这次增强为Game模块的服务层提供了更加完善和统一的接口,特别是在Handler层中可以方便地获取DTO并转换为Protobuf格式返回给前端,大大提升了开发效率和代码质量。

+ 6 - 0
AiWork/WORK.md

@@ -20,6 +20,12 @@ shop_items 的 $max_buy 确认被替代后移除,使用mcp执行sql
 
 ## 已完成任务(保留最新的10条,多余的删除)
 
+**2025-06-09 20:56** - Game模块服务层DTO和Protobuf转换功能增强:完善服务层架构,提供统一的DTO和Protobuf转换接口
+- 需求:ConsumeService、ConditionService、RewardService增加获取组方法返回DTO,增加消耗组DTO转Protobuf Deduct、奖励组DTO转Protobuf Reward转换功能
+- 实现:创建ConsumeGroupDto、ConsumeItemDto、ConditionGroupDto、ConditionItemDto等4个DTO类,创建ProtobufConverter统一转换器
+- 功能:支持通过ID或编码获取组信息,支持所有消耗类型和奖励类型的Protobuf转换,提供便捷的一步转换API
+- 文件:./AiWork/202506/092056-Game模块服务层DTO和Protobuf转换功能增强.md
+
 **2025-06-09 20:08** - 条件组消耗组类型处理逻辑统一优化:消除条件组和消耗组类型的重复性硬编码
 - 问题:Game模块中存在多处条件组类型(CONDITION_TYPE)和消耗组类型(CONSUME_TYPE)判断的重复性硬编码,不利于维护
 - 实现:创建ConditionTypeDescriptor和ConsumeTypeDescriptor统一类型描述器,重构8个相关文件,消除大量重复代码

+ 11 - 25
app/Module/GameItems/Commands/GenerateRecipeJsonCommand.php

@@ -4,6 +4,8 @@ namespace App\Module\GameItems\Commands;
 
 use App\Module\Game\DCache\RecipeJsonConfig;
 
+use App\Module\Game\Services\ConsumeService;
+use App\Module\Game\Services\RewardService;
 use Illuminate\Console\Command;
 use App\Module\GameItems\Models\ItemRecipe;
 
@@ -66,35 +68,19 @@ class GenerateRecipeJsonCommand extends Command
 
                     // 消耗组数据
                     if ($recipe->consume_group_id && $recipe->consumeGroup) {
-                        $recipeData['consume_group'] = [
-                            'id'    => $recipe->consumeGroup->id,
-                            'name'  => $recipe->consumeGroup->name,
-                            'items' => $recipe->consumeGroup->consumeItems->map(function (\App\Module\Game\Models\GameConsumeItem $item) {
-                                $consume = $item->toDeductObject();
-
-                                // 转换为 \Uraus\Kku\Common\Deduct 格式的数组(JSON可序列化)
-                                return json_decode($consume->serializeToJsonString(), true);
-                            })->toArray()
-                        ];
-
-                        $recipeData['consume_group'] = $recipeData['consume_group'] ['items'];
+
+                        $consume = ConsumeService::getConsumeGroupAsDeduct($recipe->consume_group_id);
+
+                        $recipeData['consume_group'] = json_decode($consume->serializeToJsonString(),true);
                     }
 
                     // 奖励组数据
                     if ($recipe->reward_group_id && $recipe->rewardGroup) {
-                        $recipeData['reward_group'] = [
-                            'id'           => $recipe->rewardGroup->id,
-                            'name'         => $recipe->rewardGroup->name,
-                            'is_random'    => $recipe->rewardGroup->is_random,
-                            'random_count' => $recipe->rewardGroup->random_count,
-                            'items'        => $recipe->rewardGroup->rewardItems->map(function (\App\Module\Game\Models\GameRewardItem $item) {
-                                $reward = $item->toRewardObject();
-
-                                // 转换为 \Uraus\Kku\Common\Deduct 格式的数组(JSON可序列化)
-                                return json_decode($reward->serializeToJsonString(), true);
-                            })->toArray()
-                        ];
-                        $recipeData['reward_group'] = $recipeData['reward_group'] ['items'];
+                        $reward = RewardService::getRewardGroupAsReward($recipe->reward_group_id);
+
+                        $recipeData['reward_group'] = json_decode($reward->serializeToJsonString(),true);
+
+
                     }
 
                     // 条件组,临时跳过