Files
light-code/web/src/apps/muse/prompts/index.tsx
2025-10-20 20:53:14 +08:00

190 lines
6.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React, { useState, useRef, useEffect } from 'react';
import { Send, Bot, User } from 'lucide-react';
interface Message {
id: string;
content: string;
role: 'user' | 'assistant';
timestamp: Date;
}
export const ChatInterface: React.FC = () => {
const [messages, setMessages] = useState<Message[]>([
{
id: '1',
content: '你好我是AI助手有什么可以帮助您的吗',
role: 'assistant',
timestamp: new Date()
}
]);
const [inputValue, setInputValue] = useState('');
const [isLoading, setIsLoading] = useState(false);
const messagesEndRef = useRef<HTMLDivElement>(null);
const inputRef = useRef<HTMLTextAreaElement>(null);
// 自动滚动到最新消息
const scrollToBottom = () => {
messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
};
useEffect(() => {
scrollToBottom();
}, [messages]);
// 发送消息
const handleSend = async () => {
if (!inputValue.trim() || isLoading) return;
const userMessage: Message = {
id: Date.now().toString(),
content: inputValue.trim(),
role: 'user',
timestamp: new Date()
};
setMessages(prev => [...prev, userMessage]);
setInputValue('');
setIsLoading(true);
// 模拟AI回复
setTimeout(() => {
const aiMessage: Message = {
id: (Date.now() + 1).toString(),
content: `我收到了您的消息:"${userMessage.content}"。这里是我的回复,您还有其他问题吗?`,
role: 'assistant',
timestamp: new Date()
};
setMessages(prev => [...prev, aiMessage]);
setIsLoading(false);
}, 1000);
};
// 处理键盘事件
const handleKeyDown = (e: React.KeyboardEvent) => {
if (e.key === 'Enter' && !e.shiftKey) {
e.preventDefault();
handleSend();
}
};
// 格式化时间
const formatTime = (date: Date) => {
return date.toLocaleTimeString('zh-CN', {
hour: '2-digit',
minute: '2-digit'
});
};
return (
<div className="h-full flex flex-col bg-gray-50">
{/* 头部 */}
<div className="bg-white border-b border-gray-200 p-4 shadow-sm">
<div className="flex items-center gap-3">
<div className="w-10 h-10 bg-blue-500 rounded-full flex items-center justify-center">
<Bot className="w-6 h-6 text-white" />
</div>
<div>
<h1 className="text-xl font-semibold text-gray-900"></h1>
<p className="text-sm text-gray-500">线 · </p>
</div>
</div>
</div>
{/* 对话列表区域 */}
<div className="flex-1 overflow-y-auto p-4 space-y-4">
{messages.map((message) => (
<div
key={message.id}
className={`flex gap-3 ${
message.role === 'user' ? 'justify-end' : 'justify-start'
}`}
>
{message.role === 'assistant' && (
<div className="w-8 h-8 bg-blue-500 rounded-full flex items-center justify-center flex-shrink-0">
<Bot className="w-5 h-5 text-white" />
</div>
)}
<div
className={`max-w-[70%] rounded-lg px-4 py-2 ${
message.role === 'user'
? 'bg-blue-500 text-white'
: 'bg-white text-gray-900 shadow-sm border border-gray-200'
}`}
>
<div className="text-sm leading-relaxed whitespace-pre-wrap">
{message.content}
</div>
<div
className={`text-xs mt-1 ${
message.role === 'user' ? 'text-blue-100' : 'text-gray-500'
}`}
>
{formatTime(message.timestamp)}
</div>
</div>
{message.role === 'user' && (
<div className="w-8 h-8 bg-gray-600 rounded-full flex items-center justify-center flex-shrink-0">
<User className="w-5 h-5 text-white" />
</div>
)}
</div>
))}
{/* 加载状态 */}
{isLoading && (
<div className="flex gap-3 justify-start">
<div className="w-8 h-8 bg-blue-500 rounded-full flex items-center justify-center flex-shrink-0">
<Bot className="w-5 h-5 text-white" />
</div>
<div className="bg-white rounded-lg px-4 py-2 shadow-sm border border-gray-200">
<div className="flex space-x-1">
<div className="w-2 h-2 bg-gray-400 rounded-full animate-bounce"></div>
<div className="w-2 h-2 bg-gray-400 rounded-full animate-bounce" style={{ animationDelay: '0.1s' }}></div>
<div className="w-2 h-2 bg-gray-400 rounded-full animate-bounce" style={{ animationDelay: '0.2s' }}></div>
</div>
</div>
</div>
)}
<div ref={messagesEndRef} />
</div>
{/* 输入框区域 */}
<div className="bg-white border-t border-gray-200 p-4">
<div className="flex gap-3 items-end">
<div className="flex-1 relative">
<textarea
ref={inputRef}
value={inputValue}
onChange={(e) => setInputValue(e.target.value)}
onKeyDown={handleKeyDown}
placeholder="输入您的消息... (按 Enter 发送Shift+Enter 换行)"
className="w-full px-4 py-3 border border-gray-300 rounded-lg resize-none focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
rows={1}
style={{ minHeight: '96px', maxHeight: '180px' }}
disabled={isLoading}
/>
</div>
<button
onClick={handleSend}
disabled={!inputValue.trim() || isLoading}
className={`p-3 rounded-lg flex items-center justify-center transition-colors ${
!inputValue.trim() || isLoading
? 'bg-gray-300 cursor-not-allowed'
: 'bg-blue-500 hover:bg-blue-600 text-white'
}`}
>
<Send className="w-5 h-5" />
</button>
</div>
{/* 提示文本 */}
<div className="mt-2 text-xs text-gray-500 text-center">
AI助手会根据您的输入生成回复使
</div>
</div>
</div>
);
};