@nocobase/flow-engine 2.0.0-alpha.4 → 2.0.0-alpha.41

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.
Files changed (466) hide show
  1. package/lib/BlockScopedFlowEngine.d.ts +23 -0
  2. package/lib/BlockScopedFlowEngine.js +90 -0
  3. package/lib/FlowContextProvider.d.ts +2 -2
  4. package/lib/FlowContextProvider.js +3 -3
  5. package/lib/FlowDefinition.d.ts +4 -2
  6. package/lib/JSRunner.js +3 -0
  7. package/lib/ViewScopedFlowEngine.d.ts +1 -1
  8. package/lib/ViewScopedFlowEngine.js +12 -0
  9. package/lib/acl/Acl.d.ts +1 -0
  10. package/lib/acl/Acl.js +11 -0
  11. package/lib/components/FieldModelRenderer.js +14 -6
  12. package/lib/components/FieldSkeleton.d.ts +10 -0
  13. package/lib/components/FieldSkeleton.js +64 -0
  14. package/lib/components/FlowContextSelector.js +7 -2
  15. package/lib/components/FlowModelRenderer.d.ts +3 -6
  16. package/lib/components/FlowModelRenderer.js +16 -47
  17. package/lib/components/FormItem.js +5 -1
  18. package/lib/components/MobilePopup.d.ts +20 -0
  19. package/lib/components/MobilePopup.js +102 -0
  20. package/lib/components/MobilePopup.style.d.ts +17 -0
  21. package/lib/components/MobilePopup.style.js +186 -0
  22. package/lib/components/index.d.ts +1 -0
  23. package/lib/components/index.js +3 -1
  24. package/lib/components/settings/independents/dropdown/FlowsDropdownButton.js +2 -2
  25. package/lib/components/settings/wrappers/contextual/DefaultSettingsIcon.js +17 -5
  26. package/lib/components/settings/wrappers/contextual/FlowsContextMenu.js +2 -2
  27. package/lib/components/settings/wrappers/contextual/FlowsFloatContextMenu.d.ts +2 -2
  28. package/lib/components/settings/wrappers/contextual/FlowsFloatContextMenu.js +35 -6
  29. package/lib/components/settings/wrappers/contextual/StepSettingsDialog.js +7 -1
  30. package/lib/components/variables/VariableInput.js +19 -5
  31. package/lib/components/variables/VariableTag.js +43 -2
  32. package/lib/components/variables/types.d.ts +2 -0
  33. package/lib/data-source/index.d.ts +15 -4
  34. package/lib/data-source/index.js +42 -13
  35. package/lib/data-source/sortCollectionsByInherits.d.ts +10 -0
  36. package/lib/data-source/sortCollectionsByInherits.js +71 -0
  37. package/lib/emitter.d.ts +6 -0
  38. package/lib/emitter.js +12 -0
  39. package/lib/executor/FlowExecutor.d.ts +4 -5
  40. package/lib/executor/FlowExecutor.js +168 -99
  41. package/lib/flow-registry/GlobalFlowRegistry.d.ts +1 -0
  42. package/lib/flow-registry/GlobalFlowRegistry.js +3 -0
  43. package/lib/flow-registry/InstanceFlowRegistry.d.ts +1 -0
  44. package/lib/flow-registry/InstanceFlowRegistry.js +3 -0
  45. package/lib/flowContext.d.ts +37 -5
  46. package/lib/flowContext.js +224 -87
  47. package/lib/flowEngine.d.ts +24 -1
  48. package/lib/flowEngine.js +81 -8
  49. package/lib/flowSettings.d.ts +2 -1
  50. package/lib/flowSettings.js +16 -8
  51. package/lib/hooks/useApplyAutoFlows.js +2 -1
  52. package/lib/index.d.ts +7 -1
  53. package/lib/index.js +32 -3
  54. package/lib/locale/en-US.json +4 -2
  55. package/lib/locale/index.d.ts +4 -0
  56. package/lib/locale/zh-CN.json +4 -2
  57. package/lib/models/CollectionFieldModel.d.ts +3 -0
  58. package/lib/models/CollectionFieldModel.js +52 -6
  59. package/lib/models/flowModel.d.ts +30 -29
  60. package/lib/models/flowModel.js +153 -100
  61. package/lib/models/forkFlowModel.d.ts +8 -4
  62. package/lib/models/forkFlowModel.js +38 -8
  63. package/lib/provider.d.ts +3 -1
  64. package/lib/provider.js +7 -5
  65. package/lib/resources/multiRecordResource.js +25 -1
  66. package/lib/resources/singleRecordResource.js +19 -1
  67. package/lib/resources/sqlResource.d.ts +1 -0
  68. package/lib/resources/sqlResource.js +20 -24
  69. package/lib/runjs-context/contexts/FormJSFieldItemRunJSContext.d.ts +1 -6
  70. package/lib/runjs-context/contexts/FormJSFieldItemRunJSContext.js +27 -20
  71. package/lib/runjs-context/contexts/JSBlockRunJSContext.d.ts +1 -6
  72. package/lib/runjs-context/contexts/JSBlockRunJSContext.js +46 -33
  73. package/lib/runjs-context/contexts/JSCollectionActionRunJSContext.d.ts +1 -2
  74. package/lib/runjs-context/contexts/JSCollectionActionRunJSContext.js +14 -15
  75. package/lib/runjs-context/contexts/{LinkageRunJSContext.d.ts → JSColumnRunJSContext.d.ts} +6 -3
  76. package/lib/runjs-context/contexts/JSColumnRunJSContext.js +78 -0
  77. package/lib/runjs-context/contexts/JSFieldRunJSContext.d.ts +1 -6
  78. package/lib/runjs-context/contexts/JSFieldRunJSContext.js +28 -24
  79. package/lib/runjs-context/contexts/JSItemRunJSContext.d.ts +1 -6
  80. package/lib/runjs-context/contexts/JSItemRunJSContext.js +24 -20
  81. package/lib/runjs-context/contexts/JSRecordActionRunJSContext.d.ts +1 -2
  82. package/lib/runjs-context/contexts/JSRecordActionRunJSContext.js +16 -17
  83. package/lib/runjs-context/contexts/base.d.ts +9 -0
  84. package/lib/runjs-context/contexts/base.js +205 -0
  85. package/lib/runjs-context/helpers.d.ts +5 -2
  86. package/lib/runjs-context/helpers.js +36 -27
  87. package/lib/runjs-context/registry.d.ts +7 -4
  88. package/lib/runjs-context/registry.js +10 -42
  89. package/lib/runjs-context/setup.d.ts +9 -0
  90. package/lib/runjs-context/setup.js +82 -0
  91. package/lib/runjs-context/snippets/global/{copy-record-json.snippet.js → api-request.snippet.js} +25 -10
  92. package/lib/runjs-context/snippets/global/clipboard-copy-text.snippet.js +61 -0
  93. package/lib/runjs-context/snippets/global/{view-navigation-push.snippet.js → import-esm.snippet.js} +26 -12
  94. package/lib/runjs-context/snippets/global/message-error.snippet.js +6 -0
  95. package/lib/runjs-context/snippets/global/message-success.snippet.js +6 -0
  96. package/lib/runjs-context/snippets/global/notification-open.snippet.d.ts +3 -8
  97. package/lib/runjs-context/snippets/global/notification-open.snippet.js +8 -1
  98. package/lib/runjs-context/snippets/global/open-view-dialog.snippet.js +10 -3
  99. package/lib/runjs-context/snippets/global/open-view-drawer.snippet.js +10 -3
  100. package/lib/runjs-context/snippets/global/query-selector.snippet.js +53 -0
  101. package/lib/runjs-context/snippets/global/require-amd.snippet.d.ts +11 -0
  102. package/lib/runjs-context/snippets/global/{requireAsync.snippet.js → require-amd.snippet.js} +16 -13
  103. package/lib/runjs-context/snippets/global/window-open.snippet.d.ts +3 -8
  104. package/lib/runjs-context/snippets/global/window-open.snippet.js +8 -1
  105. package/lib/runjs-context/snippets/index.d.ts +14 -3
  106. package/lib/runjs-context/snippets/index.js +162 -40
  107. package/lib/runjs-context/snippets/scene/block/add-event-listener.snippet.d.ts +11 -0
  108. package/lib/runjs-context/snippets/scene/{jsblock → block}/add-event-listener.snippet.js +11 -2
  109. package/lib/runjs-context/snippets/scene/block/api-fetch-render-list.snippet.d.ts +11 -0
  110. package/lib/runjs-context/snippets/scene/block/api-fetch-render-list.snippet.js +64 -0
  111. package/lib/runjs-context/snippets/scene/block/chartjs-bar.snippet.d.ts +11 -0
  112. package/lib/runjs-context/snippets/scene/block/chartjs-bar.snippet.js +99 -0
  113. package/lib/runjs-context/snippets/{libs → scene/block}/echarts-init.snippet.js +24 -7
  114. package/lib/runjs-context/snippets/scene/block/render-antd-icons.snippet.d.ts +11 -0
  115. package/lib/runjs-context/snippets/scene/block/render-antd-icons.snippet.js +65 -0
  116. package/lib/runjs-context/snippets/scene/block/render-button-handler.snippet.d.ts +11 -0
  117. package/lib/runjs-context/snippets/scene/{jsblock → block}/render-button-handler.snippet.js +17 -9
  118. package/lib/runjs-context/snippets/scene/block/render-iframe.snippet.d.ts +11 -0
  119. package/lib/runjs-context/snippets/scene/block/render-iframe.snippet.js +57 -0
  120. package/lib/runjs-context/snippets/scene/block/render-info-card.snippet.d.ts +11 -0
  121. package/lib/runjs-context/snippets/scene/block/render-info-card.snippet.js +71 -0
  122. package/lib/runjs-context/snippets/scene/block/render-react-jsx.snippet.d.ts +11 -0
  123. package/lib/runjs-context/snippets/scene/{jsblock/render-card.snippet.js → block/render-react-jsx.snippet.js} +26 -13
  124. package/lib/runjs-context/snippets/scene/block/render-react.snippet.d.ts +11 -0
  125. package/lib/runjs-context/snippets/scene/{jsblock → block}/render-react.snippet.js +18 -17
  126. package/lib/runjs-context/snippets/scene/block/render-statistics.snippet.d.ts +11 -0
  127. package/lib/runjs-context/snippets/scene/block/render-statistics.snippet.js +95 -0
  128. package/lib/runjs-context/snippets/scene/block/render-timeline.snippet.d.ts +11 -0
  129. package/lib/runjs-context/snippets/scene/block/render-timeline.snippet.js +84 -0
  130. package/lib/runjs-context/snippets/scene/block/resource-example.snippet.d.ts +11 -0
  131. package/lib/runjs-context/snippets/scene/block/resource-example.snippet.js +60 -0
  132. package/lib/runjs-context/snippets/scene/block/three-users-orbit.snippet.d.ts +11 -0
  133. package/lib/runjs-context/snippets/scene/block/three-users-orbit.snippet.js +283 -0
  134. package/lib/runjs-context/snippets/scene/block/vue-component.snippet.d.ts +11 -0
  135. package/lib/runjs-context/snippets/scene/block/vue-component.snippet.js +124 -0
  136. package/lib/runjs-context/snippets/scene/detail/color-by-value.snippet.d.ts +11 -0
  137. package/lib/runjs-context/snippets/scene/{jsfield → detail}/color-by-value.snippet.js +13 -3
  138. package/lib/runjs-context/snippets/scene/detail/copy-to-clipboard.snippet.d.ts +11 -0
  139. package/lib/runjs-context/snippets/{global → scene/detail}/copy-to-clipboard.snippet.js +28 -6
  140. package/lib/runjs-context/snippets/scene/detail/format-number.snippet.d.ts +11 -0
  141. package/lib/runjs-context/snippets/scene/{jsfield → detail}/format-number.snippet.js +13 -3
  142. package/lib/runjs-context/snippets/scene/detail/innerHTML-value.snippet.d.ts +11 -0
  143. package/lib/runjs-context/snippets/scene/{jsfield → detail}/innerHTML-value.snippet.js +13 -3
  144. package/lib/runjs-context/snippets/scene/detail/percentage-bar.snippet.d.ts +11 -0
  145. package/lib/runjs-context/snippets/scene/detail/percentage-bar.snippet.js +82 -0
  146. package/lib/runjs-context/snippets/scene/detail/relative-time.snippet.d.ts +11 -0
  147. package/lib/runjs-context/snippets/scene/detail/relative-time.snippet.js +80 -0
  148. package/lib/runjs-context/snippets/scene/detail/status-tag.snippet.d.ts +11 -0
  149. package/lib/runjs-context/snippets/scene/detail/status-tag.snippet.js +74 -0
  150. package/lib/runjs-context/snippets/scene/form/calculate-total.snippet.d.ts +11 -0
  151. package/lib/runjs-context/snippets/scene/form/calculate-total.snippet.js +63 -0
  152. package/lib/runjs-context/snippets/scene/form/cascade-select.snippet.d.ts +11 -0
  153. package/lib/runjs-context/snippets/scene/form/cascade-select.snippet.js +81 -0
  154. package/lib/runjs-context/snippets/scene/form/conditional-required.snippet.d.ts +11 -0
  155. package/lib/runjs-context/snippets/scene/form/conditional-required.snippet.js +64 -0
  156. package/lib/runjs-context/snippets/scene/form/copy-field-values.snippet.d.ts +11 -0
  157. package/lib/runjs-context/snippets/scene/form/copy-field-values.snippet.js +74 -0
  158. package/lib/runjs-context/snippets/scene/form/render-basic.snippet.d.ts +11 -0
  159. package/lib/runjs-context/snippets/scene/{jsitem → form}/render-basic.snippet.js +11 -2
  160. package/lib/runjs-context/snippets/scene/form/set-disabled.snippet.d.ts +11 -0
  161. package/lib/runjs-context/snippets/scene/{linkage → form}/set-disabled.snippet.js +12 -3
  162. package/lib/runjs-context/snippets/scene/form/set-field-value.snippet.d.ts +11 -0
  163. package/lib/runjs-context/snippets/scene/{linkage → form}/set-field-value.snippet.js +12 -3
  164. package/lib/runjs-context/snippets/scene/form/set-required.snippet.d.ts +11 -0
  165. package/lib/runjs-context/snippets/scene/{linkage → form}/set-required.snippet.js +12 -3
  166. package/lib/runjs-context/snippets/scene/form/toggle-multiple-fields.snippet.d.ts +11 -0
  167. package/lib/runjs-context/snippets/scene/form/toggle-multiple-fields.snippet.js +67 -0
  168. package/lib/runjs-context/snippets/scene/form/toggle-visible.snippet.d.ts +11 -0
  169. package/lib/runjs-context/snippets/scene/{linkage → form}/toggle-visible.snippet.js +12 -3
  170. package/lib/runjs-context/snippets/scene/table/cell-open-dialog.snippet.d.ts +11 -0
  171. package/lib/runjs-context/snippets/scene/table/cell-open-dialog.snippet.js +64 -0
  172. package/lib/runjs-context/snippets/scene/table/collection-selected-count.snippet.d.ts +11 -0
  173. package/lib/runjs-context/snippets/scene/{actions → table}/collection-selected-count.snippet.js +11 -2
  174. package/lib/runjs-context/snippets/scene/table/concat-fields.snippet.d.ts +11 -0
  175. package/lib/runjs-context/snippets/scene/table/concat-fields.snippet.js +79 -0
  176. package/lib/runjs-context/snippets/scene/table/destroy-selected.snippet.d.ts +11 -0
  177. package/lib/runjs-context/snippets/{global/log-json-record.snippet.js → scene/table/destroy-selected.snippet.js} +24 -11
  178. package/lib/runjs-context/snippets/scene/table/export-selected-json.snippet.d.ts +11 -0
  179. package/lib/runjs-context/snippets/scene/table/export-selected-json.snippet.js +64 -0
  180. package/lib/runjs-context/snippets/scene/table/iterate-selected-rows.snippet.d.ts +11 -0
  181. package/lib/runjs-context/snippets/scene/{actions → table}/iterate-selected-rows.snippet.js +11 -2
  182. package/lib/runjs-context/snippets/types.d.ts +9 -1
  183. package/lib/scheduler/ModelOperationScheduler.d.ts +51 -0
  184. package/lib/scheduler/ModelOperationScheduler.js +262 -0
  185. package/lib/types.d.ts +28 -3
  186. package/lib/types.js +4 -3
  187. package/lib/utils/associationObjectVariable.d.ts +32 -0
  188. package/lib/utils/associationObjectVariable.js +157 -0
  189. package/lib/utils/buildSettingsViewInputArgs.d.ts +19 -0
  190. package/lib/utils/buildSettingsViewInputArgs.js +75 -0
  191. package/lib/utils/createEphemeralContext.d.ts +13 -0
  192. package/lib/utils/createEphemeralContext.js +140 -0
  193. package/lib/utils/flows.d.ts +10 -0
  194. package/lib/{runjs-context/snippets/global/api-request-post.snippet.js → utils/flows.js} +21 -15
  195. package/lib/utils/index.d.ts +7 -2
  196. package/lib/utils/index.js +21 -2
  197. package/lib/utils/jsxTransform.d.ts +15 -0
  198. package/lib/utils/jsxTransform.js +68 -0
  199. package/lib/utils/params-resolvers.js +3 -3
  200. package/lib/utils/parsePathnameToViewParams.d.ts +1 -1
  201. package/lib/utils/parsePathnameToViewParams.js +41 -5
  202. package/lib/utils/pruneFilter.d.ts +21 -0
  203. package/lib/{runjs-context/snippets/global/try-catch-async.snippet.js → utils/pruneFilter.js} +24 -16
  204. package/lib/utils/safeGlobals.d.ts +5 -3
  205. package/lib/utils/safeGlobals.js +40 -0
  206. package/lib/utils/schema-utils.js +2 -2
  207. package/lib/utils/serverContextParams.d.ts +1 -0
  208. package/lib/utils/translation.d.ts +4 -1
  209. package/lib/utils/translation.js +6 -2
  210. package/lib/utils/variablesParams.d.ts +22 -5
  211. package/lib/utils/variablesParams.js +132 -36
  212. package/lib/views/DrawerComponent.js +21 -2
  213. package/lib/views/PageComponent.js +2 -1
  214. package/lib/views/ViewNavigation.d.ts +3 -9
  215. package/lib/views/ViewNavigation.js +16 -2
  216. package/lib/views/createViewMeta.d.ts +29 -1
  217. package/lib/views/createViewMeta.js +338 -72
  218. package/lib/views/index.d.ts +1 -0
  219. package/lib/views/index.js +3 -0
  220. package/lib/views/useDialog.d.ts +9 -8
  221. package/lib/views/useDialog.js +19 -14
  222. package/lib/views/useDrawer.d.ts +9 -8
  223. package/lib/views/useDrawer.js +54 -35
  224. package/lib/views/usePage.d.ts +9 -8
  225. package/lib/views/usePage.js +20 -14
  226. package/package.json +6 -3
  227. package/src/BlockScopedFlowEngine.ts +86 -0
  228. package/src/FlowContextProvider.tsx +4 -2
  229. package/src/JSRunner.ts +3 -0
  230. package/src/ViewScopedFlowEngine.ts +15 -1
  231. package/src/__tests__/JSRunner.test.ts +62 -53
  232. package/src/__tests__/blockScopedFlowEngine.test.ts +154 -0
  233. package/src/__tests__/createViewMeta.popup.test.ts +132 -0
  234. package/src/__tests__/flow-engine.test.ts +3 -0
  235. package/src/__tests__/flowContext.test.ts +52 -0
  236. package/src/__tests__/flowContextCreateJSRunner.test.ts +163 -0
  237. package/src/__tests__/flowEngine.saveModel.test.ts +4 -0
  238. package/src/__tests__/flowRunJSContextDefine.test.ts +508 -0
  239. package/src/__tests__/flowSettings.open.test.tsx +2 -0
  240. package/src/__tests__/flowSettings.test.ts +2 -0
  241. package/src/__tests__/globalFlowRegistry.test.ts +1 -1
  242. package/src/__tests__/modelOperationScheduler.test.ts +346 -0
  243. package/src/__tests__/objectVariable.test.ts +464 -0
  244. package/src/__tests__/runjsContext.test.ts +216 -35
  245. package/src/__tests__/runjsContextImplementations.test.ts +217 -0
  246. package/src/__tests__/runjsContextRuntime.test.ts +269 -0
  247. package/src/__tests__/runjsEdgeCases.test.ts +281 -0
  248. package/src/__tests__/runjsLocales.test.ts +36 -0
  249. package/src/__tests__/runjsRuntimeFeatures.test.ts +461 -0
  250. package/src/__tests__/runjsSnippets.test.ts +140 -0
  251. package/src/__tests__/viewScopedFlowEngine.test.ts +3 -3
  252. package/src/acl/Acl.tsx +14 -0
  253. package/src/acl/__tests__/Acl.test.tsx +43 -0
  254. package/src/components/DynamicFlowsEditor.tsx +3 -4
  255. package/src/components/FieldModelRenderer.tsx +20 -7
  256. package/src/components/FieldSkeleton.tsx +27 -0
  257. package/src/components/FlowContextSelector.tsx +6 -2
  258. package/src/components/FlowModelRenderer.tsx +33 -81
  259. package/src/components/FormItem.tsx +8 -1
  260. package/src/components/MobilePopup.style.ts +220 -0
  261. package/src/components/MobilePopup.tsx +86 -0
  262. package/src/components/__tests__/flow-model-render-error-fallback.test.tsx +6 -6
  263. package/src/components/index.ts +1 -0
  264. package/src/components/settings/independents/dropdown/FlowsDropdownButton.tsx +1 -1
  265. package/src/components/settings/wrappers/contextual/DefaultSettingsIcon.tsx +17 -4
  266. package/src/components/settings/wrappers/contextual/FlowsContextMenu.tsx +1 -1
  267. package/src/components/settings/wrappers/contextual/FlowsFloatContextMenu.tsx +39 -10
  268. package/src/components/settings/wrappers/contextual/StepSettingsDialog.tsx +14 -1
  269. package/src/components/settings/wrappers/contextual/__tests__/DefaultSettingsIcon.test.tsx +425 -0
  270. package/src/components/subModel/__tests__/AddSubModelButton.test.tsx +5 -7
  271. package/src/components/variables/VariableInput.tsx +25 -5
  272. package/src/components/variables/VariableTag.tsx +54 -2
  273. package/src/components/variables/types.ts +2 -0
  274. package/src/data-source/__tests__/sortCollectionsByInherits.test.ts +125 -0
  275. package/src/data-source/index.ts +42 -11
  276. package/src/data-source/sortCollectionsByInherits.ts +61 -0
  277. package/src/emitter.ts +14 -0
  278. package/src/executor/FlowExecutor.ts +213 -119
  279. package/src/executor/__tests__/ctx-defs-injection.test.ts +197 -0
  280. package/src/executor/__tests__/flowExecutor.test.ts +151 -5
  281. package/src/flow-registry/GlobalFlowRegistry.ts +1 -0
  282. package/src/flow-registry/InstanceFlowRegistry.ts +1 -0
  283. package/src/flow-registry/__tests__/globalFlowRegistry.test.ts +54 -0
  284. package/src/flowContext.ts +303 -104
  285. package/src/flowEngine.ts +96 -6
  286. package/src/flowSettings.ts +12 -4
  287. package/src/hooks/useApplyAutoFlows.ts +3 -1
  288. package/src/index.ts +12 -1
  289. package/src/locale/en-US.json +4 -2
  290. package/src/locale/zh-CN.json +4 -2
  291. package/src/models/CollectionFieldModel.tsx +60 -8
  292. package/src/models/__tests__/dispatchEvent.behavior.test.ts +169 -0
  293. package/src/models/__tests__/flowModel.getFlows.sort.test.ts +33 -9
  294. package/src/models/__tests__/flowModel.scheduleModelOperation.test.tsx +129 -0
  295. package/src/models/__tests__/flowModel.test.ts +234 -111
  296. package/src/models/__tests__/forkFlowModel.test.ts +40 -7
  297. package/src/models/flowModel.tsx +197 -132
  298. package/src/models/forkFlowModel.ts +48 -8
  299. package/src/provider.tsx +10 -7
  300. package/src/resources/multiRecordResource.ts +28 -1
  301. package/src/resources/singleRecordResource.ts +19 -1
  302. package/src/resources/sqlResource.ts +20 -25
  303. package/src/runjs-context/contexts/FormJSFieldItemRunJSContext.ts +28 -21
  304. package/src/runjs-context/contexts/JSBlockRunJSContext.ts +46 -34
  305. package/src/runjs-context/contexts/JSCollectionActionRunJSContext.ts +15 -16
  306. package/src/runjs-context/contexts/JSColumnRunJSContext.ts +58 -0
  307. package/src/runjs-context/contexts/JSFieldRunJSContext.ts +30 -25
  308. package/src/runjs-context/contexts/JSItemRunJSContext.ts +25 -21
  309. package/src/runjs-context/contexts/JSRecordActionRunJSContext.ts +17 -18
  310. package/src/runjs-context/contexts/base.ts +196 -0
  311. package/src/runjs-context/helpers.ts +32 -30
  312. package/src/runjs-context/registry.ts +16 -47
  313. package/src/runjs-context/setup.ts +51 -0
  314. package/src/runjs-context/snippets/global/api-request.snippet.ts +38 -0
  315. package/src/runjs-context/snippets/global/clipboard-copy-text.snippet.ts +42 -0
  316. package/src/runjs-context/snippets/global/import-esm.snippet.ts +39 -0
  317. package/src/runjs-context/snippets/global/message-error.snippet.ts +6 -0
  318. package/src/runjs-context/snippets/global/message-success.snippet.ts +6 -0
  319. package/src/runjs-context/snippets/global/notification-open.snippet.ts +11 -1
  320. package/src/runjs-context/snippets/global/open-view-dialog.snippet.ts +10 -3
  321. package/src/runjs-context/snippets/global/open-view-drawer.snippet.ts +10 -3
  322. package/src/runjs-context/snippets/global/query-selector.snippet.ts +34 -0
  323. package/src/runjs-context/snippets/global/require-amd.snippet.ts +30 -0
  324. package/src/runjs-context/snippets/global/window-open.snippet.ts +11 -1
  325. package/src/runjs-context/snippets/index.ts +178 -39
  326. package/src/runjs-context/snippets/scene/{jsblock → block}/add-event-listener.snippet.ts +14 -2
  327. package/src/runjs-context/snippets/scene/block/api-fetch-render-list.snippet.ts +45 -0
  328. package/src/runjs-context/snippets/scene/block/chartjs-bar.snippet.ts +80 -0
  329. package/src/runjs-context/snippets/scene/block/echarts-init.snippet.ts +44 -0
  330. package/src/runjs-context/snippets/scene/block/render-antd-icons.snippet.ts +46 -0
  331. package/src/runjs-context/snippets/scene/block/render-button-handler.snippet.ts +35 -0
  332. package/src/runjs-context/snippets/scene/block/render-iframe.snippet.ts +38 -0
  333. package/src/runjs-context/snippets/scene/block/render-info-card.snippet.ts +52 -0
  334. package/src/runjs-context/snippets/scene/block/render-react-jsx.snippet.ts +39 -0
  335. package/src/runjs-context/snippets/scene/block/render-react.snippet.ts +38 -0
  336. package/src/runjs-context/snippets/scene/block/render-statistics.snippet.ts +76 -0
  337. package/src/runjs-context/snippets/scene/block/render-timeline.snippet.ts +65 -0
  338. package/src/runjs-context/snippets/scene/block/resource-example.snippet.ts +46 -0
  339. package/src/runjs-context/snippets/scene/block/three-users-orbit.snippet.ts +264 -0
  340. package/src/runjs-context/snippets/scene/block/vue-component.snippet.ts +105 -0
  341. package/src/runjs-context/snippets/scene/detail/color-by-value.snippet.ts +33 -0
  342. package/src/runjs-context/snippets/scene/detail/copy-to-clipboard.snippet.ts +45 -0
  343. package/src/runjs-context/snippets/scene/detail/format-number.snippet.ts +32 -0
  344. package/src/runjs-context/snippets/scene/detail/innerHTML-value.snippet.ts +31 -0
  345. package/src/runjs-context/snippets/scene/detail/percentage-bar.snippet.ts +63 -0
  346. package/src/runjs-context/snippets/scene/detail/relative-time.snippet.ts +61 -0
  347. package/src/runjs-context/snippets/scene/detail/status-tag.snippet.ts +55 -0
  348. package/src/runjs-context/snippets/scene/form/calculate-total.snippet.ts +44 -0
  349. package/src/runjs-context/snippets/scene/form/cascade-select.snippet.ts +62 -0
  350. package/src/runjs-context/snippets/scene/form/conditional-required.snippet.ts +45 -0
  351. package/src/runjs-context/snippets/scene/form/copy-field-values.snippet.ts +55 -0
  352. package/src/runjs-context/snippets/scene/{jsitem → form}/render-basic.snippet.ts +14 -2
  353. package/src/runjs-context/snippets/scene/{linkage → form}/set-disabled.snippet.ts +15 -3
  354. package/src/runjs-context/snippets/scene/{linkage → form}/set-field-value.snippet.ts +15 -3
  355. package/src/runjs-context/snippets/scene/{linkage → form}/set-required.snippet.ts +15 -3
  356. package/src/runjs-context/snippets/scene/form/toggle-multiple-fields.snippet.ts +48 -0
  357. package/src/runjs-context/snippets/scene/{linkage → form}/toggle-visible.snippet.ts +15 -3
  358. package/src/runjs-context/snippets/scene/table/cell-open-dialog.snippet.ts +45 -0
  359. package/src/runjs-context/snippets/scene/{actions → table}/collection-selected-count.snippet.ts +14 -2
  360. package/src/runjs-context/snippets/scene/table/concat-fields.snippet.ts +60 -0
  361. package/src/runjs-context/snippets/scene/table/destroy-selected.snippet.ts +36 -0
  362. package/src/runjs-context/snippets/scene/table/export-selected-json.snippet.ts +45 -0
  363. package/src/runjs-context/snippets/scene/{actions → table}/iterate-selected-rows.snippet.ts +14 -2
  364. package/src/runjs-context/snippets/types.ts +5 -1
  365. package/src/scheduler/ModelOperationScheduler.ts +304 -0
  366. package/src/types.ts +34 -0
  367. package/src/utils/__tests__/flows.test.ts +65 -0
  368. package/src/utils/__tests__/jsxTransform.test.ts +38 -0
  369. package/src/utils/__tests__/parsePathnameToViewParams.test.ts +25 -0
  370. package/src/utils/__tests__/pruneFilter.test.ts +38 -0
  371. package/src/utils/__tests__/safeGlobals.test.ts +22 -1
  372. package/src/utils/__tests__/variablesParams.test.ts +63 -0
  373. package/src/utils/associationObjectVariable.ts +180 -0
  374. package/src/utils/buildSettingsViewInputArgs.ts +72 -0
  375. package/src/utils/createEphemeralContext.ts +142 -0
  376. package/src/utils/flows.ts +23 -0
  377. package/src/utils/index.ts +11 -2
  378. package/src/utils/jsxTransform.ts +39 -0
  379. package/src/utils/params-resolvers.ts +2 -2
  380. package/src/utils/parsePathnameToViewParams.ts +50 -6
  381. package/src/utils/pruneFilter.ts +41 -0
  382. package/src/utils/safeGlobals.ts +49 -3
  383. package/src/utils/schema-utils.ts +1 -1
  384. package/src/utils/serverContextParams.ts +1 -0
  385. package/src/utils/translation.ts +7 -2
  386. package/src/utils/variablesParams.ts +156 -38
  387. package/src/views/DrawerComponent.tsx +21 -2
  388. package/src/views/PageComponent.tsx +1 -1
  389. package/src/views/ViewNavigation.ts +20 -12
  390. package/src/views/__tests__/ViewNavigation.test.ts +10 -0
  391. package/src/views/createViewMeta.ts +393 -70
  392. package/src/views/index.tsx +1 -0
  393. package/src/views/useDialog.tsx +24 -18
  394. package/src/views/useDrawer.tsx +74 -45
  395. package/src/views/usePage.tsx +26 -17
  396. package/lib/runjs-context/contexts/FlowRunJSContext.d.ts +0 -38
  397. package/lib/runjs-context/contexts/FlowRunJSContext.js +0 -217
  398. package/lib/runjs-context/contexts/LinkageRunJSContext.js +0 -62
  399. package/lib/runjs-context/index.d.ts +0 -19
  400. package/lib/runjs-context/index.js +0 -57
  401. package/lib/runjs-context/snippets/global/api-request-get.snippet.d.ts +0 -16
  402. package/lib/runjs-context/snippets/global/api-request-get.snippet.js +0 -42
  403. package/lib/runjs-context/snippets/global/api-request-post.snippet.d.ts +0 -16
  404. package/lib/runjs-context/snippets/global/console-log-ctx.snippet.d.ts +0 -16
  405. package/lib/runjs-context/snippets/global/console-log-ctx.snippet.js +0 -41
  406. package/lib/runjs-context/snippets/global/requireAsync.snippet.d.ts +0 -16
  407. package/lib/runjs-context/snippets/global/sleep.snippet.d.ts +0 -16
  408. package/lib/runjs-context/snippets/global/sleep.snippet.js +0 -43
  409. package/lib/runjs-context/snippets/global/try-catch-async.snippet.d.ts +0 -16
  410. package/lib/runjs-context/snippets/libs/echarts-init.snippet.d.ts +0 -15
  411. package/lib/runjs-context/snippets/scene/actions/collection-selected-count.snippet.d.ts +0 -15
  412. package/lib/runjs-context/snippets/scene/actions/iterate-selected-rows.snippet.d.ts +0 -15
  413. package/lib/runjs-context/snippets/scene/actions/record-id-message.snippet.d.ts +0 -15
  414. package/lib/runjs-context/snippets/scene/actions/record-id-message.snippet.js +0 -43
  415. package/lib/runjs-context/snippets/scene/actions/run-action-basic.snippet.d.ts +0 -15
  416. package/lib/runjs-context/snippets/scene/actions/run-action-basic.snippet.js +0 -40
  417. package/lib/runjs-context/snippets/scene/jsblock/add-event-listener.snippet.d.ts +0 -15
  418. package/lib/runjs-context/snippets/scene/jsblock/append-style.snippet.d.ts +0 -15
  419. package/lib/runjs-context/snippets/scene/jsblock/append-style.snippet.js +0 -42
  420. package/lib/runjs-context/snippets/scene/jsblock/jsx-mount.snippet.d.ts +0 -15
  421. package/lib/runjs-context/snippets/scene/jsblock/jsx-mount.snippet.js +0 -46
  422. package/lib/runjs-context/snippets/scene/jsblock/jsx-unmount.snippet.d.ts +0 -15
  423. package/lib/runjs-context/snippets/scene/jsblock/jsx-unmount.snippet.js +0 -41
  424. package/lib/runjs-context/snippets/scene/jsblock/render-basic.snippet.d.ts +0 -15
  425. package/lib/runjs-context/snippets/scene/jsblock/render-basic.snippet.js +0 -41
  426. package/lib/runjs-context/snippets/scene/jsblock/render-button-handler.snippet.d.ts +0 -15
  427. package/lib/runjs-context/snippets/scene/jsblock/render-react.snippet.d.ts +0 -15
  428. package/lib/runjs-context/snippets/scene/jsfield/color-by-value.snippet.d.ts +0 -15
  429. package/lib/runjs-context/snippets/scene/jsfield/format-number.snippet.d.ts +0 -15
  430. package/lib/runjs-context/snippets/scene/jsfield/innerHTML-value.snippet.d.ts +0 -15
  431. package/lib/runjs-context/snippets/scene/jsitem/render-basic.snippet.d.ts +0 -15
  432. package/lib/runjs-context/snippets/scene/linkage/set-disabled.snippet.d.ts +0 -15
  433. package/lib/runjs-context/snippets/scene/linkage/set-field-value.snippet.d.ts +0 -15
  434. package/lib/runjs-context/snippets/scene/linkage/set-required.snippet.d.ts +0 -15
  435. package/lib/runjs-context/snippets/scene/linkage/toggle-visible.snippet.d.ts +0 -15
  436. package/src/runjs-context/contexts/FlowRunJSContext.ts +0 -190
  437. package/src/runjs-context/contexts/LinkageRunJSContext.ts +0 -35
  438. package/src/runjs-context/index.ts +0 -20
  439. package/src/runjs-context/snippets/global/api-request-get.snippet.ts +0 -20
  440. package/src/runjs-context/snippets/global/api-request-post.snippet.ts +0 -20
  441. package/src/runjs-context/snippets/global/console-log-ctx.snippet.ts +0 -19
  442. package/src/runjs-context/snippets/global/copy-record-json.snippet.ts +0 -21
  443. package/src/runjs-context/snippets/global/copy-to-clipboard.snippet.ts +0 -21
  444. package/src/runjs-context/snippets/global/log-json-record.snippet.ts +0 -21
  445. package/src/runjs-context/snippets/global/requireAsync.snippet.ts +0 -24
  446. package/src/runjs-context/snippets/global/sleep.snippet.ts +0 -21
  447. package/src/runjs-context/snippets/global/try-catch-async.snippet.ts +0 -22
  448. package/src/runjs-context/snippets/global/view-navigation-push.snippet.ts +0 -23
  449. package/src/runjs-context/snippets/libs/echarts-init.snippet.ts +0 -24
  450. package/src/runjs-context/snippets/scene/actions/record-id-message.snippet.ts +0 -21
  451. package/src/runjs-context/snippets/scene/actions/run-action-basic.snippet.ts +0 -18
  452. package/src/runjs-context/snippets/scene/jsblock/append-style.snippet.ts +0 -20
  453. package/src/runjs-context/snippets/scene/jsblock/jsx-mount.snippet.ts +0 -24
  454. package/src/runjs-context/snippets/scene/jsblock/jsx-unmount.snippet.ts +0 -19
  455. package/src/runjs-context/snippets/scene/jsblock/render-basic.snippet.ts +0 -24
  456. package/src/runjs-context/snippets/scene/jsblock/render-button-handler.snippet.ts +0 -24
  457. package/src/runjs-context/snippets/scene/jsblock/render-card.snippet.ts +0 -30
  458. package/src/runjs-context/snippets/scene/jsblock/render-react.snippet.ts +0 -34
  459. package/src/runjs-context/snippets/scene/jsfield/color-by-value.snippet.ts +0 -20
  460. package/src/runjs-context/snippets/scene/jsfield/format-number.snippet.ts +0 -19
  461. package/src/runjs-context/snippets/scene/jsfield/innerHTML-value.snippet.ts +0 -18
  462. /package/lib/runjs-context/snippets/global/{copy-record-json.snippet.d.ts → api-request.snippet.d.ts} +0 -0
  463. /package/lib/runjs-context/snippets/global/{copy-to-clipboard.snippet.d.ts → clipboard-copy-text.snippet.d.ts} +0 -0
  464. /package/lib/runjs-context/snippets/global/{log-json-record.snippet.d.ts → import-esm.snippet.d.ts} +0 -0
  465. /package/lib/runjs-context/snippets/global/{view-navigation-push.snippet.d.ts → query-selector.snippet.d.ts} +0 -0
  466. /package/lib/runjs-context/snippets/scene/{jsblock/render-card.snippet.d.ts → block/echarts-init.snippet.d.ts} +0 -0
