import React, { useState, useEffect, useMemo } from 'react'; import { Card, CardHeader, CardTitle, CardContent } from '@/components/ui/card'; import { Table, TableHeader, TableBody, TableRow, TableHead, TableCell } from '@/components/ui/table'; import { Badge } from '@/components/ui/badge'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'; import { DataTablePagination } from '@/components/ui/pagination'; import { Loader2, Search, Eye, StopCircle, Activity, PlayCircle, CheckCircle2, Clock, Workflow, XCircle, Pause } from 'lucide-react'; import { getWorkflowInstances } from './service'; import type { WorkflowTemplateWithInstances } from './types'; import type { Page } from '@/types/base'; import { DEFAULT_PAGE_SIZE, DEFAULT_CURRENT } from '@/utils/page'; import HistoryModal from './components/HistoryModal'; import dayjs from 'dayjs'; /** * 工作流实例列表页 */ const WorkflowInstanceList: React.FC = () => { const [loading, setLoading] = useState(false); const [data, setData] = useState | null>(null); const [historyVisible, setHistoryVisible] = useState(false); const [selectedWorkflowDefinitionId, setSelectedWorkflowDefinitionId] = useState(); const [query, setQuery] = useState({ pageNum: DEFAULT_CURRENT - 1, pageSize: DEFAULT_PAGE_SIZE, businessKey: '', status: undefined as string | undefined, }); // 加载数据 const loadData = async () => { setLoading(true); try { const result = await getWorkflowInstances(query); setData(result); } catch (error) { console.error('加载流程实例失败:', error); } finally { setLoading(false); } }; useEffect(() => { loadData(); }, [query]); // 搜索 const handleSearch = () => { setQuery(prev => ({ ...prev, pageNum: 0, })); }; // 重置搜索 const handleReset = () => { setQuery({ pageNum: 0, pageSize: DEFAULT_PAGE_SIZE, businessKey: '', status: undefined, }); }; // 查看历史 const handleViewHistory = (record: WorkflowTemplateWithInstances) => { setSelectedWorkflowDefinitionId(record.id); setHistoryVisible(true); }; // 终止流程(TODO:需要后端接口) const handleTerminate = async (record: WorkflowTemplateWithInstances) => { if (!confirm(`确定要终止工作流 "${record.name}" 吗?`)) return; console.log('终止流程', record); // TODO: 调用终止接口 }; // 状态徽章 const getStatusBadge = (status: string) => { const statusMap: Record = { NOT_STARTED: { variant: 'outline', text: '未启动', icon: Clock }, CREATED: { variant: 'secondary', text: '已创建', icon: PlayCircle }, RUNNING: { variant: 'default', text: '运行中', icon: Activity }, SUSPENDED: { variant: 'secondary', text: '已挂起', icon: Pause }, COMPLETED: { variant: 'success', text: '已完成', icon: CheckCircle2 }, TERMINATED: { variant: 'destructive', text: '已终止', icon: StopCircle }, FAILED: { variant: 'destructive', text: '失败', icon: XCircle }, }; const statusInfo = statusMap[status] || { variant: 'outline', text: status || '未知', icon: Clock }; const Icon = statusInfo.icon; return ( {statusInfo.text} ); }; // 统计数据 const stats = useMemo(() => { const total = data?.totalElements || 0; const runningCount = data?.content?.filter(d => d.lastExecutionStatus === 'RUNNING').length || 0; const completedCount = data?.content?.filter(d => d.lastExecutionStatus === 'COMPLETED').length || 0; const failedCount = data?.content?.filter(d => d.lastExecutionStatus === 'FAILED' || d.lastExecutionStatus === 'TERMINATED').length || 0; return { total, runningCount, completedCount, failedCount }; }, [data]); const pageCount = data?.totalElements ? Math.ceil(data.totalElements / query.pageSize) : 0; return (

工作流实例管理

查看和管理工作流实例的运行状态和执行历史。

{/* 统计卡片 */}
总实例数
{stats.total}

所有工作流实例

运行中
{stats.runningCount}

正在执行的实例

已完成
{stats.completedCount}

成功执行完成

失败/终止
{stats.failedCount}

执行失败或被终止

实例列表 {/* 搜索栏 */}
setQuery(prev => ({ ...prev, businessKey: e.target.value }))} onKeyDown={(e) => e.key === 'Enter' && handleSearch()} className="h-9" />
{/* 表格 */}
流程名称 业务标识 最后执行时间 执行状态 操作 {loading ? (
加载中...
) : data?.content && data.content.length > 0 ? ( data.content.map((record) => ( {record.name} {record.businessKey ? ( {record.businessKey} ) : ( - )} {record.lastExecutionTime ? dayjs(record.lastExecutionTime).format('YYYY-MM-DD HH:mm:ss') : '-'} {getStatusBadge(record.lastExecutionStatus)}
{record.lastExecutionStatus === 'RUNNING' && ( )}
)) ) : (
暂无工作流实例
启动工作流后,实例记录将在此显示。
)}
{/* 分页 */} {pageCount > 1 && ( setQuery(prev => ({ ...prev, pageNum: page - 1 }))} /> )}
{/* 历史记录弹窗 */} setHistoryVisible(false)} workflowDefinitionId={selectedWorkflowDefinitionId} />
); }; export default WorkflowInstanceList;