From f833f0dfd2e1fd57ee56ee25656052c70da60ea2 Mon Sep 17 00:00:00 2001 From: LTbinglingfeng Date: Fri, 6 Feb 2026 18:14:13 +0800 Subject: [PATCH] fix(config): align visual editor with backend config semantics --- package-lock.json | 13 +++++ package.json | 1 + src/components/config/VisualConfigEditor.tsx | 9 ---- src/hooks/useVisualConfig.ts | 57 ++++++++++++-------- src/i18n/locales/en.json | 4 +- src/i18n/locales/zh-CN.json | 4 +- src/pages/ConfigPage.tsx | 5 +- src/types/visualConfig.ts | 2 - 8 files changed, 53 insertions(+), 42 deletions(-) diff --git a/package-lock.json b/package-lock.json index 2ce56de..a182545 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,7 @@ "version": "0.0.0", "dependencies": { "@codemirror/lang-yaml": "^6.1.2", + "@openai/codex": "^0.98.0", "@uiw/react-codemirror": "^4.25.3", "axios": "^1.13.2", "chart.js": "^4.5.1", @@ -1243,6 +1244,18 @@ "integrity": "sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g==", "license": "MIT" }, + "node_modules/@openai/codex": { + "version": "0.98.0", + "resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.98.0.tgz", + "integrity": "sha512-CKjrhAmzTvWn7Vbsi27iZRKBAJw9a7ZTTkWQDbLgQZP1weGbDIBk1r6wiLEp1ZmDO7w0fHPLYgnVspiOrYgcxg==", + "license": "Apache-2.0", + "bin": { + "codex": "bin/codex.js" + }, + "engines": { + "node": ">=16" + } + }, "node_modules/@parcel/watcher": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.1.tgz", diff --git a/package.json b/package.json index b8d6a4d..70a1935 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ }, "dependencies": { "@codemirror/lang-yaml": "^6.1.2", + "@openai/codex": "^0.98.0", "@uiw/react-codemirror": "^4.25.3", "axios": "^1.13.2", "chart.js": "^4.5.1", diff --git a/src/components/config/VisualConfigEditor.tsx b/src/components/config/VisualConfigEditor.tsx index eff48ed..d66e9f7 100644 --- a/src/components/config/VisualConfigEditor.tsx +++ b/src/components/config/VisualConfigEditor.tsx @@ -891,15 +891,6 @@ export function VisualConfigEditor({ values, disabled = false, onChange }: Visua onChange={(e) => onChange({ logsMaxTotalSizeMb: e.target.value })} disabled={disabled} /> - onChange({ usageRecordsRetentionDays: e.target.value })} - disabled={disabled} - hint={t('config_management.visual.sections.system.usage_retention_hint')} - /> diff --git a/src/hooks/useVisualConfig.ts b/src/hooks/useVisualConfig.ts index 1f7ed30..47d3cce 100644 --- a/src/hooks/useVisualConfig.ts +++ b/src/hooks/useVisualConfig.ts @@ -102,6 +102,27 @@ function deepClone(value: T): T { return JSON.parse(JSON.stringify(value)) as T; } +function parsePayloadParamValue(raw: unknown): { valueType: PayloadParamValueType; value: string } { + if (typeof raw === 'number') { + return { valueType: 'number', value: String(raw) }; + } + + if (typeof raw === 'boolean') { + return { valueType: 'boolean', value: String(raw) }; + } + + if (raw === null || typeof raw === 'object') { + try { + const json = JSON.stringify(raw, null, 2); + return { valueType: 'json', value: json ?? 'null' }; + } catch { + return { valueType: 'json', value: String(raw) }; + } + } + + return { valueType: 'string', value: String(raw ?? '') }; +} + function parsePayloadRules(rules: unknown): PayloadRule[] { if (!Array.isArray(rules)) return []; @@ -115,19 +136,15 @@ function parsePayloadRules(rules: unknown): PayloadRule[] { })) : [], params: (rule as any)?.params - ? Object.entries((rule as any).params as Record).map(([path, value], pIndex) => ({ - id: `param-${index}-${pIndex}`, - path, - valueType: - typeof value === 'number' - ? 'number' - : typeof value === 'boolean' - ? 'boolean' - : typeof value === 'object' - ? 'json' - : 'string', - value: String(value), - })) + ? Object.entries((rule as any).params as Record).map(([path, value], pIndex) => { + const parsedValue = parsePayloadParamValue(value); + return { + id: `param-${index}-${pIndex}`, + path, + valueType: parsedValue.valueType, + value: parsedValue.value, + }; + }) : [], })); } @@ -220,7 +237,7 @@ export function useVisualConfig() { const newValues: VisualConfigValues = { host: parsed.host || '', - port: String(parsed.port || ''), + port: String(parsed.port ?? ''), tlsEnable: Boolean(parsed.tls?.enable), tlsCert: parsed.tls?.cert || '', @@ -240,14 +257,13 @@ export function useVisualConfig() { debug: Boolean(parsed.debug), commercialMode: Boolean(parsed['commercial-mode']), loggingToFile: Boolean(parsed['logging-to-file']), - logsMaxTotalSizeMb: String(parsed['logs-max-total-size-mb'] || ''), + logsMaxTotalSizeMb: String(parsed['logs-max-total-size-mb'] ?? ''), usageStatisticsEnabled: Boolean(parsed['usage-statistics-enabled']), - usageRecordsRetentionDays: String(parsed['usage-records-retention-days'] ?? ''), proxyUrl: parsed['proxy-url'] || '', forceModelPrefix: Boolean(parsed['force-model-prefix']), - requestRetry: String(parsed['request-retry'] || ''), - maxRetryInterval: String(parsed['max-retry-interval'] || ''), + requestRetry: String(parsed['request-retry'] ?? ''), + maxRetryInterval: String(parsed['max-retry-interval'] ?? ''), wsAuth: Boolean(parsed['ws-auth']), quotaSwitchProject: Boolean(parsed['quota-exceeded']?.['switch-project'] ?? true), @@ -333,11 +349,6 @@ export function useVisualConfig() { setBoolean(parsed, 'logging-to-file', values.loggingToFile); setIntFromString(parsed, 'logs-max-total-size-mb', values.logsMaxTotalSizeMb); setBoolean(parsed, 'usage-statistics-enabled', values.usageStatisticsEnabled); - setIntFromString( - parsed, - 'usage-records-retention-days', - values.usageRecordsRetentionDays - ); setString(parsed, 'proxy-url', values.proxyUrl); setBoolean(parsed, 'force-model-prefix', values.forceModelPrefix); diff --git a/src/i18n/locales/en.json b/src/i18n/locales/en.json index 6b90898..c58692d 100644 --- a/src/i18n/locales/en.json +++ b/src/i18n/locales/en.json @@ -882,9 +882,7 @@ "logging_to_file_desc": "Save logs to rotating files", "usage_statistics": "Usage Statistics", "usage_statistics_desc": "Collect usage statistics", - "logs_max_size": "Log File Size Limit (MB)", - "usage_retention_days": "Usage Records Retention Days", - "usage_retention_hint": "0 means no limit (no cleanup)" + "logs_max_size": "Log File Size Limit (MB)" }, "network": { "title": "Network Configuration", diff --git a/src/i18n/locales/zh-CN.json b/src/i18n/locales/zh-CN.json index 20f8a7f..ed769c9 100644 --- a/src/i18n/locales/zh-CN.json +++ b/src/i18n/locales/zh-CN.json @@ -882,9 +882,7 @@ "logging_to_file_desc": "将日志保存到滚动文件", "usage_statistics": "使用统计", "usage_statistics_desc": "收集使用统计信息", - "logs_max_size": "日志文件大小限制 (MB)", - "usage_retention_days": "使用记录保留天数", - "usage_retention_hint": "0 为无限制(不清理)" + "logs_max_size": "日志文件大小限制 (MB)" }, "network": { "title": "网络配置", diff --git a/src/pages/ConfigPage.tsx b/src/pages/ConfigPage.tsx index 77e3a00..eaf9442 100644 --- a/src/pages/ConfigPage.tsx +++ b/src/pages/ConfigPage.tsx @@ -80,9 +80,10 @@ export function ConfigPage() { try { const nextContent = activeTab === 'visual' ? applyVisualChangesToYaml(content) : content; await configFileApi.saveConfigYaml(nextContent); + const latestContent = await configFileApi.fetchConfigYaml(); setDirty(false); - setContent(nextContent); - loadVisualValuesFromYaml(nextContent); + setContent(latestContent); + loadVisualValuesFromYaml(latestContent); showNotification(t('config_management.save_success'), 'success'); } catch (err: unknown) { const message = err instanceof Error ? err.message : ''; diff --git a/src/types/visualConfig.ts b/src/types/visualConfig.ts index 86efcf9..ff4242a 100644 --- a/src/types/visualConfig.ts +++ b/src/types/visualConfig.ts @@ -48,7 +48,6 @@ export type VisualConfigValues = { loggingToFile: boolean; logsMaxTotalSizeMb: string; usageStatisticsEnabled: boolean; - usageRecordsRetentionDays: string; proxyUrl: string; forceModelPrefix: boolean; requestRetry: string; @@ -85,7 +84,6 @@ export const DEFAULT_VISUAL_VALUES: VisualConfigValues = { loggingToFile: false, logsMaxTotalSizeMb: '', usageStatisticsEnabled: false, - usageRecordsRetentionDays: '', proxyUrl: '', forceModelPrefix: false, requestRetry: '',