feat: JSON编辑器增强 - Token映射下拉、字段选项key:value、序列化始终包装type
1. 模型配置弹窗: Token映射三个字段由输入框改为下拉菜单
- 同步/流式从响应映射取key, 异步从回调响应映射取key
- 切换返回类型时清空Token映射, 无映射配置时禁用并提示
2. JSON编辑器序列化: 所有节点始终输出{type, value/attrs}格式
- 容器(object/array)始终{type, attrs}, 标量始终{type, value}
3. 字段配置增强:
- 对象类型新增"循环生成"开关
- 下拉控件选项列表改为key:value双输入框
4. 类型注释更新
This commit is contained in:
@@ -75,8 +75,9 @@ interface FieldConfig {
|
||||
role?: string;
|
||||
isForm?: boolean;
|
||||
required?: boolean;
|
||||
loop?: boolean;
|
||||
defaultValue?: string | number;
|
||||
options?: string[];
|
||||
options?: Array<{ label: string; value: string }>;
|
||||
constraint?: {
|
||||
minLength?: number; maxLength?: number; pattern?: string;
|
||||
min?: number; max?: number; numberType?: string;
|
||||
@@ -100,7 +101,7 @@ interface FieldFormData {
|
||||
nodeId: string;
|
||||
jsonType: string;
|
||||
fieldType: string; label: string; description: string; role: string;
|
||||
isForm: boolean; required: boolean; defaultValue: string; options: string[];
|
||||
isForm: boolean; required: boolean; loop: boolean; defaultValue: string; options: Array<{ label: string; value: string }>;
|
||||
constraint: {
|
||||
minLength?: number; maxLength?: number; pattern?: string;
|
||||
min?: number; max?: number; numberType?: string;
|
||||
@@ -182,11 +183,21 @@ function nodeToValue(node: JsonNodeData): any {
|
||||
else if (node.type === 'boolean') rawValue = node.primitiveValue === true || node.primitiveValue === 'true';
|
||||
else rawValue = String(node.primitiveValue);
|
||||
|
||||
if (node.config && hasAnyConfig(node)) {
|
||||
const dataKey = (node.type === 'object' || node.type === 'array') ? 'attrs' : 'value';
|
||||
return { type: node.type, [dataKey]: rawValue, ...node.config };
|
||||
// 容器类型(object/array)始终输出 { type, attrs, ...config }
|
||||
if (node.type === 'object' || node.type === 'array') {
|
||||
const result: Record<string, any> = { type: node.type, attrs: rawValue };
|
||||
if (node.config && hasAnyConfig(node)) {
|
||||
Object.assign(result, node.config);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return rawValue;
|
||||
|
||||
// 标量类型也始终输出 { type, value, ...config }
|
||||
const result: Record<string, any> = { type: node.type, value: rawValue };
|
||||
if (node.config && hasAnyConfig(node)) {
|
||||
Object.assign(result, node.config);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function defaultFormType(jsonType: string): string {
|
||||
@@ -274,6 +285,7 @@ function formToConfig(form: FieldFormData): FieldConfig {
|
||||
cfg.fieldType = form.fieldType || defaultFormType(form.jsonType);
|
||||
cfg.isForm = form.isForm ?? true;
|
||||
cfg.required = form.required ?? false;
|
||||
cfg.loop = form.loop ?? false;
|
||||
// 非骨架字段:有值才发
|
||||
if (form.description) cfg.description = form.description;
|
||||
if (form.role) cfg.role = form.role;
|
||||
@@ -299,6 +311,7 @@ function hasAnyConfig(node: JsonNodeData): boolean {
|
||||
if (c.label || c.description || c.role || c.defaultValue) return true;
|
||||
if (c.options?.length) return true;
|
||||
if (c.required) return true;
|
||||
if (c.loop) return true;
|
||||
if (c.isForm === false) return true;
|
||||
if (c.constraint && Object.keys(c.constraint).length > 0) return true;
|
||||
if (c.fieldType && c.fieldType !== defaultFormType(node.type)) return true;
|
||||
@@ -324,6 +337,7 @@ function openFieldDialog(nodeId: string) {
|
||||
role: cfg.role || '',
|
||||
isForm: cfg.isForm ?? true,
|
||||
required: cfg.required ?? false,
|
||||
loop: cfg.loop ?? false,
|
||||
defaultValue: String(cfg.defaultValue ?? ''),
|
||||
options: cfg.options || [],
|
||||
constraint: cfg.constraint ? { ...cfg.constraint } : {},
|
||||
@@ -355,6 +369,7 @@ function openAddChildDialog(parentNodeId: string) {
|
||||
role: '',
|
||||
isForm: true,
|
||||
required: false,
|
||||
loop: false,
|
||||
defaultValue: '',
|
||||
options: [],
|
||||
constraint: {},
|
||||
|
||||
Reference in New Issue
Block a user