From 77950e48c76f4a3b29d01831d43039caba29888a Mon Sep 17 00:00:00 2001
From: wwf <1971391498@qq.com>
Date: 星期二, 18 十一月 2025 14:12:42 +0800
Subject: [PATCH] 修改
---
app/components/workflow/panel/workflow-preview.tsx | 322 +++++++++++++++++++++++++++++------------------------
1 files changed, 177 insertions(+), 145 deletions(-)
diff --git a/app/components/workflow/panel/workflow-preview.tsx b/app/components/workflow/panel/workflow-preview.tsx
index 34b0ec6..210a95f 100644
--- a/app/components/workflow/panel/workflow-preview.tsx
+++ b/app/components/workflow/panel/workflow-preview.tsx
@@ -2,6 +2,7 @@
memo,
useCallback,
useEffect,
+ // useRef,
useState,
} from 'react'
import {
@@ -10,6 +11,7 @@
} from '@remixicon/react'
import { useTranslation } from 'react-i18next'
import copy from 'copy-to-clipboard'
+import { useBoolean } from 'ahooks'
import ResultText from '../run/result-text'
import ResultPanel from '../run/result-panel'
import TracingPanel from '../run/tracing-panel'
@@ -20,11 +22,14 @@
import {
WorkflowRunningStatus,
} from '../types'
+import { SimpleBtn } from '../../app/text-generate/item'
import Toast from '../../base/toast'
+import IterationResultPanel from '../run/iteration-result-panel'
+import RetryResultPanel from '../run/retry-result-panel'
import InputsPanel from './inputs-panel'
import cn from '@/utils/classnames'
import Loading from '@/app/components/base/loading'
-import Button from '@/app/components/base/button'
+import type { IterationDurationMap, NodeTracing } from '@/types/workflow'
const WorkflowPreview = () => {
const { t } = useTranslation()
@@ -48,163 +53,190 @@
switchTab('DETAIL')
}, [workflowRunningData])
- const [panelWidth, setPanelWidth] = useState(420)
- const [isResizing, setIsResizing] = useState(false)
+ const [iterationRunResult, setIterationRunResult] = useState<NodeTracing[][]>([])
+ const [retryRunResult, setRetryRunResult] = useState<NodeTracing[]>([])
+ const [iterDurationMap, setIterDurationMap] = useState<IterationDurationMap>({})
+ const [isShowIterationDetail, {
+ setTrue: doShowIterationDetail,
+ setFalse: doHideIterationDetail,
+ }] = useBoolean(false)
+ const [isShowRetryDetail, {
+ setTrue: doShowRetryDetail,
+ setFalse: doHideRetryDetail,
+ }] = useBoolean(false)
- const startResizing = useCallback((e: React.MouseEvent) => {
- e.preventDefault()
- setIsResizing(true)
- }, [])
+ const handleShowIterationDetail = useCallback((detail: NodeTracing[][], iterationDurationMap: IterationDurationMap) => {
+ setIterDurationMap(iterationDurationMap)
+ setIterationRunResult(detail)
+ doShowIterationDetail()
+ }, [doShowIterationDetail])
- const stopResizing = useCallback(() => {
- setIsResizing(false)
- }, [])
+ const handleRetryDetail = useCallback((detail: NodeTracing[]) => {
+ setRetryRunResult(detail)
+ doShowRetryDetail()
+ }, [doShowRetryDetail])
- const resize = useCallback((e: MouseEvent) => {
- if (isResizing) {
- const newWidth = window.innerWidth - e.clientX
- if (newWidth > 420 && newWidth < 1024)
- setPanelWidth(newWidth)
- }
- }, [isResizing])
-
- useEffect(() => {
- window.addEventListener('mousemove', resize)
- window.addEventListener('mouseup', stopResizing)
- return () => {
- window.removeEventListener('mousemove', resize)
- window.removeEventListener('mouseup', stopResizing)
- }
- }, [resize, stopResizing])
+ if (isShowIterationDetail) {
+ return (
+ <div className={`
+ flex flex-col w-[420px] h-full rounded-l-2xl border-[0.5px] border-gray-200 shadow-xl bg-white
+ `}>
+ <IterationResultPanel
+ list={iterationRunResult}
+ onHide={doHideIterationDetail}
+ onBack={doHideIterationDetail}
+ iterDurationMap={iterDurationMap}
+ />
+ </div>
+ )
+ }
return (
<div className={`
- relative flex h-full flex-col rounded-l-2xl border-[0.5px] border-components-panel-border bg-components-panel-bg shadow-xl
- `}
- style={{ width: `${panelWidth}px` }}
- >
- <div
- className="absolute bottom-0 left-[3px] top-1/2 z-50 h-6 w-[3px] cursor-col-resize rounded bg-gray-300"
- onMouseDown={startResizing}
- />
- <div className='flex items-center justify-between p-4 pb-1 text-base font-semibold text-text-primary'>
+ flex flex-col w-[420px] h-full rounded-l-2xl border-[0.5px] border-gray-200 shadow-xl bg-white
+ `}>
+ <div className='flex items-center justify-between p-4 pb-1 text-base font-semibold text-gray-900'>
{`Test Run${!workflowRunningData?.result.sequence_number ? '' : `#${workflowRunningData?.result.sequence_number}`}`}
- <div className='cursor-pointer p-1' onClick={() => handleCancelDebugAndPreviewPanel()}>
- <RiCloseLine className='h-4 w-4 text-text-tertiary' />
+ <div className='p-1 cursor-pointer' onClick={() => handleCancelDebugAndPreviewPanel()}>
+ <RiCloseLine className='w-4 h-4 text-gray-500' />
</div>
</div>
- <div className='relative flex grow flex-col'>
- <div className='flex shrink-0 items-center border-b-[0.5px] border-divider-subtle px-4'>
- {showInputsPanel && (
- <div
- className={cn(
- 'mr-6 cursor-pointer border-b-2 border-transparent py-3 text-[13px] font-semibold leading-[18px] text-text-tertiary',
- currentTab === 'INPUT' && '!border-[rgb(21,94,239)] text-text-secondary',
- )}
- onClick={() => switchTab('INPUT')}
- >{t('runLog.input')}</div>
- )}
- <div
- className={cn(
- 'mr-6 cursor-pointer border-b-2 border-transparent py-3 text-[13px] font-semibold leading-[18px] text-text-tertiary',
- currentTab === 'RESULT' && '!border-[rgb(21,94,239)] text-text-secondary',
- !workflowRunningData && '!cursor-not-allowed opacity-30',
- )}
- onClick={() => {
- if (!workflowRunningData)
- return
- switchTab('RESULT')
- }}
- >{t('runLog.result')}</div>
- <div
- className={cn(
- 'mr-6 cursor-pointer border-b-2 border-transparent py-3 text-[13px] font-semibold leading-[18px] text-text-tertiary',
- currentTab === 'DETAIL' && '!border-[rgb(21,94,239)] text-text-secondary',
- !workflowRunningData && '!cursor-not-allowed opacity-30',
- )}
- onClick={() => {
- if (!workflowRunningData)
- return
- switchTab('DETAIL')
- }}
- >{t('runLog.detail')}</div>
- <div
- className={cn(
- 'mr-6 cursor-pointer border-b-2 border-transparent py-3 text-[13px] font-semibold leading-[18px] text-text-tertiary',
- currentTab === 'TRACING' && '!border-[rgb(21,94,239)] text-text-secondary',
- !workflowRunningData && '!cursor-not-allowed opacity-30',
- )}
- onClick={() => {
- if (!workflowRunningData)
- return
- switchTab('TRACING')
- }}
- >{t('runLog.tracing')}</div>
- </div>
- <div className={cn(
- 'h-0 grow overflow-y-auto rounded-b-2xl bg-components-panel-bg',
- (currentTab === 'RESULT' || currentTab === 'TRACING') && '!bg-background-section-burn',
- )}>
- {currentTab === 'INPUT' && showInputsPanel && (
- <InputsPanel onRun={() => switchTab('RESULT')} />
- )}
- {currentTab === 'RESULT' && (
+ <div className='grow relative flex flex-col'>
+ {isShowIterationDetail
+ ? (
+ <IterationResultPanel
+ list={iterationRunResult}
+ onHide={doHideIterationDetail}
+ onBack={doHideIterationDetail}
+ iterDurationMap={iterDurationMap}
+ />
+ )
+ : (
<>
- <ResultText
- isRunning={workflowRunningData?.result?.status === WorkflowRunningStatus.Running || !workflowRunningData?.result}
- outputs={workflowRunningData?.resultText}
- allFiles={workflowRunningData?.result?.files}
- error={workflowRunningData?.result?.error}
- onClick={() => switchTab('DETAIL')}
- />
- {(workflowRunningData?.result.status === WorkflowRunningStatus.Succeeded && workflowRunningData?.resultText && typeof workflowRunningData?.resultText === 'string') && (
- <Button
- className={cn('mb-4 ml-4 space-x-1')}
+ <div className='shrink-0 flex items-center px-4 border-b-[0.5px] border-[rgba(0,0,0,0.05)]'>
+ {showInputsPanel && (
+ <div
+ className={cn(
+ 'mr-6 py-3 border-b-2 border-transparent text-[13px] font-semibold leading-[18px] text-gray-400 cursor-pointer',
+ currentTab === 'INPUT' && '!border-[rgb(21,94,239)] text-gray-700',
+ )}
+ onClick={() => switchTab('INPUT')}
+ >{t('runLog.input')}</div>
+ )}
+ <div
+ className={cn(
+ 'mr-6 py-3 border-b-2 border-transparent text-[13px] font-semibold leading-[18px] text-gray-400 cursor-pointer',
+ currentTab === 'RESULT' && '!border-[rgb(21,94,239)] text-gray-700',
+ !workflowRunningData && 'opacity-30 !cursor-not-allowed',
+ )}
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') })
- }}>
- <RiClipboardLine className='h-3.5 w-3.5' />
- <div>{t('common.operation.copy')}</div>
- </Button>
- )}
+ if (!workflowRunningData)
+ return
+ switchTab('RESULT')
+ }}
+ >{t('runLog.result')}</div>
+ <div
+ className={cn(
+ 'mr-6 py-3 border-b-2 border-transparent text-[13px] font-semibold leading-[18px] text-gray-400 cursor-pointer',
+ currentTab === 'DETAIL' && '!border-[rgb(21,94,239)] text-gray-700',
+ !workflowRunningData && 'opacity-30 !cursor-not-allowed',
+ )}
+ onClick={() => {
+ if (!workflowRunningData)
+ return
+ switchTab('DETAIL')
+ }}
+ >{t('runLog.detail')}</div>
+ <div
+ className={cn(
+ 'mr-6 py-3 border-b-2 border-transparent text-[13px] font-semibold leading-[18px] text-gray-400 cursor-pointer',
+ currentTab === 'TRACING' && '!border-[rgb(21,94,239)] text-gray-700',
+ !workflowRunningData && 'opacity-30 !cursor-not-allowed',
+ )}
+ onClick={() => {
+ if (!workflowRunningData)
+ return
+ switchTab('TRACING')
+ }}
+ >{t('runLog.tracing')}</div>
+ </div>
+ <div className={cn(
+ 'grow bg-components-panel-bg h-0 overflow-y-auto rounded-b-2xl',
+ (currentTab === 'RESULT' || currentTab === 'TRACING') && '!bg-background-section-burn',
+ )}>
+ {currentTab === 'INPUT' && showInputsPanel && (
+ <InputsPanel onRun={() => switchTab('RESULT')} />
+ )}
+ {currentTab === 'RESULT' && (
+ <>
+ <ResultText
+ isRunning={workflowRunningData?.result?.status === WorkflowRunningStatus.Running || !workflowRunningData?.result}
+ outputs={workflowRunningData?.resultText}
+ allFiles={workflowRunningData?.result?.files as any}
+ error={workflowRunningData?.result?.error}
+ onClick={() => switchTab('DETAIL')}
+ />
+ {(workflowRunningData?.result.status === WorkflowRunningStatus.Succeeded && workflowRunningData?.resultText && typeof workflowRunningData?.resultText === 'string') && (
+ <SimpleBtn
+ 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') })
+ }}>
+ <RiClipboardLine className='w-3.5 h-3.5' />
+ <div>{t('common.operation.copy')}</div>
+ </SimpleBtn>
+ )}
+ </>
+ )}
+ {currentTab === 'DETAIL' && (
+ <ResultPanel
+ inputs={workflowRunningData?.result?.inputs}
+ outputs={workflowRunningData?.result?.outputs}
+ status={workflowRunningData?.result?.status || ''}
+ error={workflowRunningData?.result?.error}
+ elapsed_time={workflowRunningData?.result?.elapsed_time}
+ total_tokens={workflowRunningData?.result?.total_tokens}
+ created_at={workflowRunningData?.result?.created_at}
+ created_by={(workflowRunningData?.result?.created_by as any)?.name}
+ steps={workflowRunningData?.result?.total_steps}
+ exceptionCounts={workflowRunningData?.result?.exceptions_count}
+ />
+ )}
+ {currentTab === 'DETAIL' && !workflowRunningData?.result && (
+ <div className='flex h-full items-center justify-center bg-components-panel-bg'>
+ <Loading />
+ </div>
+ )}
+ {currentTab === 'TRACING' && !isShowRetryDetail && (
+ <TracingPanel
+ className='bg-background-section-burn'
+ list={workflowRunningData?.tracing || []}
+ onShowIterationDetail={handleShowIterationDetail}
+ onShowRetryDetail={handleRetryDetail}
+ />
+ )}
+ {currentTab === 'TRACING' && !workflowRunningData?.tracing?.length && (
+ <div className='flex h-full items-center justify-center !bg-background-section-burn'>
+ <Loading />
+ </div>
+ )}
+ {
+ currentTab === 'TRACING' && isShowRetryDetail && (
+ <RetryResultPanel
+ list={retryRunResult}
+ onBack={doHideRetryDetail}
+ />
+ )
+ }
+ </div>
</>
)}
- {currentTab === 'DETAIL' && (
- <ResultPanel
- inputs={workflowRunningData?.result?.inputs}
- outputs={workflowRunningData?.result?.outputs}
- status={workflowRunningData?.result?.status || ''}
- error={workflowRunningData?.result?.error}
- elapsed_time={workflowRunningData?.result?.elapsed_time}
- total_tokens={workflowRunningData?.result?.total_tokens}
- created_at={workflowRunningData?.result?.created_at}
- created_by={(workflowRunningData?.result?.created_by as any)?.name}
- steps={workflowRunningData?.result?.total_steps}
- exceptionCounts={workflowRunningData?.result?.exceptions_count}
- />
- )}
- {currentTab === 'DETAIL' && !workflowRunningData?.result && (
- <div className='flex h-full items-center justify-center bg-components-panel-bg'>
- <Loading />
- </div>
- )}
- {currentTab === 'TRACING' && (
- <TracingPanel
- className='bg-background-section-burn'
- list={workflowRunningData?.tracing || []}
- />
- )}
- {currentTab === 'TRACING' && !workflowRunningData?.tracing?.length && (
- <div className='flex h-full items-center justify-center !bg-background-section-burn'>
- <Loading />
- </div>
- )}
- </div>
+
</div>
</div>
)
--
Gitblit v1.8.0