'use client'; import { useEffect } from 'react'; import { zodResolver } from '@hookform/resolvers/zod'; import { useForm } from 'react-hook-form'; import { z } from 'zod'; import { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage, } from '@/components/ui/form'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '@/components/ui/select'; import { Switch } from '@/components/ui/switch'; import { Textarea } from '@/components/ui/textarea'; import type { ProxyRouteItem } from '@/lib/services/openflare'; import { linesFromTextarea, validateCacheRules, } from '../../components/helpers'; import { proxyRouteFormIds } from '../helpers'; import { useRouteSectionSave } from '../hooks/use-route-section-save'; import { SectionShell } from './section-shell'; const cacheSchema = z .object({ cache_enabled: z.boolean(), cache_policy: z.enum(['url', 'suffix', 'path_prefix', 'path_exact']), cache_rules_text: z.string(), }) .superRefine((value, context) => { if (!value.cache_enabled) { return; } const rules = linesFromTextarea(value.cache_rules_text); const error = validateCacheRules(value.cache_policy, rules); if (error) { context.addIssue({ code: z.ZodIssueCode.custom, path: ['cache_rules_text'], message: error, }); } }); type CacheValues = z.infer; interface CacheSectionProps { route: ProxyRouteItem; onRouteUpdate: (route: ProxyRouteItem) => void; onSavingChange?: (saving: boolean) => void; } export function CacheSection({ route, onRouteUpdate, onSavingChange, }: CacheSectionProps) { const { saving, save } = useRouteSectionSave( route, onRouteUpdate, onSavingChange, ); const form = useForm({ resolver: zodResolver(cacheSchema), defaultValues: { cache_enabled: route.cache_enabled, cache_policy: (route.cache_policy || 'url') as CacheValues['cache_policy'], cache_rules_text: route.cache_rule_list.join('\n'), }, }); useEffect(() => { form.reset({ cache_enabled: route.cache_enabled, cache_policy: (route.cache_policy || 'url') as CacheValues['cache_policy'], cache_rules_text: route.cache_rule_list.join('\n'), }); }, [form, route]); const watchedEnabled = form.watch('cache_enabled'); const watchedPolicy = form.watch('cache_policy'); const rulesHint = watchedPolicy === 'suffix' ? '每行一个后缀,例如 jpg、css、js。' : watchedPolicy === 'path_prefix' ? '每行一个路径前缀,例如 /assets、/static。' : watchedPolicy === 'path_exact' ? '每行一个精确路径,例如 /robots.txt。' : '按 URL 缓存时无需额外规则。'; const rulesPlaceholder = watchedPolicy === 'suffix' ? 'jpg\ncss\njs' : watchedPolicy === 'path_prefix' ? '/assets\n/static' : watchedPolicy === 'path_exact' ? '/robots.txt\n/manifest.json' : '按 URL 缓存时无需额外规则'; return (
{ const rules = linesFromTextarea(values.cache_rules_text); await save( { cache_enabled: values.cache_enabled, cache_policy: values.cache_enabled ? values.cache_policy : 'url', cache_rules: values.cache_enabled && values.cache_policy !== 'url' ? rules : [], }, '缓存设置已保存', ); })} > (
启用站点缓存 系统仍会自动绕过非 GET、带 Authorization 或常见登录态 Cookie 的请求。
)} /> ( 缓存策略 )} /> ( 缓存规则