feat: refactor data asset center for enhanced search and analytics
Refactor homepage for focused search and data display; streamline data platform; enhance user and tag management; focus AI assistant on data analysis and report generation. Co-authored-by: null <4804959+fnvtk@users.noreply.github.com>
This commit is contained in:
@@ -3,552 +3,403 @@
|
||||
import { useState } from "react"
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
} from "@/components/ui/dialog"
|
||||
import { Input } from "@/components/ui/input"
|
||||
import { Label } from "@/components/ui/label"
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
|
||||
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"
|
||||
import { Badge } from "@/components/ui/badge"
|
||||
import { Database, Server, Link, Plus, FileText, RefreshCw } from "lucide-react"
|
||||
import { Progress } from "@/components/ui/progress"
|
||||
import {
|
||||
Database,
|
||||
GitBranch,
|
||||
Zap,
|
||||
Shield,
|
||||
Activity,
|
||||
CheckCircle,
|
||||
AlertTriangle,
|
||||
Clock,
|
||||
TrendingUp,
|
||||
Settings,
|
||||
Plus,
|
||||
} from "lucide-react"
|
||||
import Link from "next/link"
|
||||
|
||||
export default function DataIntegrationPage() {
|
||||
const [activeTab, setActiveTab] = useState("data-sources")
|
||||
const [isDialogOpen, setIsDialogOpen] = useState(false)
|
||||
const [activeTab, setActiveTab] = useState("overview")
|
||||
|
||||
return (
|
||||
<div className="container mx-auto py-6 space-y-8">
|
||||
<div className="flex flex-col md:flex-row justify-between items-start md:items-center gap-4">
|
||||
<div>
|
||||
<h1 className="text-3xl font-bold tracking-tight">数据中台</h1>
|
||||
<p className="text-muted-foreground">管理数据源和API接口</p>
|
||||
</div>
|
||||
</div>
|
||||
const integrationStats = {
|
||||
totalSources: 12,
|
||||
activeSources: 10,
|
||||
dailyVolume: 2456789,
|
||||
successRate: 98.5,
|
||||
avgLatency: 156,
|
||||
qualityScore: 94.2,
|
||||
}
|
||||
|
||||
<Tabs value={activeTab} onValueChange={setActiveTab} className="w-full">
|
||||
<TabsList className="grid w-full max-w-md grid-cols-2">
|
||||
<TabsTrigger value="data-sources">数据集成</TabsTrigger>
|
||||
<TabsTrigger value="api-management">API管理</TabsTrigger>
|
||||
</TabsList>
|
||||
|
||||
<TabsContent value="data-sources" className="space-y-6">
|
||||
<DataSourcesTab setIsDialogOpen={setIsDialogOpen} />
|
||||
<div className="mt-4">
|
||||
<Button variant="outline" asChild>
|
||||
<a href="/database-structure">
|
||||
<Database className="mr-2 h-4 w-4" />
|
||||
查看数据库结构
|
||||
</a>
|
||||
</Button>
|
||||
</div>
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="api-management" className="space-y-6">
|
||||
<ApiManagementTab />
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
|
||||
<AddDataSourceDialog isOpen={isDialogOpen} setIsOpen={setIsDialogOpen} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
// 数据源管理标签页
|
||||
function DataSourcesTab({ setIsDialogOpen }: { setIsDialogOpen: (open: boolean) => void }) {
|
||||
// 模拟数据源列表
|
||||
const dataSources = [
|
||||
{
|
||||
id: "1",
|
||||
name: "用户数据库",
|
||||
type: "MySQL",
|
||||
host: "db.example.com",
|
||||
id: 1,
|
||||
name: "MySQL主库",
|
||||
type: "database",
|
||||
status: "connected",
|
||||
lastSync: "2023-07-20 15:30",
|
||||
tables: 24,
|
||||
records: 156789,
|
||||
lastSync: "2分钟前",
|
||||
records: 1245678,
|
||||
quality: 98.5,
|
||||
},
|
||||
{
|
||||
id: "2",
|
||||
name: "订单系统",
|
||||
type: "PostgreSQL",
|
||||
host: "orders.example.com",
|
||||
id: 2,
|
||||
name: "触客宝API",
|
||||
type: "api",
|
||||
status: "connected",
|
||||
lastSync: "2023-07-19 12:45",
|
||||
tables: 18,
|
||||
records: 89456,
|
||||
lastSync: "5分钟前",
|
||||
records: 456789,
|
||||
quality: 96.2,
|
||||
},
|
||||
{
|
||||
id: "3",
|
||||
name: "内容库",
|
||||
type: "MongoDB",
|
||||
host: "content.example.com",
|
||||
id: 3,
|
||||
name: "抖音内容平台",
|
||||
type: "api",
|
||||
status: "warning",
|
||||
lastSync: "1小时前",
|
||||
records: 234567,
|
||||
quality: 89.3,
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: "小红书API",
|
||||
type: "api",
|
||||
status: "connected",
|
||||
lastSync: "10分钟前",
|
||||
records: 123456,
|
||||
quality: 95.8,
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
name: "微信视频号",
|
||||
type: "api",
|
||||
status: "connected",
|
||||
lastSync: "15分钟前",
|
||||
records: 98765,
|
||||
quality: 92.4,
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
name: "飞书妙记API",
|
||||
type: "api",
|
||||
status: "error",
|
||||
lastSync: "2023-07-15 09:20",
|
||||
tables: 12,
|
||||
lastSync: "2小时前",
|
||||
records: 45678,
|
||||
},
|
||||
{
|
||||
id: "4",
|
||||
name: "用户行为分析",
|
||||
type: "ClickHouse",
|
||||
host: "analytics.example.com",
|
||||
status: "connected",
|
||||
lastSync: "2023-07-20 10:15",
|
||||
tables: 8,
|
||||
records: 2345678,
|
||||
},
|
||||
{
|
||||
id: "5",
|
||||
name: "CRM系统",
|
||||
type: "Oracle",
|
||||
host: "crm.example.com",
|
||||
status: "pending",
|
||||
lastSync: "等待连接",
|
||||
tables: 0,
|
||||
records: 0,
|
||||
quality: 78.9,
|
||||
},
|
||||
]
|
||||
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
<div className="flex justify-between items-center">
|
||||
<h2 className="text-2xl font-bold">数据源管理</h2>
|
||||
<Button onClick={() => setIsDialogOpen(true)}>
|
||||
<Plus className="mr-2 h-4 w-4" />
|
||||
添加数据源
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>已连接的数据源</CardTitle>
|
||||
<CardDescription>管理和监控所有数据源连接</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHead>数据源名称</TableHead>
|
||||
<TableHead>类型</TableHead>
|
||||
<TableHead>主机地址</TableHead>
|
||||
<TableHead>状态</TableHead>
|
||||
<TableHead>最后同步</TableHead>
|
||||
<TableHead>表数量</TableHead>
|
||||
<TableHead>记录数</TableHead>
|
||||
<TableHead className="text-right">操作</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{dataSources.map((source) => (
|
||||
<TableRow key={source.id}>
|
||||
<TableCell>
|
||||
<div className="flex items-center">
|
||||
<Database className="h-4 w-4 mr-2 text-muted-foreground" />
|
||||
<span className="font-medium">{source.name}</span>
|
||||
</div>
|
||||
</TableCell>
|
||||
<TableCell>{source.type}</TableCell>
|
||||
<TableCell>{source.host}</TableCell>
|
||||
<TableCell>
|
||||
<Badge
|
||||
className={
|
||||
source.status === "connected"
|
||||
? "bg-green-100 text-green-800"
|
||||
: source.status === "error"
|
||||
? "bg-red-100 text-red-800"
|
||||
: "bg-yellow-100 text-yellow-800"
|
||||
}
|
||||
>
|
||||
{source.status === "connected" ? "已连接" : source.status === "error" ? "错误" : "等待中"}
|
||||
</Badge>
|
||||
</TableCell>
|
||||
<TableCell>{source.lastSync}</TableCell>
|
||||
<TableCell>{source.tables}</TableCell>
|
||||
<TableCell>{source.records.toLocaleString()}</TableCell>
|
||||
<TableCell className="text-right">
|
||||
<div className="flex justify-end gap-2">
|
||||
<Button variant="outline" size="sm">
|
||||
<Link className="h-4 w-4 mr-1" />
|
||||
查看
|
||||
</Button>
|
||||
<Button size="sm">
|
||||
<RefreshCw className="h-4 w-4 mr-1" />
|
||||
同步
|
||||
</Button>
|
||||
</div>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>数据源类型</CardTitle>
|
||||
<CardDescription>支持的数据库和数据源类型</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="grid grid-cols-2 md:grid-cols-4 gap-4">
|
||||
<div className="flex flex-col items-center p-4 border rounded-lg">
|
||||
<Database className="h-8 w-8 mb-2 text-blue-500" />
|
||||
<span className="font-medium">MySQL</span>
|
||||
<span className="text-xs text-muted-foreground">关系型数据库</span>
|
||||
</div>
|
||||
<div className="flex flex-col items-center p-4 border rounded-lg">
|
||||
<Database className="h-8 w-8 mb-2 text-blue-500" />
|
||||
<span className="font-medium">PostgreSQL</span>
|
||||
<span className="text-xs text-muted-foreground">关系型数据库</span>
|
||||
</div>
|
||||
<div className="flex flex-col items-center p-4 border rounded-lg">
|
||||
<Database className="h-8 w-8 mb-2 text-green-500" />
|
||||
<span className="font-medium">MongoDB</span>
|
||||
<span className="text-xs text-muted-foreground">文档型数据库</span>
|
||||
</div>
|
||||
<div className="flex flex-col items-center p-4 border rounded-lg">
|
||||
<Database className="h-8 w-8 mb-2 text-yellow-500" />
|
||||
<span className="font-medium">ClickHouse</span>
|
||||
<span className="text-xs text-muted-foreground">列式数据库</span>
|
||||
</div>
|
||||
<div className="flex flex-col items-center p-4 border rounded-lg">
|
||||
<Database className="h-8 w-8 mb-2 text-red-500" />
|
||||
<span className="font-medium">Oracle</span>
|
||||
<span className="text-xs text-muted-foreground">关系型数据库</span>
|
||||
</div>
|
||||
<div className="flex flex-col items-center p-4 border rounded-lg">
|
||||
<Database className="h-8 w-8 mb-2 text-purple-500" />
|
||||
<span className="font-medium">SQL Server</span>
|
||||
<span className="text-xs text-muted-foreground">关系型数据库</span>
|
||||
</div>
|
||||
<div className="flex flex-col items-center p-4 border rounded-lg">
|
||||
<Server className="h-8 w-8 mb-2 text-gray-500" />
|
||||
<span className="font-medium">Redis</span>
|
||||
<span className="text-xs text-muted-foreground">键值存储</span>
|
||||
</div>
|
||||
<div className="flex flex-col items-center p-4 border rounded-lg">
|
||||
<FileText className="h-8 w-8 mb-2 text-gray-500" />
|
||||
<span className="font-medium">CSV/Excel</span>
|
||||
<span className="text-xs text-muted-foreground">文件导入</span>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
// API管理标签页
|
||||
function ApiManagementTab() {
|
||||
// 模拟API接口数据
|
||||
const apiEndpoints = [
|
||||
const recentActivities = [
|
||||
{
|
||||
id: "1",
|
||||
name: "用户数据API",
|
||||
endpoint: "/api/users",
|
||||
method: "GET",
|
||||
category: "用户画像",
|
||||
status: "active",
|
||||
calls: 12567,
|
||||
lastCalled: "2023-07-20 16:45",
|
||||
id: 1,
|
||||
type: "sync_complete",
|
||||
message: "MySQL主库数据同步完成",
|
||||
time: "2分钟前",
|
||||
status: "success",
|
||||
},
|
||||
{
|
||||
id: "2",
|
||||
name: "用户标签API",
|
||||
endpoint: "/api/users/tags",
|
||||
method: "GET",
|
||||
category: "用户画像",
|
||||
status: "active",
|
||||
calls: 8945,
|
||||
lastCalled: "2023-07-20 15:30",
|
||||
id: 2,
|
||||
type: "quality_check",
|
||||
message: "触客宝API数据质量检查通过",
|
||||
time: "8分钟前",
|
||||
status: "success",
|
||||
},
|
||||
{
|
||||
id: "3",
|
||||
name: "流量池数据API",
|
||||
endpoint: "/api/traffic-pools",
|
||||
method: "GET",
|
||||
category: "流量池",
|
||||
status: "active",
|
||||
calls: 5678,
|
||||
lastCalled: "2023-07-20 14:20",
|
||||
id: 3,
|
||||
type: "sync_warning",
|
||||
message: "抖音内容平台同步延迟",
|
||||
time: "1小时前",
|
||||
status: "warning",
|
||||
},
|
||||
{
|
||||
id: "4",
|
||||
name: "AI分析API",
|
||||
endpoint: "/api/ai/analyze",
|
||||
method: "POST",
|
||||
category: "AI分析",
|
||||
status: "active",
|
||||
calls: 3456,
|
||||
lastCalled: "2023-07-20 13:15",
|
||||
},
|
||||
{
|
||||
id: "5",
|
||||
name: "数据同步API",
|
||||
endpoint: "/api/sync",
|
||||
method: "POST",
|
||||
category: "数据集成",
|
||||
status: "maintenance",
|
||||
calls: 2345,
|
||||
lastCalled: "2023-07-19 10:30",
|
||||
id: 4,
|
||||
type: "sync_error",
|
||||
message: "飞书妙记API连接失败",
|
||||
time: "2小时前",
|
||||
status: "error",
|
||||
},
|
||||
]
|
||||
|
||||
// 模拟API密钥数据
|
||||
const apiKeys = [
|
||||
{
|
||||
id: "1",
|
||||
name: "Web应用",
|
||||
key: "sk_web_*************",
|
||||
created: "2023-05-15",
|
||||
lastUsed: "2023-07-20",
|
||||
status: "active",
|
||||
},
|
||||
{
|
||||
id: "2",
|
||||
name: "移动应用",
|
||||
key: "sk_mobile_*************",
|
||||
created: "2023-06-10",
|
||||
lastUsed: "2023-07-19",
|
||||
status: "active",
|
||||
},
|
||||
{
|
||||
id: "3",
|
||||
name: "第三方集成",
|
||||
key: "sk_partner_*************",
|
||||
created: "2023-04-20",
|
||||
lastUsed: "2023-07-18",
|
||||
status: "active",
|
||||
},
|
||||
]
|
||||
const getStatusIcon = (status: string) => {
|
||||
switch (status) {
|
||||
case "connected":
|
||||
return <CheckCircle className="h-4 w-4 text-green-500" />
|
||||
case "warning":
|
||||
return <AlertTriangle className="h-4 w-4 text-yellow-500" />
|
||||
case "error":
|
||||
return <AlertTriangle className="h-4 w-4 text-red-500" />
|
||||
default:
|
||||
return <Clock className="h-4 w-4 text-gray-500" />
|
||||
}
|
||||
}
|
||||
|
||||
const getStatusColor = (status: string) => {
|
||||
switch (status) {
|
||||
case "connected":
|
||||
return "bg-green-100 text-green-800"
|
||||
case "warning":
|
||||
return "bg-yellow-100 text-yellow-800"
|
||||
case "error":
|
||||
return "bg-red-100 text-red-800"
|
||||
default:
|
||||
return "bg-gray-100 text-gray-800"
|
||||
}
|
||||
}
|
||||
|
||||
const getActivityIcon = (type: string) => {
|
||||
switch (type) {
|
||||
case "sync_complete":
|
||||
return <CheckCircle className="h-4 w-4 text-green-500" />
|
||||
case "quality_check":
|
||||
return <Shield className="h-4 w-4 text-blue-500" />
|
||||
case "sync_warning":
|
||||
return <AlertTriangle className="h-4 w-4 text-yellow-500" />
|
||||
case "sync_error":
|
||||
return <AlertTriangle className="h-4 w-4 text-red-500" />
|
||||
default:
|
||||
return <Activity className="h-4 w-4 text-gray-500" />
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
<div className="flex justify-between items-center">
|
||||
<h2 className="text-2xl font-bold">API接口管理</h2>
|
||||
<Button>
|
||||
<Plus className="mr-2 h-4 w-4" />
|
||||
创建新API
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>API接口列表</CardTitle>
|
||||
<CardDescription>所有可用的API接口</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHead>API名称</TableHead>
|
||||
<TableHead>接口地址</TableHead>
|
||||
<TableHead>方法</TableHead>
|
||||
<TableHead>分类</TableHead>
|
||||
<TableHead>状态</TableHead>
|
||||
<TableHead>调用次数</TableHead>
|
||||
<TableHead>最后调用</TableHead>
|
||||
<TableHead className="text-right">操作</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{apiEndpoints.map((api) => (
|
||||
<TableRow key={api.id}>
|
||||
<TableCell className="font-medium">{api.name}</TableCell>
|
||||
<TableCell>
|
||||
<code className="bg-muted px-1 py-0.5 rounded text-sm">{api.endpoint}</code>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Badge
|
||||
className={
|
||||
api.method === "GET"
|
||||
? "bg-blue-100 text-blue-800"
|
||||
: api.method === "POST"
|
||||
? "bg-green-100 text-green-800"
|
||||
: api.method === "PUT"
|
||||
? "bg-yellow-100 text-yellow-800"
|
||||
: "bg-red-100 text-red-800"
|
||||
}
|
||||
>
|
||||
{api.method}
|
||||
</Badge>
|
||||
</TableCell>
|
||||
<TableCell>{api.category}</TableCell>
|
||||
<TableCell>
|
||||
<Badge
|
||||
className={
|
||||
api.status === "active" ? "bg-green-100 text-green-800" : "bg-yellow-100 text-yellow-800"
|
||||
}
|
||||
>
|
||||
{api.status === "active" ? "正常" : "维护中"}
|
||||
</Badge>
|
||||
</TableCell>
|
||||
<TableCell>{api.calls.toLocaleString()}</TableCell>
|
||||
<TableCell>{api.lastCalled}</TableCell>
|
||||
<TableCell className="text-right">
|
||||
<div className="flex justify-end gap-2">
|
||||
<Button variant="outline" size="sm">
|
||||
文档
|
||||
</Button>
|
||||
<Button size="sm">测试</Button>
|
||||
</div>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>API密钥管理</CardTitle>
|
||||
<CardDescription>管理API访问密钥</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHead>应用名称</TableHead>
|
||||
<TableHead>密钥</TableHead>
|
||||
<TableHead>创建时间</TableHead>
|
||||
<TableHead>最后使用</TableHead>
|
||||
<TableHead>状态</TableHead>
|
||||
<TableHead className="text-right">操作</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{apiKeys.map((key) => (
|
||||
<TableRow key={key.id}>
|
||||
<TableCell className="font-medium">{key.name}</TableCell>
|
||||
<TableCell>
|
||||
<code className="bg-muted px-1 py-0.5 rounded text-sm">{key.key}</code>
|
||||
</TableCell>
|
||||
<TableCell>{key.created}</TableCell>
|
||||
<TableCell>{key.lastUsed}</TableCell>
|
||||
<TableCell>
|
||||
<Badge className="bg-green-100 text-green-800">{key.status === "active" ? "有效" : "已禁用"}</Badge>
|
||||
</TableCell>
|
||||
<TableCell className="text-right">
|
||||
<div className="flex justify-end gap-2">
|
||||
<Button variant="outline" size="sm">
|
||||
重置
|
||||
</Button>
|
||||
<Button variant="outline" size="sm" className="text-red-500">
|
||||
撤销
|
||||
</Button>
|
||||
</div>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>API使用统计</CardTitle>
|
||||
<CardDescription>API调用量和性能统计</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent className="h-80 flex items-center justify-center">
|
||||
<div className="text-center text-muted-foreground">
|
||||
<p>API调用统计图表</p>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
// 添加数据源对话框
|
||||
function AddDataSourceDialog({ isOpen, setIsOpen }: { isOpen: boolean; setIsOpen: (open: boolean) => void }) {
|
||||
const [dbType, setDbType] = useState("mysql")
|
||||
|
||||
return (
|
||||
<Dialog open={isOpen} onOpenChange={setIsOpen}>
|
||||
<DialogContent className="sm:max-w-[500px]">
|
||||
<DialogHeader>
|
||||
<DialogTitle>添加新数据源</DialogTitle>
|
||||
<DialogDescription>连接到新的数据库或数据源</DialogDescription>
|
||||
</DialogHeader>
|
||||
<div className="grid gap-4 py-4">
|
||||
<div className="grid grid-cols-4 items-center gap-4">
|
||||
<Label htmlFor="db-type" className="text-right">
|
||||
数据库类型
|
||||
</Label>
|
||||
<Select value={dbType} onValueChange={setDbType} className="col-span-3">
|
||||
<SelectTrigger id="db-type">
|
||||
<SelectValue placeholder="选择数据库类型" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="mysql">MySQL</SelectItem>
|
||||
<SelectItem value="postgresql">PostgreSQL</SelectItem>
|
||||
<SelectItem value="mongodb">MongoDB</SelectItem>
|
||||
<SelectItem value="clickhouse">ClickHouse</SelectItem>
|
||||
<SelectItem value="oracle">Oracle</SelectItem>
|
||||
<SelectItem value="sqlserver">SQL Server</SelectItem>
|
||||
<SelectItem value="redis">Redis</SelectItem>
|
||||
<SelectItem value="file">CSV/Excel文件</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
<div className="grid grid-cols-4 items-center gap-4">
|
||||
<Label htmlFor="name" className="text-right">
|
||||
数据源名称
|
||||
</Label>
|
||||
<Input id="name" placeholder="给数据源起个名字" className="col-span-3" />
|
||||
</div>
|
||||
<div className="grid grid-cols-4 items-center gap-4">
|
||||
<Label htmlFor="host" className="text-right">
|
||||
主机地址
|
||||
</Label>
|
||||
<Input id="host" placeholder="例如: db.example.com" className="col-span-3" />
|
||||
</div>
|
||||
<div className="grid grid-cols-4 items-center gap-4">
|
||||
<Label htmlFor="port" className="text-right">
|
||||
端口
|
||||
</Label>
|
||||
<Input
|
||||
id="port"
|
||||
placeholder={dbType === "mysql" ? "3306" : dbType === "postgresql" ? "5432" : "27017"}
|
||||
className="col-span-3"
|
||||
/>
|
||||
</div>
|
||||
<div className="grid grid-cols-4 items-center gap-4">
|
||||
<Label htmlFor="database" className="text-right">
|
||||
数据库名
|
||||
</Label>
|
||||
<Input id="database" placeholder="数据库名称" className="col-span-3" />
|
||||
</div>
|
||||
<div className="grid grid-cols-4 items-center gap-4">
|
||||
<Label htmlFor="username" className="text-right">
|
||||
用户名
|
||||
</Label>
|
||||
<Input id="username" placeholder="数据库用户名" className="col-span-3" />
|
||||
</div>
|
||||
<div className="grid grid-cols-4 items-center gap-4">
|
||||
<Label htmlFor="password" className="text-right">
|
||||
密码
|
||||
</Label>
|
||||
<Input id="password" type="password" placeholder="数据库密码" className="col-span-3" />
|
||||
</div>
|
||||
<div className="container mx-auto py-6 space-y-6">
|
||||
{/* 页面标题 */}
|
||||
<div className="flex flex-col md:flex-row md:justify-between md:items-center gap-4">
|
||||
<div>
|
||||
<h1 className="text-3xl font-bold tracking-tight">数据对接</h1>
|
||||
<p className="text-muted-foreground">数据源管理与全流程监控</p>
|
||||
</div>
|
||||
<DialogFooter>
|
||||
<Button variant="outline" onClick={() => setIsOpen(false)}>
|
||||
取消
|
||||
<div className="flex gap-2">
|
||||
<Button>
|
||||
<Plus className="mr-2 h-4 w-4" />
|
||||
添加数据源
|
||||
</Button>
|
||||
<Button type="submit">测试连接</Button>
|
||||
<Button type="submit">保存</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
<Button variant="outline">
|
||||
<Settings className="mr-2 h-4 w-4" />
|
||||
配置管理
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 核心指标 */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
|
||||
<Card className="bg-gradient-to-r from-blue-50 to-cyan-50 border-none shadow-md">
|
||||
<CardHeader className="pb-3">
|
||||
<div className="flex items-center justify-between">
|
||||
<CardTitle className="text-sm font-medium">数据源总数</CardTitle>
|
||||
<Database className="h-4 w-4 text-blue-600" />
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="text-2xl font-bold text-blue-600">{integrationStats.totalSources}</div>
|
||||
<div className="text-xs text-muted-foreground mt-1">活跃: {integrationStats.activeSources}个</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card className="bg-gradient-to-r from-green-50 to-emerald-50 border-none shadow-md">
|
||||
<CardHeader className="pb-3">
|
||||
<div className="flex items-center justify-between">
|
||||
<CardTitle className="text-sm font-medium">日处理量</CardTitle>
|
||||
<Activity className="h-4 w-4 text-green-600" />
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="text-2xl font-bold text-green-600">
|
||||
{(integrationStats.dailyVolume / 1000000).toFixed(1)}M
|
||||
</div>
|
||||
<div className="text-xs text-muted-foreground mt-1">条记录</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card className="bg-gradient-to-r from-purple-50 to-pink-50 border-none shadow-md">
|
||||
<CardHeader className="pb-3">
|
||||
<div className="flex items-center justify-between">
|
||||
<CardTitle className="text-sm font-medium">成功率</CardTitle>
|
||||
<TrendingUp className="h-4 w-4 text-purple-600" />
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="text-2xl font-bold text-purple-600">{integrationStats.successRate}%</div>
|
||||
<div className="text-xs text-muted-foreground mt-1">同步成功率</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card className="bg-gradient-to-r from-orange-50 to-red-50 border-none shadow-md">
|
||||
<CardHeader className="pb-3">
|
||||
<div className="flex items-center justify-between">
|
||||
<CardTitle className="text-sm font-medium">平均延迟</CardTitle>
|
||||
<Zap className="h-4 w-4 text-orange-600" />
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="text-2xl font-bold text-orange-600">{integrationStats.avgLatency}ms</div>
|
||||
<div className="text-xs text-muted-foreground mt-1">响应时间</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
{/* 数据源状态 */}
|
||||
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
|
||||
<Card className="lg:col-span-2">
|
||||
<CardHeader>
|
||||
<CardTitle className="flex items-center gap-2">
|
||||
<GitBranch className="h-5 w-5 text-blue-600" />
|
||||
数据源状态
|
||||
</CardTitle>
|
||||
<CardDescription>各数据源连接状态与同步情况</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="space-y-4">
|
||||
{dataSources.map((source) => (
|
||||
<div key={source.id} className="flex items-center justify-between p-4 border rounded-lg">
|
||||
<div className="flex items-center gap-3">
|
||||
{getStatusIcon(source.status)}
|
||||
<div>
|
||||
<p className="font-medium text-sm">{source.name}</p>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
{source.type === "database" ? "数据库" : "API接口"} • 最后同步: {source.lastSync}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="text-right">
|
||||
<Badge className={getStatusColor(source.status)}>
|
||||
{source.status === "connected" ? "已连接" : source.status === "warning" ? "警告" : "错误"}
|
||||
</Badge>
|
||||
<div className="flex items-center gap-4 mt-1 text-xs text-muted-foreground">
|
||||
<span>{source.records.toLocaleString()} 条</span>
|
||||
<span>质量: {source.quality}%</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<div className="flex justify-between mt-4">
|
||||
<Link href="/data-integration/sources">
|
||||
<Button variant="outline">管理数据源</Button>
|
||||
</Link>
|
||||
<Button>添加新数据源</Button>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
{/* 实时活动 */}
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="flex items-center gap-2">
|
||||
<Activity className="h-5 w-5 text-green-600" />
|
||||
实时活动
|
||||
</CardTitle>
|
||||
<CardDescription>数据同步活动日志</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="space-y-3">
|
||||
{recentActivities.map((activity) => (
|
||||
<div key={activity.id} className="flex items-start gap-3 p-2 hover:bg-gray-50 rounded-lg">
|
||||
{getActivityIcon(activity.type)}
|
||||
<div className="flex-1 min-w-0">
|
||||
<p className="text-sm font-medium truncate">{activity.message}</p>
|
||||
<p className="text-xs text-gray-500">{activity.time}</p>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<Button variant="outline" className="w-full mt-4 bg-transparent">
|
||||
查看全部日志
|
||||
</Button>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
{/* 数据流程概览 */}
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="flex items-center gap-2">
|
||||
<Zap className="h-5 w-5 text-purple-600" />
|
||||
数据流程概览
|
||||
</CardTitle>
|
||||
<CardDescription>数据从接入到处理的完整流程</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="grid grid-cols-1 md:grid-cols-4 gap-6">
|
||||
<Link href="/data-integration/sources">
|
||||
<div className="text-center p-4 border rounded-lg hover:bg-gray-50 transition-colors cursor-pointer">
|
||||
<GitBranch className="h-8 w-8 mx-auto mb-2 text-blue-600" />
|
||||
<h3 className="font-medium mb-1">数据源管理</h3>
|
||||
<p className="text-xs text-muted-foreground">配置和管理各种数据源</p>
|
||||
<Badge className="mt-2 bg-blue-100 text-blue-700">{integrationStats.totalSources}个源</Badge>
|
||||
</div>
|
||||
</Link>
|
||||
|
||||
<Link href="/data-integration/ingestion">
|
||||
<div className="text-center p-4 border rounded-lg hover:bg-gray-50 transition-colors cursor-pointer">
|
||||
<Database className="h-8 w-8 mx-auto mb-2 text-green-600" />
|
||||
<h3 className="font-medium mb-1">数据接入</h3>
|
||||
<p className="text-xs text-muted-foreground">实时数据采集和同步</p>
|
||||
<Badge className="mt-2 bg-green-100 text-green-700">
|
||||
{(integrationStats.dailyVolume / 1000000).toFixed(1)}M/日
|
||||
</Badge>
|
||||
</div>
|
||||
</Link>
|
||||
|
||||
<Link href="/data-integration/processing">
|
||||
<div className="text-center p-4 border rounded-lg hover:bg-gray-50 transition-colors cursor-pointer">
|
||||
<Zap className="h-8 w-8 mx-auto mb-2 text-purple-600" />
|
||||
<h3 className="font-medium mb-1">数据处理</h3>
|
||||
<p className="text-xs text-muted-foreground">清洗、转换和标准化</p>
|
||||
<Badge className="mt-2 bg-purple-100 text-purple-700">{integrationStats.successRate}%成功</Badge>
|
||||
</div>
|
||||
</Link>
|
||||
|
||||
<Link href="/data-integration/quality">
|
||||
<div className="text-center p-4 border rounded-lg hover:bg-gray-50 transition-colors cursor-pointer">
|
||||
<Shield className="h-8 w-8 mx-auto mb-2 text-orange-600" />
|
||||
<h3 className="font-medium mb-1">质量监控</h3>
|
||||
<p className="text-xs text-muted-foreground">数据质量评估和监控</p>
|
||||
<Badge className="mt-2 bg-orange-100 text-orange-700">{integrationStats.qualityScore}%质量</Badge>
|
||||
</div>
|
||||
</Link>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
{/* 性能监控 */}
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="flex items-center gap-2">
|
||||
<TrendingUp className="h-5 w-5 text-green-600" />
|
||||
性能监控
|
||||
</CardTitle>
|
||||
<CardDescription>数据处理性能指标</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
|
||||
<div>
|
||||
<div className="flex justify-between text-sm mb-2">
|
||||
<span>数据处理速度</span>
|
||||
<span className="font-medium">85%</span>
|
||||
</div>
|
||||
<Progress value={85} className="h-2 mb-1" />
|
||||
<p className="text-xs text-muted-foreground">1.2M 记录/小时</p>
|
||||
</div>
|
||||
<div>
|
||||
<div className="flex justify-between text-sm mb-2">
|
||||
<span>系统资源使用</span>
|
||||
<span className="font-medium">67%</span>
|
||||
</div>
|
||||
<Progress value={67} className="h-2 mb-1" />
|
||||
<p className="text-xs text-muted-foreground">CPU + 内存</p>
|
||||
</div>
|
||||
<div>
|
||||
<div className="flex justify-between text-sm mb-2">
|
||||
<span>存储使用率</span>
|
||||
<span className="font-medium">42%</span>
|
||||
</div>
|
||||
<Progress value={42} className="h-2 mb-1" />
|
||||
<p className="text-xs text-muted-foreground">2.1TB / 5TB</p>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user