swagger_generator_flutter/ENUM_KEY_NAMES_PROPOSAL.md

8.5 KiB
Raw Blame History

枚举键名生成优化方案

问题描述

当前生成的枚举使用通用的键名(value1, value2, value3...),不够语义化。

当前生成结果

enum SysTaskTypeEnums {
  value1(1),   // 实际应该是 SPOT_CHECK (抽查)
  value2(2),   // 实际应该是 CULTURAL (文创建设)
  value3(3),   // 实际应该是 CLASS_CADRE_MEETING (班干部会议)
  ...
}

期望结果

enum SysTaskTypeEnums {
  /// 抽查
  SPOT_CHECK(1),
  
  /// 文创建设
  CULTURAL(2),
  
  /// 班干部会议
  CLASS_CADRE_MEETING(3),
  
  /// 学生谈话
  STUDENT_TALK(4),
  ...
}

根本原因

Swagger 文档中的枚举定义只包含值numbers没有提供键名映射

{
  "SysTaskTypeEnums": {
    "enum": [1, 2, 3, 4, 5, ...],
    "type": "integer",
    "description": "任务类型枚举"
  }
}

解决方案

方案 1: 使用 OpenAPI 扩展字段 (推荐)

在 Swagger 文档中添加 x-enum-varnamesx-enum-descriptions 扩展字段:

{
  "SysTaskTypeEnums": {
    "enum": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13],
    "type": "integer",
    "description": "任务类型枚举",
    "format": "int32",
    "x-enum-varnames": [
      "SPOT_CHECK",
      "CULTURAL",
      "CLASS_CADRE_MEETING",
      "STUDENT_TALK",
      "FOLLOW_CLASS",
      "TEACHER_BEHAVIOR_OBSERVATION",
      "MEETING",
      "COACH_SUBJECT",
      "DATA_COLLECTION",
      "CLASS_MEETING",
      "TEACHER_TALK",
      "OTHER_WORK",
      "CLASS_ACTIVITY"
    ],
    "x-enum-descriptions": [
      "抽查",
      "文创建设",
      "班干部会议",
      "学生谈话",
      "双师跟课",
      "教师行为观察",
      "参加会议",
      "学科辅助",
      "数据采集",
      "召开班会",
      "教师谈话",
      "其他工作",
      "班级活动"
    ]
  }
}

优点:

  • 标准的 OpenAPI 扩展方式
  • 枚举定义和键名在同一处
  • 易于维护

缺点:

  • ⚠️ 需要修改后端 Swagger 文档
  • ⚠️ 需要后端配合

方案 2: 配置文件映射

generator_config.yaml 中添加枚举键名映射:

# generator_config.yaml

generation:
  models:
    # 枚举键名映射配置
    enum_key_mappings:
      SysTaskTypeEnums:
        1:
          name: SPOT_CHECK
          description: 抽查
        2:
          name: CULTURAL
          description: 文创建设
        3:
          name: CLASS_CADRE_MEETING
          description: 班干部会议
        4:
          name: STUDENT_TALK
          description: 学生谈话
        5:
          name: FOLLOW_CLASS
          description: 双师跟课
        # ... 其他映射

      SysRoleEnum:
        1:
          name: ADMIN
          description: 管理员
        2:
          name: USER
          description: 普通用户
        # ... 其他映射

优点:

  • 不需要修改后端
  • 灵活配置
  • 支持批量管理

缺点:

  • ⚠️ 配置文件可能很大
  • ⚠️ 需要手动维护映射

方案 3: 智能命名策略(备选)

如果 Swagger 文档中枚举的 description 字段包含中文说明,可以尝试智能转换:

"抽查" -> SPOT_CHECK (通过翻译API或预定义映射)
"文创建设" -> CULTURAL
"班干部会议" -> CLASS_CADRE_MEETING

优点:

  • 自动化程度高
  • 不需要额外配置

缺点:

  • ⚠️ 翻译质量不稳定
  • ⚠️ 需要外部服务或大量预定义映射

推荐实施方案

阶段 1: 支持 OpenAPI 扩展字段(立即实施)

修改枚举解析逻辑,支持读取 x-enum-varnamesx-enum-descriptions

// lib/core/models/api_schema.dart

class ApiModel {
  final List<String>? enumVarNames;        // 新增
  final List<String>? enumDescriptions;    // 新增
  
  factory ApiModel.fromJson(...) {
    // 解析 x-enum-varnames
    final enumVarNames = json['x-enum-varnames'] as List<dynamic>?;
    final enumDescriptions = json['x-enum-descriptions'] as List<dynamic>?;
    
    return ApiModel(
      enumVarNames: enumVarNames?.map((e) => e.toString()).toList(),
      enumDescriptions: enumDescriptions?.map((e) => e.toString()).toList(),
      ...
    );
  }
}

