/** * 文本|语音聊天框 */ import { create } from "zustand"; import { generateRandomId } from '@/utils/index' import { getMessageHistories as _getMessageHistories, type TGetMessageHistoriesParams, } from '@/service/bot' export type TMessage = { messageId: string; content: string; }; export type TRobotMessage = { reasoningContent: string robot: { avatar: string; agentId: string; name: string; }; } & TMessage; type TRobotMessageWithOptionalId = Omit & { messageId?: string; // 将 messageId 设置为可选 reasoningContent?: string; // 添加 reasoningContent }; const INIT_CURRENT_ROBOT_MESSAGE_ID = '' export interface TextChat { currentRobotMessageId: string; // 当前正在说话的 AI 机器人 id, 可用于控制是否继续输出文本至当前 message 框内 scrollTop: number; // 控制聊天内容变化后滚动至最底部 list: (TMessage | TRobotMessage)[]; // 将机器人气泡框推入聊天框 pushRobotMessage: (message: TRobotMessageWithOptionalId) => string; // 将自己发出的气泡框推入聊天框 pushMessage: (content: string) => string; // 更新自己发出的气泡框 updateMessage: (content: string, messageId: string) => string; // 更新机器人汽泡框内的内容实现 gpt 的效果 updateRobotMessage: (content: string) => void; updateRobotReasoningMessage: (reasoningContent: string, messageId: string) => void; getCurrentRobotMessage:() => TRobotMessage|undefined deleteMessage: (messageId: string) => void; // 清空 destroy: () => void; getMessageHistories: (data: TGetMessageHistoriesParams) => void } // 新messageId 为 index 加 1 const generateMessageId = () => { return generateRandomId(); } export const useTextChat = create((set, get) => ({ currentRobotMessageId: INIT_CURRENT_ROBOT_MESSAGE_ID, scrollTop: 9999, list: [], destroy: () => { set({ list: [], currentRobotMessageId: INIT_CURRENT_ROBOT_MESSAGE_ID, scrollTop: 9999, }); }, pushRobotMessage: (message) => { const messageId = generateMessageId() set((state) => { return { list: [...state.list, { ...message, messageId }], currentRobotMessageId: messageId, scrollTop: state.scrollTop + 1, }; }); setTimeout(()=> { set((state) => { return { scrollTop: state.scrollTop + 1, }; }); }, 100) return messageId }, pushMessage: (content: string) => { const messageId = generateMessageId() set((state) => { return { list: [...state.list, { messageId, content: content }], scrollTop: state.scrollTop + 1, }; }); setTimeout(()=> { set((state) => { return { scrollTop: state.scrollTop + 1, }; }); }, 100) return messageId }, updateMessage: (content, messageId) => { set((state) => { const updatedList = state.list.map((message) => { if (message.messageId === messageId) { return { ...message, content: message.content + content }; // 更新 content } return message; // 返回未修改的 message }); return { list: updatedList, scrollTop: state.scrollTop + 1 }; // 返回新的状态 }); return messageId }, updateRobotMessage: (content) => { set((state) => { const updatedList = state.list.map((message) => { if (message.messageId === state.currentRobotMessageId) { return { ...message, content: message.content + content }; // 更新 content } return message; // 返回未修改的 message }); return { list: updatedList, scrollTop: state.scrollTop + 1 }; // 返回新的状态 }); }, getCurrentRobotMessage: ()=> { const state = get() const currentMessage = state.list.find((message)=> message.messageId === state.currentRobotMessageId) as TRobotMessage return currentMessage }, updateRobotReasoningMessage: (reasoningContent, messageId) => { set((state) => { // 由于 currentRobotMessageId 可能发生变化, 所以需要传递 messageId // console.log(state.currentRobotMessageId, messageId) const updatedList = state.list.map((message) => { if (message.messageId === messageId) { //@ts-ignore return { ...message, reasoningContent: message.reasoningContent + reasoningContent }; // 更新 reasoningContent } return message; // 返回未修改的 message }); return { list: updatedList, scrollTop: state.scrollTop + 1 }; // 返回新的状态 }); }, deleteMessage: (messageId)=> { set((state) => { // 如果对话框是空的,则删除 const filtered = state.list.filter((message) => { const isEmptyContent = message.content.length <= 0 return (message.messageId !== messageId && isEmptyContent) }); return { list: filtered, scrollTop: state.scrollTop + 1 }; // 返回新的状态 }); }, // 停止当前机器人说话输出框输出 stopCurrentRobotMessaging: ()=> { set({currentRobotMessageId: INIT_CURRENT_ROBOT_MESSAGE_ID}) }, getMessageHistories: async (data: TGetMessageHistoriesParams) => { const response = await _getMessageHistories(data) console.log(response) if(response.status){ } } }));