Merge pull request #959 from SuanmoSuanyangTechnology/feature/end_zy

feat(web): add output node
This commit is contained in:
yingzhao
2026-04-21 18:45:12 +08:00
committed by GitHub
7 changed files with 67 additions and 14 deletions

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>编组 13备份</title>
<g id="空间里层页面优化" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="应用管理-工作流-配置-开始" transform="translate(-685, -694)">
<g id="编组-13备份" transform="translate(685, 694)">
<rect id="矩形" fill="#FF8A4C" x="0" y="0" width="24" height="24" rx="8"></rect>
<g id="编组" transform="translate(5.3, 6.5)" stroke="#FFFFFF" stroke-width="1.2">
<rect id="矩形" x="0" y="0" width="4.4" height="4.4" rx="1"></rect>
<rect id="矩形备份-7" x="9" y="0" width="4.4" height="4.4" rx="1"></rect>
<path d="M2,4 L2,9 C2,10.1045695 2.8954305,11 4,11 L10.4342273,11 L10.4342273,11" id="路径-23"></path>
<polyline id="路径" stroke-linecap="round" stroke-linejoin="round" points="9 9 11 11 9 13"></polyline>
<line x1="4" y1="2.2" x2="9" y2="2.2" id="路径-24"></line>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -2243,6 +2243,7 @@ Memory Bear: After the rebellion, regional warlordism intensified for several re
coreNode: 'Core Nodes',
start: 'Start',
end: 'End',
output: 'Output',
answer: 'Answer',
aiAndCognitiveProcessing: 'AI & Cognitive Processing',
llm: 'Large Language Model (LLM)',
@@ -2494,12 +2495,15 @@ Memory Bear: After the rebellion, regional warlordism intensified for several re
ne: 'Not In',
}
},
output: {
outputs: 'Output Variable',
},
name: 'Key',
type: 'Type',
value: 'Value',
addCase: 'Add Condition',
addVariable: 'Add Variables',
output: 'Output Variable',
outputVariable: 'Output Variable',
duplicateName: 'Variable name cannot be duplicated',
},
@@ -2517,8 +2521,8 @@ Memory Bear: After the rebellion, regional warlordism intensified for several re
undo: 'Undo',
fit: 'Fit View',
input: 'Input',
output: 'Output',
input_result: 'Input',
output_result: 'Output',
error: 'Error Message',
loopNum: ' loops',
iterationNum: ' iterations',
@@ -2565,6 +2569,7 @@ Memory Bear: After the rebellion, regional warlordism intensified for several re
'jinja-render.template': 'Template',
'document-extractor.file_selector': 'File variable',
'list-operator.input_list': 'Input list',
'output.outputs': 'Output Variable',
},
checkListHasErrors: 'Please resolve all issues in the checklist before publishing',
variableSelect: {

View File

@@ -2204,6 +2204,7 @@ export const zh = {
coreNode: '核心节点',
start: '开始Start',
end: '结束End',
output: '输出Output',
answer: '回复Answer',
aiAndCognitiveProcessing: 'AI与认知处理',
llm: '大语言模型 (LLM)',
@@ -2458,12 +2459,15 @@ export const zh = {
ne: '不在',
}
},
output: {
outputs: '输出变量',
},
name: '键',
type: '类型',
value: '值',
addCase: '添加条件',
addVariable: '添加变量',
output: '输出变量',
outputVariable: '输出变量',
duplicateName: '变量名不能重复',
},
@@ -2481,8 +2485,8 @@ export const zh = {
undo: '撤销',
fit: '自适应',
input: '输入',
output: '输出',
input_result: '输入',
output_result: '输出',
error: '错误信息',
loopNum: '个循环',
iterationNum: '个迭代',
@@ -2529,6 +2533,7 @@ export const zh = {
'jinja-render.template': '模板',
'document-extractor.file_selector': '文件变量',
'list-operator.input_list': '输入变量',
'output.outputs': '输出变量',
},
checkListHasErrors: '发布前确认检查清单中所有问题均已解决',
variableSelect: {

View File

@@ -2,7 +2,7 @@
* @Author: ZhaoYing
* @Date: 2026-02-24 17:57:08
* @Last Modified by: ZhaoYing
* @Last Modified time: 2026-04-14 16:33:33
* @Last Modified time: 2026-04-20 15:33:48
*/
/*
* Runtime Component
@@ -187,7 +187,7 @@ const Runtime: FC<{ item: ChatItem; index: number;}> = ({
{['input', 'output'].map(key => (
<div key={key} className="rb:bg-[#EBEBEB] rb:rounded-lg">
<div className="rb:py-2 rb:px-3 rb:flex rb:justify-between rb:items-center rb:text-[12px]">
{isLoop ? t(`workflow.runtime.${key}_cycle_vars`) : t(`workflow.${key}`)}
{isLoop ? t(`workflow.runtime.${key}_cycle_vars`) : t(`workflow.${key}_result`)}
<Button
className="rb:py-0! rb:px-1! rb:text-[12px]!"
size="small"

View File

@@ -11,12 +11,14 @@ interface MappingListProps {
options: Suggestion[];
extra?: ReactNode;
valueKey?: string;
isNeedType?: boolean;
}
const MappingList: FC<MappingListProps> = ({ label, name, options, extra, valueKey = 'value' }) => {
const MappingList: FC<MappingListProps> = ({ label, name: listName, options, extra, valueKey = 'value', isNeedType = false }) => {
const { t } = useTranslation()
const form = Form.useFormInstance()
return (
<>
<Form.List name={name}>
<Form.List name={listName}>
{(fields, { add, remove }) => (
<>
<Flex align="center" justify="space-between" className="rb:mb-2!">
@@ -59,8 +61,13 @@ const MappingList: FC<MappingListProps> = ({ label, name, options, extra, valueK
options={options}
size="small"
className="rb:flex-1!"
onChange={isNeedType ? (_val, option) => {
const dataType = (option as Suggestion | undefined)?.dataType
form.setFieldValue([listName, name, 'type'], dataType)
} : undefined}
/>
</Form.Item>
{isNeedType && <Form.Item name={[name, 'type']} hidden />}
<div
className="rb:size-4 rb:cursor-pointer rb:bg-cover rb:bg-[url('@/assets/images/workflow/deleteBg.svg')] rb:hover:bg-[url('@/assets/images/workflow/deleteBg_hover.svg')]"
onClick={() => remove(name)}

View File

@@ -2,7 +2,7 @@
* @Author: ZhaoYing
* @Date: 2026-02-03 15:39:59
* @Last Modified by: ZhaoYing
* @Last Modified time: 2026-04-21 14:15:33
* @Last Modified time: 2026-04-21 18:44:15
*/
import { type FC, useEffect, useState, useMemo } from "react";
import clsx from 'clsx'
@@ -38,6 +38,7 @@ import RbCard from '@/components/RbCard/Card';
import ModelConfig from './ModelConfig'
import ModelSelect from '@/components/ModelSelect'
import ListOperator from './ListOperator'
import MappingList from "./MappingList";
/**
* Props for Properties component
@@ -807,6 +808,15 @@ const Properties: FC<PropertiesProps> = ({
</Form.Item>
)
}
if (config.type === 'mappingList') {
return <MappingList
key={key}
label={t(`workflow.config.${selectedNode?.data?.type}.${key}`)}
name={key}
options={variableList}
isNeedType={config.isNeedType as boolean}
/>
}
if (key === 'vision_input' && !values?.vision) {
return null
@@ -906,7 +916,6 @@ const Properties: FC<PropertiesProps> = ({
}
});
console.log('list', list)
return list
}
// Filter child nodes for iteration output
@@ -960,7 +969,7 @@ const Properties: FC<PropertiesProps> = ({
<div className="rb:text-[12px] rb:leading-4.5">
<Flex gap={8} vertical>
<Flex align="center" className="rb:font-medium rb:cursor-pointer" onClick={handleToggle}>
{t('workflow.config.output')}
{t('workflow.config.outputVariable')}
<div
className={clsx("rb:size-3 rb:bg-cover rb:bg-[url('@/assets/images/common/caret_right_outlined.svg')]", {
'rb:rotate-90': !outputCollapsed

View File

@@ -2,7 +2,7 @@
* @Author: ZhaoYing
* @Date: 2026-02-03 15:06:18
* @Last Modified by: ZhaoYing
* @Last Modified time: 2026-04-16 17:52:30
* @Last Modified time: 2026-04-21 18:23:31
*/
import LoopNode from './components/Nodes/LoopNode';
import NormalNode from './components/Nodes/NormalNode';
@@ -72,6 +72,15 @@ export const nodeLibrary: NodeLibrary[] = [
}
}
},
{ type: "output", icon: 'rb:bg-[url("@/assets/images/workflow/output.svg")]',
config: {
outputs: {
type: 'mappingList',
required: true,
isNeedType: true
}
}
},
// { type: "answer", icon: answerIcon },
]
},