@nocobase/flow-engine 2.1.0-beta.14 → 2.1.0-beta.16
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/lib/components/FlowModelRenderer.js +10 -6
- package/lib/components/MobilePopup.js +6 -5
- package/lib/components/settings/wrappers/contextual/FlowsFloatContextMenu.js +13 -5
- package/lib/components/subModel/AddSubModelButton.js +1 -1
- package/lib/components/subModel/utils.js +2 -2
- package/lib/flowEngine.d.ts +132 -1
- package/lib/flowEngine.js +360 -14
- package/lib/flowSettings.d.ts +14 -6
- package/lib/flowSettings.js +34 -6
- package/lib/lazy-helper.d.ts +14 -0
- package/lib/lazy-helper.js +71 -0
- package/lib/models/flowModel.d.ts +2 -1
- package/lib/models/flowModel.js +28 -9
- package/lib/types.d.ts +46 -0
- package/lib/utils/runjsTemplateCompat.js +1 -1
- package/package.json +4 -4
- package/src/__tests__/flow-engine.test.ts +166 -0
- package/src/__tests__/flowEngine.modelLoaders.test.ts +245 -0
- package/src/__tests__/flowSettings.test.ts +94 -15
- package/src/__tests__/renderHiddenInConfig.test.tsx +6 -6
- package/src/__tests__/viewScopedFlowEngine.test.ts +3 -3
- package/src/components/FlowModelRenderer.tsx +9 -5
- package/src/components/MobilePopup.tsx +4 -2
- package/src/components/__tests__/FlowModelRenderer.test.tsx +65 -2
- package/src/components/__tests__/flow-model-render-error-fallback.test.tsx +3 -3
- package/src/components/settings/wrappers/contextual/FlowsFloatContextMenu.tsx +15 -4
- package/src/components/settings/wrappers/contextual/__tests__/FlowsFloatContextMenu.test.tsx +67 -5
- package/src/components/subModel/AddSubModelButton.tsx +1 -1
- package/src/components/subModel/__tests__/AddSubModelButton.test.tsx +93 -33
- package/src/components/subModel/utils.ts +1 -1
- package/src/flowEngine.ts +412 -10
- package/src/flowSettings.ts +40 -6
- package/src/lazy-helper.tsx +57 -0
- package/src/models/flowModel.tsx +31 -10
- package/src/types.ts +59 -0
- package/src/utils/runjsTemplateCompat.ts +1 -1
package/src/models/flowModel.tsx
CHANGED
|
@@ -11,8 +11,6 @@ import { batch, define, observable, observe } from '@formily/reactive';
|
|
|
11
11
|
import _ from 'lodash';
|
|
12
12
|
import React from 'react';
|
|
13
13
|
import { uid } from 'uid/secure';
|
|
14
|
-
import { openRequiredParamsStepFormDialog as openRequiredParamsStepFormDialogFn } from '../components/settings/wrappers/contextual/StepRequiredSettingsDialog';
|
|
15
|
-
import { openStepSettingsDialog as openStepSettingsDialogFn } from '../components/settings/wrappers/contextual/StepSettingsDialog';
|
|
16
14
|
import { Emitter } from '../emitter';
|
|
17
15
|
import { InstanceFlowRegistry } from '../flow-registry/InstanceFlowRegistry';
|
|
18
16
|
import { FlowContext, FlowModelContext, FlowRuntimeContext } from '../flowContext';
|
|
@@ -36,7 +34,9 @@ import type {
|
|
|
36
34
|
import { IModelComponentProps, ReadonlyModelProps } from '../types';
|
|
37
35
|
import { isInheritedFrom, setupRuntimeContextSteps } from '../utils';
|
|
38
36
|
// import { FlowExitAllException } from '../utils/exceptions';
|
|
39
|
-
import { Typography } from 'antd
|
|
37
|
+
import { Typography } from 'antd';
|
|
38
|
+
import type { MenuProps } from 'antd';
|
|
39
|
+
import { observer } from '..';
|
|
40
40
|
import { ModelActionRegistry } from '../action-registry/ModelActionRegistry';
|
|
41
41
|
import { buildSubModelItem } from '../components/subModel/utils';
|
|
42
42
|
import { ModelEventRegistry } from '../event-registry/ModelEventRegistry';
|
|
@@ -46,8 +46,6 @@ import { FlowSettingsOpenOptions } from '../flowSettings';
|
|
|
46
46
|
import type { ScheduleOptions } from '../scheduler/ModelOperationScheduler';
|
|
47
47
|
import type { DispatchEventOptions, EventDefinition } from '../types';
|
|
48
48
|
import { ForkFlowModel } from './forkFlowModel';
|
|
49
|
-
import type { MenuProps } from 'antd';
|
|
50
|
-
import { observer } from '..';
|
|
51
49
|
|
|
52
50
|
// 使用 WeakMap 为每个类缓存一个 ModelActionRegistry 实例
|
|
53
51
|
const classActionRegistries = new WeakMap<typeof FlowModel, ModelActionRegistry>();
|
|
@@ -88,6 +86,16 @@ type ExtraMenuItemEntry = {
|
|
|
88
86
|
|
|
89
87
|
const classMenuExtensions = new WeakMap<typeof FlowModel, Set<ExtraMenuItemEntry>>();
|
|
90
88
|
|
|
89
|
+
async function loadOpenStepSettingsDialog() {
|
|
90
|
+
const mod = await import('../components/settings/wrappers/contextual/StepSettingsDialog');
|
|
91
|
+
return mod.openStepSettingsDialog;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
async function loadOpenRequiredParamsStepFormDialog() {
|
|
95
|
+
const mod = await import('../components/settings/wrappers/contextual/StepRequiredSettingsDialog');
|
|
96
|
+
return mod.openRequiredParamsStepFormDialog;
|
|
97
|
+
}
|
|
98
|
+
|
|
91
99
|
export enum ModelRenderMode {
|
|
92
100
|
ReactElement = 'reactElement',
|
|
93
101
|
RenderFunction = 'renderFunction',
|
|
@@ -208,11 +216,14 @@ export class FlowModel<Structure extends DefaultStructure = DefaultStructure> {
|
|
|
208
216
|
if (changed.type === 'set' && _.isEqual(changed.value, changed.oldValue)) {
|
|
209
217
|
return;
|
|
210
218
|
}
|
|
219
|
+
const hasLastAutoRun = !!this._lastAutoRunParams;
|
|
211
220
|
|
|
212
221
|
if (this.flowEngine) {
|
|
213
222
|
this.invalidateFlowCache('beforeRender');
|
|
214
223
|
}
|
|
215
|
-
|
|
224
|
+
if (hasLastAutoRun) {
|
|
225
|
+
this._rerunLastAutoRun();
|
|
226
|
+
}
|
|
216
227
|
this.forks.forEach((fork) => {
|
|
217
228
|
fork.rerender();
|
|
218
229
|
});
|
|
@@ -858,6 +869,11 @@ export class FlowModel<Structure extends DefaultStructure = DefaultStructure> {
|
|
|
858
869
|
}
|
|
859
870
|
}, 100);
|
|
860
871
|
|
|
872
|
+
private resetAutoRunState(): void {
|
|
873
|
+
this._rerunLastAutoRun?.cancel?.();
|
|
874
|
+
this._lastAutoRunParams = null;
|
|
875
|
+
}
|
|
876
|
+
|
|
861
877
|
/**
|
|
862
878
|
* 通用事件分发钩子:开始
|
|
863
879
|
* 子类可覆盖;beforeRender 事件可通过抛出 FlowExitException 提前终止。
|
|
@@ -951,7 +967,7 @@ export class FlowModel<Structure extends DefaultStructure = DefaultStructure> {
|
|
|
951
967
|
}
|
|
952
968
|
|
|
953
969
|
// 创建缓存的响应式包装器组件工厂(只创建一次)
|
|
954
|
-
const createReactiveWrapper = (modelInstance:
|
|
970
|
+
const createReactiveWrapper = (modelInstance: FlowModel) => {
|
|
955
971
|
const ReactiveWrapper = observer(() => {
|
|
956
972
|
// 触发响应式更新的关键属性访问(读取 run/渲染目标的 props)
|
|
957
973
|
const renderTarget = modelInstance;
|
|
@@ -977,6 +993,7 @@ export class FlowModel<Structure extends DefaultStructure = DefaultStructure> {
|
|
|
977
993
|
model: renderTarget,
|
|
978
994
|
});
|
|
979
995
|
return () => {
|
|
996
|
+
renderTarget.resetAutoRunState();
|
|
980
997
|
if (typeof renderTarget.onUnmount === 'function') {
|
|
981
998
|
renderTarget.onUnmount();
|
|
982
999
|
}
|
|
@@ -1369,7 +1386,7 @@ export class FlowModel<Structure extends DefaultStructure = DefaultStructure> {
|
|
|
1369
1386
|
* @param {string} stepKey 步骤的唯一标识符
|
|
1370
1387
|
* @returns {void}
|
|
1371
1388
|
*/
|
|
1372
|
-
openStepSettingsDialog(flowKey: string, stepKey: string) {
|
|
1389
|
+
async openStepSettingsDialog(flowKey: string, stepKey: string) {
|
|
1373
1390
|
// 创建流程运行时上下文
|
|
1374
1391
|
const flow = this.getFlow(flowKey);
|
|
1375
1392
|
const step = flow?.steps?.[stepKey];
|
|
@@ -1383,7 +1400,9 @@ export class FlowModel<Structure extends DefaultStructure = DefaultStructure> {
|
|
|
1383
1400
|
setupRuntimeContextSteps(ctx, flow.steps, this, flowKey);
|
|
1384
1401
|
ctx.defineProperty('currentStep', { value: step });
|
|
1385
1402
|
|
|
1386
|
-
|
|
1403
|
+
const openStepSettingsDialog = await loadOpenStepSettingsDialog();
|
|
1404
|
+
|
|
1405
|
+
return openStepSettingsDialog({
|
|
1387
1406
|
model: this,
|
|
1388
1407
|
flowKey,
|
|
1389
1408
|
stepKey,
|
|
@@ -1399,7 +1418,9 @@ export class FlowModel<Structure extends DefaultStructure = DefaultStructure> {
|
|
|
1399
1418
|
* @returns {Promise<any>} 返回表单提交的值
|
|
1400
1419
|
*/
|
|
1401
1420
|
async configureRequiredSteps(dialogWidth?: number | string, dialogTitle?: string) {
|
|
1402
|
-
|
|
1421
|
+
const openRequiredParamsStepFormDialog = await loadOpenRequiredParamsStepFormDialog();
|
|
1422
|
+
|
|
1423
|
+
return openRequiredParamsStepFormDialog({
|
|
1403
1424
|
model: this,
|
|
1404
1425
|
dialogWidth,
|
|
1405
1426
|
dialogTitle,
|
package/src/types.ts
CHANGED
|
@@ -388,6 +388,65 @@ export interface CreateModelOptions {
|
|
|
388
388
|
delegateToParent?: boolean;
|
|
389
389
|
[key: string]: any; // 允许额外的自定义选项
|
|
390
390
|
}
|
|
391
|
+
|
|
392
|
+
/**
|
|
393
|
+
* FlowModel loader result.
|
|
394
|
+
* Supports returning the model constructor directly, a default export, or a module object containing the named export.
|
|
395
|
+
*/
|
|
396
|
+
export type FlowModelLoaderResult =
|
|
397
|
+
| ModelConstructor
|
|
398
|
+
| {
|
|
399
|
+
default?: ModelConstructor;
|
|
400
|
+
[key: string]: unknown;
|
|
401
|
+
}
|
|
402
|
+
| Record<string, unknown>;
|
|
403
|
+
|
|
404
|
+
/**
|
|
405
|
+
* FlowModel loader function.
|
|
406
|
+
*/
|
|
407
|
+
export type FlowModelLoader = () => Promise<FlowModelLoaderResult>;
|
|
408
|
+
|
|
409
|
+
/**
|
|
410
|
+
* FlowModel loader entry (normalized internal form).
|
|
411
|
+
*/
|
|
412
|
+
export interface FlowModelLoaderEntry {
|
|
413
|
+
loader: FlowModelLoader;
|
|
414
|
+
extends?: string[];
|
|
415
|
+
// meta?: Partial<FlowModelMeta>;
|
|
416
|
+
// scenes?: string[];
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
/**
|
|
420
|
+
* FlowModel loader input (user-facing form for registerModelLoaders).
|
|
421
|
+
* The `extends` field accepts flexible formats that will be normalized to `string[]` at registration time.
|
|
422
|
+
*/
|
|
423
|
+
export interface FlowModelLoaderInput {
|
|
424
|
+
loader: FlowModelLoader;
|
|
425
|
+
extends?: string | ModelConstructor | (string | ModelConstructor)[];
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
/**
|
|
429
|
+
* FlowModel loader entry map (normalized internal form).
|
|
430
|
+
*/
|
|
431
|
+
export type FlowModelLoaderMap = Record<string, FlowModelLoaderEntry>;
|
|
432
|
+
|
|
433
|
+
/**
|
|
434
|
+
* FlowModel loader input map (user-facing form for registerModelLoaders).
|
|
435
|
+
*/
|
|
436
|
+
export type FlowModelLoaderInputMap = Record<string, FlowModelLoaderInput>;
|
|
437
|
+
|
|
438
|
+
/**
|
|
439
|
+
* Batch ensure result.
|
|
440
|
+
*/
|
|
441
|
+
export interface EnsureBatchResult {
|
|
442
|
+
requested: string[];
|
|
443
|
+
loaded: string[];
|
|
444
|
+
failed: Array<{
|
|
445
|
+
name: string;
|
|
446
|
+
error?: unknown;
|
|
447
|
+
}>;
|
|
448
|
+
}
|
|
449
|
+
|
|
391
450
|
export interface IFlowModelRepository<T extends FlowModel = FlowModel> {
|
|
392
451
|
findOne(query: Record<string, any>): Promise<Record<string, any> | null>;
|
|
393
452
|
save(model: T, options?: { onlyStepParams?: boolean }): Promise<Record<string, any>>;
|
|
@@ -553,8 +553,8 @@ function extractUsedCtxLibKeys(code: string): string[] {
|
|
|
553
553
|
}
|
|
554
554
|
|
|
555
555
|
function injectEnsureLibsPreamble(code: string): string {
|
|
556
|
-
if (!CTX_LIBS_MARKER_RE.test(code)) return code;
|
|
557
556
|
if (ENSURE_LIBS_MARKER_RE.test(code)) return code;
|
|
557
|
+
if (!CTX_LIBS_MARKER_RE.test(code)) return code;
|
|
558
558
|
const keys = extractUsedCtxLibKeys(code);
|
|
559
559
|
if (!keys.length) return code;
|
|
560
560
|
return `/* __runjs_ensure_libs */\nawait ctx.__ensureLibs(${JSON.stringify(keys)});\n${code}`;
|