diff --git a/web/app/dashboard/ai-workflows/_components/flowgram-editor-provider.tsx b/web/app/dashboard/ai-workflows/_components/flowgram-editor-provider.tsx index e9e6820..2c23a05 100644 --- a/web/app/dashboard/ai-workflows/_components/flowgram-editor-provider.tsx +++ b/web/app/dashboard/ai-workflows/_components/flowgram-editor-provider.tsx @@ -20,16 +20,25 @@ import { syncConditionBranchTargetsFromEdges, } from "./workflow-utils" +export type SelectedWorkflowBranch = { + nodeId: string + branchId: string +} + export function useFlowgramEditorProps({ definition, nodeSpecs, + selectedBranch, readonly = false, onDefinitionChange, + onSelectBranch, }: { definition: AIWorkflowDefinition nodeSpecs: AIWorkflowNodeSpec[] + selectedBranch?: SelectedWorkflowBranch | null readonly?: boolean onDefinitionChange?: (definition: AIWorkflowDefinition) => void + onSelectBranch?: (branch: SelectedWorkflowBranch | null) => void }) { return useMemo( () => { @@ -41,7 +50,6 @@ export function useFlowgramEditorProps({ disableScrollBar: true, }, initialData: initialData as WorkflowJSON, - nodeRegistries: buildFlowgramNodeRegistries(nodeSpecs), fromNodeJSON(_node, json) { return json }, @@ -51,6 +59,7 @@ export function useFlowgramEditorProps({ materials: { renderDefaultNode: FlowgramNodeRenderer, }, + nodeRegistries: buildFlowgramNodeRegistries(nodeSpecs, selectedBranch, onSelectBranch), nodeEngine: { enable: true, }, @@ -114,7 +123,7 @@ export function useFlowgramEditorProps({ ], } }, - [definition, nodeSpecs, onDefinitionChange, readonly] + [definition, nodeSpecs, onDefinitionChange, onSelectBranch, readonly, selectedBranch] ) } diff --git a/web/app/dashboard/ai-workflows/_components/flowgram-node-registries.tsx b/web/app/dashboard/ai-workflows/_components/flowgram-node-registries.tsx index 4d2b717..43cf310 100644 --- a/web/app/dashboard/ai-workflows/_components/flowgram-node-registries.tsx +++ b/web/app/dashboard/ai-workflows/_components/flowgram-node-registries.tsx @@ -1,4 +1,4 @@ -import { Field, type WorkflowNodeRegistry } from "@flowgram.ai/free-layout-editor" +import { Field, type WorkflowNodeRegistry, useNodeRender } from "@flowgram.ai/free-layout-editor" import { PlusIcon, XIcon } from "lucide-react" import { Button } from "@/components/ui/button" @@ -8,8 +8,13 @@ import { normalizeNodeConfig, type WorkflowConditionBranch, } from "./workflow-utils" +import type { SelectedWorkflowBranch } from "./flowgram-editor-provider" -export function buildFlowgramNodeRegistries(nodeSpecs: AIWorkflowNodeSpec[]): WorkflowNodeRegistry[] { +export function buildFlowgramNodeRegistries( + nodeSpecs: AIWorkflowNodeSpec[], + selectedBranch?: SelectedWorkflowBranch | null, + onSelectBranch?: (branch: SelectedWorkflowBranch | null) => void +): WorkflowNodeRegistry[] { const seen = new Set() const specs = nodeSpecs.length > 0 ? nodeSpecs @@ -36,7 +41,14 @@ export function buildFlowgramNodeRegistries(nodeSpecs: AIWorkflowNodeSpec[]): Wo defaultPorts: defaultPortsForNodeType(spec.type), }, formMeta: { - render: () => , + render: () => ( + + ), }, })) } @@ -44,12 +56,26 @@ export function buildFlowgramNodeRegistries(nodeSpecs: AIWorkflowNodeSpec[]): Wo function FlowgramNodeForm({ nodeType, fallbackTitle, + selectedBranch, + onSelectBranch, }: { nodeType: string fallbackTitle: string + selectedBranch?: SelectedWorkflowBranch | null + onSelectBranch?: (branch: SelectedWorkflowBranch | null) => void }) { + const { node } = useNodeRender() + const nodeId = String(node.id ?? "") + if (nodeType === "condition") { - return + return ( + + ) } return ( @@ -79,7 +105,17 @@ function defaultPortsForNodeType(type: string) { return [{ type: "input" as const }, { type: "output" as const }] } -function ConditionNodeForm({ fallbackTitle }: { fallbackTitle: string }) { +function ConditionNodeForm({ + fallbackTitle, + nodeId, + selectedBranch, + onSelectBranch, +}: { + fallbackTitle: string + nodeId: string + selectedBranch?: SelectedWorkflowBranch | null + onSelectBranch?: (branch: SelectedWorkflowBranch | null) => void +}) { return (
name="title"> @@ -101,6 +137,9 @@ function ConditionNodeForm({ fallbackTitle }: { fallbackTitle: string }) { } const deleteBranch = (branchId: string) => { updateBranches(branches.filter((branch) => branch.id !== branchId)) + if (selectedBranch?.nodeId === nodeId && selectedBranch.branchId === branchId) { + onSelectBranch?.(null) + } } return ( @@ -109,7 +148,16 @@ function ConditionNodeForm({ fallbackTitle }: { fallbackTitle: string }) { {branches.map((branch, index) => (
{ + event.stopPropagation() + onSelectBranch?.({ nodeId, branchId: branch.id }) + }} > {branch.name || (branch.default ? "默认分支" : branch.id)} diff --git a/web/app/dashboard/ai-workflows/_components/node-config-panel.tsx b/web/app/dashboard/ai-workflows/_components/node-config-panel.tsx index 7c59b6e..1a7efd9 100644 --- a/web/app/dashboard/ai-workflows/_components/node-config-panel.tsx +++ b/web/app/dashboard/ai-workflows/_components/node-config-panel.tsx @@ -26,12 +26,27 @@ export type WorkflowBranchSummary = { targetName?: string } +const CONDITION_OPERATOR_OPTIONS = [ + { value: "eq", label: "等于" }, + { value: "neq", label: "不等于" }, + { value: "contains", label: "包含" }, + { value: "not_contains", label: "不包含" }, + { value: "gt", label: "大于" }, + { value: "gte", label: "大于等于" }, + { value: "lt", label: "小于" }, + { value: "lte", label: "小于等于" }, + { value: "exists", label: "存在" }, + { value: "empty", label: "为空" }, +] + export function NodeConfigPanel({ node, nodeSpec, nodes, availableVariables, showHeader = true, + showConditionBranches = true, + showConfigJSON = true, onChange, onDelete, }: { @@ -41,6 +56,8 @@ export function NodeConfigPanel({ availableVariables?: WorkflowVariableRef[] branchSummaries?: WorkflowBranchSummary[] showHeader?: boolean + showConditionBranches?: boolean + showConfigJSON?: boolean onChange: (nodeId: string, data: AIWorkflowDefinition["nodes"][number]["data"]) => void onDelete?: (nodeId: string) => void }) { @@ -174,7 +191,7 @@ export function NodeConfigPanel({
) : null} - {node.type === "condition" || branches.length > 0 ? ( + {showConditionBranches && (node.type === "condition" || branches.length > 0) ? ( ) : null} -
- -