fix: stabilize rule editor yaml roundtrip
This commit is contained in:
@@ -330,7 +330,7 @@ function normalizeBooleanText(value: string | boolean | undefined): boolean {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function rewriteExtractNodes(fields: ExtractFieldSummary[]): Array<Record<string, unknown>> {
|
function rewriteExtractNodes(fields: ExtractFieldSummary[]): Array<Record<string, unknown>> {
|
||||||
const topLevelFields = fields.filter((field) => !field.name.includes('[*].'));
|
const topLevelFields = fields.filter((field) => field.group !== '派生字段' && !field.name.includes('[*].'));
|
||||||
return Array.from(groupBy(topLevelFields, (field) => field.group || '未分组').entries()).map(([group, items]) => ({
|
return Array.from(groupBy(topLevelFields, (field) => field.group || '未分组').entries()).map(([group, items]) => ({
|
||||||
group,
|
group,
|
||||||
fields: items.map((field) => ({
|
fields: items.map((field) => ({
|
||||||
@@ -343,6 +343,46 @@ function rewriteExtractNodes(fields: ExtractFieldSummary[]): Array<Record<string
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function rewriteDerivedFieldNodes(
|
||||||
|
fields: ExtractFieldSummary[],
|
||||||
|
existingNodes: unknown,
|
||||||
|
): Array<Record<string, unknown>> {
|
||||||
|
const derivedFields = fields.filter((field) => field.group === '派生字段');
|
||||||
|
if (derivedFields.length === 0) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
const existingMap = new Map<string, Record<string, unknown>>();
|
||||||
|
if (Array.isArray(existingNodes)) {
|
||||||
|
existingNodes.forEach((node) => {
|
||||||
|
if (!node || typeof node !== 'object') return;
|
||||||
|
const record = deepClone(node as Record<string, unknown>);
|
||||||
|
const name = String(record.name || '').trim();
|
||||||
|
if (name) {
|
||||||
|
existingMap.set(name, record);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return derivedFields.map((field) => {
|
||||||
|
const existing = existingMap.get(field.name) || {};
|
||||||
|
const nextNode: Record<string, unknown> = {
|
||||||
|
...existing,
|
||||||
|
name: field.name,
|
||||||
|
type: field.type || String(existing.type || 'computed'),
|
||||||
|
};
|
||||||
|
const nextCompute = field.description && field.description !== '由其他字段计算得出'
|
||||||
|
? field.description
|
||||||
|
: String(existing.compute || '').trim();
|
||||||
|
if (nextCompute) {
|
||||||
|
nextNode.compute = nextCompute;
|
||||||
|
} else {
|
||||||
|
delete nextNode.compute;
|
||||||
|
}
|
||||||
|
return nextNode;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function rewriteSubDocumentNodes(subDocuments: SubDocumentSummary[]): Array<Record<string, unknown>> {
|
function rewriteSubDocumentNodes(subDocuments: SubDocumentSummary[]): Array<Record<string, unknown>> {
|
||||||
return subDocuments.map((document) => ({
|
return subDocuments.map((document) => ({
|
||||||
id: document.id,
|
id: document.id,
|
||||||
@@ -474,7 +514,6 @@ function rewriteRuleNode(baseRule: Record<string, unknown> | undefined, rule: Ru
|
|||||||
}
|
}
|
||||||
|
|
||||||
delete nextRule.rules;
|
delete nextRule.rules;
|
||||||
delete nextRule.logic;
|
|
||||||
|
|
||||||
const existingStages = Array.isArray(nextRule.stages) ? (nextRule.stages as Array<Record<string, unknown>>) : [];
|
const existingStages = Array.isArray(nextRule.stages) ? (nextRule.stages as Array<Record<string, unknown>>) : [];
|
||||||
const stages = existingStages.length > 0 ? deepClone(existingStages) : (buildMinimalRuleNode(rule).stages as Array<Record<string, unknown>>);
|
const stages = existingStages.length > 0 ? deepClone(existingStages) : (buildMinimalRuleNode(rule).stages as Array<Record<string, unknown>>);
|
||||||
@@ -494,6 +533,8 @@ function rewriteRuleNode(baseRule: Record<string, unknown> | undefined, rule: Ru
|
|||||||
}
|
}
|
||||||
|
|
||||||
nextRule.stages = stages;
|
nextRule.stages = stages;
|
||||||
|
if (rule.logic?.trim()) nextRule.logic = rule.logic.trim();
|
||||||
|
else if (typeof nextRule.logic === 'string' && !String(nextRule.logic).trim()) delete nextRule.logic;
|
||||||
return nextRule;
|
return nextRule;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -512,6 +553,7 @@ export function serializeEditableRuleConfig(config: EditableRuleConfig): string
|
|||||||
if (Array.isArray(config.metadata.inheritsFrom) && config.metadata.inheritsFrom.length > 0) metadata.inherits_from = [...config.metadata.inheritsFrom];
|
if (Array.isArray(config.metadata.inheritsFrom) && config.metadata.inheritsFrom.length > 0) metadata.inherits_from = [...config.metadata.inheritsFrom];
|
||||||
root.metadata = metadata;
|
root.metadata = metadata;
|
||||||
root.extract = rewriteExtractNodes(config.fields);
|
root.extract = rewriteExtractNodes(config.fields);
|
||||||
|
root.derived_fields = rewriteDerivedFieldNodes(config.fields, root.derived_fields);
|
||||||
root.sub_documents = rewriteSubDocumentNodes(config.subDocuments);
|
root.sub_documents = rewriteSubDocumentNodes(config.subDocuments);
|
||||||
root.visual_elements = rewriteVisualElementNodes(config.visualElements);
|
root.visual_elements = rewriteVisualElementNodes(config.visualElements);
|
||||||
|
|
||||||
|
|||||||
@@ -415,9 +415,9 @@ function parseRules(source: string): RuleSummary[] {
|
|||||||
group,
|
group,
|
||||||
risk: stripYamlValue(ruleBlock.match(/^\s+risk:\s*(.+)$/m)?.[1] || 'medium'),
|
risk: stripYamlValue(ruleBlock.match(/^\s+risk:\s*(.+)$/m)?.[1] || 'medium'),
|
||||||
score: stripYamlValue(ruleBlock.match(/^\s+score:\s*(.+)$/m)?.[1] || '-'),
|
score: stripYamlValue(ruleBlock.match(/^\s+score:\s*(.+)$/m)?.[1] || '-'),
|
||||||
type: stripYamlValue(ruleBlock.match(/^\s+type:\s*(.+)$/m)?.[1] || 'deterministic'),
|
type: stripYamlValue(ruleBlock.match(/^\s{4}type:\s*(.+)$/m)?.[1] || 'deterministic'),
|
||||||
checkTypes,
|
checkTypes,
|
||||||
logic: stripYamlValue(ruleBlock.match(/^\s+logic:\s*(.+)$/m)?.[1] || ''),
|
logic: stripYamlValue(ruleBlock.match(/^\s{4}logic:\s*(.+)$/m)?.[1] || ''),
|
||||||
subRules,
|
subRules,
|
||||||
subRuleIds: readList(ruleBlock, 'rules'),
|
subRuleIds: readList(ruleBlock, 'rules'),
|
||||||
scope: scope.slice(0, 8),
|
scope: scope.slice(0, 8),
|
||||||
@@ -425,7 +425,7 @@ function parseRules(source: string): RuleSummary[] {
|
|||||||
stageCount: subRules.length,
|
stageCount: subRules.length,
|
||||||
appliesIn: readFlexibleList(ruleBlock, 'applies_in'),
|
appliesIn: readFlexibleList(ruleBlock, 'applies_in'),
|
||||||
prompt: prompts.join('\n\n'),
|
prompt: prompts.join('\n\n'),
|
||||||
description: stripYamlValue(ruleBlock.match(/^\s+desc:\s*(.+)$/m)?.[1] || '')
|
description: stripYamlValue(ruleBlock.match(/^\s{4}desc:\s*(.+)$/m)?.[1] || '')
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user