'use client'; import Link from 'next/link'; import { useEffect, useMemo, useState } from 'react'; import { useMutation, useQueryClient } from '@tanstack/react-query'; import { Expand, Loader2, Pencil, Save } from 'lucide-react'; import { toast } from 'sonner'; import { Button } from '@/components/ui/button'; import { Card, CardContent, CardDescription, CardHeader, CardTitle, } from '@/components/ui/card'; import { Label } from '@/components/ui/label'; import { Switch } from '@/components/ui/switch'; import { TagsInput } from '@/components/ui/tags-input'; import { previewOriginErrorPageHTML } from '@/lib/openflare/default-origin-error-page-html'; import { validateStatusCodeTagMessage, validateStatusCodeTags, } from '@/lib/openflare/status-code-tags'; import { OptionService } from '@/lib/services/openflare'; import { defaultErrorPageFields, invalidateResponseQueries, KEY_ENABLED, KEY_GET_ONLY, KEY_STATUS_CODES, mapOptionsToErrorFields, type ErrorPageFields, } from './shared'; export function ErrorPageTab({ optionMap, }: { optionMap: Record; }) { const queryClient = useQueryClient(); const [fields, setFields] = useState(defaultErrorPageFields); const [tagError, setTagError] = useState(null); useEffect(() => { setFields(mapOptionsToErrorFields(optionMap)); setTagError(null); }, [optionMap]); const previewSrcDoc = useMemo( () => previewOriginErrorPageHTML(fields.html), [fields.html], ); /** 仅保存策略项 */ const savePolicyMutation = useMutation({ mutationFn: async () => { validateStatusCodeTags(fields.statusCodes); await OptionService.updateBatch([ { key: KEY_ENABLED, value: String(fields.enabled) }, { key: KEY_GET_ONLY, value: String(fields.getOnly) }, { key: KEY_STATUS_CODES, value: JSON.stringify(fields.statusCodes), }, ]); }, onSuccess: async () => { toast.success('触发策略已保存,请前往版本发布使配置生效'); await invalidateResponseQueries(queryClient); }, onError: (error) => { toast.error(error instanceof Error ? error.message : '保存失败'); }, }); const handleValidateTag = (tag: string) => { const message = validateStatusCodeTagMessage(tag); if (message) { setTagError(message); toast.error(message); return message; } setTagError(null); return null; }; return (
触发策略 配置源站错误页的启用条件与触发状态码。修改后需点击保存。

关闭后会透传源站或 Nginx 默认错误响应。

setFields((prev) => ({ ...prev, enabled })) } aria-label='启用源站错误页' className='mt-0.5 shrink-0' />

开启后仅对 GET 请求的匹配错误状态码返回自定义错误页;POST/PUT 等其它方法直接透传源站响应。

setFields((prev) => ({ ...prev, getOnly })) } aria-label='仅针对 GET 请求' className='mt-0.5 shrink-0' />

支持单码(如 502)或闭区间(如 500-599),范围 400–599。默认 500-599。

{ setFields((prev) => ({ ...prev, statusCodes })); setTagError(null); }} validateTag={handleValidateTag} placeholder='例如 502 或 500-599,回车添加' aria-invalid={!!tagError} disabled={!fields.enabled} /> {tagError ? (

{tagError}

) : null}
页面预览