import { useState, useEffect } from 'react'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import { Card, CardContent } from '@/components/ui/card'; import { Badge } from '@/components/ui/badge'; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from '@/components/ui/dialog'; import { Plus, Search, Edit2, Trash2, Globe, CheckCircle2, XCircle, Clock, RefreshCw, Loader2, } from 'lucide-react'; import { cloudApi } from '@/services/api'; export function DomainManager() { const [domains, setDomains] = useState([]); const [loading, setLoading] = useState(true); const [searchQuery, setSearchQuery] = useState(''); const [selectedStatus, setSelectedStatus] = useState('all'); // 创建/编辑域名表单状态 const [formOpen, setFormOpen] = useState(false); const [submitting, setSubmitting] = useState(false); const [editingDomain, setEditingDomain] = useState(null); const [formData, setFormData] = useState({ name: '', registrar: '', status: 'active', expire_date: '', dns_provider: '', record_count: '', ssl_enabled: false, ssl_expire_date: '', }); const resetForm = () => { setEditingDomain(null); setFormData({ name: '', registrar: '', status: 'active', expire_date: '', dns_provider: '', record_count: '', ssl_enabled: false, ssl_expire_date: '', }); }; const handleOpenCreate = () => { resetForm(); setFormOpen(true); }; const handleOpenEdit = (domain: any) => { setEditingDomain(domain); // 后端返回 RFC3339 时间,截取 YYYY-MM-DD 部分给 date input const toDateInput = (v: string) => (v ? v.substring(0, 10) : ''); setFormData({ name: domain.name || '', registrar: domain.registrar || '', status: domain.status || 'active', expire_date: toDateInput(domain.expire_date || ''), dns_provider: domain.dns_provider || domain.dnsProvider || '', record_count: String(domain.record_count ?? domain.recordCount ?? ''), ssl_enabled: domain.ssl_enabled ?? domain.sslEnabled ?? false, ssl_expire_date: toDateInput(domain.ssl_expire_date || ''), }); setFormOpen(true); }; const handleSubmit = async () => { if (!formData.name.trim()) return; try { setSubmitting(true); const payload: any = { name: formData.name.trim(), registrar: formData.registrar.trim(), status: formData.status, expire_date: formData.expire_date, dns_provider: formData.dns_provider.trim(), record_count: Number(formData.record_count) || 0, ssl_enabled: formData.ssl_enabled, ssl_expire_date: formData.ssl_expire_date, }; if (editingDomain) { await cloudApi.updateDomain(editingDomain.id, payload); } else { await cloudApi.createDomain(payload); } setFormOpen(false); loadData(); } catch (e) { console.error(editingDomain ? '更新域名失败:' : '创建域名失败:', e); } finally { setSubmitting(false); } }; const loadData = async () => { try { setLoading(true); const res: any = await cloudApi.getDomains(); setDomains(res?.list || []); } catch (e) { console.error('加载域名列表失败:', e); setDomains([]); } finally { setLoading(false); } }; useEffect(() => { loadData(); }, []); const handleDelete = async (id: string) => { try { await cloudApi.deleteDomain(id); loadData(); } catch (e) { console.error('删除域名失败:', e); } }; const filteredDomains = domains.filter(domain => { const matchesSearch = (domain.name || '').toLowerCase().includes(searchQuery.toLowerCase()) || (domain.registrar || '').toLowerCase().includes(searchQuery.toLowerCase()); const matchesStatus = selectedStatus === 'all' || domain.status === selectedStatus; return matchesSearch && matchesStatus; }); const stats = { total: domains.length, active: domains.filter(d => d.status === 'active').length, expired: domains.filter(d => d.status === 'expired').length, pending: domains.filter(d => d.status === 'pending').length, sslEnabled: domains.filter(d => d.ssl_enabled || d.sslEnabled).length, }; const getDaysUntilExpiry = (expireDate: string) => { if (!expireDate) return Infinity; const days = Math.ceil((new Date(expireDate).getTime() - Date.now()) / (1000 * 60 * 60 * 24)); return days; }; return (
{/* Header */}

域名管理

管理域名注册信息和DNS解析记录

{/* Stats */}

域名总数

{stats.total}

正常

{stats.active}

已过期

{stats.expired}

待审核

{stats.pending}

SSL证书

{stats.sslEnabled}

{/* Filters */}
setSearchQuery(e.target.value)} className="pl-10 bg-slate-800 border-slate-700 text-slate-100" />
{/* Domain List */} {loading ? ( 加载中... ) : filteredDomains.length === 0 ? ( 暂无域名数据 ) : (
{filteredDomains.map((domain) => { const sslEnabled = domain.ssl_enabled || domain.sslEnabled; const expireDate = domain.expire_date || domain.expireDate || ''; const sslExpireDate = domain.ssl_expire_date || domain.sslExpireDate || ''; const daysUntilExpiry = getDaysUntilExpiry(expireDate); return (

{domain.name}

{domain.status === 'active' && ( 正常 )} {domain.status === 'expired' && ( 已过期 )} {domain.status === 'pending' && ( 待审核 )} {sslEnabled && ( SSL )}
注册商: {domain.registrar || '-'} DNS: {domain.dns_provider || domain.dnsProvider || '-'} 解析记录: {domain.record_count ?? domain.recordCount ?? 0}条

到期时间

{expireDate ? expireDate.substring(0, 10) : '-'}{expireDate && ` (${daysUntilExpiry}天)`} {sslEnabled && sslExpireDate && ( · SSL: {sslExpireDate.substring(0, 10)} )}

); })}
)} {/* 创建/编辑域名 Dialog */} {editingDomain ? '编辑域名' : '添加域名'} {editingDomain ? '修改域名注册信息、DNS 配置和 SSL 证书状态' : '录入域名信息,包括注册商、DNS 服务商和到期时间'}
setFormData({ ...formData, name: e.target.value })} className="bg-slate-900 border-slate-700 text-slate-100" />
setFormData({ ...formData, registrar: e.target.value })} className="bg-slate-900 border-slate-700 text-slate-100" />
setFormData({ ...formData, expire_date: e.target.value })} className="bg-slate-900 border-slate-700 text-slate-100" />
setFormData({ ...formData, dns_provider: e.target.value })} className="bg-slate-900 border-slate-700 text-slate-100" />
setFormData({ ...formData, record_count: e.target.value })} className="bg-slate-900 border-slate-700 text-slate-100" />
setFormData({ ...formData, ssl_expire_date: e.target.value })} disabled={!formData.ssl_enabled} className="bg-slate-900 border-slate-700 text-slate-100 disabled:opacity-40" />
); }