textChat.ts 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. /**
  2. * 文本|语音聊天框
  3. */
  4. import { create } from "zustand";
  5. import { generateRandomId } from '@/utils/index'
  6. import { getMessageHistories as _getMessageHistories, type TGetMessageHistoriesParams, } from '@/service/bot'
  7. export type TMessage = {
  8. messageId: string;
  9. content: string;
  10. };
  11. export type TRobotMessage = {
  12. reasoningContent: string
  13. robot: {
  14. avatar: string;
  15. agentId: string;
  16. name: string;
  17. };
  18. } & TMessage;
  19. type TRobotMessageWithOptionalId = Omit<TRobotMessage, "messageId"> & {
  20. messageId?: string; // 将 messageId 设置为可选
  21. reasoningContent?: string; // 添加 reasoningContent
  22. };
  23. const INIT_CURRENT_ROBOT_MESSAGE_ID = ''
  24. export interface TextChat {
  25. currentRobotMessageId: string; // 当前正在说话的 AI 机器人 id, 可用于控制是否继续输出文本至当前 message 框内
  26. scrollTop: number; // 控制聊天内容变化后滚动至最底部
  27. list: (TMessage | TRobotMessage)[];
  28. // 将机器人气泡框推入聊天框
  29. pushRobotMessage: (message: TRobotMessageWithOptionalId) => string;
  30. // 将自己发出的气泡框推入聊天框
  31. pushMessage: (content: string) => string;
  32. // 更新自己发出的气泡框
  33. updateMessage: (content: string, messageId: string) => string;
  34. // 更新机器人汽泡框内的内容实现 gpt 的效果
  35. updateRobotMessage: (content: string) => void;
  36. updateRobotReasoningMessage: (reasoningContent: string, messageId: string) => void;
  37. getCurrentRobotMessage:() => TRobotMessage|undefined
  38. deleteMessage: (messageId: string) => void;
  39. // 清空
  40. destroy: () => void;
  41. getMessageHistories: (data: TGetMessageHistoriesParams) => void
  42. }
  43. // 新messageId 为 index 加 1
  44. const generateMessageId = () => {
  45. return generateRandomId();
  46. }
  47. export const useTextChat = create<TextChat>((set, get) => ({
  48. currentRobotMessageId: INIT_CURRENT_ROBOT_MESSAGE_ID,
  49. scrollTop: 9999,
  50. list: [],
  51. destroy: () => {
  52. set({
  53. list: [],
  54. currentRobotMessageId: INIT_CURRENT_ROBOT_MESSAGE_ID,
  55. scrollTop: 9999,
  56. });
  57. },
  58. pushRobotMessage: (message) => {
  59. const messageId = generateMessageId()
  60. set((state) => {
  61. return {
  62. list: [...state.list, { ...message, messageId }],
  63. currentRobotMessageId: messageId,
  64. scrollTop: state.scrollTop + 1,
  65. };
  66. });
  67. setTimeout(()=> {
  68. set((state) => {
  69. return {
  70. scrollTop: state.scrollTop + 1,
  71. };
  72. });
  73. }, 100)
  74. return messageId
  75. },
  76. pushMessage: (content: string) => {
  77. const messageId = generateMessageId()
  78. set((state) => {
  79. return {
  80. list: [...state.list, { messageId, content: content }],
  81. scrollTop: state.scrollTop + 1,
  82. };
  83. });
  84. setTimeout(()=> {
  85. set((state) => {
  86. return {
  87. scrollTop: state.scrollTop + 1,
  88. };
  89. });
  90. }, 100)
  91. return messageId
  92. },
  93. updateMessage: (content, messageId) => {
  94. set((state) => {
  95. const updatedList = state.list.map((message) => {
  96. if (message.messageId === messageId) {
  97. return { ...message, content: message.content + content }; // 更新 content
  98. }
  99. return message; // 返回未修改的 message
  100. });
  101. return { list: updatedList, scrollTop: state.scrollTop + 1 }; // 返回新的状态
  102. });
  103. return messageId
  104. },
  105. updateRobotMessage: (content) => {
  106. set((state) => {
  107. const updatedList = state.list.map((message) => {
  108. if (message.messageId === state.currentRobotMessageId) {
  109. return { ...message, content: message.content + content }; // 更新 content
  110. }
  111. return message; // 返回未修改的 message
  112. });
  113. return { list: updatedList, scrollTop: state.scrollTop + 1 }; // 返回新的状态
  114. });
  115. },
  116. getCurrentRobotMessage: ()=> {
  117. const state = get()
  118. const currentMessage = state.list.find((message)=> message.messageId === state.currentRobotMessageId) as TRobotMessage
  119. return currentMessage
  120. },
  121. updateRobotReasoningMessage: (reasoningContent, messageId) => {
  122. set((state) => {
  123. // 由于 currentRobotMessageId 可能发生变化, 所以需要传递 messageId
  124. // console.log(state.currentRobotMessageId, messageId)
  125. const updatedList = state.list.map((message) => {
  126. if (message.messageId === messageId) {
  127. //@ts-ignore
  128. return { ...message, reasoningContent: message.reasoningContent + reasoningContent }; // 更新 reasoningContent
  129. }
  130. return message; // 返回未修改的 message
  131. });
  132. return { list: updatedList, scrollTop: state.scrollTop + 1 }; // 返回新的状态
  133. });
  134. },
  135. deleteMessage: (messageId)=> {
  136. set((state) => {
  137. // 如果对话框是空的,则删除
  138. const filtered = state.list.filter((message) => {
  139. const isEmptyContent = message.content.length <= 0
  140. return (message.messageId !== messageId && isEmptyContent)
  141. });
  142. return { list: filtered, scrollTop: state.scrollTop + 1 }; // 返回新的状态
  143. });
  144. },
  145. // 停止当前机器人说话输出框输出
  146. stopCurrentRobotMessaging: ()=> {
  147. set({currentRobotMessageId: INIT_CURRENT_ROBOT_MESSAGE_ID})
  148. },
  149. getMessageHistories: async (data: TGetMessageHistoriesParams) => {
  150. const response = await _getMessageHistories(data)
  151. console.log(response)
  152. if(response.status){
  153. }
  154. }
  155. }));