Compare commits
1 Commits
main
...
release/1.
Author | SHA1 | Date | |
---|---|---|---|
![]() |
b4a07d9e96 |
@ -19,6 +19,7 @@ import {
|
|||||||
} from '@/service/share'
|
} from '@/service/share'
|
||||||
import AppIcon from '@/app/components/base/app-icon'
|
import AppIcon from '@/app/components/base/app-icon'
|
||||||
import AnswerIcon from '@/app/components/base/answer-icon'
|
import AnswerIcon from '@/app/components/base/answer-icon'
|
||||||
|
import SuggestedQuestions from '@/app/components/base/chat/chat/answer/suggested-questions'
|
||||||
import cn from '@/utils/classnames'
|
import cn from '@/utils/classnames'
|
||||||
|
|
||||||
const ChatWrapper = () => {
|
const ChatWrapper = () => {
|
||||||
@ -39,6 +40,7 @@ const ChatWrapper = () => {
|
|||||||
currentChatInstanceRef,
|
currentChatInstanceRef,
|
||||||
appData,
|
appData,
|
||||||
themeBuilder,
|
themeBuilder,
|
||||||
|
sidebarCollapseState,
|
||||||
} = useChatWithHistoryContext()
|
} = useChatWithHistoryContext()
|
||||||
const appConfig = useMemo(() => {
|
const appConfig = useMemo(() => {
|
||||||
const config = appParams || {}
|
const config = appParams || {}
|
||||||
@ -144,10 +146,10 @@ const ChatWrapper = () => {
|
|||||||
}, [chatList, doSend])
|
}, [chatList, doSend])
|
||||||
|
|
||||||
const messageList = useMemo(() => {
|
const messageList = useMemo(() => {
|
||||||
if (currentConversationId)
|
if (currentConversationId || isResponding)
|
||||||
return chatList
|
return chatList
|
||||||
return chatList.filter(item => !item.isOpeningStatement)
|
return chatList.filter(item => !item.isOpeningStatement)
|
||||||
}, [chatList, currentConversationId])
|
}, [chatList, currentConversationId, isResponding])
|
||||||
|
|
||||||
const [collapsed, setCollapsed] = useState(!!currentConversationId)
|
const [collapsed, setCollapsed] = useState(!!currentConversationId)
|
||||||
|
|
||||||
@ -166,12 +168,33 @@ const ChatWrapper = () => {
|
|||||||
|
|
||||||
const welcome = useMemo(() => {
|
const welcome = useMemo(() => {
|
||||||
const welcomeMessage = chatList.find(item => item.isOpeningStatement)
|
const welcomeMessage = chatList.find(item => item.isOpeningStatement)
|
||||||
|
if (isResponding)
|
||||||
|
return null
|
||||||
if (currentConversationId)
|
if (currentConversationId)
|
||||||
return null
|
return null
|
||||||
if (!welcomeMessage)
|
if (!welcomeMessage)
|
||||||
return null
|
return null
|
||||||
if (!collapsed && inputsForms.length > 0)
|
if (!collapsed && inputsForms.length > 0)
|
||||||
return null
|
return null
|
||||||
|
if (welcomeMessage.suggestedQuestions && welcomeMessage.suggestedQuestions?.length > 0) {
|
||||||
|
return (
|
||||||
|
<div className='h-[50vh] py-12 px-4 flex items-center justify-center'>
|
||||||
|
<div className='grow max-w-[720px] flex 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='grow px-4 py-3 bg-chat-bubble-bg text-text-primary rounded-2xl body-lg-regular'>
|
||||||
|
{welcomeMessage.content}
|
||||||
|
<SuggestedQuestions item={welcomeMessage} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<div className={cn('h-[50vh] py-12 flex flex-col items-center justify-center gap-3')}>
|
<div className={cn('h-[50vh] py-12 flex flex-col items-center justify-center gap-3')}>
|
||||||
<AppIcon
|
<AppIcon
|
||||||
@ -184,7 +207,7 @@ const ChatWrapper = () => {
|
|||||||
<div className='text-text-tertiary body-2xl-regular'>{welcomeMessage.content}</div>
|
<div className='text-text-tertiary body-2xl-regular'>{welcomeMessage.content}</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}, [appData?.site.icon, appData?.site.icon_background, appData?.site.icon_type, appData?.site.icon_url, chatList, collapsed, currentConversationId, inputsForms.length])
|
}, [appData?.site.icon, appData?.site.icon_background, appData?.site.icon_type, appData?.site.icon_url, chatList, collapsed, currentConversationId, inputsForms.length, isResponding])
|
||||||
|
|
||||||
const answerIcon = (appData?.site && appData.site.use_icon_as_answer_icon)
|
const answerIcon = (appData?.site && appData.site.use_icon_as_answer_icon)
|
||||||
? <AnswerIcon
|
? <AnswerIcon
|
||||||
@ -227,6 +250,7 @@ const ChatWrapper = () => {
|
|||||||
switchSibling={siblingMessageId => setTargetMessageId(siblingMessageId)}
|
switchSibling={siblingMessageId => setTargetMessageId(siblingMessageId)}
|
||||||
inputDisabled={inputDisabled}
|
inputDisabled={inputDisabled}
|
||||||
isMobile={isMobile}
|
isMobile={isMobile}
|
||||||
|
sidebarCollapseState={sidebarCollapseState}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
@ -9,7 +9,7 @@ import {
|
|||||||
useChatWithHistoryContext,
|
useChatWithHistoryContext,
|
||||||
} from '../context'
|
} from '../context'
|
||||||
import Operation from './operation'
|
import Operation from './operation'
|
||||||
import ActionButton from '@/app/components/base/action-button'
|
import ActionButton, { ActionButtonState } from '@/app/components/base/action-button'
|
||||||
import AppIcon from '@/app/components/base/app-icon'
|
import AppIcon from '@/app/components/base/app-icon'
|
||||||
import Tooltip from '@/app/components/base/tooltip'
|
import Tooltip from '@/app/components/base/tooltip'
|
||||||
import ViewFormDropdown from '@/app/components/base/chat/chat-with-history/inputs-form/view-form-dropdown'
|
import ViewFormDropdown from '@/app/components/base/chat/chat-with-history/inputs-form/view-form-dropdown'
|
||||||
@ -106,9 +106,16 @@ const Header = () => {
|
|||||||
<div className='h-[14px] w-px bg-divider-regular'></div>
|
<div className='h-[14px] w-px bg-divider-regular'></div>
|
||||||
</div>
|
</div>
|
||||||
{isSidebarCollapsed && (
|
{isSidebarCollapsed && (
|
||||||
<ActionButton size='l' onClick={handleNewConversation}>
|
<Tooltip
|
||||||
|
disabled={!!currentConversationId}
|
||||||
|
popupContent={t('share.chat.newChatTip')}
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<ActionButton size='l' state={!currentConversationId ? ActionButtonState.Disabled : ActionButtonState.Default} disabled={!currentConversationId} onClick={handleNewConversation}>
|
||||||
<RiEditBoxLine className='w-[18px] h-[18px]' />
|
<RiEditBoxLine className='w-[18px] h-[18px]' />
|
||||||
</ActionButton>
|
</ActionButton>
|
||||||
|
</div>
|
||||||
|
</Tooltip>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className='flex items-center gap-1'>
|
<div className='flex items-center gap-1'>
|
||||||
|
@ -82,7 +82,7 @@ const ChatWithHistory: FC<ChatWithHistoryProps> = ({
|
|||||||
{isMobile && (
|
{isMobile && (
|
||||||
<HeaderInMobile />
|
<HeaderInMobile />
|
||||||
)}
|
)}
|
||||||
<div className={cn('relative grow p-2')}>
|
<div className={cn('relative grow p-2', isMobile && 'h-[calc(100%_-_56px)] p-0')}>
|
||||||
{isSidebarCollapsed && (
|
{isSidebarCollapsed && (
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
@ -95,7 +95,7 @@ const ChatWithHistory: FC<ChatWithHistoryProps> = ({
|
|||||||
<Sidebar isPanel />
|
<Sidebar isPanel />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div className='h-full flex flex-col bg-chatbot-bg rounded-2xl border-[0,5px] border-components-panel-border-subtle overflow-hidden'>
|
<div className={cn('h-full flex flex-col bg-chatbot-bg border-[0,5px] border-components-panel-border-subtle overflow-hidden', isMobile ? 'rounded-t-2xl' : 'rounded-2xl')}>
|
||||||
{!isMobile && <Header />}
|
{!isMobile && <Header />}
|
||||||
{appChatListDataLoading && (
|
{appChatListDataLoading && (
|
||||||
<Loading type='app' />
|
<Loading type='app' />
|
||||||
|
@ -110,7 +110,7 @@ const Answer: FC<AnswerProps> = ({
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className='chat-answer-container group grow w-0 ml-4' ref={containerRef}>
|
<div className='chat-answer-container group grow w-0 ml-4 pb-4' ref={containerRef}>
|
||||||
<div className={cn('group relative pr-10', chatAnswerContainerInner)}>
|
<div className={cn('group relative pr-10', chatAnswerContainerInner)}>
|
||||||
<div
|
<div
|
||||||
ref={contentRef}
|
ref={contentRef}
|
||||||
|
@ -72,6 +72,7 @@ export type ChatProps = {
|
|||||||
noSpacing?: boolean
|
noSpacing?: boolean
|
||||||
inputDisabled?: boolean
|
inputDisabled?: boolean
|
||||||
isMobile?: boolean
|
isMobile?: boolean
|
||||||
|
sidebarCollapseState?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
const Chat: FC<ChatProps> = ({
|
const Chat: FC<ChatProps> = ({
|
||||||
@ -110,6 +111,7 @@ const Chat: FC<ChatProps> = ({
|
|||||||
noSpacing,
|
noSpacing,
|
||||||
inputDisabled,
|
inputDisabled,
|
||||||
isMobile,
|
isMobile,
|
||||||
|
sidebarCollapseState,
|
||||||
}) => {
|
}) => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const { currentLogItem, setCurrentLogItem, showPromptLogModal, setShowPromptLogModal, showAgentLogModal, setShowAgentLogModal } = useAppStore(useShallow(state => ({
|
const { currentLogItem, setCurrentLogItem, showPromptLogModal, setShowPromptLogModal, showAgentLogModal, setShowAgentLogModal } = useAppStore(useShallow(state => ({
|
||||||
@ -193,6 +195,11 @@ const Chat: FC<ChatProps> = ({
|
|||||||
}
|
}
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!sidebarCollapseState)
|
||||||
|
setTimeout(() => handleWindowResize(), 200)
|
||||||
|
}, [sidebarCollapseState])
|
||||||
|
|
||||||
const hasTryToAsk = config?.suggested_questions_after_answer?.enabled && !!suggestedQuestions?.length && onSend
|
const hasTryToAsk = config?.suggested_questions_after_answer?.enabled && !!suggestedQuestions?.length && onSend
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -255,7 +262,7 @@ const Chat: FC<ChatProps> = ({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
className={`absolute bottom-0 bg-chat-input-mask ${(hasTryToAsk || !noChatInput || !noStopResponding) && chatFooterClassName}`}
|
className={`absolute bottom-0 bg-chat-input-mask flex justify-center ${(hasTryToAsk || !noChatInput || !noStopResponding) && chatFooterClassName}`}
|
||||||
ref={chatFooterRef}
|
ref={chatFooterRef}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
|
@ -204,7 +204,7 @@ const ChatWrapper = () => {
|
|||||||
config={appConfig}
|
config={appConfig}
|
||||||
chatList={messageList}
|
chatList={messageList}
|
||||||
isResponding={isResponding}
|
isResponding={isResponding}
|
||||||
chatContainerInnerClassName={cn('mx-auto w-full max-w-full tablet:px-4', isMobile && 'px-4')}
|
chatContainerInnerClassName={cn('mx-auto w-full max-w-full pt-4 tablet:px-4', isMobile && 'px-4')}
|
||||||
chatFooterClassName={cn('pb-4', !isMobile && 'rounded-b-2xl')}
|
chatFooterClassName={cn('pb-4', !isMobile && 'rounded-b-2xl')}
|
||||||
chatFooterInnerClassName={cn('mx-auto w-full max-w-full tablet:px-4', isMobile && 'px-2')}
|
chatFooterInnerClassName={cn('mx-auto w-full max-w-full tablet:px-4', isMobile && 'px-2')}
|
||||||
onSend={doSend}
|
onSend={doSend}
|
||||||
|
@ -6,6 +6,7 @@ const translation = {
|
|||||||
},
|
},
|
||||||
chat: {
|
chat: {
|
||||||
newChat: 'Start New chat',
|
newChat: 'Start New chat',
|
||||||
|
newChatTip: 'Already in a new chat',
|
||||||
chatSettingsTitle: 'New chat setup',
|
chatSettingsTitle: 'New chat setup',
|
||||||
chatFormTip: 'Chat settings cannot be modified after the chat has started.',
|
chatFormTip: 'Chat settings cannot be modified after the chat has started.',
|
||||||
pinnedTitle: 'Pinned',
|
pinnedTitle: 'Pinned',
|
||||||
|
@ -6,6 +6,7 @@ const translation = {
|
|||||||
},
|
},
|
||||||
chat: {
|
chat: {
|
||||||
newChat: '开启新对话',
|
newChat: '开启新对话',
|
||||||
|
newChatTip: '已在新对话中',
|
||||||
chatSettingsTitle: '新对话设置',
|
chatSettingsTitle: '新对话设置',
|
||||||
chatFormTip: '对话开始后,对话设置将无法修改。',
|
chatFormTip: '对话开始后,对话设置将无法修改。',
|
||||||
pinnedTitle: '已置顶',
|
pinnedTitle: '已置顶',
|
||||||
|
Loading…
Reference in New Issue
Block a user