From 557aef7a7f9a3bc98ff98afc98363508c988fa68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=8F=E8=B4=BA?= Date: Sat, 6 Sep 2025 12:35:13 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9api=E6=98=BE=E7=A4=BA?= =?UTF-8?q?=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/components/ApiKeyCard.tsx | 57 ++++++++++++++++++++++---- 1 file changed, 48 insertions(+), 9 deletions(-) diff --git a/frontend/src/components/ApiKeyCard.tsx b/frontend/src/components/ApiKeyCard.tsx index 38c019b..75d3b0a 100644 --- a/frontend/src/components/ApiKeyCard.tsx +++ b/frontend/src/components/ApiKeyCard.tsx @@ -1,5 +1,5 @@ import React, { useState } from 'react'; -import { CheckCircle2, XCircle, Loader2, Trash2, RefreshCw } from 'lucide-react'; +import { CheckCircle2, XCircle, Loader2, Trash2, RefreshCw, Copy, Eye, EyeOff } from 'lucide-react'; import { apiKeyService } from '../services/api'; import type { ApiKey } from '../types/api'; @@ -12,6 +12,8 @@ interface ApiKeyCardProps { export function ApiKeyCard({ apiKey, onUpdate, onDelete }: ApiKeyCardProps) { const [isValidating, setIsValidating] = useState(false); const [isDeleting, setIsDeleting] = useState(false); + const [showFullKey, setShowFullKey] = useState(false); + const [copied, setCopied] = useState(false); const handleValidate = async () => { setIsValidating(true); @@ -41,6 +43,16 @@ export function ApiKeyCard({ apiKey, onUpdate, onDelete }: ApiKeyCardProps) { } }; + const handleCopy = async () => { + try { + await navigator.clipboard.writeText(apiKey.key); + setCopied(true); + setTimeout(() => setCopied(false), 2000); + } catch (error) { + console.error('复制失败:', error); + } + }; + const formatCurrency = (amount: number) => { return new Intl.NumberFormat('zh-CN', { style: 'currency', @@ -54,6 +66,14 @@ export function ApiKeyCard({ apiKey, onUpdate, onDelete }: ApiKeyCardProps) { return new Date(dateString).toLocaleString('zh-CN'); }; + const maskApiKey = (key: string) => { + if (key.length <= 8) return key; // 如果很短就直接显示 + const start = key.slice(0, 4); + const end = key.slice(-4); + const masked = '*'.repeat(Math.max(0, key.length - 8)); + return showFullKey ? key : `${start}${masked}${end}`; + }; + return (
@@ -69,11 +89,25 @@ export function ApiKeyCard({ apiKey, onUpdate, onDelete }: ApiKeyCardProps) { )}
-
+
+ +
- {/* 直接显示完整的API Key */} -
+ {/* API Key 显示区域 */} +
-
- {apiKey.key} +
+
+ {maskApiKey(apiKey.key)} +
- {apiKey.error ? ( + {apiKey.error && (

{apiKey.error}

- ) : null} + )} {apiKey.balance !== undefined && (