deploy-ease-platform/frontend/src/pages/Workflow/Design/nodes/EndEventNode.tsx
dengqichen e18874688e 1
2025-10-21 12:26:40 +08:00

141 lines
4.5 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React, { memo } from 'react';
import { Handle, Position, NodeProps } from '@xyflow/react';
import { BaseNodeDefinition, NodeType, NodeCategory } from './types';
import type { FlowNodeData } from '../types';
/**
* 结束事件节点定义(元数据)
*/
export const EndEventNodeDefinition: BaseNodeDefinition = {
nodeCode: "END_EVENT",
nodeName: "结束",
nodeType: NodeType.END_EVENT,
category: NodeCategory.EVENT,
description: "工作流的结束节点",
uiConfig: {
size: { width: 80, height: 50 },
style: {
fill: '#ff4d4f',
stroke: '#cf1322',
strokeWidth: 2,
icon: 'stop-circle',
iconColor: '#fff'
}
},
configSchema: {
type: "object",
title: "基本配置",
description: "节点的基本信息",
properties: {
nodeName: {
type: "string",
title: "节点名称",
description: "节点在流程图中显示的名称",
default: "结束"
},
nodeCode: {
type: "string",
title: "节点编码",
description: "节点的唯一标识符",
default: "END_EVENT"
},
description: {
type: "string",
title: "节点描述",
description: "节点的详细说明",
default: "工作流的结束节点"
}
},
required: ["nodeName", "nodeCode"]
}
};
/**
* 结束事件节点渲染组件
*/
const EndEventNode: React.FC<NodeProps> = ({ data, selected }) => {
const nodeData = data as FlowNodeData;
const [isHovered, setIsHovered] = React.useState(false);
return (
<div
onMouseEnter={() => setIsHovered(true)}
onMouseLeave={() => setIsHovered(false)}
style={{
padding: '12px',
borderRadius: '50%',
border: `3px solid ${selected ? '#3b82f6' : '#ef4444'}`,
background: selected
? 'linear-gradient(135deg, #fee2e2 0%, #fecaca 100%)'
: 'linear-gradient(135deg, #fef2f2 0%, #fee2e2 100%)',
minWidth: '70px',
minHeight: '70px',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
position: 'relative',
boxShadow: selected
? '0 8px 16px rgba(59, 130, 246, 0.25), 0 2px 4px rgba(59, 130, 246, 0.15)'
: isHovered
? '0 6px 12px rgba(239, 68, 68, 0.2), 0 2px 4px rgba(239, 68, 68, 0.1)'
: '0 2px 8px rgba(0,0,0,0.08)',
cursor: 'pointer',
transition: 'all 0.3s cubic-bezier(0.4, 0, 0.2, 1)',
transform: isHovered ? 'scale(1.05)' : 'scale(1)',
}}
>
{/* 图标 */}
<div style={{
fontSize: '26px',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
filter: selected ? 'brightness(1.1)' : 'none',
transition: 'filter 0.2s ease'
}}>
</div>
{/* 输入连接点 */}
<Handle
type="target"
position={Position.Left}
style={{
background: '#ef4444',
border: '3px solid white',
width: '12px',
height: '12px',
boxShadow: '0 2px 4px rgba(0,0,0,0.15)',
transition: 'all 0.2s ease',
}}
/>
{/* 节点标签 */}
<div
style={{
position: 'absolute',
bottom: '-30px',
left: '50%',
transform: 'translateX(-50%)',
fontSize: '13px',
color: '#1f2937',
fontWeight: '600',
whiteSpace: 'nowrap',
background: 'white',
padding: '4px 10px',
borderRadius: '6px',
boxShadow: '0 2px 6px rgba(0,0,0,0.1)',
border: '1px solid #e5e7eb',
}}
>
{nodeData.label || '结束'}
</div>
</div>
);
};
export default memo(EndEventNode);