From 06d4831d5527e3692fab37fb2e56d421f1970b7c Mon Sep 17 00:00:00 2001 From: ryan Date: Fri, 13 Mar 2026 14:20:51 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E8=AF=81=E4=B9=A6PEM?= =?UTF-8?q?=E5=92=8C=E7=A7=81=E9=92=A5PEM=E5=A4=8D=E5=88=B6=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=EF=BC=8C=E4=BC=98=E5=8C=96=E8=AF=81=E4=B9=A6=E8=AF=A6?= =?UTF-8?q?=E6=83=85=E6=A8=A1=E6=80=81=E6=A1=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/certificate-detail-modal.tsx | 56 ++++++++++++++++--- 1 file changed, 49 insertions(+), 7 deletions(-) diff --git a/atsf_server/web/features/websites/components/certificate-detail-modal.tsx b/atsf_server/web/features/websites/components/certificate-detail-modal.tsx index e8e8f54a..caff7584 100644 --- a/atsf_server/web/features/websites/components/certificate-detail-modal.tsx +++ b/atsf_server/web/features/websites/components/certificate-detail-modal.tsx @@ -1,9 +1,11 @@ 'use client'; import { useQuery } from '@tanstack/react-query'; +import { useState } from 'react'; import { EmptyState } from '@/components/feedback/empty-state'; import { ErrorState } from '@/components/feedback/error-state'; +import { InlineMessage } from '@/components/feedback/inline-message'; import { LoadingState } from '@/components/feedback/loading-state'; import { AppModal } from '@/components/ui/app-modal'; import { StatusBadge } from '@/components/ui/status-badge'; @@ -37,6 +39,8 @@ export function CertificateDetailModal({ onDelete, deleting = false, }: CertificateDetailModalProps) { + const [copyMessage, setCopyMessage] = useState(null); + const certificateQuery = useQuery({ queryKey: ['tls-certificates', 'detail', certificateId], queryFn: () => getTlsCertificate(certificateId as number), @@ -53,10 +57,22 @@ export function CertificateDetailModal({ const content = contentQuery.data; const status = certificate ? getCertificateStatus(certificate) : null; + const handleCopy = async (value: string, message: string) => { + try { + await navigator.clipboard.writeText(value); + setCopyMessage(message); + } catch (error) { + setCopyMessage(getErrorMessage(error)); + } + }; + return ( { + setCopyMessage(null); + onClose(); + }} title="证书详情" description="查看证书元信息、备注以及当前保存的 PEM 内容。" size="xl" @@ -82,6 +98,10 @@ export function CertificateDetailModal({ } > + {copyMessage ? ( + + ) : null} + {certificateQuery.isLoading || contentQuery.isLoading ? ( ) : certificateQuery.isError || contentQuery.isError ? ( @@ -146,17 +166,39 @@ export function CertificateDetailModal({
-

- 证书 PEM -

+
+

+ 证书 PEM +

+ + void handleCopy(content.cert_pem, '证书 PEM 已复制。') + } + > + 复制 + +
{content.cert_pem}
-

- 私钥 PEM -

+
+

+ 私钥 PEM +

+ + void handleCopy(content.key_pem, '私钥 PEM 已复制。') + } + > + 复制 + +
{content.key_pem}