@nocobase/flow-engine 2.0.0-alpha.3 → 2.0.0-alpha.30

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 (418) 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/components/FieldModelRenderer.js +10 -4
  9. package/lib/components/FieldSkeleton.d.ts +10 -0
  10. package/lib/components/FieldSkeleton.js +64 -0
  11. package/lib/components/FlowContextSelector.js +7 -2
  12. package/lib/components/FlowModelRenderer.d.ts +2 -5
  13. package/lib/components/FlowModelRenderer.js +16 -47
  14. package/lib/components/FormItem.js +5 -1
  15. package/lib/{runjs-context/snippets/global/requireAsync.snippet.d.ts → components/dnd/findModelUidPosition.d.ts} +4 -7
  16. package/lib/{runjs-context/snippets/scene/jsblock/jsx-mount.snippet.js → components/dnd/findModelUidPosition.js} +23 -19
  17. package/lib/components/dnd/gridDragPlanner.d.ts +130 -0
  18. package/lib/components/dnd/gridDragPlanner.js +497 -0
  19. package/lib/components/dnd/index.d.ts +2 -2
  20. package/lib/components/dnd/index.js +5 -5
  21. package/lib/components/settings/independents/dropdown/FlowsDropdownButton.js +2 -2
  22. package/lib/components/settings/wrappers/contextual/DefaultSettingsIcon.js +17 -5
  23. package/lib/components/settings/wrappers/contextual/FlowsContextMenu.js +2 -2
  24. package/lib/components/settings/wrappers/contextual/StepSettingsDialog.js +7 -1
  25. package/lib/components/variables/VariableInput.js +16 -2
  26. package/lib/components/variables/VariableTag.js +43 -2
  27. package/lib/components/variables/types.d.ts +2 -0
  28. package/lib/data-source/index.d.ts +12 -4
  29. package/lib/data-source/index.js +19 -13
  30. package/lib/data-source/sortCollectionsByInherits.d.ts +10 -0
  31. package/lib/data-source/sortCollectionsByInherits.js +71 -0
  32. package/lib/executor/FlowExecutor.d.ts +4 -5
  33. package/lib/executor/FlowExecutor.js +135 -100
  34. package/lib/flowContext.d.ts +33 -5
  35. package/lib/flowContext.js +193 -76
  36. package/lib/flowEngine.d.ts +8 -1
  37. package/lib/flowEngine.js +18 -6
  38. package/lib/flowSettings.d.ts +2 -1
  39. package/lib/flowSettings.js +12 -8
  40. package/lib/hooks/useApplyAutoFlows.js +2 -1
  41. package/lib/index.d.ts +7 -1
  42. package/lib/index.js +32 -3
  43. package/lib/locale/en-US.json +4 -2
  44. package/lib/locale/index.d.ts +4 -0
  45. package/lib/locale/zh-CN.json +4 -2
  46. package/lib/models/CollectionFieldModel.d.ts +2 -0
  47. package/lib/models/CollectionFieldModel.js +43 -3
  48. package/lib/models/flowModel.d.ts +28 -29
  49. package/lib/models/flowModel.js +114 -92
  50. package/lib/models/forkFlowModel.d.ts +4 -4
  51. package/lib/models/forkFlowModel.js +32 -8
  52. package/lib/provider.d.ts +3 -1
  53. package/lib/provider.js +7 -5
  54. package/lib/resources/multiRecordResource.js +2 -0
  55. package/lib/resources/singleRecordResource.js +1 -0
  56. package/lib/resources/sqlResource.d.ts +1 -0
  57. package/lib/resources/sqlResource.js +20 -24
  58. package/lib/runjs-context/contexts/FormJSFieldItemRunJSContext.d.ts +1 -6
  59. package/lib/runjs-context/contexts/FormJSFieldItemRunJSContext.js +27 -20
  60. package/lib/runjs-context/contexts/JSBlockRunJSContext.d.ts +1 -6
  61. package/lib/runjs-context/contexts/JSBlockRunJSContext.js +46 -33
  62. package/lib/runjs-context/contexts/JSCollectionActionRunJSContext.d.ts +1 -2
  63. package/lib/runjs-context/contexts/JSCollectionActionRunJSContext.js +14 -15
  64. package/lib/runjs-context/contexts/{LinkageRunJSContext.d.ts → JSColumnRunJSContext.d.ts} +6 -3
  65. package/lib/runjs-context/contexts/JSColumnRunJSContext.js +78 -0
  66. package/lib/runjs-context/contexts/JSFieldRunJSContext.d.ts +1 -6
  67. package/lib/runjs-context/contexts/JSFieldRunJSContext.js +28 -24
  68. package/lib/runjs-context/contexts/JSItemRunJSContext.d.ts +1 -6
  69. package/lib/runjs-context/contexts/JSItemRunJSContext.js +24 -20
  70. package/lib/runjs-context/contexts/JSRecordActionRunJSContext.d.ts +1 -2
  71. package/lib/runjs-context/contexts/JSRecordActionRunJSContext.js +16 -17
  72. package/lib/runjs-context/contexts/base.d.ts +9 -0
  73. package/lib/runjs-context/contexts/base.js +183 -0
  74. package/lib/runjs-context/helpers.d.ts +5 -2
  75. package/lib/runjs-context/helpers.js +36 -27
  76. package/lib/runjs-context/registry.d.ts +7 -4
  77. package/lib/runjs-context/registry.js +10 -42
  78. package/lib/runjs-context/setup.d.ts +9 -0
  79. package/lib/runjs-context/setup.js +82 -0
  80. package/lib/runjs-context/snippets/global/{copy-record-json.snippet.js → api-request.snippet.js} +25 -10
  81. package/lib/runjs-context/snippets/global/clipboard-copy-text.snippet.js +61 -0
  82. package/lib/runjs-context/snippets/global/{view-navigation-push.snippet.js → import-esm.snippet.js} +26 -12
  83. package/lib/runjs-context/snippets/global/message-error.snippet.js +6 -0
  84. package/lib/runjs-context/snippets/global/message-success.snippet.js +6 -0
  85. package/lib/runjs-context/snippets/global/notification-open.snippet.d.ts +3 -8
  86. package/lib/runjs-context/snippets/global/notification-open.snippet.js +8 -1
  87. package/lib/runjs-context/snippets/global/open-view-dialog.snippet.js +10 -3
  88. package/lib/runjs-context/snippets/global/open-view-drawer.snippet.js +10 -3
  89. package/lib/runjs-context/snippets/global/query-selector.snippet.js +53 -0
  90. package/lib/runjs-context/snippets/global/require-amd.snippet.d.ts +11 -0
  91. package/lib/runjs-context/snippets/global/{requireAsync.snippet.js → require-amd.snippet.js} +16 -13
  92. package/lib/runjs-context/snippets/global/window-open.snippet.d.ts +3 -8
  93. package/lib/runjs-context/snippets/global/window-open.snippet.js +8 -1
  94. package/lib/runjs-context/snippets/index.d.ts +14 -3
  95. package/lib/runjs-context/snippets/index.js +161 -40
  96. package/lib/runjs-context/snippets/scene/block/add-event-listener.snippet.d.ts +11 -0
  97. package/lib/runjs-context/snippets/scene/{jsblock → block}/add-event-listener.snippet.js +11 -2
  98. package/lib/runjs-context/snippets/scene/block/api-fetch-render-list.snippet.d.ts +11 -0
  99. package/lib/runjs-context/snippets/scene/block/api-fetch-render-list.snippet.js +64 -0
  100. package/lib/runjs-context/snippets/scene/block/chartjs-bar.snippet.d.ts +11 -0
  101. package/lib/runjs-context/snippets/scene/block/chartjs-bar.snippet.js +99 -0
  102. package/lib/runjs-context/snippets/{libs → scene/block}/echarts-init.snippet.js +24 -7
  103. package/lib/runjs-context/snippets/scene/block/render-button-handler.snippet.d.ts +11 -0
  104. package/lib/runjs-context/snippets/scene/{jsblock → block}/render-button-handler.snippet.js +17 -9
  105. package/lib/runjs-context/snippets/scene/block/render-iframe.snippet.d.ts +11 -0
  106. package/lib/runjs-context/snippets/scene/block/render-iframe.snippet.js +57 -0
  107. package/lib/runjs-context/snippets/scene/block/render-info-card.snippet.d.ts +11 -0
  108. package/lib/runjs-context/snippets/scene/block/render-info-card.snippet.js +71 -0
  109. package/lib/runjs-context/snippets/scene/block/render-react-jsx.snippet.d.ts +11 -0
  110. package/lib/runjs-context/snippets/scene/{jsblock/render-card.snippet.js → block/render-react-jsx.snippet.js} +26 -13
  111. package/lib/runjs-context/snippets/scene/block/render-react.snippet.d.ts +11 -0
  112. package/lib/runjs-context/snippets/scene/{jsblock → block}/render-react.snippet.js +18 -17
  113. package/lib/runjs-context/snippets/scene/block/render-statistics.snippet.d.ts +11 -0
  114. package/lib/runjs-context/snippets/scene/block/render-statistics.snippet.js +95 -0
  115. package/lib/runjs-context/snippets/scene/block/render-timeline.snippet.d.ts +11 -0
  116. package/lib/runjs-context/snippets/scene/block/render-timeline.snippet.js +84 -0
  117. package/lib/runjs-context/snippets/scene/block/resource-example.snippet.d.ts +11 -0
  118. package/lib/runjs-context/snippets/scene/block/resource-example.snippet.js +60 -0
  119. package/lib/runjs-context/snippets/scene/block/three-users-orbit.snippet.d.ts +11 -0
  120. package/lib/runjs-context/snippets/scene/block/three-users-orbit.snippet.js +283 -0
  121. package/lib/runjs-context/snippets/scene/block/vue-component.snippet.d.ts +11 -0
  122. package/lib/runjs-context/snippets/scene/block/vue-component.snippet.js +124 -0
  123. package/lib/runjs-context/snippets/scene/detail/color-by-value.snippet.d.ts +11 -0
  124. package/lib/runjs-context/snippets/scene/{jsfield → detail}/color-by-value.snippet.js +13 -3
  125. package/lib/runjs-context/snippets/scene/detail/copy-to-clipboard.snippet.d.ts +11 -0
  126. package/lib/runjs-context/snippets/{global → scene/detail}/copy-to-clipboard.snippet.js +28 -6
  127. package/lib/runjs-context/snippets/scene/detail/format-number.snippet.d.ts +11 -0
  128. package/lib/runjs-context/snippets/scene/{jsfield → detail}/format-number.snippet.js +13 -3
  129. package/lib/runjs-context/snippets/scene/detail/innerHTML-value.snippet.d.ts +11 -0
  130. package/lib/runjs-context/snippets/scene/{jsfield → detail}/innerHTML-value.snippet.js +13 -3
  131. package/lib/runjs-context/snippets/scene/detail/percentage-bar.snippet.d.ts +11 -0
  132. package/lib/runjs-context/snippets/scene/detail/percentage-bar.snippet.js +82 -0
  133. package/lib/runjs-context/snippets/scene/detail/relative-time.snippet.d.ts +11 -0
  134. package/lib/runjs-context/snippets/scene/detail/relative-time.snippet.js +80 -0
  135. package/lib/runjs-context/snippets/scene/detail/status-tag.snippet.d.ts +11 -0
  136. package/lib/runjs-context/snippets/scene/detail/status-tag.snippet.js +74 -0
  137. package/lib/runjs-context/snippets/scene/form/calculate-total.snippet.d.ts +11 -0
  138. package/lib/runjs-context/snippets/scene/form/calculate-total.snippet.js +63 -0
  139. package/lib/runjs-context/snippets/scene/form/cascade-select.snippet.d.ts +11 -0
  140. package/lib/runjs-context/snippets/scene/form/cascade-select.snippet.js +81 -0
  141. package/lib/runjs-context/snippets/scene/form/conditional-required.snippet.d.ts +11 -0
  142. package/lib/runjs-context/snippets/scene/form/conditional-required.snippet.js +64 -0
  143. package/lib/runjs-context/snippets/scene/form/copy-field-values.snippet.d.ts +11 -0
  144. package/lib/runjs-context/snippets/scene/form/copy-field-values.snippet.js +74 -0
  145. package/lib/runjs-context/snippets/scene/form/render-basic.snippet.d.ts +11 -0
  146. package/lib/runjs-context/snippets/scene/{jsitem → form}/render-basic.snippet.js +11 -2
  147. package/lib/runjs-context/snippets/scene/form/set-disabled.snippet.d.ts +11 -0
  148. package/lib/runjs-context/snippets/scene/{linkage → form}/set-disabled.snippet.js +12 -3
  149. package/lib/runjs-context/snippets/scene/form/set-field-value.snippet.d.ts +11 -0
  150. package/lib/runjs-context/snippets/scene/{linkage → form}/set-field-value.snippet.js +12 -3
  151. package/lib/runjs-context/snippets/scene/form/set-required.snippet.d.ts +11 -0
  152. package/lib/runjs-context/snippets/scene/{linkage → form}/set-required.snippet.js +12 -3
  153. package/lib/runjs-context/snippets/scene/form/toggle-multiple-fields.snippet.d.ts +11 -0
  154. package/lib/runjs-context/snippets/scene/form/toggle-multiple-fields.snippet.js +67 -0
  155. package/lib/runjs-context/snippets/scene/form/toggle-visible.snippet.d.ts +11 -0
  156. package/lib/runjs-context/snippets/scene/{linkage → form}/toggle-visible.snippet.js +12 -3
  157. package/lib/runjs-context/snippets/scene/table/cell-open-dialog.snippet.d.ts +11 -0
  158. package/lib/runjs-context/snippets/scene/table/cell-open-dialog.snippet.js +64 -0
  159. package/lib/runjs-context/snippets/scene/table/collection-selected-count.snippet.d.ts +11 -0
  160. package/lib/runjs-context/snippets/scene/{actions → table}/collection-selected-count.snippet.js +11 -2
  161. package/lib/runjs-context/snippets/scene/table/concat-fields.snippet.d.ts +11 -0
  162. package/lib/runjs-context/snippets/scene/table/concat-fields.snippet.js +79 -0
  163. package/lib/runjs-context/snippets/scene/table/destroy-selected.snippet.d.ts +11 -0
  164. package/lib/runjs-context/snippets/{global/log-json-record.snippet.js → scene/table/destroy-selected.snippet.js} +24 -11
  165. package/lib/runjs-context/snippets/scene/table/export-selected-json.snippet.d.ts +11 -0
  166. package/lib/runjs-context/snippets/scene/table/export-selected-json.snippet.js +64 -0
  167. package/lib/runjs-context/snippets/scene/table/iterate-selected-rows.snippet.d.ts +11 -0
  168. package/lib/runjs-context/snippets/scene/{actions → table}/iterate-selected-rows.snippet.js +11 -2
  169. package/lib/runjs-context/snippets/types.d.ts +9 -1
  170. package/lib/types.d.ts +28 -3
  171. package/lib/types.js +4 -3
  172. package/lib/utils/buildSettingsViewInputArgs.d.ts +19 -0
  173. package/lib/utils/buildSettingsViewInputArgs.js +75 -0
  174. package/lib/utils/createEphemeralContext.d.ts +13 -0
  175. package/lib/utils/createEphemeralContext.js +140 -0
  176. package/lib/utils/index.d.ts +3 -2
  177. package/lib/utils/index.js +5 -2
  178. package/lib/utils/jsxTransform.d.ts +15 -0
  179. package/lib/utils/jsxTransform.js +68 -0
  180. package/lib/utils/params-resolvers.js +3 -3
  181. package/lib/utils/safeGlobals.d.ts +5 -3
  182. package/lib/utils/safeGlobals.js +40 -0
  183. package/lib/utils/schema-utils.js +2 -2
  184. package/lib/utils/serverContextParams.d.ts +1 -0
  185. package/lib/utils/variablesParams.d.ts +9 -5
  186. package/lib/utils/variablesParams.js +47 -36
  187. package/lib/views/PageComponent.js +2 -1
  188. package/lib/views/createViewMeta.d.ts +29 -1
  189. package/lib/views/createViewMeta.js +338 -72
  190. package/lib/views/index.d.ts +1 -0
  191. package/lib/views/index.js +3 -0
  192. package/lib/views/useDialog.d.ts +8 -8
  193. package/lib/views/useDialog.js +8 -7
  194. package/lib/views/useDrawer.d.ts +8 -8
  195. package/lib/views/useDrawer.js +40 -26
  196. package/lib/views/usePage.d.ts +8 -8
  197. package/lib/views/usePage.js +8 -7
  198. package/package.json +5 -3
  199. package/src/BlockScopedFlowEngine.ts +86 -0
  200. package/src/FlowContextProvider.tsx +4 -2
  201. package/src/JSRunner.ts +3 -0
  202. package/src/ViewScopedFlowEngine.ts +1 -1
  203. package/src/__tests__/JSRunner.test.ts +62 -53
  204. package/src/__tests__/blockScopedFlowEngine.test.ts +154 -0
  205. package/src/__tests__/createViewMeta.popup.test.ts +132 -0
  206. package/src/__tests__/flow-engine.test.ts +3 -0
  207. package/src/__tests__/flowContextCreateJSRunner.test.ts +163 -0
  208. package/src/__tests__/flowEngine.saveModel.test.ts +4 -0
  209. package/src/__tests__/flowRunJSContextDefine.test.ts +508 -0
  210. package/src/__tests__/globalFlowRegistry.test.ts +1 -1
  211. package/src/__tests__/runjsContext.test.ts +216 -35
  212. package/src/__tests__/runjsContextImplementations.test.ts +217 -0
  213. package/src/__tests__/runjsContextRuntime.test.ts +269 -0
  214. package/src/__tests__/runjsEdgeCases.test.ts +281 -0
  215. package/src/__tests__/runjsLocales.test.ts +36 -0
  216. package/src/__tests__/runjsRuntimeFeatures.test.ts +449 -0
  217. package/src/__tests__/runjsSnippets.test.ts +140 -0
  218. package/src/__tests__/viewScopedFlowEngine.test.ts +3 -3
  219. package/src/components/DynamicFlowsEditor.tsx +3 -4
  220. package/src/components/FieldModelRenderer.tsx +16 -5
  221. package/src/components/FieldSkeleton.tsx +27 -0
  222. package/src/components/FlowContextSelector.tsx +6 -2
  223. package/src/components/FlowModelRenderer.tsx +30 -78
  224. package/src/components/FormItem.tsx +8 -1
  225. package/src/components/__tests__/flow-model-render-error-fallback.test.tsx +5 -5
  226. package/src/components/__tests__/gridDragPlanner.test.ts +494 -0
  227. package/src/components/dnd/README.md +149 -0
  228. package/src/components/dnd/findModelUidPosition.ts +26 -0
  229. package/src/components/dnd/gridDragPlanner.ts +659 -0
  230. package/src/components/dnd/index.tsx +3 -3
  231. package/src/components/settings/independents/dropdown/FlowsDropdownButton.tsx +1 -1
  232. package/src/components/settings/wrappers/contextual/DefaultSettingsIcon.tsx +17 -4
  233. package/src/components/settings/wrappers/contextual/FlowsContextMenu.tsx +1 -1
  234. package/src/components/settings/wrappers/contextual/StepSettingsDialog.tsx +14 -1
  235. package/src/components/settings/wrappers/contextual/__tests__/DefaultSettingsIcon.test.tsx +424 -0
  236. package/src/components/subModel/__tests__/AddSubModelButton.test.tsx +5 -7
  237. package/src/components/variables/VariableInput.tsx +22 -2
  238. package/src/components/variables/VariableTag.tsx +54 -2
  239. package/src/components/variables/types.ts +2 -0
  240. package/src/data-source/__tests__/sortCollectionsByInherits.test.ts +125 -0
  241. package/src/data-source/index.ts +17 -11
  242. package/src/data-source/sortCollectionsByInherits.ts +61 -0
  243. package/src/executor/FlowExecutor.ts +178 -121
  244. package/src/executor/__tests__/ctx-defs-injection.test.ts +197 -0
  245. package/src/executor/__tests__/flowExecutor.test.ts +151 -5
  246. package/src/flowContext.ts +266 -97
  247. package/src/flowEngine.ts +21 -6
  248. package/src/flowSettings.ts +9 -4
  249. package/src/hooks/useApplyAutoFlows.ts +3 -1
  250. package/src/index.ts +12 -1
  251. package/src/locale/en-US.json +4 -2
  252. package/src/locale/zh-CN.json +4 -2
  253. package/src/models/CollectionFieldModel.tsx +43 -4
  254. package/src/models/__tests__/flowModel.getFlows.sort.test.ts +4 -4
  255. package/src/models/__tests__/flowModel.test.ts +234 -111
  256. package/src/models/__tests__/forkFlowModel.test.ts +22 -7
  257. package/src/models/flowModel.tsx +149 -125
  258. package/src/models/forkFlowModel.ts +41 -8
  259. package/src/provider.tsx +10 -7
  260. package/src/resources/multiRecordResource.ts +2 -0
  261. package/src/resources/singleRecordResource.ts +1 -0
  262. package/src/resources/sqlResource.ts +20 -25
  263. package/src/runjs-context/contexts/FormJSFieldItemRunJSContext.ts +28 -21
  264. package/src/runjs-context/contexts/JSBlockRunJSContext.ts +46 -34
  265. package/src/runjs-context/contexts/JSCollectionActionRunJSContext.ts +15 -16
  266. package/src/runjs-context/contexts/JSColumnRunJSContext.ts +58 -0
  267. package/src/runjs-context/contexts/JSFieldRunJSContext.ts +30 -25
  268. package/src/runjs-context/contexts/JSItemRunJSContext.ts +25 -21
  269. package/src/runjs-context/contexts/JSRecordActionRunJSContext.ts +17 -18
  270. package/src/runjs-context/contexts/base.ts +171 -0
  271. package/src/runjs-context/helpers.ts +32 -30
  272. package/src/runjs-context/registry.ts +16 -47
  273. package/src/runjs-context/setup.ts +51 -0
  274. package/src/runjs-context/snippets/global/api-request.snippet.ts +38 -0
  275. package/src/runjs-context/snippets/global/clipboard-copy-text.snippet.ts +42 -0
  276. package/src/runjs-context/snippets/global/import-esm.snippet.ts +39 -0
  277. package/src/runjs-context/snippets/global/message-error.snippet.ts +6 -0
  278. package/src/runjs-context/snippets/global/message-success.snippet.ts +6 -0
  279. package/src/runjs-context/snippets/global/notification-open.snippet.ts +11 -1
  280. package/src/runjs-context/snippets/global/open-view-dialog.snippet.ts +10 -3
  281. package/src/runjs-context/snippets/global/open-view-drawer.snippet.ts +10 -3
  282. package/src/runjs-context/snippets/global/query-selector.snippet.ts +34 -0
  283. package/src/runjs-context/snippets/global/require-amd.snippet.ts +30 -0
  284. package/src/runjs-context/snippets/global/window-open.snippet.ts +11 -1
  285. package/src/runjs-context/snippets/index.ts +177 -39
  286. package/src/runjs-context/snippets/scene/{jsblock → block}/add-event-listener.snippet.ts +14 -2
  287. package/src/runjs-context/snippets/scene/block/api-fetch-render-list.snippet.ts +45 -0
  288. package/src/runjs-context/snippets/scene/block/chartjs-bar.snippet.ts +80 -0
  289. package/src/runjs-context/snippets/scene/block/echarts-init.snippet.ts +44 -0
  290. package/src/runjs-context/snippets/scene/block/render-button-handler.snippet.ts +35 -0
  291. package/src/runjs-context/snippets/scene/block/render-iframe.snippet.ts +38 -0
  292. package/src/runjs-context/snippets/scene/block/render-info-card.snippet.ts +52 -0
  293. package/src/runjs-context/snippets/scene/block/render-react-jsx.snippet.ts +39 -0
  294. package/src/runjs-context/snippets/scene/block/render-react.snippet.ts +38 -0
  295. package/src/runjs-context/snippets/scene/block/render-statistics.snippet.ts +76 -0
  296. package/src/runjs-context/snippets/scene/block/render-timeline.snippet.ts +65 -0
  297. package/src/runjs-context/snippets/scene/block/resource-example.snippet.ts +46 -0
  298. package/src/runjs-context/snippets/scene/block/three-users-orbit.snippet.ts +264 -0
  299. package/src/runjs-context/snippets/scene/block/vue-component.snippet.ts +105 -0
  300. package/src/runjs-context/snippets/scene/detail/color-by-value.snippet.ts +33 -0
  301. package/src/runjs-context/snippets/scene/detail/copy-to-clipboard.snippet.ts +45 -0
  302. package/src/runjs-context/snippets/scene/detail/format-number.snippet.ts +32 -0
  303. package/src/runjs-context/snippets/scene/detail/innerHTML-value.snippet.ts +31 -0
  304. package/src/runjs-context/snippets/scene/detail/percentage-bar.snippet.ts +63 -0
  305. package/src/runjs-context/snippets/scene/detail/relative-time.snippet.ts +61 -0
  306. package/src/runjs-context/snippets/scene/detail/status-tag.snippet.ts +55 -0
  307. package/src/runjs-context/snippets/scene/form/calculate-total.snippet.ts +44 -0
  308. package/src/runjs-context/snippets/scene/form/cascade-select.snippet.ts +62 -0
  309. package/src/runjs-context/snippets/scene/form/conditional-required.snippet.ts +45 -0
  310. package/src/runjs-context/snippets/scene/form/copy-field-values.snippet.ts +55 -0
  311. package/src/runjs-context/snippets/scene/{jsitem → form}/render-basic.snippet.ts +14 -2
  312. package/src/runjs-context/snippets/scene/{linkage → form}/set-disabled.snippet.ts +15 -3
  313. package/src/runjs-context/snippets/scene/{linkage → form}/set-field-value.snippet.ts +15 -3
  314. package/src/runjs-context/snippets/scene/{linkage → form}/set-required.snippet.ts +15 -3
  315. package/src/runjs-context/snippets/scene/form/toggle-multiple-fields.snippet.ts +48 -0
  316. package/src/runjs-context/snippets/scene/{linkage → form}/toggle-visible.snippet.ts +15 -3
  317. package/src/runjs-context/snippets/scene/table/cell-open-dialog.snippet.ts +45 -0
  318. package/src/runjs-context/snippets/scene/{actions → table}/collection-selected-count.snippet.ts +14 -2
  319. package/src/runjs-context/snippets/scene/table/concat-fields.snippet.ts +60 -0
  320. package/src/runjs-context/snippets/scene/table/destroy-selected.snippet.ts +36 -0
  321. package/src/runjs-context/snippets/scene/table/export-selected-json.snippet.ts +45 -0
  322. package/src/runjs-context/snippets/scene/{actions → table}/iterate-selected-rows.snippet.ts +14 -2
  323. package/src/runjs-context/snippets/types.ts +5 -1
  324. package/src/types.ts +34 -0
  325. package/src/utils/__tests__/jsxTransform.test.ts +38 -0
  326. package/src/utils/__tests__/safeGlobals.test.ts +22 -1
  327. package/src/utils/buildSettingsViewInputArgs.ts +72 -0
  328. package/src/utils/createEphemeralContext.ts +142 -0
  329. package/src/utils/index.ts +2 -2
  330. package/src/utils/jsxTransform.ts +39 -0
  331. package/src/utils/params-resolvers.ts +2 -2
  332. package/src/utils/safeGlobals.ts +49 -3
  333. package/src/utils/schema-utils.ts +1 -1
  334. package/src/utils/serverContextParams.ts +1 -0
  335. package/src/utils/variablesParams.ts +50 -38
  336. package/src/views/PageComponent.tsx +1 -1
  337. package/src/views/createViewMeta.ts +393 -70
  338. package/src/views/index.tsx +1 -0
  339. package/src/views/useDialog.tsx +12 -10
  340. package/src/views/useDrawer.tsx +60 -36
  341. package/src/views/usePage.tsx +13 -10
  342. package/lib/components/dnd/getMousePositionOnElement.d.ts +0 -50
  343. package/lib/components/dnd/getMousePositionOnElement.js +0 -95
  344. package/lib/components/dnd/moveBlock.d.ts +0 -33
  345. package/lib/components/dnd/moveBlock.js +0 -302
  346. package/lib/runjs-context/contexts/FlowRunJSContext.d.ts +0 -38
  347. package/lib/runjs-context/contexts/FlowRunJSContext.js +0 -217
  348. package/lib/runjs-context/contexts/LinkageRunJSContext.js +0 -62
  349. package/lib/runjs-context/index.d.ts +0 -19
  350. package/lib/runjs-context/index.js +0 -57
  351. package/lib/runjs-context/snippets/global/api-request-get.snippet.d.ts +0 -16
  352. package/lib/runjs-context/snippets/global/api-request-get.snippet.js +0 -42
  353. package/lib/runjs-context/snippets/global/api-request-post.snippet.d.ts +0 -16
  354. package/lib/runjs-context/snippets/global/api-request-post.snippet.js +0 -42
  355. package/lib/runjs-context/snippets/global/console-log-ctx.snippet.d.ts +0 -16
  356. package/lib/runjs-context/snippets/global/console-log-ctx.snippet.js +0 -41
  357. package/lib/runjs-context/snippets/global/sleep.snippet.d.ts +0 -16
  358. package/lib/runjs-context/snippets/global/sleep.snippet.js +0 -43
  359. package/lib/runjs-context/snippets/global/try-catch-async.snippet.d.ts +0 -16
  360. package/lib/runjs-context/snippets/global/try-catch-async.snippet.js +0 -44
  361. package/lib/runjs-context/snippets/libs/echarts-init.snippet.d.ts +0 -15
  362. package/lib/runjs-context/snippets/scene/actions/collection-selected-count.snippet.d.ts +0 -15
  363. package/lib/runjs-context/snippets/scene/actions/iterate-selected-rows.snippet.d.ts +0 -15
  364. package/lib/runjs-context/snippets/scene/actions/record-id-message.snippet.d.ts +0 -15
  365. package/lib/runjs-context/snippets/scene/actions/record-id-message.snippet.js +0 -43
  366. package/lib/runjs-context/snippets/scene/actions/run-action-basic.snippet.d.ts +0 -15
  367. package/lib/runjs-context/snippets/scene/actions/run-action-basic.snippet.js +0 -40
  368. package/lib/runjs-context/snippets/scene/jsblock/add-event-listener.snippet.d.ts +0 -15
  369. package/lib/runjs-context/snippets/scene/jsblock/append-style.snippet.d.ts +0 -15
  370. package/lib/runjs-context/snippets/scene/jsblock/append-style.snippet.js +0 -42
  371. package/lib/runjs-context/snippets/scene/jsblock/jsx-mount.snippet.d.ts +0 -15
  372. package/lib/runjs-context/snippets/scene/jsblock/jsx-unmount.snippet.d.ts +0 -15
  373. package/lib/runjs-context/snippets/scene/jsblock/jsx-unmount.snippet.js +0 -41
  374. package/lib/runjs-context/snippets/scene/jsblock/render-basic.snippet.d.ts +0 -15
  375. package/lib/runjs-context/snippets/scene/jsblock/render-basic.snippet.js +0 -41
  376. package/lib/runjs-context/snippets/scene/jsblock/render-button-handler.snippet.d.ts +0 -15
  377. package/lib/runjs-context/snippets/scene/jsblock/render-react.snippet.d.ts +0 -15
  378. package/lib/runjs-context/snippets/scene/jsfield/color-by-value.snippet.d.ts +0 -15
  379. package/lib/runjs-context/snippets/scene/jsfield/format-number.snippet.d.ts +0 -15
  380. package/lib/runjs-context/snippets/scene/jsfield/innerHTML-value.snippet.d.ts +0 -15
  381. package/lib/runjs-context/snippets/scene/jsitem/render-basic.snippet.d.ts +0 -15
  382. package/lib/runjs-context/snippets/scene/linkage/set-disabled.snippet.d.ts +0 -15
  383. package/lib/runjs-context/snippets/scene/linkage/set-field-value.snippet.d.ts +0 -15
  384. package/lib/runjs-context/snippets/scene/linkage/set-required.snippet.d.ts +0 -15
  385. package/lib/runjs-context/snippets/scene/linkage/toggle-visible.snippet.d.ts +0 -15
  386. package/src/components/dnd/getMousePositionOnElement.ts +0 -115
  387. package/src/components/dnd/moveBlock.ts +0 -379
  388. package/src/runjs-context/contexts/FlowRunJSContext.ts +0 -190
  389. package/src/runjs-context/contexts/LinkageRunJSContext.ts +0 -35
  390. package/src/runjs-context/index.ts +0 -20
  391. package/src/runjs-context/snippets/global/api-request-get.snippet.ts +0 -20
  392. package/src/runjs-context/snippets/global/api-request-post.snippet.ts +0 -20
  393. package/src/runjs-context/snippets/global/console-log-ctx.snippet.ts +0 -19
  394. package/src/runjs-context/snippets/global/copy-record-json.snippet.ts +0 -21
  395. package/src/runjs-context/snippets/global/copy-to-clipboard.snippet.ts +0 -21
  396. package/src/runjs-context/snippets/global/log-json-record.snippet.ts +0 -21
  397. package/src/runjs-context/snippets/global/requireAsync.snippet.ts +0 -24
  398. package/src/runjs-context/snippets/global/sleep.snippet.ts +0 -21
  399. package/src/runjs-context/snippets/global/try-catch-async.snippet.ts +0 -22
  400. package/src/runjs-context/snippets/global/view-navigation-push.snippet.ts +0 -23
  401. package/src/runjs-context/snippets/libs/echarts-init.snippet.ts +0 -24
  402. package/src/runjs-context/snippets/scene/actions/record-id-message.snippet.ts +0 -21
  403. package/src/runjs-context/snippets/scene/actions/run-action-basic.snippet.ts +0 -18
  404. package/src/runjs-context/snippets/scene/jsblock/append-style.snippet.ts +0 -20
  405. package/src/runjs-context/snippets/scene/jsblock/jsx-mount.snippet.ts +0 -24
  406. package/src/runjs-context/snippets/scene/jsblock/jsx-unmount.snippet.ts +0 -19
  407. package/src/runjs-context/snippets/scene/jsblock/render-basic.snippet.ts +0 -24
  408. package/src/runjs-context/snippets/scene/jsblock/render-button-handler.snippet.ts +0 -24
  409. package/src/runjs-context/snippets/scene/jsblock/render-card.snippet.ts +0 -30
  410. package/src/runjs-context/snippets/scene/jsblock/render-react.snippet.ts +0 -34
  411. package/src/runjs-context/snippets/scene/jsfield/color-by-value.snippet.ts +0 -20
  412. package/src/runjs-context/snippets/scene/jsfield/format-number.snippet.ts +0 -19
  413. package/src/runjs-context/snippets/scene/jsfield/innerHTML-value.snippet.ts +0 -18
  414. /package/lib/runjs-context/snippets/global/{copy-record-json.snippet.d.ts → api-request.snippet.d.ts} +0 -0
  415. /package/lib/runjs-context/snippets/global/{copy-to-clipboard.snippet.d.ts → clipboard-copy-text.snippet.d.ts} +0 -0
  416. /package/lib/runjs-context/snippets/global/{log-json-record.snippet.d.ts → import-esm.snippet.d.ts} +0 -0
  417. /package/lib/runjs-context/snippets/global/{view-navigation-push.snippet.d.ts → query-selector.snippet.d.ts} +0 -0
  418. /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
  });
