diff --git a/atsf_server/web/features/performance/components/performance-page.tsx b/atsf_server/web/features/performance/components/performance-page.tsx index 6e4e426f..0e9515fe 100644 --- a/atsf_server/web/features/performance/components/performance-page.tsx +++ b/atsf_server/web/features/performance/components/performance-page.tsx @@ -111,6 +111,13 @@ function isCacheLevelsValue(value: string) { return /^\d{1,2}(?::\d{1,2}){0,2}$/.test(value.trim()); } +function extractMainConfigLines(content: string, matcher: RegExp) { + return content + .split('\n') + .map((line) => line.trim()) + .filter((line) => line && matcher.test(line)); +} + export function PerformancePage() { const queryClient = useQueryClient(); const { user } = useAuth(); @@ -357,16 +364,6 @@ export function PerformancePage() { const handleCacheSave = () => { void runBusyAction('performance-cache', async () => { - if (!isPositiveInteger(performanceFields.OpenRestyGzipMinLength)) { - throw new Error('gzip_min_length 必须为大于 0 的整数。'); - } - const gzipLevel = Number.parseInt( - performanceFields.OpenRestyGzipCompLevel, - 10, - ); - if (Number.isNaN(gzipLevel) || gzipLevel < 1 || gzipLevel > 9) { - throw new Error('gzip_comp_level 必须在 1 到 9 之间。'); - } if (performanceFields.OpenRestyCacheEnabled) { if (!performanceFields.OpenRestyCachePath.trim()) { throw new Error('启用缓存时必须填写 proxy_cache_path 目录。'); @@ -388,18 +385,6 @@ export function PerformancePage() { await saveOptionEntries( [ - [ - 'OpenRestyGzipEnabled', - String(performanceFields.OpenRestyGzipEnabled), - ], - [ - 'OpenRestyGzipMinLength', - performanceFields.OpenRestyGzipMinLength.trim(), - ], - [ - 'OpenRestyGzipCompLevel', - performanceFields.OpenRestyGzipCompLevel.trim(), - ], ['OpenRestyCachePath', performanceFields.OpenRestyCachePath.trim()], [ 'OpenRestyCacheLevels', @@ -439,6 +424,39 @@ export function PerformancePage() { }); }; + const handleGzipSave = () => { + void runBusyAction('performance-gzip', async () => { + if (!isPositiveInteger(performanceFields.OpenRestyGzipMinLength)) { + throw new Error('gzip_min_length 必须为大于 0 的整数。'); + } + const gzipLevel = Number.parseInt( + performanceFields.OpenRestyGzipCompLevel, + 10, + ); + if (Number.isNaN(gzipLevel) || gzipLevel < 1 || gzipLevel > 9) { + throw new Error('gzip_comp_level 必须在 1 到 9 之间。'); + } + + await saveOptionEntries( + [ + [ + 'OpenRestyGzipEnabled', + String(performanceFields.OpenRestyGzipEnabled), + ], + [ + 'OpenRestyGzipMinLength', + performanceFields.OpenRestyGzipMinLength.trim(), + ], + [ + 'OpenRestyGzipCompLevel', + performanceFields.OpenRestyGzipCompLevel.trim(), + ], + ], + 'OpenResty 压缩参数已保存。', + ); + }); + }; + const handleTemplateSave = () => { void runBusyAction('performance-template', async () => { await saveOptionEntries( @@ -495,6 +513,15 @@ export function PerformancePage() { ); } + const cachePreviewLines = extractMainConfigLines( + preview.main_config, + /proxy_cache_path|proxy_cache_key|proxy_cache_lock(?:_timeout)?|proxy_cache_use_stale/, + ); + const gzipPreviewLines = extractMainConfigLines( + preview.main_config, + /gzip(?:_| )/, + ); + return (
- - {busyKey === 'performance-cache' - ? '保存中...' - : '保存压缩与缓存'} - - } - > -
-
- - setPerformanceFields((previous) => ({ - ...previous, - OpenRestyGzipEnabled: checked, - })) - } - /> - - setPerformanceFields((previous) => ({ - ...previous, - OpenRestyCacheEnabled: checked, - })) - } - /> - - +
+ + {busyKey === 'performance-gzip' + ? '保存中...' + : '保存压缩设置'} + + } + > +
+
+ setPerformanceFields((previous) => ({ ...previous, - OpenRestyGzipMinLength: event.target.value, + OpenRestyGzipEnabled: checked, })) } /> - - - - setPerformanceFields((previous) => ({ - ...previous, - OpenRestyGzipCompLevel: event.target.value, - })) - } - /> - +
+

+ 当前压缩预览 +

+ {gzipPreviewLines.length > 0 ? ( + + {gzipPreviewLines.join('\n')} + + ) : ( +

+ 当前主配置预览中没有压缩指令。 +

+ )} +
+ + + setPerformanceFields((previous) => ({ + ...previous, + OpenRestyGzipMinLength: event.target.value, + })) + } + /> + + + + setPerformanceFields((previous) => ({ + ...previous, + OpenRestyGzipCompLevel: event.target.value, + })) + } + /> + +
-
- - + + + + setPerformanceFields((previous) => ({ ...previous, - OpenRestyCachePath: event.target.value, + OpenRestyCacheEnabled: + !previous.OpenRestyCacheEnabled, })) } - placeholder="/var/cache/openresty/atsflare" - /> - - - - setPerformanceFields((previous) => ({ - ...previous, - OpenRestyCacheLevels: event.target.value, - })) + > + {performanceFields.OpenRestyCacheEnabled + ? '先关闭缓存' + : '先启用缓存'} + + + {busyKey === 'performance-cache' + ? '保存中...' + : performanceFields.OpenRestyCacheEnabled + ? '保存缓存设置' + : '保存为关闭状态'} + +
+ } + > +
+
+
+

+ 缓存状态 +

+
+ + +
+

+ `max_size` 会跟随 `proxy_cache_path` + 一起渲染,不会单独占一行。 +

+
+ +
+

+ 当前缓存预览 +

+ {cachePreviewLines.length > 0 ? ( + + {cachePreviewLines.join('\n')} + + ) : ( +

+ 当前主配置预览中没有缓存指令。启用缓存并保存后,会出现 + `proxy_cache_path ... max_size=...;` 这一行。 +

+ )} +
+
+ +
+ - - - + > + + setPerformanceFields((previous) => ({ + ...previous, + OpenRestyCachePath: event.target.value, + })) + } + placeholder="/var/cache/openresty/atsflare" + /> + + + + setPerformanceFields((previous) => ({ + ...previous, + OpenRestyCacheLevels: event.target.value, + })) + } + placeholder="1:2" + /> + + + + setPerformanceFields((previous) => ({ + ...previous, + OpenRestyCacheInactive: event.target.value, + })) + } + placeholder="30m" + /> + + + + setPerformanceFields((previous) => ({ + ...previous, + OpenRestyCacheMaxSize: event.target.value, + })) + } + placeholder="1g" + /> + + + + setPerformanceFields((previous) => ({ + ...previous, + OpenRestyCacheKeyTemplate: event.target.value, + })) + } + /> + + setPerformanceFields((previous) => ({ ...previous, - OpenRestyCacheInactive: event.target.value, - })) - } - placeholder="30m" - /> - - - - setPerformanceFields((previous) => ({ - ...previous, - OpenRestyCacheMaxSize: event.target.value, - })) - } - placeholder="1g" - /> - - - - setPerformanceFields((previous) => ({ - ...previous, - OpenRestyCacheKeyTemplate: event.target.value, + OpenRestyCacheLockEnabled: checked, })) } /> - - - setPerformanceFields((previous) => ({ - ...previous, - OpenRestyCacheLockEnabled: checked, - })) - } - /> - - - setPerformanceFields((previous) => ({ - ...previous, - OpenRestyCacheLockTimeout: event.target.value, - })) - } - placeholder="5s" - /> - - - - setPerformanceFields((previous) => ({ - ...previous, - OpenRestyCacheUseStale: event.target.value, - })) - } - /> - + + + setPerformanceFields((previous) => ({ + ...previous, + OpenRestyCacheLockTimeout: event.target.value, + })) + } + placeholder="5s" + /> + + + + setPerformanceFields((previous) => ({ + ...previous, + OpenRestyCacheUseStale: event.target.value, + })) + } + /> + +
-
- + +
) : (