package node // NodeGroup 节点分组标识 type NodeGroup string // NodeType 节点类型标识 type NodeType string // 分组常量定义 const ( NodeGroupBase NodeGroup = "base" NodeGroupSystem NodeGroup = "system" ) // 节点类型常量定义 const ( NodeTypeStart NodeType = "__start__" NodeTypeModel NodeType = "model" NodeTypeDataMerge NodeType = "data_merge" NodeTypeForm NodeType = "form" NodeTypeSubFlow NodeType = "sub_flow" NodeTypeHttp NodeType = "http" NodeTypeSystemSum NodeType = "system_sum" NodeTypeScriptTranscribe NodeType = "script_transcribe" ) // NodeGroupMeta 节点分组元数据 type NodeGroupMeta struct { Key NodeGroup `json:"key"` // 后端存储标识 Name string `json:"name"` // 前端展示中文名称 } // NodeTypeMeta 节点元数据 type NodeTypeMeta struct { Key NodeType `json:"key"` // 节点类型标识 Name string `json:"name"` // 节点中文名称 Group NodeGroup `json:"group"` // 所属分组 Sort int `json:"sort"` // UI排序字段 Desc string `json:"desc,omitempty"` // 可选:节点简介 PatchLayout bool `json:"patchLayout"` IsMultiParameter bool `json:"isMultiParameter"` BatchExecOption bool `json:"batchExecOption"` PreToolOption []NodePresetField `json:"preToolOption"` PostToolOption []NodePresetField `json:"postToolOption"` IsSaveFileOption bool `json:"isSaveFileOption"` FormConfigOption bool `json:"formConfigOption"` ModelConfigOption bool `json:"modelConfigOption"` SkillOption bool `json:"skillOption"` PromptOption bool `json:"promptOption"` NegativePromptOption bool `json:"negativePromptOption"` PresetOption []NodePresetField `json:"presetOption"` OutputField []NodeOutputField `json:"outputField"` } type NodeOutputField struct { Field string `json:"field"` Label string `json:"label"` } type NodePresetField struct { Value string `json:"value"` ValueSource []ValueSource `json:"valueSource"` Field string `json:"field"` Label string `json:"label"` Type string `json:"type"` IsFormField bool `json:"isFormField"` Constraint FieldConstraint `json:"constraint"` Required bool `json:"required"` Options []SelectOption `json:"options"` } type ValueSource struct { NodeId string `json:"nodeId"` Field string `json:"field"` Label string `json:"label"` } // FieldConstraint 字段约束 type FieldConstraint struct { // 数字类型:int、float、double、string Type string `json:"type" dc:"类型"` Min any `json:"min" dc:"最小值"` Max any `json:"max" dc:"最大值"` } type SelectOption struct { Key string `json:"key"` Value string `json:"value"` Config []NodePresetField `json:"config"` } // NodeGroupTree 对外输出树形结构:分组 + 分组下所有节点 type NodeGroupTree struct { Group NodeGroupMeta `json:"group"` Nodes []NodeTypeMeta `json:"nodes"` } // ===================== 元数据集中注册区(英文标识+中文文案统一维护) ===================== var NodeGroupMetaList = []NodeGroupMeta{ { Key: NodeGroupBase, Name: "基础", }, } var NodeTypeMetaList = []NodeTypeMeta{ { Key: NodeTypeModel, Name: "模型", Group: NodeGroupBase, Sort: 1, Desc: "模型调用节点,可配置模型参数、模型配置、技能、提示语、结果汇集、结果保存、结果返回、结果展示等信息。", PatchLayout: true, IsMultiParameter: true, BatchExecOption: true, PreToolOption: []NodePresetField{ { Field: "perTool", Label: "前置方法", Type: "select", Required: false, Options: []SelectOption{}, }, }, PostToolOption: []NodePresetField{ { Field: "postTool", Label: "后置方法", Type: "select", Required: false, Options: []SelectOption{}, }, }, IsSaveFileOption: true, FormConfigOption: false, ModelConfigOption: true, SkillOption: false, PromptOption: true, NegativePromptOption: false, }, { Key: NodeTypeDataMerge, Name: "结果汇集", Group: NodeGroupBase, Sort: 2, Desc: "结果汇集节点,可配置结果汇集方式、结果保存、结果返回、结果展示等信息。", IsMultiParameter: false, BatchExecOption: false, IsSaveFileOption: false, FormConfigOption: false, ModelConfigOption: false, SkillOption: false, PromptOption: false, NegativePromptOption: false, }, { Key: NodeTypeForm, Name: "表单", Group: NodeGroupBase, Sort: 3, Desc: "表单节点,可配置表单字段、表单配置、结果汇集、结果保存、结果返回、结果展示等信息。", IsMultiParameter: false, BatchExecOption: false, IsSaveFileOption: false, FormConfigOption: true, ModelConfigOption: false, SkillOption: false, PromptOption: false, NegativePromptOption: false, }, { Key: NodeTypeSubFlow, Name: "子流程", Group: NodeGroupBase, Sort: 4, PresetOption: []NodePresetField{ { Field: "maxConcurrency", Label: "生成次数", Type: "input", Value: "1", IsFormField: true, Constraint: FieldConstraint{ Type: "int", Min: 1, Max: 10, }, Required: true, }, }, }, { Key: NodeTypeHttp, Name: "HTTP(S)接口", Group: NodeGroupBase, Sort: 5, Desc: "HTTP(S)接口节点,可配置HTTP(S)接口地址、请求方式、请求头、请求体、结果返回结构、结果返回方式、结果返回结构、结果返回方式等信息。", BatchExecOption: false, IsSaveFileOption: true, FormConfigOption: false, ModelConfigOption: false, SkillOption: false, PromptOption: false, NegativePromptOption: false, PresetOption: []NodePresetField{ { Field: "method", Label: "请求方式", Type: "select", Required: true, Options: []SelectOption{ {Key: "GET", Value: "GET"}, {Key: "POST", Value: "POST"}, }, }, { Field: "url", Label: "请求地址", Type: "input", Constraint: FieldConstraint{ Type: "string", Min: 1, Max: -1, }, Required: true, }, { Field: "headers", Label: "请求头(支持Authorization鉴权)", Type: "keyValue", Required: false, }, { Field: "bodyType", Label: "请求体类型", Type: "select", Required: true, Options: []SelectOption{ {Key: "None", Value: "无"}, {Key: "JSON", Value: "JSON"}, }, }, { Field: "body", Label: "请求体内容", Type: "schemaJson", Required: false, }, { Field: "response", Label: "结果返回结构", Type: "schemaJson", Required: true, }, { Field: "responseType", Label: "结果返回方式", Type: "select", Required: true, Options: []SelectOption{ {Key: "sync", Value: "同步返回"}, {Key: "callback", Value: "等候回调", Config: []NodePresetField{ { Field: "callbackUrl", Label: "回调地址(只需要填写字段名称)", Type: "input", Constraint: FieldConstraint{ Type: "string", Min: 1, Max: -1, }, Required: true, }, }}, {Key: "pull", Value: "主动拉取", Config: []NodePresetField{ { Field: "method", Label: "请求方式", Type: "select", Required: true, Options: []SelectOption{ {Key: "GET", Value: "GET"}, {Key: "POST", Value: "POST"}, }, }, { Field: "url", Label: "请求地址", Type: "input", Constraint: FieldConstraint{ Type: "string", Min: 1, Max: -1, }, Required: true, }, { Field: "headers", Label: "请求头(支持Authorization鉴权)", Type: "keyValue", Required: false, }, { Field: "bodyType", Label: "请求体类型", Type: "select", Required: true, Options: []SelectOption{ {Key: "None", Value: "无"}, {Key: "JSON", Value: "JSON"}, }, }, { Field: "body", Label: "请求体内容", Type: "schemaJson", Required: true, }, { Field: "response", Label: "结果返回结构", Type: "schemaJson", Required: true, }, }}, }, }, }, }, { Key: NodeTypeScriptTranscribe, Name: "脚本转写", Group: NodeGroupBase, Sort: 6, Desc: "脚本转写节点,把文案/视频分析结果通过大模型转写为结构化分镜脚本([]Shot),作为视频生成节点的 shots 输入。", IsMultiParameter: false, BatchExecOption: false, IsSaveFileOption: false, FormConfigOption: false, ModelConfigOption: true, SkillOption: false, PromptOption: false, NegativePromptOption: false, PresetOption: []NodePresetField{ { Field: "totalDuration", Label: "视频总时长", Type: "input", Constraint: FieldConstraint{ Type: "int", Min: 1, Max: 300, }, Required: true, }, { Field: "modelId", Label: "视频模型", Type: "select", Required: true, Options: []SelectOption{}, }, }, OutputField: []NodeOutputField{ { Field: "prompt", Label: "转写内容", }, { Field: "duration", Label: "时长", }, { Field: "seed", Label: "种子", }, { Field: "reference_urls", Label: "参考链接", }, }, }, { Key: NodeTypeSystemSum, Name: "工作流内置节点-保存结果", Group: NodeGroupSystem, Sort: 7, }, } // ===================== 缓存map & 工具函数 ===================== var ( nodeTypeMetaMap map[NodeType]NodeTypeMeta nodeGroupMap map[NodeGroup]NodeGroupMeta ) func init() { // 初始化分组缓存 nodeGroupMap = make(map[NodeGroup]NodeGroupMeta, len(NodeGroupMetaList)) for _, meta := range NodeGroupMetaList { nodeGroupMap[meta.Key] = meta } // 初始化节点缓存 nodeTypeMetaMap = make(map[NodeType]NodeTypeMeta, len(NodeTypeMetaList)) for _, meta := range NodeTypeMetaList { nodeTypeMetaMap[meta.Key] = meta } } // GetNodeTypeMeta 根据节点类型获取元信息 func GetNodeTypeMeta(typ NodeType) (NodeTypeMeta, bool) { meta, ok := nodeTypeMetaMap[typ] return meta, ok } // GetNodeTypeName 快速获取节点中文名称,不存在返回原始key func GetNodeTypeName(typ NodeType) string { meta, ok := nodeTypeMetaMap[typ] if !ok { return string(typ) } return meta.Name } // GetNodeGroupMeta 根据分组标识获取分组元信息 func GetNodeGroupMeta(g NodeGroup) (NodeGroupMeta, bool) { meta, ok := nodeGroupMap[g] return meta, ok } // GetNodeGroupName 快速获取分组中文名称 func GetNodeGroupName(g NodeGroup) string { meta, ok := nodeGroupMap[g] if !ok { return string(g) } return meta.Name } // GetAllNodeTypeMeta 返回全部节点元数据副本 func GetAllNodeTypeMeta() []NodeTypeMeta { list := make([]NodeTypeMeta, len(NodeTypeMetaList)) copy(list, NodeTypeMetaList) return list } // GetNodeGroupTree 获取【分组+节点】树形列表,完整所有节点 func GetNodeGroupTree() []NodeGroupTree { return getFilteredNodeTree(nil) } // GetFilterNodeTree 根据指定分组过滤节点树形结构 // groups: 需要展示的分组key列表,传入nil返回全部 func GetFilterNodeTree(groups []NodeGroup) []NodeGroupTree { return getFilteredNodeTree(groups) } // getFilteredNodeTree 内部通用树形构建逻辑 func getFilteredNodeTree(filterGroups []NodeGroup) []NodeGroupTree { // 构建分组过滤集合 filterSet := make(map[NodeGroup]bool) for _, g := range filterGroups { filterSet[g] = true } groupNodeMap := make(map[NodeGroup][]NodeTypeMeta) for _, node := range NodeTypeMetaList { // 有过滤条件 && 当前分组不在过滤列表,则跳过 if len(filterSet) > 0 && !filterSet[node.Group] { continue } groupNodeMap[node.Group] = append(groupNodeMap[node.Group], node) } var tree []NodeGroupTree // 按定义顺序组装分组 for _, gMeta := range NodeGroupMetaList { // 如果开启过滤,跳过不在筛选列表中的分组 if len(filterSet) > 0 && !filterSet[gMeta.Key] { continue } nodes := groupNodeMap[gMeta.Key] if len(nodes) == 0 { continue } tree = append(tree, NodeGroupTree{ Group: gMeta, Nodes: nodes, }) } return tree }