@@ -12,6 +12,7 @@ import { FlowEngine } from '../../flowEngine';
12
12
  import type { FlowModelOptions, IModelComponentProps } from '../../types';
13
13
  import { FlowModel } from '../flowModel';
14
14
  import { ForkFlowModel } from '../forkFlowModel';
15
+ import { uid } from 'uid/secure';
15
16
 
16
17
  // Helper functions
17
18
  const createMockFlowEngine = (): FlowEngine => {
@@ -49,10 +50,9 @@ describe('ForkFlowModel', () => {
49
50
  // ==================== CONSTRUCTOR & INITIALIZATION ====================
50
51
  describe('Constructor & Initialization', () => {
51
52
  test('should create fork with basic parameters', () => {
52
- const fork = new ForkFlowModel(mockMaster, initialProps, 1);
53
+ const fork = new ForkFlowModel(mockMaster, initialProps, '1');
53
54
 
54
55
  expect(fork.uid).toBe(mockMaster.uid);
55
- expect(fork.forkId).toBe(1);
56
56
  expect(fork.localProps).toEqual(initialProps);
57
57
  expect(fork.isFork).toBe(true);
58
58
  expect((fork as any).master).toBe(mockMaster);
@@ -63,7 +63,6 @@ describe('ForkFlowModel', () => {
63
63
  const fork = new ForkFlowModel(mockMaster);
64
64
 
65
65
  expect(fork.uid).toBe(mockMaster.uid);
66
- expect(fork.forkId).toBe(0);
67
66
  expect(fork.localProps).toEqual({});
68
67
  expect(fork.isFork).toBe(true);
69
68
  });
@@ -115,7 +114,7 @@ describe('ForkFlowModel', () => {
115
114
  let fork: ForkFlowModel;
116
115
 
117
116
  beforeEach(() => {
118
- fork = new ForkFlowModel(mockMaster, initialProps, 1);
117
+ fork = new ForkFlowModel(mockMaster, initialProps, '1');
119
118
  });
120
119
 
121
120
  test('should return disposed status correctly', () => {
@@ -149,7 +148,7 @@ describe('ForkFlowModel', () => {
149
148
 
150
149
  test('should return fork own properties first', () => {
151
150
  expect(fork.uid).toBe(mockMaster.uid);
152
- expect(fork.forkId).toBe(1);
151
+ expect(fork.forkId).toBe('1');
153
152
  expect(fork.isFork).toBe(true);
154
153
  expect(fork.localProps).toEqual(initialProps);
155
154
  });
@@ -424,6 +423,24 @@ describe('ForkFlowModel', () => {
424
423
  });
425
424
  });
426
425
 
426
+ test('should clear local props with clearProps', () => {
427
+ const masterProps = { master: 'value', conflict: 'master' };
428
+ mockMaster.getProps = vi.fn(() => masterProps);
429
+
430
+ // 先设置一些本地属性
431
+ fork.setProps({ local: 'v', conflict: 'local' });
432
+ expect(fork.localProps).toEqual({ initial: 'value', local: 'v', conflict: 'local' });
433
+
434
+ // 调用 clearProps,应当返回一个空对象
435
+ const result = (fork as any).clearProps();
436
+ expect(result).toStrictEqual({});
437
+ expect(fork.localProps).toStrictEqual({});
438
+
439
+ // 清空后,合并的 props 应回退为仅 master 的 props
440
+ expect(fork.getProps()).toEqual(masterProps);
441
+ expect(fork.props).toEqual(masterProps);
442
+ });
443
+
427
444
  test('should get merged props from master and local', () => {
428
445
  const masterProps = { master: 'value', shared: 'master' };
429
446
  const localProps = { local: 'value', shared: 'local' };
@@ -662,8 +679,8 @@ describe('ForkFlowModel', () => {
662
679
  });
663
680
 
664
681
  test('should find and remove correct fork from cache', () => {
665
- const fork1 = new ForkFlowModel(mockMaster, {}, 1);
666
- const fork2 = new ForkFlowModel(mockMaster, {}, 2);
682
+ const fork1 = new ForkFlowModel(mockMaster, {}, '1');
683
+ const fork2 = new ForkFlowModel(mockMaster, {}, '2');
667
684
 
668
685
  (mockMaster as any).forkCache.set('key1', fork1);
669
686
  (mockMaster as any).forkCache.set('key2', fork2);
@@ -673,6 +690,22 @@ describe('ForkFlowModel', () => {
673
690
  expect((mockMaster as any).forkCache.has('key1')).toBe(false);
674
691
  expect((mockMaster as any).forkCache.has('key2')).toBe(true);
675
692
  });
693
+
694
+ test('forkIds must be unique', () => {
695
+ // 创建第一个 fork
696
+ const fork1 = mockMaster.createFork({}, uid());
697
+ const forkId1 = fork1.forkId;
698
+ expect(forkId1).toBeDefined();
699
+ // 创建第二个 fork
700
+ const fork2 = mockMaster.createFork({}, uid());
701
+ expect(fork2.forkId).not.toBe(forkId1);
702
+ // 销毁第一个 fork
703
+ fork1.dispose();
704
+ // 创建第三个 fork
705
+ const fork3 = mockMaster.createFork({}, uid());
706
+ expect(fork1['disposed']).toBe(true);
707
+ expect(fork3.forkId).not.toBe(fork2.forkId);
708
+ });
676
709
  });
677
710
 
678
711
  // ==================== FUNCTION BINDING AND CONTEXT ====================
@@ -50,8 +50,9 @@ import { ModelEventRegistry } from '../event-registry/ModelEventRegistry';
50
50
  import { GlobalFlowRegistry } from '../flow-registry/GlobalFlowRegistry';
51
51
  import { FlowDefinition } from '../FlowDefinition';
52
52
  import { FlowSettingsOpenOptions } from '../flowSettings';
53
- import type { EventDefinition } from '../types';
53
+ import type { EventDefinition, FlowEvent, DispatchEventOptions } from '../types';
54
54
  import { ForkFlowModel } from './forkFlowModel';
55
+ import type { ScheduleOptions } from '../scheduler/ModelOperationScheduler';
55
56
 
56
57
  // 使用 WeakMap 为每个类缓存一个 ModelActionRegistry 实例
57
58
  const classActionRegistries = new WeakMap<typeof FlowModel, ModelActionRegistry>();
@@ -89,6 +90,7 @@ export class FlowModel<Structure extends DefaultStructure = DefaultStructure> {
89
90
  private _options: FlowModelOptions<Structure>;
90
91
  protected _title: string;
91
92
  public isNew = false; // 标记是否为新建状态
93
+ public skeleton = null;
92
94
 
93
95
  /**
94
96
  * 所有 fork 实例的引用集合。
@@ -103,9 +105,9 @@ export class FlowModel<Structure extends DefaultStructure = DefaultStructure> {
103
105
  private forkCache: Map<string, ForkFlowModel<any>> = new Map();
104
106
 
105
107
  /**
106
- * 上一次 applyAutoFlows 的执行参数
108
+ * 上一次 beforeRender 的执行参数
107
109
  */
108
- private _lastAutoRunParams: any[] | null = null;
110
+ private _lastAutoRunParams: [Record<string, any> | undefined, boolean?] | null = null;
109
111
  protected observerDispose: () => void;
110
112
  #flowContext: FlowModelContext;
111
113
 
@@ -176,7 +178,7 @@ export class FlowModel<Structure extends DefaultStructure = DefaultStructure> {
176
178
  }
177
179
 
178
180
  if (this.flowEngine) {
179
- this.invalidateAutoFlowCache();
181
+ this.invalidateFlowCache('beforeRender');
180
182
  }
181
183
  this._rerunLastAutoRun();
182
184
  this.forks.forEach((fork) => {
@@ -256,6 +258,14 @@ export class FlowModel<Structure extends DefaultStructure = DefaultStructure> {
256
258
  return this._options.parentId;
257
259
  }
258
260
 
261
+ public scheduleModelOperation(
262
+ toUid: string,
263
+ fn: (model: FlowModel) => Promise<void> | void,
264
+ options?: ScheduleOptions,
265
+ ) {
266
+ return this.flowEngine?.scheduleModelOperation(this, toUid, fn, options);
267
+ }
268
+
259
269
  static get meta() {
260
270
  return modelMetas.get(this);
261
271
  }
@@ -387,13 +397,63 @@ export class FlowModel<Structure extends DefaultStructure = DefaultStructure> {
387
397
  });
388
398
  }
389
399
 
390
- public invalidateAutoFlowCache(deep = false) {
400
+ /**
401
+ * 失效指定事件的流程缓存;未指定 eventName 时,失效当前模型全部事件缓存。
402
+ * - 默认 beforeRender 与其它事件共享同一缓存体系:prefix=`event:${scope}`,flowKey=`eventName`,uid=`model.uid`
403
+ */
404
+ public invalidateFlowCache(eventName?: string, deep = false) {
391
405
  if (this.flowEngine) {
392
- const cacheKey = FlowEngine.generateApplyFlowCacheKey('autoFlow', 'all', this.uid);
393
- this.flowEngine.applyFlowCache.delete(cacheKey);
406
+ const scope = `event:${this.getFlowCacheScope(eventName || 'beforeRender')}`;
407
+ const cache = this.flowEngine.applyFlowCache;
408
+
409
+ if (eventName) {
410
+ // 删除该事件名下所有缓存(忽略不同 inputArgs 的散列差异)
411
+ const altScope = scope.replace(/:/g, '-');
412
+ const uidSuffixes = [`:${this.uid}`, `-${this.uid}`];
413
+ const eventSegments = [`:${eventName}:`, `-${eventName}-`];
414
+ for (const key of cache.keys()) {
415
+ const startMatches = key.startsWith(scope) || key.startsWith(altScope);
416
+ const endMatches = uidSuffixes.some((s) => key.endsWith(s));
417
+ const eventMatches = eventSegments.some((seg) => key.includes(seg));
418
+ if (startMatches && endMatches && eventMatches) {
419
+ cache.delete(key);
420
+ }
421
+ }
422
+ } else {
423
+ // 粗粒度:扫描并删除当前模型 uid 相关的事件缓存(任意事件)
424
+ const altScope = `${scope}:`.replace(/:/g, '-');
425
+ const prefixes = [`${scope}:`, altScope];
426
+ const uidSuffixes = [`:${this.uid}`, `-${this.uid}`];
427
+ for (const key of cache.keys()) {
428
+ const startMatches = prefixes.some((p) => key.startsWith(p));
429
+ const endMatches = uidSuffixes.some((s) => key.endsWith(s));
430
+ if (startMatches && endMatches) cache.delete(key);
431
+ }
432
+ }
433
+
434
+ // 同步失效所有 fork 的缓存
394
435
  this.forks.forEach((fork) => {
395
- const forkCacheKey = FlowEngine.generateApplyFlowCacheKey(`${fork['forkId']}`, 'all', this.uid);
396
- this.flowEngine.applyFlowCache.delete(forkCacheKey);
436
+ const forkScope = `event:${
437
+ (fork as any).getFlowCacheScope?.(eventName || 'beforeRender') ?? String((fork as any)['forkId'])
438
+ }`;
439
+ const altForkScope = forkScope.replace(/:/g, '-');
440
+ const uidSuffixes = [`:${this.uid}`, `-${this.uid}`];
441
+ if (eventName) {
442
+ const eventSegments = [`:${eventName}:`, `-${eventName}-`];
443
+ for (const key of this.flowEngine.applyFlowCache.keys()) {
444
+ const startMatches = key.startsWith(forkScope) || key.startsWith(altForkScope);
445
+ const endMatches = uidSuffixes.some((s) => key.endsWith(s));
446
+ const eventMatches = eventSegments.some((seg) => key.includes(seg));
447
+ if (startMatches && endMatches && eventMatches) this.flowEngine.applyFlowCache.delete(key);
448
+ }
449
+ } else {
450
+ const prefixes = [`${forkScope}:`, `${altForkScope}-`];
451
+ for (const key of this.flowEngine.applyFlowCache.keys()) {
452
+ const startMatches = prefixes.some((p) => key.startsWith(p));
453
+ const endMatches = uidSuffixes.some((s) => key.endsWith(s));
454
+ if (startMatches && endMatches) this.flowEngine.applyFlowCache.delete(key);
455
+ }
456
+ }
397
457
  });
398
458
  }
399
459
  if (deep) {
@@ -402,10 +462,10 @@ export class FlowModel<Structure extends DefaultStructure = DefaultStructure> {
402
462
  const subModelValue = this.subModels[subModelKey];
403
463
  if (Array.isArray(subModelValue)) {
404
464
  for (const subModel of subModelValue) {
405
- subModel.invalidateAutoFlowCache(deep);
465
+ subModel.invalidateFlowCache(eventName, deep);
406
466
  }
407
467
  } else if (subModelValue instanceof FlowModel) {
408
- subModelValue.invalidateAutoFlowCache(deep);
468
+ subModelValue.invalidateFlowCache(eventName, deep);
409
469
  }
410
470
  }
411
471
  }
@@ -551,17 +611,22 @@ export class FlowModel<Structure extends DefaultStructure = DefaultStructure> {
551
611
  const instanceKeys = new Set(instanceFlows.keys());
552
612
  const staticEntries = Array.from(staticFlows.entries()).filter(([key]) => !instanceKeys.has(key));
553
613
 
554
- // 实例流保持原始注册顺序,统一一次排序(稳定排序):
614
+ // 组内排序:
615
+ // - 静态流:GlobalFlowRegistry 已按 sort 和继承深度排序,直接使用
616
+ // - 实例流:按 sort 升序;相同 sort 保持注册顺序
555
617
  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;
618
+ const instanceEntriesWithIndex = instanceEntries.map((e, i) => ({ e, i }));
619
+ instanceEntriesWithIndex.sort((a, b) => {
620
+ const sa = a.e[1].sort ?? 0;
621
+ const sb = b.e[1].sort ?? 0;
560
622
  if (sa !== sb) return sa - sb;
561
- return 0; // 其它情况保持稳定顺序(静态内部:父类优先;实例内部:注册顺序)
623
+ return a.i - b.i; // 稳定顺序
562
624
  });
563
625
 
564
- return new Map<string, FlowDefinition>(allEntries);
626
+ // 分组合并:动态流(实例)优先于静态流
627
+ const merged: [string, FlowDefinition][] = [...instanceEntriesWithIndex.map(({ e }) => e), ...staticEntries];
628
+
629
+ return new Map<string, FlowDefinition>(merged);
565
630
  }
566
631
 
567
632
  setProps(props: IModelComponentProps): void;
@@ -637,7 +702,11 @@ export class FlowModel<Structure extends DefaultStructure = DefaultStructure> {
637
702
  return currentFlowEngine.executor.runFlow(target, flowKey, inputArgs, runId);
638
703
  }
639
704
 
640
- private async _dispatchEvent(eventName: string, inputArgs?: Record<string, any>): Promise<void> {
705
+ private async _dispatchEvent(
706
+ eventName: string,
707
+ inputArgs?: Record<string, any>,
708
+ options?: DispatchEventOptions,
709
+ ): Promise<any[]> {
641
710
  const currentFlowEngine = this.flowEngine;
642
711
  if (!currentFlowEngine) {
643
712
  console.warn('FlowEngine not available on this model for dispatchEvent. Please set flowEngine on the model.');
@@ -650,64 +719,77 @@ export class FlowModel<Structure extends DefaultStructure = DefaultStructure> {
650
719
  this.cleanRun
651
720
  }, targetIsFork=${(target as any)?.isFork === true}`,
652
721
  );
653
- await currentFlowEngine.executor.dispatchEvent(target, eventName, inputArgs);
722
+ return await currentFlowEngine.executor.dispatchEvent(target, eventName, inputArgs, options);
654
723
  }
655
724
 
656
- private _dispatchEventWithDebounce = _.debounce(async (eventName: string, inputArgs?: Record<string, any>) => {
657
- return this._dispatchEvent(eventName, inputArgs);
658
- }, 100);
725
+ private _dispatchEventWithDebounce = _.debounce(
726
+ async (eventName: string, inputArgs?: Record<string, any>, options?: DispatchEventOptions) => {
727
+ return this._dispatchEvent(eventName, inputArgs, options);
728
+ },
729
+ 100,
730
+ );
659
731
 
660
732
  async dispatchEvent(
661
733
  eventName: string,
662
734
  inputArgs?: Record<string, any>,
663
735
  options?: {
664
- /**
665
- * 是否要开启防抖功能
666
- */
667
- debounce: boolean;
668
- },
669
- ): Promise<void> {
670
- if (options?.debounce) {
671
- return this._dispatchEventWithDebounce(eventName, inputArgs);
736
+ /** 是否要开启防抖功能 */
737
+ debounce?: boolean;
738
+ } & DispatchEventOptions,
739
+ ): Promise<any[]> {
740
+ const isBeforeRender = eventName === 'beforeRender';
741
+ // 缺省值由模型层提供:beforeRender 默认顺序执行 + 使用缓存;其它事件默认顺序执行(不默认使用缓存)
742
+ const defaults = isBeforeRender ? { sequential: true, useCache: true } : { sequential: true };
743
+ const execOptions = {
744
+ sequential: options?.sequential ?? (defaults as any).sequential,
745
+ useCache: options?.useCache ?? (defaults as any).useCache,
746
+ } as DispatchEventOptions;
747
+
748
+ // 记录最近一次 beforeRender 的入参与选项,便于 stepParams 变化时触发重跑
749
+ if (isBeforeRender) {
750
+ this._lastAutoRunParams = [inputArgs, execOptions.useCache];
751
+ }
752
+ let finalInputArgs = inputArgs;
753
+ if (this.context.record) {
754
+ finalInputArgs = { record: this.context.record, ...inputArgs };
672
755
  }
673
756
 
674
- return this._dispatchEvent(eventName, inputArgs);
757
+ if (options?.debounce) {
758
+ return this._dispatchEventWithDebounce(eventName, finalInputArgs, execOptions);
759
+ }
760
+ return this._dispatchEvent(eventName, finalInputArgs, execOptions);
675
761
  }
676
762
 
677
763
  /**
678
- * 获取所有自动应用流程定义(保持 getFlows 的顺序,即按 sort 排序)
679
- * @returns {FlowDefinition[]} 自动应用流程定义数组(已按 sort 排序)
764
+ * 按事件名获取对应的流程集合(保持 getFlows 的顺序,即按 sort 排序)。
765
+ * - beforeRender 兼容:除显式 on: 'beforeRender' 外,包含未声明 on 且 manual !== true 的流程。
680
766
  */
681
- public getAutoFlows(): FlowDefinition[] {
767
+ public getEventFlows(eventName: string): FlowDefinition[] {
682
768
  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;
769
+ const beforeRender = eventName === 'beforeRender';
770
+ const isMatch = (flow: FlowDefinition) => {
771
+ if (beforeRender) {
772
+ if (flow.manual === true) return false;
773
+ if (!flow.on) return true;
774
+ return typeof flow.on === 'string' ? flow.on === 'beforeRender' : flow.on?.eventName === 'beforeRender';
694
775
  }
695
- // 其他情况默认自动执行
696
- return true;
697
- });
698
-
699
- return autoFlows;
776
+ const on = flow.on;
777
+ if (!on) return false;
778
+ return typeof on === 'string' ? on === eventName : on?.eventName === eventName;
779
+ };
780
+ return Array.from(allFlows.values()).filter(isMatch);
700
781
  }
701
782
 
702
783
  /**
703
- * 重新执行上一次的 applyAutoFlows,保持参数一致
784
+ * 重新执行上一次的 beforeRender,保持参数一致
704
785
  * 如果之前没有执行过,则直接跳过
705
786
  * 使用 lodash debounce 避免频繁调用
706
787
  */
707
788
  private _rerunLastAutoRun = _.debounce(async () => {
708
789
  if (this._lastAutoRunParams) {
709
790
  try {
710
- await this.applyAutoFlows(...this._lastAutoRunParams);
791
+ const [inputArgs] = this._lastAutoRunParams as any[];
792
+ await this.dispatchEvent('beforeRender', inputArgs);
711
793
  } catch (error) {
712
794
  console.error('FlowModel._rerunLastAutoRun: Error during rerun:', error);
713
795
  }
@@ -715,86 +797,39 @@ export class FlowModel<Structure extends DefaultStructure = DefaultStructure> {
715
797
  }, 100);
716
798
 
717
799
  /**
718
- * 自动流程执行前钩子。
719
- * 子类可覆盖;可抛出 FlowExitException 提前终止。
800
+ * 通用事件分发钩子:开始
801
+ * 子类可覆盖;beforeRender 事件可通过抛出 FlowExitException 提前终止。
720
802
  */
721
- public async onBeforeAutoFlows(inputArgs?: Record<string, any>): Promise<void> {}
803
+ public async onDispatchEventStart(
804
+ eventName: string,
805
+ options?: DispatchEventOptions,
806
+ inputArgs?: Record<string, any>,
807
+ ): Promise<void> {}
722
808
 
723
809
  /**
724
- * 自动流程执行后钩子。
810
+ * 通用事件分发钩子:结束
725
811
  * 子类可覆盖。
726
812
  */
727
- public async onAfterAutoFlows(results: any[], inputArgs?: Record<string, any>): Promise<void> {}
813
+ public async onDispatchEventEnd(
814
+ eventName: string,
815
+ options?: DispatchEventOptions,
816
+ inputArgs?: Record<string, any>,
817
+ results?: any[],
818
+ ): Promise<void> {}
728
819
 
729
820
  /**
730
- * 自动流程错误钩子。
821
+ * 通用事件分发钩子:错误
731
822
  * 子类可覆盖。
732
823
  */
733
- public async onAutoFlowsError(error: Error, inputArgs?: Record<string, any>): Promise<void> {}
824
+ public async onDispatchEventError(
825
+ eventName: string,
826
+ options?: DispatchEventOptions,
827
+ inputArgs?: Record<string, any>,
828
+ error?: Error,
829
+ ): Promise<void> {}
734
830
 
735
831
  useHooksBeforeRender() {}
736
832
 
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
833
  /**
799
834
  * 智能检测是否应该跳过响应式包装
800
835
  * 说明:
@@ -874,10 +909,20 @@ export class FlowModel<Structure extends DefaultStructure = DefaultStructure> {
874
909
  if (typeof renderTarget.onMount === 'function') {
875
910
  renderTarget.onMount();
876
911
  }
912
+ // 发射 mounted 生命周期事件(严格模式:不吞错,若有错误将以未处理拒绝暴露)
913
+ void renderTarget.flowEngine?.emitter?.emitAsync('model:mounted', {
914
+ uid: renderTarget.uid,
915
+ model: renderTarget,
916
+ });
877
917
  return () => {
878
918
  if (typeof renderTarget.onUnmount === 'function') {
879
919
  renderTarget.onUnmount();
880
920
  }
921
+ // 发射 unmounted 生命周期事件(严格模式:不吞错)
922
+ void renderTarget.flowEngine?.emitter?.emitAsync('model:unmounted', {
923
+ uid: renderTarget.uid,
924
+ model: renderTarget,
925
+ });
881
926
  };
882
927
  }, [renderTarget]);
883
928
 
@@ -891,6 +936,10 @@ export class FlowModel<Structure extends DefaultStructure = DefaultStructure> {
891
936
  return modelInstance.renderHiddenInConfig?.();
892
937
  }
893
938
 
939
+ // 订阅 stepParams 变化,以便当步骤参数(如 JS 代码等)更新时触发一次 React 渲染,
940
+ // 从而让 useHooksBeforeRender 中的副作用得以感知并执行(如 applyFlow('jsSettings'))。
941
+ modelInstance.stepParams;
942
+
894
943
  // 调用原始渲染方法
895
944
  return originalRender.call(renderTarget);
896
945
  });
@@ -962,14 +1011,14 @@ export class FlowModel<Structure extends DefaultStructure = DefaultStructure> {
962
1011
  }
963
1012
 
964
1013
  async rerender() {
965
- await this.applyAutoFlows(this._lastAutoRunParams?.[0], false);
1014
+ await this.dispatchEvent('beforeRender', this._lastAutoRunParams?.[0], { useCache: false });
966
1015
  }
967
1016
 
968
1017
  /**
969
- * 自动流程缓存的作用域标识;fork 实例可覆盖以区分缓存。
1018
+ * 事件缓存的作用域标识;可按事件区分(默认与事件无关的 scope 返回 'default')。
970
1019
  */
971
- public getAutoFlowCacheScope(): string {
972
- return 'autoFlow';
1020
+ public getFlowCacheScope(eventName: string): string {
1021
+ return String(eventName);
973
1022
  }
974
1023
 
975
1024
  setParent(parent: FlowModel): void {
@@ -1024,6 +1073,13 @@ export class FlowModel<Structure extends DefaultStructure = DefaultStructure> {
1024
1073
  model.sortIndex = maxSortIndex + 1;
1025
1074
  subModels[subKey].push(model);
1026
1075
  actualParent.emitter.emit('onSubModelAdded', model);
1076
+ // 同步发射到引擎级事件总线,便于外部统一监听模型树变更
1077
+ actualParent.flowEngine?.emitter?.emit('model:subModel:added', {
1078
+ parentUid: actualParent.uid,
1079
+ parent: actualParent,
1080
+ subKey,
1081
+ model,
1082
+ });
1027
1083
  return model;
1028
1084
  }
1029
1085
 
@@ -1050,6 +1106,12 @@ export class FlowModel<Structure extends DefaultStructure = DefaultStructure> {
1050
1106
  model.setParent(actualParent);
1051
1107
  (actualParent.subModels as any)[subKey] = model;
1052
1108
  actualParent.emitter.emit('onSubModelAdded', model);
1109
+ actualParent.flowEngine?.emitter?.emit('model:subModel:added', {
1110
+ parentUid: actualParent.uid,
1111
+ parent: actualParent,
1112
+ subKey,
1113
+ model,
1114
+ });
1053
1115
  return model;
1054
1116
  }
1055
1117
 
@@ -1128,14 +1190,17 @@ export class FlowModel<Structure extends DefaultStructure = DefaultStructure> {
1128
1190
  return this.flowEngine.createModel(options);
1129
1191
  }
1130
1192
 
1131
- async applySubModelsAutoFlows<K extends keyof Structure['subModels']>(
1193
+ /**
1194
+ * 对指定子模型派发 beforeRender 事件(顺序执行并使用缓存)。
1195
+ */
1196
+ async applySubModelsBeforeRenderFlows<K extends keyof Structure['subModels']>(
1132
1197
  subKey: K,
1133
1198
  inputArgs?: Record<string, any>,
1134
1199
  shared?: Record<string, any>,
1135
1200
  ) {
1136
1201
  await Promise.all(
1137
1202
  this.mapSubModels(subKey, async (sub) => {
1138
- await sub.applyAutoFlows(inputArgs);
1203
+ await sub.dispatchEvent('beforeRender', inputArgs);
1139
1204
  }),
1140
1205
  );
1141
1206
  }
@@ -1162,7 +1227,7 @@ export class FlowModel<Structure extends DefaultStructure = DefaultStructure> {
1162
1227
  }
1163
1228
 
1164
1229
  // 创建新的 fork 实例
1165
- const forkId = this.forks.size; // 当前集合大小作为索引
1230
+ const forkId = uid(); // 当前集合大小作为索引
1166
1231
  const fork = new ForkFlowModel<this>(this as any, localProps, forkId);
1167
1232
  if (options?.register !== false) {
1168
1233
  this.forks.add(fork as any);
@@ -1209,7 +1274,7 @@ export class FlowModel<Structure extends DefaultStructure = DefaultStructure> {
1209
1274
  throw new Error('FlowEngine is not set on this model. Please set flowEngine before saving.');
1210
1275
  }
1211
1276
  this.observerDispose();
1212
- this.invalidateAutoFlowCache(true);
1277
+ this.invalidateFlowCache('beforeRender', true);
1213
1278
  return this.flowEngine.removeModel(this.uid);
1214
1279
  }
1215
1280
 
@@ -1229,7 +1294,7 @@ export class FlowModel<Structure extends DefaultStructure = DefaultStructure> {
1229
1294
  throw new Error('FlowEngine is not set on this model. Please set flowEngine before deleting.');
1230
1295
  }
1231
1296
  this.observerDispose();
1232
- this.invalidateAutoFlowCache(true);
1297
+ this.invalidateFlowCache('beforeRender', true);
1233
1298
  // 从 FlowEngine 中销毁模型
1234
1299
  return this.flowEngine.destroyModel(this.uid);
1235
1300
  }
@@ -1307,6 +1372,7 @@ export class FlowModel<Structure extends DefaultStructure = DefaultStructure> {
1307
1372
  ..._.omit(this._options, ['flowEngine']),
1308
1373
  stepParams: this.stepParams,
1309
1374
  sortIndex: this.sortIndex,
1375
+ flowRegistry: {},
1310
1376
  };
1311
1377
  const subModels = this.subModels as {
1312
1378
  [key: string]: FlowModel | FlowModel[];
@@ -1323,8 +1389,7 @@ export class FlowModel<Structure extends DefaultStructure = DefaultStructure> {
1323
1389
  }
1324
1390
  }
1325
1391
  for (const [key, flow] of this.flowRegistry.getFlows()) {
1326
- data['flowRegistry'] = data['flowRegistry'] || {};
1327
- data['flowRegistry'][key] = flow.toData();
1392
+ data.flowRegistry[key] = flow.toData();
1328
1393
  }
1329
1394
  return data;
1330
1395
  }