'use client'; import {zodResolver} from '@hookform/resolvers/zod'; import {useMutation, useQuery, useQueryClient} from '@tanstack/react-query'; import {useEffect, useState} from 'react'; import {useForm} from 'react-hook-form'; import {ChevronDown, Loader2} from 'lucide-react'; import {Button} from '@/components/ui/button'; import {Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle,} from '@/components/ui/dialog'; import {Input} from '@/components/ui/input'; import {Label} from '@/components/ui/label'; import {Select, SelectContent, SelectItem, SelectTrigger, SelectValue,} from '@/components/ui/select'; import {Switch} from '@/components/ui/switch'; import {Textarea} from '@/components/ui/textarea'; import type {TlsCertificateItem} from '@/lib/services/openflare'; import {DnsAccountService, TlsCertificateService} from '@/lib/services/openflare'; import {type AcmeApplyFormValues, acmeApplySchema, defaultAcmeApplyValues,} from './schemas'; import {getErrorMessage} from './website-utils'; const certificatesQueryKey = ['openflare', 'tls-certificates']; type CertificateApplyMode = 'create' | 'edit-acme' | 'convert-upload'; interface CertificateApplyDialogProps { open: boolean; onOpenChange: (open: boolean) => void; onApplied?: (certificate: TlsCertificateItem) => void; mode?: CertificateApplyMode; certificate?: TlsCertificateItem | null; } export function CertificateApplyDialog({ open, onOpenChange, onApplied, mode = 'create', certificate, }: CertificateApplyDialogProps) { const queryClient = useQueryClient(); const [error, setError] = useState(''); const [showAdvanced, setShowAdvanced] = useState(false); const dnsAccountsQuery = useQuery({ queryKey: ['openflare', 'dns-accounts'], queryFn: () => DnsAccountService.list(), enabled: open, }); const defaultAcmeAccountQuery = useQuery({ queryKey: ['openflare', 'acme-accounts', 'default'], queryFn: () => TlsCertificateService.getDefaultAcmeAccount(), enabled: open, }); const form = useForm({ resolver: zodResolver(acmeApplySchema), defaultValues: defaultAcmeApplyValues, }); useEffect(() => { if (!open) return; setError(''); setShowAdvanced(false); if (certificate) { form.reset({ name: certificate.name, primary_domain: mode === 'convert-upload' ? '' : certificate.primary_domain || '', other_domains: mode === 'convert-upload' ? '' : certificate.other_domains || '', remark: certificate.remark || '', acme_account_id: mode === 'convert-upload' ? 0 : certificate.acme_account_id, dns_account_id: mode === 'convert-upload' ? 0 : certificate.dns_account_id, key_algorithm: certificate.key_algorithm || 'EC256', auto_renew: mode === 'convert-upload' ? true : certificate.auto_renew, dns1: mode === 'convert-upload' ? '' : certificate.dns1 || '', dns2: mode === 'convert-upload' ? '' : certificate.dns2 || '', disable_cname: mode === 'convert-upload' ? false : certificate.disable_cname, skip_dns: mode === 'convert-upload' ? false : certificate.skip_dns, }); if ( mode !== 'convert-upload' && (certificate.dns1 || certificate.dns2 || certificate.disable_cname || certificate.skip_dns) ) { setShowAdvanced(true); } } else { form.reset(defaultAcmeApplyValues); } }, [certificate, form, mode, open]); useEffect(() => { if (defaultAcmeAccountQuery.data && form.getValues('acme_account_id') === 0) { form.setValue('acme_account_id', defaultAcmeAccountQuery.data.id); } }, [defaultAcmeAccountQuery.data, form, open]); const applyMutation = useMutation({ mutationFn: (values: AcmeApplyFormValues) => { if (mode === 'edit-acme' && certificate) { return TlsCertificateService.updateAcme(certificate.id, values); } if (mode === 'convert-upload' && certificate) { return TlsCertificateService.convertToAcme(certificate.id, values); } return TlsCertificateService.apply(values); }, onSuccess: async (result) => { await queryClient.invalidateQueries({queryKey: certificatesQueryKey}); onApplied?.(result); onOpenChange(false); }, onError: (err) => setError(getErrorMessage(err)), }); const title = mode === 'edit-acme' ? '编辑并重新申请证书' : mode === 'convert-upload' ? '转换为申请证书' : '申请证书'; const description = mode === 'edit-acme' ? '修改 ACME 证书配置。保存后将使用新配置重新申请证书。' : mode === 'convert-upload' ? '填写 ACME 申请资料。申请成功后,当前手动证书会原地转换为可自动续签的申请证书。' : "使用 ACME (Let's Encrypt 等) 自动申请和续期证书,支持通配符域名。"; return ( {title} {description}
{ setError(''); applyMutation.mutate(values); })} > {error ?

{error}

: null}