chat-dialog.tsx 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. import { apiInterceptors, newDialogue } from '@/client/api';
  2. import useChat from '@/hooks/use-chat';
  3. import { IChatDialogueMessageSchema, IChatDialogueSchema } from '@/types/chat';
  4. import { CaretLeftOutlined } from '@ant-design/icons';
  5. import { useRequest } from 'ahooks';
  6. import classNames from 'classnames';
  7. import { useCallback, useState } from 'react';
  8. import AgentContent from '../chat/agent-content';
  9. import ChatContent from '../chat/chat-content';
  10. import { renderModelIcon } from '../chat/header/model-selector';
  11. import MyEmpty from './MyEmpty';
  12. import CompletionInput from './completion-input';
  13. interface Props {
  14. title?: string;
  15. completionApi?: string;
  16. chatMode: IChatDialogueSchema['chat_mode'];
  17. chatParams?: {
  18. select_param?: string;
  19. } & Record<string, string>;
  20. model?: string;
  21. }
  22. function ChatDialog({ title, chatMode, completionApi, chatParams, model = '' }: Props) {
  23. const { chat } = useChat({ queryAgentURL: completionApi });
  24. const [loading, setLoading] = useState(false);
  25. const [list, setList] = useState<IChatDialogueMessageSchema[]>([]);
  26. const [open, setOpen] = useState(false);
  27. const { data } = useRequest(
  28. async () => {
  29. const [, res] = await apiInterceptors(newDialogue({ chat_mode: chatMode }));
  30. return res;
  31. },
  32. {
  33. ready: !!chatMode,
  34. },
  35. );
  36. const handleChat = useCallback(
  37. (content: string) => {
  38. if (!data) return;
  39. return new Promise<void>(resolve => {
  40. const tempList: IChatDialogueMessageSchema[] = [
  41. ...list,
  42. { role: 'human', context: content, model_name: model, order: 0, time_stamp: 0 },
  43. { role: 'view', context: '', model_name: model, order: 0, time_stamp: 0 },
  44. ];
  45. const index = tempList.length - 1;
  46. setList([...tempList]);
  47. setLoading(true);
  48. chat({
  49. chatId: data?.conv_uid,
  50. data: { ...chatParams, chat_mode: chatMode, model_name: model, user_input: content },
  51. onMessage: message => {
  52. tempList[index].context = message;
  53. setList([...tempList]);
  54. },
  55. onDone: () => {
  56. resolve();
  57. },
  58. onClose: () => {
  59. resolve();
  60. },
  61. onError: message => {
  62. tempList[index].context = message;
  63. setList([...tempList]);
  64. resolve();
  65. },
  66. }).finally(() => {
  67. setLoading(false);
  68. });
  69. });
  70. },
  71. [chat, list, data?.conv_uid],
  72. );
  73. return (
  74. <div
  75. className={classNames(
  76. 'fixed top-0 right-0 w-[30rem] h-screen flex flex-col bg-white dark:bg-theme-dark-container shadow-[-5px_0_40px_-4px_rgba(100,100,100,.1)] transition-transform duration-300',
  77. {
  78. 'translate-x-0': open,
  79. 'translate-x-full': !open,
  80. },
  81. )}
  82. >
  83. {title && <div className='p-4 border-b border-solid border-gray-100'>{title}</div>}
  84. <div className='flex-1 overflow-y-auto px-2'>
  85. {list.map((item, index) => (
  86. <>
  87. {chatParams?.chat_mode === 'chat_agent' ? (
  88. <AgentContent key={index} content={item} />
  89. ) : (
  90. <ChatContent key={index} content={item} />
  91. )}
  92. </>
  93. ))}
  94. {!list.length && <MyEmpty description='' />}
  95. </div>
  96. <div className='flex w-full p-4 border-t border-solid border-gray-100 items-center'>
  97. {model && <div className='mr-2 flex'>{renderModelIcon(model)}</div>}
  98. <CompletionInput loading={loading} onSubmit={handleChat} />
  99. </div>
  100. <div
  101. className='flex items-center justify-center rounded-tl rounded-bl cursor-pointer w-5 h-11 absolute top-[50%] -left-5 -translate-y-[50%] bg-white'
  102. onClick={() => {
  103. setOpen(!open);
  104. }}
  105. >
  106. <CaretLeftOutlined />
  107. </div>
  108. </div>
  109. );
  110. }
  111. export default ChatDialog;