import React, { useState } from "react"; import { Button, Card, Progress, Badge, Tabs } from "antd"; import { GitBranch, Play, Pause, Square, Download, Upload, Plus, Settings, Database, Filter, Shuffle, Target, Zap, Clock, CheckCircle, AlertCircle, XCircle, Eye, Copy, Edit, ArrowRight, ArrowLeft, } from "lucide-react"; import { useNavigate } from "react-router"; import DevelopmentInProgress from "@/components/DevelopmentInProgress.tsx"; const { TabPane } = Tabs; interface FlowNode { id: string; type: string; name: string; description: string; position: { x: number; y: number }; config: any; status: "idle" | "running" | "completed" | "error"; progress?: number; } interface FlowConnection { id: string; source: string; target: string; } interface FlowTemplate { id: number; name: string; description: string; category: string; nodes: FlowNode[]; connections: FlowConnection[]; createdAt: string; lastUsed?: string; usageCount: number; } interface FlowExecution { id: number; templateName: string; status: "running" | "completed" | "failed" | "paused"; progress: number; startTime: string; endTime?: string; duration?: string; processedRecords: number; totalRecords: number; } const nodeTypes = [ { type: "data-source", name: "数据源", icon: Database, description: "从各种数据源读取数据", color: "bg-blue-500", category: "输入", }, { type: "data-filter", name: "数据过滤", icon: Filter, description: "根据条件过滤数据", color: "bg-green-500", category: "处理", }, { type: "data-transform", name: "数据转换", icon: Shuffle, description: "转换数据格式和结构", color: "bg-purple-500", category: "处理", }, { type: "data-validation", name: "数据验证", icon: Target, description: "验证数据质量和完整性", color: "bg-orange-500", category: "处理", }, { type: "data-enhancement", name: "数据增强", icon: Zap, description: "增强和丰富数据内容", color: "bg-pink-500", category: "处理", }, { type: "data-output", name: "数据输出", icon: Download, description: "将处理后的数据输出到目标位置", color: "bg-indigo-500", category: "输出", }, ]; const mockTemplates: FlowTemplate[] = [ { id: 1, name: "WSI病理图像预处理流程", description: "专用于WSI病理图像的标准化预处理流程", category: "医学影像", nodes: [ { id: "node1", type: "data-source", name: "WSI图像源", description: "读取WSI病理图像", position: { x: 100, y: 100 }, config: { source: "wsi_pathology", format: "svs" }, status: "idle", }, { id: "node2", type: "data-validation", name: "图像质量检查", description: "检查图像质量和完整性", position: { x: 300, y: 100 }, config: { minSize: "1GB", maxSize: "5GB" }, status: "idle", }, { id: "node3", type: "data-transform", name: "图像标准化", description: "标准化图像格式和尺寸", position: { x: 500, y: 100 }, config: { targetFormat: "tiff", normalize: true }, status: "idle", }, { id: "node4", type: "data-output", name: "处理结果输出", description: "输出处理后的图像", position: { x: 700, y: 100 }, config: { destination: "processed_wsi" }, status: "idle", }, ], connections: [ { id: "conn1", source: "node1", target: "node2" }, { id: "conn2", source: "node2", target: "node3" }, { id: "conn3", source: "node3", target: "node4" }, ], createdAt: "2024-01-20", lastUsed: "2024-01-23", usageCount: 15, }, { id: 2, name: "文本数据清洗流程", description: "通用文本数据清洗和标准化流程", category: "文本处理", nodes: [ { id: "node1", type: "data-source", name: "文本数据源", description: "读取原始文本数据", position: { x: 100, y: 100 }, config: { source: "text_corpus", encoding: "utf-8" }, status: "idle", }, { id: "node2", type: "data-filter", name: "内容过滤", description: "过滤无效和重复内容", position: { x: 300, y: 100 }, config: { minLength: 10, removeDuplicates: true }, status: "idle", }, { id: "node3", type: "data-enhancement", name: "文本增强", description: "文本清洗和格式化", position: { x: 500, y: 100 }, config: { removeHtml: true, normalizeWhitespace: true }, status: "idle", }, { id: "node4", type: "data-output", name: "清洗结果输出", description: "输出清洗后的文本", position: { x: 700, y: 100 }, config: { format: "jsonl" }, status: "idle", }, ], connections: [ { id: "conn1", source: "node1", target: "node2" }, { id: "conn2", source: "node2", target: "node3" }, { id: "conn3", source: "node3", target: "node4" }, ], createdAt: "2024-01-18", lastUsed: "2024-01-22", usageCount: 28, }, ]; const mockExecutions: FlowExecution[] = [ { id: 1, templateName: "WSI病理图像预处理流程", status: "running", progress: 65, startTime: "2024-01-23 14:30:00", processedRecords: 650, totalRecords: 1000, }, { id: 2, templateName: "文本数据清洗流程", status: "completed", progress: 100, startTime: "2024-01-23 10:15:00", endTime: "2024-01-23 12:45:00", duration: "2h 30m", processedRecords: 50000, totalRecords: 50000, }, { id: 3, templateName: "WSI病理图像预处理流程", status: "failed", progress: 25, startTime: "2024-01-22 16:20:00", endTime: "2024-01-22 16:45:00", duration: "25m", processedRecords: 250, totalRecords: 1000, }, ]; export default function OrchestrationPage() { return ; const navigate = useNavigate(); const [templates, setTemplates] = useState(mockTemplates); const [executions, setExecutions] = useState(mockExecutions); const [selectedTemplate, setSelectedTemplate] = useState( null ); const [showWorkflowEditor, setShowWorkflowEditor] = useState(false); const startNewFlow = () => { setShowWorkflowEditor(true); }; const handleSaveWorkflow = (workflow: any) => { setTemplates([workflow, ...templates]); setShowWorkflowEditor(false); }; const handleBackFromEditor = () => { setShowWorkflowEditor(false); }; if (showWorkflowEditor) { const WorkflowEditor = React.lazy(() => import("./WorkflowEditor.tsx")); return ( Loading...}> ); } const executeTemplate = (template: FlowTemplate) => { const newExecution: FlowExecution = { id: Date.now(), templateName: template.name, status: "running", progress: 0, startTime: new Date().toLocaleString(), processedRecords: 0, totalRecords: 1000, }; setExecutions([newExecution, ...executions]); // 模拟执行进度 const interval = setInterval(() => { setExecutions((prev) => prev.map((exec) => { if (exec.id === newExecution.id) { const newProgress = Math.min( exec.progress + Math.random() * 10, 100 ); return { ...exec, progress: newProgress, status: newProgress >= 100 ? "completed" : "running", processedRecords: Math.floor( (newProgress / 100) * exec.totalRecords ), endTime: newProgress >= 100 ? new Date().toLocaleString() : undefined, }; } return exec; }) ); }, 500); setTimeout(() => clearInterval(interval), 10000); }; const getStatusIcon = (status: string) => { switch (status) { case "running": return ; case "completed": return ; case "failed": return ; case "paused": return ; default: return ; } }; const getStatusBadge = (status: string) => { const statusConfig = { running: { label: "运行中", color: "processing" as const }, completed: { label: "已完成", color: "success" as const }, failed: { label: "失败", color: "error" as const }, paused: { label: "已暂停", color: "warning" as const }, }; return ( statusConfig[status as keyof typeof statusConfig] || statusConfig.running ); }; const getNodeIcon = (nodeType: string) => { const nodeTypeInfo = nodeTypes.find((nt) => nt.type === nodeType); const IconComponent = nodeTypeInfo?.icon || Settings; return ; }; return (
{/* Header */}

数据智能编排

{/* Main Content */} 流程模板 ({templates.length})} key="templates" >
{templates.map((template) => (

{template.name}

{template.description}

{template.category}
{template.nodes.length} 个节点
{template.connections.length} 个连接
创建于 {template.createdAt}
使用 {template.usageCount} 次
{/* Flow Preview */}
流程预览:
{template.nodes.map((node, index) => (
{getNodeIcon(node.type)} {node.name}
{index < template.nodes.length - 1 && ( )}
))}
))}
执行历史 ({executions.length})} key="executions" >
{executions.map((execution) => (
{getStatusIcon(execution.status)}

{execution.templateName}

执行ID: {execution.id}

{getStatusBadge(execution.status).label} {execution.status === "running" && (
)}
{execution.status === "running" && (
执行进度 {execution.processedRecords.toLocaleString()} /{" "} {execution.totalRecords.toLocaleString()}
)}
开始时间:
{execution.startTime}
{execution.endTime && (
结束时间:
{execution.endTime}
)} {execution.duration && (
执行时长:
{execution.duration}
)}
处理记录:
{execution.processedRecords.toLocaleString()}
))}
实时监控} key="monitoring">

