From a430284aa21e3ae1f0d5654e55b2ad2852519cc2 Mon Sep 17 00:00:00 2001
From: wwf <yearningwang@iqtogether.com>
Date: 星期三, 04 六月 2025 15:17:49 +0800
Subject: [PATCH] 初始化

---
 app/components/base/chat/chat-with-history/chat-wrapper.tsx |  194 +++++++++++++----------------------------------
 1 files changed, 55 insertions(+), 139 deletions(-)

diff --git a/app/components/base/chat/chat-with-history/chat-wrapper.tsx b/app/components/base/chat/chat-with-history/chat-wrapper.tsx
index 63de135..7725920 100644
--- a/app/components/base/chat/chat-with-history/chat-wrapper.tsx
+++ b/app/components/base/chat/chat-with-history/chat-wrapper.tsx
@@ -1,4 +1,4 @@
-import { useCallback, useEffect, useMemo, useState } from 'react'
+import { useCallback, useEffect, useMemo } from 'react'
 import Chat from '../chat'
 import type {
   ChatConfig,
@@ -9,20 +9,14 @@
 import { useChat } from '../chat/hooks'
 import { getLastAnswer, isValidGeneratedAnswer } from '../utils'
 import { useChatWithHistoryContext } from './context'
-import { InputVarType } from '@/app/components/workflow/types'
-import { TransferMethod } from '@/types/app'
-import InputsForm from '@/app/components/base/chat/chat-with-history/inputs-form'
+import Header from './header'
+import ConfigPanel from './config-panel'
 import {
   fetchSuggestedQuestions,
   getUrl,
   stopChatMessageResponding,
 } from '@/service/share'
-import AppIcon from '@/app/components/base/app-icon'
 import AnswerIcon from '@/app/components/base/answer-icon'
-import SuggestedQuestions from '@/app/components/base/chat/chat/answer/suggested-questions'
-import { Markdown } from '@/app/components/base/markdown'
-import cn from '@/utils/classnames'
-import type { FileEntity } from '../../file-uploader/types'
 
 const ChatWrapper = () => {
   const {
@@ -30,10 +24,8 @@
     appPrevChatTree,
     currentConversationId,
     currentConversationItem,
-    currentConversationInputs,
     inputsForms,
     newConversationInputs,
-    newConversationInputsRef,
     handleNewConversationCompleted,
     isMobile,
     isInstalledApp,
@@ -43,10 +35,6 @@
     currentChatInstanceRef,
     appData,
     themeBuilder,
-    sidebarCollapseState,
-    clearChatList,
-    setClearChatList,
-    setIsResponding,
   } = useChatWithHistoryContext()
   const appConfig = useMemo(() => {
     const config = appParams || {}
@@ -66,51 +54,17 @@
     setTargetMessageId,
     handleSend,
     handleStop,
-    isResponding: respondingState,
+    isResponding,
     suggestedQuestions,
   } = useChat(
     appConfig,
     {
-      inputs: (currentConversationId ? currentConversationInputs : newConversationInputs) as any,
+      inputs: (currentConversationId ? currentConversationItem?.inputs : newConversationInputs) as any,
       inputsForm: inputsForms,
     },
     appPrevChatTree,
     taskId => stopChatMessageResponding('', taskId, isInstalledApp, appId),
-    clearChatList,
-    setClearChatList,
   )
-  const inputsFormValue = currentConversationId ? currentConversationInputs : newConversationInputsRef?.current
-  const inputDisabled = useMemo(() => {
-    let hasEmptyInput = ''
-    let fileIsUploading = false
-    const requiredVars = inputsForms.filter(({ required }) => required)
-    if (requiredVars.length) {
-      requiredVars.forEach(({ variable, label, type }) => {
-        if (hasEmptyInput)
-          return
-
-        if (fileIsUploading)
-          return
-
-        if (!inputsFormValue?.[variable])
-          hasEmptyInput = label as string
-
-        if ((type === InputVarType.singleFile || type === InputVarType.multiFiles) && inputsFormValue?.[variable]) {
-          const files = inputsFormValue[variable]
-          if (Array.isArray(files))
-            fileIsUploading = files.find(item => item.transferMethod === TransferMethod.local_file && !item.uploadedId)
-          else
-            fileIsUploading = files.transferMethod === TransferMethod.local_file && !files.uploadedId
-        }
-      })
-    }
-    if (hasEmptyInput)
-      return true
-
-    if (fileIsUploading)
-      return true
-    return false
-  }, [inputsFormValue, inputsForms])
 
   useEffect(() => {
     if (currentChatInstanceRef.current)
@@ -118,15 +72,11 @@
   // eslint-disable-next-line react-hooks/exhaustive-deps
   }, [])
 
-  useEffect(() => {
-    setIsResponding(respondingState)
-  }, [respondingState, setIsResponding])
-
   const doSend: OnSend = useCallback((message, files, isRegenerate = false, parentAnswer: ChatItem | null = null) => {
     const data: any = {
       query: message,
       files,
-      inputs: currentConversationId ? currentConversationInputs : newConversationInputs,
+      inputs: currentConversationId ? currentConversationItem?.inputs : newConversationInputs,
       conversation_id: currentConversationId,
       parent_message_id: (isRegenerate ? parentAnswer?.id : getLastAnswer(chatList)?.id) || null,
     }
@@ -140,85 +90,59 @@
         isPublicAPI: !isInstalledApp,
       },
     )
-  }, [chatList, handleNewConversationCompleted, handleSend, currentConversationId, currentConversationInputs, newConversationInputs, isInstalledApp, appId])
+  }, [
+    chatList,
+    handleNewConversationCompleted,
+    handleSend,
+    currentConversationId,
+    currentConversationItem,
+    newConversationInputs,
+    isInstalledApp,
+    appId,
+  ])
 
