import { View, ScrollView, Video } from "@tarojs/components"; import NavBarNormal from "@/components/NavBarNormal/index"; import PageCustom from "@/components/page-custom/index"; import Taro, { useDidShow, useRouter, useUnload } from "@tarojs/taro"; import ChatMessage from "@/components/chat-message"; import InputBar from "./components/input-bar"; import { useEffect, useState, useRef, useMemo } from "react"; import { useTextChat } from "@/store/textChat"; import { TRobotMessage, TMessage, EContentType, EChatRole } from "@/types/bot"; import ChatGreeting from "./components/ChatGreeting"; import IconArrowLeftWhite24 from "@/components/icon/IconArrowLeftWhite24"; import PersonalCard from "./components/personal-card"; import { useAgentStore } from "@/store/agentStore"; import { useLoadMoreInfinite, createKey } from "@/utils/loadMoreInfinite"; import { getMessageHistories } from "@/service/bot"; import RecommendQuestions from './components/RecommendQuestions' import {useKeyboard} from './components/keyboard' import { saveMessageToServer } from "./components/input-bar/message"; import { generateUUID, getLoginId } from '@/utils/index' export default function Index() { const router = useRouter(); const { agentId, isVisitor } = router.params; if (!agentId) { return 没有相应的智能体; } const { fetchAgent, fetchAgentProfile, } = useAgentStore() const agent = useAgentStore((state) => { if(isVisitor === 'true'){ return state.agentProfile } return state.agent }); const scrollViewRef = useRef(null); const messageList = useTextChat((state) => state.list); const {keyboardHeight, marginTopOffset, triggerHeightUpdate,} = useKeyboard(scrollViewRef, '#messageList', '#scrollView') const { destroy, setScrollTop, genSessionId, sessionId, setAutoScroll } = useTextChat(); const scrollTop = useTextChat((state) => state.scrollTop); // const autoScroll = useTextChat((state) => state.autoScroll); const fetcher = async ([_url,{ nextId, pageSize}]) => { const _nextId = nextId ? decodeURIComponent(nextId) : nextId; const res = await getMessageHistories({ agentId, startId: _nextId, pageSize, }); return res.data; }; const { list, loadMore, pageIndex, mutate } = useLoadMoreInfinite( createKey(`messeagehistories${isVisitor}${agentId}`), fetcher, ); const parsedList = list.map((item: TMessage|TRobotMessage) => { if(item.contentType == EContentType.AiseekQA){ try{ const contentJson = JSON.parse(item.content as string) item.content = contentJson.answer.text // 把消息详情放入统一 body 中 item.body = {...item, content: contentJson, contentType: EContentType.AiseekQA} }catch(e){ // console.error(e) } } return item }) const allMessages = useMemo(()=> [...[...parsedList].reverse(), ...messageList], [parsedList, messageList]) const messagesLength = useMemo(() => allMessages.length, [allMessages.length]); const prevLengthRef = useRef(messagesLength); const [showWelcome, setShowWelcome] = useState(!list.length); // 加载更多 const onScrollToUpper = () => { console.log("onscroll"); loadMore(); }; const handleTouchMove = ()=> { console.log('set auto scroll false') setAutoScroll(false) } useDidShow(()=> { mutate(undefined,{revalidate: true}) }) useEffect(() => { if(agentId){ if(isVisitor){ fetchAgentProfile(agentId) }else{ fetchAgent(agentId); } } }, [agentId, isVisitor]); // 是否显示欢迎 ui useEffect(() => { setShowWelcome(!messageList.length && !list.length); }, [list, messageList]); // 将 greeting 开场白存入聊天记录里 // useEffect(()=> { // console.log(showWelcome, agent) // if(!showWelcome){ // return; // } // const loginId = getLoginId(); // if (!loginId || !agent?.agentId || !agent?.greeting || !sessionId) { // return; // } // saveMessageToServer({ // loginId, // messages: [{ // content: agent.greeting, // contentType: EContentType.TextPlain, // role: EChatRole.Assistant, // saveStatus: 2, // isStreaming: false, // msgUk: generateUUID(), // }], // agentId: agent.agentId, // sessionId, // }) // }, [showWelcome, sessionId]) // 首次进入界面滚动到底 useEffect(() => { if (pageIndex === 1) { setTimeout(() => { setScrollTop(); }, 300); } }, [pageIndex]); // 首次进入聊天生成 session id useEffect(() => { genSessionId(); }, []); // 监听消息列表变化,触发键盘高度重新计算 useEffect(() => { // 只在长度真正变化时才触发 if (prevLengthRef.current !== messagesLength) { prevLengthRef.current = messagesLength; // 使用 setTimeout 确保 DOM 更新完成后再计算高度 const timer = setTimeout(() => { triggerHeightUpdate(); }, 100); return () => clearTimeout(timer); } }, [messagesLength, triggerHeightUpdate]); useUnload(() => { destroy(); }); const renderNavLeft = () => { return ( Taro.navigateBack()} > ); }; // 大背景可以是视频,也可以是图片 const getBgContent = ()=> { if(!agent?.avatarUrl || !!!agent?.enabledChatBg){ return '' } return agent?.avatarUrl } useEffect(()=> { Taro.setNavigationBarColor({ frontColor: '#ffffff', backgroundColor: 'transparent' }) return ()=> { Taro.setNavigationBarColor({ frontColor: '#000000', backgroundColor: 'transparent' }) } }) return ( {/* <>{`${scrollTop}`}--{autoScroll ? 'true': 'false'} */} setAutoScroll(true)} > {showWelcome && } {/* 复制 histories 再 reverse 否则会影响 state */} {allMessages.map((message) => { const reasoningContent = (message as any).reasoningContent || ''; return ( ); })} {(agent) && } {/* 输入框高度占位块,todo: 改成动态获取输入框块高度 */} {agent && ( )} ); }