| @@ -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 && ( | |||
| @@ -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) | |||
| @@ -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> | |||