option('dry-run'); $this->info('开始宝箱系统迁移...'); $this->info($isDryRun ? '预览模式(不会实际修改数据)' : '实际执行模式'); // 获取所有宝箱类型物品 $chests = Item::where('type', ITEM_TYPE::CHEST)->get(); if ($chests->isEmpty()) { $this->info('没有找到宝箱类型物品,迁移完成。'); return 0; } $this->info("找到 {$chests->count()} 个宝箱物品"); $migratedCount = 0; $skippedCount = 0; foreach ($chests as $chest) { $this->info("处理宝箱: {$chest->name} (ID: {$chest->id})"); try { if ($this->migrateChest($chest, $isDryRun)) { $migratedCount++; } else { $skippedCount++; } } catch (\Exception $e) { $this->error("迁移宝箱 {$chest->id} 失败: " . $e->getMessage()); Log::error('宝箱迁移失败', [ 'chest_id' => $chest->id, 'error' => $e->getMessage(), 'trace' => $e->getTraceAsString() ]); } } $this->info("迁移完成!"); $this->info("成功迁移: {$migratedCount} 个宝箱"); $this->info("跳过: {$skippedCount} 个宝箱"); return 0; } /** * 迁移单个宝箱 * * @param Item $chest * @param bool $isDryRun * @return bool */ private function migrateChest(Item $chest, bool $isDryRun): bool { // 检查是否已经配置了新系统 $existingConfig = ItemChestConfig::where('item_id', $chest->id)->first(); if ($existingConfig) { $this->warn(" 宝箱 {$chest->id} 已配置新系统,跳过"); return false; } if ($isDryRun) { $this->previewChestMigration($chest); return true; } DB::beginTransaction(); try { // 迁移消耗配置 $consumeGroupId = $this->migrateChestCosts($chest); // 迁移奖励配置 $rewardGroupId = $this->migrateChestContents($chest); // 创建新配置 ItemChestConfig::create([ 'item_id' => $chest->id, 'consume_group_id' => $consumeGroupId, 'reward_group_id' => $rewardGroupId, 'condition_group_id' => null, // 暂不支持条件组迁移 'is_active' => true, ]); DB::commit(); $this->info(" ✓ 宝箱 {$chest->id} 迁移成功"); return true; } catch (\Exception $e) { DB::rollBack(); throw $e; } } /** * 预览宝箱迁移 * * @param Item $chest */ private function previewChestMigration(Item $chest) { $this->info(" 预览宝箱 {$chest->id} 迁移:"); // 预览消耗配置 $costs = ItemChestOpenCost::where('chest_id', $chest->id)->where('is_active', true)->get(); if ($costs->isNotEmpty()) { $this->info(" 将创建消耗组: {$chest->name}_消耗组"); foreach ($costs as $cost) { $this->info(" - 消耗类型: {$cost->cost_type}, ID: {$cost->cost_id}, 数量: {$cost->cost_quantity}"); } } else { $this->info(" 无消耗配置,不创建消耗组"); } // 预览奖励配置 $contents = ItemChestContent::where('chest_id', $chest->id)->get(); if ($contents->isNotEmpty()) { $this->info(" 将创建奖励组: {$chest->name}_奖励组"); foreach ($contents as $content) { $type = $content->item_id ? "物品ID: {$content->item_id}" : "物品组ID: {$content->group_id}"; $this->info(" - {$type}, 数量: {$content->min_quantity}-{$content->max_quantity}, 权重: {$content->weight}"); } } else { $this->warn(" 无奖励配置,将创建空奖励组"); } } /** * 迁移宝箱消耗配置 * * @param Item $chest * @return int|null */ private function migrateChestCosts(Item $chest): ?int { $costs = ItemChestOpenCost::where('chest_id', $chest->id)->where('is_active', true)->get(); if ($costs->isEmpty()) { return null; } // 创建消耗组 $consumeGroup = GameConsumeGroup::create([ 'name' => $chest->name . '_消耗组', 'code' => 'chest_' . $chest->id . '_consume_' . time(), 'description' => "宝箱 {$chest->name} 的开启消耗配置(从旧系统迁移)", ]); // 创建消耗项 foreach ($costs as $cost) { GameConsumeItem::create([ 'group_id' => $consumeGroup->id, 'consume_type' => $cost->cost_type, 'target_id' => $cost->cost_id, 'quantity' => $cost->cost_quantity, ]); } return $consumeGroup->id; } /** * 迁移宝箱内容配置 * * @param Item $chest * @return int */ private function migrateChestContents(Item $chest): int { $contents = ItemChestContent::where('chest_id', $chest->id)->get(); // 创建奖励组 $rewardGroup = GameRewardGroup::create([ 'name' => $chest->name . '_奖励组', 'code' => 'chest_' . $chest->id . '_reward_' . time(), 'description' => "宝箱 {$chest->name} 的奖励配置(从旧系统迁移)", 'is_random' => true, 'random_count' => ($chest->numeric_attributes && $chest->numeric_attributes->max_drop_count > 0) ? $chest->numeric_attributes->max_drop_count : 1, 'reward_mode' => 1, // 权重选择模式 ]); // 创建奖励项 foreach ($contents as $content) { if ($content->item_id) { // 直接物品奖励 GameRewardItem::create([ 'group_id' => $rewardGroup->id, 'reward_type' => 1, // 物品类型 'target_id' => $content->item_id, 'quantity' => $content->max_quantity, // 使用最大数量 'weight' => $content->weight, 'is_guaranteed' => false, ]); } elseif ($content->group_id) { // 物品组奖励 - 需要展开为具体物品 $this->expandGroupToRewardItems($rewardGroup->id, $content); } } return $rewardGroup->id; } /** * 展开物品组为具体奖励项 * * @param int $rewardGroupId * @param ItemChestContent $content */ private function expandGroupToRewardItems(int $rewardGroupId, ItemChestContent $content) { $groupItems = \App\Module\GameItems\Models\ItemGroupItem::where('group_id', $content->group_id)->get(); foreach ($groupItems as $groupItem) { GameRewardItem::create([ 'group_id' => $rewardGroupId, 'reward_type' => 1, // 物品类型 'target_id' => $groupItem->item_id, 'quantity' => $content->max_quantity, 'weight' => $content->weight * $groupItem->weight, // 组合权重 'is_guaranteed' => false, ]); } } }