@nocobase/flow-engine 2.0.60 → 2.0.62
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/settings/wrappers/contextual/DefaultSettingsIcon.js +76 -31
- package/lib/flowContext.d.ts +6 -1
- package/lib/flowContext.js +35 -6
- package/lib/flowEngine.d.ts +4 -3
- package/lib/flowEngine.js +67 -36
- package/lib/models/flowModel.js +45 -13
- package/lib/runjs-context/contexts/FormJSFieldItemRunJSContext.js +4 -3
- package/lib/runjs-context/contexts/JSBlockRunJSContext.js +4 -15
- package/lib/runjs-context/contexts/JSColumnRunJSContext.js +5 -2
- package/lib/runjs-context/contexts/JSEditableFieldRunJSContext.js +5 -8
- package/lib/runjs-context/contexts/JSFieldRunJSContext.js +4 -3
- package/lib/runjs-context/contexts/JSItemRunJSContext.js +4 -3
- package/lib/runjs-context/contexts/base.js +464 -29
- package/lib/runjs-context/contexts/elementDoc.d.ts +11 -0
- package/lib/runjs-context/contexts/elementDoc.js +152 -0
- package/lib/utils/loadedPageCache.d.ts +21 -0
- package/lib/utils/loadedPageCache.js +125 -0
- package/package.json +4 -4
- package/src/__tests__/flowContext.test.ts +23 -0
- package/src/__tests__/flowEngine.moveModel.test.ts +81 -1
- package/src/__tests__/runjsContext.test.ts +18 -0
- package/src/__tests__/runjsContextImplementations.test.ts +9 -2
- package/src/__tests__/runjsLocales.test.ts +6 -5
- package/src/__tests__/viewScopedFlowEngine.test.ts +133 -0
- package/src/components/settings/wrappers/contextual/DefaultSettingsIcon.tsx +79 -37
- package/src/components/settings/wrappers/contextual/__tests__/DefaultSettingsIcon.test.tsx +148 -1
- package/src/flowContext.ts +40 -6
- package/src/flowEngine.ts +69 -34
- package/src/models/__tests__/flowModel.test.ts +13 -0
- package/src/models/flowModel.tsx +62 -29
- package/src/runjs-context/contexts/FormJSFieldItemRunJSContext.ts +4 -3
- package/src/runjs-context/contexts/JSBlockRunJSContext.ts +4 -15
- package/src/runjs-context/contexts/JSColumnRunJSContext.ts +4 -2
- package/src/runjs-context/contexts/JSEditableFieldRunJSContext.ts +5 -9
- package/src/runjs-context/contexts/JSFieldRunJSContext.ts +4 -3
- package/src/runjs-context/contexts/JSItemRunJSContext.ts +4 -3
- package/src/runjs-context/contexts/base.ts +467 -31
- package/src/runjs-context/contexts/elementDoc.ts +130 -0
- package/src/utils/loadedPageCache.ts +117 -0
package/src/flowEngine.ts
CHANGED
|
@@ -20,6 +20,7 @@ import { APIResource, FlowResource, MultiRecordResource, SingleRecordResource, S
|
|
|
20
20
|
import { Emitter } from './emitter';
|
|
21
21
|
import ModelOperationScheduler from './scheduler/ModelOperationScheduler';
|
|
22
22
|
import type { ScheduleOptions, ScheduledCancel } from './scheduler/ModelOperationScheduler';
|
|
23
|
+
import { createLoadedPageCache } from './utils/loadedPageCache';
|
|
23
24
|
import type {
|
|
24
25
|
ActionDefinition,
|
|
25
26
|
ApplyFlowCacheEntry,
|
|
@@ -105,6 +106,8 @@ export class FlowEngine {
|
|
|
105
106
|
*/
|
|
106
107
|
private _savingModels = new Map<string, Promise<any>>();
|
|
107
108
|
|
|
109
|
+
private _loadedPageCache = createLoadedPageCache();
|
|
110
|
+
|
|
108
111
|
/**
|
|
109
112
|
* Flow engine context object.
|
|
110
113
|
* @private
|
|
@@ -938,7 +941,8 @@ export class FlowEngine {
|
|
|
938
941
|
async loadModel<T extends FlowModel = FlowModel>(options): Promise<T | null> {
|
|
939
942
|
if (!this.ensureModelRepository()) return;
|
|
940
943
|
const refresh = !!options?.refresh;
|
|
941
|
-
|
|
944
|
+
const bypassLoadedPageCache = this._loadedPageCache.shouldBypass(options, () => this.context.flowSettingsEnabled);
|
|
945
|
+
if (!refresh && !bypassLoadedPageCache) {
|
|
942
946
|
const model = this.findModelByParentId(options.parentId, options.subKey);
|
|
943
947
|
if (model) {
|
|
944
948
|
return model as T;
|
|
@@ -949,14 +953,24 @@ export class FlowEngine {
|
|
|
949
953
|
}
|
|
950
954
|
}
|
|
951
955
|
const data = await this._modelRepository.findOne(options);
|
|
952
|
-
if (!data?.uid)
|
|
953
|
-
|
|
956
|
+
if (!data?.uid) {
|
|
957
|
+
if (bypassLoadedPageCache) {
|
|
958
|
+
this._loadedPageCache.clear(options);
|
|
959
|
+
}
|
|
960
|
+
return null;
|
|
961
|
+
}
|
|
962
|
+
if (refresh || bypassLoadedPageCache) {
|
|
954
963
|
const existing = this.getModel(data.uid);
|
|
955
964
|
if (existing) {
|
|
956
965
|
this.removeModelWithSubModels(existing.uid);
|
|
957
966
|
}
|
|
958
967
|
}
|
|
959
|
-
|
|
968
|
+
const model = this.createModel<T>(data as any);
|
|
969
|
+
if (bypassLoadedPageCache) {
|
|
970
|
+
this._loadedPageCache.mountModelToParent(model, true);
|
|
971
|
+
this._loadedPageCache.clear(options);
|
|
972
|
+
}
|
|
973
|
+
return model;
|
|
960
974
|
}
|
|
961
975
|
|
|
962
976
|
/**
|
|
@@ -996,22 +1010,31 @@ export class FlowEngine {
|
|
|
996
1010
|
): Promise<T | null> {
|
|
997
1011
|
if (!this.ensureModelRepository()) return;
|
|
998
1012
|
const { uid, parentId, subKey } = options;
|
|
999
|
-
|
|
1013
|
+
const bypassLoadedPageCache = this._loadedPageCache.shouldBypass(options, () => this.context.flowSettingsEnabled);
|
|
1014
|
+
if (uid && !bypassLoadedPageCache && this._modelInstances.has(uid)) {
|
|
1000
1015
|
return this._modelInstances.get(uid) as T;
|
|
1001
1016
|
}
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1017
|
+
if (!bypassLoadedPageCache) {
|
|
1018
|
+
const m = this.findModelByParentId<T>(parentId, subKey);
|
|
1019
|
+
if (m) {
|
|
1020
|
+
return m;
|
|
1021
|
+
}
|
|
1006
1022
|
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1023
|
+
const hydrated = this.hydrateModelFromPreviousEngines<T>(options, extra);
|
|
1024
|
+
if (hydrated) {
|
|
1025
|
+
return hydrated;
|
|
1026
|
+
}
|
|
1010
1027
|
}
|
|
1011
1028
|
|
|
1012
1029
|
const data = await this._modelRepository.findOne(options);
|
|
1013
1030
|
let model: T | null = null;
|
|
1014
1031
|
if (data?.uid) {
|
|
1032
|
+
if (bypassLoadedPageCache) {
|
|
1033
|
+
const existing = this.getModel(data.uid);
|
|
1034
|
+
if (existing) {
|
|
1035
|
+
this.removeModelWithSubModels(existing.uid);
|
|
1036
|
+
}
|
|
1037
|
+
}
|
|
1015
1038
|
model = this.createModel<T>(data as any, extra);
|
|
1016
1039
|
} else {
|
|
1017
1040
|
model = this.createModel<T>(options, extra);
|
|
@@ -1019,18 +1042,9 @@ export class FlowEngine {
|
|
|
1019
1042
|
await model.save();
|
|
1020
1043
|
}
|
|
1021
1044
|
}
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
});
|
|
1026
|
-
if (subModel) {
|
|
1027
|
-
return model;
|
|
1028
|
-
}
|
|
1029
|
-
if (model.subType === 'array') {
|
|
1030
|
-
model.parent.addSubModel(model.subKey, model);
|
|
1031
|
-
} else {
|
|
1032
|
-
model.parent.setSubModel(model.subKey, model);
|
|
1033
|
-
}
|
|
1045
|
+
this._loadedPageCache.mountModelToParent(model, bypassLoadedPageCache);
|
|
1046
|
+
if (bypassLoadedPageCache) {
|
|
1047
|
+
this._loadedPageCache.clear(options);
|
|
1034
1048
|
}
|
|
1035
1049
|
return model;
|
|
1036
1050
|
}
|
|
@@ -1050,6 +1064,7 @@ export class FlowEngine {
|
|
|
1050
1064
|
if (!this.ensureModelRepository()) return;
|
|
1051
1065
|
|
|
1052
1066
|
const modelUid = model.uid;
|
|
1067
|
+
const dirtyLoadedPageKey = this._loadedPageCache.getDirtyKeyForModel(model);
|
|
1053
1068
|
|
|
1054
1069
|
// 如果这个 model 正在保存中,返回现有的保存 Promise
|
|
1055
1070
|
if (this._savingModels.has(modelUid)) {
|
|
@@ -1063,6 +1078,7 @@ export class FlowEngine {
|
|
|
1063
1078
|
|
|
1064
1079
|
try {
|
|
1065
1080
|
const result = await savePromise;
|
|
1081
|
+
this._loadedPageCache.markDirty(dirtyLoadedPageKey);
|
|
1066
1082
|
return result;
|
|
1067
1083
|
} finally {
|
|
1068
1084
|
// 无论成功还是失败,都要清除保存状态
|
|
@@ -1099,11 +1115,16 @@ export class FlowEngine {
|
|
|
1099
1115
|
* @returns {Promise<boolean>} Whether destroyed successfully
|
|
1100
1116
|
*/
|
|
1101
1117
|
async destroyModel(uid: string) {
|
|
1102
|
-
|
|
1118
|
+
const modelInstance = this._modelInstances.get(uid) as FlowModel;
|
|
1119
|
+
const dirtyLoadedPageKey = this._loadedPageCache.getDirtyKeyForModel(modelInstance);
|
|
1120
|
+
const hasModelRepository = this.ensureModelRepository();
|
|
1121
|
+
if (hasModelRepository) {
|
|
1103
1122
|
await this._modelRepository.destroy(uid);
|
|
1104
1123
|
}
|
|
1105
1124
|
|
|
1106
|
-
|
|
1125
|
+
if (hasModelRepository) {
|
|
1126
|
+
this._loadedPageCache.markDirty(dirtyLoadedPageKey);
|
|
1127
|
+
}
|
|
1107
1128
|
const parent = modelInstance?.parent;
|
|
1108
1129
|
const result = this.removeModel(uid);
|
|
1109
1130
|
parent && parent.emitter.emit('onSubModelDestroyed', modelInstance);
|
|
@@ -1207,17 +1228,25 @@ export class FlowEngine {
|
|
|
1207
1228
|
|
|
1208
1229
|
/**
|
|
1209
1230
|
* Move a model instance within its parent model.
|
|
1210
|
-
* @param {
|
|
1211
|
-
* @param {
|
|
1231
|
+
* @param {string | number} sourceId Source model UID
|
|
1232
|
+
* @param {string | number} targetId Target model UID
|
|
1212
1233
|
* @returns {Promise<void>} No return value
|
|
1213
1234
|
*/
|
|
1214
|
-
async moveModel(sourceId:
|
|
1215
|
-
const
|
|
1216
|
-
const
|
|
1235
|
+
async moveModel(sourceId: string | number, targetId: string | number, options?: PersistOptions): Promise<void> {
|
|
1236
|
+
const sourceUid = String(sourceId);
|
|
1237
|
+
const targetUid = String(targetId);
|
|
1238
|
+
if (!sourceUid || !targetUid || sourceUid === targetUid) {
|
|
1239
|
+
return;
|
|
1240
|
+
}
|
|
1241
|
+
|
|
1242
|
+
const sourceModel = this.getModel(sourceUid);
|
|
1243
|
+
const targetModel = this.getModel(targetUid);
|
|
1217
1244
|
if (!sourceModel || !targetModel) {
|
|
1218
1245
|
console.warn(`FlowEngine: Cannot move model. Source or target model not found.`);
|
|
1219
1246
|
return;
|
|
1220
1247
|
}
|
|
1248
|
+
let position: 'before' | 'after' = 'after';
|
|
1249
|
+
const dirtyLoadedPageKey = this._loadedPageCache.getDirtyKeyForModel(sourceModel);
|
|
1221
1250
|
const move = (sourceModel: FlowModel, targetModel: FlowModel) => {
|
|
1222
1251
|
if (!sourceModel.parent || !targetModel.parent || sourceModel.parent !== targetModel.parent) {
|
|
1223
1252
|
console.error('FlowModel.moveTo: Both models must have the same parent to perform move operation.');
|
|
@@ -1247,6 +1276,8 @@ export class FlowEngine {
|
|
|
1247
1276
|
return false;
|
|
1248
1277
|
}
|
|
1249
1278
|
|
|
1279
|
+
position = currentIndex < targetIndex ? 'after' : 'before';
|
|
1280
|
+
|
|
1250
1281
|
// 使用splice直接移动数组元素(O(n)比排序O(n log n)更快)
|
|
1251
1282
|
const [movedModel] = subModelsCopy.splice(currentIndex, 1);
|
|
1252
1283
|
subModelsCopy.splice(targetIndex, 0, movedModel);
|
|
@@ -1261,10 +1292,14 @@ export class FlowEngine {
|
|
|
1261
1292
|
|
|
1262
1293
|
return true;
|
|
1263
1294
|
};
|
|
1264
|
-
move(sourceModel, targetModel);
|
|
1295
|
+
const moved = move(sourceModel, targetModel);
|
|
1296
|
+
if (!moved) {
|
|
1297
|
+
return;
|
|
1298
|
+
}
|
|
1299
|
+
|
|
1265
1300
|
if (options?.persist !== false && this.ensureModelRepository()) {
|
|
1266
|
-
|
|
1267
|
-
|
|
1301
|
+
await this._modelRepository.move(sourceUid, targetUid, position);
|
|
1302
|
+
this._loadedPageCache.markDirty(dirtyLoadedPageKey);
|
|
1268
1303
|
}
|
|
1269
1304
|
// 触发事件以通知其他部分模型已移动
|
|
1270
1305
|
sourceModel.parent.emitter.emit('onSubModelMoved', { source: sourceModel, target: targetModel });
|
|
@@ -313,6 +313,19 @@ describe('FlowModel', () => {
|
|
|
313
313
|
|
|
314
314
|
model.emitter.off('onStepParamsChanged', listener);
|
|
315
315
|
});
|
|
316
|
+
|
|
317
|
+
test('should not emit onStepParamsChanged when params are unchanged', () => {
|
|
318
|
+
const listener = vi.fn();
|
|
319
|
+
model.emitter.on('onStepParamsChanged', listener);
|
|
320
|
+
|
|
321
|
+
model.setStepParams('testFlow', 'step1', { param1: 'value1' });
|
|
322
|
+
model.setStepParams('testFlow', { step1: { param1: 'value1' } });
|
|
323
|
+
model.setStepParams({ testFlow: { step1: { param1: 'value1' } } });
|
|
324
|
+
|
|
325
|
+
expect(listener).not.toHaveBeenCalled();
|
|
326
|
+
|
|
327
|
+
model.emitter.off('onStepParamsChanged', listener);
|
|
328
|
+
});
|
|
316
329
|
});
|
|
317
330
|
});
|
|
318
331
|
|
package/src/models/flowModel.tsx
CHANGED
|
@@ -58,6 +58,25 @@ const classEventRegistries = new WeakMap<typeof FlowModel, ModelEventRegistry>()
|
|
|
58
58
|
// 使用WeakMap存储每个类的meta
|
|
59
59
|
const modelMetas = new WeakMap<typeof FlowModel, FlowModelMeta>();
|
|
60
60
|
|
|
61
|
+
type SortableModelLike = {
|
|
62
|
+
sortIndex?: number | null;
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
function getStableSortIndex(item: SortableModelLike, fallbackIndex: number) {
|
|
66
|
+
return typeof item?.sortIndex === 'number' && Number.isFinite(item.sortIndex) ? item.sortIndex : fallbackIndex + 1;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function sortByStableSortIndex<T extends SortableModelLike>(items: T[]) {
|
|
70
|
+
return items
|
|
71
|
+
.map((item, index) => ({
|
|
72
|
+
item,
|
|
73
|
+
index,
|
|
74
|
+
sortIndex: getStableSortIndex(item, index),
|
|
75
|
+
}))
|
|
76
|
+
.sort((a, b) => a.sortIndex - b.sortIndex || a.index - b.index)
|
|
77
|
+
.map(({ item }) => item);
|
|
78
|
+
}
|
|
79
|
+
|
|
61
80
|
// 使用WeakMap存储每个类的 GlobalFlowRegistry
|
|
62
81
|
const modelGlobalRegistries = new WeakMap<typeof FlowModel, GlobalFlowRegistry>();
|
|
63
82
|
|
|
@@ -178,7 +197,7 @@ export class FlowModel<Structure extends DefaultStructure = DefaultStructure> {
|
|
|
178
197
|
};
|
|
179
198
|
this.stepParams = options.stepParams || {};
|
|
180
199
|
this.subModels = {};
|
|
181
|
-
this.sortIndex = options.sortIndex
|
|
200
|
+
this.sortIndex = getStableSortIndex({ sortIndex: options.sortIndex }, -1);
|
|
182
201
|
this._options = options;
|
|
183
202
|
this._title = '';
|
|
184
203
|
this._extraTitle = '';
|
|
@@ -447,11 +466,9 @@ export class FlowModel<Structure extends DefaultStructure = DefaultStructure> {
|
|
|
447
466
|
|
|
448
467
|
Object.entries(mergedSubModels || {}).forEach(([key, value]) => {
|
|
449
468
|
if (Array.isArray(value)) {
|
|
450
|
-
value
|
|
451
|
-
.
|
|
452
|
-
|
|
453
|
-
this.addSubModel(key, item);
|
|
454
|
-
});
|
|
469
|
+
sortByStableSortIndex(value).forEach((item) => {
|
|
470
|
+
this.addSubModel(key, item);
|
|
471
|
+
});
|
|
455
472
|
} else {
|
|
456
473
|
this.setSubModel(key, value);
|
|
457
474
|
}
|
|
@@ -712,26 +729,43 @@ export class FlowModel<Structure extends DefaultStructure = DefaultStructure> {
|
|
|
712
729
|
stepKeyOrStepsParams?: string | Record<string, ParamObject>,
|
|
713
730
|
params?: ParamObject,
|
|
714
731
|
): void {
|
|
732
|
+
let hasChanged = false;
|
|
733
|
+
|
|
715
734
|
if (typeof flowKeyOrAllParams === 'string') {
|
|
716
735
|
const flowKey = flowKeyOrAllParams;
|
|
717
736
|
if (typeof stepKeyOrStepsParams === 'string' && params !== undefined) {
|
|
718
|
-
|
|
719
|
-
|
|
737
|
+
const currentStepParams = this.stepParams[flowKey]?.[stepKeyOrStepsParams] || {};
|
|
738
|
+
const nextStepParams = { ...currentStepParams, ...params };
|
|
739
|
+
if (!_.isEqual(currentStepParams, nextStepParams)) {
|
|
740
|
+
if (!this.stepParams[flowKey]) {
|
|
741
|
+
this.stepParams[flowKey] = {};
|
|
742
|
+
}
|
|
743
|
+
this.stepParams[flowKey][stepKeyOrStepsParams] = nextStepParams;
|
|
744
|
+
hasChanged = true;
|
|
720
745
|
}
|
|
721
|
-
this.stepParams[flowKey][stepKeyOrStepsParams] = {
|
|
722
|
-
...this.stepParams[flowKey][stepKeyOrStepsParams],
|
|
723
|
-
...params,
|
|
724
|
-
};
|
|
725
746
|
} else if (typeof stepKeyOrStepsParams === 'object' && stepKeyOrStepsParams !== null) {
|
|
726
|
-
|
|
747
|
+
const currentFlowParams = this.stepParams[flowKey] || {};
|
|
748
|
+
const nextFlowParams = { ...currentFlowParams, ...stepKeyOrStepsParams };
|
|
749
|
+
if (!_.isEqual(currentFlowParams, nextFlowParams)) {
|
|
750
|
+
this.stepParams[flowKey] = nextFlowParams;
|
|
751
|
+
hasChanged = true;
|
|
752
|
+
}
|
|
727
753
|
}
|
|
728
754
|
} else if (typeof flowKeyOrAllParams === 'object' && flowKeyOrAllParams !== null) {
|
|
729
755
|
for (const fk in flowKeyOrAllParams) {
|
|
730
756
|
if (Object.prototype.hasOwnProperty.call(flowKeyOrAllParams, fk)) {
|
|
731
|
-
|
|
757
|
+
const currentFlowParams = this.stepParams[fk] || {};
|
|
758
|
+
const nextFlowParams = { ...currentFlowParams, ...flowKeyOrAllParams[fk] };
|
|
759
|
+
if (!_.isEqual(currentFlowParams, nextFlowParams)) {
|
|
760
|
+
this.stepParams[fk] = nextFlowParams;
|
|
761
|
+
hasChanged = true;
|
|
762
|
+
}
|
|
732
763
|
}
|
|
733
764
|
}
|
|
734
765
|
}
|
|
766
|
+
if (!hasChanged) {
|
|
767
|
+
return;
|
|
768
|
+
}
|
|
735
769
|
// 发起配置修改事件
|
|
736
770
|
this.emitter.emit('onStepParamsChanged');
|
|
737
771
|
}
|
|
@@ -1140,7 +1174,10 @@ export class FlowModel<Structure extends DefaultStructure = DefaultStructure> {
|
|
|
1140
1174
|
if (!Array.isArray(subModels[subKey])) {
|
|
1141
1175
|
subModels[subKey] = observable.shallow([]);
|
|
1142
1176
|
}
|
|
1143
|
-
const maxSortIndex = Math.max(
|
|
1177
|
+
const maxSortIndex = Math.max(
|
|
1178
|
+
...(subModels[subKey] as FlowModel[]).map((item, index) => getStableSortIndex(item, index)),
|
|
1179
|
+
0,
|
|
1180
|
+
);
|
|
1144
1181
|
model.sortIndex = maxSortIndex + 1;
|
|
1145
1182
|
subModels[subKey].push(model);
|
|
1146
1183
|
actualParent.emitter.emit('onSubModelAdded', model);
|
|
@@ -1198,14 +1235,12 @@ export class FlowModel<Structure extends DefaultStructure = DefaultStructure> {
|
|
|
1198
1235
|
|
|
1199
1236
|
const results: ArrayElementType<Structure['subModels'][K]>[] = [];
|
|
1200
1237
|
|
|
1201
|
-
_.castArray(model)
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
}
|
|
1208
|
-
});
|
|
1238
|
+
sortByStableSortIndex(_.castArray(model)).forEach((item, index) => {
|
|
1239
|
+
const result = (callback as (model: any, index: number) => boolean)(item, index);
|
|
1240
|
+
if (result) {
|
|
1241
|
+
results.push(item);
|
|
1242
|
+
}
|
|
1243
|
+
});
|
|
1209
1244
|
|
|
1210
1245
|
return results;
|
|
1211
1246
|
}
|
|
@@ -1222,12 +1257,10 @@ export class FlowModel<Structure extends DefaultStructure = DefaultStructure> {
|
|
|
1222
1257
|
|
|
1223
1258
|
const results: R[] = [];
|
|
1224
1259
|
|
|
1225
|
-
_.castArray(model)
|
|
1226
|
-
|
|
1227
|
-
.
|
|
1228
|
-
|
|
1229
|
-
results.push(result);
|
|
1230
|
-
});
|
|
1260
|
+
sortByStableSortIndex(_.castArray(model)).forEach((item, index) => {
|
|
1261
|
+
const result = (callback as (model: any, index: number) => R)(item, index);
|
|
1262
|
+
results.push(result);
|
|
1263
|
+
});
|
|
1231
1264
|
|
|
1232
1265
|
return results;
|
|
1233
1266
|
}
|
|
@@ -8,14 +8,15 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import { FlowRunJSContext } from '../../flowContext';
|
|
11
|
+
import { createElementPropertyDoc, createZhCNElementPropertyDoc } from './elementDoc';
|
|
11
12
|
|
|
12
13
|
export class FormJSFieldItemRunJSContext extends FlowRunJSContext {}
|
|
13
14
|
|
|
14
15
|
FormJSFieldItemRunJSContext.define({
|
|
15
16
|
label: 'FormJSFieldItem RunJS context',
|
|
16
17
|
properties: {
|
|
17
|
-
element: `ElementProxy instance providing a safe DOM container for form field rendering.
|
|
18
|
-
Supports innerHTML, append, and other DOM manipulation methods
|
|
18
|
+
element: createElementPropertyDoc(`ElementProxy instance providing a safe DOM container for form field rendering.
|
|
19
|
+
Supports innerHTML, append, and other DOM manipulation methods.`),
|
|
19
20
|
value: `Current field value (read-only in display mode; in controlled scenarios, use setProps to modify).`,
|
|
20
21
|
record: `Current record data object (read-only).
|
|
21
22
|
Contains all field values of the parent record.`,
|
|
@@ -38,7 +39,7 @@ FormJSFieldItemRunJSContext.define(
|
|
|
38
39
|
{
|
|
39
40
|
label: '表单 JS 字段项 RunJS 上下文',
|
|
40
41
|
properties: {
|
|
41
|
-
element: 'ElementProxy,表单字段容器',
|
|
42
|
+
element: createZhCNElementPropertyDoc('ElementProxy,表单字段容器'),
|
|
42
43
|
value: '字段值(展示模式为只读;受控场景用 setProps 修改)',
|
|
43
44
|
record: '当前记录(只读)',
|
|
44
45
|
formValues: {
|
|
@@ -8,21 +8,16 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import { FlowRunJSContext } from '../../flowContext';
|
|
11
|
+
import { createElementPropertyDoc, createZhCNElementPropertyDoc } from './elementDoc';
|
|
11
12
|
|
|
12
13
|
export class JSBlockRunJSContext extends FlowRunJSContext {}
|
|
13
14
|
|
|
14
15
|
JSBlockRunJSContext.define({
|
|
15
16
|
label: 'RunJS context',
|
|
16
17
|
properties: {
|
|
17
|
-
element:
|
|
18
|
-
description: `ElementProxy instance providing a safe DOM container.
|
|
18
|
+
element: createElementPropertyDoc(`ElementProxy instance providing a safe DOM container.
|
|
19
19
|
Supports innerHTML, append, and other DOM manipulation methods.
|
|
20
|
-
Use this to render content in the JS block
|
|
21
|
-
detail: 'ElementProxy',
|
|
22
|
-
properties: {
|
|
23
|
-
innerHTML: 'Set or read the HTML content of the container element.',
|
|
24
|
-
},
|
|
25
|
-
},
|
|
20
|
+
Use this to render content in the JS block.`),
|
|
26
21
|
record: `Current record data object (read-only).
|
|
27
22
|
Available when the JS block is within a data block or detail view context.`,
|
|
28
23
|
value: 'Current value of the field or component, if available in the current context.',
|
|
@@ -44,13 +39,7 @@ JSBlockRunJSContext.define(
|
|
|
44
39
|
{
|
|
45
40
|
label: 'RunJS 上下文',
|
|
46
41
|
properties: {
|
|
47
|
-
element:
|
|
48
|
-
description: 'ElementProxy,安全的 DOM 容器,支持 innerHTML/append 等',
|
|
49
|
-
detail: 'ElementProxy',
|
|
50
|
-
properties: {
|
|
51
|
-
innerHTML: '读取或设置容器的 HTML 内容',
|
|
52
|
-
},
|
|
53
|
-
},
|
|
42
|
+
element: createZhCNElementPropertyDoc('ElementProxy,安全的 DOM 容器,支持 innerHTML/append 等'),
|
|
54
43
|
record: '当前记录(只读,用于数据区块/详情等场景)',
|
|
55
44
|
value: '当前值(若存在)',
|
|
56
45
|
React: 'React 库',
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import { FlowRunJSContext } from '../../flowContext';
|
|
11
|
+
import { createElementPropertyDoc, createZhCNElementPropertyDoc } from './elementDoc';
|
|
11
12
|
|
|
12
13
|
/**
|
|
13
14
|
* RunJS context for JSColumnModel (table custom column).
|
|
@@ -18,8 +19,9 @@ export class JSColumnRunJSContext extends FlowRunJSContext {}
|
|
|
18
19
|
JSColumnRunJSContext.define({
|
|
19
20
|
label: 'JSColumn RunJS context',
|
|
20
21
|
properties: {
|
|
21
|
-
element:
|
|
22
|
+
element: createElementPropertyDoc(
|
|
22
23
|
'ElementProxy instance providing a safe DOM container for the current table cell. Supports innerHTML/append and basic DOM APIs.',
|
|
24
|
+
),
|
|
23
25
|
record: 'Current row record object (read-only).',
|
|
24
26
|
recordIndex: 'Index of the current row in the page (0-based).',
|
|
25
27
|
collection: 'Collection definition metadata (read-only).',
|
|
@@ -40,7 +42,7 @@ JSColumnRunJSContext.define(
|
|
|
40
42
|
{
|
|
41
43
|
label: 'JS 列 RunJS 上下文',
|
|
42
44
|
properties: {
|
|
43
|
-
element: 'ElementProxy,表格单元格的安全 DOM 容器,支持 innerHTML/append 等',
|
|
45
|
+
element: createZhCNElementPropertyDoc('ElementProxy,表格单元格的安全 DOM 容器,支持 innerHTML/append 等'),
|
|
44
46
|
record: '当前行记录对象(只读)',
|
|
45
47
|
recordIndex: '当前行索引(从 0 开始)',
|
|
46
48
|
collection: '集合定义元数据(只读)',
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import { FlowRunJSContext } from '../../flowContext';
|
|
11
|
+
import { createElementPropertyDoc, createZhCNElementPropertyDoc } from './elementDoc';
|
|
11
12
|
|
|
12
13
|
/**
|
|
13
14
|
* RunJS context for JSEditableFieldModel (form editable custom field).
|
|
@@ -19,11 +20,9 @@ export class JSEditableFieldRunJSContext extends FlowRunJSContext {}
|
|
|
19
20
|
JSEditableFieldRunJSContext.define({
|
|
20
21
|
label: 'JSEditableField RunJS context',
|
|
21
22
|
properties: {
|
|
22
|
-
element:
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
detail: 'ElementProxy',
|
|
26
|
-
},
|
|
23
|
+
element: createElementPropertyDoc(
|
|
24
|
+
'ElementProxy instance providing a safe DOM container for field rendering. In editable mode this container is typically a <span> element.',
|
|
25
|
+
),
|
|
27
26
|
value: {
|
|
28
27
|
description:
|
|
29
28
|
'Current field value (read-only snapshot). In editable scenarios, prefer ctx.getValue()/ctx.setValue(v) for two-way binding.',
|
|
@@ -69,10 +68,7 @@ JSEditableFieldRunJSContext.define(
|
|
|
69
68
|
{
|
|
70
69
|
label: 'JS 可编辑字段 RunJS 上下文',
|
|
71
70
|
properties: {
|
|
72
|
-
element:
|
|
73
|
-
description: 'ElementProxy,字段渲染的安全容器(通常为 <span> 容器)。',
|
|
74
|
-
detail: 'ElementProxy',
|
|
75
|
-
},
|
|
71
|
+
element: createZhCNElementPropertyDoc('ElementProxy,字段渲染的安全容器(通常为 <span> 容器)。'),
|
|
76
72
|
value: {
|
|
77
73
|
description: '字段当前值(只读快照)。可编辑场景建议使用 ctx.getValue()/ctx.setValue(v) 做双向绑定。',
|
|
78
74
|
detail: 'any',
|
|
@@ -8,14 +8,15 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import { FlowRunJSContext } from '../../flowContext';
|
|
11
|
+
import { createElementPropertyDoc, createZhCNElementPropertyDoc } from './elementDoc';
|
|
11
12
|
|
|
12
13
|
export class JSFieldRunJSContext extends FlowRunJSContext {}
|
|
13
14
|
|
|
14
15
|
JSFieldRunJSContext.define({
|
|
15
16
|
label: 'JSField RunJS context',
|
|
16
17
|
properties: {
|
|
17
|
-
element: `ElementProxy instance providing a safe DOM container for field rendering.
|
|
18
|
-
Supports innerHTML, append, and other DOM manipulation methods
|
|
18
|
+
element: createElementPropertyDoc(`ElementProxy instance providing a safe DOM container for field rendering.
|
|
19
|
+
Supports innerHTML, append, and other DOM manipulation methods.`),
|
|
19
20
|
value: `Current value of the field (read-only).
|
|
20
21
|
Contains the data value stored in this field.`,
|
|
21
22
|
record: `Current record data object (read-only).
|
|
@@ -34,7 +35,7 @@ JSFieldRunJSContext.define(
|
|
|
34
35
|
{
|
|
35
36
|
label: 'JS 字段 RunJS 上下文',
|
|
36
37
|
properties: {
|
|
37
|
-
element: 'ElementProxy,字段渲染容器,支持 innerHTML/append 等 DOM 操作',
|
|
38
|
+
element: createZhCNElementPropertyDoc('ElementProxy,字段渲染容器,支持 innerHTML/append 等 DOM 操作'),
|
|
38
39
|
value: '字段当前值(只读)',
|
|
39
40
|
record: '当前记录对象(只读,包含父记录全部字段值)',
|
|
40
41
|
collection: '集合定义元数据(只读,描述字段所属集合的 Schema)',
|
|
@@ -8,14 +8,15 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import { FlowRunJSContext } from '../../flowContext';
|
|
11
|
+
import { createElementPropertyDoc, createZhCNElementPropertyDoc } from './elementDoc';
|
|
11
12
|
|
|
12
13
|
export class JSItemRunJSContext extends FlowRunJSContext {}
|
|
13
14
|
|
|
14
15
|
JSItemRunJSContext.define({
|
|
15
16
|
label: 'JSItem RunJS context',
|
|
16
17
|
properties: {
|
|
17
|
-
element: `ElementProxy instance providing a safe DOM container for form item rendering.
|
|
18
|
-
Supports innerHTML, append, and other DOM manipulation methods
|
|
18
|
+
element: createElementPropertyDoc(`ElementProxy instance providing a safe DOM container for form item rendering.
|
|
19
|
+
Supports innerHTML, append, and other DOM manipulation methods.`),
|
|
19
20
|
resource: `Current resource instance (read-only).
|
|
20
21
|
Provides access to the data resource associated with the current form context.`,
|
|
21
22
|
record: `Current record data object (read-only).
|
|
@@ -36,7 +37,7 @@ JSItemRunJSContext.define(
|
|
|
36
37
|
{
|
|
37
38
|
label: 'JS 表单项 RunJS 上下文',
|
|
38
39
|
properties: {
|
|
39
|
-
element: 'ElementProxy,表单项渲染容器,支持 innerHTML/append 等 DOM 操作',
|
|
40
|
+
element: createZhCNElementPropertyDoc('ElementProxy,表单项渲染容器,支持 innerHTML/append 等 DOM 操作'),
|
|
40
41
|
resource: '当前资源(只读)',
|
|
41
42
|
record: '当前记录(只读)',
|
|
42
43
|
formValues: {
|