Procházet zdrojové kódy

feat: support copy run text result in debug panel in workflow (#4300)

Joel před 11 měsíci
rodič
revize
4af00e4a45

+ 20 - 14
web/app/components/app/text-generate/item/index.tsx

@@ -267,6 +267,8 @@ const GenerationItem: FC<IGenerationItemProps> = ({
     </>
   )
 
+  const [currentTab, setCurrentTab] = useState<string>('DETAIL')
+
   return (
     <div ref={ref} className={cn(className, isTop ? `rounded-xl border ${!isError ? 'border-gray-200 bg-white' : 'border-[#FECDCA] bg-[#FEF3F2]'} ` : 'rounded-br-xl !mt-0')}
       style={isTop
@@ -296,7 +298,7 @@ const GenerationItem: FC<IGenerationItemProps> = ({
                   <WorkflowProcessItem grayBg hideInfo data={workflowProcessData} expand={workflowProcessData.expand} hideProcessDetail={hideProcessDetail} />
                 )}
                 {workflowProcessData && !isError && (
-                  <ResultTab data={workflowProcessData} content={content} />
+                  <ResultTab data={workflowProcessData} content={content} currentTab={currentTab} onCurrentTabChange={setCurrentTab} />
                 )}
                 {isError && (
                   <div className='text-gray-400 text-sm'>{t('share.generation.batchFailed.outputPlaceholder')}</div>
@@ -320,19 +322,23 @@ const GenerationItem: FC<IGenerationItemProps> = ({
                     </SimpleBtn>
                   )
                 }
-                <SimpleBtn
-                  isDisabled={isError || !messageId}
-                  className={cn(isMobile && '!px-1.5', 'space-x-1')}
-                  onClick={() => {
-                    if (typeof content === 'string')
-                      copy(content)
-                    else
-                      copy(JSON.stringify(content))
-                    Toast.notify({ type: 'success', message: t('common.actionMsg.copySuccessfully') })
-                  }}>
-                  <Clipboard className='w-3.5 h-3.5' />
-                  {!isMobile && <div>{t('common.operation.copy')}</div>}
-                </SimpleBtn>
+                {currentTab === 'RESULT' && (
+                  <SimpleBtn
+                    isDisabled={isError || !messageId}
+                    className={cn(isMobile && '!px-1.5', 'space-x-1')}
+                    onClick={() => {
+                      const content = workflowProcessData?.resultText
+                      if (typeof content === 'string')
+                        copy(content)
+                      else
+                        copy(JSON.stringify(content))
+                      Toast.notify({ type: 'success', message: t('common.actionMsg.copySuccessfully') })
+                    }}>
+                    <Clipboard className='w-3.5 h-3.5' />
+                    {!isMobile && <div>{t('common.operation.copy')}</div>}
+                  </SimpleBtn>
+                )}
+
                 {isInWebApp && (
                   <>
                     {!isWorkflow && (

+ 5 - 4
web/app/components/app/text-generate/item/result-tab.tsx

@@ -1,8 +1,6 @@
 import {
   memo,
   useEffect,
-  // useRef,
-  useState,
 } from 'react'
 import cn from 'classnames'
 import { useTranslation } from 'react-i18next'
@@ -16,15 +14,18 @@ import type { WorkflowProcess } from '@/app/components/base/chat/types'
 const ResultTab = ({
   data,
   content,
+  currentTab,
+  onCurrentTabChange,
 }: {
   data?: WorkflowProcess
   content: any
+  currentTab: string
+  onCurrentTabChange: (tab: string) => void
 }) => {
   const { t } = useTranslation()
-  const [currentTab, setCurrentTab] = useState<string>('DETAIL')
 
   const switchTab = async (tab: string) => {
-    setCurrentTab(tab)
+    onCurrentTabChange(tab)
   }
   useEffect(() => {
     if (data?.resultText)

+ 27 - 6
web/app/components/workflow/panel/workflow-preview.tsx

@@ -6,6 +6,7 @@ import {
 } from 'react'
 import cn from 'classnames'
 import { useTranslation } from 'react-i18next'
+import copy from 'copy-to-clipboard'
 import ResultText from '../run/result-text'
 import ResultPanel from '../run/result-panel'
 import TracingPanel from '../run/tracing-panel'
@@ -16,9 +17,12 @@ import { useStore } from '../store'
 import {
   WorkflowRunningStatus,
 } from '../types'
+import { SimpleBtn } from '../../app/text-generate/item'
+import Toast from '../../base/toast'
 import InputsPanel from './inputs-panel'
 import Loading from '@/app/components/base/loading'
 import { XClose } from '@/app/components/base/icons/src/vender/line/general'
+import { Clipboard } from '@/app/components/base/icons/src/vender/line/files'
 
 const WorkflowPreview = () => {
   const { t } = useTranslation()
@@ -108,12 +112,28 @@ const WorkflowPreview = () => {
             <InputsPanel onRun={() => switchTab('RESULT')} />
           )}
           {currentTab === 'RESULT' && (
-            <ResultText
-              isRunning={workflowRunningData?.result?.status === WorkflowRunningStatus.Running || !workflowRunningData?.result}
-              outputs={workflowRunningData?.resultText}
-              error={workflowRunningData?.result?.error}
-              onClick={() => switchTab('DETAIL')}
-            />
+            <>
+              <ResultText
+                isRunning={workflowRunningData?.result?.status === WorkflowRunningStatus.Running || !workflowRunningData?.result}
+                outputs={workflowRunningData?.resultText}
+                error={workflowRunningData?.result?.error}
+                onClick={() => switchTab('DETAIL')}
+              />
+              <SimpleBtn
+                isDisabled={workflowRunningData?.result.status !== WorkflowRunningStatus.Succeeded}
+                className={cn('ml-4 mb-4 inline-flex space-x-1')}
+                onClick={() => {
+                  const content = workflowRunningData?.resultText
+                  if (typeof content === 'string')
+                    copy(content)
+                  else
+                    copy(JSON.stringify(content))
+                  Toast.notify({ type: 'success', message: t('common.actionMsg.copySuccessfully') })
+                }}>
+                <Clipboard className='w-3.5 h-3.5' />
+                <div>{t('common.operation.copy')}</div>
+              </SimpleBtn>
+            </>
           )}
           {currentTab === 'DETAIL' && (
             <ResultPanel
@@ -143,6 +163,7 @@ const WorkflowPreview = () => {
               <Loading />
             </div>
           )}
+
         </div>
       </div>
     </div>