Organize project by 5 core modules based on requirement docs. Co-authored-by: null <4804959+fnvtk@users.noreply.github.com>
281 lines
12 KiB
TypeScript
281 lines
12 KiB
TypeScript
"use client"
|
|
import { useState, useEffect } from "react"
|
|
import { Users, Database, Activity, DollarSign, TrendingUp, Search, ArrowUpRight, Zap } from "lucide-react"
|
|
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/ui/card"
|
|
import { Button } from "@/components/ui/button"
|
|
import { Input } from "@/components/ui/input"
|
|
import { Badge } from "@/components/ui/badge"
|
|
import Link from "next/link"
|
|
import {
|
|
LineChart,
|
|
Line,
|
|
XAxis,
|
|
YAxis,
|
|
CartesianGrid,
|
|
Tooltip,
|
|
ResponsiveContainer,
|
|
PieChart,
|
|
Pie,
|
|
Cell,
|
|
} from "recharts"
|
|
|
|
// 模拟数据
|
|
const growthData = [
|
|
{ month: "1月", users: 3200, value: 420 },
|
|
{ month: "2月", users: 3800, value: 480 },
|
|
{ month: "3月", users: 4100, value: 520 },
|
|
{ month: "4月", users: 4600, value: 580 },
|
|
{ month: "5月", users: 5200, value: 650 },
|
|
{ month: "6月", users: 5800, value: 720 },
|
|
]
|
|
|
|
const valueDistribution = [
|
|
{ name: "S级", value: 5, color: "#8B5CF6" },
|
|
{ name: "A级", value: 15, color: "#3B82F6" },
|
|
{ name: "B级", value: 35, color: "#10B981" },
|
|
{ name: "C级", value: 30, color: "#F59E0B" },
|
|
{ name: "D级", value: 15, color: "#EF4444" },
|
|
]
|
|
|
|
const recentActivities = [
|
|
{ id: 1, user: "张伟", action: "完成首次购买", time: "2分钟前", type: "purchase" },
|
|
{ id: 2, user: "李娜", action: "升级为A级用户", time: "5分钟前", type: "upgrade" },
|
|
{ id: 3, user: "王芳", action: "触发流失预警", time: "8分钟前", type: "warning" },
|
|
{ id: 4, user: "刘洋", action: "完成问卷调查", time: "12分钟前", type: "survey" },
|
|
{ id: 5, user: "陈明", action: "加入VIP计划", time: "15分钟前", type: "vip" },
|
|
]
|
|
|
|
export default function HomePage() {
|
|
const [searchQuery, setSearchQuery] = useState("")
|
|
const [currentTime, setCurrentTime] = useState(new Date())
|
|
|
|
useEffect(() => {
|
|
const timer = setInterval(() => setCurrentTime(new Date()), 1000)
|
|
return () => clearInterval(timer)
|
|
}, [])
|
|
|
|
return (
|
|
<div className="flex-1 space-y-6 p-6 md:p-8">
|
|
{/* 顶部标题区 */}
|
|
<div className="flex flex-col md:flex-row md:items-center md:justify-between gap-4">
|
|
<div>
|
|
<h1 className="text-2xl md:text-3xl font-bold tracking-tight">数据资产中台</h1>
|
|
<p className="text-muted-foreground mt-1">
|
|
{currentTime.toLocaleDateString("zh-CN", { weekday: "long", year: "numeric", month: "long", day: "numeric" })}
|
|
{" · "}
|
|
{currentTime.toLocaleTimeString("zh-CN")}
|
|
</p>
|
|
</div>
|
|
<div className="flex items-center gap-3">
|
|
<div className="relative w-full md:w-80">
|
|
<Search className="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground" />
|
|
<Input
|
|
placeholder="搜索用户、手机号、标签..."
|
|
className="pl-9"
|
|
value={searchQuery}
|
|
onChange={(e) => setSearchQuery(e.target.value)}
|
|
/>
|
|
</div>
|
|
<Button>
|
|
<Zap className="mr-2 h-4 w-4" />
|
|
快速分析
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
|
|
{/* 核心指标卡片 */}
|
|
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-4">
|
|
<Card className="bg-gradient-to-br from-violet-500/10 to-purple-500/10 border-violet-200 dark:border-violet-800">
|
|
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
|
<CardTitle className="text-sm font-medium">用户资产总量</CardTitle>
|
|
<Users className="h-4 w-4 text-violet-600" />
|
|
</CardHeader>
|
|
<CardContent>
|
|
<div className="text-2xl font-bold">40.5亿</div>
|
|
<div className="flex items-center text-xs text-muted-foreground mt-1">
|
|
<TrendingUp className="h-3 w-3 text-green-500 mr-1" />
|
|
<span className="text-green-500">+20.1%</span>
|
|
<span className="ml-1">较上月</span>
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
<Card className="bg-gradient-to-br from-blue-500/10 to-cyan-500/10 border-blue-200 dark:border-blue-800">
|
|
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
|
<CardTitle className="text-sm font-medium">活跃用户</CardTitle>
|
|
<Activity className="h-4 w-4 text-blue-600" />
|
|
</CardHeader>
|
|
<CardContent>
|
|
<div className="text-2xl font-bold">2,350万</div>
|
|
<div className="flex items-center text-xs text-muted-foreground mt-1">
|
|
<TrendingUp className="h-3 w-3 text-green-500 mr-1" />
|
|
<span className="text-green-500">+18.2%</span>
|
|
<span className="ml-1">较上月</span>
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
<Card className="bg-gradient-to-br from-emerald-500/10 to-green-500/10 border-emerald-200 dark:border-emerald-800">
|
|
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
|
<CardTitle className="text-sm font-medium">数据处理量</CardTitle>
|
|
<Database className="h-4 w-4 text-emerald-600" />
|
|
</CardHeader>
|
|
<CardContent>
|
|
<div className="text-2xl font-bold">125亿条</div>
|
|
<div className="flex items-center text-xs text-muted-foreground mt-1">
|
|
<TrendingUp className="h-3 w-3 text-green-500 mr-1" />
|
|
<span className="text-green-500">+32.5%</span>
|
|
<span className="ml-1">较上月</span>
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
<Card className="bg-gradient-to-br from-amber-500/10 to-orange-500/10 border-amber-200 dark:border-amber-800">
|
|
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
|
<CardTitle className="text-sm font-medium">资产总价值</CardTitle>
|
|
<DollarSign className="h-4 w-4 text-amber-600" />
|
|
</CardHeader>
|
|
<CardContent>
|
|
<div className="text-2xl font-bold">¥125.8亿</div>
|
|
<div className="flex items-center text-xs text-muted-foreground mt-1">
|
|
<TrendingUp className="h-3 w-3 text-green-500 mr-1" />
|
|
<span className="text-green-500">+45.2%</span>
|
|
<span className="ml-1">较上月</span>
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
</div>
|
|
|
|
{/* 图表区域 */}
|
|
<div className="grid gap-4 md:grid-cols-7">
|
|
<Card className="col-span-4">
|
|
<CardHeader>
|
|
<CardTitle>用户增长趋势</CardTitle>
|
|
<CardDescription>近6个月用户与资产价值变化</CardDescription>
|
|
</CardHeader>
|
|
<CardContent>
|
|
<ResponsiveContainer width="100%" height={300}>
|
|
<LineChart data={growthData}>
|
|
<CartesianGrid strokeDasharray="3 3" className="stroke-muted" />
|
|
<XAxis dataKey="month" className="text-xs" />
|
|
<YAxis className="text-xs" />
|
|
<Tooltip />
|
|
<Line type="monotone" dataKey="users" stroke="#8B5CF6" strokeWidth={2} name="用户(万)" />
|
|
<Line type="monotone" dataKey="value" stroke="#3B82F6" strokeWidth={2} name="价值(亿)" />
|
|
</LineChart>
|
|
</ResponsiveContainer>
|
|
</CardContent>
|
|
</Card>
|
|
<Card className="col-span-3">
|
|
<CardHeader>
|
|
<CardTitle>用户价值分布</CardTitle>
|
|
<CardDescription>S/A/B/C/D级用户占比</CardDescription>
|
|
</CardHeader>
|
|
<CardContent>
|
|
<ResponsiveContainer width="100%" height={200}>
|
|
<PieChart>
|
|
<Pie
|
|
data={valueDistribution}
|
|
cx="50%"
|
|
cy="50%"
|
|
innerRadius={50}
|
|
outerRadius={80}
|
|
dataKey="value"
|
|
label={({ name, value }) => `${name}: ${value}%`}
|
|
>
|
|
{valueDistribution.map((entry, index) => (
|
|
<Cell key={`cell-${index}`} fill={entry.color} />
|
|
))}
|
|
</Pie>
|
|
<Tooltip />
|
|
</PieChart>
|
|
</ResponsiveContainer>
|
|
<div className="flex flex-wrap justify-center gap-2 mt-4">
|
|
{valueDistribution.map((item) => (
|
|
<Badge key={item.name} variant="outline" style={{ borderColor: item.color, color: item.color }}>
|
|
{item.name}: {item.value}%
|
|
</Badge>
|
|
))}
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
</div>
|
|
|
|
{/* 底部区域 */}
|
|
<div className="grid gap-4 md:grid-cols-2">
|
|
<Card>
|
|
<CardHeader>
|
|
<CardTitle>实时动态</CardTitle>
|
|
<CardDescription>用户行为实时监控</CardDescription>
|
|
</CardHeader>
|
|
<CardContent>
|
|
<div className="space-y-4">
|
|
{recentActivities.map((activity) => (
|
|
<div key={activity.id} className="flex items-center justify-between">
|
|
<div className="flex items-center gap-3">
|
|
<div className="h-8 w-8 rounded-full bg-muted flex items-center justify-center text-sm font-medium">
|
|
{activity.user.charAt(0)}
|
|
</div>
|
|
<div>
|
|
<p className="text-sm font-medium">{activity.user}</p>
|
|
<p className="text-xs text-muted-foreground">{activity.action}</p>
|
|
</div>
|
|
</div>
|
|
<span className="text-xs text-muted-foreground">{activity.time}</span>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
<Card>
|
|
<CardHeader>
|
|
<CardTitle>快速入口</CardTitle>
|
|
<CardDescription>常用功能快速访问</CardDescription>
|
|
</CardHeader>
|
|
<CardContent>
|
|
<div className="grid grid-cols-2 gap-3">
|
|
<Link href="/data-platform">
|
|
<Button variant="outline" className="w-full justify-start h-auto py-4 bg-transparent">
|
|
<Database className="mr-2 h-4 w-4" />
|
|
<div className="text-left">
|
|
<div className="font-medium">数据中台</div>
|
|
<div className="text-xs text-muted-foreground">数据源管理</div>
|
|
</div>
|
|
<ArrowUpRight className="ml-auto h-4 w-4" />
|
|
</Button>
|
|
</Link>
|
|
<Link href="/user-portrait">
|
|
<Button variant="outline" className="w-full justify-start h-auto py-4 bg-transparent">
|
|
<Users className="mr-2 h-4 w-4" />
|
|
<div className="text-left">
|
|
<div className="font-medium">用户画像</div>
|
|
<div className="text-xs text-muted-foreground">用户分析</div>
|
|
</div>
|
|
<ArrowUpRight className="ml-auto h-4 w-4" />
|
|
</Button>
|
|
</Link>
|
|
<Link href="/value-assessment">
|
|
<Button variant="outline" className="w-full justify-start h-auto py-4 bg-transparent">
|
|
<DollarSign className="mr-2 h-4 w-4" />
|
|
<div className="text-left">
|
|
<div className="font-medium">价值评估</div>
|
|
<div className="text-xs text-muted-foreground">RFM模型</div>
|
|
</div>
|
|
<ArrowUpRight className="ml-auto h-4 w-4" />
|
|
</Button>
|
|
</Link>
|
|
<Link href="/ai-assistant">
|
|
<Button variant="outline" className="w-full justify-start h-auto py-4 bg-transparent">
|
|
<Zap className="mr-2 h-4 w-4" />
|
|
<div className="text-left">
|
|
<div className="font-medium">AI助手</div>
|
|
<div className="text-xs text-muted-foreground">智能分析</div>
|
|
</div>
|
|
<ArrowUpRight className="ml-auto h-4 w-4" />
|
|
</Button>
|
|
</Link>
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|