"use client" import { Card } from "@/components/ui/card" import { Smartphone, Users, Activity, MessageSquare, TrendingUp } from "lucide-react" import { Progress } from "@/components/ui/progress" import { useRouter } from "next/navigation" import Link from "next/link" import { useState, useEffect, useRef } from "react" // 导入Chart.js import { Chart, registerables } from "chart.js" Chart.register(...registerables) // API接口定义 const API_BASE_URL = process.env.NEXT_PUBLIC_API_BASE_URL || "https://ckbapi.quwanzhi.com" // 统一的API请求客户端 async function apiRequest(url: string): Promise { try { const token = typeof window !== "undefined" ? localStorage.getItem("ckb_token") : null const headers: Record = { "Content-Type": "application/json", Accept: "application/json", } if (token) { headers["Authorization"] = `Bearer ${token}` } console.log("发送API请求:", url) const response = await fetch(url, { method: "GET", headers, mode: "cors", }) console.log("API响应状态:", response.status, response.statusText) // 检查响应头的Content-Type const contentType = response.headers.get("content-type") console.log("响应Content-Type:", contentType) if (!response.ok) { // 如果是401未授权,清除本地存储 if (response.status === 401) { if (typeof window !== "undefined") { localStorage.removeItem("ckb_token") localStorage.removeItem("ckb_user") } } throw new Error(`HTTP ${response.status}: ${response.statusText}`) } // 检查是否是JSON响应 if (!contentType || !contentType.includes("application/json")) { const text = await response.text() console.log("非JSON响应内容:", text.substring(0, 200)) throw new Error("服务器返回了非JSON格式的数据,可能是HTML错误页面") } const data = await response.json() console.log("API响应数据:", data) // 检查业务状态码 if (data.code && data.code !== 200 && data.code !== 0) { throw new Error(data.message || "请求失败") } return data.data || data } catch (error) { console.error("API请求失败:", error) throw error } } export default function Home() { const router = useRouter() const chartRef = useRef(null) const chartInstance = useRef(null) // 统一设备数据 const [stats, setStats] = useState({ totalDevices: 0, onlineDevices: 0, totalWechatAccounts: 0, onlineWechatAccounts: 0, }) const [isLoading, setIsLoading] = useState(true) const [apiError, setApiError] = useState("") useEffect(() => { // 获取统计数据 const fetchStats = async () => { try { setIsLoading(true) setApiError("") // 检查是否有token const token = localStorage.getItem("ckb_token") if (!token) { console.log("未找到登录token,使用默认数据") setStats({ totalDevices: 42, onlineDevices: 35, totalWechatAccounts: 42, onlineWechatAccounts: 35, }) setIsLoading(false) return } // 尝试请求API数据 try { // 并行请求多个接口 const [deviceStatsResult, wechatStatsResult] = await Promise.allSettled([ apiRequest(`${API_BASE_URL}/v1/dashboard/device-stats`), apiRequest(`${API_BASE_URL}/v1/dashboard/wechat-stats`), ]) const newStats = { ...stats } // 处理设备统计数据 if (deviceStatsResult.status === "fulfilled") { const deviceData = deviceStatsResult.value as any newStats.totalDevices = deviceData.total || 0 newStats.onlineDevices = deviceData.online || 0 } else { console.warn("设备统计API失败:", deviceStatsResult.reason) } // 处理微信号统计数据 if (wechatStatsResult.status === "fulfilled") { const wechatData = wechatStatsResult.value as any newStats.totalWechatAccounts = wechatData.total || 0 newStats.onlineWechatAccounts = wechatData.active || 0 } else { console.warn("微信号统计API失败:", wechatStatsResult.reason) } setStats(newStats) } catch (apiError) { console.warn("API请求失败,使用默认数据:", apiError) setApiError(apiError instanceof Error ? apiError.message : "API连接失败") // 使用默认数据 setStats({ totalDevices: 42, onlineDevices: 35, totalWechatAccounts: 42, onlineWechatAccounts: 35, }) } } catch (error) { console.error("获取统计数据失败:", error) setApiError(error instanceof Error ? error.message : "数据加载失败") // 使用默认数据 setStats({ totalDevices: 42, onlineDevices: 35, totalWechatAccounts: 42, onlineWechatAccounts: 35, }) } finally { setIsLoading(false) } } fetchStats() // 定时刷新数据(每30秒) const interval = setInterval(fetchStats, 30000) return () => clearInterval(interval) }, []) // 使用Chart.js创建图表 useEffect(() => { if (chartRef.current && !isLoading) { // 如果已经有图表实例,先销毁它 if (chartInstance.current) { chartInstance.current.destroy() } const ctx = chartRef.current.getContext("2d") // 创建新的图表实例 chartInstance.current = new Chart(ctx, { type: "line", data: { labels: ["周一", "周二", "周三", "周四", "周五", "周六", "周日"], datasets: [ { label: "获客数量", data: [120, 150, 180, 200, 230, 210, 190], backgroundColor: "rgba(59, 130, 246, 0.2)", borderColor: "rgba(59, 130, 246, 1)", borderWidth: 2, tension: 0.3, pointRadius: 4, pointBackgroundColor: "rgba(59, 130, 246, 1)", pointHoverRadius: 6, }, ], }, options: { responsive: true, maintainAspectRatio: false, plugins: { legend: { display: false, }, tooltip: { backgroundColor: "rgba(255, 255, 255, 0.9)", titleColor: "#333", bodyColor: "#666", borderColor: "#ddd", borderWidth: 1, padding: 10, displayColors: false, callbacks: { label: (context) => `获客数量: ${context.parsed.y}`, }, }, }, scales: { x: { grid: { display: false, }, }, y: { beginAtZero: true, grid: { color: "rgba(0, 0, 0, 0.05)", }, }, }, }, }) } // 组件卸载时清理图表实例 return () => { if (chartInstance.current) { chartInstance.current.destroy() } } }, [isLoading]) const handleDevicesClick = () => { router.push("/profile/devices") } const handleWechatClick = () => { router.push("/wechat-accounts") } const scenarioFeatures = [ { id: "douyin", name: "抖音获客", icon: "https://hebbkx1anhila5yf.public.blob.vercel-storage.com/image-QR8ManuDplYTySUJsY4mymiZkDYnQ9.png", color: "bg-blue-100 text-blue-600", value: 156, growth: 12, }, { id: "xiaohongshu", name: "小红书获客", icon: "https://hebbkx1anhila5yf.public.blob.vercel-storage.com/image-yvnMxpoBUzcvEkr8DfvHgPHEo1kmQ3.png", color: "bg-red-100 text-red-600", value: 89, growth: 8, }, { id: "gongzhonghao", name: "公众号获客", icon: "https://hebbkx1anhila5yf.public.blob.vercel-storage.com/image-Gsg0CMf5tsZb41mioszdjqU1WmsRxW.png", color: "bg-green-100 text-green-600", value: 234, growth: 15, }, { id: "haibao", name: "海报获客", icon: "https://hebbkx1anhila5yf.public.blob.vercel-storage.com/image-x92XJgXy4MI7moNYlA1EAes2FqDxMH.png", color: "bg-orange-100 text-orange-600", value: 167, growth: 10, }, ] // 今日数据统计 const todayStats = [ { title: "朋友圈同步", value: "12", icon: , color: "text-purple-600", path: "/workspace/moments-sync", }, { title: "群发任务", value: "8", icon: , color: "text-orange-600", path: "/workspace/group-push", }, { title: "获客转化", value: "85%", icon: , color: "text-green-600", path: "/scenarios", }, { title: "系统活跃度", value: "98%", icon: , color: "text-blue-600", path: "/workspace", }, ] if (isLoading) { return (

存客宝

{[...Array(3)].map((_, i) => (
))}
) } return (

存客宝

{apiError && (
API连接异常,显示默认数据
)}
设备数量
{stats.totalDevices}
微信号数量
{stats.totalWechatAccounts}
在线微信号
{stats.onlineWechatAccounts}
0 ? (stats.onlineWechatAccounts / stats.totalWechatAccounts) * 100 : 0 } className="h-1" />
{/* 场景获客统计 */}

场景获客统计

{scenarioFeatures .sort((a, b) => b.value - a.value) .slice(0, 4) // 只显示前4个 .map((scenario) => (
{scenario.name}
{scenario.value}
{scenario.name}
))}
{/* 今日数据统计 */}

今日数据

{todayStats.map((stat, index) => (
stat.path && router.push(stat.path)} >
{stat.icon}
{stat.value}
{stat.title}
))}
{/* 每日获客趋势 */}

每日获客趋势

) }