'use client'; import Link from 'next/link'; import {useMemo} from 'react'; import {ExternalLink, FileKey} from 'lucide-react'; import {EmptyStateWithBorder} from '@/components/layout/empty'; import {Badge} from '@/components/ui/badge'; import {Button} from '@/components/ui/button'; import {Card, CardContent, CardDescription, CardHeader, CardTitle} from '@/components/ui/card'; import {Table, TableBody, TableCell, TableHead, TableHeader, TableRow} from '@/components/ui/table'; import type {TlsCertificateItem, ZoneDomainItem} from '@/lib/services/openflare'; import {formatDateTime} from '@/lib/utils'; import {getCertificateStatus} from '../../components/website-utils'; export function ZoneCertificatesPanel({ domains, certificates, }: { domains: ZoneDomainItem[]; certificates: TlsCertificateItem[]; }) { const certificateMap = useMemo( () => new Map(certificates.map((certificate) => [certificate.id, certificate])), [certificates], ); const boundCertificates = useMemo(() => { const rows = new Map< number, {certificate: TlsCertificateItem; domains: ZoneDomainItem[]} >(); for (const domain of domains) { if (domain.cert_id == null) { continue; } const certificate = certificateMap.get(domain.cert_id); if (!certificate) { continue; } const existing = rows.get(certificate.id); if (existing) { existing.domains.push(domain); } else { rows.set(certificate.id, {certificate, domains: [domain]}); } } return Array.from(rows.values()).sort((left, right) => left.certificate.name.localeCompare(right.certificate.name), ); }, [certificateMap, domains]); const unboundCount = domains.filter((domain) => domain.cert_id == null).length; return (
还有 {unboundCount} 个域名未绑定证书,可在「域名」Tab 中选择证书。
) : null} {boundCertificates.length === 0 ? (