"use client"; import { ArrowRightLeftIcon, ChevronLeft, ChevronRight, CircleUserRoundIcon, CircleXIcon, FilePlus2Icon, Menu, MoreHorizontalIcon, X, } from "lucide-react"; import { useEffect, useRef, useState } from "react"; import { toast } from "sonner"; import type { PanelImperativeHandle } from "react-resizable-panels"; import { ConversationCloseDialog } from "@/components/conversation-actions/close-dialog"; import { ConversationTransferDialog } from "@/components/conversation-actions/transfer-dialog"; import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"; import { Button } from "@/components/ui/button"; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu"; import { ResizableHandle, ResizablePanel, ResizablePanelGroup, } from "@/components/ui/resizable"; import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { Sheet, SheetContent } from "@/components/ui/sheet"; import { useAgentConversationRealtime } from "@/hooks/use-agent-conversation-realtime"; import { agentConversationFilterOptions, agentConversationSelectors, type AgentConversationFilterKey, useAgentConversationsStore, } from "@/lib/stores/agent-conversations"; import { CreateTicketFromConversationDialog } from "../tickets/_components/create-ticket-from-conversation-dialog"; import { ChatPanel } from "./_components/chat-panel"; import { ConversationInfoPanel } from "./_components/conversation-info-panel"; import { ConversationList } from "./_components/conversation-list"; export default function ConversationsPage() { const conversation = useAgentConversationsStore( agentConversationSelectors.selectedConversation, ); const conversationFilter = useAgentConversationsStore( (state) => state.conversationFilter, ); const setConversationFilter = useAgentConversationsStore( (state) => state.setConversationFilter, ); const loadConversations = useAgentConversationsStore( (state) => state.loadConversations, ); const loadMessages = useAgentConversationsStore( (state) => state.loadMessages, ); const [sidebarCollapsed, setSidebarCollapsed] = useState(false); const [infoPanelCollapsed, setInfoPanelCollapsed] = useState(false); const [mobileMenuOpen, setMobileMenuOpen] = useState(false); const [mobileCustomerSheetOpen, setMobileCustomerSheetOpen] = useState(false); const [transferOpen, setTransferOpen] = useState(false); const [closeOpen, setCloseOpen] = useState(false); const [createTicketOpen, setCreateTicketOpen] = useState(false); const sidebarPanelRef = useRef(null); const infoPanelRef = useRef(null); useEffect(() => { void loadConversations().catch((error) => { toast.error(error instanceof Error ? error.message : "加载会话列表失败"); }); }, [loadConversations, conversationFilter]); async function handleConversationChanged(conversationId: number) { await loadConversations(); await loadMessages(conversationId, { forceLoading: false, reset: false, }); } useAgentConversationRealtime(); const handleSidebarToggle = () => { const panel = sidebarPanelRef.current; if (!panel) { setSidebarCollapsed((current) => !current); return; } if (panel.isCollapsed()) { panel.expand(); setSidebarCollapsed(false); return; } panel.collapse(); setSidebarCollapsed(true); }; const handleInfoPanelToggle = () => { const panel = infoPanelRef.current; if (!panel) { setInfoPanelCollapsed((current) => !current); return; } if (panel.isCollapsed()) { panel.expand(); setInfoPanelCollapsed(false); return; } panel.collapse(); setInfoPanelCollapsed(true); }; const renderConversationSidebar = (opts?: { onListAfterSelect?: () => void }) => (
setConversationFilter(value as AgentConversationFilterKey) } className="min-w-0 flex-1 gap-0" > {agentConversationFilterOptions.map((opt) => ( {opt.label} ))}
); const workspaceContent = (
{conversation ? ( <>

{conversation.subject}

{conversation.externalSource} / {conversation.externalId} {conversation.customerId ? ( <> / 已关联客户 ) : null}

) : (

会话工作台

打开菜单选择会话

请选择左侧会话开始处理消息

)}
} > setCreateTicketOpen(true)} disabled={!conversation} > 转工单 setTransferOpen(true)} disabled={!conversation || conversation.status !== 2} > 转接会话 setCloseOpen(true)} disabled={!conversation || conversation.status === 3} > 关闭会话
); return (
{/* H5 无左侧导航:顶栏 h-12、left-0;lg 起有 w-14 侧栏,与 layout 一致 */} {mobileMenuOpen && (
); }