"use client"; import { useState } from "react"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Badge } from "@/components/ui/badge"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from "@/components/ui/dialog"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "@/components/ui/table"; import { fetchWithAuth } from "@/lib/api/client"; import type { AdminStatsData, AdminUser, AdminUserListResponse, AdminActionResponse } from "@/lib/api/admin"; import { useApi } from "@/lib/hooks/use-api"; import { LoadingState, ErrorState } from "@/components/ui/api-states"; import { clsx } from "clsx"; import { Users, Search, Quote, Percent, Loader2, AlertTriangle, CheckCircle, Ban, UserCheck, ChevronLeft, ChevronRight, } from "lucide-react"; const PLAN_OPTIONS = [ { value: "free", label: "免费版" }, { value: "starter", label: "入门版" }, { value: "pro", label: "专业版" }, { value: "business", label: "企业版" }, ]; const LIMIT = 10; export default function AdminPage() { const [skip, setSkip] = useState(0); const [search, setSearch] = useState(""); const [mutationError, setMutationError] = useState(null); const [success, setSuccess] = useState(null); const [dialogOpen, setDialogOpen] = useState(false); const [dialogType, setDialogType] = useState<"toggle" | "plan">("toggle"); const [selectedUser, setSelectedUser] = useState(null); const [selectedPlan, setSelectedPlan] = useState(""); const [actionLoading, setActionLoading] = useState(false); const { data: stats, isLoading: loadingStats, error: statsError } = useApi("/api/v1/admin/stats"); const usersUrl = `/api/v1/admin/users?skip=${skip}&limit=${LIMIT}${search ? `&search=${encodeURIComponent(search)}` : ""}`; const { data: usersData, isLoading: loadingUsers, error: usersError, refresh: refreshUsers } = useApi(usersUrl); const users: AdminUser[] = usersData?.items ?? []; const totalUsers = usersData?.total ?? 0; const error = mutationError || statsError?.message || usersError?.message || null; function openToggleDialog(user: AdminUser) { setSelectedUser(user); setDialogType("toggle"); setDialogOpen(true); } function openPlanDialog(user: AdminUser) { setSelectedUser(user); setSelectedPlan(user.plan); setDialogType("plan"); setDialogOpen(true); } async function handleConfirm() { if (!selectedUser) return; setActionLoading(true); setSuccess(null); setMutationError(null); try { if (dialogType === "toggle") { const res = await fetchWithAuth( `/api/v1/admin/users/${selectedUser.id}/toggle-active`, { method: "POST" } ) as AdminActionResponse; setSuccess(res.message || "操作成功"); } else { const res = await fetchWithAuth( `/api/v1/admin/users/${selectedUser.id}/update-plan`, { method: "PUT", body: JSON.stringify({ plan: selectedPlan }) } ) as AdminActionResponse; setSuccess(res.message || "套餐更新成功"); } refreshUsers(); setDialogOpen(false); setTimeout(() => setSuccess(null), 3000); } catch (err) { setMutationError(err instanceof Error ? err.message : "操作失败"); setDialogOpen(false); } finally { setActionLoading(false); } } const totalPages = Math.ceil(totalUsers / LIMIT); const currentPage = Math.floor(skip / LIMIT) + 1; const statCards = [ { title: "总用户数", value: stats?.total_users ?? 0, icon: Users, color: "text-blue-600", bg: "bg-blue-50", }, { title: "总查询数", value: stats?.total_queries ?? 0, icon: Search, color: "text-emerald-600", bg: "bg-emerald-50", }, { title: "总引用次数", value: stats?.total_citations ?? 0, icon: Quote, color: "text-violet-600", bg: "bg-violet-50", }, { title: "引用率", value: stats ? `${stats.citation_rate}%` : "0%", icon: Percent, color: "text-amber-600", bg: "bg-amber-50", }, ]; function formatDate(dateStr: string) { if (!dateStr) return "-"; const d = new Date(dateStr); return d.toLocaleDateString("zh-CN"); } if (loadingStats && !stats) { return (

管理后台

系统统计与用户管理

); } return (

管理后台

系统统计与用户管理

{error && (
{error}
)} {success && (
{success}
)} {/* Stats Cards */}
{statCards.map((card) => (

{card.title}

{loadingStats ? : card.value}

))}
{/* User Management */} 用户管理
{ setSearch(e.target.value); setSkip(0); }} className="max-w-sm" />
{usersError ? ( ) : (
邮箱 用户名 套餐 查询数 邮箱验证 状态 注册日期 操作 {loadingUsers ? ( ) : users.length === 0 ? ( 暂无用户数据 ) : ( users.map((user) => ( {user.email} {user.name || "-"} {user.plan} {user.query_count} {user.email_verified ? ( 已验证 ) : ( 未验证 )} {user.is_active ? ( 正常 ) : ( 禁用 )} {formatDate(user.created_at)}
)) )}
)} {/* Pagination */} {totalPages > 1 && (
第 {currentPage} / {totalPages} 页 (共 {totalUsers} 条)
)}
{/* Dialog */} {dialogType === "toggle" ? selectedUser?.is_active ? "禁用用户" : "启用用户" : "修改套餐"} {dialogType === "toggle" ? `确认${selectedUser?.is_active ? "禁用" : "启用"}用户 ${selectedUser?.email}?` : `请选择用户 ${selectedUser?.email} 的新套餐`} {dialogType === "plan" && (
)}
); }