fix(config): preserve source draft on visual save

This commit is contained in:
LTbinglingfeng
2026-05-20 01:27:19 +08:00
parent 075c2fa980
commit 2cb98ad118
+30 -8
View File
@@ -35,6 +35,15 @@ function readCommercialModeFromYaml(yamlContent: string): boolean {
}
}
function normalizeYamlForVisualDiff(yamlContent: string): string {
try {
const doc = parseDocument(yamlContent);
return doc.toString({ indent: 2, lineWidth: 120, minContentWidth: 0 });
} catch {
return yamlContent;
}
}
export function ConfigPage() {
const { t } = useTranslation();
const pageTransitionLayer = usePageTransitionLayer();
@@ -178,6 +187,8 @@ export function ConfigPage() {
try {
const latestServerYaml = await configFileApi.fetchConfigYaml();
const visualBaseYaml = dirty ? content : latestServerYaml;
if (activeTab !== 'source') {
const latestDocument = parseDocument(latestServerYaml);
if (latestDocument.errors.length > 0) {
@@ -191,23 +202,34 @@ export function ConfigPage() {
);
return;
}
if (visualBaseYaml !== latestServerYaml) {
const visualBaseDocument = parseDocument(visualBaseYaml);
if (visualBaseDocument.errors.length > 0) {
showNotification(
t('config_management.visual_mode_latest_yaml_invalid', {
message:
visualBaseDocument.errors[0]?.message ??
t('config_management.visual_mode_save_blocked'),
}),
'error'
);
return;
}
}
}
// In source mode, save exactly what the user edited. In visual mode, materialize visual changes into the latest YAML.
// In source mode, save exactly what the user edited. In visual mode, preserve the
// local source draft when it has unsaved edits so source-only backend fields are not dropped.
const nextMergedYaml =
activeTab === 'source' ? content : applyVisualChangesToYaml(latestServerYaml);
activeTab === 'source' ? content : applyVisualChangesToYaml(visualBaseYaml);
// In visual mode, applyVisualChangesToYaml re-serializes YAML via parseDocument → toString,
// which may reformat comments/whitespace. Normalize the server YAML through the same pipeline
// so the diff only shows actual value changes, not cosmetic reformatting.
let diffOriginal = latestServerYaml;
if (activeTab !== 'source') {
try {
const doc = parseDocument(latestServerYaml);
diffOriginal = doc.toString({ indent: 2, lineWidth: 120, minContentWidth: 0 });
} catch {
/* keep raw on parse failure */
}
diffOriginal = normalizeYamlForVisualDiff(latestServerYaml);
}
if (diffOriginal === nextMergedYaml) {