Files
users/components/data-integration/integration-history.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

241 lines
7.7 KiB
TypeScript

"use client"
import { useState } from "react"
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"
import { Button } from "@/components/ui/button"
import { Badge } from "@/components/ui/badge"
import { Input } from "@/components/ui/input"
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
import { Search, FileDown, Eye, RefreshCw } from "lucide-react"
import {
Pagination,
PaginationContent,
PaginationItem,
PaginationLink,
PaginationNext,
PaginationPrevious,
} from "@/components/ui/pagination"
interface IntegrationRecord {
id: string
sourceId: string
sourceName: string
startTime: Date
endTime: Date
status: "success" | "failed" | "partial" | "running"
totalRecords: number
successRecords: number
failedRecords: number
notes: string
}
export function IntegrationHistory() {
const [searchQuery, setSearchQuery] = useState("")
const [statusFilter, setStatusFilter] = useState("all")
// 模拟数据
const integrationRecords: IntegrationRecord[] = [
{
id: "1",
sourceId: "1",
sourceName: "CRM系统用户数据",
startTime: new Date(2023, 6, 15, 14, 30),
endTime: new Date(2023, 6, 15, 14, 45),
status: "success",
totalRecords: 5280,
successRecords: 5280,
failedRecords: 0,
notes: "完全同步成功",
},
{
id: "2",
sourceId: "2",
sourceName: "电商平台订单数据",
startTime: new Date(2023, 6, 15, 10, 15),
endTime: new Date(2023, 6, 15, 10, 40),
status: "partial",
totalRecords: 12500,
successRecords: 12350,
failedRecords: 150,
notes: "部分记录格式错误",
},
{
id: "3",
sourceId: "3",
sourceName: "营销活动参与用户",
startTime: new Date(2023, 6, 14, 9, 45),
endTime: new Date(2023, 6, 14, 9, 50),
status: "success",
totalRecords: 875,
successRecords: 875,
failedRecords: 0,
notes: "同步成功",
},
{
id: "4",
sourceId: "4",
sourceName: "APP用户行为数据",
startTime: new Date(2023, 6, 10, 16, 20),
endTime: new Date(2023, 6, 10, 16, 35),
status: "failed",
totalRecords: 8500,
successRecords: 0,
failedRecords: 8500,
notes: "API连接超时",
},
{
id: "5",
sourceId: "5",
sourceName: "社交媒体用户数据",
startTime: new Date(2023, 6, 15, 8, 0),
endTime: new Date(2023, 6, 15, 8, 15),
status: "success",
totalRecords: 3200,
successRecords: 3200,
failedRecords: 0,
notes: "同步成功",
},
{
id: "6",
sourceId: "7",
sourceName: "新用户注册数据",
startTime: new Date(2023, 6, 15, 16, 0),
endTime: null,
status: "running",
totalRecords: 0,
successRecords: 0,
failedRecords: 0,
notes: "首次同步进行中",
},
]
// 过滤记录
const filteredRecords = integrationRecords.filter((record) => {
const matchesSearch = record.sourceName.toLowerCase().includes(searchQuery.toLowerCase())
const matchesStatus = statusFilter === "all" || record.status === statusFilter
return matchesSearch && matchesStatus
})
const formatDate = (date: Date | null) => {
if (!date) return "进行中"
return date.toLocaleString("zh-CN", {
year: "numeric",
month: "2-digit",
day: "2-digit",
hour: "2-digit",
minute: "2-digit",
})
}
const getStatusBadge = (status: IntegrationRecord["status"]) => {
switch (status) {
case "success":
return <Badge className="bg-green-100 text-green-800"></Badge>
case "failed":
return <Badge className="bg-red-100 text-red-800"></Badge>
case "partial":
return <Badge className="bg-yellow-100 text-yellow-800"></Badge>
case "running":
return <Badge className="bg-blue-100 text-blue-800"></Badge>
}
}
return (
<div className="space-y-4">
<div className="flex justify-between items-center">
<div className="flex space-x-2">
<div className="relative w-64">
<Search className="absolute left-2 top-2.5 h-4 w-4 text-muted-foreground" />
<Input
placeholder="搜索数据源..."
className="pl-8"
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
/>
</div>
<Select value={statusFilter} onValueChange={setStatusFilter}>
<SelectTrigger className="w-[150px]">
<SelectValue placeholder="状态筛选" />
</SelectTrigger>
<SelectContent>
<SelectItem value="all"></SelectItem>
<SelectItem value="success"></SelectItem>
<SelectItem value="failed"></SelectItem>
<SelectItem value="partial"></SelectItem>
<SelectItem value="running"></SelectItem>
</SelectContent>
</Select>
</div>
<Button variant="outline">
<RefreshCw className="mr-2 h-4 w-4" />
</Button>
</div>
<div className="rounded-md border">
<Table>
<TableHeader>
<TableRow>
<TableHead></TableHead>
<TableHead></TableHead>
<TableHead></TableHead>
<TableHead></TableHead>
<TableHead></TableHead>
<TableHead></TableHead>
<TableHead></TableHead>
<TableHead></TableHead>
<TableHead className="text-right"></TableHead>
</TableRow>
</TableHeader>
<TableBody>
{filteredRecords.map((record) => (
<TableRow key={record.id}>
<TableCell className="font-medium">{record.sourceName}</TableCell>
<TableCell>{formatDate(record.startTime)}</TableCell>
<TableCell>{formatDate(record.endTime)}</TableCell>
<TableCell>{getStatusBadge(record.status)}</TableCell>
<TableCell>{record.totalRecords.toLocaleString()}</TableCell>
<TableCell>{record.successRecords.toLocaleString()}</TableCell>
<TableCell>{record.failedRecords.toLocaleString()}</TableCell>
<TableCell>{record.notes}</TableCell>
<TableCell className="text-right">
<div className="flex justify-end space-x-2">
<Button variant="ghost" size="icon">
<Eye className="h-4 w-4" />
</Button>
<Button variant="ghost" size="icon">
<FileDown className="h-4 w-4" />
</Button>
</div>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</div>
<Pagination>
<PaginationContent>
<PaginationItem>
<PaginationPrevious href="#" />
</PaginationItem>
<PaginationItem>
<PaginationLink href="#">1</PaginationLink>
</PaginationItem>
<PaginationItem>
<PaginationLink href="#" isActive>
2
</PaginationLink>
</PaginationItem>
<PaginationItem>
<PaginationLink href="#">3</PaginationLink>
</PaginationItem>
<PaginationItem>
<PaginationNext href="#" />
</PaginationItem>
</PaginationContent>
</Pagination>
</div>
)
}