mirror of
https://github.com/router-for-me/Cli-Proxy-API-Management-Center.git
synced 2026-02-18 10:40:50 +08:00
fix(config): align visual editor with backend config semantics
This commit is contained in:
13
package-lock.json
generated
13
package-lock.json
generated
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -891,15 +891,6 @@ export function VisualConfigEditor({ values, disabled = false, onChange }: Visua
|
||||
onChange={(e) => onChange({ logsMaxTotalSizeMb: e.target.value })}
|
||||
disabled={disabled}
|
||||
/>
|
||||
<Input
|
||||
label={t('config_management.visual.sections.system.usage_retention_days')}
|
||||
type="number"
|
||||
placeholder="30"
|
||||
value={values.usageRecordsRetentionDays}
|
||||
onChange={(e) => onChange({ usageRecordsRetentionDays: e.target.value })}
|
||||
disabled={disabled}
|
||||
hint={t('config_management.visual.sections.system.usage_retention_hint')}
|
||||
/>
|
||||
</SectionGrid>
|
||||
</div>
|
||||
</ConfigSection>
|
||||
|
||||
@@ -102,6 +102,27 @@ function deepClone<T>(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<string, unknown>).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<string, unknown>).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);
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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": "网络配置",
|
||||
|
||||
@@ -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 : '';
|
||||
|
||||
@@ -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: '',
|
||||
|
||||
Reference in New Issue
Block a user