70 lines
3.2 KiB
TypeScript
70 lines
3.2 KiB
TypeScript
// File: frontend/app/workflow/components/ChatInputNode.tsx (新建)
|
|
// Description: 自定义 ChatInput 节点
|
|
|
|
import React, { memo, useCallback, ChangeEvent } from 'react';
|
|
import { Handle, Position, useReactFlow, Node } from 'reactflow';
|
|
import { MessageCircleQuestion } from 'lucide-react'; // 使用合适的图标
|
|
import { Label } from "@/components/ui/label";
|
|
import { Textarea } from "@/components/ui/textarea";
|
|
import type { ChatInputNodeData, CustomNodeProps } from './types';
|
|
|
|
const ChatInputNodeComponent = ({ id, data, isConnectable }: CustomNodeProps<ChatInputNodeData>) => {
|
|
const { setNodes } = useReactFlow<ChatInputNodeData>();
|
|
|
|
const handleTextChange = useCallback((event: ChangeEvent<HTMLTextAreaElement>) => {
|
|
const newText = event.target.value;
|
|
setNodes((nds: Node<ChatInputNodeData>[]) =>
|
|
nds.map((node) => {
|
|
if (node.id === id) {
|
|
return { ...node, data: { ...node.data, text: newText } };
|
|
}
|
|
return node;
|
|
})
|
|
);
|
|
}, [id, setNodes]);
|
|
|
|
return (
|
|
<div className="react-flow__node-genericNode nopan bg-gray-50 dark:bg-gray-800 border border-gray-300 dark:border-gray-700 rounded-lg shadow-lg w-96"> {/* 调整宽度 */}
|
|
{/* 节点头部 */}
|
|
<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">
|
|
<MessageCircleQuestion size={18} className="text-gray-700 dark:text-gray-300" />
|
|
<strong className="text-gray-800 dark:text-gray-200">Chat Input</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-input-text-${id}`} className="text-xs font-semibold text-gray-500 dark:text-gray-400">Text</Label>
|
|
<Textarea
|
|
id={`chat-input-text-${id}`}
|
|
name="text"
|
|
value={data.text || ''}
|
|
onChange={handleTextChange}
|
|
placeholder="输入聊天内容..."
|
|
className="mt-1 text-sm min-h-[80px] bg-white dark:bg-gray-700"
|
|
rows={3}
|
|
/>
|
|
</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-output"
|
|
isConnectable={isConnectable}
|
|
className="!w-3 !h-3 !bg-purple-500 top-1/2" // 使用紫色 Handle
|
|
/>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
ChatInputNodeComponent.displayName = 'ChatInputNode';
|
|
export const ChatInputNode = memo(ChatInputNodeComponent);
|