{executions.filter((e) => e.status === "running").length}

运行中

{executions.filter((e) => e.status === "completed").length}

已完成

{executions.filter((e) => e.status === "failed").length}

失败

{templates.length}

流程模板

{/* Real-time Execution Monitor */}

实时执行监控

当前正在执行的流程实时状态
{executions.filter((e) => e.status === "running").length > 0 ? (
{executions .filter((e) => e.status === "running") .map((execution) => (

{execution.templateName}

运行中
进度: {Math.round(execution.progress)}% {execution.processedRecords.toLocaleString()} /{" "} {execution.totalRecords.toLocaleString()}
开始时间: {execution.startTime}
))}
) : (

当前没有正在执行的流程

)}
{/* Template Detail Modal */} {selectedTemplate && (
{selectedTemplate.name}
{selectedTemplate.description}
{selectedTemplate.nodes.length}
处理节点
{selectedTemplate.connections.length}
节点连接
{selectedTemplate.usageCount}
使用次数
{selectedTemplate.createdAt}
创建日期

流程节点详情

{selectedTemplate.nodes.map((node, index) => (
{index + 1}
{getNodeIcon(node.type)} {node.name} { nodeTypes.find((nt) => nt.type === node.type) ?.category }
{node.description}
{Object.keys(node.config).length > 0 && (
配置:{" "} {JSON.stringify(node.config, null, 2)}
)}
))}
)}
); }