84 lines
4.1 KiB
TypeScript
84 lines
4.1 KiB
TypeScript
// File: frontend/app/workflow/components/ChatOutputNode.tsx (新建)
|
||
// Description: 自定义 ChatOutput 节点
|
||
|
||
import React, { memo, useCallback, ChangeEvent } from 'react';
|
||
import { Handle, Position, useReactFlow, Node } from 'reactflow';
|
||
import { MessageCircleReply } from 'lucide-react'; // 使用合适的图标
|
||
import { Label } from "@/components/ui/label";
|
||
import { Input } from "@/components/ui/input"; // 使用 Input 或 Textarea 根据需要
|
||
import type { ChatOutputNodeData, CustomNodeProps } from './types';
|
||
|
||
const ChatOutputNodeComponent = ({ id, data, isConnectable }: CustomNodeProps<ChatOutputNodeData>) => {
|
||
const { setNodes } = useReactFlow<ChatOutputNodeData>();
|
||
|
||
// 处理文本变化 (如果需要可编辑)
|
||
const handleTextChange = useCallback((event: ChangeEvent<HTMLInputElement>) => {
|
||
const newText = event.target.value;
|
||
setNodes((nds: Node<ChatOutputNodeData>[]) =>
|
||
nds.map((node) => {
|
||
if (node.id === id) {
|
||
return { ...node, data: { ...node.data, displayText: newText } };
|
||
}
|
||
return node;
|
||
})
|
||
);
|
||
}, [id, setNodes]);
|
||
|
||
return (
|
||
<div className="react-flow__node-genericNode bg-gray-50 dark:bg-gray-800 border border-gray-300 dark:border-gray-700 rounded-lg shadow-lg w-96">
|
||
{/* 输入 Handle */}
|
||
<Handle
|
||
type="target"
|
||
position={Position.Left}
|
||
id="message-input"
|
||
isConnectable={isConnectable}
|
||
className="!w-3 !h-3 !bg-purple-500 top-1/2" // 使用紫色 Handle
|
||
/>
|
||
|
||
{/* 节点头部 */}
|
||
<div className="bg-gray-100 dark:bg-gray-700 p-3 border-b border-gray-300 dark:border-gray-600">
|
||
<div className="flex items-center gap-2">
|
||
<MessageCircleReply size={18} className="text-gray-700 dark:text-gray-300" />
|
||
<strong className="text-gray-800 dark:text-gray-200">Chat Output</strong>
|
||
</div>
|
||
<p className="text-xs text-gray-600 dark:text-gray-400 mt-1">在 Playground 显示聊天消息。</p>
|
||
</div>
|
||
|
||
{/* 节点内容 */}
|
||
<div className="p-4 space-y-2">
|
||
<div className="nodrag">
|
||
<Label htmlFor={`chat-output-text-${id}`} className="text-xs font-semibold text-gray-500 dark:text-gray-400">Text</Label>
|
||
{/* 根据截图,这里像是一个 Input,可能用于显示模板或结果 */}
|
||
<Input
|
||
id={`chat-output-text-${id}`}
|
||
name="displayText"
|
||
value={data.displayText || ''} // 显示传入的数据
|
||
onChange={handleTextChange} // 如果需要可编辑
|
||
placeholder="等待输入..."
|
||
className="mt-1 text-sm h-10 bg-white dark:bg-gray-700"
|
||
// readOnly // 如果只是显示,可以设为只读
|
||
/>
|
||
{/* 或者只是一个简单的文本显示区域 */}
|
||
{/* <p className="mt-1 text-sm p-2 border rounded bg-white dark:bg-gray-700 min-h-[40px]">
|
||
{data.displayText || '等待输入...'}
|
||
</p> */}
|
||
</div>
|
||
</div>
|
||
|
||
{/* 输出 Handle (可选,根据是否需要继续传递) */}
|
||
{/* <div className="relative p-2 border-t border-gray-300 dark:border-gray-600">
|
||
<Label className="text-xs font-semibold text-gray-500 dark:text-gray-400 block text-right pr-7">Message</Label>
|
||
<Handle
|
||
type="source"
|
||
position={Position.Right}
|
||
id="message-passthrough"
|
||
isConnectable={isConnectable}
|
||
className="w-3 h-3 !bg-purple-500 top-1/2"
|
||
/>
|
||
</div> */}
|
||
</div>
|
||
);
|
||
};
|
||
|
||
ChatOutputNodeComponent.displayName = 'ChatOutputNode';
|
||
export const ChatOutputNode = memo(ChatOutputNodeComponent); |