AssistantMessage.tsx 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. import _React from "react";
  2. import { Button, Space } from "antd";
  3. import {
  4. RedoOutlined,
  5. LikeOutlined,
  6. DislikeOutlined,
  7. CopyOutlined,
  8. ShareAltOutlined,
  9. } from "@ant-design/icons";
  10. import type { AssistantMessageProps } from "../../types/chat"
  11. import Marked from "../general/Marked";
  12. import { VersionSwitcher } from "./VersionSwitcher";
  13. import ToolMessage from "./ToolMessage";
  14. const AssistantMessage = ({
  15. session,
  16. onRefresh,
  17. ___onEdit,
  18. isPending,
  19. onLike,
  20. onDislike,
  21. onCopy,
  22. onShare,
  23. onVersionSwitch,
  24. }: AssistantMessageProps) => {
  25. const messages = session.ai_messages;
  26. const mainMessage = messages.find((m) => m.role === "assistant" && m.content);
  27. const _____toolMessages = messages.filter((m) => m.role === "tool");
  28. const handleCopy = () => {
  29. if (mainMessage?.content && onCopy) {
  30. onCopy(mainMessage.uid);
  31. }
  32. };
  33. const handleShare = async () => {
  34. if (mainMessage && onShare) {
  35. try {
  36. const shareUrl = await onShare(mainMessage.uid);
  37. // 可以显示分享链接或复制到剪贴板
  38. navigator.clipboard.writeText(shareUrl);
  39. } catch (err) {
  40. console.error("分享失败:", err);
  41. }
  42. }
  43. };
  44. return (
  45. <div className="assistant-message">
  46. <div className="message-header">
  47. <span className="role-label">
  48. {mainMessage?.model_id && (
  49. <span className="model-info">{mainMessage.model_id}</span>
  50. )}
  51. </span>
  52. </div>
  53. <div className="message-content" style={{ backgroundColor: "unset" }}>
  54. {/* Tool calls 显示 */}
  55. <ToolMessage session={session} />
  56. {/* 主要回答内容 */}
  57. {mainMessage?.content && (
  58. <div className="message-text">
  59. <Marked text={mainMessage.content} />
  60. {isPending && (
  61. <span className="status-indicator pending">生成中...</span>
  62. )}
  63. </div>
  64. )}
  65. {/* Token 使用信息 */}
  66. {mainMessage?.metadata?.token_usage && (
  67. <div className="token-info">
  68. Token: {mainMessage.metadata.token_usage.total_tokens}
  69. </div>
  70. )}
  71. </div>
  72. {!isPending && (
  73. <div className="message-actions">
  74. <Space size="small">
  75. <Button
  76. size="small"
  77. type="text"
  78. icon={<CopyOutlined />}
  79. onClick={handleCopy}
  80. />
  81. <Button
  82. size="small"
  83. type="text"
  84. icon={<LikeOutlined />}
  85. onClick={() => mainMessage && onLike && onLike(mainMessage.uid)}
  86. />
  87. <Button
  88. size="small"
  89. type="text"
  90. icon={<DislikeOutlined />}
  91. onClick={() =>
  92. mainMessage && onDislike && onDislike(mainMessage.uid)
  93. }
  94. />
  95. <Button
  96. size="small"
  97. type="text"
  98. icon={<ShareAltOutlined />}
  99. onClick={handleShare}
  100. />
  101. {/* 版本切换器 */}
  102. {session.versions && session.versions.length > 1 && (
  103. <VersionSwitcher
  104. versions={session.versions}
  105. currentVersion={session.current_version}
  106. onSwitch={(versionIndex) =>
  107. onVersionSwitch &&
  108. onVersionSwitch(session.versions[versionIndex].message_id)
  109. }
  110. />
  111. )}
  112. <Button
  113. size="small"
  114. type="text"
  115. icon={<RedoOutlined />}
  116. onClick={onRefresh}
  117. />
  118. </Space>
  119. </div>
  120. )}
  121. </div>
  122. );
  123. };
  124. export default AssistantMessage;