refactor: restructure navigation and module layout

Reorganize navigation and module structure based on new requirements.

Co-authored-by: null <4804959+fnvtk@users.noreply.github.com>
This commit is contained in:
v0
2026-01-31 04:32:36 +00:00
parent 22e725887a
commit b17b488f8e
105 changed files with 20530 additions and 3622 deletions

View File

@@ -0,0 +1,348 @@
"use client"
import { useState } from "react"
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
import { Badge } from "@/components/ui/badge"
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
import { Database, RefreshCw, CheckCircle2, AlertTriangle, Search, FileText, Upload, Download, Filter, TrendingUp, Zap, Tag } from 'lucide-react'
import { Progress } from "@/components/ui/progress"
export default function DataManagement() {
const [searchQuery, setSearchQuery] = useState("")
// 数据源管理
const dataSources = [
{
id: 1,
name: "私域系统数据源",
type: "微信生态",
status: "active",
lastSync: "2分钟前",
users: 2850000000,
syncRate: 98.5,
dataSize: "850TB",
},
{
id: 2,
name: "电商平台数据",
type: "淘宝/京东",
status: "active",
lastSync: "5分钟前",
users: 680000000,
syncRate: 95.2,
dataSize: "210TB",
},
{
id: 3,
name: "表单收集数据",
type: "第三方表单",
status: "active",
lastSync: "10分钟前",
users: 425000000,
syncRate: 92.8,
dataSize: "125TB",
},
{
id: 4,
name: "碰撞补全数据",
type: "数据碰撞",
status: "syncing",
lastSync: "正在同步",
users: 280000000,
syncRate: 76.3,
dataSize: "95TB",
},
{
id: 5,
name: "项目API数据源",
type: "外部API",
status: "active",
lastSync: "1分钟前",
users: 50670000,
syncRate: 99.1,
dataSize: "18TB",
},
]
// 数据清洗进度
const cleaningTasks = [
{ name: "手机号格式校验", total: 4285670000, processed: 4200000000, progress: 98.0, errors: 1250000 },
{ name: "重复数据去除", total: 4285670000, processed: 3850000000, progress: 89.8, errors: 85000000 },
{ name: "缺失字段补全", total: 4285670000, processed: 3250000000, progress: 75.8, errors: 125000000 },
{ name: "异常值检测", total: 4285670000, processed: 4100000000, progress: 95.7, errors: 8500000 },
]
// 标签系统统计
const tagStats = {
totalTags: 1258,
systemTags: 485,
customTags: 773,
activeRules: 2850,
todayTagged: 2845000,
}
// 数据质量检测
const qualityChecks = [
{ type: "重复数据", count: 85420000, percentage: 2.0, severity: "warning" },
{ type: "异常数据", count: 12850000, percentage: 0.3, severity: "error" },
{ type: "缺失字段", count: 325680000, percentage: 7.6, severity: "warning" },
{ type: "格式错误", count: 5280000, percentage: 0.12, severity: "error" },
]
const formatNumber = (num: number): string => {
if (num >= 1000000000) return `${(num / 1000000000).toFixed(1)}B`
if (num >= 1000000) return `${(num / 1000000).toFixed(1)}M`
if (num >= 1000) return `${(num / 1000).toFixed(1)}K`
return num.toString()
}
return (
<div className="min-h-screen bg-black text-white p-6">
{/* Header */}
<div className="mb-8 flex items-center justify-between">
<div>
<h1 className="text-4xl font-bold mb-2"></h1>
<p className="text-gray-400"></p>
</div>
<div className="flex items-center gap-4">
<Button variant="outline" className="bg-white/5 border-white/10 hover:bg-white/10">
<Upload className="w-4 h-4 mr-2" />
</Button>
<Button variant="outline" className="bg-white/5 border-white/10 hover:bg-white/10">
<Download className="w-4 h-4 mr-2" />
</Button>
</div>
</div>
<Tabs defaultValue="sources" className="space-y-6">
<TabsList className="bg-white/5 border border-white/10">
<TabsTrigger value="sources"></TabsTrigger>
<TabsTrigger value="cleaning"></TabsTrigger>
<TabsTrigger value="tags"></TabsTrigger>
<TabsTrigger value="quality"></TabsTrigger>
</TabsList>
{/* 数据源管理 */}
<TabsContent value="sources" className="space-y-6">
{/* 搜索栏 */}
<div className="flex items-center gap-4">
<div className="relative flex-1">
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 w-4 h-4 text-gray-400" />
<Input
placeholder="搜索数据源..."
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
className="pl-10 bg-white/5 border-white/10"
/>
</div>
<Button variant="outline" className="bg-white/5 border-white/10 hover:bg-white/10">
<Filter className="w-4 h-4 mr-2" />
</Button>
</div>
{/* 数据源列表 */}
<div className="grid grid-cols-1 gap-4">
{dataSources.map((source) => (
<Card key={source.id} className="bg-white/5 border-white/10">
<CardContent className="p-6">
<div className="flex items-center justify-between mb-4">
<div className="flex items-center gap-4">
<div className="w-12 h-12 rounded-lg bg-gradient-to-br from-blue-500 to-purple-500 flex items-center justify-center">
<Database className="w-6 h-6" />
</div>
<div>
<h3 className="text-lg font-semibold text-white">{source.name}</h3>
<p className="text-sm text-gray-400">{source.type}</p>
</div>
</div>
<div className="flex items-center gap-4">
<Badge
variant="outline"
className={
source.status === "active"
? "border-green-500/50 text-green-400"
: "border-yellow-500/50 text-yellow-400"
}
>
{source.status === "active" ? (
<>
<CheckCircle2 className="w-3 h-3 mr-1" />
</>
) : (
<>
<RefreshCw className="w-3 h-3 mr-1 animate-spin" />
</>
)}
</Badge>
<Button size="sm" variant="outline" className="bg-white/5 border-white/10 hover:bg-white/10">
<RefreshCw className="w-3 h-3 mr-1" />
</Button>
</div>
</div>
<div className="grid grid-cols-4 gap-4 mb-3">
<div>
<div className="text-sm text-gray-400 mb-1"></div>
<div className="text-xl font-bold text-white">{formatNumber(source.users)}</div>
</div>
<div>
<div className="text-sm text-gray-400 mb-1"></div>
<div className="text-xl font-bold text-green-400">{source.syncRate}%</div>
</div>
<div>
<div className="text-sm text-gray-400 mb-1"></div>
<div className="text-xl font-bold text-blue-400">{source.dataSize}</div>
</div>
<div>
<div className="text-sm text-gray-400 mb-1"></div>
<div className="text-sm font-semibold text-white">{source.lastSync}</div>
</div>
</div>
<Progress value={source.syncRate} className="h-2" />
</CardContent>
</Card>
))}
</div>
</TabsContent>
{/* 数据清洗 */}
<TabsContent value="cleaning" className="space-y-6">
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
{cleaningTasks.map((task, index) => (
<Card key={index} className="bg-white/5 border-white/10">
<CardHeader>
<CardTitle className="text-white flex items-center gap-2">
<Zap className="w-5 h-5 text-yellow-400" />
{task.name}
</CardTitle>
</CardHeader>
<CardContent>
<div className="space-y-4">
<div className="flex items-center justify-between">
<span className="text-gray-400"></span>
<span className="text-2xl font-bold text-green-400">{task.progress}%</span>
</div>
<Progress value={task.progress} className="h-2" />
<div className="grid grid-cols-2 gap-4 pt-4 border-t border-white/10">
<div>
<div className="text-sm text-gray-400 mb-1"></div>
<div className="text-lg font-semibold text-white">{formatNumber(task.processed)}</div>
</div>
<div>
<div className="text-sm text-gray-400 mb-1"></div>
<div className="text-lg font-semibold text-red-400">{formatNumber(task.errors)}</div>
</div>
</div>
</div>
</CardContent>
</Card>
))}
</div>
</TabsContent>
{/* 标签系统 */}
<TabsContent value="tags" className="space-y-6">
<div className="grid grid-cols-1 lg:grid-cols-5 gap-6 mb-6">
<Card className="bg-gradient-to-br from-purple-500/20 to-purple-900/20 border-purple-500/30">
<CardContent className="p-6 text-center">
<Tag className="w-8 h-8 text-purple-400 mx-auto mb-2" />
<div className="text-3xl font-bold text-purple-400 mb-1">{tagStats.totalTags}</div>
<div className="text-sm text-gray-400"></div>
</CardContent>
</Card>
<Card className="bg-white/5 border-white/10">
<CardContent className="p-6 text-center">
<FileText className="w-8 h-8 text-blue-400 mx-auto mb-2" />
<div className="text-3xl font-bold text-blue-400 mb-1">{tagStats.systemTags}</div>
<div className="text-sm text-gray-400"></div>
</CardContent>
</Card>
<Card className="bg-white/5 border-white/10">
<CardContent className="p-6 text-center">
<Tag className="w-8 h-8 text-green-400 mx-auto mb-2" />
<div className="text-3xl font-bold text-green-400 mb-1">{tagStats.customTags}</div>
<div className="text-sm text-gray-400"></div>
</CardContent>
</Card>
<Card className="bg-white/5 border-white/10">
<CardContent className="p-6 text-center">
<Zap className="w-8 h-8 text-yellow-400 mx-auto mb-2" />
<div className="text-3xl font-bold text-yellow-400 mb-1">{tagStats.activeRules}</div>
<div className="text-sm text-gray-400"></div>
</CardContent>
</Card>
<Card className="bg-white/5 border-white/10">
<CardContent className="p-6 text-center">
<TrendingUp className="w-8 h-8 text-orange-400 mx-auto mb-2" />
<div className="text-3xl font-bold text-orange-400 mb-1">{formatNumber(tagStats.todayTagged)}</div>
<div className="text-sm text-gray-400"></div>
</CardContent>
</Card>
</div>
<Card className="bg-white/5 border-white/10">
<CardHeader>
<CardTitle className="text-white"></CardTitle>
</CardHeader>
<CardContent>
<div className="text-gray-400 text-center py-8">
...
</div>
</CardContent>
</Card>
</TabsContent>
{/* 质量检测 */}
<TabsContent value="quality" className="space-y-6">
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
{qualityChecks.map((check, index) => (
<Card key={index} className="bg-white/5 border-white/10">
<CardContent className="p-6">
<div className="flex items-center justify-between mb-4">
<div className="flex items-center gap-3">
{check.severity === "error" ? (
<AlertTriangle className="w-6 h-6 text-red-400" />
) : (
<AlertTriangle className="w-6 h-6 text-yellow-400" />
)}
<h3 className="text-lg font-semibold text-white">{check.type}</h3>
</div>
<Badge
variant="outline"
className={
check.severity === "error"
? "border-red-500/50 text-red-400"
: "border-yellow-500/50 text-yellow-400"
}
>
{check.severity === "error" ? "严重" : "警告"}
</Badge>
</div>
<div className="space-y-2">
<div className="flex items-center justify-between">
<span className="text-gray-400"></span>
<span className="text-2xl font-bold text-white">{formatNumber(check.count)}</span>
</div>
<div className="flex items-center justify-between">
<span className="text-gray-400"></span>
<span className="text-lg font-semibold text-white">{check.percentage}%</span>
</div>
</div>
</CardContent>
</Card>
))}
</div>
</TabsContent>
</Tabs>
</div>
)
}