9.3 KiB
9.3 KiB
枚举配置文件映射功能实现总结
实现日期: 2025-11-24
功能状态: ✅ 已完成并测试
概述
成功实现了阶段 2:配置文件映射功能,允许用户通过 generator_config.yaml 配置文件为枚举值定义有意义的键名和描述,即使后端不支持 OpenAPI 扩展字段。
核心特性
1. 三级优先级系统
配置文件映射 > x-enum-varnames > 智能生成
- 配置文件映射(最高优先级):用户在
generator_config.yaml中显式配置 - x-enum-varnames(中优先级):后端在 Swagger 文档中提供的扩展字段
- 智能生成(最低优先级):自动生成
valueN格式
2. 灵活的配置方式
支持在 generator_config.yaml 中配置:
generation:
models:
enum_key_mappings:
SysTaskTypeEnums:
- value: 1
name: SPOT_CHECK
description: 抽查
- value: 2
name: CULTURAL
description: 文创建设
3. 完整的类型支持
- ✅ 整数枚举 (
integer,number) - ✅ 字符串枚举 (
string) - ✅ 枚举键名和描述
- ✅ 部分映射(可以只配置部分枚举值)
- ✅ 自动添加
UNKNOWN枚举值(整数类型用-9999,字符串类型用'UNKNOWN') - ✅ 容错处理(未知值返回
UNKNOWN而不是抛异常)
实现细节
修改的文件
1. lib/core/config_repository.dart
新增 EnumKeyMapping 数据类和解析逻辑:
/// 枚举键名映射
class EnumKeyMapping {
const EnumKeyMapping({
required this.name,
this.description,
});
final String name;
final String? description;
}
class ConfigRepository {
/// 获取枚举键名映射配置
Map<String, Map<dynamic, EnumKeyMapping>>? get enumKeyMappings {
// 从配置文件解析枚举映射
// 返回格式: { "EnumName": { value: EnumKeyMapping } }
}
}
2. lib/core/config.dart
暴露枚举映射配置:
class SwaggerConfig {
/// 获取枚举键名映射配置(从配置文件读取)
static Map<String, Map<dynamic, EnumKeyMapping>>? get enumKeyMappings =>
ConfigRepository.loadSync().enumKeyMappings;
}
3. lib/pipeline/generate/impl/model/model_content_builders.dart
修改枚举生成逻辑,支持三级优先级:
String _generateEnumCodeWithoutImports(ApiModel model) {
// 获取配置文件中的枚举映射
final enumMappings = SwaggerConfig.enumKeyMappings?[model.name];
for (var i = 0; i < model.enumValues.length; i++) {
final value = model.enumValues[i];
String enumName;
String? description;
// 优先级 1: 配置文件映射
if (enumMappings != null && enumMappings.containsKey(value)) {
final mapping = enumMappings[value]!;
enumName = mapping.name;
description = mapping.description;
}
// 优先级 2: x-enum-varnames
else if (model.enumVarNames != null && i < model.enumVarNames!.length) {
enumName = model.enumVarNames![i];
if (model.enumDescriptions != null && i < model.enumDescriptions!.length) {
description = model.enumDescriptions![i];
}
}
// 优先级 3: 智能生成
else {
enumName = StringHelper.generateEnumValueName(value, i);
}
// 生成枚举代码...
}
}
4. generator_config.template.yaml
添加详细的配置示例和说明:
generation:
models:
# 枚举键名映射配置(可选)
# 用于为枚举值定义有意义的键名和描述
# 优先级:配置文件映射 > x-enum-varnames > 智能生成
enum_key_mappings:
SysTaskTypeEnums:
- value: 1
name: SPOT_CHECK
description: 抽查
- value: 2
name: CULTURAL
description: 文创建设
测试文件
测试 Swagger 文档
创建了 example/swagger_config_mapping_test.json:
{
"components": {
"schemas": {
"SysTaskTypeEnums": {
"type": "integer",
"description": "任务类型枚举",
"enum": [1, 2, 3, 4, 5, 6, 7]
}
}
}
}
测试配置文件
创建了 example/test_config_mapping.yaml,包含完整的枚举映射配置。
测试结果
✅ 成功生成了包含有意义键名和描述的枚举代码:
/// 任务类型枚举
@JsonEnum()
enum SysTaskTypeEnums {
/// 抽查
SPOT_CHECK(1),
/// 文创建设
CULTURAL(2),
/// 班干部会议
CLASS_CADRE_MEETING(3),
/// 文创项目
CULTURAL_PROJECT(4),
/// 教工评优
TEACHER_AWARD(5),
/// 班级评比
CLASS_EVALUATION(6),
/// 组织生活
ORGANIZATION_LIFE(7),
/// 未知值
UNKNOWN(-9999);
const SysTaskTypeEnums(this.value);
final int value;
static SysTaskTypeEnums fromValue(dynamic value) {
for (final enumValue in SysTaskTypeEnums.values) {
if (enumValue.value == value) {
return enumValue;
}
}
return SysTaskTypeEnums.UNKNOWN; // 返回 UNKNOWN 而不是抛异常
}
// ... 其余代码
}
文档更新
1. ENUM_KEY_NAMES_PROPOSAL.md
- ✅ 标记阶段 2 已完成
- ✅ 更新实施步骤
- ✅ 添加配置文件格式说明
2. ENUM_KEY_NAMES_USAGE.md
- ✅ 添加"方法 2: 通过配置文件映射"章节
- ✅ 提供完整的配置示例
- ✅ 说明优先级规则
- ✅ 列出使用场景和注意事项
3. generator_config.template.yaml
- ✅ 添加
enum_key_mappings配置节 - ✅ 提供详细的注释和示例
- ✅ 说明优先级和使用场景
使用示例
场景 1: 后端不支持扩展字段
Swagger 文档:
{
"SysTaskTypeEnums": {
"enum": [1, 2, 3],
"type": "integer"
}
}
配置文件:
generation:
models:
enum_key_mappings:
SysTaskTypeEnums:
- value: 1
name: SPOT_CHECK
description: 抽查
- value: 2
name: CULTURAL
description: 文创建设
- value: 3
name: CLASS_CADRE_MEETING
description: 班干部会议
生成结果: 使用配置文件中的键名和描述 ✅
场景 2: 覆盖 Swagger 文档定义
Swagger 文档:
{
"SysTaskTypeEnums": {
"enum": [1, 2, 3],
"type": "integer",
"x-enum-varnames": ["TYPE_1", "TYPE_2", "TYPE_3"]
}
}
配置文件:
generation:
models:
enum_key_mappings:
SysTaskTypeEnums:
- value: 1
name: SPOT_CHECK
description: 抽查
生成结果:
- value 1: 使用配置文件的
SPOT_CHECK✅ - value 2: 使用 Swagger 的
TYPE_2✅ - value 3: 使用 Swagger 的
TYPE_3✅
场景 3: 只使用 Swagger 扩展字段
Swagger 文档:
{
"SysTaskTypeEnums": {
"enum": [1, 2, 3],
"type": "integer",
"x-enum-varnames": ["SPOT_CHECK", "CULTURAL", "CLASS_CADRE_MEETING"]
}
}
配置文件: 无配置
生成结果: 使用 Swagger 的枚举键名 ✅
UNKNOWN 枚举值
设计理念
每个生成的枚举都会自动添加一个 UNKNOWN 枚举值,用于处理未知或无效的枚举值,提供更好的容错性。
值的选择
- 整数枚举: 使用
-9999作为UNKNOWN的值 - 字符串枚举: 使用
'UNKNOWN'作为UNKNOWN的值
优势
- 容错处理: 当接收到未知的枚举值时,返回
UNKNOWN而不是抛出异常 - 前向兼容: 当后端添加新的枚举值时,前端不会崩溃
- 安全检查: 可以在业务逻辑中检查是否为
UNKNOWN值
使用示例
// 后端返回了一个新增的枚举值 99(前端代码还未更新)
final taskType = SysTaskTypeEnums.fromValue(99);
print(taskType); // SysTaskTypeEnums.UNKNOWN
// 业务逻辑中检查
if (taskType == SysTaskTypeEnums.UNKNOWN) {
print('遇到未知的任务类型,请更新应用版本');
}
优势
1. 灵活性
- ✅ 无需后端支持即可使用
- ✅ 可以快速修改枚举定义
- ✅ 支持覆盖 Swagger 文档定义
2. 兼容性
- ✅ 完全向后兼容
- ✅ 不影响现有功能
- ✅ 与 x-enum-varnames 共存
- ✅ 自动容错处理(UNKNOWN 枚举值)
3. 可维护性
- ✅ 集中式配置管理
- ✅ 易于团队协作
- ✅ 支持部分映射
注意事项
1. 维护成本
⚠️ 配置文件需要手动维护,当后端枚举值变化时需要同步更新。
建议: 如果后端支持,优先使用 Swagger 扩展字段,保持单一数据源。
2. 值匹配
⚠️ 配置文件中的 value 必须与 Swagger 文档中的枚举值完全匹配(类型和值都要匹配)。
3. 命名规范
⚠️ 枚举键名必须是有效的 Dart 标识符(大写字母+下划线)。
后续计划
- ✅ 基础功能实现
- ✅ 测试验证
- ✅ 文档更新
- 🔄 收集用户反馈
- 🔄 优化用户体验
总结
阶段 2 的配置文件映射功能已成功实现,为用户提供了更灵活的枚举键名配置方式。用户现在可以:
- ✅ 在后端不支持扩展字段时使用配置文件
- ✅ 覆盖 Swagger 文档中的枚举定义
- ✅ 快速修改枚举键名,无需等待后端
- ✅ 为不同项目使用不同的枚举命名规范
功能已完成测试,生成的代码符合预期,文档已更新完毕。
实现者: Assistant
日期: 2025-11-24
状态: ✅ 已完成