Files
users/app/page.tsx
v0 2408d50cb0 refactor: overhaul UI for streamlined user experience
Redesign navigation, home overview, user portrait, and valuation pages
with improved functionality and responsive design.

Co-authored-by: null <4804959+fnvtk@users.noreply.github.com>
2025-07-18 13:47:12 +00:00

309 lines
13 KiB
TypeScript

"use client"
import { useRouter } from "next/navigation"
import { cn } from "@/lib/utils"
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
import { Button } from "@/components/ui/button"
import { Progress } from "@/components/ui/progress"
import { Database, Users, Target, TrendingUp, Activity, CheckCircle, ArrowRight, BarChart3, Zap } from "lucide-react"
export default function Home() {
const router = useRouter()
// 真实的数据概览
const systemOverview = {
totalUsers: 156234,
activeUsers: 89167,
dataIntegrations: 12,
avgUserValue: 3248,
dataQuality: 94.6,
syncStatus: "正常",
}
// 数据集成状态
const dataIntegrations = [
{ name: "用户行为数据", status: "connected", lastSync: "2分钟前", records: 245673 },
{ name: "CRM系统", status: "connected", lastSync: "5分钟前", records: 156234 },
{ name: "内容互动数据", status: "connected", lastSync: "1分钟前", records: 892456 },
{ name: "营销活动数据", status: "syncing", lastSync: "正在同步", records: 0 },
]
// 用户画像概览
const userPortraitStats = {
totalTags: 342,
activeTags: 287,
userCoverage: 95.8,
segmentCount: 24,
}
// 用户估值概览
const userValueStats = {
highValueUsers: 18234,
mediumValueUsers: 47891,
lowValueUsers: 32156,
upgradeRate: 12.3,
}
const quickActions = [
{
title: "数据集成",
description: "管理数据源和同步",
icon: <Database className="h-5 w-5" />,
href: "/data-integration",
color: "bg-blue-50 hover:bg-blue-100 border-blue-200",
},
{
title: "用户画像",
description: "查看用户标签和分群",
icon: <Users className="h-5 w-5" />,
href: "/user-portrait",
color: "bg-purple-50 hover:bg-purple-100 border-purple-200",
},
{
title: "用户估值",
description: "分析用户价值和升级路径",
icon: <Target className="h-5 w-5" />,
href: "/user-value",
color: "bg-green-50 hover:bg-green-100 border-green-200",
},
]
return (
<div className="container mx-auto py-6 space-y-8">
{/* 页面标题 */}
<div className="text-center space-y-2">
<h1 className="text-3xl font-bold bg-gradient-to-r from-blue-600 to-purple-600 bg-clip-text text-transparent">
</h1>
<p className="text-muted-foreground"></p>
</div>
{/* 系统概览 */}
<Card className="border-none shadow-lg">
<CardHeader>
<CardTitle className="flex items-center gap-2">
<BarChart3 className="h-5 w-5" />
</CardTitle>
<CardDescription></CardDescription>
</CardHeader>
<CardContent>
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
<div className="bg-gradient-to-r from-blue-50 to-blue-100 rounded-lg p-4">
<div className="flex items-center justify-between">
<div>
<p className="text-sm font-medium text-blue-600"></p>
<p className="text-2xl font-bold text-blue-900">{systemOverview.totalUsers.toLocaleString()}</p>
</div>
<Users className="h-8 w-8 text-blue-600" />
</div>
<div className="mt-2">
<p className="text-xs text-blue-600">
: {systemOverview.activeUsers.toLocaleString()} (
{((systemOverview.activeUsers / systemOverview.totalUsers) * 100).toFixed(1)}%)
</p>
</div>
</div>
<div className="bg-gradient-to-r from-purple-50 to-purple-100 rounded-lg p-4">
<div className="flex items-center justify-between">
<div>
<p className="text-sm font-medium text-purple-600"></p>
<p className="text-2xl font-bold text-purple-900">¥{systemOverview.avgUserValue.toLocaleString()}</p>
</div>
<Target className="h-8 w-8 text-purple-600" />
</div>
<div className="mt-2">
<p className="text-xs text-purple-600"> 8.2%</p>
</div>
</div>
<div className="bg-gradient-to-r from-green-50 to-green-100 rounded-lg p-4">
<div className="flex items-center justify-between">
<div>
<p className="text-sm font-medium text-green-600"></p>
<p className="text-2xl font-bold text-green-900">{systemOverview.dataQuality}%</p>
</div>
<CheckCircle className="h-8 w-8 text-green-600" />
</div>
<div className="mt-2">
<Progress value={systemOverview.dataQuality} className="h-2" />
</div>
</div>
</div>
</CardContent>
</Card>
{/* 快速操作 */}
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
{quickActions.map((action, index) => (
<Card
key={index}
className={cn(
"border-2 cursor-pointer transition-all duration-300 hover:shadow-lg hover:scale-105",
action.color,
)}
onClick={() => router.push(action.href)}
>
<CardContent className="p-6">
<div className="flex items-center justify-between mb-4">
<div className="p-2 rounded-lg bg-white/50">{action.icon}</div>
<ArrowRight className="h-5 w-5 text-gray-400" />
</div>
<h3 className="font-semibold text-lg mb-2">{action.title}</h3>
<p className="text-sm text-gray-600">{action.description}</p>
</CardContent>
</Card>
))}
</div>
{/* 详细状态 */}
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
{/* 数据集成状态 */}
<Card>
<CardHeader>
<CardTitle className="flex items-center gap-2">
<Database className="h-5 w-5" />
</CardTitle>
<CardDescription></CardDescription>
</CardHeader>
<CardContent>
<div className="space-y-3">
{dataIntegrations.map((integration, index) => (
<div key={index} className="flex items-center justify-between p-3 bg-gray-50 rounded-lg">
<div className="flex items-center gap-3">
<div
className={cn(
"w-3 h-3 rounded-full",
integration.status === "connected"
? "bg-green-500"
: integration.status === "syncing"
? "bg-yellow-500"
: "bg-red-500",
)}
/>
<div>
<p className="font-medium text-sm">{integration.name}</p>
<p className="text-xs text-gray-500">{integration.lastSync}</p>
</div>
</div>
<div className="text-right">
<p className="text-sm font-medium">{integration.records.toLocaleString()}</p>
<p className="text-xs text-gray-500"></p>
</div>
</div>
))}
</div>
<Button
variant="outline"
className="w-full mt-4 bg-transparent"
onClick={() => router.push("/data-integration")}
>
</Button>
</CardContent>
</Card>
{/* 用户画像概览 */}
<Card>
<CardHeader>
<CardTitle className="flex items-center gap-2">
<Users className="h-5 w-5" />
</CardTitle>
<CardDescription></CardDescription>
</CardHeader>
<CardContent>
<div className="grid grid-cols-2 gap-4 mb-4">
<div className="text-center p-3 bg-purple-50 rounded-lg">
<p className="text-2xl font-bold text-purple-600">{userPortraitStats.totalTags}</p>
<p className="text-sm text-gray-600"></p>
</div>
<div className="text-center p-3 bg-blue-50 rounded-lg">
<p className="text-2xl font-bold text-blue-600">{userPortraitStats.segmentCount}</p>
<p className="text-sm text-gray-600"></p>
</div>
</div>
<div className="space-y-3">
<div className="flex justify-between items-center">
<span className="text-sm"></span>
<span className="text-sm font-medium">{userPortraitStats.userCoverage}%</span>
</div>
<Progress value={userPortraitStats.userCoverage} className="h-2" />
<div className="flex justify-between items-center">
<span className="text-sm"></span>
<span className="text-sm font-medium">{userPortraitStats.activeTags}</span>
</div>
<Progress value={(userPortraitStats.activeTags / userPortraitStats.totalTags) * 100} className="h-2" />
</div>
<Button
variant="outline"
className="w-full mt-4 bg-transparent"
onClick={() => router.push("/user-portrait")}
>
</Button>
</CardContent>
</Card>
{/* 用户估值概览 */}
<Card className="lg:col-span-2">
<CardHeader>
<CardTitle className="flex items-center gap-2">
<Target className="h-5 w-5" />
</CardTitle>
<CardDescription></CardDescription>
</CardHeader>
<CardContent>
<div className="grid grid-cols-1 md:grid-cols-4 gap-4">
<div className="bg-green-50 p-4 rounded-lg">
<div className="flex items-center justify-between mb-2">
<p className="text-sm font-medium text-green-600"></p>
<TrendingUp className="h-4 w-4 text-green-600" />
</div>
<p className="text-xl font-bold text-green-900">{userValueStats.highValueUsers.toLocaleString()}</p>
<p className="text-xs text-green-600">
{((userValueStats.highValueUsers / systemOverview.totalUsers) * 100).toFixed(1)}%
</p>
</div>
<div className="bg-blue-50 p-4 rounded-lg">
<div className="flex items-center justify-between mb-2">
<p className="text-sm font-medium text-blue-600"></p>
<Activity className="h-4 w-4 text-blue-600" />
</div>
<p className="text-xl font-bold text-blue-900">{userValueStats.mediumValueUsers.toLocaleString()}</p>
<p className="text-xs text-blue-600">
{((userValueStats.mediumValueUsers / systemOverview.totalUsers) * 100).toFixed(1)}%
</p>
</div>
<div className="bg-gray-50 p-4 rounded-lg">
<div className="flex items-center justify-between mb-2">
<p className="text-sm font-medium text-gray-600"></p>
<Users className="h-4 w-4 text-gray-600" />
</div>
<p className="text-xl font-bold text-gray-900">{userValueStats.lowValueUsers.toLocaleString()}</p>
<p className="text-xs text-gray-600">
{((userValueStats.lowValueUsers / systemOverview.totalUsers) * 100).toFixed(1)}%
</p>
</div>
<div className="bg-orange-50 p-4 rounded-lg">
<div className="flex items-center justify-between mb-2">
<p className="text-sm font-medium text-orange-600"></p>
<Zap className="h-4 w-4 text-orange-600" />
</div>
<p className="text-xl font-bold text-orange-900">{userValueStats.upgradeRate}%</p>
<p className="text-xs text-orange-600"> 2.1%</p>
</div>
</div>
<Button variant="outline" className="w-full mt-4 bg-transparent" onClick={() => router.push("/user-value")}>
</Button>
</CardContent>
</Card>
</div>
</div>
)
}