From 2391e582f2639aea28d4c8d8d2948532aa36799b Mon Sep 17 00:00:00 2001 From: Joel Date: Mon, 18 Aug 2025 16:57:41 +0800 Subject: [PATCH] feat: debug show big data --- .../json-schema-config-modal/code-editor.tsx | 3 ++ .../schema-editor.tsx | 4 ++ .../variable-inspect/large-data-alert.tsx | 30 ++++++++++++++ .../workflow/variable-inspect/right.tsx | 39 ++++++++++++++++--- .../variable-inspect/value-content.tsx | 4 +- web/i18n/en-US/workflow.ts | 1 + web/i18n/zh-Hans/workflow.ts | 1 + web/types/workflow.ts | 7 ++++ 8 files changed, 83 insertions(+), 6 deletions(-) create mode 100644 web/app/components/workflow/variable-inspect/large-data-alert.tsx diff --git a/web/app/components/workflow/nodes/llm/components/json-schema-config-modal/code-editor.tsx b/web/app/components/workflow/nodes/llm/components/json-schema-config-modal/code-editor.tsx index 920757c6a6..7bb5d0c73c 100644 --- a/web/app/components/workflow/nodes/llm/components/json-schema-config-modal/code-editor.tsx +++ b/web/app/components/workflow/nodes/llm/components/json-schema-config-modal/code-editor.tsx @@ -15,6 +15,7 @@ type CodeEditorProps = { editorWrapperClassName?: string readOnly?: boolean hideTopMenu?: boolean + topContent?: React.ReactNode } & React.HTMLAttributes const CodeEditor: FC = ({ @@ -24,6 +25,7 @@ const CodeEditor: FC = ({ editorWrapperClassName, readOnly = false, hideTopMenu = false, + topContent, className, }) => { const { t } = useTranslation() @@ -127,6 +129,7 @@ const CodeEditor: FC = ({ )} + {topContent}
= ({ @@ -16,6 +18,7 @@ const SchemaEditor: FC = ({ hideTopMenu, className, readonly = false, + isTruncated, }) => { return ( = ({ value={schema} onUpdate={onUpdate} hideTopMenu={hideTopMenu} + topContent={isTruncated && } /> ) } diff --git a/web/app/components/workflow/variable-inspect/large-data-alert.tsx b/web/app/components/workflow/variable-inspect/large-data-alert.tsx new file mode 100644 index 0000000000..caea85e841 --- /dev/null +++ b/web/app/components/workflow/variable-inspect/large-data-alert.tsx @@ -0,0 +1,30 @@ +'use client' +import { RiInformation2Fill } from '@remixicon/react' +import type { FC } from 'react' +import React from 'react' +import cn from '@/utils/classnames' + +type Props = { + downloadUrl?: string + className?: string +} + +const LargeDataAlert: FC = ({ + downloadUrl, + className, +}) => { + const isShowDownload = !!downloadUrl + const text = isShowDownload ? 'Large data - partial preview only' : 'Large data, read-only preview. Export to view all.' + return ( +
+
+ +
{text}
+
+ {isShowDownload && ( +
Export
+ )} +
+ ) +} +export default React.memo(LargeDataAlert) diff --git a/web/app/components/workflow/variable-inspect/right.tsx b/web/app/components/workflow/variable-inspect/right.tsx index 2b87c46b55..ae9838251b 100644 --- a/web/app/components/workflow/variable-inspect/right.tsx +++ b/web/app/components/workflow/variable-inspect/right.tsx @@ -2,6 +2,7 @@ import { useTranslation } from 'react-i18next' import { RiArrowGoBackLine, RiCloseLine, + RiFileDownloadFill, RiMenuLine, RiSparklingFill, } from '@remixicon/react' @@ -52,6 +53,13 @@ const Right = ({ const bottomPanelWidth = useStore(s => s.bottomPanelWidth) const setShowVariableInspectPanel = useStore(s => s.setShowVariableInspectPanel) const setCurrentFocusNodeId = useStore(s => s.setCurrentFocusNodeId) + const isTruncated = currentNodeVar?.var.is_truncated + const fullContent = currentNodeVar?.var.full_content + // const isTruncated = true + // const fullContent = { + // size_bytes: 11289600, + // download_url: 'https://upload.dify.ai/files/222bc6e7-40bd-4433-9ba8-4b9ecda88b14/file-preview?timestamp=1754976824&nonce=d970eb39b119f76ec94a9b026f2825b3&sign=ltJO4vS0jrwxuBl4GU74E1Sg_Tia2Y4g2LoBoPh3970=&as_attachment=true', + // } const { resetConversationVar, @@ -183,7 +191,16 @@ const Right = ({ )}
{currentNodeVar.var.name}
-
{currentNodeVar.var.value_type}
+
+ {currentNodeVar.var.value_type} + {isTruncated && ( + <> + · + {((fullContent?.size_bytes || 0) / 1024 / 1024).toFixed(1)}MB + + )} +
+ )}
@@ -200,20 +217,32 @@ const Right = ({ )} - {currentNodeVar.var.edited && ( + {isTruncated && ( + + + + + + + + )} + {!isTruncated && currentNodeVar.var.edited && ( {t('workflow.debug.variableInspect.edited')} )} - {currentNodeVar.var.edited && currentNodeVar.var.type !== VarInInspectType.conversation && ( + {!isTruncated && currentNodeVar.var.edited && currentNodeVar.var.type !== VarInInspectType.conversation && ( )} - {currentNodeVar.var.edited && currentNodeVar.var.type === VarInInspectType.conversation && ( + {!isTruncated && currentNodeVar.var.edited && currentNodeVar.var.type === VarInInspectType.conversation && ( @@ -238,7 +267,7 @@ const Right = ({ )} - {currentNodeVar && !isValueFetching && } + {currentNodeVar && !isValueFetching && } {isShowPromptGenerator && ( isCodeBlock diff --git a/web/app/components/workflow/variable-inspect/value-content.tsx b/web/app/components/workflow/variable-inspect/value-content.tsx index 3770dbb022..9495f5d8dd 100644 --- a/web/app/components/workflow/variable-inspect/value-content.tsx +++ b/web/app/components/workflow/variable-inspect/value-content.tsx @@ -25,11 +25,13 @@ import cn from '@/utils/classnames' type Props = { currentVar: VarInInspect handleValueChange: (varId: string, value: any) => void + isTruncated: boolean } const ValueContent = ({ currentVar, handleValueChange, + isTruncated, }: Props) => { const contentContainerRef = useRef(null) const errorMessageRef = useRef(null) @@ -72,7 +74,6 @@ const ValueContent = ({ if (showFileEditor) setFileValue(formatFileValue(currentVar)) - // eslint-disable-next-line react-hooks/exhaustive-deps }, [currentVar.id, currentVar.value]) const handleTextChange = (value: string) => { @@ -185,6 +186,7 @@ const ValueContent = ({ hideTopMenu schema={json} onUpdate={handleEditorChange} + isTruncated={isTruncated} /> )} {showFileEditor && ( diff --git a/web/i18n/en-US/workflow.ts b/web/i18n/en-US/workflow.ts index dbc9b908be..696413bc88 100644 --- a/web/i18n/en-US/workflow.ts +++ b/web/i18n/en-US/workflow.ts @@ -987,6 +987,7 @@ const translation = { envNode: 'Environment', chatNode: 'Conversation', systemNode: 'System', + exportToolTip: 'Export Variable as File', }, lastOutput: 'Last Output', relations: { diff --git a/web/i18n/zh-Hans/workflow.ts b/web/i18n/zh-Hans/workflow.ts index 95d4d254a3..3727feaef3 100644 --- a/web/i18n/zh-Hans/workflow.ts +++ b/web/i18n/zh-Hans/workflow.ts @@ -987,6 +987,7 @@ const translation = { envNode: '环境变量', chatNode: '会话变量', systemNode: '系统变量', + exportToolTip: '导出变量为文件', }, lastOutput: '上次输出', relations: { diff --git a/web/types/workflow.ts b/web/types/workflow.ts index 1cbcc942a5..d1d59374d1 100644 --- a/web/types/workflow.ts +++ b/web/types/workflow.ts @@ -378,6 +378,11 @@ export enum VarInInspectType { system = 'sys', } +export type FullContent = { + size_bytes: number + download_url: string +} + export type VarInInspect = { id: string type: VarInInspectType @@ -388,6 +393,8 @@ export type VarInInspect = { value: any edited: boolean visible: boolean + is_truncated: boolean + full_content: FullContent } export type NodeWithVar = {