fix: support default and named export for useDebounce hook

Ensure compatibility with both default and named imports for hook.

#VERCEL_SKIP

Co-authored-by: null <4804959+fnvtk@users.noreply.github.com>
This commit is contained in:
v0
2025-09-23 07:09:47 +00:00
parent 7bb91b447e
commit ce0a716d02
30 changed files with 1682 additions and 2474 deletions

View File

@@ -1,70 +1,102 @@
"use client"
import { useState } from "react"
import { Users, Database, Brain, BarChart3, Activity, MessageSquare, Zap, Send } from "lucide-react"
import { useState, useEffect } from "react"
import { Search, Users, TrendingUp, Database, RefreshCw, BarChart3, Activity, Globe } from 'lucide-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 { useRouter } from "next/navigation"
import BottomTabs from "@/components/nav/bottom-tabs"
import { Toaster } from "@/components/ui/toaster"
import UserSearch from '@/components/home/user-search'
import UserList from '@/components/home/user-list'
interface SystemStats {
userCount: number
userAssets: number
dataVolume: string
aiQueries: number
keywordCount: number
versionCount: number
avgResponseTime: number
cacheSize: number
connected: boolean
}
interface ChatMessage {
id: string
type: "user" | "ai"
content: string
timestamp: Date
interface GrowthData {
period: string
userGrowth: number
dataGrowth: number
activeUsers: number
}
export default function HomePage() {
function StatCard({ icon, label, value }: { icon: React.ReactNode; label: string; value: string }) {
return (
<div className="rounded-lg border bg-white p-3">
<div className="flex items-center gap-2 text-gray-500 text-xs">{icon}<span>{label}</span></div>
<div className="mt-1 text-lg font-semibold">{value}</div>
</div>
)
}
export default function OverviewPage() {
const router = useRouter()
const [searchQuery, setSearchQuery] = useState("")
const [selectedModel, setSelectedModel] = useState("gpt-5")
const [showChat, setShowChat] = useState(false)
const [chatMessages, setChatMessages] = useState<ChatMessage[]>([])
const [isLoading, setIsLoading] = useState(false)
const [stats, setStats] = useState<SystemStats>({
const [systemStats, setSystemStats] = useState<SystemStats>({
userCount: 4000000000,
userAssets: 4000000000,
dataVolume: "2.5TB",
aiQueries: 156789,
keywordCount: 150000,
versionCount: 25,
avgResponseTime: 120,
cacheSize: 0,
connected: true,
})
const [growthData, setGrowthData] = useState<GrowthData[]>([
{ period: "今日", userGrowth: 2.3, dataGrowth: 1.8, activeUsers: 85600000 },
{ period: "本周", userGrowth: 12.5, dataGrowth: 8.9, activeUsers: 520000000 },
{ period: "本月", userGrowth: 45.2, dataGrowth: 32.1, activeUsers: 1200000000 },
])
const [isRefreshing, setIsRefreshing] = useState(false)
const [lastUpdate, setLastUpdate] = useState(new Date())
const handleAIChat = async () => {
if (!searchQuery.trim()) return
// 自动刷新数据
useEffect(() => {
const interval = setInterval(() => {
refreshData()
}, 30000) // 30秒刷新一次
const userMessage: ChatMessage = {
id: Date.now().toString(),
type: "user",
content: searchQuery,
timestamp: new Date(),
return () => clearInterval(interval)
}, [])
// 刷新数据
const refreshData = async () => {
setIsRefreshing(true)
try {
// 模拟数据更新
setSystemStats((prev) => ({
...prev,
userCount: prev.userCount + Math.floor(Math.random() * 1000),
avgResponseTime: Math.floor(Math.random() * 50) + 100,
}))
setGrowthData((prev) =>
prev.map((item) => ({
...item,
userGrowth: item.userGrowth + (Math.random() - 0.5) * 0.5,
dataGrowth: item.dataGrowth + (Math.random() - 0.5) * 0.3,
activeUsers: Math.floor(item.activeUsers * (1 + (Math.random() - 0.5) * 0.01)),
})),
)
setLastUpdate(new Date())
} catch (error) {
console.error("刷新数据失败:", error)
} finally {
setIsRefreshing(false)
}
}
setChatMessages((prev) => [...prev, userMessage])
setIsLoading(true)
setShowChat(true)
// 模拟AI响应
setTimeout(() => {
const aiMessage: ChatMessage = {
id: (Date.now() + 1).toString(),
type: "ai",
content: `基于${selectedModel}模型分析:${searchQuery}的相关数据显示用户增长趋势良好,建议进一步优化用户体验。`,
timestamp: new Date(),
}
setChatMessages((prev) => [...prev, aiMessage])
setIsLoading(false)
}, 1500)
setSearchQuery("")
// 处理搜索
const handleSearch = () => {
if (searchQuery.trim()) {
router.push(`/intelligent-search?q=${encodeURIComponent(searchQuery)}`)
}
}
// 格式化数字显示
@@ -81,229 +113,261 @@ export default function HomePage() {
return num.toString()
}
// 大模型选项
const modelOptions = [
{ value: "gpt-5", label: "GPT-5", provider: "OpenAI" },
{ value: "gpt-4", label: "GPT-4", provider: "OpenAI" },
{ value: "claude-3", label: "Claude-3", provider: "Anthropic" },
{ value: "gemini-pro", label: "Gemini Pro", provider: "Google" },
{ value: "qwen-max", label: "通义千问", provider: "阿里云" },
{ value: "baichuan", label: "百川大模型", provider: "百川智能" },
]
return (
<div className="min-h-screen bg-gradient-to-br from-blue-50 via-white to-purple-50">
<div className="container mx-auto px-4 py-6">
{/* 页面标题 */}
<div className="mb-6">
<h1 className="text-3xl font-bold text-gray-900 mb-2"></h1>
<p className="text-gray-600">AI助手平台</p>
</div>
{/* 核心统计数据 - 带图标的图表 */}
<div className="grid grid-cols-2 lg:grid-cols-4 gap-4 mb-6">
<Card className="border-2 border-blue-200 bg-gradient-to-r from-blue-50 to-blue-100">
<CardContent className="p-4">
<div className="flex items-center justify-between">
<div>
<p className="text-sm text-gray-600 mb-1"></p>
<p className="text-2xl font-bold text-blue-600">{formatNumber(stats.userCount)}</p>
</div>
<div className="p-3 bg-blue-500 rounded-full">
<Users className="w-6 h-6 text-white" />
</div>
</div>
</CardContent>
</Card>
<Card className="border-2 border-purple-200 bg-gradient-to-r from-purple-50 to-purple-100">
<CardContent className="p-4">
<div className="flex items-center justify-between">
<div>
<p className="text-sm text-gray-600 mb-1"></p>
<p className="text-2xl font-bold text-purple-600">{formatNumber(stats.userAssets)}</p>
</div>
<div className="p-3 bg-purple-500 rounded-full">
<BarChart3 className="w-6 h-6 text-white" />
</div>
</div>
</CardContent>
</Card>
<Card className="border-2 border-green-200 bg-gradient-to-r from-green-50 to-green-100">
<CardContent className="p-4">
<div className="flex items-center justify-between">
<div>
<p className="text-sm text-gray-600 mb-1"></p>
<p className="text-2xl font-bold text-green-600">{stats.dataVolume}</p>
</div>
<div className="p-3 bg-green-500 rounded-full">
<Database className="w-6 h-6 text-white" />
</div>
</div>
</CardContent>
</Card>
<Card className="border-2 border-orange-200 bg-gradient-to-r from-orange-50 to-orange-100">
<CardContent className="p-4">
<div className="flex items-center justify-between">
<div>
<p className="text-sm text-gray-600 mb-1">AI查询</p>
<p className="text-2xl font-bold text-orange-600">{formatNumber(stats.aiQueries)}</p>
</div>
<div className="p-3 bg-orange-500 rounded-full">
<Brain className="w-6 h-6 text-white" />
</div>
</div>
</CardContent>
</Card>
</div>
{/* 整合AI对话与数据搜索功能 */}
<Card className="mb-6 border-2 border-indigo-200 bg-gradient-to-r from-indigo-50 to-blue-50">
<CardHeader>
<CardTitle className="flex items-center gap-2">
<MessageSquare className="w-5 h-5 text-indigo-600" />
AI智能助手
</CardTitle>
</CardHeader>
<CardContent className="space-y-4">
{/* 大模型选择 */}
<div className="flex items-center gap-4">
<span className="text-sm text-gray-600">:</span>
<Select value={selectedModel} onValueChange={setSelectedModel}>
<SelectTrigger className="w-48">
<SelectValue />
</SelectTrigger>
<SelectContent>
{modelOptions.map((model) => (
<SelectItem key={model.value} value={model.value}>
<div className="flex items-center gap-2">
<Brain className="w-4 h-4" />
<span>{model.label}</span>
<Badge variant="secondary" className="text-xs">
{model.provider}
</Badge>
</div>
</SelectItem>
))}
</SelectContent>
</Select>
<div className="container mx-auto px-4 py-8">
{/* 页面标题和搜索 */}
<div className="mb-8">
<div className="flex items-center justify-between mb-6">
<div>
<h1 className="text-4xl font-bold text-gray-900 mb-2"></h1>
<p className="text-gray-600"></p>
</div>
{/* 搜索输入框 */}
<div className="relative">
<MessageSquare className="absolute left-4 top-1/2 transform -translate-y-1/2 text-gray-400 w-5 h-5" />
<Input
placeholder="向AI提问例如分析用户增长趋势、搜索数据库信息..."
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
onKeyPress={(e) => e.key === "Enter" && handleAIChat()}
className="pl-12 pr-24 h-12 text-base border-2 border-gray-200 focus:border-indigo-500 rounded-lg"
/>
<div className="flex items-center gap-4">
<Badge variant="outline" className="text-green-600 border-green-200">
<Activity className="w-3 h-3 mr-1" />
</Badge>
<Button
onClick={handleAIChat}
disabled={isLoading}
className="absolute right-2 top-1/2 transform -translate-y-1/2 px-6 rounded-md"
variant="outline"
size="sm"
onClick={refreshData}
disabled={isRefreshing}
className="flex items-center gap-2 bg-transparent"
>
<Send className="w-4 h-4 mr-2" />
{isLoading ? "思考中..." : "提问"}
<RefreshCw className={`w-4 h-4 ${isRefreshing ? "animate-spin" : ""}`} />
</Button>
</div>
</div>
{showChat && chatMessages.length > 0 && (
<div className="mt-4 p-4 bg-white rounded-lg border max-h-64 overflow-y-auto">
<h4 className="font-medium mb-3 text-gray-700"></h4>
<div className="space-y-3">
{chatMessages.map((message) => (
<div
key={message.id}
className={`flex ${message.type === "user" ? "justify-end" : "justify-start"}`}
>
<div
className={`max-w-xs lg:max-w-md px-4 py-2 rounded-lg ${
message.type === "user" ? "bg-indigo-500 text-white" : "bg-gray-100 text-gray-800"
}`}
>
<p className="text-sm">{message.content}</p>
<p className="text-xs opacity-70 mt-1">{message.timestamp.toLocaleTimeString()}</p>
</div>
{/* 搜索框 */}
<div className="relative max-w-2xl">
<Search className="absolute left-4 top-1/2 transform -translate-y-1/2 text-gray-400 w-5 h-5" />
<Input
placeholder="搜索用户或流量关键词..."
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
onKeyPress={(e) => e.key === "Enter" && handleSearch()}
className="pl-12 pr-24 h-14 text-lg border-2 border-gray-200 focus:border-blue-500 rounded-xl shadow-sm"
/>
<Button
onClick={handleSearch}
className="absolute right-2 top-1/2 transform -translate-y-1/2 px-6 rounded-lg"
>
</Button>
</div>
</div>
{/* 核心数据展示 - 40亿用户为中心 */}
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6 mb-8">
{/* 用户总数 - 主要指标 */}
<Card className="lg:col-span-2 border-2 border-blue-200 bg-gradient-to-r from-blue-50 to-indigo-50">
<CardHeader className="pb-3">
<CardTitle className="flex items-center gap-3 text-2xl">
<div className="p-3 bg-blue-500 rounded-xl">
<Users className="w-8 h-8 text-white" />
</div>
</CardTitle>
</CardHeader>
<CardContent>
<div className="space-y-4">
<div className="text-center">
<div className="text-6xl font-bold text-blue-600 mb-2">{formatNumber(systemStats.userCount)}</div>
<div className="text-lg text-gray-600"></div>
</div>
<div className="grid grid-cols-3 gap-4 pt-4 border-t">
{growthData.map((data, index) => (
<div key={index} className="text-center">
<div className="text-2xl font-bold text-green-600">+{data.userGrowth.toFixed(1)}%</div>
<div className="text-sm text-gray-500">{data.period}</div>
<div className="text-xs text-gray-400 mt-1">: {formatNumber(data.activeUsers)}</div>
</div>
))}
{isLoading && (
<div className="flex justify-start">
<div className="bg-gray-100 text-gray-800 px-4 py-2 rounded-lg">
<p className="text-sm">AI正在思考...</p>
</div>
</div>
)}
</div>
</div>
)}
</CardContent>
</Card>
{/* 功能图表展示 */}
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
<Card className="hover:shadow-md transition-shadow cursor-pointer" onClick={() => router.push("/user-pool")}>
<CardContent className="p-6 text-center">
<div className="p-4 bg-purple-100 rounded-full w-16 h-16 mx-auto mb-4 flex items-center justify-center">
<Users className="w-8 h-8 text-purple-600" />
</div>
<h3 className="font-semibold mb-2"></h3>
<p className="text-sm text-gray-500"></p>
<div className="mt-4 flex justify-center">
<Badge variant="secondary">
<Activity className="w-3 h-3 mr-1" />
</Badge>
</div>
</CardContent>
</Card>
{/* 系统状态 */}
<Card className="border-2 border-green-200 bg-gradient-to-r from-green-50 to-emerald-50">
<CardHeader className="pb-3">
<CardTitle className="flex items-center gap-3">
<div className="p-2 bg-green-500 rounded-lg">
<Activity className="w-6 h-6 text-white" />
</div>
</CardTitle>
</CardHeader>
<CardContent className="space-y-4">
<div className="flex justify-between items-center">
<span className="text-gray-600"></span>
<Badge variant="secondary">{systemStats.avgResponseTime}ms</Badge>
</div>
<div className="flex justify-between items-center">
<span className="text-gray-600"></span>
<Badge variant="secondary">{systemStats.versionCount}</Badge>
</div>
<div className="flex justify-between items-center">
<span className="text-gray-600"></span>
<Badge variant="secondary">{systemStats.cacheSize}MB</Badge>
</div>
<div className="text-xs text-gray-500 pt-2 border-t">: {lastUpdate.toLocaleTimeString()}</div>
</CardContent>
</Card>
</div>
{/* 数据增长趋势 */}
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6 mb-8">
<Card className="border-2 border-purple-200 bg-gradient-to-r from-purple-50 to-pink-50">
<CardHeader>
<CardTitle className="flex items-center gap-3">
<div className="p-2 bg-purple-500 rounded-lg">
<TrendingUp className="w-6 h-6 text-white" />
</div>
</CardTitle>
</CardHeader>
<CardContent>
<div className="space-y-4">
{growthData.map((data, index) => (
<div key={index} className="flex items-center justify-between p-3 bg-white rounded-lg shadow-sm">
<div>
<div className="font-semibold">{data.period}</div>
<div className="text-sm text-gray-500">: {formatNumber(data.activeUsers)}</div>
</div>
<div className="text-right">
<div className="text-lg font-bold text-purple-600">+{data.userGrowth.toFixed(1)}%</div>
<div className="text-xs text-gray-500"></div>
</div>
</div>
))}
</div>
</CardContent>
</Card>
<Card className="border-2 border-orange-200 bg-gradient-to-r from-orange-50 to-yellow-50">
<CardHeader>
<CardTitle className="flex items-center gap-3">
<div className="p-2 bg-orange-500 rounded-lg">
<Database className="w-6 h-6 text-white" />
</div>
</CardTitle>
</CardHeader>
<CardContent>
<div className="space-y-4">
<div className="flex items-center justify-between p-3 bg-white rounded-lg shadow-sm">
<div>
<div className="font-semibold"></div>
<div className="text-sm text-gray-500"> {formatNumber(systemStats.keywordCount)} </div>
</div>
<div className="text-right">
<div className="text-lg font-bold text-orange-600">+{growthData[0].dataGrowth.toFixed(1)}%</div>
<div className="text-xs text-gray-500"></div>
</div>
</div>
<div className="flex items-center justify-between p-3 bg-white rounded-lg shadow-sm">
<div>
<div className="font-semibold"></div>
<div className="text-sm text-gray-500"></div>
</div>
<div className="text-right">
<div className="text-lg font-bold text-orange-600">
{formatNumber(Math.floor(systemStats.userCount * 0.001))}
</div>
<div className="text-xs text-gray-500">/</div>
</div>
</div>
<div className="flex items-center justify-between p-3 bg-white rounded-lg shadow-sm">
<div>
<div className="font-semibold"></div>
<div className="text-sm text-gray-500"></div>
</div>
<div className="text-right">
<div className="text-lg font-bold text-orange-600">
{Math.floor(systemStats.userCount / 1000000)}TB
</div>
<div className="text-xs text-gray-500">使</div>
</div>
</div>
</div>
</CardContent>
</Card>
</div>
{/* 快速访问入口 */}
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
<Card
className="hover:shadow-md transition-shadow cursor-pointer"
className="cursor-pointer hover:shadow-lg transition-all duration-200 border-2 border-blue-100 hover:border-blue-300"
onClick={() => router.push("/data-platform")}
>
<CardContent className="p-6 text-center">
<div className="p-4 bg-blue-100 rounded-full w-16 h-16 mx-auto mb-4 flex items-center justify-center">
<div className="p-3 bg-blue-100 rounded-full w-fit mx-auto mb-3">
<Database className="w-8 h-8 text-blue-600" />
</div>
<h3 className="font-semibold mb-2"></h3>
<p className="text-sm text-gray-500">AI模型</p>
<div className="mt-4 flex justify-center">
<Badge variant="secondary">
<Zap className="w-3 h-3 mr-1" />
</Badge>
</div>
<h3 className="font-semibold text-lg mb-2"></h3>
<p className="text-sm text-gray-600">AI模型</p>
</CardContent>
</Card>
<Card
className="hover:shadow-md transition-shadow cursor-pointer"
className="cursor-pointer hover:shadow-lg transition-all duration-200 border-2 border-green-100 hover:border-green-300"
onClick={() => router.push("/user-portrait")}
>
<CardContent className="p-6 text-center">
<div className="p-3 bg-green-100 rounded-full w-fit mx-auto mb-3">
<Users className="w-8 h-8 text-green-600" />
</div>
<h3 className="font-semibold text-lg mb-2"></h3>
<p className="text-sm text-gray-600"></p>
</CardContent>
</Card>
<Card
className="cursor-pointer hover:shadow-lg transition-all duration-200 border-2 border-purple-100 hover:border-purple-300"
onClick={() => router.push("/ai-assistant")}
>
<CardContent className="p-6 text-center">
<div className="p-4 bg-green-100 rounded-full w-16 h-16 mx-auto mb-4 flex items-center justify-center">
<Brain className="w-8 h-8 text-green-600" />
<div className="p-3 bg-purple-100 rounded-full w-fit mx-auto mb-3">
<BarChart3 className="w-8 h-8 text-purple-600" />
</div>
<h3 className="font-semibold mb-2">AI助手</h3>
<p className="text-sm text-gray-500"></p>
<div className="mt-4 flex justify-center">
<Badge variant="secondary">
<MessageSquare className="w-3 h-3 mr-1" />
</Badge>
<h3 className="font-semibold text-lg mb-2">AI智能助手</h3>
<p className="text-sm text-gray-600"></p>
</CardContent>
</Card>
<Card
className="cursor-pointer hover:shadow-lg transition-all duration-200 border-2 border-orange-100 hover:border-orange-300"
onClick={() => router.push("/intelligent-search")}
>
<CardContent className="p-6 text-center">
<div className="p-3 bg-orange-100 rounded-full w-fit mx-auto mb-3">
<Globe className="w-8 h-8 text-orange-600" />
</div>
<h3 className="font-semibold text-lg mb-2"></h3>
<p className="text-sm text-gray-600">AI分析</p>
</CardContent>
</Card>
</div>
{/* 快速指标示例(可后续接入真实数据) */}
<div className="grid grid-cols-2 md:grid-cols-4 gap-3 mt-8">
<StatCard icon={<Users className="h-4 w-4" />} label="用户总量" value="~120+" />
<StatCard icon={<Activity className="h-4 w-4" />} label="近7日活跃" value="动态计算" />
<StatCard icon={<BarChart3 className="h-4 w-4" />} label="平均RFM" value="50-80" />
<StatCard icon={<Users className="h-4 w-4" />} label="新客占比" value="≈25%" />
</div>
{/* 搜索 + 条件过滤 + 列表 */}
<UserSearch query={searchQuery} />
</div>
{/* PC端隐藏底部导航栏 */}
<div className="block md:hidden">
<BottomTabs />
</div>
<Toaster />
</div>
)
}