@@ -662,8 +661,8 @@ describe('ForkFlowModel', () => {
662
661
  });
663
662
 
664
663
  test('should find and remove correct fork from cache', () => {
665
- const fork1 = new ForkFlowModel(mockMaster, {}, 1);
666
- const fork2 = new ForkFlowModel(mockMaster, {}, 2);
664
+ const fork1 = new ForkFlowModel(mockMaster, {}, '1');
665
+ const fork2 = new ForkFlowModel(mockMaster, {}, '2');
667
666
 
668
667
  (mockMaster as any).forkCache.set('key1', fork1);
669
668
  (mockMaster as any).forkCache.set('key2', fork2);
@@ -673,6 +672,22 @@ describe('ForkFlowModel', () => {
673
672
  expect((mockMaster as any).forkCache.has('key1')).toBe(false);
674
673
  expect((mockMaster as any).forkCache.has('key2')).toBe(true);
675
674
  });
675
+
676
+ test('forkIds must be unique', () => {
677
+ // 创建第一个 fork
678
+ const fork1 = mockMaster.createFork({}, uid());
679
+ const forkId1 = fork1.forkId;
680
+ expect(forkId1).toBeDefined();
681
+ // 创建第二个 fork
682
+ const fork2 = mockMaster.createFork({}, uid());
683
+ expect(fork2.forkId).not.toBe(forkId1);
684
+ // 销毁第一个 fork
685
+ fork1.dispose();
686
+ // 创建第三个 fork
687
+ const fork3 = mockMaster.createFork({}, uid());
688
+ expect(fork1['disposed']).toBe(true);
689
+ expect(fork3.forkId).not.toBe(fork2.forkId);
690
+ });
676
691
  });
