feat: add Flutter schema-driven form cards

This commit is contained in:
selfrelease
2026-07-18 09:13:27 +08:00
parent e13b6c7778
commit 2105fe3bac
85 changed files with 3141 additions and 3 deletions
@@ -0,0 +1,92 @@
enum JsonValueType { string, number, boolean }
enum FormControlType { text, textArea, select, dateTime }
class DynamicFormDefinition {
const DynamicFormDefinition({
required this.dataSchema,
required this.uiSchema,
});
final JsonFormSchema dataSchema;
final FormUiSchema uiSchema;
}
class JsonFormSchema {
const JsonFormSchema({
required this.id,
required this.title,
required this.properties,
this.required = const {},
});
final String id;
final String title;
final Map<String, JsonFieldSchema> properties;
final Set<String> required;
}
class JsonFieldSchema {
const JsonFieldSchema({
required this.type,
this.format,
this.enumValues = const [],
this.minLength,
this.maxLength,
});
final JsonValueType type;
final String? format;
final List<String> enumValues;
final int? minLength;
final int? maxLength;
}
class FormUiSchema {
const FormUiSchema({required this.description, required this.sections});
final String description;
final List<FormSectionSchema> sections;
}
class FormSectionSchema {
const FormSectionSchema({required this.title, required this.controls});
final String title;
final List<FormControlSchema> controls;
}
class FormControlSchema {
const FormControlSchema({
required this.field,
required this.label,
required this.control,
this.placeholder,
this.helperText,
this.optionLabels = const {},
});
final String field;
final String label;
final FormControlType control;
final String? placeholder;
final String? helperText;
final Map<String, String> optionLabels;
}
class DynamicFormState {
const DynamicFormState({this.values = const {}, this.errors = const {}});
final Map<String, Object?> values;
final Map<String, String> errors;
DynamicFormState copyWith({
Map<String, Object?>? values,
Map<String, String>? errors,
}) {
return DynamicFormState(
values: values ?? this.values,
errors: errors ?? this.errors,
);
}
}
@@ -0,0 +1,30 @@
import 'package:aioa_mobile/core/forms/schema/form_schema.dart';
Map<String, String> validateDynamicForm(
JsonFormSchema schema,
Map<String, Object?> values,
) {
final errors = <String, String>{};
for (final entry in schema.properties.entries) {
final key = entry.key;
final value = values[key];
final field = entry.value;
final empty = value == null || (value is String && value.trim().isEmpty);
if (schema.required.contains(key) && empty) {
errors[key] = '此项为必填项';
continue;
}
if (empty) continue;
if (value is String) {
if (field.minLength != null && value.trim().length < field.minLength!) {
errors[key] = '至少输入 ${field.minLength} 个字符';
} else if (field.maxLength != null && value.length > field.maxLength!) {
errors[key] = '最多输入 ${field.maxLength} 个字符';
} else if (field.enumValues.isNotEmpty &&
!field.enumValues.contains(value)) {
errors[key] = '选项无效';
}
}
}
return errors;
}