From 7c0fb624d9beac769d71656074397f572ef9e0da Mon Sep 17 00:00:00 2001 From: zhaoying Date: Fri, 10 Apr 2026 17:34:38 +0800 Subject: [PATCH] feat(web): workflow variable type --- .../views/ApplicationConfig/ReleasePage.tsx | 38 +++++++++++++--- .../Properties/HttpRequest/EditableTable.tsx | 9 +--- .../Workflow/components/Properties/index.tsx | 44 +++++++++++++++---- 3 files changed, 68 insertions(+), 23 deletions(-) diff --git a/web/src/views/ApplicationConfig/ReleasePage.tsx b/web/src/views/ApplicationConfig/ReleasePage.tsx index 3e516c88..4de226f1 100644 --- a/web/src/views/ApplicationConfig/ReleasePage.tsx +++ b/web/src/views/ApplicationConfig/ReleasePage.tsx @@ -2,12 +2,13 @@ * @Author: ZhaoYing * @Date: 2026-02-03 16:29:41 * @Last Modified by: ZhaoYing - * @Last Modified time: 2026-03-26 15:24:41 + * @Last Modified time: 2026-04-10 17:02:07 */ import { type FC, useState, useEffect, useRef } from 'react'; import { useTranslation } from 'react-i18next'; import clsx from 'clsx'; import { Space, Input, Form, App, Flex } from 'antd'; +import copy from 'copy-to-clipboard'; import Tag, { type TagProps } from './components/Tag' import RbCard from '@/components/RbCard/Card' @@ -15,8 +16,9 @@ import { getReleaseList, rollbackRelease, appExport } from '@/api/application' import ReleaseModal from './components/ReleaseModal' import ReleaseShareModal from './components/ReleaseShareModal' import AppSharingModal from './components/AppSharingModal' -import type { Release, ReleaseModalRef, ReleaseShareModalRef, AppSharingModalRef } from './types' +import type { Release, ReleaseModalRef, ReleaseShareModalRef, AppSharingModalRef, WorkflowRef } from './types' import type { Application } from '@/views/ApplicationManagement/types' +import { runCheckOnGraph } from '@/views/Workflow/components/CheckList' import Empty from '@/components/Empty' import { formatDateTime } from '@/utils/format'; import Markdown from '@/components/Markdown' @@ -37,7 +39,7 @@ const heightClass = 'rb:max-h-[calc(100vh-140px)]' * @param data - Application data * @param refresh - Function to refresh application data */ -const ReleasePage: FC<{data: Application; refresh: () => void}> = ({data, refresh}) => { +const ReleasePage: FC<{data: Application; refresh: () => void; workflowRef?: React.RefObject}> = ({data, refresh, workflowRef}) => { const { t } = useTranslation(); const { message } = App.useApp() const releaseModalRef = useRef(null) @@ -75,6 +77,10 @@ const ReleasePage: FC<{data: Application; refresh: () => void}> = ({data, refres if (!selectedVersion) return appExport(data.id, data.name, { release_id: selectedVersion.id}) } + const handleCopy = (id: string) => { + copy(id) + message.success(t('common.copySuccess')) + } return (
@@ -102,7 +108,7 @@ const ReleasePage: FC<{data: Application; refresh: () => void}> = ({data, refres } } className={clsx("rb:hover:shadow-[0px_2px_8px_0px_rgba(0,0,0,0.2)]! rb:cursor-pointer rb:bg-white", { - 'rb:border-[#171719]!': version.id === selectedVersion.id, + 'rb:border! rb:border-[#171719]!': version.id === selectedVersion.id, 'rb:border-[#DFE4ED] ': version.id !== selectedVersion.id })} headerType="borderless" @@ -140,13 +146,33 @@ const ReleasePage: FC<{data: Application; refresh: () => void}> = ({data, refres releaseShareModalRef.current?.handleOpen()}>{t('application.share')} {data?.type !== 'multi_agent' && appSharingModalRef.current?.handleOpen()}>{t('application.sharing')}} } - releaseModalRef.current?.handleOpen()}>{t('application.release')} + { + if (data?.type === 'workflow') { + const graph = workflowRef?.current?.graphRef?.current + if (graph) { + const errors = await runCheckOnGraph(graph, t) + if (errors.length) { + message.error(t('workflow.checkListHasErrors')) + return + } + } + } + releaseModalRef.current?.handleOpen() + }}>{t('application.release')} {selectedVersion && {t('application.VersionInformation')} + + (ID: {selectedVersion.id} +
handleCopy(selectedVersion.id)} + >
+ ) +
+
} headerType="borderless" >
diff --git a/web/src/views/Workflow/components/Properties/HttpRequest/EditableTable.tsx b/web/src/views/Workflow/components/Properties/HttpRequest/EditableTable.tsx index de3ae9a7..e0a27b47 100644 --- a/web/src/views/Workflow/components/Properties/HttpRequest/EditableTable.tsx +++ b/web/src/views/Workflow/components/Properties/HttpRequest/EditableTable.tsx @@ -38,13 +38,6 @@ const EditableTable: FC = ({ ...(typeOptions.length > 0 && { type: typeOptions[0].value }) }); - // Filter options based on boolean type if needed - const booleanFilterOptions = useMemo(() => { - return filterBooleanType - ? options.filter(option => option.dataType !== 'boolean') - : options - }, [options, filterBooleanType]) - const namefilterOptions = useMemo(() => { const filterList: Suggestion[] = []; options.forEach(vo => { @@ -76,7 +69,7 @@ const EditableTable: FC = ({ ...vo, disabled: true }) - } else { + } else if (vo.dataType !== 'array[file]') { filterOptions.push(vo) } }) diff --git a/web/src/views/Workflow/components/Properties/index.tsx b/web/src/views/Workflow/components/Properties/index.tsx index 37c8cc8d..b5bc2d2e 100644 --- a/web/src/views/Workflow/components/Properties/index.tsx +++ b/web/src/views/Workflow/components/Properties/index.tsx @@ -2,7 +2,7 @@ * @Author: ZhaoYing * @Date: 2026-02-03 15:39:59 * @Last Modified by: ZhaoYing - * @Last Modified time: 2026-04-08 14:10:40 + * @Last Modified time: 2026-04-10 17:24:19 */ import { type FC, useEffect, useState, useMemo } from "react"; import clsx from 'clsx' @@ -315,8 +315,24 @@ const Properties: FC = ({ return filteredList; } - if (nodeType === 'knowledge-retrieval' - || (nodeType === 'parameter-extractor' && key === 'text') + if (nodeType === 'knowledge-retrieval') { + const allList = addParentIterationVars(variableList); + let filteredList: Suggestion[] = [] + allList.forEach(variable => { + if (variable.dataType === 'string') { + filteredList.push(variable) + } else if (variable.dataType === 'file') { + filteredList.push({ + ...variable, + disabled: true, + children: variable.children.filter((child: Suggestion) => child.dataType === 'string') + }) + } + }) + + return filteredList + } + if ((nodeType === 'parameter-extractor' && key === 'text') || (nodeType === 'question-classifier' && ['input_variable', 'categories'].includes(key as string)) ) { const allList = addParentIterationVars(variableList); @@ -359,8 +375,20 @@ const Properties: FC = ({ return filteredList; } if (nodeType === 'memory-write') { - let filteredList = addParentIterationVars(variableList).filter(variable => variable.dataType === 'string' || variable.dataType.includes('file')); - return filteredList; + const allList = addParentIterationVars(variableList); + let filteredList: Suggestion[] = [] + allList.forEach(variable => { + if (['string', 'array[file]'].includes(variable.dataType)) { + filteredList.push(variable) + } else if (variable.dataType === 'file') { + filteredList.push({ + ...variable, + children: variable.children.filter((child: Suggestion) => child.dataType === 'string') + }) + } + }) + + return filteredList } if (nodeType === 'parameter-extractor' && key === 'prompt') { let filteredList = addParentIterationVars(variableList).filter(variable => variable.dataType === 'string' || variable.dataType === 'number'); @@ -400,9 +428,7 @@ const Properties: FC = ({ return variableList.filter(variable => variable.dataType.includes('array')); } - if (nodeType === 'code' - || (nodeType === 'if-else' && key === 'cases') - ) { + if ((nodeType === 'if-else' && key === 'cases')) { const allList = addParentIterationVars(variableList); let filteredList: Suggestion[] = [] allList.forEach(variable => { @@ -919,7 +945,7 @@ const Properties: FC = ({ options={getFilteredVariableList(selectedNode?.data?.type, key)} /> : config.type === 'editor' - ? + ? : null }