123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193 |
- /**
- * 文本|语音聊天框
- */
- import { create } from "zustand";
- import { generateUUID } from '@/utils/index'
- import { getMessageHistories, type TGetMessageHistoriesParams, } from '@/service/bot'
- import { EChatRole, TAnyMessage, TRobotMessage, TMessage } from "@/types/bot";
- type TRobotMessageWithOptionalId = Omit<TRobotMessage, "msgUk"> & {
- msgUk?: string; // 将 messageId 设置为可选
- reasoningContent?: string; // 添加 reasoningContent
- };
- const INIT_CURRENT_ROBOT_MSG_UK = ''
- export interface TextChat {
- currentRobotMsgUk: string; // 当前正在说话的 AI 机器人 id, 可用于控制是否继续输出文本至当前 message 框内
- scrollTop: number; // 控制聊天内容变化后滚动至最底部
- autoScroll: boolean
- list: TAnyMessage[];
- questions: string[]; //推荐问题
- sessionId: string|null
- // 显示聊天历史
- setAutoScroll: (b: boolean) => void // 是否自动滚动
- genSessionId: () => void // 进入聊天界面后,本次的 sessionId
- setQuestions: (q:string[]) => void // 设置推荐问题
- setScrollTop: () => void
- // 将机器人气泡框推入聊天框
- pushRobotMessage: (message: TRobotMessageWithOptionalId) => string;
- // 将自己发出的气泡框推入聊天框
- pushMessage: (content: string) => {msgUk: string, sessionId: string};
- // 更新自己发出的气泡框
- updateMessage: (content: string, msgUk: string) => string;
- // 更新机器人汽泡框内的内容实现 gpt 的效果
- updateRobotMessage: (content: string, body?: Record<string,any>, saveStatus?: number) => void;
- updateRobotReasoningMessage: (msgUk: string, reasoningContent: string, body?:Record<string,any>) => void;
- getCurrentRobotMessage:() => TRobotMessage|undefined
- deleteMessage: (msgUk: string) => void;
- // 清空
- destroy: () => void;
- fetchMessageHistories: (data: TGetMessageHistoriesParams) => void
- }
- // 新messageId 为 index 加 1
- const generateUk = () => {
- return generateUUID();
- }
- export const useTextChat = create<TextChat>((set, get) => ({
- currentRobotMsgUk: INIT_CURRENT_ROBOT_MSG_UK,
- scrollTop: 999999,
- autoScroll: true,
- list: [],
- sessionId: null,
- questions: [],
- setAutoScroll: (b)=> {
- set({autoScroll: b})
- },
- setQuestions: (q:string[])=> {
- set({questions: q})
- },
- genSessionId: ()=> {
- const sessionId = generateUUID();
- set({
- sessionId
- })
- },
- // 重置
- destroy: () => {
- set({
- list: [],
- questions: [],
- currentRobotMsgUk: INIT_CURRENT_ROBOT_MSG_UK,
- scrollTop: 9999,
- sessionId: null,
- });
- },
- pushRobotMessage: (message) => {
- const msgUk = generateUk()
- set((state) => {
- const newRobotMessage = { ...message, msgUk, role: EChatRole.Assistant } as TRobotMessage
- return {
- list: [...state.list, newRobotMessage],
- currentRobotMsgUk: msgUk,
- scrollTop: state.scrollTop + 1,
- };
- });
- setTimeout(()=> {
- set((state) => {
- return {
- scrollTop: state.scrollTop + 1,
- };
- });
- }, 100)
- return msgUk
- },
- setScrollTop: ()=> {
- set((state) => {
- return {
- scrollTop: state.scrollTop + 1,
- };
- });
- },
- pushMessage: (content: string) => {
- const msgUk = generateUk();
- const newMessage:TMessage ={ msgUk, content: content, role: EChatRole.User, saveStatus: 0 }
- set((state) => {
- return {
- list: [...state.list, newMessage],
- scrollTop: state.scrollTop + 1,
- };
- });
- setTimeout(()=> {
- set((state) => {
- return {
- scrollTop: state.scrollTop + 1,
- };
- });
- }, 100)
-
- return {msgUk, sessionId: get().sessionId ?? ''}
- },
- updateMessage: (content, msgUk) => {
- set((state) => {
- const updatedList = state.list.map((message) => {
- if (message.msgUk === msgUk) {
- return { ...message, content: message.content + content, saveStatus: 0 }; // 更新 content
- }
- return message; // 返回未修改的 message
- });
- return { list: updatedList, scrollTop: state.scrollTop + 1 }; // 返回新的状态
- });
- return msgUk
- },
- updateRobotMessage: (content, body={}, saveStatus: number = 0) => {
- set((state) => {
- const updatedList = state.list.map((message) => {
- if (message.msgUk === state.currentRobotMsgUk) {
- // 更新消息后, saveStatus 变为 0,说明又需要上报此消息
- return { ...message, content: message.content + content, body, saveStatus: saveStatus } as TRobotMessage // 更新 content
- }
- return message; // 返回未修改的 message
- });
-
- return { list: updatedList, scrollTop: state.autoScroll ? state.scrollTop + 1 : state.scrollTop}; // 返回新的状态
- });
- },
- getCurrentRobotMessage: ()=> {
- const state = get()
- const currentMessage = state.list.find((message)=> message.msgUk === state.currentRobotMsgUk) as TRobotMessage
- return currentMessage
- },
- updateRobotReasoningMessage: (msgUk, reasoningContent, body={}) => {
- set((state) => {
- // 由于 currentRobotMsgUk 可能发生变化, 所以需要传递 msgUk
- // console.log(state.currentRobotMsgUk, msgUk)
- const updatedList = state.list.map((message) => {
- if (message.msgUk === msgUk) {
- //@ts-ignore
- return { ...message, body, reasoningContent: message.reasoningContent + reasoningContent } as TRobotMessage // 更新 reasoningContent
- }
- return message; // 返回未修改的 message
- });
- return { list: updatedList, scrollTop: state.autoScroll ? state.scrollTop + 1 : state.scrollTop}; // 返回新的状态
- });
- },
- deleteMessage: (msgUk)=> {
- set((state) => {
- // 如果对话框是空的,则删除
- const filtered = state.list.filter((message) => {
- const isEmptyContent = message.content.length <= 0
- return (message.msgUk !== msgUk && isEmptyContent)
- });
- return { list: filtered, scrollTop: state.scrollTop + 1 }; // 返回新的状态
- });
- },
- // 停止当前机器人说话输出框输出
- stopCurrentRobotMessaging: ()=> {
- set({currentRobotMsgUk: INIT_CURRENT_ROBOT_MSG_UK})
- },
- fetchMessageHistories: async (data: TGetMessageHistoriesParams) => {
- const response = await getMessageHistories(data)
- console.log(response)
- if(response.status){
-
- }
- }
- }));
|