Files
apikey-validator/frontend/src/components/ApiKeyForm.tsx
2025-09-05 21:07:34 +08:00

105 lines
3.2 KiB
TypeScript

import React, { useState } from 'react';
import { Plus, Loader2 } from 'lucide-react';
import { apiKeyService } from '../services/api';
import { cn } from '../utils/cn';
interface ApiKeyFormProps {
onSuccess: () => void;
}
export function ApiKeyForm({ onSuccess }: ApiKeyFormProps) {
const [formData, setFormData] = useState({
name: '',
key: '',
description: '',
});
const [isSubmitting, setIsSubmitting] = useState(false);
const [error, setError] = useState<string | null>(null);
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
setIsSubmitting(true);
setError(null);
try {
await apiKeyService.createApiKey(formData);
setFormData({ name: '', key: '', description: '' });
onSuccess();
} catch (err) {
setError(err instanceof Error ? err.message : '未知错误');
} finally {
setIsSubmitting(false);
}
};
return (
<form onSubmit={handleSubmit} className="space-y-4">
<div>
<label className="block text-sm font-medium mb-2">
API Key *
</label>
<input
type="text"
required
value={formData.name}
onChange={(e) => setFormData({ ...formData, name: e.target.value })}
className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
placeholder="例如: 生产环境 API"
/>
</div>
<div>
<label className="block text-sm font-medium mb-2">
API Key *
</label>
<input
type="password"
required
value={formData.key}
onChange={(e) => setFormData({ ...formData, key: e.target.value })}
className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 font-mono text-sm"
placeholder="sk-... 或sf-xxxxx"
/>
</div>
<div>
<label className="block text-sm font-medium mb-2">
()
</label>
<textarea
value={formData.description}
onChange={(e) => setFormData({ ...formData, description: e.target.value })}
className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
rows={2}
placeholder="用于管理此API Key的描述信息"
/>
</div>
{error && (
<div className="px-3 py-2 bg-red-100 border border-red-300 rounded-md text-red-700 text-sm">
{error}
</div>
)}
<button
type="submit"
disabled={isSubmitting}
className={cn(
"w-full flex items-center justify-center px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 disabled:opacity-50 disabled:cursor-not-allowed"
)}
>
{isSubmitting ? (
<>
<Loader2 className="w-4 h-4 mr-2 animate-spin" />
...
</>
) : (
<>
<Plus className="w-4 h-4 mr-2" />
API Key
</>
)}
</button>
</form>
);
}