-  const doRegenerate = useCallback((chatItem: ChatItemInTree, editedQuestion?: { message: string, files?: FileEntity[] }) => {
-    const question = editedQuestion ? chatItem : chatList.find(item => item.id === chatItem.parentMessageId)!
+  const doRegenerate = useCallback((chatItem: ChatItemInTree) => {
+    const question = chatList.find(item => item.id === chatItem.parentMessageId)!
     const parentAnswer = chatList.find(item => item.id === question.parentMessageId)
-    doSend(editedQuestion ? editedQuestion.message : question.content,
-      editedQuestion ? editedQuestion.files : question.message_files,
-      true,
-      isValidGeneratedAnswer(parentAnswer) ? parentAnswer : null,
-    )
+    doSend(question.content, question.message_files, true, isValidGeneratedAnswer(parentAnswer) ? parentAnswer : null)
   }, [chatList, doSend])
 
-  const messageList = useMemo(() => {
-    if (currentConversationId)
-      return chatList
-    return chatList.filter(item => !item.isOpeningStatement)
-  }, [chatList, currentConversationId])
-
-  const [collapsed, setCollapsed] = useState(!!currentConversationId)
-
   const chatNode = useMemo(() => {
-    if (!inputsForms.length)
-      return null
-    if (isMobile) {
-      if (!currentConversationId)
-        return <InputsForm collapsed={collapsed} setCollapsed={setCollapsed} />
-      return null
-    }
-    else {
-      return <InputsForm collapsed={collapsed} setCollapsed={setCollapsed} />
-    }
-  }, [inputsForms.length, isMobile, currentConversationId, collapsed])
-
-  const welcome = useMemo(() => {
-    const welcomeMessage = chatList.find(item => item.isOpeningStatement)
-    if (respondingState)
-      return null
-    if (currentConversationId)
-      return null
-    if (!welcomeMessage)
-      return null
-    if (!collapsed && inputsForms.length > 0)
-      return null
-    if (welcomeMessage.suggestedQuestions && welcomeMessage.suggestedQuestions?.length > 0) {
+    if (inputsForms.length) {
       return (
-        <div className='flex min-h-[50vh] items-center justify-center px-4 py-12'>
-          <div className='flex max-w-[720px] grow gap-4'>
-            <AppIcon
-              size='xl'
-              iconType={appData?.site.icon_type}
-              icon={appData?.site.icon}
-              background={appData?.site.icon_background}
-              imageUrl={appData?.site.icon_url}
-            />
-            <div className='w-0 grow'>
-              <div className='body-lg-regular grow rounded-2xl bg-chat-bubble-bg px-4 py-3 text-text-primary'>
-                <Markdown content={welcomeMessage.content} />
-                <SuggestedQuestions item={welcomeMessage} />
+        <>
+          <Header
+            isMobile={isMobile}
+            title={currentConversationItem?.name || ''}
+          />
+          {
+            !currentConversationId && (
+              <div className={`mx-auto w-full max-w-[720px] ${isMobile && 'px-4'}`}>
+                <div className='mb-6' />
+                <ConfigPanel />
+                <div
+                  className='my-6 h-[1px]'
+                  style={{ background: 'linear-gradient(90deg, rgba(242, 244, 247, 0.00) 0%, #F2F4F7 49.17%, rgba(242, 244, 247, 0.00) 100%)' }}
+                />
               </div>
-            </div>
-          </div>
-        </div>
+            )
+          }
+        </>
       )
     }
+
     return (
-      <div className={cn('flex h-[50vh] flex-col items-center justify-center gap-3 py-12')}>
-        <AppIcon
-          size='xl'
-          iconType={appData?.site.icon_type}
-          icon={appData?.site.icon}
-          background={appData?.site.icon_background}
-          imageUrl={appData?.site.icon_url}
-        />
-        <div className='max-w-[768px] px-4'>
-          <Markdown className='!body-2xl-regular !text-text-tertiary' content={welcomeMessage.content} />
-        </div>
-      </div>
+      <Header
+        isMobile={isMobile}
+        title={currentConversationItem?.name || ''}
+      />
     )
-  }, [appData?.site.icon, appData?.site.icon_background, appData?.site.icon_type, appData?.site.icon_url, chatList, collapsed, currentConversationId, inputsForms.length, respondingState])
+  }, [
+    currentConversationId,
+    inputsForms,
+    currentConversationItem,
+    isMobile,
+  ])
 
   const answerIcon = (appData?.site && appData.site.use_icon_as_answer_icon)
     ? <AnswerIcon
@@ -231,27 +155,22 @@
 
   return (
     <div
-      className='h-full overflow-hidden bg-chatbot-bg'
+      className='h-full bg-chatbot-bg overflow-hidden'
     >
       <Chat
         appData={appData}
         config={appConfig}
-        chatList={messageList}
-        isResponding={respondingState}
-        chatContainerInnerClassName={`mx-auto pt-6 w-full max-w-[768px] ${isMobile && 'px-4'}`}
+        chatList={chatList}
+        isResponding={isResponding}
+        chatContainerInnerClassName={`mx-auto pt-6 w-full max-w-[720px] ${isMobile && 'px-4'}`}
         chatFooterClassName='pb-4'
-        chatFooterInnerClassName={`mx-auto w-full max-w-[768px] ${isMobile ? 'px-2' : 'px-4'}`}
+        chatFooterInnerClassName={`mx-auto w-full max-w-[720px] ${isMobile && 'px-4'}`}
         onSend={doSend}
-        inputs={currentConversationId ? currentConversationInputs as any : newConversationInputs}
+        inputs={currentConversationId ? currentConversationItem?.inputs as any : newConversationInputs}
         inputsForm={inputsForms}
         onRegenerate={doRegenerate}
         onStopResponding={handleStop}
-        chatNode={
-          <>
-            {chatNode}
-            {welcome}
-          </>
-        }
+        chatNode={chatNode}
         allToolIcons={appMeta?.tool_icons || {}}
         onFeedback={handleFeedback}
         suggestedQuestions={suggestedQuestions}
@@ -259,9 +178,6 @@
         hideProcessDetail
         themeBuilder={themeBuilder}
         switchSibling={siblingMessageId => setTargetMessageId(siblingMessageId)}
-        inputDisabled={inputDisabled}
-        isMobile={isMobile}
-        sidebarCollapseState={sidebarCollapseState}
       />
     </div>
   )

--
Gitblit v1.8.0