1
This commit is contained in:
parent
40d0ba918f
commit
a59bd47cd0
@ -13,12 +13,12 @@ export const EndEventNodeDefinition: BaseNodeDefinition = {
|
||||
|
||||
// 渲染配置(配置驱动)
|
||||
renderConfig: {
|
||||
shape: 'rounded-rect',
|
||||
size: { width: 80, height: 48 },
|
||||
shape: 'ellipse',
|
||||
size: { width: 120, height: 50 },
|
||||
icon: {
|
||||
type: 'emoji',
|
||||
content: '⏹️',
|
||||
size: 32
|
||||
size: 24
|
||||
},
|
||||
theme: {
|
||||
primary: '#ef4444',
|
||||
|
||||
@ -13,12 +13,12 @@ export const StartEventNodeDefinition: BaseNodeDefinition = {
|
||||
|
||||
// 渲染配置(配置驱动)
|
||||
renderConfig: {
|
||||
shape: 'rounded-rect',
|
||||
size: { width: 80, height: 48 },
|
||||
shape: 'ellipse',
|
||||
size: { width: 120, height: 50 },
|
||||
icon: {
|
||||
type: 'emoji',
|
||||
content: '▶️',
|
||||
size: 32
|
||||
size: 24
|
||||
},
|
||||
theme: {
|
||||
primary: '#10b981',
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import React from 'react';
|
||||
import { Handle, Position, NodeProps } from '@xyflow/react';
|
||||
import type { FlowNodeData } from '../../types';
|
||||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
||||
|
||||
/**
|
||||
* BaseNode - shadcn/ui 风格节点
|
||||
@ -16,32 +17,29 @@ const BaseNode: React.FC<NodeProps> = ({ data, selected }) => {
|
||||
|
||||
const config = definition.renderConfig;
|
||||
|
||||
// 获取输出字段简要信息
|
||||
const getOutputsSummary = () => {
|
||||
// 渲染输出字段标签
|
||||
const renderOutputSection = () => {
|
||||
if (!nodeData.outputs || nodeData.outputs.length === 0) {
|
||||
return null;
|
||||
}
|
||||
return nodeData.outputs.map(output => output.name).join(', ');
|
||||
};
|
||||
|
||||
// shadcn 风格容器类名
|
||||
const getContainerClass = () => {
|
||||
// 基础样式 - shadcn card 风格
|
||||
// 使用 items-start 让图标和文本顶部对齐
|
||||
const baseClass = `
|
||||
relative inline-flex items-start gap-2 px-3 py-2
|
||||
bg-background border border-border
|
||||
rounded-lg shadow-sm
|
||||
transition-all duration-200
|
||||
hover:shadow-md hover:border-primary/50
|
||||
`;
|
||||
|
||||
// 选中状态 - shadcn 的 ring 效果
|
||||
const selectedClass = selected
|
||||
? 'border-primary shadow-md ring-2 ring-ring ring-offset-2 ring-offset-background'
|
||||
: '';
|
||||
|
||||
return `${baseClass} ${selectedClass}`;
|
||||
return (
|
||||
<div className="space-y-2">
|
||||
{/* 输出标签 - 靠左 */}
|
||||
<div className="text-xs text-muted-foreground font-medium">输出</div>
|
||||
{/* 输出字段标签 */}
|
||||
<div className="flex flex-wrap gap-1.5">
|
||||
{nodeData.outputs.map((output, index) => (
|
||||
<code
|
||||
key={index}
|
||||
className="text-xs px-2 py-1 bg-secondary text-secondary-foreground rounded-md font-mono inline-flex items-center"
|
||||
title={output.title || output.description}
|
||||
>
|
||||
{output.name}
|
||||
</code>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
// 图标容器 - shadcn 风格
|
||||
@ -51,20 +49,20 @@ const BaseNode: React.FC<NodeProps> = ({ data, selected }) => {
|
||||
<div
|
||||
className="
|
||||
flex items-center justify-center
|
||||
rounded-md
|
||||
transition-transform duration-200
|
||||
group-hover:scale-110
|
||||
rounded-lg
|
||||
transition-all duration-200
|
||||
group-hover:scale-105
|
||||
flex-shrink-0
|
||||
mt-0.5
|
||||
shadow-sm
|
||||
"
|
||||
style={{
|
||||
width: '32px',
|
||||
height: '32px',
|
||||
width: '36px',
|
||||
height: '36px',
|
||||
background: `linear-gradient(135deg, ${config.theme.primary}, ${config.theme.secondary})`,
|
||||
}}
|
||||
>
|
||||
<span
|
||||
className="text-white text-base leading-none"
|
||||
className="text-white text-lg leading-none"
|
||||
>
|
||||
{config.icon.content}
|
||||
</span>
|
||||
@ -76,9 +74,9 @@ const BaseNode: React.FC<NodeProps> = ({ data, selected }) => {
|
||||
|
||||
// shadcn 风格连接点
|
||||
const handleClass = `
|
||||
!w-2.5 !h-2.5 !rounded-full !border-2 !border-background
|
||||
!w-3 !h-3 !rounded-full !border-2 !border-background
|
||||
transition-all duration-200
|
||||
hover:!w-3 hover:!h-3
|
||||
hover:!w-3.5 hover:!h-3.5 hover:!shadow-md
|
||||
`;
|
||||
|
||||
const getHandleStyle = () => ({
|
||||
@ -107,9 +105,11 @@ const BaseNode: React.FC<NodeProps> = ({ data, selected }) => {
|
||||
);
|
||||
};
|
||||
|
||||
// 椭圆形节点(开始/结束)使用特殊布局
|
||||
const isEllipse = config.shape === 'ellipse';
|
||||
|
||||
return (
|
||||
<div className="group">
|
||||
<div className={getContainerClass()}>
|
||||
<div className="group relative">
|
||||
{/* 输入连接点 */}
|
||||
{config.handles.input && (
|
||||
<Handle
|
||||
@ -120,23 +120,45 @@ const BaseNode: React.FC<NodeProps> = ({ data, selected }) => {
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* 图标 */}
|
||||
{/* 使用 shadcn Card 组件 */}
|
||||
<Card
|
||||
className={`
|
||||
${isEllipse ? 'rounded-full px-6 py-3' : 'min-w-[240px] max-w-[420px]'}
|
||||
${selected ? 'ring-2 ring-primary ring-offset-2 ring-offset-background' : ''}
|
||||
transition-all duration-200
|
||||
hover:shadow-lg hover:border-primary/50
|
||||
`}
|
||||
>
|
||||
{isEllipse ? (
|
||||
// 椭圆形节点:紧凑布局,图标+文字居中
|
||||
<div className="flex items-center justify-center gap-3 px-2">
|
||||
{renderIcon()}
|
||||
|
||||
{/* 标签和输出信息 - 垂直布局 */}
|
||||
<div className="flex flex-col gap-0.5 min-w-0">
|
||||
{/* 节点名称 */}
|
||||
<div className="text-sm font-medium text-foreground whitespace-nowrap">
|
||||
<span className="text-sm font-semibold whitespace-nowrap">
|
||||
{nodeData.label || definition.nodeName}
|
||||
</span>
|
||||
</div>
|
||||
) : (
|
||||
// 普通节点:使用 Card 的标准布局
|
||||
<>
|
||||
<CardHeader className="pb-3">
|
||||
{/* 图标 + 标题 */}
|
||||
<div className="flex items-center gap-3">
|
||||
{renderIcon()}
|
||||
<CardTitle className="text-base">
|
||||
{nodeData.label || definition.nodeName}
|
||||
</CardTitle>
|
||||
</div>
|
||||
</CardHeader>
|
||||
|
||||
{/* 输出能力简要信息 */}
|
||||
{getOutputsSummary() && (
|
||||
<div className="text-[10px] text-muted-foreground">
|
||||
输出:{getOutputsSummary()}
|
||||
</div>
|
||||
{/* 输出部分 */}
|
||||
{renderOutputSection() && (
|
||||
<CardContent className="pt-0">
|
||||
{renderOutputSection()}
|
||||
</CardContent>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</Card>
|
||||
|
||||
{/* 输出连接点 */}
|
||||
{config.handles.output && (
|
||||
@ -151,7 +173,6 @@ const BaseNode: React.FC<NodeProps> = ({ data, selected }) => {
|
||||
{/* 配置徽章 */}
|
||||
{renderBadge()}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@ -72,7 +72,7 @@ export interface NodeSize {
|
||||
}
|
||||
|
||||
// 节点形状
|
||||
export type NodeShape = 'circle' | 'rounded-rect' | 'rect' | 'diamond';
|
||||
export type NodeShape = 'circle' | 'rounded-rect' | 'rect' | 'diamond' | 'ellipse';
|
||||
|
||||
// 图标配置
|
||||
export interface IconConfig {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user