wwf
3 天以前 a430284aa21e3ae1f0d5654e55b2ad2852519cc2
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'>
          <CopyBtn
            value={content}
            className='hidden group-hover:block'
          />
        )}
        {!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 && (
              <>
                <Log logItem={item} />
                <div className='mx-1 w-[1px] h-[14px] bg-gray-200' />
              </>
            )}
            {(config?.text_to_speech?.enabled) && (
              <NewAudioButton
              <>
                <AudioBtn
                id={id}
                value={content}
                  noCache={false}
                voice={config?.text_to_speech?.voice}
                  className='hidden group-hover:block'
              />
            )}
            <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>
        )}
        {!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 && (
              <>
                <ActionButton onClick={() => handleFeedback('like')}>
                  <RiThumbUpLine className='h-4 w-4' />
                </ActionButton>
                <ActionButton onClick={() => handleFeedback('dislike')}>
                  <RiThumbDownLine className='h-4 w-4' />
                </ActionButton>
              </>
            )}
          </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>
        {(!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)}
          />
            )}
            {localFeedback?.rating === 'dislike' && (
              <ActionButton state={ActionButtonState.Destructive} onClick={() => handleFeedback(null)}>
                <RiThumbDownLine className='h-4 w-4' />
              </ActionButton>
            )}
        {
          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}