'use client'; import Link from 'next/link'; import { usePathname, useRouter } from 'next/navigation'; import { Plus, PanelLeft, Trash2, MoreHorizontal, Loader2 } from 'lucide-react'; import { UserMenu } from '@/components/ui/UserMenu'; import { cn } from '@/lib/utils'; import { useConversations } from '@/hooks/useConversations'; import { useSettings } from '@/hooks/useSettings'; import type { User } from '@/types'; import type { Conversation } from '@/drizzle/schema'; import { useState } from 'react'; interface SidebarProps { user: User; chatHistories?: { id: string; title: string }[]; // 保持向后兼容 isOpen?: boolean; onToggle?: () => void; } export function Sidebar({ user, isOpen = true }: SidebarProps) { const pathname = usePathname(); const router = useRouter(); const { conversations, loading, createConversation, deleteConversation } = useConversations(); const { settings } = useSettings(); const [creatingChat, setCreatingChat] = useState(false); const [menuOpen, setMenuOpen] = useState(null); // 创建新对话 const handleNewChat = async () => { if (creatingChat) return; try { setCreatingChat(true); const newConversation = await createConversation({ model: settings?.defaultModel || 'claude-sonnet-4-20250514', tools: settings?.defaultTools || [], enableThinking: settings?.enableThinking || false, }); router.push(`/chat/${newConversation.conversationId}`); } catch (error) { console.error('Failed to create conversation:', error); } finally { setCreatingChat(false); } }; // 删除对话 const handleDeleteConversation = async (conversationId: string, e: React.MouseEvent) => { e.preventDefault(); e.stopPropagation(); try { await deleteConversation(conversationId); setMenuOpen(null); // 如果当前正在查看被删除的对话,跳转到首页 if (pathname === `/chat/${conversationId}`) { router.push('/'); } } catch (error) { console.error('Failed to delete conversation:', error); } }; // 按时间分组对话 const groupedConversations = groupConversationsByTime(conversations); return ( <> {/* 侧边栏 */} {/* 移动端遮罩 */} {isOpen && (
setMenuOpen(null)} /> )} ); } // 侧边栏切换按钮 export function SidebarToggle({ onClick }: { onClick?: () => void }) { return ( ); } // 按时间分组对话 function groupConversationsByTime(conversations: Conversation[]): Record { const now = new Date(); const today = new Date(now.getFullYear(), now.getMonth(), now.getDate()); const yesterday = new Date(today.getTime() - 24 * 60 * 60 * 1000); const weekAgo = new Date(today.getTime() - 7 * 24 * 60 * 60 * 1000); const monthAgo = new Date(today.getTime() - 30 * 24 * 60 * 60 * 1000); const groups: Record = {}; conversations.forEach((conversation) => { const date = new Date(conversation.lastMessageAt || conversation.createdAt || now); let group: string; if (date >= today) { group = 'Today'; } else if (date >= yesterday) { group = 'Yesterday'; } else if (date >= weekAgo) { group = 'Past 7 days'; } else if (date >= monthAgo) { group = 'Past 30 days'; } else { group = 'Older'; } if (!groups[group]) { groups[group] = []; } groups[group].push(conversation); }); return groups; }