677
692
 
678
693
  // ==================== FUNCTION BINDING AND CONTEXT ====================
@@ -50,7 +50,7 @@ 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
55
 
56
56
  // 使用 WeakMap 为每个类缓存一个 ModelActionRegistry 实例
@@ -89,6 +89,7 @@ export class FlowModel<Structure extends DefaultStructure = DefaultStructure> {
89
89
  private _options: FlowModelOptions<Structure>;
90
90
  protected _title: string;
91
91
  public isNew = false; // 标记是否为新建状态
92
+ public skeleton = null;
92
93
 
93
94
  /**
94
95
  * 所有 fork 实例的引用集合。
@@ -103,9 +104,9 @@ export class FlowModel<Structure extends DefaultStructure = DefaultStructure> {
103
104
  private forkCache: Map<string, ForkFlowModel<any>> = new Map();
104
105
 
105
106
  /**
106
- * 上一次 applyAutoFlows 的执行参数
107
+ * 上一次 beforeRender 的执行参数
107
108
  */
108
- private _lastAutoRunParams: any[] | null = null;
109
+ private _lastAutoRunParams: [Record<string, any> | undefined, boolean?] | null = null;
109
110
  protected observerDispose: () => void;
110
111
  #flowContext: FlowModelContext;
111
112
 
@@ -176,7 +177,7 @@ export class FlowModel<Structure extends DefaultStructure = DefaultStructure> {
176
177
  }
177
178
 
178
179
  if (this.flowEngine) {
179
- this.invalidateAutoFlowCache();
180
+ this.invalidateFlowCache('beforeRender');
180
181
  }
181
182
  this._rerunLastAutoRun();
182
183
  this.forks.forEach((fork) => {
@@ -387,13 +388,63 @@ export class FlowModel<Structure extends DefaultStructure = DefaultStructure> {
387
388
  });
388
389
  }
389
390
 
390
- public invalidateAutoFlowCache(deep = false) {
391
+ /**
392
+ * 失效指定事件的流程缓存;未指定 eventName 时,失效当前模型全部事件缓存。
393
+ * - 默认 beforeRender 与其它事件共享同一缓存体系:prefix=`event:${scope}`,flowKey=`eventName`,uid=`model.uid`
394
+ */
395
+ public invalidateFlowCache(eventName?: string, deep = false) {
391
396
  if (this.flowEngine) {
392
- const cacheKey = FlowEngine.generateApplyFlowCacheKey('autoFlow', 'all', this.uid);
393
- this.flowEngine.applyFlowCache.delete(cacheKey);
397
+ const scope = `event:${this.getFlowCacheScope(eventName || 'beforeRender')}`;
398
+ const cache = this.flowEngine.applyFlowCache;
399
+
400
+ if (eventName) {
401
+ // 删除该事件名下所有缓存(忽略不同 inputArgs 的散列差异)
402
+ const altScope = scope.replace(/:/g, '-');
403
+ const uidSuffixes = [`:${this.uid}`, `-${this.uid}`];
404
+ const eventSegments = [`:${eventName}:`, `-${eventName}-`];
405
+ for (const key of cache.keys()) {
406
+ const startMatches = key.startsWith(scope) || key.startsWith(altScope);
407
+ const endMatches = uidSuffixes.some((s) => key.endsWith(s));
408
+ const eventMatches = eventSegments.some((seg) => key.includes(seg));
409
+ if (startMatches && endMatches && eventMatches) {
410
+ cache.delete(key);
411
+ }
412
+ }
413
+ } else {
414
+ // 粗粒度:扫描并删除当前模型 uid 相关的事件缓存(任意事件)
415
+ const altScope = `${scope}:`.replace(/:/g, '-');
416
+ const prefixes = [`${scope}:`, altScope];
417
+ const uidSuffixes = [`:${this.uid}`, `-${this.uid}`];
418
+ for (const key of cache.keys()) {
419
+ const startMatches = prefixes.some((p) => key.startsWith(p));
420
+ const endMatches = uidSuffixes.some((s) => key.endsWith(s));
421
+ if (startMatches && endMatches) cache.delete(key);
422
+ }
423
+ }
424
+
425
+ // 同步失效所有 fork 的缓存
394
426
  this.forks.forEach((fork) => {
395
- const forkCacheKey = FlowEngine.generateApplyFlowCacheKey(`${fork['forkId']}`, 'all', this.uid);
396
- this.flowEngine.applyFlowCache.delete(forkCacheKey);
427
+ const forkScope = `event:${
428
+ (fork as any).getFlowCacheScope?.(eventName || 'beforeRender') ?? String((fork as any)['forkId'])
429
+ }`;
430
+ const altForkScope = forkScope.replace(/:/g, '-');
431
+ const uidSuffixes = [`:${this.uid}`, `-${this.uid}`];
432
+ if (eventName) {
433
+ const eventSegments = [`:${eventName}:`, `-${eventName}-`];
434
+ for (const key of this.flowEngine.applyFlowCache.keys()) {
435
+ const startMatches = key.startsWith(forkScope) || key.startsWith(altForkScope);
436
+ const endMatches = uidSuffixes.some((s) => key.endsWith(s));
437
+ const eventMatches = eventSegments.some((seg) => key.includes(seg));
438
+ if (startMatches && endMatches && eventMatches) this.flowEngine.applyFlowCache.delete(key);
439
+ }
440
+ } else {
441
+ const prefixes = [`${forkScope}:`, `${altForkScope}-`];
442
+ for (const key of this.flowEngine.applyFlowCache.keys()) {
443
+ const startMatches = prefixes.some((p) => key.startsWith(p));
444
+ const endMatches = uidSuffixes.some((s) => key.endsWith(s));
445
+ if (startMatches && endMatches) this.flowEngine.applyFlowCache.delete(key);
446
+ }
447
+ }
397
448
  });
398
449
  }
399
450
  if (deep) {
@@ -402,10 +453,10 @@ export class FlowModel<Structure extends DefaultStructure = DefaultStructure> {
402
453
  const subModelValue = this.subModels[subModelKey];
403
454
  if (Array.isArray(subModelValue)) {
404
455
  for (const subModel of subModelValue) {
405
- subModel.invalidateAutoFlowCache(deep);
456
+ subModel.invalidateFlowCache(eventName, deep);
406
457
  }
407
458
  } else if (subModelValue instanceof FlowModel) {
408
- subModelValue.invalidateAutoFlowCache(deep);
459
+ subModelValue.invalidateFlowCache(eventName, deep);
409
460
  }
410
461
  }
411
462
  }
@@ -637,7 +688,11 @@ export class FlowModel<Structure extends DefaultStructure = DefaultStructure> {
637
688
  return currentFlowEngine.executor.runFlow(target, flowKey, inputArgs, runId);
638
689
  }
639
690
 
640
- private async _dispatchEvent(eventName: string, inputArgs?: Record<string, any>): Promise<void> {
691
+ private async _dispatchEvent(
692
+ eventName: string,
693
+ inputArgs?: Record<string, any>,
694
+ options?: DispatchEventOptions,
695
+ ): Promise<any[]> {
641
696
  const currentFlowEngine = this.flowEngine;
642
697
  if (!currentFlowEngine) {
643
698
  console.warn('FlowEngine not available on this model for dispatchEvent. Please set flowEngine on the model.');
@@ -650,64 +705,73 @@ export class FlowModel<Structure extends DefaultStructure = DefaultStructure> {
650
705
  this.cleanRun
651
706
  }, targetIsFork=${(target as any)?.isFork === true}`,
652
707
  );
653
- await currentFlowEngine.executor.dispatchEvent(target, eventName, inputArgs);
708
+ return await currentFlowEngine.executor.dispatchEvent(target, eventName, inputArgs, options);
654
709
  }
655
710
 
656
- private _dispatchEventWithDebounce = _.debounce(async (eventName: string, inputArgs?: Record<string, any>) => {
657
- return this._dispatchEvent(eventName, inputArgs);
658
- }, 100);
711
+ private _dispatchEventWithDebounce = _.debounce(
712
+ async (eventName: string, inputArgs?: Record<string, any>, options?: DispatchEventOptions) => {
713
+ return this._dispatchEvent(eventName, inputArgs, options);
714
+ },
715
+ 100,
716
+ );
659
717
 
660
718
  async dispatchEvent(
661
719
  eventName: string,
662
720
  inputArgs?: Record<string, any>,
663
721
  options?: {
664
- /**
665
- * 是否要开启防抖功能
666
- */
667
- debounce: boolean;
668
- },
669
- ): Promise<void> {
670
- if (options?.debounce) {
671
- return this._dispatchEventWithDebounce(eventName, inputArgs);
722
+ /** 是否要开启防抖功能 */
723
+ debounce?: boolean;
724
+ } & DispatchEventOptions,
725
+ ): Promise<any[]> {
726
+ const isBeforeRender = eventName === 'beforeRender';
727
+ // 缺省值由模型层提供:beforeRender 默认顺序执行 + 使用缓存;可被 options 覆盖
728
+ const defaults = isBeforeRender ? { sequential: true, useCache: true } : {};
729
+ const execOptions = {
730
+ sequential: options?.sequential ?? (defaults as any).sequential,
731
+ useCache: options?.useCache ?? (defaults as any).useCache,
732
+ } as DispatchEventOptions;
733
+
734
+ // 记录最近一次 beforeRender 的入参与选项,便于 stepParams 变化时触发重跑
735
+ if (isBeforeRender) {
736
+ this._lastAutoRunParams = [inputArgs, execOptions.useCache];
672
737
  }
673
738
 
674
- return this._dispatchEvent(eventName, inputArgs);
739
+ if (options?.debounce) {
740
+ return this._dispatchEventWithDebounce(eventName, inputArgs, execOptions);
741
+ }
742
+ return this._dispatchEvent(eventName, inputArgs, execOptions);
675
743
  }
676
744
 
677
745
  /**
678
- * 获取所有自动应用流程定义(保持 getFlows 的顺序,即按 sort 排序)
679
- * @returns {FlowDefinition[]} 自动应用流程定义数组(已按 sort 排序)
746
+ * 按事件名获取对应的流程集合(保持 getFlows 的顺序,即按 sort 排序)。
747
+ * - beforeRender 兼容:除显式 on: 'beforeRender' 外,包含未声明 on 且 manual !== true 的流程。
680
748
  */
681
- public getAutoFlows(): FlowDefinition[] {
749
+ public getEventFlows(eventName: string): FlowDefinition[] {
682
750
  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;
751
+ const beforeRender = eventName === 'beforeRender';
752
+ const isMatch = (flow: FlowDefinition) => {
753
+ if (beforeRender) {
754
+ if (flow.manual === true) return false;
755
+ if (!flow.on) return true;
756
+ return typeof flow.on === 'string' ? flow.on === 'beforeRender' : flow.on?.eventName === 'beforeRender';
694
757
  }
695
- // 其他情况默认自动执行
696
- return true;
697
- });
698
-
699
- return autoFlows;
758
+ const on = flow.on;
759
+ if (!on) return false;
760
+ return typeof on === 'string' ? on === eventName : on?.eventName === eventName;
761
+ };
762
+ return Array.from(allFlows.values()).filter(isMatch);
700
763
  }
701
764
 
702
765
  /**
703
- * 重新执行上一次的 applyAutoFlows,保持参数一致
766
+ * 重新执行上一次的 beforeRender,保持参数一致
704
767
  * 如果之前没有执行过,则直接跳过
705
768
  * 使用 lodash debounce 避免频繁调用
706
769
  */
707
770
  private _rerunLastAutoRun = _.debounce(async () => {
708
771
  if (this._lastAutoRunParams) {
709
772
  try {
710
- await this.applyAutoFlows(...this._lastAutoRunParams);
773
+ const [inputArgs] = this._lastAutoRunParams as any[];
774
+ await this.dispatchEvent('beforeRender', inputArgs);
711
775
  } catch (error) {
712
776
  console.error('FlowModel._rerunLastAutoRun: Error during rerun:', error);
713
777
  }
@@ -715,86 +779,39 @@ export class FlowModel<Structure extends DefaultStructure = DefaultStructure> {
715
779
  }, 100);
716
780
 
717
781
  /**
718
- * 自动流程执行前钩子。
719
- * 子类可覆盖;可抛出 FlowExitException 提前终止。
782
+ * 通用事件分发钩子:开始
783
+ * 子类可覆盖;beforeRender 事件可通过抛出 FlowExitException 提前终止。
720
784
  */
721
- public async onBeforeAutoFlows(inputArgs?: Record<string, any>): Promise<void> {}
785
+ public async onDispatchEventStart(
786
+ eventName: string,
787
+ options?: DispatchEventOptions,
788
+ inputArgs?: Record<string, any>,
789
+ ): Promise<void> {}
722
790
 
723
791
  /**
724
- * 自动流程执行后钩子。
792
+ * 通用事件分发钩子:结束
725
793
  * 子类可覆盖。
726
794
  */
727
- public async onAfterAutoFlows(results: any[], inputArgs?: Record<string, any>): Promise<void> {}
795
+ public async onDispatchEventEnd(
796
+ eventName: string,
797
+ options?: DispatchEventOptions,
798
+ inputArgs?: Record<string, any>,
799
+ results?: any[],
800
+ ): Promise<void> {}
728
801
 
729
802
  /**
730
- * 自动流程错误钩子。
803
+ * 通用事件分发钩子:错误
731
804
  * 子类可覆盖。
732
805
  */
733
- public async onAutoFlowsError(error: Error, inputArgs?: Record<string, any>): Promise<void> {}
806
+ public async onDispatchEventError(
807
+ eventName: string,
808
+ options?: DispatchEventOptions,
809
+ inputArgs?: Record<string, any>,
810
+ error?: Error,
811
+ ): Promise<void> {}
734
812
 
735
813
  useHooksBeforeRender() {}
736
814
 
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
815
  /**
799
816
  * 智能检测是否应该跳过响应式包装
800
817
  * 说明:
@@ -891,6 +908,10 @@ export class FlowModel<Structure extends DefaultStructure = DefaultStructure> {
891
908
  return modelInstance.renderHiddenInConfig?.();
892
909
  }
893
910
 
911
+ // 订阅 stepParams 变化,以便当步骤参数(如 JS 代码等)更新时触发一次 React 渲染,
912
+ // 从而让 useHooksBeforeRender 中的副作用得以感知并执行(如 applyFlow('jsSettings'))。
913
+ modelInstance.stepParams;
914
+
894
915
  // 调用原始渲染方法
895
916
  return originalRender.call(renderTarget);
896
917
  });
@@ -962,14 +983,14 @@ export class FlowModel<Structure extends DefaultStructure = DefaultStructure> {
962
983
  }
963
984
 
964
985
  async rerender() {
965
- await this.applyAutoFlows(this._lastAutoRunParams?.[0], false);
986
+ await this.dispatchEvent('beforeRender', this._lastAutoRunParams?.[0], { useCache: false });
966
987
  }
967
988
 
968
989
  /**
969
- * 自动流程缓存的作用域标识;fork 实例可覆盖以区分缓存。
990
+ * 事件缓存的作用域标识;可按事件区分(默认与事件无关的 scope 返回 'default')。
970
991
  */
971
- public getAutoFlowCacheScope(): string {
972
- return 'autoFlow';
992
+ public getFlowCacheScope(eventName: string): string {
993
+ return String(eventName);
973
994
  }
974
995
 
975
996
  setParent(parent: FlowModel): void {
@@ -1128,14 +1149,17 @@ export class FlowModel<Structure extends DefaultStructure = DefaultStructure> {
1128
1149
  return this.flowEngine.createModel(options);
1129
1150
  }
1130
1151
 
1131
- async applySubModelsAutoFlows<K extends keyof Structure['subModels']>(
1152
+ /**
1153
+ * 对指定子模型派发 beforeRender 事件(顺序执行并使用缓存)。
1154
+ */
1155
+ async applySubModelsBeforeRenderFlows<K extends keyof Structure['subModels']>(
1132
1156
  subKey: K,
1133
1157
  inputArgs?: Record<string, any>,
1134
1158
  shared?: Record<string, any>,
1135
1159
  ) {
1136
1160
  await Promise.all(
1137
1161
  this.mapSubModels(subKey, async (sub) => {
1138
- await sub.applyAutoFlows(inputArgs);
1162
+ await sub.dispatchEvent('beforeRender', inputArgs);
1139
1163
  }),
1140
1164
  );
1141
1165
  }
@@ -1162,7 +1186,7 @@ export class FlowModel<Structure extends DefaultStructure = DefaultStructure> {
1162
1186
  }
1163
1187
 
1164
1188
  // 创建新的 fork 实例
1165
- const forkId = this.forks.size; // 当前集合大小作为索引
1189
+ const forkId = uid(); // 当前集合大小作为索引
1166
1190
  const fork = new ForkFlowModel<this>(this as any, localProps, forkId);
1167
1191
  if (options?.register !== false) {
1168
1192
  this.forks.add(fork as any);
@@ -1209,7 +1233,7 @@ export class FlowModel<Structure extends DefaultStructure = DefaultStructure> {
1209
1233
  throw new Error('FlowEngine is not set on this model. Please set flowEngine before saving.');
1210
1234
  }
1211
1235
  this.observerDispose();
1212
- this.invalidateAutoFlowCache(true);
1236
+ this.invalidateFlowCache('beforeRender', true);
1213
1237
  return this.flowEngine.removeModel(this.uid);
1214
1238
  }
1215
1239
 
@@ -1229,7 +1253,7 @@ export class FlowModel<Structure extends DefaultStructure = DefaultStructure> {
1229
1253
  throw new Error('FlowEngine is not set on this model. Please set flowEngine before deleting.');
1230
1254
  }
1231
1255
  this.observerDispose();
1232
- this.invalidateAutoFlowCache(true);
1256
+ this.invalidateFlowCache('beforeRender', true);
1233
1257
  // 从 FlowEngine 中销毁模型
1234
1258
  return this.flowEngine.destroyModel(this.uid);
1235
1259
  }
@@ -1307,6 +1331,7 @@ export class FlowModel<Structure extends DefaultStructure = DefaultStructure> {
1307
1331
  ..._.omit(this._options, ['flowEngine']),
1308
1332
  stepParams: this.stepParams,
1309
1333
  sortIndex: this.sortIndex,
1334
+ flowRegistry: {},
1310
1335
  };
1311
1336
  const subModels = this.subModels as {
1312
1337
  [key: string]: FlowModel | FlowModel[];
@@ -1323,8 +1348,7 @@ export class FlowModel<Structure extends DefaultStructure = DefaultStructure> {
1323
1348
  }
1324
1349
  }
1325
1350
  for (const [key, flow] of this.flowRegistry.getFlows()) {
1326
- data['flowRegistry'] = data['flowRegistry'] || {};
1327
- data['flowRegistry'][key] = flow.toData();
1351
+ data.flowRegistry[key] = flow.toData();
1328
1352
  }
1329
1353
  return data;
1330
1354
  }
@@ -12,6 +12,7 @@ import { FlowForkModelContext, FlowModelContext } from '../flowContext';
12
12
  import type { IModelComponentProps } from '../types';
13
13
  import { FlowModel } from './flowModel';
14
14
  import { FlowEngine } from '../flowEngine';
15
+ import { uid } from 'uid/secure';
15
16
 
16
17
  /**
17
18
  * ForkFlowModel 作为 FlowModel 的独立实例:
@@ -38,7 +39,7 @@ export class ForkFlowModel<TMaster extends FlowModel = FlowModel> {
38
39
  private disposed = false;
39
40
 
40
41
  /** fork 在 master.forks 中的索引 */
41
- public readonly forkId: number;
42
+ public readonly forkId: string;
42
43
 
43
44
  /** 需要与 master 共享的属性列表 */
44
45
  private static readonly SHARED_PROPERTIES = ['stepParams', 'sortIndex'];
@@ -67,12 +68,12 @@ export class ForkFlowModel<TMaster extends FlowModel = FlowModel> {
67
68
  // 不需要定义自己的属性了,现在是SHARED_PROPERTIES中指定的少数几个属性,所有属性设置时会自动添加自己的fork内的独有属性
68
69
  #flowContext: FlowModelContext;
69
70
 
70
- constructor(master: TMaster, initialProps: IModelComponentProps = {}, forkId = 0) {
71
+ constructor(master: TMaster, initialProps: IModelComponentProps = {}, forkId?: string) {
71
72
  void this.localProperties; // 避免 IDE 提示 unused
72
73
  this.master = master;
73
74
  this.uid = master.uid;
74
75
  this.localProps = { ...initialProps };
75
- this.forkId = forkId;
76
+ this.forkId = forkId || uid();
76
77
  this.hidden = this.master.hidden;
77
78
 
78
79
  define(this, {
@@ -224,10 +225,10 @@ export class ForkFlowModel<TMaster extends FlowModel = FlowModel> {
224
225
  }
225
226
 
226
227
  /**
227
- * 自动流程缓存的作用域标识(fork 专用)。
228
+ * 事件缓存的作用域标识(fork 专用)。
228
229
  */
229
- public getAutoFlowCacheScope(): string {
230
- return String(this.forkId);
230
+ public getFlowCacheScope(eventName: string): string {
231
+ return `${String(eventName)}:${String(this.forkId)}`;
231
232
  }
232
233
 
233
234
  // onUnmount() {
@@ -250,9 +251,41 @@ export class ForkFlowModel<TMaster extends FlowModel = FlowModel> {
250
251
  dispose() {
251
252
  if (this.disposed) return;
252
253
  this.disposed = true;
254
+ // 统一按事件缓存命名规则清理当前 fork 的所有缓存项(覆盖所有事件)
255
+ try {
256
+ const cache = this.flowEngine?.applyFlowCache;
257
+ if (cache && cache.size > 0) {
258
+ const uidSuffixes = [`:${this.uid}`, `-${this.uid}`];
259
+ const forkIdColon = `:${this.forkId}:`;
260
+ const forkIdHyphen = `-${this.forkId}-`;
261
+
262
+ for (const key of cache.keys()) {
263
+ // 事件缓存统一以 event: 或 event- 开头
264
+ const isEventCache = key.startsWith('event:') || key.startsWith('event-');
265
+ if (!isEventCache) continue;
266
+
267
+ // 仅删除当前 fork + 当前 uid 的键
268
+ const endMatches = uidSuffixes.some((s) => key.endsWith(s));
269
+ if (!endMatches) continue;
270
+
271
+ // 限定在去除 uid 后缀的范围内匹配 forkId 片段,避免误伤
272
+ let trimmed = key;
273
+ for (const suf of uidSuffixes) {
274
+ if (trimmed.endsWith(suf)) {
275
+ trimmed = trimmed.slice(0, -suf.length);
276
+ break;
277
+ }
278
+ }
279
+ if (trimmed.includes(forkIdColon) || trimmed.includes(forkIdHyphen)) {
280
+ cache.delete(key);
281
+ }
282
+ }
283
+ }
284
+ } catch {
285
+ // 忽略清理阶段异常,避免影响后续释放
286
+ }
287
+
253
288
  if (this.master && (this.master as any).forks) {
254
- const forkCacheKey = FlowEngine.generateApplyFlowCacheKey(`${this.forkId}`, 'all', this.uid);
255
- this.flowEngine.applyFlowCache.delete(forkCacheKey);
256
289
  (this.master as any).forks.delete(this as any);
257
290
  }
258
291
  // 从 master 的 forkCache 中移除自己
package/src/provider.tsx CHANGED
@@ -14,6 +14,7 @@ import { FlowContextProvider } from './FlowContextProvider';
14
14
  import { FlowEngine } from './flowEngine';
15
15
  import { useDialog, useDrawer, usePage, usePopover } from './views';
16
16
  import { FlowViewer } from './views/FlowView';
17
+ import { observer } from '@formily/reactive-react';
17
18
 
18
19
  interface FlowEngineProviderProps {
19
20
  engine: FlowEngine;
@@ -22,7 +23,7 @@ interface FlowEngineProviderProps {
22
23
 
23
24
  const FlowEngineReactContext = createContext<FlowEngine | null>(null);
24
25
 
25
- export const FlowEngineProvider: React.FC<FlowEngineProviderProps> = (props) => {
26
+ export const FlowEngineProvider: React.FC<FlowEngineProviderProps> = React.memo((props) => {
26
27
  const { engine, children } = props;
27
28
  if (!engine) {
28
29
  throw new Error('FlowEngineProvider must be supplied with an engine.');
@@ -32,7 +33,9 @@ export const FlowEngineProvider: React.FC<FlowEngineProviderProps> = (props) =>
32
33
  <FlowContextProvider context={engine.context}>{children}</FlowContextProvider>
33
34
  </FlowEngineReactContext.Provider>
34
35
  );
35
- };
36
+ });
37
+
38
+ FlowEngineProvider.displayName = 'FlowEngineProvider';
36
39
 
37
40
  export const FlowEngineGlobalsContextProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
38
41
  const { modal, message, notification } = App.useApp();
@@ -72,20 +75,20 @@ export const FlowEngineGlobalsContextProvider: React.FC<{ children: React.ReactN
72
75
  }, [engine, drawer, modal, message, notification, config, popover, token, dialog, embed]);
73
76
 
74
77
  return (
75
- <>
78
+ <ConfigProvider {...config} locale={engine.context.locales?.antd} popupMatchSelectWidth={false}>
76
79
  {children}
77
80
  {contextHolder as any}
78
81
  {popoverContextHolder as any}
79
82
  {pageContextHolder as any}
80
83
  {dialogContextHolder as any}
81
84
  {/* The modal context is provided by App.useApp() */}
82
- </>
85
+ </ConfigProvider>
83
86
  );
84
87
  };
85
-
86
- export const useFlowEngine = (): FlowEngine => {
88
+ // 不 throw Error 怎么处理?
89
+ export const useFlowEngine = ({ throwError = true } = {}): FlowEngine => {
87
90
  const context = useContext(FlowEngineReactContext);
88
- if (!context) {
91
+ if (!context && throwError) {
89
92
  // This error should ideally not be hit if FlowEngineProvider is used correctly at the root
90
93
  // and always supplied with an engine.
91
94
  throw new Error(
@@ -113,6 +113,7 @@ export class MultiRecordResource<TDataItem = any> extends BaseRecordResource<TDa
113
113
  async create(data: TDataItem, options?: AxiosRequestConfig): Promise<void> {
114
114
  const config = this.mergeRequestConfig({ data }, this.createActionOptions, options);
115
115
  await this.runAction('create', config);
116
+ this.emit('saved', data);
116
117
  await this.refresh();
117
118
  }
118
119
 
@@ -140,6 +141,7 @@ export class MultiRecordResource<TDataItem = any> extends BaseRecordResource<TDa
140
141
  options,
141
142
  );
142
143
  await this.runAction('update', config);
144
+ this.emit('saved', data);
143
145
  await this.refresh();
144
146
  }
145
147