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",
|
"version": "0.0.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@codemirror/lang-yaml": "^6.1.2",
|
"@codemirror/lang-yaml": "^6.1.2",
|
||||||
|
"@openai/codex": "^0.98.0",
|
||||||
"@uiw/react-codemirror": "^4.25.3",
|
"@uiw/react-codemirror": "^4.25.3",
|
||||||
"axios": "^1.13.2",
|
"axios": "^1.13.2",
|
||||||
"chart.js": "^4.5.1",
|
"chart.js": "^4.5.1",
|
||||||
@@ -1243,6 +1244,18 @@
|
|||||||
"integrity": "sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g==",
|
"integrity": "sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g==",
|
||||||
"license": "MIT"
|
"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": {
|
"node_modules/@parcel/watcher": {
|
||||||
"version": "2.5.1",
|
"version": "2.5.1",
|
||||||
"resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.1.tgz",
|
"resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.1.tgz",
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@codemirror/lang-yaml": "^6.1.2",
|
"@codemirror/lang-yaml": "^6.1.2",
|
||||||
|
"@openai/codex": "^0.98.0",
|
||||||
"@uiw/react-codemirror": "^4.25.3",
|
"@uiw/react-codemirror": "^4.25.3",
|
||||||
"axios": "^1.13.2",
|
"axios": "^1.13.2",
|
||||||
"chart.js": "^4.5.1",
|
"chart.js": "^4.5.1",
|
||||||
|
|||||||
@@ -891,15 +891,6 @@ export function VisualConfigEditor({ values, disabled = false, onChange }: Visua
|
|||||||
onChange={(e) => onChange({ logsMaxTotalSizeMb: e.target.value })}
|
onChange={(e) => onChange({ logsMaxTotalSizeMb: e.target.value })}
|
||||||
disabled={disabled}
|
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>
|
</SectionGrid>
|
||||||
</div>
|
</div>
|
||||||
</ConfigSection>
|
</ConfigSection>
|
||||||
|
|||||||
@@ -102,6 +102,27 @@ function deepClone<T>(value: T): T {
|
|||||||
return JSON.parse(JSON.stringify(value)) as 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[] {
|
function parsePayloadRules(rules: unknown): PayloadRule[] {
|
||||||
if (!Array.isArray(rules)) return [];
|
if (!Array.isArray(rules)) return [];
|
||||||
|
|
||||||
@@ -115,19 +136,15 @@ function parsePayloadRules(rules: unknown): PayloadRule[] {
|
|||||||
}))
|
}))
|
||||||
: [],
|
: [],
|
||||||
params: (rule as any)?.params
|
params: (rule as any)?.params
|
||||||
? Object.entries((rule as any).params as Record<string, unknown>).map(([path, value], pIndex) => ({
|
? Object.entries((rule as any).params as Record<string, unknown>).map(([path, value], pIndex) => {
|
||||||
id: `param-${index}-${pIndex}`,
|
const parsedValue = parsePayloadParamValue(value);
|
||||||
path,
|
return {
|
||||||
valueType:
|
id: `param-${index}-${pIndex}`,
|
||||||
typeof value === 'number'
|
path,
|
||||||
? 'number'
|
valueType: parsedValue.valueType,
|
||||||
: typeof value === 'boolean'
|
value: parsedValue.value,
|
||||||
? 'boolean'
|
};
|
||||||
: typeof value === 'object'
|
})
|
||||||
? 'json'
|
|
||||||
: 'string',
|
|
||||||
value: String(value),
|
|
||||||
}))
|
|
||||||
: [],
|
: [],
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
@@ -220,7 +237,7 @@ export function useVisualConfig() {
|
|||||||
|
|
||||||
const newValues: VisualConfigValues = {
|
const newValues: VisualConfigValues = {
|
||||||
host: parsed.host || '',
|
host: parsed.host || '',
|
||||||
port: String(parsed.port || ''),
|
port: String(parsed.port ?? ''),
|
||||||
|
|
||||||
tlsEnable: Boolean(parsed.tls?.enable),
|
tlsEnable: Boolean(parsed.tls?.enable),
|
||||||
tlsCert: parsed.tls?.cert || '',
|
tlsCert: parsed.tls?.cert || '',
|
||||||
@@ -240,14 +257,13 @@ export function useVisualConfig() {
|
|||||||
debug: Boolean(parsed.debug),
|
debug: Boolean(parsed.debug),
|
||||||
commercialMode: Boolean(parsed['commercial-mode']),
|
commercialMode: Boolean(parsed['commercial-mode']),
|
||||||
loggingToFile: Boolean(parsed['logging-to-file']),
|
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']),
|
usageStatisticsEnabled: Boolean(parsed['usage-statistics-enabled']),
|
||||||
usageRecordsRetentionDays: String(parsed['usage-records-retention-days'] ?? ''),
|
|
||||||
|
|
||||||
proxyUrl: parsed['proxy-url'] || '',
|
proxyUrl: parsed['proxy-url'] || '',
|
||||||
forceModelPrefix: Boolean(parsed['force-model-prefix']),
|
forceModelPrefix: Boolean(parsed['force-model-prefix']),
|
||||||
requestRetry: String(parsed['request-retry'] || ''),
|
requestRetry: String(parsed['request-retry'] ?? ''),
|
||||||
maxRetryInterval: String(parsed['max-retry-interval'] || ''),
|
maxRetryInterval: String(parsed['max-retry-interval'] ?? ''),
|
||||||
wsAuth: Boolean(parsed['ws-auth']),
|
wsAuth: Boolean(parsed['ws-auth']),
|
||||||
|
|
||||||
quotaSwitchProject: Boolean(parsed['quota-exceeded']?.['switch-project'] ?? true),
|
quotaSwitchProject: Boolean(parsed['quota-exceeded']?.['switch-project'] ?? true),
|
||||||
@@ -333,11 +349,6 @@ export function useVisualConfig() {
|
|||||||
setBoolean(parsed, 'logging-to-file', values.loggingToFile);
|
setBoolean(parsed, 'logging-to-file', values.loggingToFile);
|
||||||
setIntFromString(parsed, 'logs-max-total-size-mb', values.logsMaxTotalSizeMb);
|
setIntFromString(parsed, 'logs-max-total-size-mb', values.logsMaxTotalSizeMb);
|
||||||
setBoolean(parsed, 'usage-statistics-enabled', values.usageStatisticsEnabled);
|
setBoolean(parsed, 'usage-statistics-enabled', values.usageStatisticsEnabled);
|
||||||
setIntFromString(
|
|
||||||
parsed,
|
|
||||||
'usage-records-retention-days',
|
|
||||||
values.usageRecordsRetentionDays
|
|
||||||
);
|
|
||||||
|
|
||||||
setString(parsed, 'proxy-url', values.proxyUrl);
|
setString(parsed, 'proxy-url', values.proxyUrl);
|
||||||
setBoolean(parsed, 'force-model-prefix', values.forceModelPrefix);
|
setBoolean(parsed, 'force-model-prefix', values.forceModelPrefix);
|
||||||
|
|||||||
@@ -882,9 +882,7 @@
|
|||||||
"logging_to_file_desc": "Save logs to rotating files",
|
"logging_to_file_desc": "Save logs to rotating files",
|
||||||
"usage_statistics": "Usage Statistics",
|
"usage_statistics": "Usage Statistics",
|
||||||
"usage_statistics_desc": "Collect usage statistics",
|
"usage_statistics_desc": "Collect usage statistics",
|
||||||
"logs_max_size": "Log File Size Limit (MB)",
|
"logs_max_size": "Log File Size Limit (MB)"
|
||||||
"usage_retention_days": "Usage Records Retention Days",
|
|
||||||
"usage_retention_hint": "0 means no limit (no cleanup)"
|
|
||||||
},
|
},
|
||||||
"network": {
|
"network": {
|
||||||
"title": "Network Configuration",
|
"title": "Network Configuration",
|
||||||
|
|||||||
@@ -882,9 +882,7 @@
|
|||||||
"logging_to_file_desc": "将日志保存到滚动文件",
|
"logging_to_file_desc": "将日志保存到滚动文件",
|
||||||
"usage_statistics": "使用统计",
|
"usage_statistics": "使用统计",
|
||||||
"usage_statistics_desc": "收集使用统计信息",
|
"usage_statistics_desc": "收集使用统计信息",
|
||||||
"logs_max_size": "日志文件大小限制 (MB)",
|
"logs_max_size": "日志文件大小限制 (MB)"
|
||||||
"usage_retention_days": "使用记录保留天数",
|
|
||||||
"usage_retention_hint": "0 为无限制(不清理)"
|
|
||||||
},
|
},
|
||||||
"network": {
|
"network": {
|
||||||
"title": "网络配置",
|
"title": "网络配置",
|
||||||
|
|||||||
@@ -80,9 +80,10 @@ export function ConfigPage() {
|
|||||||
try {
|
try {
|
||||||
const nextContent = activeTab === 'visual' ? applyVisualChangesToYaml(content) : content;
|
const nextContent = activeTab === 'visual' ? applyVisualChangesToYaml(content) : content;
|
||||||
await configFileApi.saveConfigYaml(nextContent);
|
await configFileApi.saveConfigYaml(nextContent);
|
||||||
|
const latestContent = await configFileApi.fetchConfigYaml();
|
||||||
setDirty(false);
|
setDirty(false);
|
||||||
setContent(nextContent);
|
setContent(latestContent);
|
||||||
loadVisualValuesFromYaml(nextContent);
|
loadVisualValuesFromYaml(latestContent);
|
||||||
showNotification(t('config_management.save_success'), 'success');
|
showNotification(t('config_management.save_success'), 'success');
|
||||||
} catch (err: unknown) {
|
} catch (err: unknown) {
|
||||||
const message = err instanceof Error ? err.message : '';
|
const message = err instanceof Error ? err.message : '';
|
||||||
|
|||||||
@@ -48,7 +48,6 @@ export type VisualConfigValues = {
|
|||||||
loggingToFile: boolean;
|
loggingToFile: boolean;
|
||||||
logsMaxTotalSizeMb: string;
|
logsMaxTotalSizeMb: string;
|
||||||
usageStatisticsEnabled: boolean;
|
usageStatisticsEnabled: boolean;
|
||||||
usageRecordsRetentionDays: string;
|
|
||||||
proxyUrl: string;
|
proxyUrl: string;
|
||||||
forceModelPrefix: boolean;
|
forceModelPrefix: boolean;
|
||||||
requestRetry: string;
|
requestRetry: string;
|
||||||
@@ -85,7 +84,6 @@ export const DEFAULT_VISUAL_VALUES: VisualConfigValues = {
|
|||||||
loggingToFile: false,
|
loggingToFile: false,
|
||||||
logsMaxTotalSizeMb: '',
|
logsMaxTotalSizeMb: '',
|
||||||
usageStatisticsEnabled: false,
|
usageStatisticsEnabled: false,
|
||||||
usageRecordsRetentionDays: '',
|
|
||||||
proxyUrl: '',
|
proxyUrl: '',
|
||||||
forceModelPrefix: false,
|
forceModelPrefix: false,
|
||||||
requestRetry: '',
|
requestRetry: '',
|
||||||
|
|||||||
Reference in New Issue
Block a user