# 部署记录流程图前端绘制指南 ## 概述 本文档说明前端如何调用API获取部署记录的工作流流程图数据,以及如何使用这些数据绘制流程图并标记节点状态。 ## API接口 ### 获取部署流程图数据 **接口地址:** `GET /api/v1/deploy/records/{deployRecordId}/flow-graph` **路径参数:** - `deployRecordId` (Long): 部署记录ID **响应示例:** ```json { "success": true, "message": "操作成功", "data": { "deployRecordId": 16, "workflowInstanceId": 16, "processInstanceId": "b24d97ec-b97f-11f0-be70-de5a4815c9ef", "deployStatus": "REJECTED", "graph": { "nodes": [ { "id": "startNode", "nodeCode": "start", "nodeType": "START", "nodeName": "开始", "position": { "x": 100, "y": 200 }, "configs": {}, "inputMapping": {}, "outputs": [] }, { "id": "sid_4ee9fab9_d626_4691_816c_9435902fc3d0", "nodeCode": "approval", "nodeType": "APPROVAL", "nodeName": "审批节点", "position": { "x": 300, "y": 200 }, "configs": { "userIds": ["admin"] }, "inputMapping": {}, "outputs": [] }, { "id": "endNode", "nodeCode": "end", "nodeType": "END", "nodeName": "结束", "position": { "x": 500, "y": 200 }, "configs": {}, "inputMapping": {}, "outputs": [] } ], "edges": [ { "source": "startNode", "target": "sid_4ee9fab9_d626_4691_816c_816c_9435902fc3d0" }, { "source": "sid_4ee9fab9_d626_4691_816c_9435902fc3d0", "target": "endNode" } ] }, "nodeInstances": [ { "id": 1, "processInstanceId": "b24d97ec-b97f-11f0-be70-de5a4815c9ef", "nodeId": "startNode", "nodeName": "开始", "nodeType": "START", "status": "COMPLETED", "startTime": "2025-11-04T21:10:00", "endTime": "2025-11-04T21:10:01" }, { "id": 2, "processInstanceId": "b24d97ec-b97f-11f0-be70-de5a4815c9ef", "nodeId": "sid_4ee9fab9_d626_4691_816c_9435902fc3d0", "nodeName": "审批节点", "nodeType": "APPROVAL", "status": "REJECTED", "startTime": "2025-11-04T21:10:01", "endTime": "2025-11-04T21:14:34" }, { "id": null, "processInstanceId": "b24d97ec-b97f-11f0-be70-de5a4815c9ef", "nodeId": "endNode", "nodeName": "结束", "nodeType": "END", "status": "NOT_STARTED", "startTime": null, "endTime": null } ] } } ``` ## 数据结构说明 ### DeployRecordFlowGraphDTO | 字段 | 类型 | 说明 | |------|------|------| | `deployRecordId` | Long | 部署记录ID | | `workflowInstanceId` | Long | 工作流实例ID | | `processInstanceId` | String | Flowable流程实例ID | | `deployStatus` | String | 部署状态(CREATED/PENDING_APPROVAL/RUNNING/SUCCESS/FAILED/REJECTED/CANCELLED/TERMINATED/PARTIAL_SUCCESS) | | `graph` | WorkflowDefinitionGraph | 流程图结构数据(包含节点和边的位置信息) | | `nodeInstances` | List | 节点执行状态列表 | ### WorkflowDefinitionGraph | 字段 | 类型 | 说明 | |------|------|------| | `nodes` | List | 节点列表(包含位置信息) | | `edges` | List | 边列表(连接关系) | ### WorkflowDefinitionGraphNode | 字段 | 类型 | 说明 | |------|------|------| | `id` | String | 节点ID(用于匹配nodeInstances) | | `nodeCode` | String | 节点代码 | | `nodeType` | String | 节点类型(START/END/APPROVAL/SHELL等) | | `nodeName` | String | 节点名称 | | `position` | Map | 节点位置信息(x, y坐标) | | `configs` | Map | 节点配置信息 | | `inputMapping` | Map | 输入映射 | | `outputs` | List | 输出字段列表 | ### WorkflowNodeInstanceDTO | 字段 | 类型 | 说明 | |------|------|------| | `id` | Long | 节点实例ID(可能为null,表示未开始) | | `nodeId` | String | 节点ID(与graph.nodes中的id匹配) | | `nodeName` | String | 节点名称 | | `nodeType` | String | 节点类型 | | `status` | String | 节点执行状态(NOT_STARTED/RUNNING/COMPLETED/FAILED/REJECTED等) | | `startTime` | LocalDateTime | 开始时间 | | `endTime` | LocalDateTime | 结束时间 | ## 前端绘制流程 ### 1. 调用API获取数据 ```typescript // 使用React示例 const fetchDeployFlowGraph = async (deployRecordId: number) => { const response = await fetch(`/api/v1/deploy/records/${deployRecordId}/flow-graph`, { headers: { 'Authorization': `Bearer ${token}` } }); const result = await response.json(); return result.data; }; ``` ### 2. 绘制流程图 使用流程图库(如 `react-flow`、`antv x6`、`mxGraph` 等)绘制流程图: #### 步骤1:创建节点映射 ```typescript // 将nodeInstances转换为Map,方便查找 const nodeStatusMap = new Map( data.nodeInstances.map(node => [node.nodeId, node]) ); ``` #### 步骤2:根据graph.nodes创建节点 ```typescript const flowNodes = data.graph.nodes.map(node => { const nodeInstance = nodeStatusMap.get(node.id); const status = nodeInstance?.status || 'NOT_STARTED'; return { id: node.id, type: mapNodeType(node.nodeType), // 根据节点类型选择不同的节点组件 position: { x: node.position.x, y: node.position.y }, data: { label: node.nodeName, nodeType: node.nodeType, status: status, // 节点状态,用于样式标记 nodeInstance: nodeInstance, // 完整的节点实例信息 configs: node.configs }, style: getNodeStyle(status) // 根据状态设置样式 }; }); ``` #### 步骤3:根据graph.edges创建边 ```typescript const flowEdges = data.graph.edges.map(edge => ({ id: `${edge.source}-${edge.target}`, source: edge.source, target: edge.target, style: getEdgeStyle(edge, nodeStatusMap) // 根据节点状态设置边的样式 })); ``` ### 3. 节点状态样式映射 ```typescript // 节点状态颜色映射 const statusColorMap = { 'NOT_STARTED': '#d9d9d9', // 灰色 - 未开始 'RUNNING': '#1890ff', // 蓝色 - 运行中 'COMPLETED': '#52c41a', // 绿色 - 已完成 'FAILED': '#ff4d4f', // 红色 - 失败 'REJECTED': '#ff4d4f', // 红色 - 审批被拒绝 'CANCELLED': '#d9d9d9', // 灰色 - 已取消 'TERMINATED': '#ff4d4f' // 红色 - 已终止 }; const getNodeStyle = (status: string) => { return { background: statusColorMap[status] || '#d9d9d9', border: `2px solid ${statusColorMap[status] || '#d9d9d9'}`, borderRadius: '8px', padding: '10px', color: '#fff', fontWeight: 'bold' }; }; ``` ### 4. 边的状态样式 ```typescript const getEdgeStyle = (edge: any, nodeStatusMap: Map) => { const sourceStatus = nodeStatusMap.get(edge.source)?.status || 'NOT_STARTED'; const targetStatus = nodeStatusMap.get(edge.target)?.status || 'NOT_STARTED'; // 如果源节点已完成,边显示为已完成 if (sourceStatus === 'COMPLETED') { return { stroke: '#52c41a', strokeWidth: 2 }; } // 如果源节点失败或被拒绝,边显示为失败 if (sourceStatus === 'FAILED' || sourceStatus === 'REJECTED') { return { stroke: '#ff4d4f', strokeWidth: 2, strokeDasharray: '5,5' // 虚线表示流程中断 }; } // 默认样式 return { stroke: '#d9d9d9', strokeWidth: 1 }; }; ``` ### 5. 整体部署状态标记 ```typescript // 根据deployStatus显示整体状态 const deployStatusMap = { 'CREATED': { color: '#1890ff', text: '已创建' }, 'PENDING_APPROVAL': { color: '#faad14', text: '待审批' }, 'RUNNING': { color: '#1890ff', text: '运行中' }, 'SUCCESS': { color: '#52c41a', text: '部署成功' }, 'FAILED': { color: '#ff4d4f', text: '部署失败' }, 'REJECTED': { color: '#ff4d4f', text: '审批被拒绝' }, 'CANCELLED': { color: '#d9d9d9', text: '已取消' }, 'TERMINATED': { color: '#ff4d4f', text: '已终止' }, 'PARTIAL_SUCCESS': { color: '#faad14', text: '部分成功' } }; // 在流程图上方显示整体状态 const statusInfo = deployStatusMap[data.deployStatus]; ``` ## 完整示例(React + react-flow) ```typescript import React, { useEffect, useState } from 'react'; import ReactFlow, { Node, Edge } from 'react-flow-renderer'; interface DeployFlowGraphProps { deployRecordId: number; } const DeployFlowGraph: React.FC = ({ deployRecordId }) => { const [nodes, setNodes] = useState([]); const [edges, setEdges] = useState([]); const [deployStatus, setDeployStatus] = useState(''); useEffect(() => { fetchDeployFlowGraph(deployRecordId).then(data => { // 创建节点状态映射 const nodeStatusMap = new Map( data.nodeInstances.map(node => [node.nodeId, node]) ); // 创建节点 const flowNodes = data.graph.nodes.map(node => { const nodeInstance = nodeStatusMap.get(node.id); const status = nodeInstance?.status || 'NOT_STARTED'; return { id: node.id, type: 'default', position: { x: node.position.x, y: node.position.y }, data: { label: (
{node.nodeName}
{getStatusText(status)}
), status: status }, style: { background: getStatusColor(status), color: '#fff', border: `2px solid ${getStatusColor(status)}`, borderRadius: '8px', padding: '10px', width: 150 } }; }); // 创建边 const flowEdges = data.graph.edges.map(edge => ({ id: `${edge.source}-${edge.target}`, source: edge.source, target: edge.target, style: { stroke: getEdgeColor(edge, nodeStatusMap), strokeWidth: 2 } })); setNodes(flowNodes); setEdges(flowEdges); setDeployStatus(data.deployStatus); }); }, [deployRecordId]); return (

