import { useState, useEffect, useCallback } from "react" import { Plus, Trash2, Shield, ShieldAlert, Key } from "lucide-react" import { Button } from "@/components/ui/button" import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "@/components/ui/table" import { Badge } from "@/components/ui/badge" import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from "@/components/ui/dialog" import { Input } from "@/components/ui/input" import { Label } from "@/components/ui/label" import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select" import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, } from "@/components/ui/alert-dialog" import { fetchAdmins, createAdmin, deleteAdmin, resetAdminPassword } from "@/lib/api/admin-api" import { ADMIN_ROLE_LABELS } from "@/lib/constants" import type { Admin, AdminRole, CreateAdminForm } from "@/types/admin" const roleIcons = { admin: Shield, moderator: ShieldAlert, } const roleBadgeVariants: Record = { admin: "default", moderator: "secondary", } export default function AdminsPage() { const [admins, setAdmins] = useState([]) const [loading, setLoading] = useState(true) const [dialogOpen, setDialogOpen] = useState(false) const [deleteOpen, setDeleteOpen] = useState(false) const [resetPasswordOpen, setResetPasswordOpen] = useState(false) const [selectedAdmin, setSelectedAdmin] = useState(null) const [submitting, setSubmitting] = useState(false) // 表单状态 const [formData, setFormData] = useState({ username: "", password: "", role: "moderator", }) // 重置密码表单 const [resetPasswordData, setResetPasswordData] = useState({ newPassword: "", confirmPassword: "", }) const loadAdmins = useCallback(async () => { setLoading(true) try { const res = await fetchAdmins() setAdmins(res.data) } catch { setAdmins([]) } finally { setLoading(false) } }, []) useEffect(() => { loadAdmins() }, [loadAdmins]) function openCreateDialog() { setSelectedAdmin(null) setFormData({ username: "", password: "", role: "moderator", }) setDialogOpen(true) } function openDeleteDialog(admin: Admin) { setSelectedAdmin(admin) setDeleteOpen(true) } function openResetPasswordDialog(admin: Admin) { setSelectedAdmin(admin) setResetPasswordData({ newPassword: "", confirmPassword: "" }) setResetPasswordOpen(true) } async function handleSubmit() { if (!formData.password) { return } setSubmitting(true) try { await createAdmin(formData) setDialogOpen(false) await loadAdmins() } finally { setSubmitting(false) } } async function handleDelete() { if (!selectedAdmin) return await deleteAdmin(selectedAdmin.id) setDeleteOpen(false) setSelectedAdmin(null) await loadAdmins() } async function handleResetPassword() { if (!selectedAdmin || resetPasswordData.newPassword !== resetPasswordData.confirmPassword) { return } setSubmitting(true) try { await resetAdminPassword(selectedAdmin.id, resetPasswordData.newPassword) setResetPasswordOpen(false) // TODO: 显示成功提示 } finally { setSubmitting(false) } } // 获取当前管理员的信息(从 localStorage) const currentAdminId = localStorage.getItem("duoqi_admin_current_id") return ( <>

管理员管理

管理后台管理员账号和权限

用户名 角色 创建时间 最后登录 操作 {loading ? ( 加载中... ) : admins.length === 0 ? ( 暂无管理员账号 ) : ( admins.map((admin) => { const RoleIcon = roleIcons[admin.role] const isCurrentUser = admin.id === currentAdminId return (
{admin.username} {isCurrentUser && ( 当前账号 )}
{ADMIN_ROLE_LABELS[admin.role]} {new Date(admin.createdAt).toLocaleString("zh-CN")} {admin.lastLoginAt ? new Date(admin.lastLoginAt).toLocaleString("zh-CN") : "从未登录"}
) }) )}
{/* 创建管理员对话框 */} 新建管理员 创建新的管理员账号,请妥善保管密码
setFormData({ ...formData, username: e.target.value })} placeholder="请输入用户名" />
setFormData({ ...formData, password: e.target.value })} placeholder="请输入密码(至少 6 位)" />
{/* 删除确认 */} 确认删除 确定要删除管理员"{selectedAdmin?.username}"吗?此操作不可撤销。 取消 删除 {/* 重置密码对话框 */} 重置密码 为管理员"{selectedAdmin?.username}"设置新密码
setResetPasswordData({ ...resetPasswordData, newPassword: e.target.value }) } placeholder="请输入新密码(至少 6 位)" />
setResetPasswordData({ ...resetPasswordData, confirmPassword: e.target.value }) } placeholder="请再次输入新密码" /> {resetPasswordData.newPassword !== resetPasswordData.confirmPassword && (

两次输入的密码不一致

)}
) }