1
This commit is contained in:
parent
2515ab3d14
commit
3374885ce2
@ -1,129 +1,115 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Modal, Steps, Card, Tag, Row, Col } from 'antd';
|
import { Modal, Steps, Card, Descriptions, Tag, Timeline } from 'antd';
|
||||||
import { CheckCircleOutlined, LoadingOutlined, CloseCircleOutlined } from '@ant-design/icons';
|
import { WorkflowHistoricalInstance, WorkflowInstanceStage } from '../types';
|
||||||
import './styles.css';
|
import dayjs from 'dayjs';
|
||||||
|
|
||||||
interface DetailModalProps {
|
interface DetailModalProps {
|
||||||
visible: boolean;
|
visible: boolean;
|
||||||
onCancel: () => void;
|
onCancel: () => void;
|
||||||
instanceData?: any;
|
instanceData?: WorkflowHistoricalInstance;
|
||||||
}
|
}
|
||||||
|
|
||||||
const mockInstanceDetail = {
|
const DetailModal: React.FC<DetailModalProps> = ({ visible, onCancel, instanceData }) => {
|
||||||
nodes: [
|
if (!instanceData) return null;
|
||||||
{
|
|
||||||
id: 'start',
|
|
||||||
name: '开始',
|
|
||||||
status: 'COMPLETED',
|
|
||||||
startTime: '2024-12-17 16:25:00',
|
|
||||||
endTime: '2024-12-17 16:25:01',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'script1',
|
|
||||||
name: '环境检查',
|
|
||||||
status: 'COMPLETED',
|
|
||||||
startTime: '2024-12-17 16:25:02',
|
|
||||||
endTime: '2024-12-17 16:25:10',
|
|
||||||
output: '环境检查完成,所有依赖已就绪'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'script2',
|
|
||||||
name: '部署应用',
|
|
||||||
status: 'RUNNING',
|
|
||||||
startTime: '2024-12-17 16:25:11',
|
|
||||||
output: '正在部署应用...'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'end',
|
|
||||||
name: '结束',
|
|
||||||
status: 'PENDING'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
};
|
|
||||||
|
|
||||||
const getStepStatus = (status: string) => {
|
const getStatusTag = (status: string) => {
|
||||||
switch (status) {
|
const statusMap: Record<string, { color: string; text: string }> = {
|
||||||
case 'COMPLETED':
|
COMPLETED: { color: 'success', text: '已完成' },
|
||||||
return 'finish';
|
RUNNING: { color: 'processing', text: '运行中' },
|
||||||
case 'RUNNING':
|
FAILED: { color: 'error', text: '失败' },
|
||||||
return 'process';
|
TERMINATED: { color: 'warning', text: '已终止' },
|
||||||
case 'ERROR':
|
NOT_STARTED: { color: 'default', text: '未执行' }
|
||||||
return 'error';
|
};
|
||||||
default:
|
const statusInfo = statusMap[status] || { color: 'default', text: status };
|
||||||
return 'wait';
|
return <Tag color={statusInfo.color}>{statusInfo.text}</Tag>;
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const getStatusTag = (status: string) => {
|
|
||||||
const statusConfig = {
|
|
||||||
COMPLETED: { color: 'success', icon: <CheckCircleOutlined />, text: '已完成' },
|
|
||||||
RUNNING: { color: 'processing', icon: <LoadingOutlined />, text: '执行中' },
|
|
||||||
ERROR: { color: 'error', icon: <CloseCircleOutlined />, text: '错误' },
|
|
||||||
PENDING: { color: 'default', text: '等待中' }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const config = statusConfig[status] || statusConfig.PENDING;
|
const getNodeTypeText = (nodeType: string) => {
|
||||||
return (
|
const nodeTypeMap: Record<string, string> = {
|
||||||
<Tag color={config.color} icon={config.icon}>
|
startEvent: '开始节点',
|
||||||
{config.text}
|
endEvent: '结束节点',
|
||||||
</Tag>
|
serviceTask: '服务任务',
|
||||||
);
|
userTask: '用户任务',
|
||||||
};
|
scriptTask: '脚本任务'
|
||||||
|
};
|
||||||
|
return nodeTypeMap[nodeType] || nodeType;
|
||||||
|
};
|
||||||
|
|
||||||
const DetailModal: React.FC<DetailModalProps> = ({ visible, onCancel }) => {
|
const getStepStatus = (stage: WorkflowInstanceStage) => {
|
||||||
const data = mockInstanceDetail;
|
switch (stage.status) {
|
||||||
const currentNodeIndex = data.nodes.findIndex(node => node.status === 'RUNNING');
|
case 'COMPLETED':
|
||||||
const currentNode = data.nodes[currentNodeIndex];
|
return 'finish';
|
||||||
|
case 'RUNNING':
|
||||||
|
return 'process';
|
||||||
|
case 'FAILED':
|
||||||
|
return 'error';
|
||||||
|
case 'TERMINATED':
|
||||||
|
return 'wait';
|
||||||
|
default:
|
||||||
|
return 'wait';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
title="流程实例详情"
|
title="流程执行详情"
|
||||||
open={visible}
|
open={visible}
|
||||||
onCancel={onCancel}
|
onCancel={onCancel}
|
||||||
|
width={1200}
|
||||||
footer={null}
|
footer={null}
|
||||||
width={800}
|
|
||||||
>
|
>
|
||||||
<div className="workflow-steps">
|
<Card className="mb-4">
|
||||||
|
<Descriptions title="基本信息" bordered column={2}>
|
||||||
|
<Descriptions.Item label="业务标识">{instanceData.businessKey}</Descriptions.Item>
|
||||||
|
<Descriptions.Item label="状态">{getStatusTag(instanceData.status)}</Descriptions.Item>
|
||||||
|
<Descriptions.Item label="开始时间">{dayjs(instanceData.startTime).format('YYYY-MM-DD HH:mm:ss')}</Descriptions.Item>
|
||||||
|
<Descriptions.Item label="结束时间">
|
||||||
|
{instanceData.endTime ? dayjs(instanceData.endTime).format('YYYY-MM-DD HH:mm:ss') : '暂无'}
|
||||||
|
</Descriptions.Item>
|
||||||
|
<Descriptions.Item label="流程实例ID">{instanceData.processInstanceId}</Descriptions.Item>
|
||||||
|
<Descriptions.Item label="流程定义ID">{instanceData.processDefinitionId}</Descriptions.Item>
|
||||||
|
</Descriptions>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
<Card title="执行阶段" className="mb-4">
|
||||||
<Steps
|
<Steps
|
||||||
current={currentNodeIndex}
|
progressDot
|
||||||
items={data.nodes.map(node => ({
|
current={instanceData.stages.length}
|
||||||
title: node.name,
|
items={instanceData.stages.map((stage) => ({
|
||||||
status: getStepStatus(node.status)
|
title: stage.nodeName,
|
||||||
|
description: (
|
||||||
|
<div className="text-xs">
|
||||||
|
<div>{getNodeTypeText(stage.nodeType)}</div>
|
||||||
|
<div>{getStatusTag(stage.status)}</div>
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
status: getStepStatus(stage)
|
||||||
}))}
|
}))}
|
||||||
/>
|
/>
|
||||||
</div>
|
</Card>
|
||||||
|
|
||||||
<Card className="current-node-info" title="当前节点详情">
|
<Card title="详细时间线">
|
||||||
{currentNode && (
|
<Timeline
|
||||||
<Row gutter={16}>
|
items={instanceData.stages.map((stage) => ({
|
||||||
<Col span={8}>
|
color: stage.status === 'COMPLETED' ? 'green' :
|
||||||
<div className="info-item">
|
stage.status === 'FAILED' ? 'red' :
|
||||||
<div className="info-label">节点名称</div>
|
stage.status === 'RUNNING' ? 'blue' : 'gray',
|
||||||
<div className="info-value">{currentNode.name}</div>
|
children: (
|
||||||
</div>
|
<div>
|
||||||
</Col>
|
<div className="font-medium">{stage.nodeName} ({getNodeTypeText(stage.nodeType)})</div>
|
||||||
<Col span={8}>
|
<div className="text-gray-500 text-sm">
|
||||||
<div className="info-item">
|
开始:{dayjs(stage.startTime).format('YYYY-MM-DD HH:mm:ss')}
|
||||||
<div className="info-label">状态</div>
|
|
||||||
<div className="info-value">{getStatusTag(currentNode.status)}</div>
|
|
||||||
</div>
|
|
||||||
</Col>
|
|
||||||
<Col span={8}>
|
|
||||||
<div className="info-item">
|
|
||||||
<div className="info-label">开始时间</div>
|
|
||||||
<div className="info-value">{currentNode.startTime || '-'}</div>
|
|
||||||
</div>
|
|
||||||
</Col>
|
|
||||||
{currentNode.output && (
|
|
||||||
<Col span={24}>
|
|
||||||
<div className="info-item">
|
|
||||||
<div className="info-label">执行输出</div>
|
|
||||||
<div className="output-block">{currentNode.output}</div>
|
|
||||||
</div>
|
</div>
|
||||||
</Col>
|
{stage.endTime && (
|
||||||
)}
|
<div className="text-gray-500 text-sm">
|
||||||
</Row>
|
结束:{dayjs(stage.endTime).format('YYYY-MM-DD HH:mm:ss')}
|
||||||
)}
|
</div>
|
||||||
|
)}
|
||||||
|
<div>{getStatusTag(stage.status)}</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}))}
|
||||||
|
/>
|
||||||
</Card>
|
</Card>
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -17,13 +17,19 @@ const HistoryModal: React.FC<HistoryModalProps> = ({ visible, onCancel, workflow
|
|||||||
const [data, setData] = useState<WorkflowHistoricalInstance[]>([]);
|
const [data, setData] = useState<WorkflowHistoricalInstance[]>([]);
|
||||||
const [total, setTotal] = useState(0);
|
const [total, setTotal] = useState(0);
|
||||||
const [query, setQuery] = useState({
|
const [query, setQuery] = useState({
|
||||||
pageNum: DEFAULT_CURRENT,
|
pageNum: DEFAULT_CURRENT - 1,
|
||||||
pageSize: DEFAULT_PAGE_SIZE,
|
pageSize: DEFAULT_PAGE_SIZE,
|
||||||
workflowDefinitionId
|
|
||||||
});
|
});
|
||||||
const [detailVisible, setDetailVisible] = useState(false);
|
const [detailVisible, setDetailVisible] = useState(false);
|
||||||
const [selectedInstance, setSelectedInstance] = useState<WorkflowHistoricalInstance>();
|
const [selectedInstance, setSelectedInstance] = useState<WorkflowHistoricalInstance>();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setQuery(prev => ({
|
||||||
|
...prev,
|
||||||
|
workflowDefinitionId
|
||||||
|
}));
|
||||||
|
}, [workflowDefinitionId]);
|
||||||
|
|
||||||
const loadData = async () => {
|
const loadData = async () => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
try {
|
try {
|
||||||
@ -118,11 +124,11 @@ const HistoryModal: React.FC<HistoryModalProps> = ({ visible, onCancel, workflow
|
|||||||
current: query.pageNum + 1,
|
current: query.pageNum + 1,
|
||||||
pageSize: query.pageSize,
|
pageSize: query.pageSize,
|
||||||
total: total,
|
total: total,
|
||||||
onChange: (page, pageSize) => setQuery({
|
onChange: (page, pageSize) => setQuery(prev => ({
|
||||||
...query,
|
...prev,
|
||||||
pageNum: page - 1,
|
pageNum: page - 1,
|
||||||
pageSize
|
pageSize
|
||||||
}),
|
})),
|
||||||
showSizeChanger: true,
|
showSizeChanger: true,
|
||||||
showQuickJumper: true,
|
showQuickJumper: true,
|
||||||
}}
|
}}
|
||||||
|
|||||||
@ -63,7 +63,7 @@ const WorkflowInstanceList: React.FC = () => {
|
|||||||
render: (time: string) => time || '暂无'
|
render: (time: string) => time || '暂无'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '状态',
|
title: '最后执行状态',
|
||||||
dataIndex: 'lastExecutionStatus',
|
dataIndex: 'lastExecutionStatus',
|
||||||
key: 'lastExecutionStatus',
|
key: 'lastExecutionStatus',
|
||||||
render: (status: string) => {
|
render: (status: string) => {
|
||||||
|
|||||||
@ -17,4 +17,4 @@ export const getWorkflowInstances = (params?: WorkflowTemplateWithInstancesQuery
|
|||||||
* @param params 查询参数
|
* @param params 查询参数
|
||||||
*/
|
*/
|
||||||
export const getHistoricalInstances = (params?: WorkflowHistoricalInstanceQuery) =>
|
export const getHistoricalInstances = (params?: WorkflowHistoricalInstanceQuery) =>
|
||||||
request.post<Page<WorkflowHistoricalInstance>>(`${INSTANCE_URL}/historical-instances`, params);
|
request.get<Page<WorkflowHistoricalInstance>>(`${INSTANCE_URL}/historical-instances`, {params});
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user