ConversationSidebar.tsx 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. "use client";
  2. import { ConversationSummary } from "@/features/agent/types";
  3. import { ConversationHeader, type ConversationFilter } from "./ConversationHeader";
  4. import { ConversationSearch } from "./ConversationSearch";
  5. import { ConversationList } from "./ConversationList";
  6. import { Button } from "@/components/ui/button";
  7. import { Plus } from "lucide-react";
  8. type ConversationStatus = "open" | "closed";
  9. interface ConversationSidebarProps {
  10. conversations: ConversationSummary[];
  11. selectedConversationId: number | null;
  12. searchQuery: string;
  13. onSearchChange: (value: string) => void;
  14. onSelectConversation: (id: number) => void;
  15. filter: ConversationFilter;
  16. onFilterChange: (filter: ConversationFilter) => void;
  17. status?: ConversationStatus;
  18. onStatusChange?: (status: ConversationStatus) => void;
  19. /** 内部对话(知识库测试)模式:显示「新建内部对话」按钮,隐藏筛选 */
  20. mode?: "visitor" | "internal";
  21. onNewClick?: () => void;
  22. }
  23. export function ConversationSidebar({
  24. conversations,
  25. selectedConversationId,
  26. searchQuery,
  27. onSearchChange,
  28. onSelectConversation,
  29. filter,
  30. onFilterChange,
  31. status = "open",
  32. onStatusChange,
  33. mode = "visitor",
  34. onNewClick,
  35. }: ConversationSidebarProps) {
  36. return (
  37. <div className="w-80 min-w-0 flex-1 flex flex-col bg-white border-r border-gray-200 min-h-0 overflow-hidden">
  38. {mode === "internal" ? (
  39. <div className="h-14 flex items-center justify-between px-3 border-b border-border bg-background flex-shrink-0">
  40. <span className="text-sm font-medium text-foreground truncate">知识库测试</span>
  41. {onNewClick && (
  42. <Button size="sm" variant="outline" onClick={onNewClick} className="flex-shrink-0 gap-1">
  43. <Plus className="w-4 h-4" />
  44. 新建
  45. </Button>
  46. )}
  47. </div>
  48. ) : (
  49. <ConversationHeader
  50. filter={filter}
  51. onFilterChange={onFilterChange}
  52. listStatus={status}
  53. onListStatusChange={onStatusChange}
  54. />
  55. )}
  56. <div className="flex-shrink-0 px-2 min-w-0">
  57. <ConversationSearch value={searchQuery} onChange={onSearchChange} />
  58. </div>
  59. <ConversationList
  60. conversations={conversations}
  61. selectedConversationId={selectedConversationId}
  62. onSelect={onSelectConversation}
  63. searchQuery={searchQuery}
  64. />
  65. </div>
  66. );
  67. }