1
This commit is contained in:
parent
2515ab3d14
commit
3374885ce2
@ -1,129 +1,115 @@
|
||||
import React from 'react';
|
||||
import { Modal, Steps, Card, Tag, Row, Col } from 'antd';
|
||||
import { CheckCircleOutlined, LoadingOutlined, CloseCircleOutlined } from '@ant-design/icons';
|
||||
import './styles.css';
|
||||
import { Modal, Steps, Card, Descriptions, Tag, Timeline } from 'antd';
|
||||
import { WorkflowHistoricalInstance, WorkflowInstanceStage } from '../types';
|
||||
import dayjs from 'dayjs';
|
||||
|
||||
interface DetailModalProps {
|
||||
visible: boolean;
|
||||
onCancel: () => void;
|
||||
instanceData?: any;
|
||||
instanceData?: WorkflowHistoricalInstance;
|
||||
}
|
||||
|
||||
const mockInstanceDetail = {
|
||||
nodes: [
|
||||
{
|
||||
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 DetailModal: React.FC<DetailModalProps> = ({ visible, onCancel, instanceData }) => {
|
||||
if (!instanceData) return null;
|
||||
|
||||
const getStepStatus = (status: string) => {
|
||||
switch (status) {
|
||||
const getStatusTag = (status: string) => {
|
||||
const statusMap: Record<string, { color: string; text: string }> = {
|
||||
COMPLETED: { color: 'success', text: '已完成' },
|
||||
RUNNING: { color: 'processing', text: '运行中' },
|
||||
FAILED: { color: 'error', text: '失败' },
|
||||
TERMINATED: { color: 'warning', text: '已终止' },
|
||||
NOT_STARTED: { color: 'default', text: '未执行' }
|
||||
};
|
||||
const statusInfo = statusMap[status] || { color: 'default', text: status };
|
||||
return <Tag color={statusInfo.color}>{statusInfo.text}</Tag>;
|
||||
};
|
||||
|
||||
const getNodeTypeText = (nodeType: string) => {
|
||||
const nodeTypeMap: Record<string, string> = {
|
||||
startEvent: '开始节点',
|
||||
endEvent: '结束节点',
|
||||
serviceTask: '服务任务',
|
||||
userTask: '用户任务',
|
||||
scriptTask: '脚本任务'
|
||||
};
|
||||
return nodeTypeMap[nodeType] || nodeType;
|
||||
};
|
||||
|
||||
const getStepStatus = (stage: WorkflowInstanceStage) => {
|
||||
switch (stage.status) {
|
||||
case 'COMPLETED':
|
||||
return 'finish';
|
||||
case 'RUNNING':
|
||||
return 'process';
|
||||
case 'ERROR':
|
||||
case 'FAILED':
|
||||
return 'error';
|
||||
case 'TERMINATED':
|
||||
return 'wait';
|
||||
default:
|
||||
return 'wait';
|
||||
}
|
||||
};
|
||||
|
||||
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;
|
||||
return (
|
||||
<Tag color={config.color} icon={config.icon}>
|
||||
{config.text}
|
||||
</Tag>
|
||||
);
|
||||
};
|
||||
|
||||
const DetailModal: React.FC<DetailModalProps> = ({ visible, onCancel }) => {
|
||||
const data = mockInstanceDetail;
|
||||
const currentNodeIndex = data.nodes.findIndex(node => node.status === 'RUNNING');
|
||||
const currentNode = data.nodes[currentNodeIndex];
|
||||
|
||||
return (
|
||||
<Modal
|
||||
title="流程实例详情"
|
||||
title="流程执行详情"
|
||||
open={visible}
|
||||
onCancel={onCancel}
|
||||
width={1200}
|
||||
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
|
||||
current={currentNodeIndex}
|
||||
items={data.nodes.map(node => ({
|
||||
title: node.name,
|
||||
status: getStepStatus(node.status)
|
||||
progressDot
|
||||
current={instanceData.stages.length}
|
||||
items={instanceData.stages.map((stage) => ({
|
||||
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="当前节点详情">
|
||||
{currentNode && (
|
||||
<Row gutter={16}>
|
||||
<Col span={8}>
|
||||
<div className="info-item">
|
||||
<div className="info-label">节点名称</div>
|
||||
<div className="info-value">{currentNode.name}</div>
|
||||
<Card title="详细时间线">
|
||||
<Timeline
|
||||
items={instanceData.stages.map((stage) => ({
|
||||
color: stage.status === 'COMPLETED' ? 'green' :
|
||||
stage.status === 'FAILED' ? 'red' :
|
||||
stage.status === 'RUNNING' ? 'blue' : 'gray',
|
||||
children: (
|
||||
<div>
|
||||
<div className="font-medium">{stage.nodeName} ({getNodeTypeText(stage.nodeType)})</div>
|
||||
<div className="text-gray-500 text-sm">
|
||||
开始:{dayjs(stage.startTime).format('YYYY-MM-DD HH:mm:ss')}
|
||||
</div>
|
||||
</Col>
|
||||
<Col span={8}>
|
||||
<div className="info-item">
|
||||
<div className="info-label">状态</div>
|
||||
<div className="info-value">{getStatusTag(currentNode.status)}</div>
|
||||
{stage.endTime && (
|
||||
<div className="text-gray-500 text-sm">
|
||||
结束:{dayjs(stage.endTime).format('YYYY-MM-DD HH:mm:ss')}
|
||||
</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>
|
||||
</Col>
|
||||
)}
|
||||
</Row>
|
||||
)}
|
||||
<div>{getStatusTag(stage.status)}</div>
|
||||
</div>
|
||||
)
|
||||
}))}
|
||||
/>
|
||||
</Card>
|
||||
</Modal>
|
||||
);
|
||||
|
||||
@ -17,13 +17,19 @@ const HistoryModal: React.FC<HistoryModalProps> = ({ visible, onCancel, workflow
|
||||
const [data, setData] = useState<WorkflowHistoricalInstance[]>([]);
|
||||
const [total, setTotal] = useState(0);
|
||||
const [query, setQuery] = useState({
|
||||
pageNum: DEFAULT_CURRENT,
|
||||
pageNum: DEFAULT_CURRENT - 1,
|
||||
pageSize: DEFAULT_PAGE_SIZE,
|
||||
workflowDefinitionId
|
||||
});
|
||||
const [detailVisible, setDetailVisible] = useState(false);
|
||||
const [selectedInstance, setSelectedInstance] = useState<WorkflowHistoricalInstance>();
|
||||
|
||||
useEffect(() => {
|
||||
setQuery(prev => ({
|
||||
...prev,
|
||||
workflowDefinitionId
|
||||
}));
|
||||
}, [workflowDefinitionId]);
|
||||
|
||||
const loadData = async () => {
|
||||
setLoading(true);
|
||||
try {
|
||||
@ -118,11 +124,11 @@ const HistoryModal: React.FC<HistoryModalProps> = ({ visible, onCancel, workflow
|
||||
current: query.pageNum + 1,
|
||||
pageSize: query.pageSize,
|
||||
total: total,
|
||||
onChange: (page, pageSize) => setQuery({
|
||||
...query,
|
||||
onChange: (page, pageSize) => setQuery(prev => ({
|
||||
...prev,
|
||||
pageNum: page - 1,
|
||||
pageSize
|
||||
}),
|
||||
})),
|
||||
showSizeChanger: true,
|
||||
showQuickJumper: true,
|
||||
}}
|
||||
|
||||
@ -63,7 +63,7 @@ const WorkflowInstanceList: React.FC = () => {
|
||||
render: (time: string) => time || '暂无'
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
title: '最后执行状态',
|
||||
dataIndex: 'lastExecutionStatus',
|
||||
key: 'lastExecutionStatus',
|
||||
render: (status: string) => {
|
||||
|
||||
@ -17,4 +17,4 @@ export const getWorkflowInstances = (params?: WorkflowTemplateWithInstancesQuery
|
||||
* @param params 查询参数
|
||||
*/
|
||||
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