8.5 KiB
8.5 KiB
枚举键名生成优化方案
问题描述
当前生成的枚举使用通用的键名(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-varnames 和 x-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-varnames 和 x-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: 修改数据模型 ✅
- 在
ApiModel中添加enumVarNames和enumDescriptions字段 - 在
fromJson中解析扩展字段
Step 2: 修改生成逻辑 ✅
- 修改
_generateEnumCodeWithoutImports方法 - 实现三级优先级:配置文件 > x-enum-varnames > 智能生成
- 支持配置文件覆盖 Swagger 文档定义
Step 3: 配置文件支持 ✅
- 在
ConfigRepository中添加enumKeyMappings解析 - 在
SwaggerConfig中暴露配置 - 在枚举生成逻辑中使用配置
- 更新配置模板文件
Step 4: 文档和示例 ✅
- 更新使用文档
- 提供 Swagger 文档示例
- 提供配置文件示例
- 创建测试配置和测试文档
Step 5: 测试 ✅
- 创建测试 Swagger 文档
- 创建测试配置文件
- 运行生成器验证功能
- 确认生成的枚举键名和描述正确
使用示例
后端 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