土地升级消耗组迁移.md 6.0 KB

土地升级消耗组迁移

最后更新时间:2024年5月

1. 概述

为了提高系统的灵活性和可维护性,我们将 FarmLandUpgradeConfig 模型中的 materials JSON 字段改为关联 Game 模块中的消耗组(GameConsumeGroup)。这样做的好处是:

  1. 统一了消耗管理,可以在一个地方管理所有类型的消耗
  2. 支持更复杂的消耗组合,如同时消耗物品和货币
  3. 提高了代码的可维护性和可扩展性

2. 数据库变更

farm_land_upgrade_configs 表中添加了 consume_group_id 字段,用于关联 game_consume_groups 表:

ALTER TABLE `kku_farm_land_upgrade_configs` 
ADD COLUMN `consume_group_id` int(10) unsigned DEFAULT NULL COMMENT '消耗组ID,关联game_consume_groups表' AFTER `to_type_id`,
ADD INDEX `idx_consume_group_id` (`consume_group_id`);

3. 代码变更

3.1 模型变更

FarmLandUpgradeConfig 模型中添加了与消耗组的关联:

/**
 * 获取关联的消耗组
 *
 * @return BelongsTo
 */
public function consumeGroup(): BelongsTo
{
    return $this->belongsTo(GameConsumeGroup::class, 'consume_group_id', 'id');
}

同时,添加了 getUpgradeMaterials 方法,用于获取升级所需材料:

/**
 * 获取升级所需材料
 * 
 * 兼容旧版本,优先使用消耗组,如果没有则使用 materials 字段
 *
 * @return array
 */
public function getUpgradeMaterials(): array
{
    // 如果有关联的消耗组,则使用消耗组中的消耗项
    if ($this->consume_group_id && $this->consumeGroup) {
        $consumeItems = $this->consumeGroup->consumeItems;
        $materials = [];
        
        foreach ($consumeItems as $item) {
            if ($item->consume_type == \App\Module\Game\Enums\CONSUME_TYPE::ITEM->value) {
                $materials[] = [
                    'item_id' => $item->target_id,
                    'amount' => $item->quantity
                ];
            }
        }
        
        return $materials;
    }
    
    // 否则使用 materials 字段
    if (is_string($this->materials)) {
        return json_decode($this->materials, true)['materials'] ?? [];
    }
    
    return $this->materials['materials'] ?? [];
}

3.2 逻辑层变更

LandLogic 类中添加了 getUpgradeMaterials 方法,用于获取升级所需材料:

/**
 * 获取升级所需材料
 *
 * @param int $currentType 当前土地类型
 * @param int $targetType 目标土地类型
 * @return array 升级所需材料
 */
public function getUpgradeMaterials(int $currentType, int $targetType): array
{
    try {
        // 从数据库中获取升级配置
        $upgradeConfig = FarmLandUpgradeConfig::where('from_type_id', $currentType)
            ->where('to_type_id', $targetType)
            ->first();

        if (!$upgradeConfig) {
            return [];
        }

        // 使用模型的 getUpgradeMaterials 方法获取材料
        return $upgradeConfig->getUpgradeMaterials();
    } catch (\Exception $e) {
        Log::error('获取升级所需材料失败', [
            'current_type' => $currentType,
            'target_type' => $targetType,
            'error' => $e->getMessage(),
            'trace' => $e->getTraceAsString()
        ]);

        return [];
    }
}

同时,修改了 getAvailableUpgradePaths 方法,使用 getUpgradeMaterials 方法获取材料:

// 格式化返回结果
return $availablePaths->map(function ($path) {
    // 获取升级所需材料
    $materials = $path->getUpgradeMaterials();
    
    return [
        'from_type_id' => $path->from_type_id,
        'to_type_id' => $path->to_type_id,
        'to_type_name' => $path->toType->name,
        'materials' => ['materials' => $materials], // 保持与旧版本兼容的格式
        'conditions' => $path->conditions,
        'consume_group_id' => $path->consume_group_id,
    ];
})->values()->toArray();

3.3 控制器变更

FarmLandUpgradeConfigController 类中添加了消耗组选择字段:

// 添加消耗组选择
$form->select('consume_group_id', '消耗组')
    ->options(function () {
        return GameConsumeGroup::pluck('name', 'id')->toArray();
    })
    ->help('选择消耗组后,将使用消耗组中的消耗项作为升级所需材料,而不使用 materials 字段');

4. 数据迁移

为了将现有的 materials 字段数据转换为消耗组,我们创建了一个迁移命令:

php artisan farm:migrate-land-upgrade-materials [--dry-run]

该命令会执行以下操作:

  1. 获取所有土地升级配置
  2. 对于每个配置,如果没有关联的消耗组,则创建一个新的消耗组
  3. materials 字段中的物品添加到消耗组中
  4. 更新土地升级配置,设置 consume_group_id 字段

使用 --dry-run 参数可以查看将要执行的操作,而不实际执行。

5. 使用方法

5.1 创建消耗组

  1. 在后台管理界面中,进入"消耗组管理"页面
  2. 点击"新增"按钮,填写消耗组的名称、编码和描述,然后保存
  3. 在消耗组详情页面,可以查看和管理该消耗组下的消耗项

5.2 添加消耗项

  1. 在后台管理界面中,进入"消耗项管理"页面
  2. 点击"新增"按钮,选择所属的消耗组,填写消耗类型、目标ID、数量等信息,然后保存
  3. 根据不同的消耗类型,填写相应的参数和额外数据

5.3 关联消耗组

  1. 在后台管理界面中,进入"土地升级配置管理"页面
  2. 编辑土地升级配置,选择对应的消耗组,然后保存
  3. 如果没有选择消耗组,系统会继续使用 materials 字段

6. 注意事项

  1. 为了保持向后兼容性,系统会优先使用消耗组,如果没有关联的消耗组,则使用 materials 字段
  2. 在迁移过程中,只会将 materials 字段中的物品添加到消耗组中,不会处理其他类型的消耗
  3. 建议在迁移前先使用 --dry-run 参数查看将要执行的操作,确保没有问题后再执行实际迁移