fix: resolve deployment errors and add missing files

Fix CSS issue and create missing documentation files
Add new data platform and mobile optimization features

Co-authored-by: null <4804959+fnvtk@users.noreply.github.com>
This commit is contained in:
v0
2025-07-19 02:34:18 +00:00
parent ea95107713
commit 901763fae0
20 changed files with 3216 additions and 1882 deletions

View File

@@ -0,0 +1,3 @@
export default function Loading() {
return null
}

429
app/user-discovery/page.tsx Normal file
View File

@@ -0,0 +1,429 @@
"use client"
import { useState } from "react"
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
import { Button } from "@/components/ui/button"
import { Badge } from "@/components/ui/badge"
import { Progress } from "@/components/ui/progress"
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
import {
Search,
Users,
TrendingUp,
BarChart3,
Filter,
RefreshCw,
Download,
ChevronRight,
ChevronDown,
Eye,
Clock,
Smartphone,
} from "lucide-react"
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@/components/ui/collapsible"
export default function UserDiscoveryPage() {
const [timeRange, setTimeRange] = useState("today")
const [searchQuery, setSearchQuery] = useState("")
const [expandedSections, setExpandedSections] = useState({
overview: true,
behavior: true,
segmentation: false,
engagement: false,
})
// 用户发现数据
const discoveryData = {
overview: {
totalUsers: 125678,
activeUsers: 45678,
newUsers: 1234,
engagement: 87.5,
growth: "+12.3%",
},
behaviorPatterns: [
{
pattern: "购买决策路径",
users: 12456,
avgTime: "3.2天",
conversion: "23.5%",
trend: "+8.2%",
},
{
pattern: "内容浏览偏好",
users: 8765,
avgTime: "15分钟",
conversion: "45.8%",
trend: "+12.1%",
},
{
pattern: "社交分享行为",
users: 6543,
avgTime: "2.1分钟",
conversion: "67.3%",
trend: "+5.7%",
},
{
pattern: "移动端使用习惯",
users: 9876,
avgTime: "8.5分钟",
conversion: "34.2%",
trend: "+15.4%",
},
],
userSegments: [
{
name: "高价值活跃用户",
count: 12456,
percentage: 28.6,
characteristics: ["高频使用", "高消费", "高推荐"],
color: "bg-green-100 text-green-800",
},
{
name: "潜力增长用户",
count: 18765,
percentage: 43.2,
characteristics: ["中频使用", "增长潜力", "易转化"],
color: "bg-blue-100 text-blue-800",
},
{
name: "新注册用户",
count: 8234,
percentage: 18.9,
characteristics: ["新用户", "探索期", "需引导"],
color: "bg-purple-100 text-purple-800",
},
{
name: "流失风险用户",
count: 4123,
percentage: 9.3,
characteristics: ["低活跃", "流失风险", "需挽回"],
color: "bg-red-100 text-red-800",
},
],
engagementMetrics: {
dailyActive: 45678,
weeklyActive: 89234,
monthlyActive: 125678,
avgSessionTime: "12.5分钟",
bounceRate: "23.4%",
returnRate: "67.8%",
},
}
const toggleSection = (section: string) => {
setExpandedSections((prev) => ({
...prev,
[section]: !prev[section],
}))
}
return (
<div className="container mx-auto py-4 md:py-6 space-y-4 md:space-y-6">
{/* 页面标题和工具栏 */}
<div className="flex flex-col md:flex-row md:justify-between md:items-center gap-4">
<div>
<h1 className="text-2xl md:text-3xl font-bold"></h1>
<p className="text-sm md:text-base text-muted-foreground mt-1"></p>
</div>
<div className="flex flex-wrap gap-2">
<Select value={timeRange} onValueChange={setTimeRange}>
<SelectTrigger className="w-[120px] text-sm">
<SelectValue placeholder="时间范围" />
</SelectTrigger>
<SelectContent>
<SelectItem value="today"></SelectItem>
<SelectItem value="week"></SelectItem>
<SelectItem value="month"></SelectItem>
</SelectContent>
</Select>
<Button variant="outline" size="icon" className="h-9 w-9 bg-transparent">
<Filter className="h-4 w-4" />
</Button>
<Button variant="outline" size="icon" className="h-9 w-9 bg-transparent">
<RefreshCw className="h-4 w-4" />
</Button>
<Button variant="outline" size="sm" className="hidden md:flex bg-transparent">
<Download className="mr-2 h-4 w-4" />
</Button>
</div>
</div>
{/* 用户发现概览 */}
<Collapsible
open={expandedSections.overview}
onOpenChange={(open) => setExpandedSections((prev) => ({ ...prev, overview: open }))}
>
<Card className="border-none shadow-md">
<CollapsibleTrigger className="w-full">
<CardHeader className="bg-gradient-to-r from-green-50 to-emerald-50 border-b hover:from-green-100 hover:to-emerald-100 transition-colors cursor-pointer py-3 md:py-4">
<div className="flex justify-between items-center">
<div className="flex items-center gap-3">
<Search className="h-4 w-4 md:h-5 md:w-5 text-green-600" />
<div className="text-left">
<CardTitle className="text-base md:text-lg"></CardTitle>
<CardDescription className="text-xs md:text-sm"></CardDescription>
</div>
</div>
{expandedSections.overview ? (
<ChevronDown className="h-4 w-4 md:h-5 md:w-5" />
) : (
<ChevronRight className="h-4 w-4 md:h-5 md:w-5" />
)}
</div>
</CardHeader>
</CollapsibleTrigger>
<CollapsibleContent>
<CardContent className="p-4">
<div className="grid grid-cols-2 md:grid-cols-5 gap-3 md:gap-4">
<div className="bg-blue-50 p-3 rounded-lg text-center">
<div className="text-lg md:text-2xl font-bold text-blue-600">
{discoveryData.overview.totalUsers.toLocaleString()}
</div>
<div className="text-xs text-blue-700"></div>
</div>
<div className="bg-green-50 p-3 rounded-lg text-center">
<div className="text-lg md:text-2xl font-bold text-green-600">
{discoveryData.overview.activeUsers.toLocaleString()}
</div>
<div className="text-xs text-green-700"></div>
</div>
<div className="bg-purple-50 p-3 rounded-lg text-center">
<div className="text-lg md:text-2xl font-bold text-purple-600">
{discoveryData.overview.newUsers.toLocaleString()}
</div>
<div className="text-xs text-purple-700"></div>
</div>
<div className="bg-orange-50 p-3 rounded-lg text-center">
<div className="text-lg md:text-2xl font-bold text-orange-600">
{discoveryData.overview.engagement}%
</div>
<div className="text-xs text-orange-700"></div>
</div>
<div className="bg-pink-50 p-3 rounded-lg text-center">
<div className="text-lg md:text-2xl font-bold text-pink-600">{discoveryData.overview.growth}</div>
<div className="text-xs text-pink-700"></div>
</div>
</div>
</CardContent>
</CollapsibleContent>
</Card>
</Collapsible>
{/* 行为模式分析 */}
<Collapsible
open={expandedSections.behavior}
onOpenChange={(open) => setExpandedSections((prev) => ({ ...prev, behavior: open }))}
>
<Card className="border-none shadow-md">
<CollapsibleTrigger className="w-full">
<CardHeader className="bg-gradient-to-r from-blue-50 to-indigo-50 border-b hover:from-blue-100 hover:to-indigo-100 transition-colors cursor-pointer py-3 md:py-4">
<div className="flex justify-between items-center">
<div className="flex items-center gap-3">
<BarChart3 className="h-4 w-4 md:h-5 md:w-5 text-blue-600" />
<div className="text-left">
<CardTitle className="text-base md:text-lg"></CardTitle>
<CardDescription className="text-xs md:text-sm"></CardDescription>
</div>
</div>
{expandedSections.behavior ? (
<ChevronDown className="h-4 w-4 md:h-5 md:w-5" />
) : (
<ChevronRight className="h-4 w-4 md:h-5 md:w-5" />
)}
</div>
</CardHeader>
</CollapsibleTrigger>
<CollapsibleContent>
<CardContent className="p-4">
<div className="space-y-3">
{discoveryData.behaviorPatterns.map((pattern, index) => (
<div key={index} className="bg-white border rounded-lg p-3 md:p-4">
<div className="flex flex-col md:flex-row md:items-center justify-between gap-2">
<div className="flex-1">
<h3 className="font-medium text-sm md:text-base">{pattern.pattern}</h3>
<p className="text-xs text-gray-500">{pattern.users.toLocaleString()} </p>
</div>
<div className="grid grid-cols-3 gap-3 md:gap-4 text-center">
<div>
<div className="text-sm font-bold">{pattern.avgTime}</div>
<div className="text-xs text-gray-500"></div>
</div>
<div>
<div className="text-sm font-bold">{pattern.conversion}</div>
<div className="text-xs text-gray-500"></div>
</div>
<div>
<div className="text-sm font-bold text-green-600">{pattern.trend}</div>
<div className="text-xs text-gray-500"></div>
</div>
</div>
</div>
</div>
))}
</div>
</CardContent>
</CollapsibleContent>
</Card>
</Collapsible>
{/* 用户分群 */}
<Collapsible
open={expandedSections.segmentation}
onOpenChange={(open) => setExpandedSections((prev) => ({ ...prev, segmentation: open }))}
>
<Card className="border-none shadow-md">
<CollapsibleTrigger className="w-full">
<CardHeader className="bg-gradient-to-r from-purple-50 to-pink-50 border-b hover:from-purple-100 hover:to-pink-100 transition-colors cursor-pointer py-3 md:py-4">
<div className="flex justify-between items-center">
<div className="flex items-center gap-3">
<Users className="h-4 w-4 md:h-5 md:w-5 text-purple-600" />
<div className="text-left">
<CardTitle className="text-base md:text-lg"></CardTitle>
<CardDescription className="text-xs md:text-sm"></CardDescription>
</div>
</div>
{expandedSections.segmentation ? (
<ChevronDown className="h-4 w-4 md:h-5 md:w-5" />
) : (
<ChevronRight className="h-4 w-4 md:h-5 md:w-5" />
)}
</div>
</CardHeader>
</CollapsibleTrigger>
<CollapsibleContent>
<CardContent className="p-4">
<div className="space-y-3">
{discoveryData.userSegments.map((segment, index) => (
<div key={index} className="bg-white border rounded-lg p-3 md:p-4">
<div className="flex flex-col md:flex-row md:items-center justify-between gap-3">
<div className="flex-1">
<div className="flex items-center gap-2 mb-2">
<Badge className={segment.color}>{segment.name}</Badge>
<span className="text-sm font-bold">{segment.count.toLocaleString()}</span>
<span className="text-xs text-gray-500">({segment.percentage}%)</span>
</div>
<div className="flex flex-wrap gap-1">
{segment.characteristics.map((char, charIndex) => (
<Badge key={charIndex} variant="outline" className="text-xs">
{char}
</Badge>
))}
</div>
</div>
<div className="w-full md:w-32">
<Progress value={segment.percentage} className="h-2" />
</div>
</div>
</div>
))}
</div>
</CardContent>
</CollapsibleContent>
</Card>
</Collapsible>
{/* 参与度指标 */}
<Collapsible
open={expandedSections.engagement}
onOpenChange={(open) => setExpandedSections((prev) => ({ ...prev, engagement: open }))}
>
<Card className="border-none shadow-md">
<CollapsibleTrigger className="w-full">
<CardHeader className="bg-gradient-to-r from-orange-50 to-red-50 border-b hover:from-orange-100 hover:to-red-100 transition-colors cursor-pointer py-3 md:py-4">
<div className="flex justify-between items-center">
<div className="flex items-center gap-3">
<TrendingUp className="h-4 w-4 md:h-5 md:w-5 text-orange-600" />
<div className="text-left">
<CardTitle className="text-base md:text-lg"></CardTitle>
<CardDescription className="text-xs md:text-sm"></CardDescription>
</div>
</div>
{expandedSections.engagement ? (
<ChevronDown className="h-4 w-4 md:h-5 md:w-5" />
) : (
<ChevronRight className="h-4 w-4 md:h-5 md:w-5" />
)}
</div>
</CardHeader>
</CollapsibleTrigger>
<CollapsibleContent>
<CardContent className="p-4">
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
<div className="bg-blue-50 p-4 rounded-lg">
<div className="flex items-center gap-2 mb-2">
<Clock className="h-4 w-4 text-blue-600" />
<span className="text-sm font-medium"></span>
</div>
<div className="space-y-2">
<div className="flex justify-between">
<span className="text-xs text-gray-600"></span>
<span className="text-sm font-bold">
{discoveryData.engagementMetrics.dailyActive.toLocaleString()}
</span>
</div>
<div className="flex justify-between">
<span className="text-xs text-gray-600"></span>
<span className="text-sm font-bold">
{discoveryData.engagementMetrics.weeklyActive.toLocaleString()}
</span>
</div>
<div className="flex justify-between">
<span className="text-xs text-gray-600"></span>
<span className="text-sm font-bold">
{discoveryData.engagementMetrics.monthlyActive.toLocaleString()}
</span>
</div>
</div>
</div>
<div className="bg-green-50 p-4 rounded-lg">
<div className="flex items-center gap-2 mb-2">
<Eye className="h-4 w-4 text-green-600" />
<span className="text-sm font-medium"></span>
</div>
<div className="space-y-2">
<div className="flex justify-between">
<span className="text-xs text-gray-600"></span>
<span className="text-sm font-bold">{discoveryData.engagementMetrics.avgSessionTime}</span>
</div>
<div className="flex justify-between">
<span className="text-xs text-gray-600"></span>
<span className="text-sm font-bold">{discoveryData.engagementMetrics.bounceRate}</span>
</div>
<div className="flex justify-between">
<span className="text-xs text-gray-600">访</span>
<span className="text-sm font-bold">{discoveryData.engagementMetrics.returnRate}</span>
</div>
</div>
</div>
<div className="bg-purple-50 p-4 rounded-lg">
<div className="flex items-center gap-2 mb-2">
<Smartphone className="h-4 w-4 text-purple-600" />
<span className="text-sm font-medium"></span>
</div>
<div className="space-y-2">
<div className="flex justify-between">
<span className="text-xs text-gray-600"></span>
<span className="text-sm font-bold">68.5%</span>
</div>
<div className="flex justify-between">
<span className="text-xs text-gray-600"></span>
<span className="text-sm font-bold">24.3%</span>
</div>
<div className="flex justify-between">
<span className="text-xs text-gray-600"></span>
<span className="text-sm font-bold">7.2%</span>
</div>
</div>
</div>
</div>
</CardContent>
</CollapsibleContent>
</Card>
</Collapsible>
</div>
)
}