From 7407884bae298c77551059ef0fb6b7f88479c0ca Mon Sep 17 00:00:00 2001 From: gchust Date: Thu, 26 Jun 2025 09:24:12 +0800 Subject: [PATCH] feat: add extralToolbarItems support to FlowsFloatContextMenu and FlowModelRenderer --- .../src/components/FlowModelRenderer.tsx | 27 ++++++++++++++++- .../contextual/FlowsFloatContextMenu.tsx | 30 +++++++++++++++++-- 2 files changed, 54 insertions(+), 3 deletions(-) diff --git a/packages/core/flow-engine/src/components/FlowModelRenderer.tsx b/packages/core/flow-engine/src/components/FlowModelRenderer.tsx index 8a479ce894..f027b4d66d 100644 --- a/packages/core/flow-engine/src/components/FlowModelRenderer.tsx +++ b/packages/core/flow-engine/src/components/FlowModelRenderer.tsx @@ -42,6 +42,7 @@ import React, { Suspense, useEffect } from 'react'; import { ErrorBoundary } from 'react-error-boundary'; import { useApplyAutoFlows, FlowModelProvider } from '../hooks'; import { FlowModel } from '../models'; +import { ToolbarItemConfig } from '../types'; import { FlowsContextMenu } from './settings/wrappers/contextual/FlowsContextMenu'; import { FlowsFloatContextMenu } from './settings/wrappers/contextual/FlowsFloatContextMenu'; import { FlowErrorFallback } from './FlowErrorFallback'; @@ -75,6 +76,9 @@ interface FlowModelRendererProps { /** 设置菜单层级:1=仅当前模型(默认),2=包含子模型 */ settingsMenuLevel?: number; + + /** 额外的工具栏项目,仅应用于此实例 */ + extralToolbarItems?: ToolbarItemConfig[]; } /** @@ -89,6 +93,7 @@ const FlowModelRendererWithAutoFlows: React.FC<{ sharedContext?: Record; showErrorFallback?: boolean; settingsMenuLevel?: number; + extralToolbarItems?: ToolbarItemConfig[]; }> = observer( ({ model, @@ -99,6 +104,7 @@ const FlowModelRendererWithAutoFlows: React.FC<{ sharedContext, showErrorFallback, settingsMenuLevel, + extralToolbarItems, }) => { useApplyAutoFlows(model, extraContext); @@ -111,6 +117,7 @@ const FlowModelRendererWithAutoFlows: React.FC<{ hideRemoveInSettings={hideRemoveInSettings} showErrorFallback={showErrorFallback} settingsMenuLevel={settingsMenuLevel} + extralToolbarItems={extralToolbarItems} /> ); @@ -128,6 +135,7 @@ const FlowModelRendererWithoutAutoFlows: React.FC<{ sharedContext?: Record; showErrorFallback?: boolean; settingsMenuLevel?: number; + extralToolbarItems?: ToolbarItemConfig[]; }> = observer( ({ model, @@ -137,6 +145,7 @@ const FlowModelRendererWithoutAutoFlows: React.FC<{ sharedContext, showErrorFallback, settingsMenuLevel, + extralToolbarItems, }) => { return ( @@ -147,6 +156,7 @@ const FlowModelRendererWithoutAutoFlows: React.FC<{ hideRemoveInSettings={hideRemoveInSettings} showErrorFallback={showErrorFallback} settingsMenuLevel={settingsMenuLevel} + extralToolbarItems={extralToolbarItems} /> ); @@ -163,8 +173,17 @@ const FlowModelRendererCore: React.FC<{ hideRemoveInSettings: boolean; showErrorFallback?: boolean; settingsMenuLevel?: number; + extralToolbarItems?: ToolbarItemConfig[]; }> = observer( - ({ model, showFlowSettings, flowSettingsVariant, hideRemoveInSettings, showErrorFallback, settingsMenuLevel }) => { + ({ + model, + showFlowSettings, + flowSettingsVariant, + hideRemoveInSettings, + showErrorFallback, + settingsMenuLevel, + extralToolbarItems, + }) => { // 渲染模型内容 const modelContent = model.render(); @@ -191,6 +210,7 @@ const FlowModelRendererCore: React.FC<{ showBackground={_.isObject(showFlowSettings) ? showFlowSettings.showBackground : undefined} showBorder={_.isObject(showFlowSettings) ? showFlowSettings.showBorder : undefined} settingsMenuLevel={settingsMenuLevel} + extralToolbarItems={extralToolbarItems} > {wrapWithErrorBoundary(modelContent)} @@ -224,6 +244,7 @@ const FlowModelRendererCore: React.FC<{ showBackground={_.isObject(showFlowSettings) ? showFlowSettings.showBackground : undefined} showBorder={_.isObject(showFlowSettings) ? showFlowSettings.showBorder : undefined} settingsMenuLevel={settingsMenuLevel} + extralToolbarItems={extralToolbarItems} > {wrapWithErrorBoundary(modelContent)} @@ -246,6 +267,7 @@ const FlowModelRendererCore: React.FC<{ * @param {any} props.extraContext - Extra context to pass to useApplyAutoFlows when skipApplyAutoFlows is false. * @param {any} props.sharedContext - Shared context to pass to the model. * @param {number} props.settingsMenuLevel - Settings menu levels: 1=current model only (default), 2=include sub-models. + * @param {ToolbarItemConfig[]} props.extralToolbarItems - Extra toolbar items to add to this renderer instance. * @returns {React.ReactNode | null} The rendered output of the model, or null if the model or its render method is invalid. */ export const FlowModelRenderer: React.FC = observer( @@ -260,6 +282,7 @@ export const FlowModelRenderer: React.FC = observer( sharedContext, showErrorFallback = false, settingsMenuLevel, + extralToolbarItems, }) => { if (!model || typeof model.render !== 'function') { // 可以选择渲染 null 或者一个错误/提示信息 @@ -283,6 +306,7 @@ export const FlowModelRenderer: React.FC = observer( sharedContext={sharedContext} showErrorFallback={showErrorFallback} settingsMenuLevel={settingsMenuLevel} + extralToolbarItems={extralToolbarItems} /> ); @@ -298,6 +322,7 @@ export const FlowModelRenderer: React.FC = observer( sharedContext={sharedContext} showErrorFallback={showErrorFallback} settingsMenuLevel={settingsMenuLevel} + extralToolbarItems={extralToolbarItems} /> ); diff --git a/packages/core/flow-engine/src/components/settings/wrappers/contextual/FlowsFloatContextMenu.tsx b/packages/core/flow-engine/src/components/settings/wrappers/contextual/FlowsFloatContextMenu.tsx index 818c5b011e..75589b75f8 100644 --- a/packages/core/flow-engine/src/components/settings/wrappers/contextual/FlowsFloatContextMenu.tsx +++ b/packages/core/flow-engine/src/components/settings/wrappers/contextual/FlowsFloatContextMenu.tsx @@ -41,10 +41,17 @@ const renderToolbarItems = ( showCopyUidButton: boolean, flowEngine: FlowEngine, settingsMenuLevel?: number, + extralToolbarItems?: ToolbarItemConfig[], ) => { const toolbarItems = flowEngine?.flowSettings?.getToolbarItems?.() || []; - return toolbarItems + // 合并额外的工具栏项目 + const allToolbarItems = [...toolbarItems, ...(extralToolbarItems || [])]; + + // 按 sort 字段排序 + allToolbarItems.sort((a, b) => (a.sort || 0) - (b.sort || 0)).reverse(); + + return allToolbarItems .filter((itemConfig: ToolbarItemConfig) => { // 检查项目是否应该显示 return itemConfig.visible ? itemConfig.visible(model) : true; @@ -150,6 +157,10 @@ interface ModelProvidedProps { * Settings menu levels: 1=current model only (default), 2=include sub-models */ settingsMenuLevel?: number; + /** + * Extra toolbar items to add to this context menu instance + */ + extralToolbarItems?: ToolbarItemConfig[]; } interface ModelByIdProps { @@ -173,6 +184,10 @@ interface ModelByIdProps { * Settings menu levels: 1=current model only (default), 2=include sub-models */ settingsMenuLevel?: number; + /** + * Extra toolbar items to add to this context menu instance + */ + extralToolbarItems?: ToolbarItemConfig[]; } type FlowsFloatContextMenuProps = ModelProvidedProps | ModelByIdProps; @@ -204,6 +219,7 @@ const isModelByIdProps = (props: FlowsFloatContextMenuProps): props is ModelById * @param props.containerStyle 容器自定义样式 * @param props.className 容器自定义类名 * @param props.settingsMenuLevel 设置菜单层级:1=仅当前模型(默认),2=包含子模型 + * @param props.extralToolbarItems 额外的工具栏项目,仅应用于此实例 */ const FlowsFloatContextMenu: React.FC = observer((props) => { const flowEngine = useFlowEngine(); @@ -231,6 +247,7 @@ const FlowsFloatContextMenuWithModel: React.FC = observer( showBackground = true, showBorder = true, settingsMenuLevel, + extralToolbarItems, }: ModelProvidedProps) => { const [hideMenu, setHideMenu] = useState(false); const [hasButton, setHasButton] = useState(false); @@ -305,7 +322,14 @@ const FlowsFloatContextMenuWithModel: React.FC = observer(
- {renderToolbarItems(model, showDeleteButton, showCopyUidButton, flowEngine, settingsMenuLevel)} + {renderToolbarItems( + model, + showDeleteButton, + showCopyUidButton, + flowEngine, + settingsMenuLevel, + extralToolbarItems, + )}
@@ -326,6 +350,7 @@ const FlowsFloatContextMenuWithModelById: React.FC = observer( containerStyle, className, settingsMenuLevel, + extralToolbarItems, }) => { const model = useFlowModelById(uid, modelClassName); @@ -342,6 +367,7 @@ const FlowsFloatContextMenuWithModelById: React.FC = observer( containerStyle={containerStyle} className={className} settingsMenuLevel={settingsMenuLevel} + extralToolbarItems={extralToolbarItems} > {children}