From b0f82142a55c532c6ea9f57e463e18bb140b3ca6 Mon Sep 17 00:00:00 2001 From: Xin Wang Date: Mon, 3 Aug 2026 09:58:01 +0800 Subject: [PATCH] feat(workflow): show variables in drawer --- .../assistant-editor/dynamic-variables.tsx | 94 +++++++++++++++---- .../assistant-editor/workflow-page.tsx | 19 ++-- .../components/workflow/WorkflowCanvas.tsx | 59 +++++++++--- frontend/src/components/workflow/types.ts | 4 +- 4 files changed, 133 insertions(+), 43 deletions(-) diff --git a/frontend/src/components/assistant-editor/dynamic-variables.tsx b/frontend/src/components/assistant-editor/dynamic-variables.tsx index 5314f68..a8a303d 100644 --- a/frontend/src/components/assistant-editor/dynamic-variables.tsx +++ b/frontend/src/components/assistant-editor/dynamic-variables.tsx @@ -151,6 +151,59 @@ export function DynamicVariablesDialog({ onOpenChange: (open: boolean) => void; definitions: Record; onChange: (definitions: Record) => void; +}) { + return ( + + + + + + 动态变量 + + + 助手配置中引用的自定义变量会自动出现在这里。 + + + + + + + ); +} + +export function DynamicVariablesPanel({ + definitions, + onChange, +}: { + definitions: Record; + onChange: (definitions: Record) => void; +}) { + return ( +
+

+ 助手配置中引用的自定义变量会自动出现在这里。 +

+ +
+ ); +} + +function DynamicVariablesEditor({ + definitions, + onChange, + layout, +}: { + definitions: Record; + onChange: (definitions: Record) => void; + layout: "dialog" | "panel"; }) { const entries = Object.entries(definitions); const [copiedSystemVariable, setCopiedSystemVariable] = useState( @@ -168,20 +221,15 @@ export function DynamicVariablesDialog({ } return ( - - - - - - 动态变量 - - - 助手配置中引用的自定义变量会自动出现在这里。 - - - - - + + 自定义变量 @@ -198,7 +246,11 @@ export function DynamicVariablesDialog({ {entries.length === 0 ? (
@@ -316,7 +368,11 @@ export function DynamicVariablesDialog({

将完整引用复制到提示词或开场白中,不能只填写中文名称。 @@ -363,9 +419,7 @@ export function DynamicVariablesDialog({

))} -
-
-
-
+ + ); } diff --git a/frontend/src/components/assistant-editor/workflow-page.tsx b/frontend/src/components/assistant-editor/workflow-page.tsx index 7bc1232..422e869 100644 --- a/frontend/src/components/assistant-editor/workflow-page.tsx +++ b/frontend/src/components/assistant-editor/workflow-page.tsx @@ -3,7 +3,7 @@ import { Bug, Loader2, Save } from "lucide-react"; import { DebugDrawer } from "@/components/assistant-editor/debug-preview"; -import { DynamicVariablesDialog } from "@/components/assistant-editor/dynamic-variables"; +import { DynamicVariablesPanel } from "@/components/assistant-editor/dynamic-variables"; import { AssistantIdentity, EditableTitle, @@ -115,6 +115,7 @@ export function WorkflowPage({ disabled={!assistantId} onClick={() => { setWorkflowSettingsOpen(false); + setDynamicVariablesOpen(false); setWorkflowEditingNodeId(null); setWorkflowEditingEdgeId(null); setWorkflowDebugOpen(true); @@ -144,7 +145,14 @@ export function WorkflowPage({ onChange={setWorkflowGraph} settings={workflowSettings} onSettingsChange={setWorkflowSettings} - onOpenDynamicVariables={() => setDynamicVariablesOpen(true)} + dynamicVariablesOpen={dynamicVariablesOpen} + onDynamicVariablesOpenChange={setDynamicVariablesOpen} + dynamicVariablesPanel={ + + } editingNodeId={workflowEditingNodeId} onEditingNodeIdChange={setWorkflowEditingNodeId} editingEdgeId={workflowEditingEdgeId} @@ -179,13 +187,6 @@ export function WorkflowPage({ knowledgeOptions={kbOptions} /> - - ); } diff --git a/frontend/src/components/workflow/WorkflowCanvas.tsx b/frontend/src/components/workflow/WorkflowCanvas.tsx index f256a4a..4e5e867 100644 --- a/frontend/src/components/workflow/WorkflowCanvas.tsx +++ b/frontend/src/components/workflow/WorkflowCanvas.tsx @@ -153,7 +153,9 @@ export function WorkflowCanvas({ onSettingsChange, modelOptions, activeNodeId, - onOpenDynamicVariables, + dynamicVariablesOpen, + onDynamicVariablesOpenChange, + dynamicVariablesPanel, editingNodeId, onEditingNodeIdChange, editingEdgeId, @@ -288,6 +290,7 @@ export function WorkflowCanvas({ setAddSourceId(null); setAddPosition(null); setSettingsOpen(false); + onDynamicVariablesOpenChange(false); onDebugOpenChange(false); onEditingEdgeIdChange(null); onEditingNodeIdChange(id); @@ -297,6 +300,7 @@ export function WorkflowCanvas({ addSourceId, nodes, onDebugOpenChange, + onDynamicVariablesOpenChange, onEditingEdgeIdChange, onEditingNodeIdChange, screenToFlowPosition, @@ -456,11 +460,13 @@ export function WorkflowCanvas({ ); const openSettings = useCallback(() => { onDebugOpenChange(false); + onDynamicVariablesOpenChange(false); onEditingNodeIdChange(null); onEditingEdgeIdChange(null); setSettingsOpen(true); }, [ onDebugOpenChange, + onDynamicVariablesOpenChange, onEditingEdgeIdChange, onEditingNodeIdChange, setSettingsOpen, @@ -470,6 +476,7 @@ export function WorkflowCanvas({ () => ({ edit: (id: string) => { setSettingsOpen(false); + onDynamicVariablesOpenChange(false); onDebugOpenChange(false); onEditingEdgeIdChange(null); onEditingNodeIdChange(id); @@ -481,6 +488,7 @@ export function WorkflowCanvas({ deleteNode, duplicateNode, onDebugOpenChange, + onDynamicVariablesOpenChange, onEditingEdgeIdChange, onEditingNodeIdChange, setSettingsOpen, @@ -490,6 +498,7 @@ export function WorkflowCanvas({ () => ({ edit: (id: string) => { setSettingsOpen(false); + onDynamicVariablesOpenChange(false); onDebugOpenChange(false); onEditingNodeIdChange(null); onEditingEdgeIdChange(id); @@ -499,11 +508,25 @@ export function WorkflowCanvas({ [ deleteEdge, onDebugOpenChange, + onDynamicVariablesOpenChange, onEditingEdgeIdChange, onEditingNodeIdChange, setSettingsOpen, ], ); + const openDynamicVariables = useCallback(() => { + setSettingsOpen(false); + onDebugOpenChange(false); + onEditingNodeIdChange(null); + onEditingEdgeIdChange(null); + onDynamicVariablesOpenChange(true); + }, [ + onDebugOpenChange, + onDynamicVariablesOpenChange, + onEditingEdgeIdChange, + onEditingNodeIdChange, + setSettingsOpen, + ]); const editingNode = nodes.find((n) => n.id === editingNodeId); const editingSpec = editingNode ? specsByType[editingNode.type as string] : null; @@ -580,6 +603,7 @@ export function WorkflowCanvas({ className="h-10 w-10 rounded-full shadow-sm" aria-label="添加节点" onClick={() => { + onDynamicVariablesOpenChange(false); setAddSourceId(null); setAddPosition(null); setAddOpen(true); @@ -613,7 +637,7 @@ export function WorkflowCanvas({ variant="outline" className="h-10 w-10 rounded-full border-hairline-strong bg-card text-foreground shadow-sm hover:bg-surface-strong" aria-label="动态变量" - onClick={onOpenDynamicVariables} + onClick={openDynamicVariables} > @@ -642,6 +666,7 @@ export function WorkflowCanvas({ /> {(debugOpen || + dynamicVariablesOpen || settingsOpen || (editingNode && editingSpec) || editingEdge) && ( @@ -649,24 +674,30 @@ export function WorkflowCanvas({ title={ debugOpen ? undefined - : settingsOpen - ? "工作流设置" - : editingEdge - ? "编辑连接条件" - : `编辑${editingSpec?.displayName ?? "节点"}` + : dynamicVariablesOpen + ? "动态变量" + : settingsOpen + ? "工作流设置" + : editingEdge + ? "编辑连接条件" + : `编辑${editingSpec?.displayName ?? "节点"}` } closeLabel={ - settingsOpen - ? "关闭工作流设置" - : editingEdge - ? "关闭边编辑" - : "关闭节点编辑" + dynamicVariablesOpen + ? "关闭动态变量" + : settingsOpen + ? "关闭工作流设置" + : editingEdge + ? "关闭边编辑" + : "关闭节点编辑" } onClose={ debugOpen ? undefined : () => { - if (settingsOpen) setSettingsOpen(false); + if (dynamicVariablesOpen) { + onDynamicVariablesOpenChange(false); + } else if (settingsOpen) setSettingsOpen(false); else if (editingEdge) onEditingEdgeIdChange(null); else onEditingNodeIdChange(null); } @@ -674,6 +705,8 @@ export function WorkflowCanvas({ > {debugOpen ? ( debugPanel + ) : dynamicVariablesOpen ? ( + dynamicVariablesPanel ) : (
{settingsOpen ? ( diff --git a/frontend/src/components/workflow/types.ts b/frontend/src/components/workflow/types.ts index e31ebde..2254b94 100644 --- a/frontend/src/components/workflow/types.ts +++ b/frontend/src/components/workflow/types.ts @@ -33,7 +33,9 @@ export type WorkflowEditorProps = { }; toolOptions?: ModelOption[]; knowledgeOptions?: ModelOption[]; - onOpenDynamicVariables: () => void; + dynamicVariablesOpen: boolean; + onDynamicVariablesOpenChange: (open: boolean) => void; + dynamicVariablesPanel: ReactNode; editingNodeId: string | null; onEditingNodeIdChange: (nodeId: string | null) => void; editingEdgeId: string | null;