From 9ff9942af1a485563a036bfdbfa8578a68ecf6c0 Mon Sep 17 00:00:00 2001 From: yyh Date: Fri, 27 Feb 2026 17:16:03 +0800 Subject: [PATCH] refactor(web): move sandbox tree builder to workflow artifacts utils --- .../file-tree/artifacts/artifacts-section.tsx | 3 +- .../skill/file-tree/artifacts/utils.ts | 43 +++++++++++++++++++ .../variable-inspect/artifacts-tab.tsx | 3 +- web/service/use-sandbox-file.ts | 43 ------------------- 4 files changed, 47 insertions(+), 45 deletions(-) create mode 100644 web/app/components/workflow/skill/file-tree/artifacts/utils.ts diff --git a/web/app/components/workflow/skill/file-tree/artifacts/artifacts-section.tsx b/web/app/components/workflow/skill/file-tree/artifacts/artifacts-section.tsx index 89af8c6b11..dc52435e51 100644 --- a/web/app/components/workflow/skill/file-tree/artifacts/artifacts-section.tsx +++ b/web/app/components/workflow/skill/file-tree/artifacts/artifacts-section.tsx @@ -7,10 +7,11 @@ import { useCallback, useMemo, useState } from 'react' import { useTranslation } from 'react-i18next' import FolderSpark from '@/app/components/base/icons/src/vender/workflow/FolderSpark' import { useStore, useWorkflowStore } from '@/app/components/workflow/store' -import { buildTreeFromFlatList, sandboxFilesTreeOptions, useDownloadSandboxFile } from '@/service/use-sandbox-file' +import { sandboxFilesTreeOptions, useDownloadSandboxFile } from '@/service/use-sandbox-file' import { cn } from '@/utils/classnames' import { downloadUrl } from '@/utils/download' import ArtifactsTree from './artifacts-tree' +import { buildTreeFromFlatList } from './utils' type ArtifactsSectionProps = { className?: string diff --git a/web/app/components/workflow/skill/file-tree/artifacts/utils.ts b/web/app/components/workflow/skill/file-tree/artifacts/utils.ts new file mode 100644 index 0000000000..a36eb08836 --- /dev/null +++ b/web/app/components/workflow/skill/file-tree/artifacts/utils.ts @@ -0,0 +1,43 @@ +import type { + SandboxFileNode, + SandboxFileTreeNode, +} from '@/types/sandbox-file' + +export function buildTreeFromFlatList(nodes: SandboxFileNode[]): SandboxFileTreeNode[] { + const nodeMap = new Map() + const roots: SandboxFileTreeNode[] = [] + + const sorted = [...nodes].sort((a, b) => + a.path.split('/').length - b.path.split('/').length, + ) + + for (const node of sorted) { + const parts = node.path.split('/') + const name = parts[parts.length - 1] + const parentPath = parts.slice(0, -1).join('/') + + const treeNode: SandboxFileTreeNode = { + id: node.path, + name, + path: node.path, + node_type: node.is_dir ? 'folder' : 'file', + size: node.size, + mtime: node.mtime, + extension: node.extension, + children: [], + } + + nodeMap.set(node.path, treeNode) + + if (parentPath === '') { + roots.push(treeNode) + } + else { + const parent = nodeMap.get(parentPath) + if (parent) + parent.children.push(treeNode) + } + } + + return roots +} diff --git a/web/app/components/workflow/variable-inspect/artifacts-tab.tsx b/web/app/components/workflow/variable-inspect/artifacts-tab.tsx index 595ba1018a..0ee451fc9a 100644 --- a/web/app/components/workflow/variable-inspect/artifacts-tab.tsx +++ b/web/app/components/workflow/variable-inspect/artifacts-tab.tsx @@ -11,9 +11,10 @@ import Loading from '@/app/components/base/loading' import ArtifactsTree from '@/app/components/workflow/skill/file-tree/artifacts/artifacts-tree' import ReadOnlyFilePreview from '@/app/components/workflow/skill/viewer/read-only-file-preview' import { useDocLink } from '@/context/i18n' -import { buildTreeFromFlatList, sandboxFileDownloadUrlOptions, sandboxFilesTreeOptions, useDownloadSandboxFile } from '@/service/use-sandbox-file' +import { sandboxFileDownloadUrlOptions, sandboxFilesTreeOptions, useDownloadSandboxFile } from '@/service/use-sandbox-file' import { cn } from '@/utils/classnames' import { downloadUrl } from '@/utils/download' +import { buildTreeFromFlatList } from '../skill/file-tree/artifacts/utils' import { useStore } from '../store' import { WorkflowRunningStatus } from '../types' import InspectLayout from './inspect-layout' diff --git a/web/service/use-sandbox-file.ts b/web/service/use-sandbox-file.ts index a22ef8e309..2b588b91c3 100644 --- a/web/service/use-sandbox-file.ts +++ b/web/service/use-sandbox-file.ts @@ -1,7 +1,3 @@ -import type { - SandboxFileNode, - SandboxFileTreeNode, -} from '@/types/sandbox-file' import { skipToken, useMutation, useQueryClient } from '@tanstack/react-query' import { useCallback } from 'react' import { consoleClient, consoleQuery } from '@/service/client' @@ -54,42 +50,3 @@ export function useDownloadSandboxFile(appId: string | undefined) { }, }) } - -export function buildTreeFromFlatList(nodes: SandboxFileNode[]): SandboxFileTreeNode[] { - const nodeMap = new Map() - const roots: SandboxFileTreeNode[] = [] - - const sorted = [...nodes].sort((a, b) => - a.path.split('/').length - b.path.split('/').length, - ) - - for (const node of sorted) { - const parts = node.path.split('/') - const name = parts[parts.length - 1] - const parentPath = parts.slice(0, -1).join('/') - - const treeNode: SandboxFileTreeNode = { - id: node.path, - name, - path: node.path, - node_type: node.is_dir ? 'folder' : 'file', - size: node.size, - mtime: node.mtime, - extension: node.extension, - children: [], - } - - nodeMap.set(node.path, treeNode) - - if (parentPath === '') { - roots.push(treeNode) - } - else { - const parent = nodeMap.get(parentPath) - if (parent) - parent.children.push(treeNode) - } - } - - return roots -}