修改枚举生成逻辑:

// lib/pipeline/generate/impl/model/model_content_builders.dart

String _generateEnumCodeWithoutImports(ApiModel model) {
  ...
  for (var i = 0; i < model.enumValues.length; i++) {
    final value = model.enumValues[i];
    
    // 优先使用 x-enum-varnames
    final enumName = model.enumVarNames != null && i < model.enumVarNames!.length
        ? model.enumVarNames![i]
        : StringHelper.generateEnumValueName(value, i);
    
    // 添加描述注释
    if (model.enumDescriptions != null && i < model.enumDescriptions!.length) {
      buffer.writeln('  /// ${model.enumDescriptions![i]}');
    }
    
    final enumLine = enumType == 'integer' || enumType == 'number'
        ? '  $enumName($value),'
        : "  $enumName('$value'),";
    
    buffer.writeln(enumLine);
  }
  ...
}

阶段 2: 支持配置文件映射

已实现配置支持:

// lib/core/config_repository.dart

class EnumKeyMapping {
  final String name;
  final String? description;
  
  const EnumKeyMapping({required this.name, this.description});
}

class ConfigRepository {
  /// 获取枚举键名映射配置
  /// 返回格式: { "EnumName": { value: { "name": "KEY_NAME", "description": "描述" } } }
  Map<String, Map<dynamic, EnumKeyMapping>>? get enumKeyMappings { ... }
}

配置文件格式(generator_config.yaml

generation:
  models:
    enum_key_mappings:
      SysTaskTypeEnums:
        - value: 1
          name: SPOT_CHECK
          description: 抽查
        - value: 2
          name: CULTURAL
          description: 文创建设

实施步骤

Step 1: 修改数据模型

  1. ApiModel 中添加 enumVarNamesenumDescriptions 字段
  2. fromJson 中解析扩展字段

Step 2: 修改生成逻辑

  1. 修改 _generateEnumCodeWithoutImports 方法
  2. 实现三级优先级:配置文件 > x-enum-varnames > 智能生成
  3. 支持配置文件覆盖 Swagger 文档定义

Step 3: 配置文件支持

  1. ConfigRepository 中添加 enumKeyMappings 解析
  2. SwaggerConfig 中暴露配置
  3. 在枚举生成逻辑中使用配置
  4. 更新配置模板文件

Step 4: 文档和示例

  1. 更新使用文档
  2. 提供 Swagger 文档示例
  3. 提供配置文件示例
  4. 创建测试配置和测试文档

Step 5: 测试

  1. 创建测试 Swagger 文档
  2. 创建测试配置文件
  3. 运行生成器验证功能
  4. 确认生成的枚举键名和描述正确

使用示例

后端 Swagger 文档(推荐)

{
  "components": {
    "schemas": {
      "SysTaskTypeEnums": {
        "enum": [1, 2, 3],
        "type": "integer",
        "description": "任务类型枚举",
        "x-enum-varnames": ["SPOT_CHECK", "CULTURAL", "CLASS_CADRE_MEETING"],
        "x-enum-descriptions": ["抽查", "文创建设", "班干部会议"]
      }
    }
  }
}

配置文件映射(备选)

# generator_config.yaml
generation:
  models:
    enum_key_mappings:
      SysTaskTypeEnums:
        1: { name: "SPOT_CHECK", description: "抽查" }
        2: { name: "CULTURAL", description: "文创建设" }
        3: { name: "CLASS_CADRE_MEETING", description: "班干部会议" }

生成结果

/// 任务类型枚举
@JsonEnum()
enum SysTaskTypeEnums {
  /// 抽查
  SPOT_CHECK(1),
  
  /// 文创建设
  CULTURAL(2),
  
  /// 班干部会议
  CLASS_CADRE_MEETING(3);

  const SysTaskTypeEnums(this.value);
  final int value;

  static SysTaskTypeEnums fromValue(dynamic value) {
    for (final enumValue in SysTaskTypeEnums.values) {
      if (enumValue.value == value) {
        return enumValue;
      }
    }
    throw ArgumentError('Unknown enum value: $value');
  }

  factory SysTaskTypeEnums.fromJson(dynamic json) {
    return fromValue(json);
  }

  dynamic toJson() => value;
}

兼容性

  • 向后兼容:如果没有提供扩展字段或配置,仍使用 value1, value2
  • 灵活配置:支持全局配置或单个枚举配置
  • 标准支持:使用标准的 OpenAPI 扩展字段

相关资源


提案日期: 2025-11-24
状态: 待实施
优先级: Medium