@nocobase/flow-engine 2.0.0-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +661 -0
- package/README.md +30 -0
- package/lib/ContextPathProxy.d.ts +17 -0
- package/lib/ContextPathProxy.js +65 -0
- package/lib/ElementProxy.d.ts +17 -0
- package/lib/ElementProxy.js +93 -0
- package/lib/FlowContextProvider.d.ts +24 -0
- package/lib/FlowContextProvider.js +82 -0
- package/lib/FlowDefinition.d.ts +423 -0
- package/lib/FlowDefinition.js +257 -0
- package/lib/JSRunner.d.ts +32 -0
- package/lib/JSRunner.js +95 -0
- package/lib/ReactView.d.ts +20 -0
- package/lib/ReactView.js +120 -0
- package/lib/ViewScopedFlowEngine.d.ts +23 -0
- package/lib/ViewScopedFlowEngine.js +81 -0
- package/lib/acl/Acl.d.ts +31 -0
- package/lib/acl/Acl.js +115 -0
- package/lib/action-registry/BaseActionRegistry.d.ts +23 -0
- package/lib/action-registry/BaseActionRegistry.js +57 -0
- package/lib/action-registry/EngineActionRegistry.d.ts +20 -0
- package/lib/action-registry/EngineActionRegistry.js +47 -0
- package/lib/action-registry/ModelActionRegistry.d.ts +34 -0
- package/lib/action-registry/ModelActionRegistry.js +79 -0
- package/lib/components/DynamicFlowsEditor.d.ts +17 -0
- package/lib/components/DynamicFlowsEditor.js +49 -0
- package/lib/components/FieldModelRenderer.d.ts +10 -0
- package/lib/components/FieldModelRenderer.js +94 -0
- package/lib/components/FlowContextSelector.d.ts +11 -0
- package/lib/components/FlowContextSelector.js +221 -0
- package/lib/components/FlowErrorFallback.d.ts +25 -0
- package/lib/components/FlowErrorFallback.js +264 -0
- package/lib/components/FlowModelRenderer.d.ts +64 -0
- package/lib/components/FlowModelRenderer.js +254 -0
- package/lib/components/FormItem.d.ts +18 -0
- package/lib/components/FormItem.js +147 -0
- package/lib/components/common/FlowSettingsButton.d.ts +11 -0
- package/lib/components/common/FlowSettingsButton.js +66 -0
- package/lib/components/common/index.d.ts +9 -0
- package/lib/components/common/index.js +30 -0
- package/lib/components/common/withFlowDesignMode.d.ts +26 -0
- package/lib/components/common/withFlowDesignMode.js +61 -0
- package/lib/components/dnd/getMousePositionOnElement.d.ts +50 -0
- package/lib/components/dnd/getMousePositionOnElement.js +95 -0
- package/lib/components/dnd/index.d.ts +24 -0
- package/lib/components/dnd/index.js +164 -0
- package/lib/components/dnd/moveBlock.d.ts +33 -0
- package/lib/components/dnd/moveBlock.js +302 -0
- package/lib/components/index.d.ts +18 -0
- package/lib/components/index.js +48 -0
- package/lib/components/settings/independents/dropdown/FlowsDropdownButton.d.ts +46 -0
- package/lib/components/settings/independents/dropdown/FlowsDropdownButton.js +225 -0
- package/lib/components/settings/independents/dropdown/index.d.ts +9 -0
- package/lib/components/settings/independents/dropdown/index.js +30 -0
- package/lib/components/settings/independents/index.d.ts +1 -0
- package/lib/components/settings/independents/index.js +30 -0
- package/lib/components/settings/index.d.ts +10 -0
- package/lib/components/settings/index.js +32 -0
- package/lib/components/settings/wrappers/contextual/DefaultSettingsIcon.d.ts +24 -0
- package/lib/components/settings/wrappers/contextual/DefaultSettingsIcon.js +501 -0
- package/lib/components/settings/wrappers/contextual/FlowsContextMenu.d.ts +45 -0
- package/lib/components/settings/wrappers/contextual/FlowsContextMenu.js +231 -0
- package/lib/components/settings/wrappers/contextual/FlowsFloatContextMenu.d.ts +111 -0
- package/lib/components/settings/wrappers/contextual/FlowsFloatContextMenu.js +484 -0
- package/lib/components/settings/wrappers/contextual/StepRequiredSettingsDialog.d.ts +26 -0
- package/lib/components/settings/wrappers/contextual/StepRequiredSettingsDialog.js +342 -0
- package/lib/components/settings/wrappers/contextual/StepSettings.d.ts +23 -0
- package/lib/components/settings/wrappers/contextual/StepSettings.js +110 -0
- package/lib/components/settings/wrappers/contextual/StepSettingsDialog.d.ts +20 -0
- package/lib/components/settings/wrappers/contextual/StepSettingsDialog.js +206 -0
- package/lib/components/settings/wrappers/contextual/StepSettingsDrawer.d.ts +20 -0
- package/lib/components/settings/wrappers/contextual/StepSettingsDrawer.js +47 -0
- package/lib/components/settings/wrappers/contextual/index.d.ts +14 -0
- package/lib/components/settings/wrappers/contextual/index.js +40 -0
- package/lib/components/settings/wrappers/embedded/FlowSettings.d.ts +33 -0
- package/lib/components/settings/wrappers/embedded/FlowSettings.js +207 -0
- package/lib/components/settings/wrappers/embedded/FlowsSettings.d.ts +41 -0
- package/lib/components/settings/wrappers/embedded/FlowsSettings.js +84 -0
- package/lib/components/settings/wrappers/embedded/FlowsSettingsContent.d.ts +16 -0
- package/lib/components/settings/wrappers/embedded/FlowsSettingsContent.js +88 -0
- package/lib/components/settings/wrappers/embedded/index.d.ts +10 -0
- package/lib/components/settings/wrappers/embedded/index.js +32 -0
- package/lib/components/settings/wrappers/index.d.ts +2 -0
- package/lib/components/settings/wrappers/index.js +32 -0
- package/lib/components/subModel/AddSubModelButton.d.ts +62 -0
- package/lib/components/subModel/AddSubModelButton.js +415 -0
- package/lib/components/subModel/LazyDropdown.d.ts +55 -0
- package/lib/components/subModel/LazyDropdown.js +524 -0
- package/lib/components/subModel/index.d.ts +10 -0
- package/lib/components/subModel/index.js +32 -0
- package/lib/components/subModel/utils.d.ts +34 -0
- package/lib/components/subModel/utils.js +287 -0
- package/lib/components/variables/InlineVariableTag.d.ts +21 -0
- package/lib/components/variables/InlineVariableTag.js +123 -0
- package/lib/components/variables/SlateVariableEditor.d.ts +46 -0
- package/lib/components/variables/SlateVariableEditor.js +302 -0
- package/lib/components/variables/VariableInput.d.ts +11 -0
- package/lib/components/variables/VariableInput.js +322 -0
- package/lib/components/variables/VariableTag.d.ts +11 -0
- package/lib/components/variables/VariableTag.js +148 -0
- package/lib/components/variables/VariableTrigger.d.ts +20 -0
- package/lib/components/variables/VariableTrigger.js +136 -0
- package/lib/components/variables/index.d.ts +15 -0
- package/lib/components/variables/index.js +53 -0
- package/lib/components/variables/types.d.ts +93 -0
- package/lib/components/variables/types.js +24 -0
- package/lib/components/variables/useResolvedMetaTree.d.ts +19 -0
- package/lib/components/variables/useResolvedMetaTree.js +91 -0
- package/lib/components/variables/utils.d.ts +22 -0
- package/lib/components/variables/utils.js +177 -0
- package/lib/data-source/index.d.ts +180 -0
- package/lib/data-source/index.js +733 -0
- package/lib/data-source/jioToJoiSchema.d.ts +19 -0
- package/lib/data-source/jioToJoiSchema.js +114 -0
- package/lib/decorators/index.d.ts +9 -0
- package/lib/decorators/index.js +36 -0
- package/lib/decorators/largeField.d.ts +9 -0
- package/lib/decorators/largeField.js +42 -0
- package/lib/emitter.d.ts +16 -0
- package/lib/emitter.js +58 -0
- package/lib/event-registry/BaseEventRegistry.d.ts +22 -0
- package/lib/event-registry/BaseEventRegistry.js +57 -0
- package/lib/event-registry/EngineEventRegistry.d.ts +19 -0
- package/lib/event-registry/EngineEventRegistry.js +47 -0
- package/lib/event-registry/ModelEventRegistry.d.ts +33 -0
- package/lib/event-registry/ModelEventRegistry.js +79 -0
- package/lib/executor/FlowExecutor.d.ts +26 -0
- package/lib/executor/FlowExecutor.js +262 -0
- package/lib/flow-registry/BaseFlowRegistry.d.ts +46 -0
- package/lib/flow-registry/BaseFlowRegistry.js +86 -0
- package/lib/flow-registry/GlobalFlowRegistry.d.ts +22 -0
- package/lib/flow-registry/GlobalFlowRegistry.js +95 -0
- package/lib/flow-registry/InstanceFlowRegistry.d.ts +21 -0
- package/lib/flow-registry/InstanceFlowRegistry.js +59 -0
- package/lib/flow-registry/index.d.ts +11 -0
- package/lib/flow-registry/index.js +34 -0
- package/lib/flowContext.d.ts +215 -0
- package/lib/flowContext.js +1266 -0
- package/lib/flowEngine.d.ts +340 -0
- package/lib/flowEngine.js +781 -0
- package/lib/flowI18n.d.ts +46 -0
- package/lib/flowI18n.js +117 -0
- package/lib/flowSettings.d.ts +266 -0
- package/lib/flowSettings.js +850 -0
- package/lib/hooks/index.d.ts +14 -0
- package/lib/hooks/index.js +40 -0
- package/lib/hooks/useApplyAutoFlows.d.ts +21 -0
- package/lib/hooks/useApplyAutoFlows.js +62 -0
- package/lib/hooks/useFlowModel.d.ts +29 -0
- package/lib/hooks/useFlowModel.js +72 -0
- package/lib/hooks/useFlowModelById.d.ts +11 -0
- package/lib/hooks/useFlowModelById.js +61 -0
- package/lib/hooks/useFlowSettingsContext.d.ts +20 -0
- package/lib/hooks/useFlowSettingsContext.js +61 -0
- package/lib/hooks/useFlowStep.d.ts +17 -0
- package/lib/hooks/useFlowStep.js +56 -0
- package/lib/hooks/useNiceDropdownMaxHeight.d.ts +13 -0
- package/lib/hooks/useNiceDropdownMaxHeight.js +52 -0
- package/lib/index.d.ts +27 -0
- package/lib/index.js +73 -0
- package/lib/locale/en-US.json +61 -0
- package/lib/locale/index.d.ts +141 -0
- package/lib/locale/index.js +70 -0
- package/lib/locale/zh-CN.json +61 -0
- package/lib/models/CollectionFieldModel.d.ts +50 -0
- package/lib/models/CollectionFieldModel.js +242 -0
- package/lib/models/DisplayItemModel.d.ts +12 -0
- package/lib/models/DisplayItemModel.js +41 -0
- package/lib/models/EditableItemModel.d.ts +12 -0
- package/lib/models/EditableItemModel.js +41 -0
- package/lib/models/FilterableItemModel.d.ts +12 -0
- package/lib/models/FilterableItemModel.js +41 -0
- package/lib/models/flowModel.d.ts +344 -0
- package/lib/models/flowModel.js +1133 -0
- package/lib/models/forkFlowModel.d.ts +83 -0
- package/lib/models/forkFlowModel.js +257 -0
- package/lib/models/index.d.ts +14 -0
- package/lib/models/index.js +40 -0
- package/lib/provider.d.ts +22 -0
- package/lib/provider.js +114 -0
- package/lib/resources/apiResource.d.ts +34 -0
- package/lib/resources/apiResource.js +153 -0
- package/lib/resources/baseRecordResource.d.ts +61 -0
- package/lib/resources/baseRecordResource.js +264 -0
- package/lib/resources/filterItem.d.ts +33 -0
- package/lib/resources/filterItem.js +93 -0
- package/lib/resources/flowResource.d.ts +45 -0
- package/lib/resources/flowResource.js +146 -0
- package/lib/resources/index.d.ts +15 -0
- package/lib/resources/index.js +42 -0
- package/lib/resources/multiRecordResource.d.ts +53 -0
- package/lib/resources/multiRecordResource.js +230 -0
- package/lib/resources/singleRecordResource.d.ts +23 -0
- package/lib/resources/singleRecordResource.js +111 -0
- package/lib/resources/sqlResource.d.ts +73 -0
- package/lib/resources/sqlResource.js +294 -0
- package/lib/runjs-context/contexts/FlowRunJSContext.d.ts +38 -0
- package/lib/runjs-context/contexts/FlowRunJSContext.js +217 -0
- package/lib/runjs-context/contexts/FormJSFieldItemRunJSContext.d.ts +16 -0
- package/lib/runjs-context/contexts/FormJSFieldItemRunJSContext.js +66 -0
- package/lib/runjs-context/contexts/JSBlockRunJSContext.d.ts +16 -0
- package/lib/runjs-context/contexts/JSBlockRunJSContext.js +78 -0
- package/lib/runjs-context/contexts/JSCollectionActionRunJSContext.d.ts +12 -0
- package/lib/runjs-context/contexts/JSCollectionActionRunJSContext.js +59 -0
- package/lib/runjs-context/contexts/JSFieldRunJSContext.d.ts +16 -0
- package/lib/runjs-context/contexts/JSFieldRunJSContext.js +70 -0
- package/lib/runjs-context/contexts/JSItemRunJSContext.d.ts +16 -0
- package/lib/runjs-context/contexts/JSItemRunJSContext.js +66 -0
- package/lib/runjs-context/contexts/JSRecordActionRunJSContext.d.ts +12 -0
- package/lib/runjs-context/contexts/JSRecordActionRunJSContext.js +61 -0
- package/lib/runjs-context/contexts/LinkageRunJSContext.d.ts +12 -0
- package/lib/runjs-context/contexts/LinkageRunJSContext.js +62 -0
- package/lib/runjs-context/helpers.d.ts +17 -0
- package/lib/runjs-context/helpers.js +79 -0
- package/lib/runjs-context/index.d.ts +19 -0
- package/lib/runjs-context/index.js +57 -0
- package/lib/runjs-context/registry.d.ts +17 -0
- package/lib/runjs-context/registry.js +93 -0
- package/lib/runjs-context/snippets/global/api-request-get.snippet.d.ts +16 -0
- package/lib/runjs-context/snippets/global/api-request-get.snippet.js +42 -0
- package/lib/runjs-context/snippets/global/api-request-post.snippet.d.ts +16 -0
- package/lib/runjs-context/snippets/global/api-request-post.snippet.js +42 -0
- package/lib/runjs-context/snippets/global/console-log-ctx.snippet.d.ts +16 -0
- package/lib/runjs-context/snippets/global/console-log-ctx.snippet.js +41 -0
- package/lib/runjs-context/snippets/global/copy-record-json.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/global/copy-record-json.snippet.js +42 -0
- package/lib/runjs-context/snippets/global/copy-to-clipboard.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/global/copy-to-clipboard.snippet.js +42 -0
- package/lib/runjs-context/snippets/global/log-json-record.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/global/log-json-record.snippet.js +42 -0
- package/lib/runjs-context/snippets/global/message-error.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/global/message-error.snippet.js +41 -0
- package/lib/runjs-context/snippets/global/message-success.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/global/message-success.snippet.js +41 -0
- package/lib/runjs-context/snippets/global/notification-open.snippet.d.ts +16 -0
- package/lib/runjs-context/snippets/global/notification-open.snippet.js +43 -0
- package/lib/runjs-context/snippets/global/open-view-dialog.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/global/open-view-dialog.snippet.js +47 -0
- package/lib/runjs-context/snippets/global/open-view-drawer.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/global/open-view-drawer.snippet.js +47 -0
- package/lib/runjs-context/snippets/global/requireAsync.snippet.d.ts +16 -0
- package/lib/runjs-context/snippets/global/requireAsync.snippet.js +46 -0
- package/lib/runjs-context/snippets/global/sleep.snippet.d.ts +16 -0
- package/lib/runjs-context/snippets/global/sleep.snippet.js +43 -0
- package/lib/runjs-context/snippets/global/try-catch-async.snippet.d.ts +16 -0
- package/lib/runjs-context/snippets/global/try-catch-async.snippet.js +44 -0
- package/lib/runjs-context/snippets/global/view-navigation-push.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/global/view-navigation-push.snippet.js +44 -0
- package/lib/runjs-context/snippets/global/window-open.snippet.d.ts +16 -0
- package/lib/runjs-context/snippets/global/window-open.snippet.js +41 -0
- package/lib/runjs-context/snippets/index.d.ts +11 -0
- package/lib/runjs-context/snippets/index.js +94 -0
- package/lib/runjs-context/snippets/libs/echarts-init.snippet.d.ts +15 -0
- package/lib/runjs-context/snippets/libs/echarts-init.snippet.js +46 -0
- package/lib/runjs-context/snippets/scene/actions/collection-selected-count.snippet.d.ts +15 -0
- package/lib/runjs-context/snippets/scene/actions/collection-selected-count.snippet.js +44 -0
- package/lib/runjs-context/snippets/scene/actions/iterate-selected-rows.snippet.d.ts +15 -0
- package/lib/runjs-context/snippets/scene/actions/iterate-selected-rows.snippet.js +43 -0
- package/lib/runjs-context/snippets/scene/actions/record-id-message.snippet.d.ts +15 -0
- package/lib/runjs-context/snippets/scene/actions/record-id-message.snippet.js +43 -0
- package/lib/runjs-context/snippets/scene/actions/run-action-basic.snippet.d.ts +15 -0
- package/lib/runjs-context/snippets/scene/actions/run-action-basic.snippet.js +40 -0
- package/lib/runjs-context/snippets/scene/jsblock/add-event-listener.snippet.d.ts +15 -0
- package/lib/runjs-context/snippets/scene/jsblock/add-event-listener.snippet.js +46 -0
- package/lib/runjs-context/snippets/scene/jsblock/append-style.snippet.d.ts +15 -0
- package/lib/runjs-context/snippets/scene/jsblock/append-style.snippet.js +42 -0
- package/lib/runjs-context/snippets/scene/jsblock/jsx-mount.snippet.d.ts +15 -0
- package/lib/runjs-context/snippets/scene/jsblock/jsx-mount.snippet.js +46 -0
- package/lib/runjs-context/snippets/scene/jsblock/jsx-unmount.snippet.d.ts +15 -0
- package/lib/runjs-context/snippets/scene/jsblock/jsx-unmount.snippet.js +41 -0
- package/lib/runjs-context/snippets/scene/jsblock/render-basic.snippet.d.ts +15 -0
- package/lib/runjs-context/snippets/scene/jsblock/render-basic.snippet.js +41 -0
- package/lib/runjs-context/snippets/scene/jsblock/render-button-handler.snippet.d.ts +15 -0
- package/lib/runjs-context/snippets/scene/jsblock/render-button-handler.snippet.js +46 -0
- package/lib/runjs-context/snippets/scene/jsblock/render-card.snippet.d.ts +11 -0
- package/lib/runjs-context/snippets/scene/jsblock/render-card.snippet.js +45 -0
- package/lib/runjs-context/snippets/scene/jsblock/render-react.snippet.d.ts +15 -0
- package/lib/runjs-context/snippets/scene/jsblock/render-react.snippet.js +56 -0
- package/lib/runjs-context/snippets/scene/jsfield/color-by-value.snippet.d.ts +15 -0
- package/lib/runjs-context/snippets/scene/jsfield/color-by-value.snippet.js +42 -0
- package/lib/runjs-context/snippets/scene/jsfield/format-number.snippet.d.ts +15 -0
- package/lib/runjs-context/snippets/scene/jsfield/format-number.snippet.js +41 -0
- package/lib/runjs-context/snippets/scene/jsfield/innerHTML-value.snippet.d.ts +15 -0
- package/lib/runjs-context/snippets/scene/jsfield/innerHTML-value.snippet.js +40 -0
- package/lib/runjs-context/snippets/scene/jsitem/render-basic.snippet.d.ts +15 -0
- package/lib/runjs-context/snippets/scene/jsitem/render-basic.snippet.js +44 -0
- package/lib/runjs-context/snippets/scene/linkage/set-disabled.snippet.d.ts +15 -0
- package/lib/runjs-context/snippets/scene/linkage/set-disabled.snippet.js +60 -0
- package/lib/runjs-context/snippets/scene/linkage/set-field-value.snippet.d.ts +15 -0
- package/lib/runjs-context/snippets/scene/linkage/set-field-value.snippet.js +59 -0
- package/lib/runjs-context/snippets/scene/linkage/set-required.snippet.d.ts +15 -0
- package/lib/runjs-context/snippets/scene/linkage/set-required.snippet.js +60 -0
- package/lib/runjs-context/snippets/scene/linkage/toggle-visible.snippet.d.ts +15 -0
- package/lib/runjs-context/snippets/scene/linkage/toggle-visible.snippet.js +60 -0
- package/lib/runjs-context/snippets/types.d.ts +16 -0
- package/lib/runjs-context/snippets/types.js +24 -0
- package/lib/types.d.ts +398 -0
- package/lib/types.js +43 -0
- package/lib/utils/autoFlowError.d.ts +16 -0
- package/lib/utils/autoFlowError.js +53 -0
- package/lib/utils/constants.d.ts +29 -0
- package/lib/utils/constants.js +77 -0
- package/lib/utils/context.d.ts +40 -0
- package/lib/utils/context.js +63 -0
- package/lib/utils/createCollectionContextMeta.d.ts +11 -0
- package/lib/utils/createCollectionContextMeta.js +117 -0
- package/lib/utils/exceptions.d.ts +22 -0
- package/lib/utils/exceptions.js +62 -0
- package/lib/utils/flow-definitions.d.ts +11 -0
- package/lib/utils/flow-definitions.js +40 -0
- package/lib/utils/index.d.ts +22 -0
- package/lib/utils/index.js +117 -0
- package/lib/utils/inheritance.d.ts +16 -0
- package/lib/utils/inheritance.js +53 -0
- package/lib/utils/params-resolvers.d.ts +51 -0
- package/lib/utils/params-resolvers.js +309 -0
- package/lib/utils/parsePathnameToViewParams.d.ts +34 -0
- package/lib/utils/parsePathnameToViewParams.js +84 -0
- package/lib/utils/safeGlobals.d.ts +16 -0
- package/lib/utils/safeGlobals.js +179 -0
- package/lib/utils/schema-utils.d.ts +40 -0
- package/lib/utils/schema-utils.js +161 -0
- package/lib/utils/serverContextParams.d.ts +28 -0
- package/lib/utils/serverContextParams.js +106 -0
- package/lib/utils/setupRuntimeContextSteps.d.ts +19 -0
- package/lib/utils/setupRuntimeContextSteps.js +88 -0
- package/lib/utils/translation.d.ts +18 -0
- package/lib/utils/translation.js +58 -0
- package/lib/utils/variablesParams.d.ts +51 -0
- package/lib/utils/variablesParams.js +150 -0
- package/lib/views/DialogComponent.d.ts +22 -0
- package/lib/views/DialogComponent.js +98 -0
- package/lib/views/DrawerComponent.d.ts +11 -0
- package/lib/views/DrawerComponent.js +101 -0
- package/lib/views/FlowView.d.ts +76 -0
- package/lib/views/FlowView.js +81 -0
- package/lib/views/PageComponent.d.ts +10 -0
- package/lib/views/PageComponent.js +167 -0
- package/lib/views/ViewNavigation.d.ts +45 -0
- package/lib/views/ViewNavigation.js +97 -0
- package/lib/views/createViewMeta.d.ts +16 -0
- package/lib/views/createViewMeta.js +171 -0
- package/lib/views/index.d.ts +13 -0
- package/lib/views/index.js +48 -0
- package/lib/views/useDialog.d.ts +32 -0
- package/lib/views/useDialog.js +199 -0
- package/lib/views/useDrawer.d.ts +33 -0
- package/lib/views/useDrawer.js +206 -0
- package/lib/views/usePage.d.ts +32 -0
- package/lib/views/usePage.js +193 -0
- package/lib/views/usePatchElement.d.ts +10 -0
- package/lib/views/usePatchElement.js +54 -0
- package/lib/views/usePopover.d.ts +17 -0
- package/lib/views/usePopover.js +159 -0
- package/package.json +37 -0
- package/src/ContextPathProxy.ts +45 -0
- package/src/ElementProxy.ts +69 -0
- package/src/FlowContextProvider.tsx +40 -0
- package/src/FlowDefinition.ts +275 -0
- package/src/JSRunner.ts +84 -0
- package/src/ReactView.tsx +104 -0
- package/src/ViewScopedFlowEngine.ts +75 -0
- package/src/__tests__/ElementProxy.test.ts +51 -0
- package/src/__tests__/JSRunner.test.ts +92 -0
- package/src/__tests__/ReactView.test.tsx +63 -0
- package/src/__tests__/context-path-proxy.test.ts +35 -0
- package/src/__tests__/flow-engine.test.ts +189 -0
- package/src/__tests__/flowContext.test.ts +2012 -0
- package/src/__tests__/flowEngine.saveModel.test.ts +171 -0
- package/src/__tests__/flowI18n.test.ts +28 -0
- package/src/__tests__/flowModel.getFlows.test.ts +61 -0
- package/src/__tests__/flowModel.openView.navigation.test.ts +78 -0
- package/src/__tests__/flowRuntimeContext.test.ts +187 -0
- package/src/__tests__/flowSettings.open.test.tsx +1920 -0
- package/src/__tests__/flowSettings.test.ts +566 -0
- package/src/__tests__/globalFlowRegistry.test.ts +77 -0
- package/src/__tests__/isFieldInterfaceMatch.test.ts +51 -0
- package/src/__tests__/metaTreeNodeCache.test.ts +234 -0
- package/src/__tests__/path-aggregation.test.ts +85 -0
- package/src/__tests__/provider.test.tsx +28 -0
- package/src/__tests__/renderHiddenInConfig.test.tsx +91 -0
- package/src/__tests__/runjsContext.test.ts +60 -0
- package/src/__tests__/viewScopedFlowEngine.test.ts +212 -0
- package/src/acl/Acl.tsx +109 -0
- package/src/acl/__tests__/Acl.test.tsx +72 -0
- package/src/action-registry/BaseActionRegistry.ts +46 -0
- package/src/action-registry/EngineActionRegistry.ts +32 -0
- package/src/action-registry/ModelActionRegistry.ts +75 -0
- package/src/action-registry/__tests__/engineActionRegistry.test.ts +43 -0
- package/src/action-registry/__tests__/modelActionRegistry.test.ts +107 -0
- package/src/components/DynamicFlowsEditor.tsx +318 -0
- package/src/components/FieldModelRenderer.tsx +62 -0
- package/src/components/FlowContextSelector.tsx +255 -0
- package/src/components/FlowErrorFallback.tsx +316 -0
- package/src/components/FlowModelRenderer.tsx +428 -0
- package/src/components/FormItem.tsx +130 -0
- package/src/components/__tests__/flow-model-render-error-fallback.test.tsx +226 -0
- package/src/components/common/FlowSettingsButton.tsx +30 -0
- package/src/components/common/index.ts +10 -0
- package/src/components/common/withFlowDesignMode.tsx +49 -0
- package/src/components/dnd/getMousePositionOnElement.ts +115 -0
- package/src/components/dnd/index.tsx +128 -0
- package/src/components/dnd/moveBlock.ts +379 -0
- package/src/components/index.ts +20 -0
- package/src/components/settings/independents/dropdown/FlowsDropdownButton.tsx +279 -0
- package/src/components/settings/independents/dropdown/index.ts +10 -0
- package/src/components/settings/independents/index.ts +2 -0
- package/src/components/settings/index.ts +11 -0
- package/src/components/settings/wrappers/contextual/DefaultSettingsIcon.tsx +617 -0
- package/src/components/settings/wrappers/contextual/FlowsContextMenu.tsx +292 -0
- package/src/components/settings/wrappers/contextual/FlowsFloatContextMenu.tsx +655 -0
- package/src/components/settings/wrappers/contextual/StepRequiredSettingsDialog.tsx +446 -0
- package/src/components/settings/wrappers/contextual/StepSettings.tsx +109 -0
- package/src/components/settings/wrappers/contextual/StepSettingsDialog.tsx +217 -0
- package/src/components/settings/wrappers/contextual/StepSettingsDrawer.tsx +32 -0
- package/src/components/settings/wrappers/contextual/index.ts +15 -0
- package/src/components/settings/wrappers/embedded/FlowSettings.tsx +258 -0
- package/src/components/settings/wrappers/embedded/FlowsSettings.tsx +111 -0
- package/src/components/settings/wrappers/embedded/FlowsSettingsContent.tsx +96 -0
- package/src/components/settings/wrappers/embedded/index.ts +11 -0
- package/src/components/settings/wrappers/index.ts +5 -0
- package/src/components/subModel/AddSubModelButton.tsx +575 -0
- package/src/components/subModel/LazyDropdown.tsx +714 -0
- package/src/components/subModel/__tests__/AddSubModelButton.test.tsx +1185 -0
- package/src/components/subModel/__tests__/buildWrapperFieldChildren.test.ts +192 -0
- package/src/components/subModel/__tests__/utils.test.ts +425 -0
- package/src/components/subModel/index.ts +12 -0
- package/src/components/subModel/utils.ts +278 -0
- package/src/components/variables/InlineVariableTag.tsx +97 -0
- package/src/components/variables/SlateVariableEditor.tsx +384 -0
- package/src/components/variables/VariableInput.tsx +342 -0
- package/src/components/variables/VariableTag.tsx +123 -0
- package/src/components/variables/VariableTrigger.tsx +116 -0
- package/src/components/variables/__tests__/FlowContextSelector.test.tsx +553 -0
- package/src/components/variables/__tests__/VariableInput.test.tsx +550 -0
- package/src/components/variables/__tests__/VariableTag.test.tsx +347 -0
- package/src/components/variables/__tests__/test-utils.tsx +62 -0
- package/src/components/variables/__tests__/utils.test.ts +310 -0
- package/src/components/variables/index.ts +16 -0
- package/src/components/variables/types.ts +100 -0
- package/src/components/variables/useResolvedMetaTree.ts +76 -0
- package/src/components/variables/utils.ts +192 -0
- package/src/data-source/__tests__/collection.test.ts +58 -0
- package/src/data-source/__tests__/index.test.ts +82 -0
- package/src/data-source/__tests__/jioToJoiSchema.test.ts +56 -0
- package/src/data-source/index.ts +812 -0
- package/src/data-source/jioToJoiSchema.ts +103 -0
- package/src/decorators/index.ts +10 -0
- package/src/decorators/largeField.ts +14 -0
- package/src/emitter.ts +33 -0
- package/src/event-registry/BaseEventRegistry.ts +40 -0
- package/src/event-registry/EngineEventRegistry.ts +26 -0
- package/src/event-registry/ModelEventRegistry.ts +69 -0
- package/src/event-registry/__tests__/engineEventRegistry.test.ts +48 -0
- package/src/executor/FlowExecutor.ts +256 -0
- package/src/executor/__tests__/eventStep.test.ts +157 -0
- package/src/executor/__tests__/flowExecutor.test.ts +163 -0
- package/src/flow-registry/BaseFlowRegistry.ts +91 -0
- package/src/flow-registry/GlobalFlowRegistry.ts +82 -0
- package/src/flow-registry/InstanceFlowRegistry.ts +39 -0
- package/src/flow-registry/__tests__/globalFlowRegistry.test.ts +141 -0
- package/src/flow-registry/__tests__/instance-and-global-registry.test.ts +67 -0
- package/src/flow-registry/__tests__/instanceFlowRegistry.test.ts +83 -0
- package/src/flow-registry/index.ts +12 -0
- package/src/flowContext.ts +1639 -0
- package/src/flowEngine.ts +905 -0
- package/src/flowI18n.ts +96 -0
- package/src/flowSettings.ts +1045 -0
- package/src/hooks/index.ts +15 -0
- package/src/hooks/useApplyAutoFlows.ts +51 -0
- package/src/hooks/useFlowModel.tsx +59 -0
- package/src/hooks/useFlowModelById.ts +37 -0
- package/src/hooks/useFlowSettingsContext.tsx +37 -0
- package/src/hooks/useFlowStep.tsx +19 -0
- package/src/hooks/useNiceDropdownMaxHeight.ts +34 -0
- package/src/index.ts +38 -0
- package/src/locale/en-US.json +61 -0
- package/src/locale/index.ts +38 -0
- package/src/locale/zh-CN.json +61 -0
- package/src/models/CollectionFieldModel.tsx +269 -0
- package/src/models/DisplayItemModel.tsx +13 -0
- package/src/models/EditableItemModel.tsx +13 -0
- package/src/models/FilterableItemModel.tsx +13 -0
- package/src/models/__tests__/CollectionFieldModel.test.ts +122 -0
- package/src/models/__tests__/defaultParams-on-create.test.ts +83 -0
- package/src/models/__tests__/flow-model-oninit.test.ts +44 -0
- package/src/models/__tests__/flowModel.actions.integration.test.ts +100 -0
- package/src/models/__tests__/flowModel.getFlows.sort.test.ts +100 -0
- package/src/models/__tests__/flowModel.test.ts +2746 -0
- package/src/models/__tests__/flowRegistry.test.ts +512 -0
- package/src/models/__tests__/forkFlowModel.test.ts +1047 -0
- package/src/models/__tests__/model-actions.test.ts +70 -0
- package/src/models/__tests__/model-events.test.ts +69 -0
- package/src/models/flowModel.tsx +1398 -0
- package/src/models/forkFlowModel.ts +287 -0
- package/src/models/index.ts +17 -0
- package/src/provider.tsx +101 -0
- package/src/resources/__tests__/apiResource.test.ts +201 -0
- package/src/resources/__tests__/baseRecordResource.test.ts +262 -0
- package/src/resources/__tests__/filterItem.test.ts +260 -0
- package/src/resources/__tests__/flowResource.test.ts +127 -0
- package/src/resources/apiResource.ts +148 -0
- package/src/resources/baseRecordResource.ts +279 -0
- package/src/resources/filterItem.ts +74 -0
- package/src/resources/flowResource.ts +143 -0
- package/src/resources/index.ts +17 -0
- package/src/resources/multiRecordResource.ts +219 -0
- package/src/resources/singleRecordResource.ts +83 -0
- package/src/resources/sqlResource.ts +299 -0
- package/src/runjs-context/contexts/FlowRunJSContext.ts +190 -0
- package/src/runjs-context/contexts/FormJSFieldItemRunJSContext.ts +39 -0
- package/src/runjs-context/contexts/JSBlockRunJSContext.ts +52 -0
- package/src/runjs-context/contexts/JSCollectionActionRunJSContext.ts +32 -0
- package/src/runjs-context/contexts/JSFieldRunJSContext.ts +43 -0
- package/src/runjs-context/contexts/JSItemRunJSContext.ts +39 -0
- package/src/runjs-context/contexts/JSRecordActionRunJSContext.ts +34 -0
- package/src/runjs-context/contexts/LinkageRunJSContext.ts +35 -0
- package/src/runjs-context/helpers.ts +56 -0
- package/src/runjs-context/index.ts +20 -0
- package/src/runjs-context/registry.ts +65 -0
- package/src/runjs-context/snippets/global/api-request-get.snippet.ts +20 -0
- package/src/runjs-context/snippets/global/api-request-post.snippet.ts +20 -0
- package/src/runjs-context/snippets/global/console-log-ctx.snippet.ts +19 -0
- package/src/runjs-context/snippets/global/copy-record-json.snippet.ts +21 -0
- package/src/runjs-context/snippets/global/copy-to-clipboard.snippet.ts +21 -0
- package/src/runjs-context/snippets/global/log-json-record.snippet.ts +21 -0
- package/src/runjs-context/snippets/global/message-error.snippet.ts +20 -0
- package/src/runjs-context/snippets/global/message-success.snippet.ts +20 -0
- package/src/runjs-context/snippets/global/notification-open.snippet.ts +21 -0
- package/src/runjs-context/snippets/global/open-view-dialog.snippet.ts +26 -0
- package/src/runjs-context/snippets/global/open-view-drawer.snippet.ts +26 -0
- package/src/runjs-context/snippets/global/requireAsync.snippet.ts +24 -0
- package/src/runjs-context/snippets/global/sleep.snippet.ts +21 -0
- package/src/runjs-context/snippets/global/try-catch-async.snippet.ts +22 -0
- package/src/runjs-context/snippets/global/view-navigation-push.snippet.ts +23 -0
- package/src/runjs-context/snippets/global/window-open.snippet.ts +19 -0
- package/src/runjs-context/snippets/index.ts +59 -0
- package/src/runjs-context/snippets/libs/echarts-init.snippet.ts +24 -0
- package/src/runjs-context/snippets/scene/actions/collection-selected-count.snippet.ts +22 -0
- package/src/runjs-context/snippets/scene/actions/iterate-selected-rows.snippet.ts +21 -0
- package/src/runjs-context/snippets/scene/actions/record-id-message.snippet.ts +21 -0
- package/src/runjs-context/snippets/scene/actions/run-action-basic.snippet.ts +18 -0
- package/src/runjs-context/snippets/scene/jsblock/add-event-listener.snippet.ts +29 -0
- package/src/runjs-context/snippets/scene/jsblock/append-style.snippet.ts +20 -0
- package/src/runjs-context/snippets/scene/jsblock/jsx-mount.snippet.ts +24 -0
- package/src/runjs-context/snippets/scene/jsblock/jsx-unmount.snippet.ts +19 -0
- package/src/runjs-context/snippets/scene/jsblock/render-basic.snippet.ts +24 -0
- package/src/runjs-context/snippets/scene/jsblock/render-button-handler.snippet.ts +24 -0
- package/src/runjs-context/snippets/scene/jsblock/render-card.snippet.ts +30 -0
- package/src/runjs-context/snippets/scene/jsblock/render-react.snippet.ts +34 -0
- package/src/runjs-context/snippets/scene/jsfield/color-by-value.snippet.ts +20 -0
- package/src/runjs-context/snippets/scene/jsfield/format-number.snippet.ts +19 -0
- package/src/runjs-context/snippets/scene/jsfield/innerHTML-value.snippet.ts +18 -0
- package/src/runjs-context/snippets/scene/jsitem/render-basic.snippet.ts +27 -0
- package/src/runjs-context/snippets/scene/linkage/set-disabled.snippet.ts +38 -0
- package/src/runjs-context/snippets/scene/linkage/set-field-value.snippet.ts +37 -0
- package/src/runjs-context/snippets/scene/linkage/set-required.snippet.ts +38 -0
- package/src/runjs-context/snippets/scene/linkage/toggle-visible.snippet.ts +38 -0
- package/src/runjs-context/snippets/types.ts +17 -0
- package/src/types.ts +474 -0
- package/src/utils/__tests__/context.test.ts +93 -0
- package/src/utils/__tests__/params-resolvers.test.ts +652 -0
- package/src/utils/__tests__/parsePathnameToViewParams.test.ts +104 -0
- package/src/utils/__tests__/safeGlobals.test.ts +29 -0
- package/src/utils/__tests__/utils.test.ts +1021 -0
- package/src/utils/__tests__/variablesParams.test.ts +52 -0
- package/src/utils/autoFlowError.ts +29 -0
- package/src/utils/constants.ts +60 -0
- package/src/utils/context.ts +70 -0
- package/src/utils/createCollectionContextMeta.ts +122 -0
- package/src/utils/exceptions.ts +36 -0
- package/src/utils/flow-definitions.ts +16 -0
- package/src/utils/index.ts +63 -0
- package/src/utils/inheritance.ts +39 -0
- package/src/utils/params-resolvers.ts +482 -0
- package/src/utils/parsePathnameToViewParams.ts +103 -0
- package/src/utils/safeGlobals.ts +188 -0
- package/src/utils/schema-utils.ts +201 -0
- package/src/utils/serverContextParams.ts +111 -0
- package/src/utils/setupRuntimeContextSteps.ts +89 -0
- package/src/utils/translation.ts +37 -0
- package/src/utils/variablesParams.ts +175 -0
- package/src/views/DialogComponent.tsx +79 -0
- package/src/views/DrawerComponent.tsx +72 -0
- package/src/views/FlowView.tsx +103 -0
- package/src/views/PageComponent.tsx +150 -0
- package/src/views/ViewNavigation.ts +122 -0
- package/src/views/__tests__/FlowView.test.ts +31 -0
- package/src/views/__tests__/ViewNavigation.test.ts +191 -0
- package/src/views/__tests__/usePatchElement.test.tsx +28 -0
- package/src/views/createViewMeta.ts +157 -0
- package/src/views/index.tsx +14 -0
- package/src/views/useDialog.tsx +192 -0
- package/src/views/useDrawer.tsx +205 -0
- package/src/views/usePage.tsx +182 -0
- package/src/views/usePatchElement.tsx +27 -0
- package/src/views/usePopover.tsx +131 -0
|
@@ -0,0 +1,1398 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { batch, define, observable, observe } from '@formily/reactive';
|
|
11
|
+
import { observer } from '@formily/reactive-react';
|
|
12
|
+
import _ from 'lodash';
|
|
13
|
+
import React from 'react';
|
|
14
|
+
import { uid } from 'uid/secure';
|
|
15
|
+
import { openRequiredParamsStepFormDialog as openRequiredParamsStepFormDialogFn } from '../components/settings/wrappers/contextual/StepRequiredSettingsDialog';
|
|
16
|
+
import { openStepSettingsDialog as openStepSettingsDialogFn } from '../components/settings/wrappers/contextual/StepSettingsDialog';
|
|
17
|
+
import { Emitter } from '../emitter';
|
|
18
|
+
import { InstanceFlowRegistry } from '../flow-registry/InstanceFlowRegistry';
|
|
19
|
+
import { FlowContext, FlowModelContext, FlowRuntimeContext } from '../flowContext';
|
|
20
|
+
import { FlowEngine } from '../flowEngine';
|
|
21
|
+
import type {
|
|
22
|
+
ActionDefinition,
|
|
23
|
+
ArrayElementType,
|
|
24
|
+
CreateModelOptions,
|
|
25
|
+
CreateSubModelOptions,
|
|
26
|
+
DefaultStructure,
|
|
27
|
+
FlowDefinitionOptions,
|
|
28
|
+
FlowModelMeta,
|
|
29
|
+
FlowModelOptions,
|
|
30
|
+
ModelConstructor,
|
|
31
|
+
ParamObject,
|
|
32
|
+
ParentFlowModel,
|
|
33
|
+
PersistOptions,
|
|
34
|
+
StepDefinition,
|
|
35
|
+
StepParams,
|
|
36
|
+
} from '../types';
|
|
37
|
+
import { IModelComponentProps, ReadonlyModelProps } from '../types';
|
|
38
|
+
import {
|
|
39
|
+
FlowExitException,
|
|
40
|
+
isInheritedFrom,
|
|
41
|
+
resolveDefaultParams,
|
|
42
|
+
resolveExpressions,
|
|
43
|
+
setupRuntimeContextSteps,
|
|
44
|
+
} from '../utils';
|
|
45
|
+
// import { FlowExitAllException } from '../utils/exceptions';
|
|
46
|
+
import { Typography } from 'antd/lib';
|
|
47
|
+
import { ModelActionRegistry } from '../action-registry/ModelActionRegistry';
|
|
48
|
+
import { buildSubModelItem } from '../components/subModel/utils';
|
|
49
|
+
import { ModelEventRegistry } from '../event-registry/ModelEventRegistry';
|
|
50
|
+
import { GlobalFlowRegistry } from '../flow-registry/GlobalFlowRegistry';
|
|
51
|
+
import { FlowDefinition } from '../FlowDefinition';
|
|
52
|
+
import { FlowSettingsOpenOptions } from '../flowSettings';
|
|
53
|
+
import type { EventDefinition } from '../types';
|
|
54
|
+
import { ForkFlowModel } from './forkFlowModel';
|
|
55
|
+
|
|
56
|
+
// 使用 WeakMap 为每个类缓存一个 ModelActionRegistry 实例
|
|
57
|
+
const classActionRegistries = new WeakMap<typeof FlowModel, ModelActionRegistry>();
|
|
58
|
+
|
|
59
|
+
// 使用 WeakMap 为每个类缓存一个 ModelEventRegistry 实例
|
|
60
|
+
const classEventRegistries = new WeakMap<typeof FlowModel, ModelEventRegistry>();
|
|
61
|
+
|
|
62
|
+
// 使用WeakMap存储每个类的meta
|
|
63
|
+
const modelMetas = new WeakMap<typeof FlowModel, FlowModelMeta>();
|
|
64
|
+
|
|
65
|
+
// 使用WeakMap存储每个类的 GlobalFlowRegistry
|
|
66
|
+
const modelGlobalRegistries = new WeakMap<typeof FlowModel, GlobalFlowRegistry>();
|
|
67
|
+
|
|
68
|
+
export enum ModelRenderMode {
|
|
69
|
+
ReactElement = 'reactElement',
|
|
70
|
+
RenderFunction = 'renderFunction',
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export class FlowModel<Structure extends DefaultStructure = DefaultStructure> {
|
|
74
|
+
/**
|
|
75
|
+
* 当 flowSettings.enabled 且 model.hidden 为 true 时用于渲染设置态组件(实例方法,子类可覆盖)。
|
|
76
|
+
* 基类默认仅返回一个透明度降低的占位元素
|
|
77
|
+
*/
|
|
78
|
+
protected renderHiddenInConfig(): React.ReactNode | undefined {
|
|
79
|
+
return <span style={{ opacity: 0.5 }}>{this.translate?.('Hidden') || 'Hidden'}</span>;
|
|
80
|
+
}
|
|
81
|
+
public readonly uid: string;
|
|
82
|
+
public sortIndex: number;
|
|
83
|
+
public hidden = false;
|
|
84
|
+
public props: IModelComponentProps = {};
|
|
85
|
+
public stepParams: StepParams = {};
|
|
86
|
+
public flowEngine: FlowEngine;
|
|
87
|
+
public parent: ParentFlowModel<Structure>;
|
|
88
|
+
public subModels: Structure['subModels'];
|
|
89
|
+
private _options: FlowModelOptions<Structure>;
|
|
90
|
+
protected _title: string;
|
|
91
|
+
public isNew = false; // 标记是否为新建状态
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* 所有 fork 实例的引用集合。
|
|
95
|
+
* 使用 Set 便于在销毁时主动遍历并调用 dispose,避免悬挂引用。
|
|
96
|
+
*/
|
|
97
|
+
public forks: Set<ForkFlowModel<any>> = new Set();
|
|
98
|
+
public emitter: Emitter = new Emitter();
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* 基于 key 的 fork 实例缓存,用于复用 fork 实例
|
|
102
|
+
*/
|
|
103
|
+
private forkCache: Map<string, ForkFlowModel<any>> = new Map();
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* 上一次 applyAutoFlows 的执行参数
|
|
107
|
+
*/
|
|
108
|
+
private _lastAutoRunParams: any[] | null = null;
|
|
109
|
+
protected observerDispose: () => void;
|
|
110
|
+
#flowContext: FlowModelContext;
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* 原始 render 方法的引用
|
|
114
|
+
*/
|
|
115
|
+
private _originalRender: (() => any) | null = null;
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* 缓存的响应式包装器组件(每个实例一个)
|
|
119
|
+
*/
|
|
120
|
+
private _reactiveWrapperCache?: React.ComponentType;
|
|
121
|
+
|
|
122
|
+
flowRegistry: InstanceFlowRegistry;
|
|
123
|
+
private _cleanRun?: boolean;
|
|
124
|
+
/**
|
|
125
|
+
* 声明渲染模式:
|
|
126
|
+
* - 'renderElement': render 返回 React 节点,框架会用 observer 包装以获得响应式;
|
|
127
|
+
* - 'renderFunction': render 返回渲染函数(例如表格单元格渲染器),不做包装也不预调用;
|
|
128
|
+
*/
|
|
129
|
+
static renderMode: ModelRenderMode = ModelRenderMode.ReactElement;
|
|
130
|
+
|
|
131
|
+
constructor(options: FlowModelOptions<Structure>) {
|
|
132
|
+
if (!options.flowEngine) {
|
|
133
|
+
throw new Error('FlowModel must be initialized with a FlowEngine instance.');
|
|
134
|
+
}
|
|
135
|
+
this.flowEngine = options.flowEngine;
|
|
136
|
+
if (this.flowEngine.getModel(options.uid)) {
|
|
137
|
+
// 此时 new FlowModel 并不创建新实例,而是返回已存在的实例,避免重复创建同一个model实例
|
|
138
|
+
return this.flowEngine.getModel(options.uid);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
if (!options.uid) {
|
|
142
|
+
options.uid = uid();
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
this.uid = options.uid;
|
|
146
|
+
this.props = {
|
|
147
|
+
...options.props,
|
|
148
|
+
};
|
|
149
|
+
this.stepParams = options.stepParams || {};
|
|
150
|
+
this.subModels = {};
|
|
151
|
+
this.sortIndex = options.sortIndex || 0;
|
|
152
|
+
this._options = options;
|
|
153
|
+
|
|
154
|
+
define(this, {
|
|
155
|
+
hidden: observable,
|
|
156
|
+
props: observable,
|
|
157
|
+
subModels: observable.shallow,
|
|
158
|
+
stepParams: observable,
|
|
159
|
+
// setProps: action,
|
|
160
|
+
setProps: batch,
|
|
161
|
+
// setStepParams: action,
|
|
162
|
+
setStepParams: batch,
|
|
163
|
+
});
|
|
164
|
+
// 保证onInit在所有属性都定义完成后调用
|
|
165
|
+
// queueMicrotask(() => {
|
|
166
|
+
// this.onInit(options);
|
|
167
|
+
// });
|
|
168
|
+
|
|
169
|
+
this.flowRegistry = new InstanceFlowRegistry(this);
|
|
170
|
+
this.flowRegistry.addFlows(options.flowRegistry);
|
|
171
|
+
|
|
172
|
+
this.observerDispose = observe(this.stepParams, (changed) => {
|
|
173
|
+
// if doesn't change, skip
|
|
174
|
+
if (changed.type === 'set' && _.isEqual(changed.value, changed.oldValue)) {
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
if (this.flowEngine) {
|
|
179
|
+
this.invalidateAutoFlowCache();
|
|
180
|
+
}
|
|
181
|
+
this._rerunLastAutoRun();
|
|
182
|
+
this.forks.forEach((fork) => {
|
|
183
|
+
fork.rerender();
|
|
184
|
+
});
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
// 设置 render 方法的响应式包装
|
|
188
|
+
try {
|
|
189
|
+
this.setupReactiveRender();
|
|
190
|
+
} catch (error) {
|
|
191
|
+
console.error(`Failed to setup reactive render for ${this.constructor.name}:`, error);
|
|
192
|
+
// 如果包装失败,确保 render 方法仍然可用
|
|
193
|
+
if (typeof this.render !== 'function') {
|
|
194
|
+
this.render = () => React.createElement('div', null, 'Render method not available');
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
this._cleanRun = !!options['cleanRun'];
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* 对外暴露的上下文:
|
|
203
|
+
*/
|
|
204
|
+
get context() {
|
|
205
|
+
if (!this.#flowContext) {
|
|
206
|
+
this.#flowContext = new FlowModelContext(this);
|
|
207
|
+
}
|
|
208
|
+
return this.#flowContext;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
on(eventName: string, listener: (...args: any[]) => void) {
|
|
212
|
+
this.emitter.on(eventName, listener);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
onInit(options) {
|
|
216
|
+
// Dynamic flows loading is disabled. Previous logic preserved for reference:
|
|
217
|
+
/*
|
|
218
|
+
this.loadDynamicFlows()
|
|
219
|
+
.then((flows) => {
|
|
220
|
+
if (!_.isEmpty(flows)) {
|
|
221
|
+
this.setDynamicFlows(flows);
|
|
222
|
+
}
|
|
223
|
+
})
|
|
224
|
+
.catch((error) => {
|
|
225
|
+
console.error(`Failed to load dynamic flows for ${this.constructor.name}:`, error);
|
|
226
|
+
});
|
|
227
|
+
*/
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* 通过 AddSubModelButton 添加为子模型后调用(子类可覆盖)
|
|
232
|
+
*/
|
|
233
|
+
async afterAddAsSubModel() {}
|
|
234
|
+
|
|
235
|
+
get async() {
|
|
236
|
+
return this._options.async || false;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
get use() {
|
|
240
|
+
return this._options.use;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
get subKey() {
|
|
244
|
+
return this._options.subKey;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
get subType() {
|
|
248
|
+
return this._options.subType;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
get reactView() {
|
|
252
|
+
return this.flowEngine.reactView;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
get parentId() {
|
|
256
|
+
return this._options.parentId;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
static get meta() {
|
|
260
|
+
return modelMetas.get(this);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
static get globalFlowRegistry(): GlobalFlowRegistry {
|
|
264
|
+
const Cls = this as unknown as typeof FlowModel;
|
|
265
|
+
let reg = modelGlobalRegistries.get(Cls);
|
|
266
|
+
if (!reg) {
|
|
267
|
+
reg = new GlobalFlowRegistry(Cls);
|
|
268
|
+
modelGlobalRegistries.set(Cls, reg);
|
|
269
|
+
}
|
|
270
|
+
return reg;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// 获取当前类的动作注册表(含父子链注入),按类缓存
|
|
274
|
+
protected static get actionRegistry(): ModelActionRegistry {
|
|
275
|
+
const ModelClass = this;
|
|
276
|
+
let registry = classActionRegistries.get(ModelClass);
|
|
277
|
+
if (!registry) {
|
|
278
|
+
let parentRegistry: ModelActionRegistry | null = null;
|
|
279
|
+
const ParentClass = Object.getPrototypeOf(ModelClass);
|
|
280
|
+
if (ParentClass && ParentClass !== Function.prototype && ParentClass !== Object.prototype) {
|
|
281
|
+
const isSubclassOfFlowModel = ParentClass === FlowModel || isInheritedFrom(ParentClass, FlowModel);
|
|
282
|
+
if (isSubclassOfFlowModel) {
|
|
283
|
+
parentRegistry = (ParentClass as typeof FlowModel).actionRegistry as ModelActionRegistry;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
registry = new ModelActionRegistry(ModelClass, parentRegistry);
|
|
287
|
+
classActionRegistries.set(ModelClass, registry);
|
|
288
|
+
}
|
|
289
|
+
return registry;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
// 获取当前类的事件注册表(含父子链注入),按类缓存
|
|
293
|
+
protected static get eventRegistry(): ModelEventRegistry {
|
|
294
|
+
const ModelClass = this;
|
|
295
|
+
let registry = classEventRegistries.get(ModelClass);
|
|
296
|
+
if (!registry) {
|
|
297
|
+
let parentRegistry: ModelEventRegistry | null = null;
|
|
298
|
+
const ParentClass = Object.getPrototypeOf(ModelClass);
|
|
299
|
+
if (ParentClass && ParentClass !== Function.prototype && ParentClass !== Object.prototype) {
|
|
300
|
+
const isSubclassOfFlowModel = ParentClass === FlowModel || isInheritedFrom(ParentClass, FlowModel);
|
|
301
|
+
if (isSubclassOfFlowModel) {
|
|
302
|
+
parentRegistry = (ParentClass as typeof FlowModel).eventRegistry as ModelEventRegistry;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
registry = new ModelEventRegistry(ModelClass, parentRegistry);
|
|
306
|
+
classEventRegistries.set(ModelClass, registry);
|
|
307
|
+
}
|
|
308
|
+
return registry;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* 注册仅当前 FlowModel 类及其子类可用的 Action。
|
|
313
|
+
* 该注册是类级别的,不会影响全局(FlowEngine)的 Action 注册。
|
|
314
|
+
*/
|
|
315
|
+
public static registerAction<TModel extends FlowModel = FlowModel>(definition: ActionDefinition<TModel>): void {
|
|
316
|
+
this.actionRegistry.registerAction(definition);
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* 批量注册仅当前 FlowModel 类及其子类可用的 Actions。
|
|
321
|
+
*/
|
|
322
|
+
public static registerActions<TModel extends FlowModel = FlowModel>(
|
|
323
|
+
actions: Record<string, ActionDefinition<TModel>>,
|
|
324
|
+
): void {
|
|
325
|
+
this.actionRegistry.registerActions(actions);
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
/**
|
|
329
|
+
* 注册仅当前 FlowModel 类及其子类可用的 Event。
|
|
330
|
+
* 该注册是类级别的,不会影响全局(FlowEngine)的 Event 注册。
|
|
331
|
+
*/
|
|
332
|
+
public static registerEvent<TModel extends FlowModel = FlowModel>(definition: EventDefinition<TModel>): void {
|
|
333
|
+
this.eventRegistry.registerEvent(definition);
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
/**
|
|
337
|
+
* 批量注册仅当前 FlowModel 类及其子类可用的 Events。
|
|
338
|
+
*/
|
|
339
|
+
public static registerEvents<TModel extends FlowModel = FlowModel>(
|
|
340
|
+
events: Record<string, EventDefinition<TModel>>,
|
|
341
|
+
): void {
|
|
342
|
+
this.eventRegistry.registerEvents(events);
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
static buildChildrenFromModels(ctx, Models: Array<any>) {
|
|
346
|
+
return Models.map((M) => buildSubModelItem(M, ctx, true));
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
get title() {
|
|
350
|
+
// model 可以通过 setTitle 来自定义title, 具有更高的优先级
|
|
351
|
+
return this.translate(this._title) || this.translate(this.constructor['meta']?.label);
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
setTitle(value: string) {
|
|
355
|
+
this._title = value;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
setHidden(value: boolean) {
|
|
359
|
+
this.hidden = !!value;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
_createSubModels(subModels: Record<string, CreateSubModelOptions | CreateSubModelOptions[]>) {
|
|
363
|
+
// Merge default subModels declared in meta.createModelOptions (object form) with provided subModels.
|
|
364
|
+
// Provided subModels take precedence over defaults.
|
|
365
|
+
let mergedSubModels: Record<string, CreateSubModelOptions | CreateSubModelOptions[]> = subModels || {};
|
|
366
|
+
try {
|
|
367
|
+
const Cls = this.constructor as typeof FlowModel;
|
|
368
|
+
const meta = Cls.meta as any;
|
|
369
|
+
const metaCreate = meta?.createModelOptions;
|
|
370
|
+
if (metaCreate && typeof metaCreate === 'object' && metaCreate.subModels) {
|
|
371
|
+
mergedSubModels = _.merge({}, _.cloneDeep(metaCreate.subModels || {}), _.cloneDeep(subModels || {}));
|
|
372
|
+
}
|
|
373
|
+
} catch (e) {
|
|
374
|
+
// Fallback silently if meta defaults resolution fails
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
Object.entries(mergedSubModels || {}).forEach(([key, value]) => {
|
|
378
|
+
if (Array.isArray(value)) {
|
|
379
|
+
value
|
|
380
|
+
.sort((a, b) => (a.sortIndex || 0) - (b.sortIndex || 0))
|
|
381
|
+
.forEach((item) => {
|
|
382
|
+
this.addSubModel(key, item);
|
|
383
|
+
});
|
|
384
|
+
} else {
|
|
385
|
+
this.setSubModel(key, value);
|
|
386
|
+
}
|
|
387
|
+
});
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
public invalidateAutoFlowCache(deep = false) {
|
|
391
|
+
if (this.flowEngine) {
|
|
392
|
+
const cacheKey = FlowEngine.generateApplyFlowCacheKey('autoFlow', 'all', this.uid);
|
|
393
|
+
this.flowEngine.applyFlowCache.delete(cacheKey);
|
|
394
|
+
this.forks.forEach((fork) => {
|
|
395
|
+
const forkCacheKey = FlowEngine.generateApplyFlowCacheKey(`${fork['forkId']}`, 'all', this.uid);
|
|
396
|
+
this.flowEngine.applyFlowCache.delete(forkCacheKey);
|
|
397
|
+
});
|
|
398
|
+
}
|
|
399
|
+
if (deep) {
|
|
400
|
+
const subModelKeys = Object.keys(this.subModels);
|
|
401
|
+
for (const subModelKey of subModelKeys) {
|
|
402
|
+
const subModelValue = this.subModels[subModelKey];
|
|
403
|
+
if (Array.isArray(subModelValue)) {
|
|
404
|
+
for (const subModel of subModelValue) {
|
|
405
|
+
subModel.invalidateAutoFlowCache(deep);
|
|
406
|
+
}
|
|
407
|
+
} else if (subModelValue instanceof FlowModel) {
|
|
408
|
+
subModelValue.invalidateAutoFlowCache(deep);
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
/**
|
|
415
|
+
* 设置FlowEngine实例
|
|
416
|
+
* @param {FlowEngine} flowEngine FlowEngine实例
|
|
417
|
+
*/
|
|
418
|
+
setFlowEngine(flowEngine: FlowEngine): void {
|
|
419
|
+
// this.flowEngine = flowEngine;
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
static define(meta: FlowModelMeta) {
|
|
423
|
+
modelMetas.set(this, meta);
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
/**
|
|
427
|
+
* 注册一个 Flow。
|
|
428
|
+
* @template TModel 具体的FlowModel子类类型
|
|
429
|
+
* @param {string | FlowDefinitionOptions<TModel>} keyOrDefinition 流程的 Key 或 FlowDefinitionOptions 对象。
|
|
430
|
+
* 如果为字符串,则为流程 Key,需要配合 flowDefinition 参数。
|
|
431
|
+
* 如果为对象,则为包含 key 属性的完整 FlowDefinitionOptions。
|
|
432
|
+
* @param {FlowDefinitionOptions<TModel>} [flowDefinition] 当第一个参数为流程 Key 时,此参数为流程的定义。
|
|
433
|
+
* @returns {void}
|
|
434
|
+
*/
|
|
435
|
+
public static registerFlow<
|
|
436
|
+
TClass extends ModelConstructor,
|
|
437
|
+
TModel extends InstanceType<TClass> = InstanceType<TClass>,
|
|
438
|
+
>(
|
|
439
|
+
this: TClass,
|
|
440
|
+
keyOrDefinition: string | FlowDefinitionOptions<TModel>,
|
|
441
|
+
flowDefinition?: Omit<FlowDefinitionOptions<TModel>, 'key'> & { key?: string },
|
|
442
|
+
): void {
|
|
443
|
+
const Cls = this as unknown as typeof FlowModel;
|
|
444
|
+
if (typeof keyOrDefinition === 'string') {
|
|
445
|
+
Cls.globalFlowRegistry.addFlow(keyOrDefinition, flowDefinition);
|
|
446
|
+
} else {
|
|
447
|
+
Cls.globalFlowRegistry.addFlow(keyOrDefinition.key, keyOrDefinition);
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
// /**
|
|
452
|
+
// * 清空所有注册的流程定义。在测试中用来清理已注册的流,防止对其它测试产生影响。
|
|
453
|
+
// */
|
|
454
|
+
// public static clearFlows(): void {
|
|
455
|
+
// modelFlows = new WeakMap<typeof FlowModel, Map<string, FlowDefinition>>();
|
|
456
|
+
// }
|
|
457
|
+
|
|
458
|
+
/**
|
|
459
|
+
* 获取已注册的流程定义。
|
|
460
|
+
* 如果当前类不存在对应的flow,会继续往父类查找。
|
|
461
|
+
* @param {string} key 流程 Key。
|
|
462
|
+
* @returns {FlowDefinition | undefined} 流程定义,如果未找到则返回 undefined。
|
|
463
|
+
*/
|
|
464
|
+
public getFlow(key: string): FlowDefinition | undefined {
|
|
465
|
+
if (this.flowRegistry.hasFlow(key)) {
|
|
466
|
+
return this.flowRegistry.getFlow(key);
|
|
467
|
+
}
|
|
468
|
+
const Cls = this.constructor as typeof FlowModel;
|
|
469
|
+
return Cls.globalFlowRegistry.getFlow(key);
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
/**
|
|
473
|
+
* 注册一个实例级别的流程定义。
|
|
474
|
+
* @template TModel 具体的FlowModel子类类型
|
|
475
|
+
* @param {string | FlowDefinitionOptions<TModel>} keyOrDefinition 流程的 Key 或 FlowDefinitionOptions 对象。
|
|
476
|
+
* @param {FlowDefinitionOptions<TModel>} [flowDefinition] 当第一个参数为流程 Key 时,此参数为流程的定义。
|
|
477
|
+
* @returns {FlowDefinition} 注册的流程定义实例
|
|
478
|
+
*/
|
|
479
|
+
public registerFlow<TModel extends FlowModel = this>(
|
|
480
|
+
keyOrDefinition: string | FlowDefinitionOptions<TModel>,
|
|
481
|
+
flowDefinition?: Omit<FlowDefinitionOptions<TModel>, 'key'> & { key?: string },
|
|
482
|
+
): FlowDefinition {
|
|
483
|
+
if (typeof keyOrDefinition === 'string') {
|
|
484
|
+
return this.flowRegistry.addFlow(keyOrDefinition, flowDefinition);
|
|
485
|
+
} else {
|
|
486
|
+
return this.flowRegistry.addFlow(keyOrDefinition.key, keyOrDefinition);
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
/**
|
|
491
|
+
* 获取当前模型可用的所有 Actions:
|
|
492
|
+
* - 包含全局(FlowEngine)注册的 Actions;
|
|
493
|
+
* - 合并类级(FlowModel.registerAction(s))注册的 Actions,并考虑继承(子类覆盖父类同名 Action)。
|
|
494
|
+
*/
|
|
495
|
+
public getActions<TModel extends FlowModel = this, TCtx extends FlowContext = FlowRuntimeContext<TModel>>(): Map<
|
|
496
|
+
string,
|
|
497
|
+
ActionDefinition<TModel, TCtx>
|
|
498
|
+
> {
|
|
499
|
+
const ModelClass = this.constructor as typeof FlowModel;
|
|
500
|
+
const merged = ModelClass.actionRegistry.getActions<TModel, TCtx>();
|
|
501
|
+
const actions = new Map<string, ActionDefinition<TModel, TCtx>>();
|
|
502
|
+
const globalActions = this.flowEngine?.getActions<TModel, TCtx>();
|
|
503
|
+
if (globalActions) for (const [k, v] of globalActions) actions.set(k, v);
|
|
504
|
+
for (const [k, v] of merged) actions.set(k, v);
|
|
505
|
+
return actions;
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
/**
|
|
509
|
+
* 获取当前模型可用的所有 Events:
|
|
510
|
+
* - 包含全局(FlowEngine)注册的 Events;
|
|
511
|
+
* - 合并类级(FlowModel.registerEvent(s))注册的 Events,并考虑继承(子类覆盖父类同名 Event)。
|
|
512
|
+
*/
|
|
513
|
+
public getEvents<TModel extends FlowModel = this>(): Map<string, EventDefinition<TModel>> {
|
|
514
|
+
const ModelClass = this.constructor as typeof FlowModel;
|
|
515
|
+
const merged = ModelClass.eventRegistry.getEvents();
|
|
516
|
+
const events = new Map<string, EventDefinition<TModel>>();
|
|
517
|
+
const globalEvents = this.flowEngine?.getEvents<TModel>();
|
|
518
|
+
if (globalEvents) for (const [k, v] of globalEvents) events.set(k, v);
|
|
519
|
+
for (const [k, v] of merged) events.set(k, v);
|
|
520
|
+
return events;
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
/**
|
|
524
|
+
* 获取指定名称的 Event(优先返回类级注册的,未找到则回退到全局)。
|
|
525
|
+
*/
|
|
526
|
+
public getEvent<TModel extends FlowModel = this>(name: string): EventDefinition<TModel> | undefined {
|
|
527
|
+
const ModelClass = this.constructor as typeof FlowModel;
|
|
528
|
+
const own = ModelClass.eventRegistry.getEvent(name) as EventDefinition<TModel> | undefined;
|
|
529
|
+
if (own) return own;
|
|
530
|
+
return this.flowEngine?.getEvent<TModel>(name);
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
/**
|
|
534
|
+
* 获取指定名称的 Action(优先返回类级注册的,未找到则回退到全局)。
|
|
535
|
+
*/
|
|
536
|
+
public getAction<TModel extends FlowModel = this, TCtx extends FlowContext = FlowRuntimeContext<TModel>>(
|
|
537
|
+
name: string,
|
|
538
|
+
): ActionDefinition<TModel, TCtx> | undefined {
|
|
539
|
+
const ModelClass = this.constructor as typeof FlowModel;
|
|
540
|
+
const own = ModelClass.actionRegistry.getAction<TModel, TCtx>(name);
|
|
541
|
+
if (own) return own;
|
|
542
|
+
return this.flowEngine?.getAction<TModel, TCtx>(name);
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
getFlows() {
|
|
546
|
+
// 分离获取:实例流(未排序)与静态流(在 GlobalFlowRegistry 中已排序)
|
|
547
|
+
const instanceFlows = this.flowRegistry.getFlows();
|
|
548
|
+
const staticFlows = (this.constructor as typeof FlowModel).globalFlowRegistry.getFlows();
|
|
549
|
+
|
|
550
|
+
// 跳过同名静态流(实例覆盖静态)
|
|
551
|
+
const instanceKeys = new Set(instanceFlows.keys());
|
|
552
|
+
const staticEntries = Array.from(staticFlows.entries()).filter(([key]) => !instanceKeys.has(key));
|
|
553
|
+
|
|
554
|
+
// 实例流保持原始注册顺序,统一一次排序(稳定排序):
|
|
555
|
+
const instanceEntries = Array.from(instanceFlows.entries());
|
|
556
|
+
const allEntries = [...staticEntries, ...instanceEntries];
|
|
557
|
+
allEntries.sort(([, a], [, b]) => {
|
|
558
|
+
const sa = a.sort ?? 0;
|
|
559
|
+
const sb = b.sort ?? 0;
|
|
560
|
+
if (sa !== sb) return sa - sb;
|
|
561
|
+
return 0; // 其它情况保持稳定顺序(静态内部:父类优先;实例内部:注册顺序)
|
|
562
|
+
});
|
|
563
|
+
|
|
564
|
+
return new Map<string, FlowDefinition>(allEntries);
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
setProps(props: IModelComponentProps): void;
|
|
568
|
+
setProps(key: string, value: any): void;
|
|
569
|
+
setProps(props: IModelComponentProps | string, value?: any): void {
|
|
570
|
+
if (typeof props === 'string') {
|
|
571
|
+
this.props[props] = value;
|
|
572
|
+
} else {
|
|
573
|
+
this.props = { ...this.props, ...props };
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
getProps(): ReadonlyModelProps {
|
|
578
|
+
return this.props as ReadonlyModelProps;
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
setStepParams(flowKey: string, stepKey: string, params: ParamObject): void;
|
|
582
|
+
setStepParams(flowKey: string, stepParams: Record<string, ParamObject>): void;
|
|
583
|
+
setStepParams(allParams: StepParams): void;
|
|
584
|
+
setStepParams(
|
|
585
|
+
flowKeyOrAllParams: string | StepParams,
|
|
586
|
+
stepKeyOrStepsParams?: string | Record<string, ParamObject>,
|
|
587
|
+
params?: ParamObject,
|
|
588
|
+
): void {
|
|
589
|
+
if (typeof flowKeyOrAllParams === 'string') {
|
|
590
|
+
const flowKey = flowKeyOrAllParams;
|
|
591
|
+
if (typeof stepKeyOrStepsParams === 'string' && params !== undefined) {
|
|
592
|
+
if (!this.stepParams[flowKey]) {
|
|
593
|
+
this.stepParams[flowKey] = {};
|
|
594
|
+
}
|
|
595
|
+
this.stepParams[flowKey][stepKeyOrStepsParams] = {
|
|
596
|
+
...this.stepParams[flowKey][stepKeyOrStepsParams],
|
|
597
|
+
...params,
|
|
598
|
+
};
|
|
599
|
+
} else if (typeof stepKeyOrStepsParams === 'object' && stepKeyOrStepsParams !== null) {
|
|
600
|
+
this.stepParams[flowKey] = { ...(this.stepParams[flowKey] || {}), ...stepKeyOrStepsParams };
|
|
601
|
+
}
|
|
602
|
+
} else if (typeof flowKeyOrAllParams === 'object' && flowKeyOrAllParams !== null) {
|
|
603
|
+
for (const fk in flowKeyOrAllParams) {
|
|
604
|
+
if (Object.prototype.hasOwnProperty.call(flowKeyOrAllParams, fk)) {
|
|
605
|
+
this.stepParams[fk] = { ...(this.stepParams[fk] || {}), ...flowKeyOrAllParams[fk] };
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
getStepParams(flowKey: string, stepKey: string): any | undefined;
|
|
612
|
+
getStepParams(flowKey: string): Record<string, any> | undefined;
|
|
613
|
+
getStepParams(): StepParams;
|
|
614
|
+
getStepParams(flowKey?: string, stepKey?: string): any {
|
|
615
|
+
if (flowKey && stepKey) {
|
|
616
|
+
return this.stepParams[flowKey]?.[stepKey];
|
|
617
|
+
}
|
|
618
|
+
if (flowKey) {
|
|
619
|
+
return this.stepParams[flowKey];
|
|
620
|
+
}
|
|
621
|
+
return this.stepParams;
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
async applyFlow(flowKey: string, inputArgs?: Record<string, any>, runId?: string): Promise<any> {
|
|
625
|
+
const currentFlowEngine = this.flowEngine;
|
|
626
|
+
if (!currentFlowEngine) {
|
|
627
|
+
console.warn('FlowEngine not available on this model for applyFlow. Check and model.flowEngine setup.');
|
|
628
|
+
return Promise.reject(new Error('FlowEngine not available for applyFlow. Please set flowEngine on the model.'));
|
|
629
|
+
}
|
|
630
|
+
const isFork = (this as any).isFork === true;
|
|
631
|
+
const target = this;
|
|
632
|
+
console.log(
|
|
633
|
+
`[FlowModel] applyFlow: uid=${this.uid}, flowKey=${flowKey}, isFork=${isFork}, cleanRun=${
|
|
634
|
+
this.cleanRun
|
|
635
|
+
}, targetIsFork=${(target as any)?.isFork === true}`,
|
|
636
|
+
);
|
|
637
|
+
return currentFlowEngine.executor.runFlow(target, flowKey, inputArgs, runId);
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
private async _dispatchEvent(eventName: string, inputArgs?: Record<string, any>): Promise<void> {
|
|
641
|
+
const currentFlowEngine = this.flowEngine;
|
|
642
|
+
if (!currentFlowEngine) {
|
|
643
|
+
console.warn('FlowEngine not available on this model for dispatchEvent. Please set flowEngine on the model.');
|
|
644
|
+
return;
|
|
645
|
+
}
|
|
646
|
+
const isFork = (this as any).isFork === true;
|
|
647
|
+
const target = this;
|
|
648
|
+
console.log(
|
|
649
|
+
`[FlowModel] dispatchEvent: uid=${this.uid}, event=${eventName}, isFork=${isFork}, cleanRun=${
|
|
650
|
+
this.cleanRun
|
|
651
|
+
}, targetIsFork=${(target as any)?.isFork === true}`,
|
|
652
|
+
);
|
|
653
|
+
await currentFlowEngine.executor.dispatchEvent(target, eventName, inputArgs);
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
private _dispatchEventWithDebounce = _.debounce(async (eventName: string, inputArgs?: Record<string, any>) => {
|
|
657
|
+
return this._dispatchEvent(eventName, inputArgs);
|
|
658
|
+
}, 100);
|
|
659
|
+
|
|
660
|
+
async dispatchEvent(
|
|
661
|
+
eventName: string,
|
|
662
|
+
inputArgs?: Record<string, any>,
|
|
663
|
+
options?: {
|
|
664
|
+
/**
|
|
665
|
+
* 是否要开启防抖功能
|
|
666
|
+
*/
|
|
667
|
+
debounce: boolean;
|
|
668
|
+
},
|
|
669
|
+
): Promise<void> {
|
|
670
|
+
if (options?.debounce) {
|
|
671
|
+
return this._dispatchEventWithDebounce(eventName, inputArgs);
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
return this._dispatchEvent(eventName, inputArgs);
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
/**
|
|
678
|
+
* 获取所有自动应用流程定义(保持 getFlows 的顺序,即按 sort 排序)
|
|
679
|
+
* @returns {FlowDefinition[]} 自动应用流程定义数组(已按 sort 排序)
|
|
680
|
+
*/
|
|
681
|
+
public getAutoFlows(): FlowDefinition[] {
|
|
682
|
+
const allFlows = this.getFlows();
|
|
683
|
+
|
|
684
|
+
// 过滤出自动流程(保持 Map 的原有顺序)
|
|
685
|
+
// 没有 on 属性且没有 manual: true 的流程默认自动执行
|
|
686
|
+
const autoFlows = Array.from(allFlows.values()).filter((flow) => {
|
|
687
|
+
// 如果有 on 属性,说明是事件触发流程,不自动执行
|
|
688
|
+
if (flow.on) {
|
|
689
|
+
return false;
|
|
690
|
+
}
|
|
691
|
+
// 如果明确设置了 manual: true,不自动执行
|
|
692
|
+
if (flow.manual === true) {
|
|
693
|
+
return false;
|
|
694
|
+
}
|
|
695
|
+
// 其他情况默认自动执行
|
|
696
|
+
return true;
|
|
697
|
+
});
|
|
698
|
+
|
|
699
|
+
return autoFlows;
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
/**
|
|
703
|
+
* 重新执行上一次的 applyAutoFlows,保持参数一致
|
|
704
|
+
* 如果之前没有执行过,则直接跳过
|
|
705
|
+
* 使用 lodash debounce 避免频繁调用
|
|
706
|
+
*/
|
|
707
|
+
private _rerunLastAutoRun = _.debounce(async () => {
|
|
708
|
+
if (this._lastAutoRunParams) {
|
|
709
|
+
try {
|
|
710
|
+
await this.applyAutoFlows(...this._lastAutoRunParams);
|
|
711
|
+
} catch (error) {
|
|
712
|
+
console.error('FlowModel._rerunLastAutoRun: Error during rerun:', error);
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
}, 100);
|
|
716
|
+
|
|
717
|
+
/**
|
|
718
|
+
* 自动流程执行前钩子。
|
|
719
|
+
* 子类可覆盖;可抛出 FlowExitException 提前终止。
|
|
720
|
+
*/
|
|
721
|
+
public async onBeforeAutoFlows(inputArgs?: Record<string, any>): Promise<void> {}
|
|
722
|
+
|
|
723
|
+
/**
|
|
724
|
+
* 自动流程执行后钩子。
|
|
725
|
+
* 子类可覆盖。
|
|
726
|
+
*/
|
|
727
|
+
public async onAfterAutoFlows(results: any[], inputArgs?: Record<string, any>): Promise<void> {}
|
|
728
|
+
|
|
729
|
+
/**
|
|
730
|
+
* 自动流程错误钩子。
|
|
731
|
+
* 子类可覆盖。
|
|
732
|
+
*/
|
|
733
|
+
public async onAutoFlowsError(error: Error, inputArgs?: Record<string, any>): Promise<void> {}
|
|
734
|
+
|
|
735
|
+
useHooksBeforeRender() {}
|
|
736
|
+
|
|
737
|
+
/**
|
|
738
|
+
* 执行所有自动应用流程
|
|
739
|
+
* @param {Record<string, any>} [inputArgs] 可选的运行时参数
|
|
740
|
+
* @param {boolean} [useCache=true] 是否使用缓存机制,默认为 true
|
|
741
|
+
* @returns {Promise<any[]>} 所有自动应用流程的执行结果数组
|
|
742
|
+
*/
|
|
743
|
+
async applyAutoFlows(inputArgs?: Record<string, any>, useCache?: boolean): Promise<any[]>;
|
|
744
|
+
async applyAutoFlows(...args: any[]): Promise<any[]> {
|
|
745
|
+
const [inputArgs, useCache = true] = args;
|
|
746
|
+
const cacheKey = useCache
|
|
747
|
+
? FlowEngine.generateApplyFlowCacheKey(this['forkId'] ?? 'autoFlow', 'all', this.uid)
|
|
748
|
+
: null;
|
|
749
|
+
if (!_.isEqual(inputArgs, this._lastAutoRunParams?.[0]) && cacheKey) {
|
|
750
|
+
this.flowEngine.applyFlowCache.delete(cacheKey);
|
|
751
|
+
}
|
|
752
|
+
this._lastAutoRunParams = args;
|
|
753
|
+
|
|
754
|
+
// 在执行自动流程前触发(无论是否命中缓存都应触发)
|
|
755
|
+
try {
|
|
756
|
+
await this.onBeforeAutoFlows(inputArgs);
|
|
757
|
+
} catch (error) {
|
|
758
|
+
if (error instanceof FlowExitException) {
|
|
759
|
+
this.context.logger?.debug(`[FlowModel.applyAutoFlows] ${error.message}`);
|
|
760
|
+
return [];
|
|
761
|
+
}
|
|
762
|
+
try {
|
|
763
|
+
await this.onAutoFlowsError(error as Error, inputArgs);
|
|
764
|
+
} catch (_) {
|
|
765
|
+
// swallow secondary hook error to avoid masking the original
|
|
766
|
+
}
|
|
767
|
+
throw error;
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
// 执行自动流程(内部可能命中缓存)
|
|
771
|
+
let results: any[] = [];
|
|
772
|
+
try {
|
|
773
|
+
results = await this.flowEngine.executor.runAutoFlows(this, inputArgs, useCache);
|
|
774
|
+
} catch (error) {
|
|
775
|
+
try {
|
|
776
|
+
await this.onAutoFlowsError(error as Error, inputArgs);
|
|
777
|
+
} catch (_) {
|
|
778
|
+
// ignore secondary error from error hook
|
|
779
|
+
}
|
|
780
|
+
throw error;
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
// 执行后钩子
|
|
784
|
+
try {
|
|
785
|
+
await this.onAfterAutoFlows(results, inputArgs);
|
|
786
|
+
} catch (error) {
|
|
787
|
+
try {
|
|
788
|
+
await this.onAutoFlowsError(error as Error, inputArgs);
|
|
789
|
+
} catch (_) {
|
|
790
|
+
// ignore
|
|
791
|
+
}
|
|
792
|
+
throw error;
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
return results;
|
|
796
|
+
}
|
|
797
|
+
|
|
798
|
+
/**
|
|
799
|
+
* 智能检测是否应该跳过响应式包装
|
|
800
|
+
* 说明:
|
|
801
|
+
* - 仅基于标记判断,不会执行 render,避免出现“预调用 render”带来的副作用和双调用问题。
|
|
802
|
+
* - 当子类需要返回函数(如表格列的单元格渲染器),应在子类上设置静态属性 `renderReturnsFunction = true`。
|
|
803
|
+
*/
|
|
804
|
+
private shouldSkipReactiveWrapping(): boolean {
|
|
805
|
+
// 已经包裹过则跳过
|
|
806
|
+
if ((this.render as any).__isReactiveWrapped) {
|
|
807
|
+
return true;
|
|
808
|
+
}
|
|
809
|
+
// 子类显式声明渲染模式为 renderFunction,则跳过包裹
|
|
810
|
+
const Cls = this.constructor as typeof FlowModel;
|
|
811
|
+
if (Cls.renderMode === ModelRenderMode.RenderFunction) {
|
|
812
|
+
return true;
|
|
813
|
+
}
|
|
814
|
+
return false;
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
/**
|
|
818
|
+
* 设置 render 方法的响应式包装
|
|
819
|
+
* @private
|
|
820
|
+
*/
|
|
821
|
+
private setupReactiveRender(): void {
|
|
822
|
+
// 确保 render 方法存在且是函数
|
|
823
|
+
if (typeof this.render !== 'function') {
|
|
824
|
+
return;
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
try {
|
|
828
|
+
// 保存原始 render 方法的引用
|
|
829
|
+
const originalRender = this.render;
|
|
830
|
+
this._originalRender = originalRender;
|
|
831
|
+
|
|
832
|
+
// 验证原始方法是函数
|
|
833
|
+
if (typeof originalRender !== 'function') {
|
|
834
|
+
console.error(`FlowModel ${this.constructor.name}: original render method is not a function`, originalRender);
|
|
835
|
+
return;
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
// 如果需要跳过响应式包装(例如返回渲染函数),也需要包一层以处理 hidden/config 逻辑
|
|
839
|
+
if (this.shouldSkipReactiveWrapping()) {
|
|
840
|
+
const wrappedNonReactive = function (this: any) {
|
|
841
|
+
const isConfigMode = !!this?.flowEngine?.flowSettings?.enabled;
|
|
842
|
+
if (this.hidden) {
|
|
843
|
+
if (!isConfigMode) return null;
|
|
844
|
+
const rendered = this.renderHiddenInConfig?.();
|
|
845
|
+
const Cls = this.constructor as typeof FlowModel;
|
|
846
|
+
const returnsFunction = Cls.renderMode === ModelRenderMode.RenderFunction;
|
|
847
|
+
return returnsFunction ? (typeof rendered === 'function' ? rendered : () => rendered) : rendered;
|
|
848
|
+
}
|
|
849
|
+
return originalRender.call(this);
|
|
850
|
+
};
|
|
851
|
+
(wrappedNonReactive as any).__originalRender = originalRender;
|
|
852
|
+
this.render = wrappedNonReactive;
|
|
853
|
+
return;
|
|
854
|
+
}
|
|
855
|
+
|
|
856
|
+
// 创建缓存的响应式包装器组件工厂(只创建一次)
|
|
857
|
+
const createReactiveWrapper = (modelInstance: any) => {
|
|
858
|
+
const ReactiveWrapper = observer(() => {
|
|
859
|
+
// 触发响应式更新的关键属性访问(读取 run/渲染目标的 props)
|
|
860
|
+
const renderTarget = modelInstance;
|
|
861
|
+
if (renderTarget !== modelInstance && (renderTarget as any)?.localProps !== undefined) {
|
|
862
|
+
// 订阅 fork 的本地 props 变更
|
|
863
|
+
(renderTarget as any).localProps;
|
|
864
|
+
// 同时订阅原实例(master/UI fork)的 props 变更,
|
|
865
|
+
// 以捕获诸如 FormItem→FieldModelRenderer 通过 model.setProps 写到 master.props 的更新
|
|
866
|
+
modelInstance.props;
|
|
867
|
+
} else {
|
|
868
|
+
// 订阅当前实例的 props 变更
|
|
869
|
+
modelInstance.props;
|
|
870
|
+
}
|
|
871
|
+
|
|
872
|
+
// 添加生命周期钩子:当渲染目标变化时,解绑旧目标并绑定新目标
|
|
873
|
+
React.useEffect(() => {
|
|
874
|
+
if (typeof renderTarget.onMount === 'function') {
|
|
875
|
+
renderTarget.onMount();
|
|
876
|
+
}
|
|
877
|
+
return () => {
|
|
878
|
+
if (typeof renderTarget.onUnmount === 'function') {
|
|
879
|
+
renderTarget.onUnmount();
|
|
880
|
+
}
|
|
881
|
+
};
|
|
882
|
+
}, [renderTarget]);
|
|
883
|
+
|
|
884
|
+
// 处理 hidden 渲染逻辑:
|
|
885
|
+
const isConfigMode = !!modelInstance?.flowEngine?.flowSettings?.enabled;
|
|
886
|
+
if (modelInstance.hidden) {
|
|
887
|
+
if (!isConfigMode) {
|
|
888
|
+
return null;
|
|
889
|
+
}
|
|
890
|
+
// 设置态隐藏时的渲染:由实例方法 renderHiddenInConfig 决定;若为渲染函数模式,则包装为函数
|
|
891
|
+
return modelInstance.renderHiddenInConfig?.();
|
|
892
|
+
}
|
|
893
|
+
|
|
894
|
+
// 调用原始渲染方法
|
|
895
|
+
return originalRender.call(renderTarget);
|
|
896
|
+
});
|
|
897
|
+
|
|
898
|
+
// 设置显示名称便于调试
|
|
899
|
+
ReactiveWrapper.displayName = `ReactiveWrapper(${modelInstance.constructor.name})`;
|
|
900
|
+
|
|
901
|
+
return ReactiveWrapper;
|
|
902
|
+
};
|
|
903
|
+
|
|
904
|
+
const wrappedRender = function (this: any) {
|
|
905
|
+
// 当前实例创建或获取缓存的 ReactiveWrapper
|
|
906
|
+
if (!this._reactiveWrapperCache) {
|
|
907
|
+
this._reactiveWrapperCache = createReactiveWrapper(this);
|
|
908
|
+
}
|
|
909
|
+
|
|
910
|
+
// 返回响应式组件
|
|
911
|
+
return React.createElement(this._reactiveWrapperCache);
|
|
912
|
+
};
|
|
913
|
+
|
|
914
|
+
// 标记已被包装
|
|
915
|
+
(wrappedRender as any).__isReactiveWrapped = true;
|
|
916
|
+
(wrappedRender as any).__originalRender = originalRender;
|
|
917
|
+
|
|
918
|
+
// 替换 render 方法
|
|
919
|
+
this.render = wrappedRender;
|
|
920
|
+
} catch (error) {
|
|
921
|
+
console.error(`FlowModel ${this.constructor.name}: Error during render method wrapping:`, error);
|
|
922
|
+
}
|
|
923
|
+
}
|
|
924
|
+
|
|
925
|
+
get cleanRun() {
|
|
926
|
+
return true; // 故意的设置 cleanRun 为true
|
|
927
|
+
// return !!this._cleanRun;
|
|
928
|
+
}
|
|
929
|
+
|
|
930
|
+
setCleanRun(value: boolean) {
|
|
931
|
+
const prev = this._cleanRun;
|
|
932
|
+
this._cleanRun = !!value;
|
|
933
|
+
}
|
|
934
|
+
|
|
935
|
+
/**
|
|
936
|
+
* 组件挂载时的生命周期钩子
|
|
937
|
+
* 子类可以重写此方法来添加挂载时的逻辑
|
|
938
|
+
* @protected
|
|
939
|
+
*/
|
|
940
|
+
// eslint-disable-next-line no-empty
|
|
941
|
+
protected onMount(): void {
|
|
942
|
+
// 默认为空实现,子类可以重写
|
|
943
|
+
}
|
|
944
|
+
|
|
945
|
+
/**
|
|
946
|
+
* 组件卸载时的生命周期钩子
|
|
947
|
+
* 子类可以重写此方法来添加卸载时的逻辑
|
|
948
|
+
* @protected
|
|
949
|
+
*/
|
|
950
|
+
protected onUnmount(): void {
|
|
951
|
+
// 默认为空实现,子类可以重写
|
|
952
|
+
}
|
|
953
|
+
|
|
954
|
+
/**
|
|
955
|
+
* 有权限时的渲染逻辑。
|
|
956
|
+
* 这是一个抽象方法,所有子类都必须实现,用于返回自己的正常 UI。
|
|
957
|
+
*
|
|
958
|
+
* @returns {React.ReactNode} 有权限时的渲染结果
|
|
959
|
+
*/
|
|
960
|
+
public render(): any {
|
|
961
|
+
return <div {...this.props}></div>;
|
|
962
|
+
}
|
|
963
|
+
|
|
964
|
+
async rerender() {
|
|
965
|
+
await this.applyAutoFlows(this._lastAutoRunParams?.[0], false);
|
|
966
|
+
}
|
|
967
|
+
|
|
968
|
+
/**
|
|
969
|
+
* 自动流程缓存的作用域标识;fork 实例可覆盖以区分缓存。
|
|
970
|
+
*/
|
|
971
|
+
public getAutoFlowCacheScope(): string {
|
|
972
|
+
return 'autoFlow';
|
|
973
|
+
}
|
|
974
|
+
|
|
975
|
+
setParent(parent: FlowModel): void {
|
|
976
|
+
// forkflowModel instanceof FlowModel is false, but fork can be used as parent
|
|
977
|
+
const isValidParent =
|
|
978
|
+
parent && (parent.constructor === FlowModel || isInheritedFrom(parent.constructor as any, FlowModel));
|
|
979
|
+
if (!isValidParent) {
|
|
980
|
+
throw new Error('Parent must be an instance of FlowModel.');
|
|
981
|
+
}
|
|
982
|
+
this.parent = parent as ParentFlowModel<Structure>;
|
|
983
|
+
this._options.parentId = parent.uid;
|
|
984
|
+
if (this._options.delegateToParent !== false) {
|
|
985
|
+
this.context.addDelegate(this.parent.context);
|
|
986
|
+
}
|
|
987
|
+
}
|
|
988
|
+
|
|
989
|
+
removeParentDelegate() {
|
|
990
|
+
if (!this.parent) {
|
|
991
|
+
return;
|
|
992
|
+
}
|
|
993
|
+
this.context.removeDelegate(this.parent.context);
|
|
994
|
+
}
|
|
995
|
+
|
|
996
|
+
addSubModel<T extends FlowModel>(subKey: string, options: CreateModelOptions | T) {
|
|
997
|
+
const actualParent: FlowModel = (this['master'] as FlowModel) || this;
|
|
998
|
+
|
|
999
|
+
let model: T;
|
|
1000
|
+
if (options instanceof FlowModel) {
|
|
1001
|
+
// Compare by uid to tolerate fork wrappers and contextThis bindings
|
|
1002
|
+
const hasParent = !!options.parent;
|
|
1003
|
+
const parentUid = options.parent?.uid;
|
|
1004
|
+
if (hasParent && parentUid && parentUid !== actualParent.uid) {
|
|
1005
|
+
throw new Error('Sub model already has a parent.');
|
|
1006
|
+
}
|
|
1007
|
+
model = options;
|
|
1008
|
+
} else {
|
|
1009
|
+
model = actualParent.flowEngine.createModel<T>({
|
|
1010
|
+
...options,
|
|
1011
|
+
parentId: actualParent.uid,
|
|
1012
|
+
subKey,
|
|
1013
|
+
subType: 'array',
|
|
1014
|
+
});
|
|
1015
|
+
}
|
|
1016
|
+
model.setParent(actualParent);
|
|
1017
|
+
const subModels = actualParent.subModels as {
|
|
1018
|
+
[subKey: string]: FlowModel[];
|
|
1019
|
+
};
|
|
1020
|
+
if (!Array.isArray(subModels[subKey])) {
|
|
1021
|
+
subModels[subKey] = observable.shallow([]);
|
|
1022
|
+
}
|
|
1023
|
+
const maxSortIndex = Math.max(...(subModels[subKey] as FlowModel[]).map((item) => item.sortIndex || 0), 0);
|
|
1024
|
+
model.sortIndex = maxSortIndex + 1;
|
|
1025
|
+
subModels[subKey].push(model);
|
|
1026
|
+
actualParent.emitter.emit('onSubModelAdded', model);
|
|
1027
|
+
return model;
|
|
1028
|
+
}
|
|
1029
|
+
|
|
1030
|
+
setSubModel(subKey: string, options: CreateModelOptions | FlowModel) {
|
|
1031
|
+
const actualParent: FlowModel = (this['master'] as FlowModel) || this;
|
|
1032
|
+
|
|
1033
|
+
let model: FlowModel;
|
|
1034
|
+
if (options instanceof FlowModel) {
|
|
1035
|
+
// Compare by uid to tolerate fork wrappers and contextThis bindings
|
|
1036
|
+
const hasParent = !!options.parent;
|
|
1037
|
+
const parentUid = options.parent?.uid;
|
|
1038
|
+
if (hasParent && parentUid && parentUid !== actualParent.uid) {
|
|
1039
|
+
throw new Error('Sub model already has a parent.');
|
|
1040
|
+
}
|
|
1041
|
+
model = options;
|
|
1042
|
+
} else {
|
|
1043
|
+
model = actualParent.flowEngine.createModel({
|
|
1044
|
+
...options,
|
|
1045
|
+
parentId: actualParent.uid,
|
|
1046
|
+
subKey,
|
|
1047
|
+
subType: 'object',
|
|
1048
|
+
});
|
|
1049
|
+
}
|
|
1050
|
+
model.setParent(actualParent);
|
|
1051
|
+
(actualParent.subModels as any)[subKey] = model;
|
|
1052
|
+
actualParent.emitter.emit('onSubModelAdded', model);
|
|
1053
|
+
return model;
|
|
1054
|
+
}
|
|
1055
|
+
|
|
1056
|
+
filterSubModels<K extends keyof Structure['subModels'], R>(
|
|
1057
|
+
subKey: K,
|
|
1058
|
+
callback: (model: ArrayElementType<Structure['subModels'][K]>, index: number) => boolean,
|
|
1059
|
+
): ArrayElementType<Structure['subModels'][K]>[] {
|
|
1060
|
+
const model = (this.subModels as any)[subKey as string];
|
|
1061
|
+
|
|
1062
|
+
if (!model) {
|
|
1063
|
+
return [];
|
|
1064
|
+
}
|
|
1065
|
+
|
|
1066
|
+
const results: ArrayElementType<Structure['subModels'][K]>[] = [];
|
|
1067
|
+
|
|
1068
|
+
_.castArray(model)
|
|
1069
|
+
.sort((a, b) => (a.sortIndex || 0) - (b.sortIndex || 0))
|
|
1070
|
+
.forEach((item, index) => {
|
|
1071
|
+
const result = (callback as (model: any, index: number) => boolean)(item, index);
|
|
1072
|
+
if (result) {
|
|
1073
|
+
results.push(item);
|
|
1074
|
+
}
|
|
1075
|
+
});
|
|
1076
|
+
|
|
1077
|
+
return results;
|
|
1078
|
+
}
|
|
1079
|
+
|
|
1080
|
+
mapSubModels<K extends keyof Structure['subModels'], R>(
|
|
1081
|
+
subKey: K,
|
|
1082
|
+
callback: (model: ArrayElementType<Structure['subModels'][K]>, index: number) => R,
|
|
1083
|
+
): R[] {
|
|
1084
|
+
const model = (this.subModels as any)[subKey as string];
|
|
1085
|
+
|
|
1086
|
+
if (!model) {
|
|
1087
|
+
return [];
|
|
1088
|
+
}
|
|
1089
|
+
|
|
1090
|
+
const results: R[] = [];
|
|
1091
|
+
|
|
1092
|
+
_.castArray(model)
|
|
1093
|
+
.sort((a, b) => (a.sortIndex || 0) - (b.sortIndex || 0))
|
|
1094
|
+
.forEach((item, index) => {
|
|
1095
|
+
const result = (callback as (model: any, index: number) => R)(item, index);
|
|
1096
|
+
results.push(result);
|
|
1097
|
+
});
|
|
1098
|
+
|
|
1099
|
+
return results;
|
|
1100
|
+
}
|
|
1101
|
+
|
|
1102
|
+
hasSubModel<K extends keyof Structure['subModels']>(subKey: K) {
|
|
1103
|
+
const subModel = (this.subModels as any)[subKey as string];
|
|
1104
|
+
if (!subModel) {
|
|
1105
|
+
return false;
|
|
1106
|
+
}
|
|
1107
|
+
return _.castArray(subModel).length > 0;
|
|
1108
|
+
}
|
|
1109
|
+
|
|
1110
|
+
findSubModel<K extends keyof Structure['subModels'], R>(
|
|
1111
|
+
subKey: K,
|
|
1112
|
+
callback: (model: ArrayElementType<Structure['subModels'][K]>) => R,
|
|
1113
|
+
): ArrayElementType<Structure['subModels'][K]> | null {
|
|
1114
|
+
const model = (this.subModels as any)[subKey as string];
|
|
1115
|
+
|
|
1116
|
+
if (!model) {
|
|
1117
|
+
return null;
|
|
1118
|
+
}
|
|
1119
|
+
|
|
1120
|
+
return (
|
|
1121
|
+
(_.castArray(model).find((item) => {
|
|
1122
|
+
return (callback as (model: any) => R)(item);
|
|
1123
|
+
}) as ArrayElementType<Structure['subModels'][K]> | undefined) || null
|
|
1124
|
+
);
|
|
1125
|
+
}
|
|
1126
|
+
|
|
1127
|
+
createRootModel(options) {
|
|
1128
|
+
return this.flowEngine.createModel(options);
|
|
1129
|
+
}
|
|
1130
|
+
|
|
1131
|
+
async applySubModelsAutoFlows<K extends keyof Structure['subModels']>(
|
|
1132
|
+
subKey: K,
|
|
1133
|
+
inputArgs?: Record<string, any>,
|
|
1134
|
+
shared?: Record<string, any>,
|
|
1135
|
+
) {
|
|
1136
|
+
await Promise.all(
|
|
1137
|
+
this.mapSubModels(subKey, async (sub) => {
|
|
1138
|
+
await sub.applyAutoFlows(inputArgs);
|
|
1139
|
+
}),
|
|
1140
|
+
);
|
|
1141
|
+
}
|
|
1142
|
+
|
|
1143
|
+
/**
|
|
1144
|
+
* 创建一个 fork 实例,实现"一份数据(master)多视图(fork)"的能力。
|
|
1145
|
+
* @param {IModelComponentProps} [localProps={}] fork 专属的局部 props,优先级高于 master.props
|
|
1146
|
+
* @param {string} [key] 可选的 key,用于复用 fork 实例。如果提供了 key,会尝试复用已存在的 fork
|
|
1147
|
+
* @returns {ForkFlowModel<this>} 创建的 fork 实例
|
|
1148
|
+
*/
|
|
1149
|
+
createFork(
|
|
1150
|
+
localProps?: IModelComponentProps,
|
|
1151
|
+
key?: string,
|
|
1152
|
+
options?: { sharedProperties?: string[]; register?: boolean },
|
|
1153
|
+
): ForkFlowModel<this> {
|
|
1154
|
+
// 如果提供了 key,尝试从缓存中获取
|
|
1155
|
+
if (key) {
|
|
1156
|
+
const cachedFork = this.forkCache.get(key);
|
|
1157
|
+
if (cachedFork && !(cachedFork as any).disposed) {
|
|
1158
|
+
// 更新 localProps
|
|
1159
|
+
cachedFork.setProps(localProps || {});
|
|
1160
|
+
return cachedFork as ForkFlowModel<this>;
|
|
1161
|
+
}
|
|
1162
|
+
}
|
|
1163
|
+
|
|
1164
|
+
// 创建新的 fork 实例
|
|
1165
|
+
const forkId = this.forks.size; // 当前集合大小作为索引
|
|
1166
|
+
const fork = new ForkFlowModel<this>(this as any, localProps, forkId);
|
|
1167
|
+
if (options?.register !== false) {
|
|
1168
|
+
this.forks.add(fork as any);
|
|
1169
|
+
}
|
|
1170
|
+
|
|
1171
|
+
// 如果提供了 key,将 fork 缓存起来
|
|
1172
|
+
if (key && options?.register !== false) {
|
|
1173
|
+
this.forkCache.set(key, fork as any);
|
|
1174
|
+
}
|
|
1175
|
+
|
|
1176
|
+
return fork as ForkFlowModel<this>;
|
|
1177
|
+
}
|
|
1178
|
+
|
|
1179
|
+
clearForks() {
|
|
1180
|
+
console.log(`FlowModel ${this.uid} clearing all forks.`);
|
|
1181
|
+
// 主动使所有 fork 失效
|
|
1182
|
+
if (this.forks?.size) {
|
|
1183
|
+
this.forks.forEach((fork) => fork.dispose());
|
|
1184
|
+
this.forks.clear();
|
|
1185
|
+
}
|
|
1186
|
+
// 清理 fork 缓存
|
|
1187
|
+
this.forkCache.clear();
|
|
1188
|
+
}
|
|
1189
|
+
|
|
1190
|
+
getFork(key: string) {
|
|
1191
|
+
return this.forkCache.get(key);
|
|
1192
|
+
}
|
|
1193
|
+
|
|
1194
|
+
/**
|
|
1195
|
+
* 移动当前模型到目标模型的位置
|
|
1196
|
+
* @param {FlowModel} targetModel 目标模型
|
|
1197
|
+
* @param {PersistOptions} [options] 可选的持久化选项
|
|
1198
|
+
* @returns {boolean} 是否成功移动
|
|
1199
|
+
*/
|
|
1200
|
+
moveTo(targetModel: FlowModel, options?: PersistOptions) {
|
|
1201
|
+
if (!this.flowEngine) {
|
|
1202
|
+
throw new Error('FlowEngine is not set on this model. Please set flowEngine before saving.');
|
|
1203
|
+
}
|
|
1204
|
+
return this.flowEngine.moveModel(this.uid, targetModel.uid, options);
|
|
1205
|
+
}
|
|
1206
|
+
|
|
1207
|
+
remove() {
|
|
1208
|
+
if (!this.flowEngine) {
|
|
1209
|
+
throw new Error('FlowEngine is not set on this model. Please set flowEngine before saving.');
|
|
1210
|
+
}
|
|
1211
|
+
this.observerDispose();
|
|
1212
|
+
this.invalidateAutoFlowCache(true);
|
|
1213
|
+
return this.flowEngine.removeModel(this.uid);
|
|
1214
|
+
}
|
|
1215
|
+
|
|
1216
|
+
async save() {
|
|
1217
|
+
if (!this.flowEngine) {
|
|
1218
|
+
throw new Error('FlowEngine is not set on this model. Please set flowEngine before saving.');
|
|
1219
|
+
}
|
|
1220
|
+
return this.flowEngine.saveModel(this);
|
|
1221
|
+
}
|
|
1222
|
+
|
|
1223
|
+
async saveStepParams() {
|
|
1224
|
+
return this.flowEngine.saveModel(this, { onlyStepParams: true });
|
|
1225
|
+
}
|
|
1226
|
+
|
|
1227
|
+
async destroy() {
|
|
1228
|
+
if (!this.flowEngine) {
|
|
1229
|
+
throw new Error('FlowEngine is not set on this model. Please set flowEngine before deleting.');
|
|
1230
|
+
}
|
|
1231
|
+
this.observerDispose();
|
|
1232
|
+
this.invalidateAutoFlowCache(true);
|
|
1233
|
+
// 从 FlowEngine 中销毁模型
|
|
1234
|
+
return this.flowEngine.destroyModel(this.uid);
|
|
1235
|
+
}
|
|
1236
|
+
|
|
1237
|
+
/**
|
|
1238
|
+
* @deprecated
|
|
1239
|
+
* 打开步骤设置对话框
|
|
1240
|
+
* 用于配置流程中特定步骤的参数和设置
|
|
1241
|
+
* @param {string} flowKey 流程的唯一标识符
|
|
1242
|
+
* @param {string} stepKey 步骤的唯一标识符
|
|
1243
|
+
* @returns {void}
|
|
1244
|
+
*/
|
|
1245
|
+
openStepSettingsDialog(flowKey: string, stepKey: string) {
|
|
1246
|
+
// 创建流程运行时上下文
|
|
1247
|
+
const flow = this.getFlow(flowKey);
|
|
1248
|
+
const step = flow?.steps?.[stepKey];
|
|
1249
|
+
|
|
1250
|
+
if (!flow || !step) {
|
|
1251
|
+
console.error(`Flow ${flowKey} or step ${stepKey} not found`);
|
|
1252
|
+
return;
|
|
1253
|
+
}
|
|
1254
|
+
|
|
1255
|
+
const ctx = new FlowRuntimeContext(this, flowKey, 'settings');
|
|
1256
|
+
setupRuntimeContextSteps(ctx, flow.steps, this, flowKey);
|
|
1257
|
+
ctx.defineProperty('currentStep', { value: step });
|
|
1258
|
+
|
|
1259
|
+
return openStepSettingsDialogFn({
|
|
1260
|
+
model: this,
|
|
1261
|
+
flowKey,
|
|
1262
|
+
stepKey,
|
|
1263
|
+
ctx,
|
|
1264
|
+
});
|
|
1265
|
+
}
|
|
1266
|
+
|
|
1267
|
+
/**
|
|
1268
|
+
* 配置必填步骤参数
|
|
1269
|
+
* 用于在一个分步表单中配置所有需要参数的步骤
|
|
1270
|
+
* @param {number | string} [dialogWidth=800] 对话框宽度,默认为800
|
|
1271
|
+
* @param {string} [dialogTitle='步骤参数配置'] 对话框标题,默认为'步骤参数配置'
|
|
1272
|
+
* @returns {Promise<any>} 返回表单提交的值
|
|
1273
|
+
*/
|
|
1274
|
+
async configureRequiredSteps(dialogWidth?: number | string, dialogTitle?: string) {
|
|
1275
|
+
return openRequiredParamsStepFormDialogFn({
|
|
1276
|
+
model: this,
|
|
1277
|
+
dialogWidth,
|
|
1278
|
+
dialogTitle,
|
|
1279
|
+
});
|
|
1280
|
+
}
|
|
1281
|
+
|
|
1282
|
+
/**
|
|
1283
|
+
* @deprecated
|
|
1284
|
+
* @param dialogWidth
|
|
1285
|
+
* @param dialogTitle
|
|
1286
|
+
* @returns
|
|
1287
|
+
*/
|
|
1288
|
+
async openPresetStepSettingsDialog(dialogWidth?: number | string, dialogTitle?: string) {
|
|
1289
|
+
return this.configureRequiredSteps(dialogWidth, dialogTitle);
|
|
1290
|
+
}
|
|
1291
|
+
|
|
1292
|
+
async openFlowStepSettingsDialog(options: {
|
|
1293
|
+
flowKey?: string;
|
|
1294
|
+
stepKey?: string;
|
|
1295
|
+
preset?: boolean;
|
|
1296
|
+
uiMode?: 'drawer' | 'dialog';
|
|
1297
|
+
}) {}
|
|
1298
|
+
|
|
1299
|
+
get translate() {
|
|
1300
|
+
return this.flowEngine.translate.bind(this.flowEngine);
|
|
1301
|
+
}
|
|
1302
|
+
|
|
1303
|
+
// TODO: 不完整,需要考虑 sub-model 的情况
|
|
1304
|
+
serialize(): Record<string, any> {
|
|
1305
|
+
const data = {
|
|
1306
|
+
uid: this.uid,
|
|
1307
|
+
..._.omit(this._options, ['flowEngine']),
|
|
1308
|
+
stepParams: this.stepParams,
|
|
1309
|
+
sortIndex: this.sortIndex,
|
|
1310
|
+
};
|
|
1311
|
+
const subModels = this.subModels as {
|
|
1312
|
+
[key: string]: FlowModel | FlowModel[];
|
|
1313
|
+
};
|
|
1314
|
+
for (const subModelKey in subModels) {
|
|
1315
|
+
data.subModels = data.subModels || {};
|
|
1316
|
+
if (Array.isArray(subModels[subModelKey])) {
|
|
1317
|
+
(data.subModels as any)[subModelKey] = (subModels[subModelKey] as FlowModel[]).map((model, index) => ({
|
|
1318
|
+
...model.serialize(),
|
|
1319
|
+
sortIndex: index,
|
|
1320
|
+
}));
|
|
1321
|
+
} else if (subModels[subModelKey] instanceof FlowModel) {
|
|
1322
|
+
(data.subModels as any)[subModelKey] = (subModels[subModelKey] as FlowModel).serialize();
|
|
1323
|
+
}
|
|
1324
|
+
}
|
|
1325
|
+
for (const [key, flow] of this.flowRegistry.getFlows()) {
|
|
1326
|
+
data['flowRegistry'] = data['flowRegistry'] || {};
|
|
1327
|
+
data['flowRegistry'][key] = flow.toData();
|
|
1328
|
+
}
|
|
1329
|
+
return data;
|
|
1330
|
+
}
|
|
1331
|
+
|
|
1332
|
+
/**
|
|
1333
|
+
* Opens the flow settings dialog for this flow model.
|
|
1334
|
+
* @param options - Configuration options for opening flow settings, excluding the model property
|
|
1335
|
+
* @returns A promise that resolves when the flow settings dialog is opened
|
|
1336
|
+
*/
|
|
1337
|
+
async openFlowSettings(options?: Omit<FlowSettingsOpenOptions, 'model'>) {
|
|
1338
|
+
return this.flowEngine.flowSettings.open({
|
|
1339
|
+
model: this,
|
|
1340
|
+
...options,
|
|
1341
|
+
});
|
|
1342
|
+
}
|
|
1343
|
+
|
|
1344
|
+
// =============================
|
|
1345
|
+
// Dynamic flows (disabled)
|
|
1346
|
+
// The following APIs are kept as comments to preserve context
|
|
1347
|
+
// =============================
|
|
1348
|
+
/*
|
|
1349
|
+
async openDynamicFlowsEditor(
|
|
1350
|
+
options?: Omit<FlowSettingsOpenOptions, 'model' | 'flowKey' | 'flowKeys' | 'stepKey' | 'preset'>,
|
|
1351
|
+
) {
|
|
1352
|
+
return this.flowEngine.flowSettings.openDynamicFlowsEditor({
|
|
1353
|
+
model: this,
|
|
1354
|
+
...options,
|
|
1355
|
+
});
|
|
1356
|
+
}
|
|
1357
|
+
|
|
1358
|
+
#dynamicFlows: FlowDefinition[] = [];
|
|
1359
|
+
|
|
1360
|
+
async loadDynamicFlows(): Promise<FlowDefinition[]> {
|
|
1361
|
+
return JSON.parse(localStorage.getItem('DYNAMIC_FLOWS') || '[]');
|
|
1362
|
+
}
|
|
1363
|
+
|
|
1364
|
+
async saveDynamicFlows(): Promise<void> {
|
|
1365
|
+
localStorage.setItem('DYNAMIC_FLOWS', JSON.stringify(this.#dynamicFlows));
|
|
1366
|
+
}
|
|
1367
|
+
|
|
1368
|
+
setDynamicFlows(flows: FlowDefinition[]): void {
|
|
1369
|
+
this.#dynamicFlows = flows;
|
|
1370
|
+
flows.forEach((flow) => {
|
|
1371
|
+
// @ts-ignore
|
|
1372
|
+
this.constructor.registerFlow(flow);
|
|
1373
|
+
});
|
|
1374
|
+
}
|
|
1375
|
+
|
|
1376
|
+
getDynamicFlows(): FlowDefinitionOptions[] {
|
|
1377
|
+
return this.#dynamicFlows;
|
|
1378
|
+
}
|
|
1379
|
+
*/
|
|
1380
|
+
}
|
|
1381
|
+
|
|
1382
|
+
export class ErrorFlowModel extends FlowModel {
|
|
1383
|
+
public errorMessage: string;
|
|
1384
|
+
|
|
1385
|
+
setErrorMessage(msg: string) {
|
|
1386
|
+
this.errorMessage = msg;
|
|
1387
|
+
}
|
|
1388
|
+
|
|
1389
|
+
public render() {
|
|
1390
|
+
return <Typography.Text type="danger">{this.errorMessage}</Typography.Text>;
|
|
1391
|
+
}
|
|
1392
|
+
}
|
|
1393
|
+
|
|
1394
|
+
export function defineFlow<TModel extends FlowModel = FlowModel>(
|
|
1395
|
+
definition: FlowDefinitionOptions,
|
|
1396
|
+
): FlowDefinitionOptions<TModel> {
|
|
1397
|
+
return definition as FlowDefinitionOptions<TModel>;
|
|
1398
|
+
}
|