ChatHeader.tsx 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. "use client";
  2. import { formatConversationTime } from "@/utils/format";
  3. import { Button } from "@/components/ui/button";
  4. import { Separator } from "@/components/ui/separator";
  5. interface ChatHeaderProps {
  6. conversationId: number;
  7. lastSeenAt?: string | null;
  8. unreadCount: number;
  9. onMarkAllRead: () => void;
  10. onCloseConversation?: () => void;
  11. onRefresh: () => void;
  12. includeAIMessages?: boolean;
  13. onToggleAIMessages?: () => void;
  14. soundEnabled?: boolean;
  15. onToggleSound?: () => void;
  16. hideAIToggle?: boolean; // 内部对话时隐藏「显示 AI 消息」切换
  17. }
  18. export function ChatHeader({
  19. conversationId,
  20. lastSeenAt,
  21. unreadCount,
  22. onMarkAllRead,
  23. onCloseConversation,
  24. onRefresh,
  25. includeAIMessages = false,
  26. onToggleAIMessages,
  27. soundEnabled = false,
  28. onToggleSound,
  29. hideAIToggle = false,
  30. }: ChatHeaderProps) {
  31. return (
  32. <div className="h-16 flex items-center justify-between px-4 bg-background flex-shrink-0 relative">
  33. <div className="z-10">
  34. <div className="font-semibold text-foreground">对话 #{conversationId}</div>
  35. <div className="text-xs text-muted-foreground mt-0.5">
  36. {lastSeenAt
  37. ? `last seen ${formatConversationTime(lastSeenAt)}`
  38. : "last seen 未知"}
  39. </div>
  40. </div>
  41. <div className="flex items-center gap-2">
  42. {/* 显示/隐藏 AI 消息切换按钮(内部对话不显示,默认始终包含 AI 消息) */}
  43. {onToggleAIMessages && !hideAIToggle && (
  44. <Button
  45. variant={includeAIMessages ? "default" : "outline"}
  46. size="sm"
  47. onClick={onToggleAIMessages}
  48. title={includeAIMessages ? "隐藏 AI 消息" : "显示 AI 消息"}
  49. className="text-xs"
  50. >
  51. {includeAIMessages ? "隐藏 AI 消息" : "显示 AI 消息"}
  52. </Button>
  53. )}
  54. {/* 声音开关按钮 */}
  55. {onToggleSound && (
  56. <Button
  57. variant="ghost"
  58. size="icon"
  59. title={soundEnabled ? "关闭声音提示" : "开启声音提示"}
  60. onClick={onToggleSound}
  61. >
  62. {soundEnabled ? (
  63. <svg
  64. className="w-5 h-5"
  65. fill="none"
  66. stroke="currentColor"
  67. viewBox="0 0 24 24"
  68. >
  69. <path
  70. strokeLinecap="round"
  71. strokeLinejoin="round"
  72. strokeWidth={2}
  73. d="M15.536 8.464a5 5 0 010 7.072m2.828-9.9a9 9 0 010 12.728M5.586 15H4a1 1 0 01-1-1v-4a1 1 0 011-1h1.586l4.707-4.707C10.923 3.663 12 4.109 12 5v14c0 .891-1.077 1.337-1.707.707L5.586 15z"
  74. />
  75. </svg>
  76. ) : (
  77. <svg
  78. className="w-5 h-5"
  79. fill="none"
  80. stroke="currentColor"
  81. viewBox="0 0 24 24"
  82. >
  83. <path
  84. strokeLinecap="round"
  85. strokeLinejoin="round"
  86. strokeWidth={2}
  87. d="M5.586 15H4a1 1 0 01-1-1v-4a1 1 0 011-1h1.586l4.707-4.707C10.923 3.663 12 4.109 12 5v14c0 .891-1.077 1.337-1.707.707L5.586 15z"
  88. />
  89. <path
  90. strokeLinecap="round"
  91. strokeLinejoin="round"
  92. strokeWidth={2}
  93. d="M17 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2"
  94. />
  95. </svg>
  96. )}
  97. </Button>
  98. )}
  99. <Button
  100. variant="ghost"
  101. size="icon"
  102. title="关闭会话"
  103. onClick={onCloseConversation}
  104. disabled={!onCloseConversation}
  105. >
  106. <svg
  107. className="w-5 h-5"
  108. fill="none"
  109. stroke="currentColor"
  110. viewBox="0 0 24 24"
  111. >
  112. <path
  113. strokeLinecap="round"
  114. strokeLinejoin="round"
  115. strokeWidth={2}
  116. d="M6 6l12 12M18 6L6 18"
  117. />
  118. </svg>
  119. </Button>
  120. <Button
  121. variant="ghost"
  122. size="icon"
  123. title="刷新"
  124. onClick={onRefresh}
  125. >
  126. <svg
  127. className="w-5 h-5 text-muted-foreground"
  128. fill="none"
  129. stroke="currentColor"
  130. viewBox="0 0 24 24"
  131. >
  132. <path
  133. strokeLinecap="round"
  134. strokeLinejoin="round"
  135. strokeWidth={2}
  136. d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"
  137. />
  138. </svg>
  139. </Button>
  140. </div>
  141. <Separator className="absolute bottom-0 left-0 right-0" />
  142. </div>
  143. );
  144. }