import React, { useState, useEffect, useMemo } from 'react'; import { useNavigate } from 'react-router-dom'; 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, Plus, Search, Edit, Trash2, Play, CheckCircle2, Clock, Activity, Workflow, Eye, Pencil, FolderKanban } from 'lucide-react'; import { useToast } from '@/components/ui/use-toast'; import { getDefinitions, getWorkflowCategoryList, deleteDefinition, publishDefinition, startWorkflowInstance } from './service'; import type { WorkflowDefinition, WorkflowDefinitionQuery, WorkflowCategoryResponse, WorkflowDefinitionStatus } from './types'; import type { Page } from '@/types/base'; import { DEFAULT_PAGE_SIZE, DEFAULT_CURRENT } from '@/utils/page'; import EditModal from './components/EditModal'; import DeleteDialog from './components/DeleteDialog'; import DeployDialog from './components/DeployDialog'; import CategoryManageDialog from './components/CategoryManageDialog'; import StartWorkflowModal from './components/StartWorkflowModal'; import { getDefinitionById as getFormDefinitionById } from '@/pages/Form/Definition/service'; import type { FormDefinitionResponse } from '@/pages/Form/Definition/types'; /** * 工作流定义列表页 */ const WorkflowDefinitionList: React.FC = () => { const navigate = useNavigate(); const { toast } = useToast(); const [loading, setLoading] = useState(false); const [data, setData] = useState | null>(null); const [categories, setCategories] = useState([]); const [editModalVisible, setEditModalVisible] = useState(false); const [editRecord, setEditRecord] = useState(); const [deleteDialogOpen, setDeleteDialogOpen] = useState(false); const [deleteRecord, setDeleteRecord] = useState(null); const [deployDialogOpen, setDeployDialogOpen] = useState(false); const [deployRecord, setDeployRecord] = useState(null); const [categoryDialogOpen, setCategoryDialogOpen] = useState(false); const [startModalVisible, setStartModalVisible] = useState(false); const [startRecord, setStartRecord] = useState(null); const [formDefinition, setFormDefinition] = useState(null); const [query, setQuery] = useState({ pageNum: DEFAULT_CURRENT - 1, pageSize: DEFAULT_PAGE_SIZE, name: '', categoryId: undefined, status: undefined }); // 加载数据 const loadData = async () => { setLoading(true); try { const result = await getDefinitions(query); setData(result); } catch (error) { console.error('加载工作流定义失败:', error); } finally { setLoading(false); } }; // 加载分类 const loadCategories = async () => { try { const result = await getWorkflowCategoryList(); setCategories(result || []); } catch (error) { console.error('加载分类失败:', error); } }; useEffect(() => { loadCategories(); }, []); useEffect(() => { loadData(); }, [query]); // 搜索 const handleSearch = () => { setQuery(prev => ({ ...prev, pageNum: 0 })); }; // 重置 const handleReset = () => { setQuery({ pageNum: 0, pageSize: DEFAULT_PAGE_SIZE, name: '', categoryId: undefined, status: undefined }); }; // 新建 const handleCreate = async () => { try { // 先预加载分类列表,确保接口可用 await getWorkflowCategoryList(); // 接口成功,打开弹窗 setEditRecord(undefined); setEditModalVisible(true); } catch (error) { // 接口失败,不打开弹窗,直接报错 toast({ title: '服务异常', description: '暂时无法申请', variant: 'destructive', }); } }; // 编辑 const handleEdit = (record: WorkflowDefinition) => { setEditRecord(record); setEditModalVisible(true); }; // 设计 const handleDesign = (record: WorkflowDefinition) => { navigate(`/workflow/design/${record.id}`); }; // 发布 const handleDeploy = (record: WorkflowDefinition) => { setDeployRecord(record); setDeployDialogOpen(true); }; const confirmDeploy = async () => { if (!deployRecord) return; try { await publishDefinition(deployRecord.id); toast({ title: '发布成功', description: `工作流 "${deployRecord.name}" 已发布`, }); loadData(); setDeployDialogOpen(false); setDeployRecord(null); } catch (error) { console.error('发布失败:', error); toast({ title: '发布失败', description: error instanceof Error ? error.message : '未知错误', variant: 'destructive' }); } }; // 删除 const handleDelete = (record: WorkflowDefinition) => { setDeleteRecord(record); setDeleteDialogOpen(true); }; const confirmDelete = async () => { if (!deleteRecord) return; try { await deleteDefinition(deleteRecord.id); toast({ title: '删除成功', description: `工作流 "${deleteRecord.name}" 已删除`, }); loadData(); setDeleteDialogOpen(false); setDeleteRecord(null); } catch (error) { console.error('删除失败:', error); toast({ title: '删除失败', description: error instanceof Error ? error.message : '未知错误', variant: 'destructive' }); } }; // 启动工作流 const handleStart = async (record: WorkflowDefinition) => { // 检查是否有关联的启动表单 if (record.formDefinitionId) { // 加载表单定义数据 try { const formDef = await getFormDefinitionById(record.formDefinitionId); setFormDefinition(formDef); setStartRecord(record); setStartModalVisible(true); } catch (error) { console.error('加载启动表单失败:', error); toast({ title: '加载失败', description: '无法加载启动表单,请稍后重试', variant: 'destructive' }); } } else { // 没有启动表单,直接启动(不传递表单数据) try { const result = await startWorkflowInstance({ processKey: record.key }); console.log('🚀 工作流启动成功:', result); toast({ title: '启动成功', description: `工作流 "${record.name}" 已启动`, }); loadData(); // 刷新列表 } catch (error) { console.error('启动失败:', error); toast({ title: '启动失败', description: error instanceof Error ? error.message : '未知错误', variant: 'destructive' }); } } }; // 处理启动工作流提交(带表单数据) const handleStartWorkflowSubmit = async (workflow: WorkflowDefinition, formData: Record) => { try { console.log('🚀 启动工作流,携带表单数据:', formData); // 调用启动API,传递表单数据 const result = await startWorkflowInstance({ processKey: workflow.key, // 流程定义key formKey: formDefinition?.key, // 表单标识 formData: formData, // 表单数据 businessKey: undefined // 自动生成 businessKey }); console.log('✅ 工作流实例已创建:', result); toast({ title: '启动成功', description: `工作流 "${workflow.name}" 已启动`, }); loadData(); // 刷新列表 } catch (error) { console.error('❌ 启动失败:', error); toast({ title: '启动失败', description: error instanceof Error ? error.message : '未知错误', variant: 'destructive' }); throw error; // 重新抛出让弹窗知道失败了 } }; // 状态徽章 const getStatusBadge = (status: string) => { const statusMap: Record = { DRAFT: { variant: 'outline', text: '草稿', icon: Clock }, PUBLISHED: { variant: 'success', text: '已发布', icon: CheckCircle2 }, DISABLED: { variant: 'secondary', text: '已停用', icon: Clock }, }; 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 draftCount = data?.content?.filter(d => d.status === 'DRAFT').length || 0; const publishedCount = data?.content?.filter(d => d.status === 'PUBLISHED').length || 0; return { total, draftCount, publishedCount }; }, [data]); const pageCount = data?.totalElements ? Math.ceil(data.totalElements / (query.pageSize || DEFAULT_PAGE_SIZE)) : 0; return (

工作流定义管理

创建和管理工作流定义,设计流程图并发布上线。

{/* 统计卡片 */}
总工作流
{stats.total}

全部工作流定义

草稿
{stats.draftCount}

待发布的工作流

已发布
{stats.publishedCount}

正在使用的工作流

工作流列表
{/* 搜索栏 */}
setQuery(prev => ({ ...prev, name: e.target.value }))} onKeyDown={(e) => e.key === 'Enter' && handleSearch()} className="h-9" />
{/* 表格 */}
流程名称 流程标识 分类 版本 状态 描述 操作 {loading ? (
加载中...
) : data?.content && data.content.length > 0 ? ( data.content.map((record) => { const categoryInfo = categories.find(c => c.id === record.categoryId); const isDraft = record.status === 'DRAFT'; return ( {record.name} {record.key} {categoryInfo ? ( {categoryInfo.name} ) : ( 未分类 )} {record.flowVersion || 1} {getStatusBadge(record.status || 'DRAFT')} {record.description || '-'}
{isDraft ? ( <> ) : ( <> )}
); }) ) : (
暂无工作流定义
点击右上角"新建工作流"开始设计您的第一个工作流。
)}
{/* 分页 */} {pageCount > 1 && ( setQuery(prev => ({ ...prev, pageNum: page - 1 }))} /> )}
{/* 编辑弹窗 */} { setEditModalVisible(false); setEditRecord(undefined); }} onSuccess={loadData} record={editRecord} /> {/* 发布确认对话框 */} {/* 删除确认对话框 */} {/* 分类管理弹窗 */} {/* 启动工作流弹窗 */} { setStartModalVisible(false); setStartRecord(null); setFormDefinition(null); }} workflowDefinition={startRecord} formDefinition={formDefinition} onSubmit={handleStartWorkflowSubmit} />
); }; export default WorkflowDefinitionList;