156 lines
6.0 KiB
Python
156 lines
6.0 KiB
Python
"""
|
||
开始节点
|
||
"""
|
||
import logging
|
||
from typing import Any, Dict, List
|
||
|
||
from ..base import BaseNode, NodeContext, NodeResult
|
||
from ..registry import NodeRegistry
|
||
|
||
logger = logging.getLogger(__name__)
|
||
|
||
|
||
@NodeRegistry.register
|
||
class StartNode(BaseNode):
|
||
"""
|
||
开始节点
|
||
|
||
工作流的入口节点,接收用户输入
|
||
"""
|
||
|
||
node_type = 'start'
|
||
node_name = '开始'
|
||
node_category = 'basic'
|
||
node_icon = 'play-circle'
|
||
node_description = '工作流的开始节点,接收用户输入'
|
||
|
||
inputs = []
|
||
|
||
outputs = [
|
||
{
|
||
'name': 'user_input',
|
||
'type': 'string',
|
||
'description': '用户输入',
|
||
},
|
||
{
|
||
'name': 'application_id',
|
||
'type': 'string',
|
||
'description': '子应用ID(在子应用模式下自动注入)',
|
||
},
|
||
{
|
||
'name': 'application_code',
|
||
'type': 'string',
|
||
'description': '子应用编码(在子应用模式下自动注入)',
|
||
},
|
||
{
|
||
'name': 'form_code',
|
||
'type': 'string',
|
||
'description': '表单编码(从表单列表调用时自动注入)',
|
||
},
|
||
]
|
||
|
||
def execute(self, context: NodeContext) -> NodeResult:
|
||
"""执行开始节点"""
|
||
output_variables = {}
|
||
|
||
# 调试日志
|
||
logger.info(f"StartNode execute - context.variables: {list(context.variables.keys())}")
|
||
logger.info(f"StartNode execute - application_id in variables: {'application_id' in context.variables}")
|
||
if 'application_id' in context.variables:
|
||
logger.info(f"StartNode execute - application_id value: {context.variables['application_id']}")
|
||
|
||
# 首先将 user_input 作为开始节点的输出变量
|
||
# 这样下游节点可以通过 {{start-xxx.user_input}} 引用
|
||
if context.user_input:
|
||
output_variables['user_input'] = context.user_input
|
||
elif 'user_input' in context.variables:
|
||
output_variables['user_input'] = context.variables['user_input']
|
||
|
||
# 将 application_id 作为开始节点的输出变量
|
||
# 这样下游节点可以通过 {{start-xxx.application_id}} 引用
|
||
# 主应用模式下为空字符串,子应用模式下为实际的应用ID
|
||
output_variables['application_id'] = context.variables.get('application_id', 'main')
|
||
|
||
# 将 application_code 作为开始节点的输出变量
|
||
# 这样下游节点可以通过 {{start-xxx.application_code}} 引用
|
||
# 主应用模式下为空字符串,子应用模式下为实际的应用编码
|
||
output_variables['application_code'] = context.variables.get('application_code', '')
|
||
|
||
# 将 form_code 作为开始节点的输出变量
|
||
# 这样下游节点可以通过 {{start-xxx.form_code}} 引用
|
||
# 从表单列表调用时会自动注入,否则为空字符串
|
||
output_variables['form_code'] = context.variables.get('form_code', '')
|
||
|
||
logger.info(f"StartNode execute - output_variables: {output_variables}")
|
||
|
||
# 处理前端定义的变量(variables 数组)
|
||
# 格式: [{ variable: 'name', type: 'string', label: '名称', required: true, default_value: '' }]
|
||
variables = self.config.get('variables', [])
|
||
for var in variables:
|
||
var_name = var.get('variable', '')
|
||
if not var_name:
|
||
continue
|
||
|
||
default_value = var.get('default_value', '')
|
||
var_type = var.get('type', 'string')
|
||
|
||
# 如果 context 中已有该变量(从 inputs 传入),使用传入的值
|
||
# 否则使用默认值
|
||
if var_name in context.variables and context.variables[var_name]:
|
||
value = context.variables[var_name]
|
||
else:
|
||
value = default_value
|
||
|
||
# 类型转换
|
||
if var_type == 'number' and value:
|
||
try:
|
||
value = float(value) if '.' in str(value) else int(value)
|
||
except (ValueError, TypeError):
|
||
pass
|
||
elif var_type == 'boolean':
|
||
if isinstance(value, str):
|
||
value = value.lower() in ('true', '1', 'yes')
|
||
|
||
context.set_variable(var_name, value)
|
||
output_variables[var_name] = value
|
||
|
||
# 处理自定义输入变量(兼容旧格式 input_variables)
|
||
input_variables = self.config.get('input_variables', [])
|
||
for var in input_variables:
|
||
var_name = var.get('name', '')
|
||
var_value = var.get('default', '')
|
||
if var_name:
|
||
# 如果 context 中没有该变量,使用默认值
|
||
if var_name not in context.variables or not context.variables[var_name]:
|
||
context.set_variable(var_name, var_value)
|
||
output_variables[var_name] = context.get_variable(var_name)
|
||
|
||
return NodeResult(
|
||
success=True,
|
||
output=output_variables,
|
||
output_variables=output_variables,
|
||
)
|
||
|
||
@classmethod
|
||
def get_config_schema(cls) -> Dict[str, Any]:
|
||
"""获取配置 Schema"""
|
||
return {
|
||
'type': 'object',
|
||
'properties': {
|
||
'input_variables': {
|
||
'type': 'array',
|
||
'title': '输入变量',
|
||
'items': {
|
||
'type': 'object',
|
||
'properties': {
|
||
'name': {'type': 'string', 'title': '变量名'},
|
||
'type': {'type': 'string', 'title': '类型', 'enum': ['string', 'number', 'boolean']},
|
||
'description': {'type': 'string', 'title': '描述'},
|
||
'default': {'type': 'string', 'title': '默认值'},
|
||
'required': {'type': 'boolean', 'title': '是否必填'},
|
||
},
|
||
},
|
||
},
|
||
},
|
||
}
|