import { ChatContentContext } from '@/pages/chat'; import { LoadingOutlined } from '@ant-design/icons'; import { Button, Input, Spin } from 'antd'; import classNames from 'classnames'; import { useSearchParams } from 'next/navigation'; import React, { forwardRef, useContext, useImperativeHandle, useMemo, useRef, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { UserChatContent } from '@/types/chat'; import { parseResourceValue } from '@/utils'; import ToolsBar from './ToolsBar'; const ChatInputPanel: React.ForwardRefRenderFunction = ({ ctrl }, ref) => { const { t } = useTranslation(); const { replyLoading, handleChat, appInfo, currentDialogue, temperatureValue, maxNewTokensValue, resourceValue, setResourceValue, refreshDialogList, } = useContext(ChatContentContext); const searchParams = useSearchParams(); const scene = searchParams?.get('scene') ?? ''; const select_param = searchParams?.get('select_param') ?? ''; const [userInput, setUserInput] = useState(''); const [isFocus, setIsFocus] = useState(false); const [isZhInput, setIsZhInput] = useState(false); const submitCountRef = useRef(0); const paramKey: string[] = useMemo(() => { return appInfo.param_need?.map(i => i.type) || []; }, [appInfo.param_need]); const onSubmit = async () => { submitCountRef.current++; // Remove immediate scroll to avoid conflict with ChatContentContainer's auto-scroll // ChatContentContainer will handle scrolling when new content is added setUserInput(''); const resources = parseResourceValue(resourceValue); // Clear the resourceValue if it not empty let newUserInput: UserChatContent; if (resources.length > 0) { if (scene !== 'chat_excel') { // Chat Excel scene does not need to clear the resourceValue // We need to find a better way to handle this setResourceValue(null); } const messages = [...resources]; messages.push({ type: 'text', text: userInput, }); newUserInput = { role: 'user', content: messages, }; } else { newUserInput = userInput; } const params = { app_code: appInfo.app_code || '', ...(paramKey.includes('temperature') && { temperature: temperatureValue }), ...(paramKey.includes('max_new_tokens') && { max_new_tokens: maxNewTokensValue }), select_param, ...(paramKey.includes('resource') && { select_param: typeof resourceValue === 'string' ? resourceValue : JSON.stringify(resourceValue) || currentDialogue.select_param, }), }; await handleChat(newUserInput, params); // 如果应用进来第一次对话,刷新对话列表 if (submitCountRef.current === 1) { await refreshDialogList(); } }; // expose setUserInput to parent via ref useImperativeHandle(ref, () => ({ setUserInput, })); return (
{ if (e.key === 'Enter') { if (e.shiftKey) { return; } if (isZhInput) { return; } e.preventDefault(); if (!userInput.trim() || replyLoading) { return; } onSubmit(); } }} onChange={e => { setUserInput(e.target.value); }} onFocus={() => { setIsFocus(true); }} onBlur={() => setIsFocus(false)} onCompositionStart={() => setIsZhInput(true)} onCompositionEnd={() => setIsZhInput(false)} />
); }; export default forwardRef(ChatInputPanel);