@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
package/src/flowEngine.ts CHANGED
@@ -17,6 +17,9 @@ import { FlowSettings } from './flowSettings';
17
17
  import { ErrorFlowModel, FlowModel } from './models';
18
18
  import { ReactView } from './ReactView';
19
19
  import { APIResource, FlowResource, MultiRecordResource, SingleRecordResource, SQLResource } from './resources';
20
+ import { Emitter } from './emitter';
21
+ import ModelOperationScheduler from './scheduler/ModelOperationScheduler';
22
+ import type { ScheduleOptions, ScheduledCancel } from './scheduler/ModelOperationScheduler';
20
23
  import type {
21
24
  ActionDefinition,
22
25
  ApplyFlowCacheEntry,
@@ -114,6 +117,15 @@ export class FlowEngine {
114
117
 
115
118
  private _resources = new Map<string, typeof FlowResource>();
116
119
 
120
+ /**
121
+ * 引擎事件总线(目前用于模型生命周期等事件)。
122
+ * ViewScopedFlowEngine 持有自己的实例,实现作用域隔离。
123
+ */
124
+ public emitter: Emitter = new Emitter();
125
+
126
+ /** 调度器:仅在 View 作用域引擎本地启用;根/Block 作用域默认不持有 */
127
+ private _modelOperationScheduler?: ModelOperationScheduler;
128
+
117
129
  logger: pino.Logger;
118
130
 
119
131
  /**
@@ -130,7 +142,7 @@ export class FlowEngine {
130
142
  */
131
143
  public reactView: ReactView;
132
144
  /**
133
- * Flow executor that runs flows and auto-flows.
145
+ * Flow executor that runs event flows.
134
146
  */
135
147
  public executor: FlowExecutor;
136
148
 
@@ -165,6 +177,35 @@ export class FlowEngine {
165
177
  this.executor = new FlowExecutor(this);
166
178
  }
167
179
 
180
+ /** 获取/创建当前引擎的调度器(仅在本地作用域) */
181
+ public getScheduler(): ModelOperationScheduler {
182
+ if (!this._modelOperationScheduler) {
183
+ this._modelOperationScheduler = new ModelOperationScheduler(this);
184
+ }
185
+ return this._modelOperationScheduler;
186
+ }
187
+
188
+ /** 释放并清理当前引擎本地调度器(若存在) */
189
+ public disposeScheduler(): void {
190
+ if (this._modelOperationScheduler) {
191
+ try {
192
+ this._modelOperationScheduler.dispose();
193
+ } finally {
194
+ this._modelOperationScheduler = undefined;
195
+ }
196
+ }
197
+ }
198
+
199
+ /** 在目标模型生命周期达成时执行操作(仅在 View 引擎本地存储计划) */
200
+ public scheduleModelOperation(
201
+ fromModelOrUid: FlowModel | string,
202
+ toUid: string,
203
+ fn: (model: FlowModel) => Promise<void> | void,
204
+ options?: ScheduleOptions,
205
+ ): ScheduledCancel {
206
+ return this.getScheduler().schedule(fromModelOrUid, toUid, fn, options);
207
+ }
208
+
168
209
  /** 上一个引擎(根引擎为 undefined) */
169
210
  get previousEngine(): FlowEngine | undefined {
170
211
  return this._previousEngine;
@@ -447,6 +488,12 @@ export class FlowEngine {
447
488
 
448
489
  modelInstance.onInit(options);
449
490
 
491
+ // 发射 created 生命周期事件
492
+ void this.emitter.emitAsync('model:created', {
493
+ uid: modelInstance.uid,
494
+ model: modelInstance,
495
+ });
496
+
450
497
  // 在模型实例化阶段应用 flow 级 defaultParams(仅填充缺失的 stepParams,不覆盖)
451
498
  // 不阻塞创建流程:允许 defaultParams 为异步函数
452
499
  this._applyFlowDefinitionDefaultParams(modelInstance as FlowModel).catch((err) => {
@@ -555,16 +602,32 @@ export class FlowEngine {
555
602
  if (index !== -1) {
556
603
  subModelValue.splice(index, 1);
557
604
  modelInstance.parent.emitter.emit('onSubModelRemoved', modelInstance);
605
+ this.emitter?.emit('model:subModel:removed', {
606
+ parentUid: modelInstance.parent.uid,
607
+ parent: modelInstance.parent,
608
+ model: modelInstance,
609
+ });
558
610
  break;
559
611
  }
560
612
  } else if (subModelValue && subModelValue === modelInstance) {
561
613
  delete modelInstance.parent.subModels[subKey];
562
614
  modelInstance.parent.emitter.emit('onSubModelRemoved', modelInstance);
615
+ this.emitter?.emit('model:subModel:removed', {
616
+ parentUid: modelInstance.parent.uid,
617
+ parent: modelInstance.parent,
618
+ model: modelInstance,
619
+ });
563
620
  break;
564
621
  }
565
622
  }
566
623
  }
567
624
  this._modelInstances.delete(uid);
625
+
626
+ // 发射 destroyed 生命周期事件(在移除后,但携带实例便于调度器传递;严格模式:不吞错)
627
+ void this.emitter.emitAsync('model:destroyed', {
628
+ uid,
629
+ model: modelInstance,
630
+ });
568
631
  return true;
569
632
  }
570
633
 
@@ -734,6 +797,17 @@ export class FlowEngine {
734
797
  return this.removeModel(uid);
735
798
  }
736
799
 
800
+ /**
801
+ * Duplicate a model tree via repository API.
802
+ * Returns the duplicated model JSON (root with subModels) or null if not available.
803
+ * @param {string} uid UID of the model to duplicate
804
+ * @returns {Promise<any | null>} Duplicated model JSON or null
805
+ */
806
+ async duplicateModel(uid: string) {
807
+ if (!this.ensureModelRepository()) return null;
808
+ return this._modelRepository.duplicate(uid);
809
+ }
810
+
737
811
  /**
738
812
  * Replace a model instance with a new instance of a class.
739
813
  * @template T New model type
@@ -803,9 +877,15 @@ export class FlowEngine {
803
877
  // 7. 触发事件以通知其他部分模型已替换
804
878
  if (currentParent) {
805
879
  currentParent.emitter.setPaused(false);
806
- currentParent.parent.invalidateAutoFlowCache(true);
880
+ currentParent.parent.invalidateFlowCache('beforeRender', true);
807
881
  currentParent.parent?.rerender();
808
882
  currentParent.emitter.emit('onSubModelReplaced', { oldModel, newModel });
883
+ this.emitter?.emit('model:subModel:replaced', {
884
+ parentUid: currentParent.uid,
885
+ parent: currentParent,
886
+ oldModel,
887
+ newModel,
888
+ });
809
889
  }
810
890
  await newModel.save();
811
891
  return newModel;
@@ -837,7 +917,8 @@ export class FlowEngine {
837
917
  return false;
838
918
  }
839
919
 
840
- const findIndex = (model: FlowModel) => subModels.findIndex((item) => item.uid === model.uid);
920
+ const subModelsCopy = [...subModels];
921
+ const findIndex = (model: FlowModel) => subModelsCopy.findIndex((item) => item.uid === model.uid);
841
922
 
842
923
  const currentIndex = findIndex(sourceModel);
843
924
  const targetIndex = findIndex(targetModel);
@@ -853,14 +934,17 @@ export class FlowEngine {
853
934
  }
854
935
 
855
936
  // 使用splice直接移动数组元素(O(n)比排序O(n log n)更快)
856
- const [movedModel] = subModels.splice(currentIndex, 1);
857
- subModels.splice(targetIndex, 0, movedModel);
937
+ const [movedModel] = subModelsCopy.splice(currentIndex, 1);
938
+ subModelsCopy.splice(targetIndex, 0, movedModel);
858
939
 
859
940
  // 重新分配连续的sortIndex
860
- subModels.forEach((model, index) => {
941
+ subModelsCopy.forEach((model, index) => {
861
942
  model.sortIndex = index;
862
943
  });
863
944
 
945
+ // 更新父模型的subModels引用
946
+ sourceModel.parent.subModels[sourceModel.subKey] = subModelsCopy;
947
+
864
948
  return true;
865
949
  };
866
950
  move(sourceModel, targetModel);
@@ -870,6 +954,12 @@ export class FlowEngine {
870
954
  }
871
955
  // 触发事件以通知其他部分模型已移动
872
956
  sourceModel.parent.emitter.emit('onSubModelMoved', { source: sourceModel, target: targetModel });
957
+ this.emitter?.emit('model:subModel:moved', {
958
+ parentUid: sourceModel.parent?.uid,
959
+ parent: sourceModel.parent,
960
+ source: sourceModel,
961
+ target: targetModel,
962
+ });
873
963
  }
874
964
 
875
965
  /**
@@ -29,6 +29,7 @@ import {
29
29
  resolveStepUiSchema,
30
30
  resolveUiMode,
31
31
  setupRuntimeContextSteps,
32
+ buildSettingsViewInputArgs,
32
33
  } from './utils';
33
34
  import { FlowStepContext } from './hooks/useFlowStep';
34
35
 
@@ -205,8 +206,7 @@ export class FlowSettings {
205
206
  Upload,
206
207
  } = await import('@formily/antd-v5');
207
208
 
208
- // 单独导入 Button 组件
209
- const { Button } = await import('antd');
209
+ const { Button, Alert } = await import('antd');
210
210
 
211
211
  // 注册基础组件
212
212
  this.components.Form = Form;
@@ -254,6 +254,7 @@ export class FlowSettings {
254
254
  this.components.Space = Space;
255
255
  this.components.Editable = Editable;
256
256
  this.components.PreviewText = PreviewText;
257
+ this.components.Alert = Alert;
257
258
 
258
259
  // 注册按钮组件
259
260
  this.components.Button = Button;
@@ -464,12 +465,14 @@ export class FlowSettings {
464
465
  flowEngine,
465
466
  form,
466
467
  onFormValuesChange,
468
+ key,
467
469
  }: {
468
470
  uiSchema: any;
469
471
  initialValues: any;
470
472
  flowEngine: any;
471
473
  form?: any;
472
474
  onFormValuesChange?: (form: any) => void;
475
+ key?: string;
473
476
  }): React.ReactElement {
474
477
  // 获取 scopes 和 components
475
478
  const scopes = {
@@ -496,7 +499,7 @@ export class FlowSettings {
496
499
 
497
500
  return React.createElement(
498
501
  FormProviderWithForm,
499
- { form, initialValues, onFormValuesChange },
502
+ { form, initialValues, onFormValuesChange, key },
500
503
  React.createElement(SchemaField as any, {
501
504
  schema: compiledSchema,
502
505
  components: flowEngine?.flowSettings?.components || {},
@@ -601,7 +604,7 @@ export class FlowSettings {
601
604
  let actionDefaultParams: Record<string, any> = {};
602
605
  let uiMode;
603
606
  if (step.use) {
604
- const action = (model as any).flowEngine?.getAction?.(step.use);
607
+ const action = model.getAction?.(step.use);
605
608
  if (action) {
606
609
  actionDefaultParams = action.defaultParams || {};
607
610
  stepTitle = stepTitle || action.title;
@@ -615,6 +618,9 @@ export class FlowSettings {
615
618
  const flowRuntimeContext = new FlowRuntimeContext(model as any, fk, 'settings');
616
619
  setupRuntimeContextSteps(flowRuntimeContext as any, flow.steps, model as any, fk);
617
620
  flowRuntimeContext.defineProperty('currentStep', { value: step });
621
+ flowRuntimeContext.defineMethod('getStepFormValues', (flowKey: string, stepKey: string) => {
622
+ return forms.get(keyOf({ flowKey, stepKey }))?.values;
623
+ });
618
624
 
619
625
  // 解析默认值 + 当前参数
620
626
  const modelStepParams = (model as any).getStepParams(fk, sk) || {};
@@ -764,6 +770,8 @@ export class FlowSettings {
764
770
  zIndex: 5000,
765
771
  // 允许透传其它 props(如 maskClosable、footer 等),但确保 content 由我们接管
766
772
  ...modeProps,
773
+ // 统一构造 settings 弹窗的 inputArgs(集合/记录/父导航/关联)
774
+ inputArgs: buildSettingsViewInputArgs(model as any, (modeProps as any)?.inputArgs),
767
775
  content: (currentView, viewCtx) => {
768
776
  viewCtx?.defineMethod('getStepFormValues', (flowKey: string, stepKey: string) => {
769
777
  return forms.get(keyOf({ flowKey, stepKey }))?.values;
@@ -35,7 +35,9 @@ export function useApplyAutoFlows(
35
35
 
36
36
  const { loading, error } = useRequest(
37
37
  async () => {
38
- await model.applyAutoFlows(inputArgs);
38
+ if (!model) return;
39
+ // beforeRender 在模型层默认顺序执行并默认使用缓存(可覆盖)
40
+ await model.dispatchEvent('beforeRender', inputArgs);
39
41
  },
40
42
  {
41
43
  refreshDeps: [model, inputArgs],
package/src/index.ts CHANGED
@@ -12,6 +12,7 @@ export * from './types';
12
12
 
13
13
  // 工具函数
14
14
  export * from './utils';
15
+ export { compileRunJs } from './utils/jsxTransform';
15
16
 
16
17
  // 资源类
17
18
  export * from './resources';
@@ -31,8 +32,18 @@ export * from './ElementProxy';
31
32
  export * from './flowContext';
32
33
  export * from './FlowContextProvider';
33
34
  export * from './JSRunner';
34
- export * from './runjs-context';
35
+ export {
36
+ getRunJSDocFor,
37
+ createJSRunnerWithVersion,
38
+ getRunJSScenesForModel,
39
+ getRunJSScenesForContext,
40
+ } from './runjs-context/helpers';
41
+ export { RunJSContextRegistry, getModelClassName } from './runjs-context/registry';
42
+ export { setupRunJSContexts } from './runjs-context/setup';
43
+ export { getSnippetBody, listSnippetsForContext } from './runjs-context/snippets';
35
44
 
36
45
  export * from './views';
37
46
 
38
47
  export * from './FlowDefinition';
48
+ export { createViewScopedEngine } from './ViewScopedFlowEngine';
49
+ export { createBlockScopedEngine } from './BlockScopedFlowEngine';
@@ -23,6 +23,7 @@
23
23
  "UID copied to clipboard": "UID copied to clipboard",
24
24
  "Copy failed": "Copy failed",
25
25
  "Copy failed, please copy [{{uid}}] manually.": "Copy failed, please copy [{{uid}}] manually.",
26
+ "Copy failed under HTTP. Clipboard API is unavailable on non-HTTPS pages. Please copy [{{uid}}] manually.": "Copy failed under HTTP. Clipboard API is unavailable on non-HTTPS pages. Please copy [{{uid}}] manually.",
26
27
  "Confirm delete": "Confirm delete",
27
28
  "Are you sure you want to delete this item? This action cannot be undone.": "Are you sure you want to delete this item? This action cannot be undone.",
28
29
  "Delete operation failed": "Delete operation failed",
@@ -57,5 +58,6 @@
57
58
  "Name": "Name",
58
59
  "Model with ID {{uid}} not found": "Model with ID {{uid}} not found",
59
60
  "Common actions": "Common actions",
60
- "This variable is not available": "This variable is not available"
61
- }
61
+ "This variable is not available": "This variable is not available",
62
+ "Copy popup UID": "Copy popup UID"
63
+ }
@@ -23,6 +23,7 @@
23
23
  "UID copied to clipboard": "UID 已复制到剪贴板",
24
24
  "Copy failed": "复制失败",
25
25
  "Copy failed, please copy [{{uid}}] manually.": "复制失败,请手动复制 [{{uid}}]。",
26
+ "Copy failed under HTTP. Clipboard API is unavailable on non-HTTPS pages. Please copy [{{uid}}] manually.": "HTTP 环境下复制失败。非 HTTPS 页面不支持剪贴板 API,请手动复制 [{{uid}}]。",
26
27
  "Confirm delete": "确认删除",
27
28
  "Are you sure you want to delete this item? This action cannot be undone.": "确定要删除此项吗?此操作不可撤销。",
28
29
  "Delete operation failed": "删除操作失败",
@@ -57,5 +58,6 @@
57
58
  "Name": "名称",
58
59
  "Model with ID {{uid}} not found": "未找到 ID 为 {{uid}} 的模型",
59
60
  "Common actions": "通用操作",
60
- "This variable is not available": "此变量不可用"
61
- }
61
+ "This variable is not available": "此变量不可用",
62
+ "Copy popup UID": "复制弹窗 UID"
63
+ }
@@ -9,14 +9,17 @@
9
9
 
10
10
  import { Card, Form } from 'antd';
11
11
  import _ from 'lodash';
12
- import React from 'react';
12
+ import React, { useMemo } from 'react';
13
+ import { useTranslation } from 'react-i18next';
13
14
  import { CollectionField } from '../data-source';
14
15
  import { FlowEngineContext } from '../flowContext';
16
+ import { useFlowModel } from '../hooks';
15
17
  import { DefaultStructure } from '../types';
16
18
  import { escapeT } from '../utils';
17
19
  import { FlowModel } from './flowModel';
18
20
 
19
21
  export function FieldPlaceholder() {
22
+ const { t } = useTranslation();
20
23
  return (
21
24
  <Form.Item>
22
25
  <Card
@@ -27,12 +30,42 @@ export function FieldPlaceholder() {
27
30
  },
28
31
  }}
29
32
  >
30
- 该字段已被隐藏,你无法查看(该内容仅在激活 UI Editor 时显示)。
33
+ {t(
34
+ 'This field has been hidden and you cannot view it (this content is only visible when the UI Editor is activated).',
35
+ )}
31
36
  </Card>
32
37
  </Form.Item>
33
38
  );
34
39
  }
35
40
 
41
+ export function FieldDeletePlaceholder() {
42
+ const { t } = useTranslation();
43
+ const model: any = useFlowModel();
44
+ const blockModel = model.context.blockModel;
45
+ const dataSource = blockModel.collection.dataSource;
46
+ const collection = blockModel.collection;
47
+ const name = model.fieldPath;
48
+ const nameValue = useMemo(() => {
49
+ const dataSourcePrefix = `${t(dataSource.displayName || dataSource.key)} > `;
50
+ const collectionPrefix = collection ? `${t(collection.title) || collection.name || collection.tableName} > ` : '';
51
+ return `${dataSourcePrefix}${collectionPrefix}${name}`;
52
+ }, []);
53
+ return (
54
+ <Form.Item>
55
+ <div
56
+ style={{
57
+ color: 'rgba(0,0,0,0.45)',
58
+ }}
59
+ >
60
+ {t(`The {{type}} "{{name}}" may have been deleted. Please remove this {{blockType}}.`, {
61
+ type: t('Field'),
62
+ name: nameValue,
63
+ blockType: t('Field'),
64
+ }).replaceAll('&gt;', '>')}
65
+ </div>
66
+ </Form.Item>
67
+ );
68
+ }
36
69
  export interface FieldSettingsInitParams {
37
70
  dataSourceKey: string;
38
71
  collectionName: string;
@@ -51,8 +84,12 @@ const defaultWhen = () => true;
51
84
 
52
85
  export class CollectionFieldModel<T extends DefaultStructure = DefaultStructure> extends FlowModel<T> {
53
86
  private static _bindings = new Map();
87
+ fieldDeleted = false;
54
88
 
55
89
  renderHiddenInConfig(): React.ReactNode | undefined {
90
+ if (this.fieldDeleted) {
91
+ return <FieldDeletePlaceholder />;
92
+ }
56
93
  return <FieldPlaceholder />;
57
94
  }
58
95
 
@@ -76,12 +113,14 @@ export class CollectionFieldModel<T extends DefaultStructure = DefaultStructure>
76
113
  return this.fieldPath;
77
114
  },
78
115
  });
79
- this.context.blockModel.addAppends(this.fieldPath);
80
- this.context.blockModel.addAppends(this.associationPathName);
116
+ if (this.context.blockModel) {
117
+ this.context.blockModel.addAppends(this.fieldPath);
118
+ this.context.blockModel.addAppends(this.associationPathName);
119
+ }
81
120
  }
82
121
 
83
122
  getFieldSettingsInitParams(): FieldSettingsInitParams {
84
- return this.getStepParams('fieldSettings', 'init');
123
+ return this.getStepParams('fieldSettings', 'init') || {};
85
124
  }
86
125
 
87
126
  get fieldPath(): string {
@@ -103,6 +142,9 @@ export class CollectionFieldModel<T extends DefaultStructure = DefaultStructure>
103
142
  }
104
143
 
105
144
  static getBindingsByField(ctx: FlowEngineContext, collectionField: CollectionField): BindingOptions[] {
145
+ if (!collectionField) {
146
+ return;
147
+ }
106
148
  const interfaceName = collectionField.interface;
107
149
 
108
150
  // Check if the interface exists in the map
@@ -120,13 +162,23 @@ export class CollectionFieldModel<T extends DefaultStructure = DefaultStructure>
120
162
  static getDefaultBindingByField(
121
163
  ctx: FlowEngineContext,
122
164
  collectionField: CollectionField,
123
- options: { useStrict?: boolean; fallbackToTargetTitleField?: boolean } = {},
165
+ options: {
166
+ useStrict?: boolean;
167
+ fallbackToTargetTitleField?: boolean;
168
+ targetCollectionTitleField?: CollectionField;
169
+ } = {},
124
170
  ): BindingOptions | null {
125
171
  if (options.fallbackToTargetTitleField) {
126
172
  const binding = this.getDefaultBindingByField(ctx, collectionField, { useStrict: true });
127
173
  if (!binding) {
128
- if (collectionField.isAssociationField() && collectionField.targetCollectionTitleField) {
129
- return this.getDefaultBindingByField(ctx, collectionField.targetCollectionTitleField);
174
+ if (
175
+ (collectionField.isAssociationField() && options?.targetCollectionTitleField) ||
176
+ collectionField.targetCollectionTitleField
177
+ ) {
178
+ return this.getDefaultBindingByField(
179
+ ctx,
180
+ options?.targetCollectionTitleField || collectionField.targetCollectionTitleField,
181
+ );
130
182
  }
131
183
  }
132
184
  return binding;
@@ -0,0 +1,169 @@
1
+ /**
2
+ * This file is part of the NocoBase (R) project.
3
+ * Copyright (c) 2020-2024 NocoBase Co., Ltd.
4
+ * Authors: NocoBase Team.
5
+ *
6
+ * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
7
+ * For more information, please refer to: https://www.nocobase.com/agreement.
8
+ */
9
+
10
+ import { describe, test, expect } from 'vitest';
11
+ import { FlowEngine } from '../../flowEngine';
12
+ import { FlowModel } from '../../models/flowModel';
13
+
14
+ describe('dispatchEvent behavior (defaults, parallel, errors)', () => {
15
+ test('non-beforeRender defaults to sequential execution and respects getEventFlows order', async () => {
16
+ const engine = new FlowEngine();
17
+ class M extends FlowModel {}
18
+ engine.registerModels({ M });
19
+
20
+ const calls: string[] = [];
21
+
22
+ // Static flow with higher sort
23
+ M.registerFlow({
24
+ key: 'S',
25
+ on: { eventName: 'go' },
26
+ sort: 10,
27
+ steps: { s: { handler: async () => void calls.push('static') } as any },
28
+ });
29
+
30
+ const model = engine.createModel({ use: 'M' });
31
+
32
+ // Instance flows
33
+ model.registerFlow('I1', {
34
+ on: { eventName: 'go' },
35
+ sort: 0,
36
+ steps: { i1: { handler: async () => void calls.push('inst1') } as any },
37
+ });
38
+ model.registerFlow('I2', {
39
+ on: { eventName: 'go' },
40
+ sort: 5,
41
+ steps: { i2: { handler: async () => void calls.push('inst2') } as any },
42
+ });
43
+
44
+ // No options provided -> should default to sequential execution
45
+ await model.dispatchEvent('go');
46
+
47
+ // Expected order should match getEventFlows('go') order
48
+ const expected = model.getEventFlows('go').map((f) => f.key);
49
+ expect(calls).toEqual(expected.map((k) => (k === 'I1' ? 'inst1' : k === 'I2' ? 'inst2' : 'static')));
50
+ });
51
+
52
+ test('parallel mode (sequential=false) runs all and tolerates non-beforeRender errors', async () => {
53
+ const engine = new FlowEngine();
54
+ class M extends FlowModel {}
55
+ engine.registerModels({ M });
56
+
57
+ const calls: string[] = [];
58
+
59
+ M.registerFlow({
60
+ key: 'S',
61
+ on: { eventName: 'go' },
62
+ sort: 1,
63
+ steps: { s: { handler: async () => 'static-ok' } as any },
64
+ });
65
+
66
+ const model = engine.createModel({ use: 'M' });
67
+
68
+ model.registerFlow('I1', {
69
+ on: { eventName: 'go' },
70
+ sort: 0,
71
+ steps: { i1: { handler: async () => (calls.push('inst1'), 'i1-ok') } as any },
72
+ });
73
+ model.registerFlow('I2', {
74
+ on: { eventName: 'go' },
75
+ sort: 2,
76
+ steps: { i2: { handler: async () => (calls.push('inst2'), 'i2-ok') } as any },
77
+ });
78
+ model.registerFlow('ERR', {
79
+ on: { eventName: 'go' },
80
+ sort: 3,
81
+ steps: {
82
+ e: {
83
+ handler: async () => {
84
+ calls.push('err');
85
+ throw new Error('boom');
86
+ },
87
+ } as any,
88
+ },
89
+ });
90
+
91
+ const results = await model.dispatchEvent('go', undefined, { sequential: false });
92
+
93
+ // All handlers ran; order is not guaranteed in parallel mode
94
+ expect(new Set(calls)).toEqual(new Set(['inst1', 'inst2', 'err']));
95
+ // The error flow returns undefined and is filtered out; others return stepResults objects
96
+ // Expect one result object per successful flow with its step key
97
+ expect(Array.isArray(results)).toBe(true);
98
+ const keys = (results as any[]).flatMap((o) => Object.keys(o));
99
+ expect(new Set(keys)).toEqual(new Set(['i1', 'i2', 's']));
100
+ const byKey = Object.assign({}, ...(results as any[]));
101
+ expect(byKey['i1']).toBe('i1-ok');
102
+ expect(byKey['i2']).toBe('i2-ok');
103
+ expect(byKey['s']).toBe('static-ok');
104
+ });
105
+
106
+ test('sequential non-beforeRender: stops subsequent flows on error', async () => {
107
+ const engine = new FlowEngine();
108
+ class M extends FlowModel {}
109
+ engine.registerModels({ M });
110
+
111
+ const calls: string[] = [];
112
+ const model = engine.createModel({ use: 'M' });
113
+
114
+ model.registerFlow('I1', {
115
+ on: { eventName: 'go' },
116
+ sort: 0,
117
+ steps: { i1: { handler: async () => void calls.push('i1') } as any },
118
+ });
119
+ model.registerFlow('ERR', {
120
+ on: { eventName: 'go' },
121
+ sort: 1,
122
+ steps: {
123
+ e: {
124
+ handler: async () => {
125
+ throw new Error('X');
126
+ },
127
+ } as any,
128
+ },
129
+ });
130
+ model.registerFlow('I2', {
131
+ on: { eventName: 'go' },
132
+ sort: 2,
133
+ steps: { i2: { handler: async () => void calls.push('i2') } as any },
134
+ });
135
+
136
+ await model.dispatchEvent('go', undefined, { sequential: true }).catch(() => undefined);
137
+ // 只应执行第一个 flow,后续被中止
138
+ expect(calls).toEqual(['i1']);
139
+ });
140
+
141
+ test('beforeRender errors are thrown (sequential default)', async () => {
142
+ const engine = new FlowEngine();
143
+ class M extends FlowModel {}
144
+ engine.registerModels({ M });
145
+
146
+ const calls: string[] = [];
147
+ const model = engine.createModel({ use: 'M' });
148
+
149
+ model.registerFlow('F1', {
150
+ on: 'beforeRender',
151
+ sort: 0,
152
+ steps: {
153
+ a: {
154
+ handler: async () => {
155
+ throw new Error('BR');
156
+ },
157
+ } as any,
158
+ },
159
+ });
160
+ model.registerFlow('F2', {
161
+ on: 'beforeRender',
162
+ sort: 1,
163
+ steps: { b: { handler: async () => void calls.push('b') } as any },
164
+ });
165
+
166
+ await expect(model.dispatchEvent('beforeRender', undefined, { useCache: false })).rejects.toThrow('BR');
167
+ expect(calls).toEqual([]);
168
+ });
169
+ });