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/answer/operation.tsx | 197 ++++++++++++++++++++++++++++++------------------- 1 files changed, 120 insertions(+), 77 deletions(-) diff --git a/app/components/base/chat/chat/answer/operation.tsx b/app/components/base/chat/chat/answer/operation.tsx index 0fbb7ce..dcd3df6 100644 --- a/app/components/base/chat/chat/answer/operation.tsx +++ b/app/components/base/chat/chat/answer/operation.tsx @@ -5,22 +5,21 @@ useState, } from 'react' import { useTranslation } from 'react-i18next' -import { - RiClipboardLine, - RiResetLeftLine, - RiThumbDownLine, - RiThumbUpLine, -} from '@remixicon/react' import type { ChatItem } from '../../types' import { useChatContext } from '../context' -import copy from 'copy-to-clipboard' -import Toast from '@/app/components/base/toast' -import AnnotationCtrlButton from '@/app/components/base/features/new-feature-panel/annotation-reply/annotation-ctrl-button' -import EditReplyModal from '@/app/components/app/annotation/edit-annotation-modal' -import Log from '@/app/components/base/chat/chat/log' -import ActionButton, { ActionButtonState } from '@/app/components/base/action-button' -import NewAudioButton from '@/app/components/base/new-audio-button' +import RegenerateBtn from '@/app/components/base/regenerate-btn' import cn from '@/utils/classnames' +import CopyBtn from '@/app/components/base/copy-btn' +import { MessageFast } from '@/app/components/base/icons/src/vender/solid/communication' +import AudioBtn from '@/app/components/base/audio-btn' +import AnnotationCtrlBtn from '@/app/components/base/features/new-feature-panel/annotation-reply/annotation-ctrl-btn' +import EditReplyModal from '@/app/components/app/annotation/edit-annotation-modal' +import { + ThumbsDown, + ThumbsUp, +} from '@/app/components/base/icons/src/vender/line/alertsAndFeedback' +import Tooltip from '@/app/components/base/tooltip' +import Log from '@/app/components/base/chat/chat/log' type OperationProps = { item: ChatItem @@ -61,6 +60,7 @@ adminFeedback, agent_thoughts, } = item + const hasAnnotation = !!annotation?.id const [localFeedback, setLocalFeedback] = useState(config?.supportAnnotation ? adminFeedback : feedback) const content = useMemo(() => { @@ -81,13 +81,13 @@ const operationWidth = useMemo(() => { let width = 0 if (!isOpeningStatement) - width += 26 + width += 28 if (!isOpeningStatement && showPromptLog) - width += 28 + 8 + width += 102 + 8 if (!isOpeningStatement && config?.text_to_speech?.enabled) - width += 26 + width += 33 if (!isOpeningStatement && config?.supportAnnotation && config?.annotation_reply?.enabled) - width += 26 + width += 56 + 8 if (config?.supportFeedback && !localFeedback?.rating && onFeedback && !isOpeningStatement) width += 60 + 8 if (config?.supportFeedback && localFeedback?.rating && onFeedback && !isOpeningStatement) @@ -102,78 +102,121 @@ <div className={cn( 'absolute flex justify-end gap-1', - hasWorkflowProcess && '-bottom-4 right-2', - !positionRight && '-bottom-4 right-2', + hasWorkflowProcess && '-top-3.5 -right-3.5', + !positionRight && '-top-3.5 -right-3.5', !hasWorkflowProcess && positionRight && '!top-[9px]', )} style={(!hasWorkflowProcess && positionRight) ? { left: contentWidth + 8 } : {}} > - {showPromptLog && !isOpeningStatement && ( - <div className='hidden group-hover:block'> - <Log logItem={item} /> - </div> - )} {!isOpeningStatement && ( - <div className='ml-1 hidden items-center gap-0.5 rounded-[10px] border-[0.5px] border-components-actionbar-border bg-components-actionbar-bg p-0.5 shadow-md backdrop-blur-sm group-hover:flex'> - {(config?.text_to_speech?.enabled) && ( - <NewAudioButton - id={id} - value={content} - voice={config?.text_to_speech?.voice} - /> - )} - <ActionButton onClick={() => { - copy(content) - Toast.notify({ type: 'success', message: t('common.actionMsg.copySuccessfully') }) - }}> - <RiClipboardLine className='h-4 w-4' /> - </ActionButton> - {!noChatInput && ( - <ActionButton onClick={() => onRegenerate?.(item)}> - <RiResetLeftLine className='h-4 w-4' /> - </ActionButton> - )} - {(config?.supportAnnotation && config.annotation_reply?.enabled) && ( - <AnnotationCtrlButton - appId={config?.appId || ''} - messageId={id} - cached={!!annotation?.id} - query={question} - answer={content} - onAdded={(id, authorName) => onAnnotationAdded?.(id, authorName, question, content, index)} - onEdit={() => setIsShowReplyModal(true)} - /> - )} - </div> + <CopyBtn + value={content} + className='hidden group-hover:block' + /> )} - {!isOpeningStatement && config?.supportFeedback && !localFeedback?.rating && onFeedback && ( - <div className='ml-1 hidden items-center gap-0.5 rounded-[10px] border-[0.5px] border-components-actionbar-border bg-components-actionbar-bg p-0.5 shadow-md backdrop-blur-sm group-hover:flex'> - {!localFeedback?.rating && ( + + {!isOpeningStatement && (showPromptLog || config?.text_to_speech?.enabled) && ( + <div className='hidden group-hover:flex items-center w-max h-[28px] p-0.5 rounded-lg bg-white border-[0.5px] border-gray-100 shadow-md shrink-0'> + {showPromptLog && ( <> - <ActionButton onClick={() => handleFeedback('like')}> - <RiThumbUpLine className='h-4 w-4' /> - </ActionButton> - <ActionButton onClick={() => handleFeedback('dislike')}> - <RiThumbDownLine className='h-4 w-4' /> - </ActionButton> + <Log logItem={item} /> + <div className='mx-1 w-[1px] h-[14px] bg-gray-200' /> + </> + )} + + {(config?.text_to_speech?.enabled) && ( + <> + <AudioBtn + id={id} + value={content} + noCache={false} + voice={config?.text_to_speech?.voice} + className='hidden group-hover:block' + /> </> )} </div> )} - {!isOpeningStatement && config?.supportFeedback && localFeedback?.rating && onFeedback && ( - <div className='ml-1 flex items-center gap-0.5 rounded-[10px] border-[0.5px] border-components-actionbar-border bg-components-actionbar-bg p-0.5 shadow-md backdrop-blur-sm'> - {localFeedback?.rating === 'like' && ( - <ActionButton state={ActionButtonState.Active} onClick={() => handleFeedback(null)}> - <RiThumbUpLine className='h-4 w-4' /> - </ActionButton> - )} - {localFeedback?.rating === 'dislike' && ( - <ActionButton state={ActionButtonState.Destructive} onClick={() => handleFeedback(null)}> - <RiThumbDownLine className='h-4 w-4' /> - </ActionButton> - )} - </div> + + {(!isOpeningStatement && config?.supportAnnotation && config.annotation_reply?.enabled) && ( + <AnnotationCtrlBtn + appId={config?.appId || ''} + messageId={id} + annotationId={annotation?.id || ''} + className='hidden group-hover:block ml-1 shrink-0' + cached={hasAnnotation} + query={question} + answer={content} + onAdded={(id, authorName) => onAnnotationAdded?.(id, authorName, question, content, index)} + onEdit={() => setIsShowReplyModal(true)} + onRemoved={() => onAnnotationRemoved?.(index)} + /> )} + { + annotation?.id && ( + <div + className='relative box-border flex items-center justify-center h-7 w-7 p-0.5 rounded-lg bg-white cursor-pointer text-[#444CE7] shadow-md group-hover:hidden' + > + <div className='p-1 rounded-lg bg-[#EEF4FF] '> + <MessageFast className='w-4 h-4' /> + </div> + </div> + ) + } + { + !isOpeningStatement && !noChatInput && <RegenerateBtn className='hidden group-hover:block mr-1' onClick={() => onRegenerate?.(item)} /> + } + { + config?.supportFeedback && !localFeedback?.rating && onFeedback && !isOpeningStatement && ( + <div className='hidden group-hover:flex shrink-0 items-center px-0.5 bg-white border-[0.5px] border-gray-100 shadow-md text-gray-500 rounded-lg'> + <Tooltip popupContent={t('appDebug.operation.agree')}> + <div + className='flex items-center justify-center mr-0.5 w-6 h-6 rounded-md hover:bg-black/5 hover:text-gray-800 cursor-pointer' + onClick={() => handleFeedback('like')} + > + <ThumbsUp className='w-4 h-4' /> + </div> + </Tooltip> + <Tooltip + popupContent={t('appDebug.operation.disagree')} + > + <div + className='flex items-center justify-center w-6 h-6 rounded-md hover:bg-black/5 hover:text-gray-800 cursor-pointer' + onClick={() => handleFeedback('dislike')} + > + <ThumbsDown className='w-4 h-4' /> + </div> + </Tooltip> + </div> + ) + } + { + config?.supportFeedback && localFeedback?.rating && onFeedback && !isOpeningStatement && ( + <Tooltip + popupContent={localFeedback.rating === 'like' ? t('appDebug.operation.cancelAgree') : t('appDebug.operation.cancelDisagree')} + > + <div + className={` + flex items-center justify-center w-7 h-7 rounded-[10px] border-[2px] border-white cursor-pointer + ${localFeedback.rating === 'like' && 'bg-blue-50 text-blue-600'} + ${localFeedback.rating === 'dislike' && 'bg-red-100 text-red-600'} + `} + onClick={() => handleFeedback(null)} + > + { + localFeedback.rating === 'like' && ( + <ThumbsUp className='w-4 h-4' /> + ) + } + { + localFeedback.rating === 'dislike' && ( + <ThumbsDown className='w-4 h-4' /> + ) + } + </div> + </Tooltip> + ) + } </div> <EditReplyModal isShow={isShowReplyModal} -- Gitblit v1.8.0