mirror of
https://github.com/router-for-me/Cli-Proxy-API-Management-Center.git
synced 2026-06-16 21:03:58 +08:00
fix(config): preserve source draft on visual save
This commit is contained in:
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user