ChatArea.jsx 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. /*
  2. Copyright (C) 2025 QuantumNous
  3. This program is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU Affero General Public License as
  5. published by the Free Software Foundation, either version 3 of the
  6. License, or (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU Affero General Public License for more details.
  11. You should have received a copy of the GNU Affero General Public License
  12. along with this program. If not, see <https://www.gnu.org/licenses/>.
  13. For commercial licensing, please contact support@quantumnous.com
  14. */
  15. import React from 'react';
  16. import { Card, Chat, Typography, Button } from '@douyinfe/semi-ui';
  17. import { MessageSquare, Eye, EyeOff } from 'lucide-react';
  18. import { useTranslation } from 'react-i18next';
  19. import CustomInputRender from './CustomInputRender';
  20. const ChatArea = ({
  21. chatRef,
  22. message,
  23. inputs,
  24. styleState,
  25. showDebugPanel,
  26. roleInfo,
  27. onMessageSend,
  28. onMessageCopy,
  29. onMessageReset,
  30. onMessageDelete,
  31. onStopGenerator,
  32. onClearMessages,
  33. onToggleDebugPanel,
  34. renderCustomChatContent,
  35. renderChatBoxAction,
  36. }) => {
  37. const { t } = useTranslation();
  38. const renderInputArea = React.useCallback((props) => {
  39. return <CustomInputRender {...props} />;
  40. }, []);
  41. return (
  42. <Card
  43. className='h-full'
  44. bordered={false}
  45. bodyStyle={{
  46. padding: 0,
  47. height: 'calc(100vh - 66px)',
  48. display: 'flex',
  49. flexDirection: 'column',
  50. overflow: 'hidden',
  51. }}
  52. >
  53. {/* 聊天头部 */}
  54. {styleState.isMobile ? (
  55. <div className='pt-4'></div>
  56. ) : (
  57. <div className='px-6 py-4 bg-gradient-to-r from-purple-500 to-blue-500 rounded-t-2xl'>
  58. <div className='flex items-center justify-between'>
  59. <div className='flex items-center gap-3'>
  60. <div className='w-10 h-10 rounded-full bg-white/20 backdrop-blur flex items-center justify-center'>
  61. <MessageSquare size={20} className='text-white' />
  62. </div>
  63. <div>
  64. <Typography.Title heading={5} className='!text-white mb-0'>
  65. {t('AI 对话')}
  66. </Typography.Title>
  67. <Typography.Text className='!text-white/80 text-sm hidden sm:inline'>
  68. {inputs.model || t('选择模型开始对话')}
  69. </Typography.Text>
  70. </div>
  71. </div>
  72. <div className='flex items-center gap-2'>
  73. <Button
  74. icon={showDebugPanel ? <EyeOff size={14} /> : <Eye size={14} />}
  75. onClick={onToggleDebugPanel}
  76. theme='borderless'
  77. type='primary'
  78. size='small'
  79. className='!rounded-lg !text-white/80 hover:!text-white hover:!bg-white/10'
  80. >
  81. {showDebugPanel ? t('隐藏调试') : t('显示调试')}
  82. </Button>
  83. </div>
  84. </div>
  85. </div>
  86. )}
  87. {/* 聊天内容区域 */}
  88. <div className='flex-1 overflow-hidden'>
  89. <Chat
  90. ref={chatRef}
  91. chatBoxRenderConfig={{
  92. renderChatBoxContent: renderCustomChatContent,
  93. renderChatBoxAction: renderChatBoxAction,
  94. renderChatBoxTitle: () => null,
  95. }}
  96. renderInputArea={renderInputArea}
  97. roleConfig={roleInfo}
  98. style={{
  99. height: '100%',
  100. maxWidth: '100%',
  101. overflow: 'hidden',
  102. }}
  103. chats={message}
  104. onMessageSend={onMessageSend}
  105. onMessageCopy={onMessageCopy}
  106. onMessageReset={onMessageReset}
  107. onMessageDelete={onMessageDelete}
  108. showClearContext
  109. showStopGenerate
  110. onStopGenerator={onStopGenerator}
  111. onClear={onClearMessages}
  112. className='h-full'
  113. placeholder={t('请输入您的问题...')}
  114. />
  115. </div>
  116. </Card>
  117. );
  118. };
  119. export default ChatArea;