部署状态:{getDeployStatusText(deployStatus)}

); }; ``` ## 注意事项 1. **节点ID匹配**:`graph.nodes` 中的 `id` 与 `nodeInstances` 中的 `nodeId` 需要匹配,用于确定每个节点的执行状态。 2. **未开始的节点**:如果某个节点还没有开始执行,`nodeInstances` 中可能没有对应的记录,或者 `status` 为 `NOT_STARTED`,`id` 可能为 `null`。 3. **状态优先级**: - 如果部署状态为 `REJECTED`,说明审批被拒绝,相关审批节点的状态应该也是 `REJECTED`。 - 如果部署状态为 `PARTIAL_SUCCESS`,说明部分节点失败,需要检查哪些节点的状态是 `FAILED`。 4. **节点位置**:`graph.nodes` 中的 `position` 字段包含了节点在画布上的位置信息(x, y坐标),直接使用即可。 5. **边的绘制顺序**:`graph.edges` 中的边定义了节点之间的连接关系,按照 `source` 和 `target` 绘制即可。 ## 状态流转示意 ``` CREATED → PENDING_APPROVAL → RUNNING → SUCCESS ↓ FAILED/REJECTED ``` - **CREATED**:部署记录已创建,工作流已启动 - **PENDING_APPROVAL**:等待审批中 - **RUNNING**:审批通过,正在执行部署 - **SUCCESS**:部署成功 - **FAILED**:部署失败 - **REJECTED**:审批被拒绝(终态) - **CANCELLED**:已取消 - **TERMINATED**:已终止 - **PARTIAL_SUCCESS**:部分成功(工作流完成但存在失败的节点)