68ab6a2016
将 web 和 desktop 的重复代码抽取到 @ai-assistant/ui 包: - 添加可配置的 API 客户端 (configureApiClient) - 迁移共享组件: ChatMessage, ChatInput, Sidebar, FileBrowser, ConfigPanel - 迁移共享 hook: useChat - 添加 responsive prop 支持响应式布局 - 更新 web/desktop 依赖并删除重复代码
99 lines
2.6 KiB
TypeScript
99 lines
2.6 KiB
TypeScript
/**
|
|
* Chat Page
|
|
*/
|
|
|
|
import { useEffect, useRef } from 'react';
|
|
import { Wifi, WifiOff } from 'lucide-react';
|
|
import {
|
|
useChat,
|
|
ChatMessage,
|
|
StreamingMessage,
|
|
TypingIndicator,
|
|
ChatInput,
|
|
} from '@ai-assistant/ui';
|
|
|
|
interface ChatPageProps {
|
|
sessionId: string;
|
|
onSessionNotFound?: () => void;
|
|
responsive?: boolean;
|
|
}
|
|
|
|
export function ChatPage({ sessionId, onSessionNotFound, responsive = false }: ChatPageProps) {
|
|
const {
|
|
messages,
|
|
isConnected,
|
|
isLoading,
|
|
streamingContent,
|
|
sendMessage,
|
|
cancelProcessing,
|
|
} = useChat({
|
|
sessionId,
|
|
onError: (error) => {
|
|
console.error('Chat error:', error);
|
|
},
|
|
onSessionNotFound,
|
|
});
|
|
|
|
const messagesEndRef = useRef<HTMLDivElement>(null);
|
|
|
|
// 自动滚动到底部
|
|
useEffect(() => {
|
|
messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
|
|
}, [messages, streamingContent]);
|
|
|
|
return (
|
|
<div className="flex-1 flex flex-col h-screen">
|
|
{/* Header */}
|
|
<div className="flex items-center justify-between px-6 py-3 border-b border-gray-700 bg-gray-800">
|
|
<h1 className="text-lg font-medium">Chat</h1>
|
|
<div className="flex items-center gap-2 text-sm">
|
|
{isConnected ? (
|
|
<>
|
|
<Wifi size={16} className="text-green-500" />
|
|
<span className="text-green-500">Connected</span>
|
|
</>
|
|
) : (
|
|
<>
|
|
<WifiOff size={16} className="text-red-500" />
|
|
<span className="text-red-500">Disconnected</span>
|
|
</>
|
|
)}
|
|
</div>
|
|
</div>
|
|
|
|
{/* Messages */}
|
|
<div className="flex-1 overflow-y-auto p-6">
|
|
<div className="max-w-4xl mx-auto space-y-4">
|
|
{messages.length === 0 && !isLoading && (
|
|
<div className="text-center py-20">
|
|
<h2 className="text-2xl font-semibold mb-2">Start a conversation</h2>
|
|
<p className="text-gray-400">
|
|
Type a message below to begin chatting with your AI assistant.
|
|
</p>
|
|
</div>
|
|
)}
|
|
|
|
{messages.map((message) => (
|
|
<ChatMessage key={message.id} message={message} />
|
|
))}
|
|
|
|
{streamingContent && <StreamingMessage content={streamingContent} />}
|
|
|
|
{isLoading && !streamingContent && <TypingIndicator />}
|
|
|
|
<div ref={messagesEndRef} />
|
|
</div>
|
|
</div>
|
|
|
|
{/* Input */}
|
|
<ChatInput
|
|
onSend={sendMessage}
|
|
onCancel={cancelProcessing}
|
|
isLoading={isLoading}
|
|
disabled={!isConnected}
|
|
responsive={responsive}
|
|
/>
|
|
</div>
|
|
);
|
|
}
|