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>
699 lines
29 KiB
TypeScript
699 lines
29 KiB
TypeScript
"use client"
|
||
|
||
import { useState } from "react"
|
||
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/ui/card"
|
||
import { Button } from "@/components/ui/button"
|
||
import { Input } from "@/components/ui/input"
|
||
import { Label } from "@/components/ui/label"
|
||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
|
||
import { Switch } from "@/components/ui/switch"
|
||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
|
||
import { Badge } from "@/components/ui/badge"
|
||
import { Separator } from "@/components/ui/separator"
|
||
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"
|
||
import { Plus, Trash2, Clock, RefreshCw, Database, Server, FileText, Settings, HelpCircle } from "lucide-react"
|
||
import {
|
||
Dialog,
|
||
DialogContent,
|
||
DialogDescription,
|
||
DialogFooter,
|
||
DialogHeader,
|
||
DialogTitle,
|
||
} from "@/components/ui/dialog"
|
||
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip"
|
||
|
||
interface CollectionTask {
|
||
id: string
|
||
name: string
|
||
source: string
|
||
type: string
|
||
schedule: string
|
||
lastRun: string | null
|
||
nextRun: string | null
|
||
status: "active" | "paused" | "error" | "completed"
|
||
recordsCollected: number
|
||
}
|
||
|
||
export function DataCollectionSettings() {
|
||
const [activeTab, setActiveTab] = useState("tasks")
|
||
const [isAddingTask, setIsAddingTask] = useState(false)
|
||
const [selectedTaskId, setSelectedTaskId] = useState<string | null>(null)
|
||
|
||
// 模拟数据采集任务
|
||
const [collectionTasks, setCollectionTasks] = useState<CollectionTask[]>([
|
||
{
|
||
id: "1",
|
||
name: "用户基本信息采集",
|
||
source: "CRM系统",
|
||
type: "数据库",
|
||
schedule: "每日 00:00",
|
||
lastRun: "2023-07-20 00:00",
|
||
nextRun: "2023-07-21 00:00",
|
||
status: "active",
|
||
recordsCollected: 125678,
|
||
},
|
||
{
|
||
id: "2",
|
||
name: "用户行为数据采集",
|
||
source: "行为分析平台",
|
||
type: "API",
|
||
schedule: "每小时",
|
||
lastRun: "2023-07-20 15:00",
|
||
nextRun: "2023-07-20 16:00",
|
||
status: "active",
|
||
recordsCollected: 458921,
|
||
},
|
||
{
|
||
id: "3",
|
||
name: "社交媒体数据采集",
|
||
source: "MCP SERVER",
|
||
type: "AI工具",
|
||
schedule: "每日 02:00",
|
||
lastRun: "2023-07-20 02:00",
|
||
nextRun: "2023-07-21 02:00",
|
||
status: "active",
|
||
recordsCollected: 87452,
|
||
},
|
||
{
|
||
id: "4",
|
||
name: "历史交易数据导入",
|
||
source: "交易系统",
|
||
type: "文件",
|
||
schedule: "手动",
|
||
lastRun: "2023-07-15 10:30",
|
||
nextRun: null,
|
||
status: "completed",
|
||
recordsCollected: 254789,
|
||
},
|
||
{
|
||
id: "5",
|
||
name: "设备信息采集",
|
||
source: "设备管理系统",
|
||
type: "API",
|
||
schedule: "每日 03:00",
|
||
lastRun: "2023-07-20 03:00",
|
||
nextRun: "2023-07-21 03:00",
|
||
status: "error",
|
||
recordsCollected: 12547,
|
||
},
|
||
])
|
||
|
||
// 模拟数据源
|
||
const dataSources = [
|
||
{ id: "crm", name: "CRM系统", type: "数据库" },
|
||
{ id: "behavior", name: "行为分析平台", type: "API" },
|
||
{ id: "mcp", name: "MCP SERVER", type: "AI工具" },
|
||
{ id: "transaction", name: "交易系统", type: "文件" },
|
||
{ id: "device", name: "设备管理系统", type: "API" },
|
||
{ id: "social", name: "社交媒体平台", type: "API" },
|
||
{ id: "ecommerce", name: "电商平台", type: "API" },
|
||
]
|
||
|
||
// 模拟采集类型
|
||
const collectionTypes = [
|
||
{ id: "full", name: "全量采集", description: "采集所有数据" },
|
||
{ id: "incremental", name: "增量采集", description: "仅采集新增或变更的数据" },
|
||
{ id: "scheduled", name: "定时采集", description: "按照设定的时间计划采集数据" },
|
||
{ id: "event", name: "事件触发采集", description: "在特定事件发生时采集数据" },
|
||
{ id: "manual", name: "手动采集", description: "手动触发数据采集" },
|
||
]
|
||
|
||
const getStatusBadge = (status: CollectionTask["status"]) => {
|
||
switch (status) {
|
||
case "active":
|
||
return <Badge className="bg-green-100 text-green-800">运行中</Badge>
|
||
case "paused":
|
||
return <Badge className="bg-yellow-100 text-yellow-800">已暂停</Badge>
|
||
case "error":
|
||
return <Badge className="bg-red-100 text-red-800">错误</Badge>
|
||
case "completed":
|
||
return <Badge className="bg-blue-100 text-blue-800">已完成</Badge>
|
||
}
|
||
}
|
||
|
||
const getSourceIcon = (type: string) => {
|
||
switch (type) {
|
||
case "数据库":
|
||
return <Database className="h-4 w-4 text-blue-500" />
|
||
case "API":
|
||
return <Server className="h-4 w-4 text-purple-500" />
|
||
case "文件":
|
||
return <FileText className="h-4 w-4 text-green-500" />
|
||
case "AI工具":
|
||
return <Settings className="h-4 w-4 text-orange-500" />
|
||
default:
|
||
return <Database className="h-4 w-4" />
|
||
}
|
||
}
|
||
|
||
const addTask = (task: Omit<CollectionTask, "id" | "lastRun" | "recordsCollected">) => {
|
||
const newTask: CollectionTask = {
|
||
id: `task-${Date.now()}`,
|
||
...task,
|
||
lastRun: null,
|
||
recordsCollected: 0,
|
||
}
|
||
setCollectionTasks([...collectionTasks, newTask])
|
||
setIsAddingTask(false)
|
||
}
|
||
|
||
const deleteTask = (id: string) => {
|
||
setCollectionTasks(collectionTasks.filter((task) => task.id !== id))
|
||
}
|
||
|
||
const toggleTaskStatus = (id: string) => {
|
||
setCollectionTasks(
|
||
collectionTasks.map((task) => {
|
||
if (task.id === id) {
|
||
return {
|
||
...task,
|
||
status: task.status === "active" ? "paused" : "active",
|
||
}
|
||
}
|
||
return task
|
||
}),
|
||
)
|
||
}
|
||
|
||
const selectedTask = selectedTaskId ? collectionTasks.find((task) => task.id === selectedTaskId) : null
|
||
|
||
return (
|
||
<div className="space-y-4">
|
||
<Card>
|
||
<CardHeader>
|
||
<CardTitle>数据采集设置</CardTitle>
|
||
<CardDescription>配置和管理数据采集任务</CardDescription>
|
||
</CardHeader>
|
||
<CardContent>
|
||
<Tabs value={activeTab} onValueChange={setActiveTab} className="space-y-4">
|
||
<TabsList>
|
||
<TabsTrigger value="tasks">采集任务</TabsTrigger>
|
||
<TabsTrigger value="sources">数据源</TabsTrigger>
|
||
<TabsTrigger value="settings">采集设置</TabsTrigger>
|
||
</TabsList>
|
||
|
||
<TabsContent value="tasks" className="space-y-4">
|
||
<div className="flex justify-between items-center">
|
||
<div className="flex items-center gap-2">
|
||
<Badge className="bg-blue-100 text-blue-800">共 {collectionTasks.length} 个任务</Badge>
|
||
<TooltipProvider>
|
||
<Tooltip>
|
||
<TooltipTrigger asChild>
|
||
<Button variant="ghost" size="icon">
|
||
<HelpCircle className="h-4 w-4" />
|
||
</Button>
|
||
</TooltipTrigger>
|
||
<TooltipContent>
|
||
<p className="max-w-xs">
|
||
数据采集任务用于从各个数据源采集数据,并将其整合到用户数据资产中台。
|
||
您可以设置采集频率、采集方式和数据处理规则。
|
||
</p>
|
||
</TooltipContent>
|
||
</Tooltip>
|
||
</TooltipProvider>
|
||
</div>
|
||
<Button onClick={() => setIsAddingTask(true)}>
|
||
<Plus 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 className="text-right">操作</TableHead>
|
||
</TableRow>
|
||
</TableHeader>
|
||
<TableBody>
|
||
{collectionTasks.map((task) => (
|
||
<TableRow key={task.id}>
|
||
<TableCell className="font-medium">{task.name}</TableCell>
|
||
<TableCell>
|
||
<div className="flex items-center gap-1">
|
||
{getSourceIcon(task.type)}
|
||
<span>{task.source}</span>
|
||
</div>
|
||
</TableCell>
|
||
<TableCell>{task.schedule}</TableCell>
|
||
<TableCell>{task.lastRun || "从未运行"}</TableCell>
|
||
<TableCell>{task.nextRun || "无计划"}</TableCell>
|
||
<TableCell>{getStatusBadge(task.status)}</TableCell>
|
||
<TableCell>{task.recordsCollected.toLocaleString()}</TableCell>
|
||
<TableCell className="text-right">
|
||
<div className="flex justify-end space-x-2">
|
||
<Button
|
||
variant="ghost"
|
||
size="icon"
|
||
onClick={() => toggleTaskStatus(task.id)}
|
||
disabled={task.status === "completed"}
|
||
>
|
||
{task.status === "active" ? (
|
||
<Clock className="h-4 w-4 text-yellow-500" />
|
||
) : (
|
||
<RefreshCw className="h-4 w-4 text-green-500" />
|
||
)}
|
||
</Button>
|
||
<Button variant="ghost" size="icon" onClick={() => setSelectedTaskId(task.id)}>
|
||
<Settings className="h-4 w-4" />
|
||
</Button>
|
||
<Button variant="ghost" size="icon" onClick={() => deleteTask(task.id)}>
|
||
<Trash2 className="h-4 w-4 text-red-500" />
|
||
</Button>
|
||
</div>
|
||
</TableCell>
|
||
</TableRow>
|
||
))}
|
||
</TableBody>
|
||
</Table>
|
||
</div>
|
||
</TabsContent>
|
||
|
||
<TabsContent value="sources" className="space-y-4">
|
||
<div className="flex justify-between items-center">
|
||
<h3 className="text-lg font-medium">可用数据源</h3>
|
||
<Button variant="outline">添加数据源</Button>
|
||
</div>
|
||
|
||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
||
{dataSources.map((source) => (
|
||
<Card key={source.id} className="border shadow-sm">
|
||
<CardContent className="p-4">
|
||
<div className="flex items-center justify-between">
|
||
<div className="flex items-center gap-2">
|
||
{getSourceIcon(source.type)}
|
||
<div>
|
||
<h4 className="font-medium">{source.name}</h4>
|
||
<p className="text-sm text-muted-foreground">{source.type}</p>
|
||
</div>
|
||
</div>
|
||
<Button variant="ghost" size="icon">
|
||
<Settings className="h-4 w-4" />
|
||
</Button>
|
||
</div>
|
||
</CardContent>
|
||
</Card>
|
||
))}
|
||
</div>
|
||
|
||
<Card className="mt-4">
|
||
<CardHeader>
|
||
<CardTitle>MCP SERVER 配置</CardTitle>
|
||
<CardDescription>配置MCP SERVER AI工具的采集参数</CardDescription>
|
||
</CardHeader>
|
||
<CardContent className="space-y-4">
|
||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||
<div className="space-y-2">
|
||
<Label htmlFor="mcp-server-url">服务器地址</Label>
|
||
<Input id="mcp-server-url" defaultValue="https://mcp.example.com/api" />
|
||
</div>
|
||
<div className="space-y-2">
|
||
<Label htmlFor="mcp-api-key">API密钥</Label>
|
||
<Input id="mcp-api-key" type="password" defaultValue="••••••••••••••••" />
|
||
</div>
|
||
</div>
|
||
|
||
<div className="space-y-2">
|
||
<Label htmlFor="mcp-model">AI模型选择</Label>
|
||
<Select defaultValue="gpt-4">
|
||
<SelectTrigger id="mcp-model">
|
||
<SelectValue placeholder="选择AI模型" />
|
||
</SelectTrigger>
|
||
<SelectContent>
|
||
<SelectItem value="gpt-4">GPT-4</SelectItem>
|
||
<SelectItem value="gpt-3.5-turbo">GPT-3.5 Turbo</SelectItem>
|
||
<SelectItem value="claude-2">Claude 2</SelectItem>
|
||
<SelectItem value="llama-2">Llama 2</SelectItem>
|
||
</SelectContent>
|
||
</Select>
|
||
</div>
|
||
|
||
<div className="space-y-2">
|
||
<div className="flex items-center justify-between">
|
||
<Label htmlFor="mcp-auto-process">自动处理采集数据</Label>
|
||
<Switch id="mcp-auto-process" defaultChecked />
|
||
</div>
|
||
<p className="text-sm text-muted-foreground">
|
||
启用后,系统将自动使用AI处理采集的数据,提取关键信息并生成标签
|
||
</p>
|
||
</div>
|
||
|
||
<Separator />
|
||
|
||
<div className="space-y-2">
|
||
<Label>采集数据类型</Label>
|
||
<div className="grid grid-cols-2 gap-2">
|
||
<div className="flex items-center space-x-2">
|
||
<Switch id="collect-profile" defaultChecked />
|
||
<Label htmlFor="collect-profile">用户资料</Label>
|
||
</div>
|
||
<div className="flex items-center space-x-2">
|
||
<Switch id="collect-posts" defaultChecked />
|
||
<Label htmlFor="collect-posts">发布内容</Label>
|
||
</div>
|
||
<div className="flex items-center space-x-2">
|
||
<Switch id="collect-interactions" defaultChecked />
|
||
<Label htmlFor="collect-interactions">互动数据</Label>
|
||
</div>
|
||
<div className="flex items-center space-x-2">
|
||
<Switch id="collect-followers" defaultChecked />
|
||
<Label htmlFor="collect-followers">关注者数据</Label>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div className="flex justify-end">
|
||
<Button>保存MCP配置</Button>
|
||
</div>
|
||
</CardContent>
|
||
</Card>
|
||
</TabsContent>
|
||
|
||
<TabsContent value="settings" className="space-y-4">
|
||
<Card>
|
||
<CardHeader>
|
||
<CardTitle>全局采集设置</CardTitle>
|
||
</CardHeader>
|
||
<CardContent className="space-y-4">
|
||
<div className="space-y-2">
|
||
<div className="flex items-center justify-between">
|
||
<Label htmlFor="enable-collection">启用数据采集</Label>
|
||
<Switch id="enable-collection" defaultChecked />
|
||
</div>
|
||
<p className="text-sm text-muted-foreground">关闭后,所有数据采集任务将暂停执行</p>
|
||
</div>
|
||
|
||
<div className="space-y-2">
|
||
<Label htmlFor="collection-threads">并发采集线程数</Label>
|
||
<Select defaultValue="5">
|
||
<SelectTrigger id="collection-threads">
|
||
<SelectValue placeholder="选择并发线程数" />
|
||
</SelectTrigger>
|
||
<SelectContent>
|
||
<SelectItem value="1">1</SelectItem>
|
||
<SelectItem value="3">3</SelectItem>
|
||
<SelectItem value="5">5</SelectItem>
|
||
<SelectItem value="10">10</SelectItem>
|
||
<SelectItem value="20">20</SelectItem>
|
||
</SelectContent>
|
||
</Select>
|
||
<p className="text-sm text-muted-foreground">
|
||
设置同时执行的数据采集任务数量,数值越大系统负载越高
|
||
</p>
|
||
</div>
|
||
|
||
<div className="space-y-2">
|
||
<Label htmlFor="retry-attempts">失败重试次数</Label>
|
||
<Select defaultValue="3">
|
||
<SelectTrigger id="retry-attempts">
|
||
<SelectValue placeholder="选择重试次数" />
|
||
</SelectTrigger>
|
||
<SelectContent>
|
||
<SelectItem value="0">不重试</SelectItem>
|
||
<SelectItem value="1">1次</SelectItem>
|
||
<SelectItem value="3">3次</SelectItem>
|
||
<SelectItem value="5">5次</SelectItem>
|
||
<SelectItem value="10">10次</SelectItem>
|
||
</SelectContent>
|
||
</Select>
|
||
</div>
|
||
|
||
<div className="space-y-2">
|
||
<Label htmlFor="retry-delay">重试间隔(秒)</Label>
|
||
<Input id="retry-delay" type="number" defaultValue="60" />
|
||
</div>
|
||
|
||
<div className="space-y-2">
|
||
<div className="flex items-center justify-between">
|
||
<Label htmlFor="data-deduplication">数据去重</Label>
|
||
<Switch id="data-deduplication" defaultChecked />
|
||
</div>
|
||
<p className="text-sm text-muted-foreground">启用后,系统将自动检测并去除重复数据</p>
|
||
</div>
|
||
|
||
<div className="space-y-2">
|
||
<div className="flex items-center justify-between">
|
||
<Label htmlFor="data-validation">数据验证</Label>
|
||
<Switch id="data-validation" defaultChecked />
|
||
</div>
|
||
<p className="text-sm text-muted-foreground">启用后,系统将验证采集数据的完整性和有效性</p>
|
||
</div>
|
||
|
||
<div className="space-y-2">
|
||
<div className="flex items-center justify-between">
|
||
<Label htmlFor="notification">采集任务通知</Label>
|
||
<Switch id="notification" defaultChecked />
|
||
</div>
|
||
<p className="text-sm text-muted-foreground">启用后,系统将在采集任务完成或出错时发送通知</p>
|
||
</div>
|
||
|
||
<div className="flex justify-end">
|
||
<Button>保存设置</Button>
|
||
</div>
|
||
</CardContent>
|
||
</Card>
|
||
</TabsContent>
|
||
</Tabs>
|
||
</CardContent>
|
||
</Card>
|
||
|
||
{/* 添加采集任务对话框 */}
|
||
<Dialog open={isAddingTask} onOpenChange={setIsAddingTask}>
|
||
<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="task-name" className="text-right">
|
||
任务名称
|
||
</Label>
|
||
<Input id="task-name" className="col-span-3" placeholder="例如:用户基本信息采集" />
|
||
</div>
|
||
<div className="grid grid-cols-4 items-center gap-4">
|
||
<Label htmlFor="data-source" className="text-right">
|
||
数据源
|
||
</Label>
|
||
<Select>
|
||
<SelectTrigger id="data-source" className="col-span-3">
|
||
<SelectValue placeholder="选择数据源" />
|
||
</SelectTrigger>
|
||
<SelectContent>
|
||
{dataSources.map((source) => (
|
||
<SelectItem key={source.id} value={source.id}>
|
||
{source.name} ({source.type})
|
||
</SelectItem>
|
||
))}
|
||
</SelectContent>
|
||
</Select>
|
||
</div>
|
||
<div className="grid grid-cols-4 items-center gap-4">
|
||
<Label htmlFor="collection-type" className="text-right">
|
||
采集类型
|
||
</Label>
|
||
<Select>
|
||
<SelectTrigger id="collection-type" className="col-span-3">
|
||
<SelectValue placeholder="选择采集类型" />
|
||
</SelectTrigger>
|
||
<SelectContent>
|
||
{collectionTypes.map((type) => (
|
||
<SelectItem key={type.id} value={type.id}>
|
||
{type.name}
|
||
</SelectItem>
|
||
))}
|
||
</SelectContent>
|
||
</Select>
|
||
</div>
|
||
<div className="grid grid-cols-4 items-center gap-4">
|
||
<Label htmlFor="schedule" className="text-right">
|
||
采集频率
|
||
</Label>
|
||
<Select>
|
||
<SelectTrigger id="schedule" className="col-span-3">
|
||
<SelectValue placeholder="选择采集频率" />
|
||
</SelectTrigger>
|
||
<SelectContent>
|
||
<SelectItem value="hourly">每小时</SelectItem>
|
||
<SelectItem value="daily">每日</SelectItem>
|
||
<SelectItem value="weekly">每周</SelectItem>
|
||
<SelectItem value="monthly">每月</SelectItem>
|
||
<SelectItem value="manual">手动</SelectItem>
|
||
</SelectContent>
|
||
</Select>
|
||
</div>
|
||
<div className="grid grid-cols-4 items-center gap-4">
|
||
<Label htmlFor="time" className="text-right">
|
||
执行时间
|
||
</Label>
|
||
<Input id="time" type="time" className="col-span-3" />
|
||
</div>
|
||
<div className="grid grid-cols-4 items-center gap-4">
|
||
<div className="text-right">
|
||
<Label htmlFor="auto-process">自动处理</Label>
|
||
</div>
|
||
<div className="flex items-center space-x-2 col-span-3">
|
||
<Switch id="auto-process" />
|
||
<Label htmlFor="auto-process">采集后自动处理数据</Label>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<DialogFooter>
|
||
<Button variant="outline" onClick={() => setIsAddingTask(false)}>
|
||
取消
|
||
</Button>
|
||
<Button
|
||
onClick={() =>
|
||
addTask({
|
||
name: "新建采集任务",
|
||
source: "CRM系统",
|
||
type: "数据库",
|
||
schedule: "每日 00:00",
|
||
nextRun: "2023-07-21 00:00",
|
||
status: "active",
|
||
})
|
||
}
|
||
>
|
||
创建任务
|
||
</Button>
|
||
</DialogFooter>
|
||
</DialogContent>
|
||
</Dialog>
|
||
|
||
{/* 任务详情对话框 */}
|
||
<Dialog open={!!selectedTaskId} onOpenChange={(open) => !open && setSelectedTaskId(null)}>
|
||
<DialogContent className="sm:max-w-[600px]">
|
||
<DialogHeader>
|
||
<DialogTitle>任务详情</DialogTitle>
|
||
<DialogDescription>查看和编辑采集任务详情</DialogDescription>
|
||
</DialogHeader>
|
||
{selectedTask && (
|
||
<div className="space-y-4 py-4">
|
||
<div className="grid grid-cols-2 gap-4">
|
||
<div>
|
||
<Label className="text-sm text-muted-foreground">任务名称</Label>
|
||
<p className="font-medium">{selectedTask.name}</p>
|
||
</div>
|
||
<div>
|
||
<Label className="text-sm text-muted-foreground">数据源</Label>
|
||
<p className="font-medium">{selectedTask.source}</p>
|
||
</div>
|
||
<div>
|
||
<Label className="text-sm text-muted-foreground">采集频率</Label>
|
||
<p className="font-medium">{selectedTask.schedule}</p>
|
||
</div>
|
||
<div>
|
||
<Label className="text-sm text-muted-foreground">状态</Label>
|
||
<div>{getStatusBadge(selectedTask.status)}</div>
|
||
</div>
|
||
<div>
|
||
<Label className="text-sm text-muted-foreground">上次运行</Label>
|
||
<p className="font-medium">{selectedTask.lastRun || "从未运行"}</p>
|
||
</div>
|
||
<div>
|
||
<Label className="text-sm text-muted-foreground">下次运行</Label>
|
||
<p className="font-medium">{selectedTask.nextRun || "无计划"}</p>
|
||
</div>
|
||
<div>
|
||
<Label className="text-sm text-muted-foreground">已采集记录</Label>
|
||
<p className="font-medium">{selectedTask.recordsCollected.toLocaleString()}</p>
|
||
</div>
|
||
</div>
|
||
|
||
<Separator />
|
||
|
||
<div className="space-y-2">
|
||
<Label>采集字段</Label>
|
||
<Table>
|
||
<TableHeader>
|
||
<TableRow>
|
||
<TableHead>字段名</TableHead>
|
||
<TableHead>数据类型</TableHead>
|
||
<TableHead>是否采集</TableHead>
|
||
</TableRow>
|
||
</TableHeader>
|
||
<TableBody>
|
||
<TableRow>
|
||
<TableCell>用户ID</TableCell>
|
||
<TableCell>字符串</TableCell>
|
||
<TableCell>
|
||
<Switch defaultChecked />
|
||
</TableCell>
|
||
</TableRow>
|
||
<TableRow>
|
||
<TableCell>手机号</TableCell>
|
||
<TableCell>字符串</TableCell>
|
||
<TableCell>
|
||
<Switch defaultChecked />
|
||
</TableCell>
|
||
</TableRow>
|
||
<TableRow>
|
||
<TableCell>身份证号</TableCell>
|
||
<TableCell>字符串</TableCell>
|
||
<TableCell>
|
||
<Switch defaultChecked />
|
||
</TableCell>
|
||
</TableRow>
|
||
<TableRow>
|
||
<TableCell>设备IMEI</TableCell>
|
||
<TableCell>字符串</TableCell>
|
||
<TableCell>
|
||
<Switch defaultChecked />
|
||
</TableCell>
|
||
</TableRow>
|
||
<TableRow>
|
||
<TableCell>注册时间</TableCell>
|
||
<TableCell>日期时间</TableCell>
|
||
<TableCell>
|
||
<Switch defaultChecked />
|
||
</TableCell>
|
||
</TableRow>
|
||
</TableBody>
|
||
</Table>
|
||
</div>
|
||
|
||
<div className="space-y-2">
|
||
<Label>数据处理规则</Label>
|
||
<div className="grid grid-cols-2 gap-2">
|
||
<div className="flex items-center space-x-2">
|
||
<Switch defaultChecked />
|
||
<Label>数据去重</Label>
|
||
</div>
|
||
<div className="flex items-center space-x-2">
|
||
<Switch defaultChecked />
|
||
<Label>数据验证</Label>
|
||
</div>
|
||
<div className="flex items-center space-x-2">
|
||
<Switch defaultChecked />
|
||
<Label>数据脱敏</Label>
|
||
</div>
|
||
<div className="flex items-center space-x-2">
|
||
<Switch defaultChecked />
|
||
<Label>数据转换</Label>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
)}
|
||
<DialogFooter>
|
||
<Button variant="outline" onClick={() => setSelectedTaskId(null)}>
|
||
关闭
|
||
</Button>
|
||
<Button variant="outline" onClick={() => {}}>
|
||
立即执行
|
||
</Button>
|
||
<Button onClick={() => setSelectedTaskId(null)}>保存更改</Button>
|
||
</DialogFooter>
|
||
</DialogContent>
|
||
</Dialog>
|
||
</div>
|
||
)
|
||
}
|