UNPKG

@nocobase/flow-engine

Version:

A standalone flow engine for NocoBase, managing workflows, models, and actions.

1,134 lines (1,127 loc) 42 kB
/** * This file is part of the NocoBase (R) project. * Copyright (c) 2020-2024 NocoBase Co., Ltd. * Authors: NocoBase Team. * * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License. * For more information, please refer to: https://www.nocobase.com/agreement. */ var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __typeError = (msg) => { throw TypeError(msg); }; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value); var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg); var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj)); var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value); var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value); var flowModel_exports = {}; __export(flowModel_exports, { ErrorFlowModel: () => ErrorFlowModel, FlowModel: () => FlowModel, ModelRenderMode: () => ModelRenderMode, defineFlow: () => defineFlow }); module.exports = __toCommonJS(flowModel_exports); var import_reactive = require("@formily/reactive"); var import_reactive_react = require("@formily/reactive-react"); var import_lodash = __toESM(require("lodash")); var import_react = __toESM(require("react")); var import_secure = require("uid/secure"); var import_StepRequiredSettingsDialog = require("../components/settings/wrappers/contextual/StepRequiredSettingsDialog"); var import_StepSettingsDialog = require("../components/settings/wrappers/contextual/StepSettingsDialog"); var import_emitter = require("../emitter"); var import_InstanceFlowRegistry = require("../flow-registry/InstanceFlowRegistry"); var import_flowContext = require("../flowContext"); var import_flowEngine = require("../flowEngine"); var import_utils = require("../utils"); var import_lib = require("antd/lib"); var import_ModelActionRegistry = require("../action-registry/ModelActionRegistry"); var import_utils2 = require("../components/subModel/utils"); var import_ModelEventRegistry = require("../event-registry/ModelEventRegistry"); var import_GlobalFlowRegistry = require("../flow-registry/GlobalFlowRegistry"); var import_forkFlowModel = require("./forkFlowModel"); var _flowContext; const classActionRegistries = /* @__PURE__ */ new WeakMap(); const classEventRegistries = /* @__PURE__ */ new WeakMap(); const modelMetas = /* @__PURE__ */ new WeakMap(); const modelGlobalRegistries = /* @__PURE__ */ new WeakMap(); var ModelRenderMode = /* @__PURE__ */ ((ModelRenderMode2) => { ModelRenderMode2["ReactElement"] = "reactElement"; ModelRenderMode2["RenderFunction"] = "renderFunction"; return ModelRenderMode2; })(ModelRenderMode || {}); const _FlowModel = class _FlowModel { constructor(options) { __publicField(this, "uid"); __publicField(this, "sortIndex"); __publicField(this, "hidden", false); __publicField(this, "props", {}); __publicField(this, "stepParams", {}); __publicField(this, "flowEngine"); __publicField(this, "parent"); __publicField(this, "subModels"); __publicField(this, "_options"); __publicField(this, "_title"); __publicField(this, "isNew", false); // 标记是否为新建状态 /** * 所有 fork 实例的引用集合。 * 使用 Set 便于在销毁时主动遍历并调用 dispose,避免悬挂引用。 */ __publicField(this, "forks", /* @__PURE__ */ new Set()); __publicField(this, "emitter", new import_emitter.Emitter()); /** * 基于 key 的 fork 实例缓存,用于复用 fork 实例 */ __publicField(this, "forkCache", /* @__PURE__ */ new Map()); /** * 上一次 applyAutoFlows 的执行参数 */ __publicField(this, "_lastAutoRunParams", null); __publicField(this, "observerDispose"); __privateAdd(this, _flowContext); /** * 原始 render 方法的引用 */ __publicField(this, "_originalRender", null); /** * 缓存的响应式包装器组件(每个实例一个) */ __publicField(this, "_reactiveWrapperCache"); __publicField(this, "flowRegistry"); __publicField(this, "_cleanRun"); __publicField(this, "_dispatchEventWithDebounce", import_lodash.default.debounce(async (eventName, inputArgs) => { return this._dispatchEvent(eventName, inputArgs); }, 100)); /** * 重新执行上一次的 applyAutoFlows,保持参数一致 * 如果之前没有执行过,则直接跳过 * 使用 lodash debounce 避免频繁调用 */ __publicField(this, "_rerunLastAutoRun", import_lodash.default.debounce(async () => { if (this._lastAutoRunParams) { try { await this.applyAutoFlows(...this._lastAutoRunParams); } catch (error) { console.error("FlowModel._rerunLastAutoRun: Error during rerun:", error); } } }, 100)); if (!options.flowEngine) { throw new Error("FlowModel must be initialized with a FlowEngine instance."); } this.flowEngine = options.flowEngine; if (this.flowEngine.getModel(options.uid)) { return this.flowEngine.getModel(options.uid); } if (!options.uid) { options.uid = (0, import_secure.uid)(); } this.uid = options.uid; this.props = { ...options.props }; this.stepParams = options.stepParams || {}; this.subModels = {}; this.sortIndex = options.sortIndex || 0; this._options = options; (0, import_reactive.define)(this, { hidden: import_reactive.observable, props: import_reactive.observable, subModels: import_reactive.observable.shallow, stepParams: import_reactive.observable, // setProps: action, setProps: import_reactive.batch, // setStepParams: action, setStepParams: import_reactive.batch }); this.flowRegistry = new import_InstanceFlowRegistry.InstanceFlowRegistry(this); this.flowRegistry.addFlows(options.flowRegistry); this.observerDispose = (0, import_reactive.observe)(this.stepParams, (changed) => { if (changed.type === "set" && import_lodash.default.isEqual(changed.value, changed.oldValue)) { return; } if (this.flowEngine) { this.invalidateAutoFlowCache(); } this._rerunLastAutoRun(); this.forks.forEach((fork) => { fork.rerender(); }); }); try { this.setupReactiveRender(); } catch (error) { console.error(`Failed to setup reactive render for ${this.constructor.name}:`, error); if (typeof this.render !== "function") { this.render = () => import_react.default.createElement("div", null, "Render method not available"); } } this._cleanRun = !!options["cleanRun"]; } /** * 当 flowSettings.enabled 且 model.hidden 为 true 时用于渲染设置态组件(实例方法,子类可覆盖)。 * 基类默认仅返回一个透明度降低的占位元素 */ renderHiddenInConfig() { var _a; return /* @__PURE__ */ import_react.default.createElement("span", { style: { opacity: 0.5 } }, ((_a = this.translate) == null ? void 0 : _a.call(this, "Hidden")) || "Hidden"); } /** * 对外暴露的上下文: */ get context() { if (!__privateGet(this, _flowContext)) { __privateSet(this, _flowContext, new import_flowContext.FlowModelContext(this)); } return __privateGet(this, _flowContext); } on(eventName, listener) { this.emitter.on(eventName, listener); } onInit(options) { } /** * 通过 AddSubModelButton 添加为子模型后调用(子类可覆盖) */ async afterAddAsSubModel() { } get async() { return this._options.async || false; } get use() { return this._options.use; } get subKey() { return this._options.subKey; } get subType() { return this._options.subType; } get reactView() { return this.flowEngine.reactView; } get parentId() { return this._options.parentId; } static get meta() { return modelMetas.get(this); } static get globalFlowRegistry() { const Cls = this; let reg = modelGlobalRegistries.get(Cls); if (!reg) { reg = new import_GlobalFlowRegistry.GlobalFlowRegistry(Cls); modelGlobalRegistries.set(Cls, reg); } return reg; } // 获取当前类的动作注册表(含父子链注入),按类缓存 static get actionRegistry() { const ModelClass = this; let registry = classActionRegistries.get(ModelClass); if (!registry) { let parentRegistry = null; const ParentClass = Object.getPrototypeOf(ModelClass); if (ParentClass && ParentClass !== Function.prototype && ParentClass !== Object.prototype) { const isSubclassOfFlowModel = ParentClass === _FlowModel || (0, import_utils.isInheritedFrom)(ParentClass, _FlowModel); if (isSubclassOfFlowModel) { parentRegistry = ParentClass.actionRegistry; } } registry = new import_ModelActionRegistry.ModelActionRegistry(ModelClass, parentRegistry); classActionRegistries.set(ModelClass, registry); } return registry; } // 获取当前类的事件注册表(含父子链注入),按类缓存 static get eventRegistry() { const ModelClass = this; let registry = classEventRegistries.get(ModelClass); if (!registry) { let parentRegistry = null; const ParentClass = Object.getPrototypeOf(ModelClass); if (ParentClass && ParentClass !== Function.prototype && ParentClass !== Object.prototype) { const isSubclassOfFlowModel = ParentClass === _FlowModel || (0, import_utils.isInheritedFrom)(ParentClass, _FlowModel); if (isSubclassOfFlowModel) { parentRegistry = ParentClass.eventRegistry; } } registry = new import_ModelEventRegistry.ModelEventRegistry(ModelClass, parentRegistry); classEventRegistries.set(ModelClass, registry); } return registry; } /** * 注册仅当前 FlowModel 类及其子类可用的 Action。 * 该注册是类级别的,不会影响全局(FlowEngine)的 Action 注册。 */ static registerAction(definition) { this.actionRegistry.registerAction(definition); } /** * 批量注册仅当前 FlowModel 类及其子类可用的 Actions。 */ static registerActions(actions) { this.actionRegistry.registerActions(actions); } /** * 注册仅当前 FlowModel 类及其子类可用的 Event。 * 该注册是类级别的,不会影响全局(FlowEngine)的 Event 注册。 */ static registerEvent(definition) { this.eventRegistry.registerEvent(definition); } /** * 批量注册仅当前 FlowModel 类及其子类可用的 Events。 */ static registerEvents(events) { this.eventRegistry.registerEvents(events); } static buildChildrenFromModels(ctx, Models) { return Models.map((M) => (0, import_utils2.buildSubModelItem)(M, ctx, true)); } get title() { var _a; return this.translate(this._title) || this.translate((_a = this.constructor["meta"]) == null ? void 0 : _a.label); } setTitle(value) { this._title = value; } setHidden(value) { this.hidden = !!value; } _createSubModels(subModels) { let mergedSubModels = subModels || {}; try { const Cls = this.constructor; const meta = Cls.meta; const metaCreate = meta == null ? void 0 : meta.createModelOptions; if (metaCreate && typeof metaCreate === "object" && metaCreate.subModels) { mergedSubModels = import_lodash.default.merge({}, import_lodash.default.cloneDeep(metaCreate.subModels || {}), import_lodash.default.cloneDeep(subModels || {})); } } catch (e) { } Object.entries(mergedSubModels || {}).forEach(([key, value]) => { if (Array.isArray(value)) { value.sort((a, b) => (a.sortIndex || 0) - (b.sortIndex || 0)).forEach((item) => { this.addSubModel(key, item); }); } else { this.setSubModel(key, value); } }); } invalidateAutoFlowCache(deep = false) { if (this.flowEngine) { const cacheKey = import_flowEngine.FlowEngine.generateApplyFlowCacheKey("autoFlow", "all", this.uid); this.flowEngine.applyFlowCache.delete(cacheKey); this.forks.forEach((fork) => { const forkCacheKey = import_flowEngine.FlowEngine.generateApplyFlowCacheKey(`${fork["forkId"]}`, "all", this.uid); this.flowEngine.applyFlowCache.delete(forkCacheKey); }); } if (deep) { const subModelKeys = Object.keys(this.subModels); for (const subModelKey of subModelKeys) { const subModelValue = this.subModels[subModelKey]; if (Array.isArray(subModelValue)) { for (const subModel of subModelValue) { subModel.invalidateAutoFlowCache(deep); } } else if (subModelValue instanceof _FlowModel) { subModelValue.invalidateAutoFlowCache(deep); } } } } /** * 设置FlowEngine实例 * @param {FlowEngine} flowEngine FlowEngine实例 */ setFlowEngine(flowEngine) { } static define(meta) { modelMetas.set(this, meta); } /** * 注册一个 Flow。 * @template TModel 具体的FlowModel子类类型 * @param {string | FlowDefinitionOptions<TModel>} keyOrDefinition 流程的 Key 或 FlowDefinitionOptions 对象。 * 如果为字符串,则为流程 Key,需要配合 flowDefinition 参数。 * 如果为对象,则为包含 key 属性的完整 FlowDefinitionOptions。 * @param {FlowDefinitionOptions<TModel>} [flowDefinition] 当第一个参数为流程 Key 时,此参数为流程的定义。 * @returns {void} */ static registerFlow(keyOrDefinition, flowDefinition) { const Cls = this; if (typeof keyOrDefinition === "string") { Cls.globalFlowRegistry.addFlow(keyOrDefinition, flowDefinition); } else { Cls.globalFlowRegistry.addFlow(keyOrDefinition.key, keyOrDefinition); } } // /** // * 清空所有注册的流程定义。在测试中用来清理已注册的流,防止对其它测试产生影响。 // */ // public static clearFlows(): void { // modelFlows = new WeakMap<typeof FlowModel, Map<string, FlowDefinition>>(); // } /** * 获取已注册的流程定义。 * 如果当前类不存在对应的flow,会继续往父类查找。 * @param {string} key 流程 Key。 * @returns {FlowDefinition | undefined} 流程定义,如果未找到则返回 undefined。 */ getFlow(key) { if (this.flowRegistry.hasFlow(key)) { return this.flowRegistry.getFlow(key); } const Cls = this.constructor; return Cls.globalFlowRegistry.getFlow(key); } /** * 注册一个实例级别的流程定义。 * @template TModel 具体的FlowModel子类类型 * @param {string | FlowDefinitionOptions<TModel>} keyOrDefinition 流程的 Key 或 FlowDefinitionOptions 对象。 * @param {FlowDefinitionOptions<TModel>} [flowDefinition] 当第一个参数为流程 Key 时,此参数为流程的定义。 * @returns {FlowDefinition} 注册的流程定义实例 */ registerFlow(keyOrDefinition, flowDefinition) { if (typeof keyOrDefinition === "string") { return this.flowRegistry.addFlow(keyOrDefinition, flowDefinition); } else { return this.flowRegistry.addFlow(keyOrDefinition.key, keyOrDefinition); } } /** * 获取当前模型可用的所有 Actions: * - 包含全局(FlowEngine)注册的 Actions; * - 合并类级(FlowModel.registerAction(s))注册的 Actions,并考虑继承(子类覆盖父类同名 Action)。 */ getActions() { var _a; const ModelClass = this.constructor; const merged = ModelClass.actionRegistry.getActions(); const actions = /* @__PURE__ */ new Map(); const globalActions = (_a = this.flowEngine) == null ? void 0 : _a.getActions(); if (globalActions) for (const [k, v] of globalActions) actions.set(k, v); for (const [k, v] of merged) actions.set(k, v); return actions; } /** * 获取当前模型可用的所有 Events: * - 包含全局(FlowEngine)注册的 Events; * - 合并类级(FlowModel.registerEvent(s))注册的 Events,并考虑继承(子类覆盖父类同名 Event)。 */ getEvents() { var _a; const ModelClass = this.constructor; const merged = ModelClass.eventRegistry.getEvents(); const events = /* @__PURE__ */ new Map(); const globalEvents = (_a = this.flowEngine) == null ? void 0 : _a.getEvents(); if (globalEvents) for (const [k, v] of globalEvents) events.set(k, v); for (const [k, v] of merged) events.set(k, v); return events; } /** * 获取指定名称的 Event(优先返回类级注册的,未找到则回退到全局)。 */ getEvent(name) { var _a; const ModelClass = this.constructor; const own = ModelClass.eventRegistry.getEvent(name); if (own) return own; return (_a = this.flowEngine) == null ? void 0 : _a.getEvent(name); } /** * 获取指定名称的 Action(优先返回类级注册的,未找到则回退到全局)。 */ getAction(name) { var _a; const ModelClass = this.constructor; const own = ModelClass.actionRegistry.getAction(name); if (own) return own; return (_a = this.flowEngine) == null ? void 0 : _a.getAction(name); } getFlows() { const instanceFlows = this.flowRegistry.getFlows(); const staticFlows = this.constructor.globalFlowRegistry.getFlows(); const instanceKeys = new Set(instanceFlows.keys()); const staticEntries = Array.from(staticFlows.entries()).filter(([key]) => !instanceKeys.has(key)); const instanceEntries = Array.from(instanceFlows.entries()); const allEntries = [...staticEntries, ...instanceEntries]; allEntries.sort(([, a], [, b]) => { const sa = a.sort ?? 0; const sb = b.sort ?? 0; if (sa !== sb) return sa - sb; return 0; }); return new Map(allEntries); } setProps(props, value) { if (typeof props === "string") { this.props[props] = value; } else { this.props = { ...this.props, ...props }; } } getProps() { return this.props; } setStepParams(flowKeyOrAllParams, stepKeyOrStepsParams, params) { if (typeof flowKeyOrAllParams === "string") { const flowKey = flowKeyOrAllParams; if (typeof stepKeyOrStepsParams === "string" && params !== void 0) { if (!this.stepParams[flowKey]) { this.stepParams[flowKey] = {}; } this.stepParams[flowKey][stepKeyOrStepsParams] = { ...this.stepParams[flowKey][stepKeyOrStepsParams], ...params }; } else if (typeof stepKeyOrStepsParams === "object" && stepKeyOrStepsParams !== null) { this.stepParams[flowKey] = { ...this.stepParams[flowKey] || {}, ...stepKeyOrStepsParams }; } } else if (typeof flowKeyOrAllParams === "object" && flowKeyOrAllParams !== null) { for (const fk in flowKeyOrAllParams) { if (Object.prototype.hasOwnProperty.call(flowKeyOrAllParams, fk)) { this.stepParams[fk] = { ...this.stepParams[fk] || {}, ...flowKeyOrAllParams[fk] }; } } } } getStepParams(flowKey, stepKey) { var _a; if (flowKey && stepKey) { return (_a = this.stepParams[flowKey]) == null ? void 0 : _a[stepKey]; } if (flowKey) { return this.stepParams[flowKey]; } return this.stepParams; } async applyFlow(flowKey, inputArgs, runId) { const currentFlowEngine = this.flowEngine; if (!currentFlowEngine) { console.warn("FlowEngine not available on this model for applyFlow. Check and model.flowEngine setup."); return Promise.reject(new Error("FlowEngine not available for applyFlow. Please set flowEngine on the model.")); } const isFork = this.isFork === true; const target = this; console.log( `[FlowModel] applyFlow: uid=${this.uid}, flowKey=${flowKey}, isFork=${isFork}, cleanRun=${this.cleanRun}, targetIsFork=${(target == null ? void 0 : target.isFork) === true}` ); return currentFlowEngine.executor.runFlow(target, flowKey, inputArgs, runId); } async _dispatchEvent(eventName, inputArgs) { const currentFlowEngine = this.flowEngine; if (!currentFlowEngine) { console.warn("FlowEngine not available on this model for dispatchEvent. Please set flowEngine on the model."); return; } const isFork = this.isFork === true; const target = this; console.log( `[FlowModel] dispatchEvent: uid=${this.uid}, event=${eventName}, isFork=${isFork}, cleanRun=${this.cleanRun}, targetIsFork=${(target == null ? void 0 : target.isFork) === true}` ); await currentFlowEngine.executor.dispatchEvent(target, eventName, inputArgs); } async dispatchEvent(eventName, inputArgs, options) { if (options == null ? void 0 : options.debounce) { return this._dispatchEventWithDebounce(eventName, inputArgs); } return this._dispatchEvent(eventName, inputArgs); } /** * 获取所有自动应用流程定义(保持 getFlows 的顺序,即按 sort 排序) * @returns {FlowDefinition[]} 自动应用流程定义数组(已按 sort 排序) */ getAutoFlows() { const allFlows = this.getFlows(); const autoFlows = Array.from(allFlows.values()).filter((flow) => { if (flow.on) { return false; } if (flow.manual === true) { return false; } return true; }); return autoFlows; } /** * 自动流程执行前钩子。 * 子类可覆盖;可抛出 FlowExitException 提前终止。 */ async onBeforeAutoFlows(inputArgs) { } /** * 自动流程执行后钩子。 * 子类可覆盖。 */ async onAfterAutoFlows(results, inputArgs) { } /** * 自动流程错误钩子。 * 子类可覆盖。 */ async onAutoFlowsError(error, inputArgs) { } useHooksBeforeRender() { } async applyAutoFlows(...args) { var _a, _b; const [inputArgs, useCache = true] = args; const cacheKey = useCache ? import_flowEngine.FlowEngine.generateApplyFlowCacheKey(this["forkId"] ?? "autoFlow", "all", this.uid) : null; if (!import_lodash.default.isEqual(inputArgs, (_a = this._lastAutoRunParams) == null ? void 0 : _a[0]) && cacheKey) { this.flowEngine.applyFlowCache.delete(cacheKey); } this._lastAutoRunParams = args; try { await this.onBeforeAutoFlows(inputArgs); } catch (error) { if (error instanceof import_utils.FlowExitException) { (_b = this.context.logger) == null ? void 0 : _b.debug(`[FlowModel.applyAutoFlows] ${error.message}`); return []; } try { await this.onAutoFlowsError(error, inputArgs); } catch (_2) { } throw error; } let results = []; try { results = await this.flowEngine.executor.runAutoFlows(this, inputArgs, useCache); } catch (error) { try { await this.onAutoFlowsError(error, inputArgs); } catch (_2) { } throw error; } try { await this.onAfterAutoFlows(results, inputArgs); } catch (error) { try { await this.onAutoFlowsError(error, inputArgs); } catch (_2) { } throw error; } return results; } /** * 智能检测是否应该跳过响应式包装 * 说明: * - 仅基于标记判断,不会执行 render,避免出现“预调用 render”带来的副作用和双调用问题。 * - 当子类需要返回函数(如表格列的单元格渲染器),应在子类上设置静态属性 `renderReturnsFunction = true`。 */ shouldSkipReactiveWrapping() { if (this.render.__isReactiveWrapped) { return true; } const Cls = this.constructor; if (Cls.renderMode === "renderFunction" /* RenderFunction */) { return true; } return false; } /** * 设置 render 方法的响应式包装 * @private */ setupReactiveRender() { if (typeof this.render !== "function") { return; } try { const originalRender = this.render; this._originalRender = originalRender; if (typeof originalRender !== "function") { console.error(`FlowModel ${this.constructor.name}: original render method is not a function`, originalRender); return; } if (this.shouldSkipReactiveWrapping()) { const wrappedNonReactive = /* @__PURE__ */ __name(function() { var _a, _b, _c; const isConfigMode = !!((_b = (_a = this == null ? void 0 : this.flowEngine) == null ? void 0 : _a.flowSettings) == null ? void 0 : _b.enabled); if (this.hidden) { if (!isConfigMode) return null; const rendered = (_c = this.renderHiddenInConfig) == null ? void 0 : _c.call(this); const Cls = this.constructor; const returnsFunction = Cls.renderMode === "renderFunction" /* RenderFunction */; return returnsFunction ? typeof rendered === "function" ? rendered : () => rendered : rendered; } return originalRender.call(this); }, "wrappedNonReactive"); wrappedNonReactive.__originalRender = originalRender; this.render = wrappedNonReactive; return; } const createReactiveWrapper = /* @__PURE__ */ __name((modelInstance) => { const ReactiveWrapper = (0, import_reactive_react.observer)(() => { var _a, _b, _c; const renderTarget = modelInstance; if (renderTarget !== modelInstance && (renderTarget == null ? void 0 : renderTarget.localProps) !== void 0) { renderTarget.localProps; modelInstance.props; } else { modelInstance.props; } import_react.default.useEffect(() => { if (typeof renderTarget.onMount === "function") { renderTarget.onMount(); } return () => { if (typeof renderTarget.onUnmount === "function") { renderTarget.onUnmount(); } }; }, [renderTarget]); const isConfigMode = !!((_b = (_a = modelInstance == null ? void 0 : modelInstance.flowEngine) == null ? void 0 : _a.flowSettings) == null ? void 0 : _b.enabled); if (modelInstance.hidden) { if (!isConfigMode) { return null; } return (_c = modelInstance.renderHiddenInConfig) == null ? void 0 : _c.call(modelInstance); } return originalRender.call(renderTarget); }); ReactiveWrapper.displayName = `ReactiveWrapper(${modelInstance.constructor.name})`; return ReactiveWrapper; }, "createReactiveWrapper"); const wrappedRender = /* @__PURE__ */ __name(function() { if (!this._reactiveWrapperCache) { this._reactiveWrapperCache = createReactiveWrapper(this); } return import_react.default.createElement(this._reactiveWrapperCache); }, "wrappedRender"); wrappedRender.__isReactiveWrapped = true; wrappedRender.__originalRender = originalRender; this.render = wrappedRender; } catch (error) { console.error(`FlowModel ${this.constructor.name}: Error during render method wrapping:`, error); } } get cleanRun() { return true; } setCleanRun(value) { const prev = this._cleanRun; this._cleanRun = !!value; } /** * 组件挂载时的生命周期钩子 * 子类可以重写此方法来添加挂载时的逻辑 * @protected */ // eslint-disable-next-line no-empty onMount() { } /** * 组件卸载时的生命周期钩子 * 子类可以重写此方法来添加卸载时的逻辑 * @protected */ onUnmount() { } /** * 有权限时的渲染逻辑。 * 这是一个抽象方法,所有子类都必须实现,用于返回自己的正常 UI。 * * @returns {React.ReactNode} 有权限时的渲染结果 */ render() { return /* @__PURE__ */ import_react.default.createElement("div", { ...this.props }); } async rerender() { var _a; await this.applyAutoFlows((_a = this._lastAutoRunParams) == null ? void 0 : _a[0], false); } /** * 自动流程缓存的作用域标识;fork 实例可覆盖以区分缓存。 */ getAutoFlowCacheScope() { return "autoFlow"; } setParent(parent) { const isValidParent = parent && (parent.constructor === _FlowModel || (0, import_utils.isInheritedFrom)(parent.constructor, _FlowModel)); if (!isValidParent) { throw new Error("Parent must be an instance of FlowModel."); } this.parent = parent; this._options.parentId = parent.uid; if (this._options.delegateToParent !== false) { this.context.addDelegate(this.parent.context); } } removeParentDelegate() { if (!this.parent) { return; } this.context.removeDelegate(this.parent.context); } addSubModel(subKey, options) { var _a; const actualParent = this["master"] || this; let model; if (options instanceof _FlowModel) { const hasParent = !!options.parent; const parentUid = (_a = options.parent) == null ? void 0 : _a.uid; if (hasParent && parentUid && parentUid !== actualParent.uid) { throw new Error("Sub model already has a parent."); } model = options; } else { model = actualParent.flowEngine.createModel({ ...options, parentId: actualParent.uid, subKey, subType: "array" }); } model.setParent(actualParent); const subModels = actualParent.subModels; if (!Array.isArray(subModels[subKey])) { subModels[subKey] = import_reactive.observable.shallow([]); } const maxSortIndex = Math.max(...subModels[subKey].map((item) => item.sortIndex || 0), 0); model.sortIndex = maxSortIndex + 1; subModels[subKey].push(model); actualParent.emitter.emit("onSubModelAdded", model); return model; } setSubModel(subKey, options) { var _a; const actualParent = this["master"] || this; let model; if (options instanceof _FlowModel) { const hasParent = !!options.parent; const parentUid = (_a = options.parent) == null ? void 0 : _a.uid; if (hasParent && parentUid && parentUid !== actualParent.uid) { throw new Error("Sub model already has a parent."); } model = options; } else { model = actualParent.flowEngine.createModel({ ...options, parentId: actualParent.uid, subKey, subType: "object" }); } model.setParent(actualParent); actualParent.subModels[subKey] = model; actualParent.emitter.emit("onSubModelAdded", model); return model; } filterSubModels(subKey, callback) { const model = this.subModels[subKey]; if (!model) { return []; } const results = []; import_lodash.default.castArray(model).sort((a, b) => (a.sortIndex || 0) - (b.sortIndex || 0)).forEach((item, index) => { const result = callback(item, index); if (result) { results.push(item); } }); return results; } mapSubModels(subKey, callback) { const model = this.subModels[subKey]; if (!model) { return []; } const results = []; import_lodash.default.castArray(model).sort((a, b) => (a.sortIndex || 0) - (b.sortIndex || 0)).forEach((item, index) => { const result = callback(item, index); results.push(result); }); return results; } hasSubModel(subKey) { const subModel = this.subModels[subKey]; if (!subModel) { return false; } return import_lodash.default.castArray(subModel).length > 0; } findSubModel(subKey, callback) { const model = this.subModels[subKey]; if (!model) { return null; } return import_lodash.default.castArray(model).find((item) => { return callback(item); }) || null; } createRootModel(options) { return this.flowEngine.createModel(options); } async applySubModelsAutoFlows(subKey, inputArgs, shared) { await Promise.all( this.mapSubModels(subKey, async (sub) => { await sub.applyAutoFlows(inputArgs); }) ); } /** * 创建一个 fork 实例,实现"一份数据(master)多视图(fork)"的能力。 * @param {IModelComponentProps} [localProps={}] fork 专属的局部 props,优先级高于 master.props * @param {string} [key] 可选的 key,用于复用 fork 实例。如果提供了 key,会尝试复用已存在的 fork * @returns {ForkFlowModel<this>} 创建的 fork 实例 */ createFork(localProps, key, options) { if (key) { const cachedFork = this.forkCache.get(key); if (cachedFork && !cachedFork.disposed) { cachedFork.setProps(localProps || {}); return cachedFork; } } const forkId = this.forks.size; const fork = new import_forkFlowModel.ForkFlowModel(this, localProps, forkId); if ((options == null ? void 0 : options.register) !== false) { this.forks.add(fork); } if (key && (options == null ? void 0 : options.register) !== false) { this.forkCache.set(key, fork); } return fork; } clearForks() { var _a; console.log(`FlowModel ${this.uid} clearing all forks.`); if ((_a = this.forks) == null ? void 0 : _a.size) { this.forks.forEach((fork) => fork.dispose()); this.forks.clear(); } this.forkCache.clear(); } getFork(key) { return this.forkCache.get(key); } /** * 移动当前模型到目标模型的位置 * @param {FlowModel} targetModel 目标模型 * @param {PersistOptions} [options] 可选的持久化选项 * @returns {boolean} 是否成功移动 */ moveTo(targetModel, options) { if (!this.flowEngine) { throw new Error("FlowEngine is not set on this model. Please set flowEngine before saving."); } return this.flowEngine.moveModel(this.uid, targetModel.uid, options); } remove() { if (!this.flowEngine) { throw new Error("FlowEngine is not set on this model. Please set flowEngine before saving."); } this.observerDispose(); this.invalidateAutoFlowCache(true); return this.flowEngine.removeModel(this.uid); } async save() { if (!this.flowEngine) { throw new Error("FlowEngine is not set on this model. Please set flowEngine before saving."); } return this.flowEngine.saveModel(this); } async saveStepParams() { return this.flowEngine.saveModel(this, { onlyStepParams: true }); } async destroy() { if (!this.flowEngine) { throw new Error("FlowEngine is not set on this model. Please set flowEngine before deleting."); } this.observerDispose(); this.invalidateAutoFlowCache(true); return this.flowEngine.destroyModel(this.uid); } /** * @deprecated * 打开步骤设置对话框 * 用于配置流程中特定步骤的参数和设置 * @param {string} flowKey 流程的唯一标识符 * @param {string} stepKey 步骤的唯一标识符 * @returns {void} */ openStepSettingsDialog(flowKey, stepKey) { var _a; const flow = this.getFlow(flowKey); const step = (_a = flow == null ? void 0 : flow.steps) == null ? void 0 : _a[stepKey]; if (!flow || !step) { console.error(`Flow ${flowKey} or step ${stepKey} not found`); return; } const ctx = new import_flowContext.FlowRuntimeContext(this, flowKey, "settings"); (0, import_utils.setupRuntimeContextSteps)(ctx, flow.steps, this, flowKey); ctx.defineProperty("currentStep", { value: step }); return (0, import_StepSettingsDialog.openStepSettingsDialog)({ model: this, flowKey, stepKey, ctx }); } /** * 配置必填步骤参数 * 用于在一个分步表单中配置所有需要参数的步骤 * @param {number | string} [dialogWidth=800] 对话框宽度,默认为800 * @param {string} [dialogTitle='步骤参数配置'] 对话框标题,默认为'步骤参数配置' * @returns {Promise<any>} 返回表单提交的值 */ async configureRequiredSteps(dialogWidth, dialogTitle) { return (0, import_StepRequiredSettingsDialog.openRequiredParamsStepFormDialog)({ model: this, dialogWidth, dialogTitle }); } /** * @deprecated * @param dialogWidth * @param dialogTitle * @returns */ async openPresetStepSettingsDialog(dialogWidth, dialogTitle) { return this.configureRequiredSteps(dialogWidth, dialogTitle); } async openFlowStepSettingsDialog(options) { } get translate() { return this.flowEngine.translate.bind(this.flowEngine); } // TODO: 不完整,需要考虑 sub-model 的情况 serialize() { const data = { uid: this.uid, ...import_lodash.default.omit(this._options, ["flowEngine"]), stepParams: this.stepParams, sortIndex: this.sortIndex }; const subModels = this.subModels; for (const subModelKey in subModels) { data.subModels = data.subModels || {}; if (Array.isArray(subModels[subModelKey])) { data.subModels[subModelKey] = subModels[subModelKey].map((model, index) => ({ ...model.serialize(), sortIndex: index })); } else if (subModels[subModelKey] instanceof _FlowModel) { data.subModels[subModelKey] = subModels[subModelKey].serialize(); } } for (const [key, flow] of this.flowRegistry.getFlows()) { data["flowRegistry"] = data["flowRegistry"] || {}; data["flowRegistry"][key] = flow.toData(); } return data; } /** * Opens the flow settings dialog for this flow model. * @param options - Configuration options for opening flow settings, excluding the model property * @returns A promise that resolves when the flow settings dialog is opened */ async openFlowSettings(options) { return this.flowEngine.flowSettings.open({ model: this, ...options }); } // ============================= // Dynamic flows (disabled) // The following APIs are kept as comments to preserve context // ============================= /* async openDynamicFlowsEditor( options?: Omit<FlowSettingsOpenOptions, 'model' | 'flowKey' | 'flowKeys' | 'stepKey' | 'preset'>, ) { return this.flowEngine.flowSettings.openDynamicFlowsEditor({ model: this, ...options, }); } #dynamicFlows: FlowDefinition[] = []; async loadDynamicFlows(): Promise<FlowDefinition[]> { return JSON.parse(localStorage.getItem('DYNAMIC_FLOWS') || '[]'); } async saveDynamicFlows(): Promise<void> { localStorage.setItem('DYNAMIC_FLOWS', JSON.stringify(this.#dynamicFlows)); } setDynamicFlows(flows: FlowDefinition[]): void { this.#dynamicFlows = flows; flows.forEach((flow) => { // @ts-ignore this.constructor.registerFlow(flow); }); } getDynamicFlows(): FlowDefinitionOptions[] { return this.#dynamicFlows; } */ }; _flowContext = new WeakMap(); __name(_FlowModel, "FlowModel"); /** * 声明渲染模式: * - 'renderElement': render 返回 React 节点,框架会用 observer 包装以获得响应式; * - 'renderFunction': render 返回渲染函数(例如表格单元格渲染器),不做包装也不预调用; */ __publicField(_FlowModel, "renderMode", "reactElement" /* ReactElement */); let FlowModel = _FlowModel; const _ErrorFlowModel = class _ErrorFlowModel extends FlowModel { errorMessage; setErrorMessage(msg) { this.errorMessage = msg; } render() { return /* @__PURE__ */ import_react.default.createElement(import_lib.Typography.Text, { type: "danger" }, this.errorMessage); } }; __name(_ErrorFlowModel, "ErrorFlowModel"); let ErrorFlowModel = _ErrorFlowModel; function defineFlow(definition) { return definition; } __name(defineFlow, "defineFlow"); // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { ErrorFlowModel, FlowModel, ModelRenderMode, defineFlow });