@nocobase/flow-engine 2.0.0-alpha.2 → 2.0.0-alpha.20

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 (387) 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 +2 -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/wrappers/contextual/StepSettingsDialog.js +7 -1
  22. package/lib/components/variables/VariableInput.js +16 -2
  23. package/lib/components/variables/VariableTag.js +43 -2
  24. package/lib/components/variables/types.d.ts +2 -0
  25. package/lib/data-source/index.d.ts +12 -4
  26. package/lib/data-source/index.js +18 -12
  27. package/lib/data-source/sortCollectionsByInherits.d.ts +10 -0
  28. package/lib/data-source/sortCollectionsByInherits.js +71 -0
  29. package/lib/executor/FlowExecutor.d.ts +4 -5
  30. package/lib/executor/FlowExecutor.js +122 -94
  31. package/lib/flowContext.d.ts +33 -5
  32. package/lib/flowContext.js +145 -74
  33. package/lib/flowEngine.d.ts +8 -1
  34. package/lib/flowEngine.js +12 -2
  35. package/lib/flowSettings.d.ts +2 -1
  36. package/lib/flowSettings.js +7 -3
  37. package/lib/hooks/useApplyAutoFlows.js +2 -1
  38. package/lib/index.d.ts +6 -1
  39. package/lib/index.js +29 -3
  40. package/lib/models/CollectionFieldModel.d.ts +2 -0
  41. package/lib/models/CollectionFieldModel.js +43 -3
  42. package/lib/models/flowModel.d.ts +28 -29
  43. package/lib/models/flowModel.js +110 -88
  44. package/lib/models/forkFlowModel.d.ts +2 -2
  45. package/lib/models/forkFlowModel.js +29 -6
  46. package/lib/provider.d.ts +3 -1
  47. package/lib/provider.js +7 -5
  48. package/lib/resources/multiRecordResource.js +2 -0
  49. package/lib/resources/singleRecordResource.js +1 -0
  50. package/lib/runjs-context/contexts/FormJSFieldItemRunJSContext.d.ts +1 -6
  51. package/lib/runjs-context/contexts/FormJSFieldItemRunJSContext.js +27 -20
  52. package/lib/runjs-context/contexts/JSBlockRunJSContext.d.ts +1 -6
  53. package/lib/runjs-context/contexts/JSBlockRunJSContext.js +46 -33
  54. package/lib/runjs-context/contexts/JSCollectionActionRunJSContext.d.ts +1 -2
  55. package/lib/runjs-context/contexts/JSCollectionActionRunJSContext.js +14 -15
  56. package/lib/runjs-context/contexts/{LinkageRunJSContext.d.ts → JSColumnRunJSContext.d.ts} +6 -3
  57. package/lib/runjs-context/contexts/JSColumnRunJSContext.js +78 -0
  58. package/lib/runjs-context/contexts/JSFieldRunJSContext.d.ts +1 -6
  59. package/lib/runjs-context/contexts/JSFieldRunJSContext.js +28 -24
  60. package/lib/runjs-context/contexts/JSItemRunJSContext.d.ts +1 -6
  61. package/lib/runjs-context/contexts/JSItemRunJSContext.js +24 -20
  62. package/lib/runjs-context/contexts/JSRecordActionRunJSContext.d.ts +1 -2
  63. package/lib/runjs-context/contexts/JSRecordActionRunJSContext.js +16 -17
  64. package/lib/runjs-context/contexts/base.d.ts +9 -0
  65. package/lib/runjs-context/contexts/base.js +169 -0
  66. package/lib/runjs-context/helpers.d.ts +5 -2
  67. package/lib/runjs-context/helpers.js +36 -27
  68. package/lib/runjs-context/registry.d.ts +7 -4
  69. package/lib/runjs-context/registry.js +10 -42
  70. package/lib/runjs-context/setup.d.ts +9 -0
  71. package/lib/runjs-context/setup.js +82 -0
  72. package/lib/runjs-context/snippets/global/{copy-record-json.snippet.js → api-request.snippet.js} +25 -10
  73. package/lib/runjs-context/snippets/global/clipboard-copy-text.snippet.js +61 -0
  74. package/lib/runjs-context/snippets/global/{view-navigation-push.snippet.js → import-esm.snippet.js} +26 -12
  75. package/lib/runjs-context/snippets/global/message-error.snippet.js +6 -0
  76. package/lib/runjs-context/snippets/global/message-success.snippet.js +6 -0
  77. package/lib/runjs-context/snippets/global/notification-open.snippet.d.ts +3 -8
  78. package/lib/runjs-context/snippets/global/notification-open.snippet.js +8 -1
  79. package/lib/runjs-context/snippets/global/open-view-dialog.snippet.js +10 -3
  80. package/lib/runjs-context/snippets/global/open-view-drawer.snippet.js +10 -3
  81. package/lib/runjs-context/snippets/global/query-selector.snippet.js +53 -0
  82. package/lib/runjs-context/snippets/global/require-amd.snippet.d.ts +11 -0
  83. package/lib/runjs-context/snippets/global/{requireAsync.snippet.js → require-amd.snippet.js} +16 -13
  84. package/lib/runjs-context/snippets/global/window-open.snippet.d.ts +3 -8
  85. package/lib/runjs-context/snippets/global/window-open.snippet.js +8 -1
  86. package/lib/runjs-context/snippets/index.d.ts +14 -3
  87. package/lib/runjs-context/snippets/index.js +160 -40
  88. package/lib/runjs-context/snippets/scene/block/add-event-listener.snippet.d.ts +11 -0
  89. package/lib/runjs-context/snippets/scene/{jsblock → block}/add-event-listener.snippet.js +11 -2
  90. package/lib/runjs-context/snippets/scene/block/api-fetch-render-list.snippet.d.ts +11 -0
  91. package/lib/runjs-context/snippets/scene/block/api-fetch-render-list.snippet.js +64 -0
  92. package/lib/runjs-context/snippets/scene/block/chartjs-bar.snippet.d.ts +11 -0
  93. package/lib/runjs-context/snippets/scene/block/chartjs-bar.snippet.js +99 -0
  94. package/lib/runjs-context/snippets/{libs → scene/block}/echarts-init.snippet.js +24 -7
  95. package/lib/runjs-context/snippets/scene/block/render-button-handler.snippet.d.ts +11 -0
  96. package/lib/runjs-context/snippets/scene/{jsblock → block}/render-button-handler.snippet.js +12 -6
  97. package/lib/runjs-context/snippets/scene/block/render-iframe.snippet.d.ts +11 -0
  98. package/lib/runjs-context/snippets/scene/block/render-iframe.snippet.js +57 -0
  99. package/lib/runjs-context/snippets/scene/block/render-info-card.snippet.d.ts +11 -0
  100. package/lib/runjs-context/snippets/scene/block/render-info-card.snippet.js +72 -0
  101. package/lib/runjs-context/snippets/scene/block/render-react.snippet.d.ts +11 -0
  102. package/lib/runjs-context/snippets/scene/{jsblock → block}/render-react.snippet.js +12 -11
  103. package/lib/runjs-context/snippets/scene/block/render-statistics.snippet.d.ts +11 -0
  104. package/lib/runjs-context/snippets/scene/block/render-statistics.snippet.js +100 -0
  105. package/lib/runjs-context/snippets/scene/block/render-timeline.snippet.d.ts +11 -0
  106. package/lib/runjs-context/snippets/scene/block/render-timeline.snippet.js +85 -0
  107. package/lib/runjs-context/snippets/scene/block/resource-example.snippet.d.ts +11 -0
  108. package/lib/runjs-context/snippets/scene/block/resource-example.snippet.js +60 -0
  109. package/lib/runjs-context/snippets/scene/block/three-users-orbit.snippet.d.ts +11 -0
  110. package/lib/runjs-context/snippets/scene/block/three-users-orbit.snippet.js +283 -0
  111. package/lib/runjs-context/snippets/scene/block/vue-component.snippet.d.ts +11 -0
  112. package/lib/runjs-context/snippets/scene/block/vue-component.snippet.js +124 -0
  113. package/lib/runjs-context/snippets/scene/detail/color-by-value.snippet.d.ts +11 -0
  114. package/lib/runjs-context/snippets/scene/{jsfield → detail}/color-by-value.snippet.js +13 -3
  115. package/lib/runjs-context/snippets/scene/detail/copy-to-clipboard.snippet.d.ts +11 -0
  116. package/lib/runjs-context/snippets/{global → scene/detail}/copy-to-clipboard.snippet.js +28 -6
  117. package/lib/runjs-context/snippets/scene/detail/format-number.snippet.d.ts +11 -0
  118. package/lib/runjs-context/snippets/scene/{jsfield → detail}/format-number.snippet.js +13 -3
  119. package/lib/runjs-context/snippets/scene/detail/innerHTML-value.snippet.d.ts +11 -0
  120. package/lib/runjs-context/snippets/scene/{jsfield → detail}/innerHTML-value.snippet.js +13 -3
  121. package/lib/runjs-context/snippets/scene/detail/percentage-bar.snippet.d.ts +11 -0
  122. package/lib/runjs-context/snippets/scene/detail/percentage-bar.snippet.js +82 -0
  123. package/lib/runjs-context/snippets/scene/detail/relative-time.snippet.d.ts +11 -0
  124. package/lib/runjs-context/snippets/scene/detail/relative-time.snippet.js +80 -0
  125. package/lib/runjs-context/snippets/scene/detail/status-tag.snippet.d.ts +11 -0
  126. package/lib/runjs-context/snippets/scene/detail/status-tag.snippet.js +74 -0
  127. package/lib/runjs-context/snippets/scene/form/calculate-total.snippet.d.ts +11 -0
  128. package/lib/runjs-context/snippets/scene/form/calculate-total.snippet.js +63 -0
  129. package/lib/runjs-context/snippets/scene/form/cascade-select.snippet.d.ts +11 -0
  130. package/lib/runjs-context/snippets/scene/form/cascade-select.snippet.js +81 -0
  131. package/lib/runjs-context/snippets/scene/form/conditional-required.snippet.d.ts +11 -0
  132. package/lib/runjs-context/snippets/scene/form/conditional-required.snippet.js +64 -0
  133. package/lib/runjs-context/snippets/scene/form/copy-field-values.snippet.d.ts +11 -0
  134. package/lib/runjs-context/snippets/scene/form/copy-field-values.snippet.js +74 -0
  135. package/lib/runjs-context/snippets/scene/form/render-basic.snippet.d.ts +11 -0
  136. package/lib/runjs-context/snippets/scene/{jsitem → form}/render-basic.snippet.js +11 -2
  137. package/lib/runjs-context/snippets/scene/form/set-disabled.snippet.d.ts +11 -0
  138. package/lib/runjs-context/snippets/scene/{linkage → form}/set-disabled.snippet.js +12 -3
  139. package/lib/runjs-context/snippets/scene/form/set-field-value.snippet.d.ts +11 -0
  140. package/lib/runjs-context/snippets/scene/{linkage → form}/set-field-value.snippet.js +12 -3
  141. package/lib/runjs-context/snippets/scene/form/set-required.snippet.d.ts +11 -0
  142. package/lib/runjs-context/snippets/scene/{linkage → form}/set-required.snippet.js +12 -3
  143. package/lib/runjs-context/snippets/scene/form/toggle-multiple-fields.snippet.d.ts +11 -0
  144. package/lib/runjs-context/snippets/scene/form/toggle-multiple-fields.snippet.js +67 -0
  145. package/lib/runjs-context/snippets/scene/form/toggle-visible.snippet.d.ts +11 -0
  146. package/lib/runjs-context/snippets/scene/{linkage → form}/toggle-visible.snippet.js +12 -3
  147. package/lib/runjs-context/snippets/scene/table/cell-open-dialog.snippet.d.ts +11 -0
  148. package/lib/runjs-context/snippets/scene/table/cell-open-dialog.snippet.js +64 -0
  149. package/lib/runjs-context/snippets/scene/table/collection-selected-count.snippet.d.ts +11 -0
  150. package/lib/runjs-context/snippets/scene/{actions → table}/collection-selected-count.snippet.js +11 -2
  151. package/lib/runjs-context/snippets/scene/table/concat-fields.snippet.d.ts +11 -0
  152. package/lib/runjs-context/snippets/scene/table/concat-fields.snippet.js +79 -0
  153. package/lib/runjs-context/snippets/scene/table/destroy-selected.snippet.d.ts +11 -0
  154. package/lib/runjs-context/snippets/{global/log-json-record.snippet.js → scene/table/destroy-selected.snippet.js} +24 -11
  155. package/lib/runjs-context/snippets/scene/table/export-selected-json.snippet.d.ts +11 -0
  156. package/lib/runjs-context/snippets/scene/table/export-selected-json.snippet.js +64 -0
  157. package/lib/runjs-context/snippets/scene/table/iterate-selected-rows.snippet.d.ts +11 -0
  158. package/lib/runjs-context/snippets/scene/{actions → table}/iterate-selected-rows.snippet.js +11 -2
  159. package/lib/runjs-context/snippets/types.d.ts +9 -1
  160. package/lib/types.d.ts +15 -3
  161. package/lib/types.js +4 -3
  162. package/lib/utils/buildSettingsViewInputArgs.d.ts +19 -0
  163. package/lib/utils/buildSettingsViewInputArgs.js +75 -0
  164. package/lib/utils/index.d.ts +3 -2
  165. package/lib/utils/index.js +5 -2
  166. package/lib/utils/params-resolvers.js +2 -2
  167. package/lib/utils/safeGlobals.d.ts +5 -3
  168. package/lib/utils/safeGlobals.js +40 -0
  169. package/lib/utils/serverContextParams.d.ts +1 -0
  170. package/lib/utils/variablesParams.d.ts +9 -5
  171. package/lib/utils/variablesParams.js +47 -36
  172. package/lib/views/PageComponent.js +2 -1
  173. package/lib/views/createViewMeta.d.ts +29 -1
  174. package/lib/views/createViewMeta.js +321 -72
  175. package/lib/views/index.d.ts +1 -0
  176. package/lib/views/index.js +3 -0
  177. package/lib/views/useDialog.d.ts +8 -8
  178. package/lib/views/useDialog.js +8 -7
  179. package/lib/views/useDrawer.d.ts +8 -8
  180. package/lib/views/useDrawer.js +40 -26
  181. package/lib/views/usePage.d.ts +8 -8
  182. package/lib/views/usePage.js +8 -7
  183. package/package.json +4 -3
  184. package/src/BlockScopedFlowEngine.ts +86 -0
  185. package/src/FlowContextProvider.tsx +4 -2
  186. package/src/JSRunner.ts +3 -0
  187. package/src/ViewScopedFlowEngine.ts +1 -1
  188. package/src/__tests__/JSRunner.test.ts +62 -53
  189. package/src/__tests__/blockScopedFlowEngine.test.ts +154 -0
  190. package/src/__tests__/flow-engine.test.ts +3 -0
  191. package/src/__tests__/flowContextCreateJSRunner.test.ts +163 -0
  192. package/src/__tests__/flowEngine.saveModel.test.ts +4 -0
  193. package/src/__tests__/flowRunJSContextDefine.test.ts +508 -0
  194. package/src/__tests__/globalFlowRegistry.test.ts +1 -1
  195. package/src/__tests__/runjsContext.test.ts +216 -35
  196. package/src/__tests__/runjsContextImplementations.test.ts +217 -0
  197. package/src/__tests__/runjsContextRuntime.test.ts +269 -0
  198. package/src/__tests__/runjsEdgeCases.test.ts +281 -0
  199. package/src/__tests__/runjsLocales.test.ts +36 -0
  200. package/src/__tests__/runjsRuntimeFeatures.test.ts +449 -0
  201. package/src/__tests__/runjsSnippets.test.ts +140 -0
  202. package/src/__tests__/viewScopedFlowEngine.test.ts +3 -3
  203. package/src/components/DynamicFlowsEditor.tsx +3 -4
  204. package/src/components/FieldModelRenderer.tsx +16 -5
  205. package/src/components/FieldSkeleton.tsx +27 -0
  206. package/src/components/FlowContextSelector.tsx +6 -2
  207. package/src/components/FlowModelRenderer.tsx +30 -78
  208. package/src/components/FormItem.tsx +8 -1
  209. package/src/components/__tests__/flow-model-render-error-fallback.test.tsx +5 -5
  210. package/src/components/__tests__/gridDragPlanner.test.ts +494 -0
  211. package/src/components/dnd/README.md +149 -0
  212. package/src/components/dnd/findModelUidPosition.ts +26 -0
  213. package/src/components/dnd/gridDragPlanner.ts +659 -0
  214. package/src/components/dnd/index.tsx +3 -3
  215. package/src/components/settings/wrappers/contextual/StepSettingsDialog.tsx +14 -1
  216. package/src/components/subModel/__tests__/AddSubModelButton.test.tsx +1 -0
  217. package/src/components/variables/VariableInput.tsx +22 -2
  218. package/src/components/variables/VariableTag.tsx +54 -2
  219. package/src/components/variables/types.ts +2 -0
  220. package/src/data-source/__tests__/sortCollectionsByInherits.test.ts +125 -0
  221. package/src/data-source/index.ts +16 -10
  222. package/src/data-source/sortCollectionsByInherits.ts +61 -0
  223. package/src/executor/FlowExecutor.ts +160 -114
  224. package/src/executor/__tests__/flowExecutor.test.ts +151 -5
  225. package/src/flowContext.ts +196 -93
  226. package/src/flowEngine.ts +13 -2
  227. package/src/flowSettings.ts +8 -3
  228. package/src/hooks/useApplyAutoFlows.ts +3 -1
  229. package/src/index.ts +11 -1
  230. package/src/models/CollectionFieldModel.tsx +43 -4
  231. package/src/models/__tests__/flowModel.getFlows.sort.test.ts +4 -4
  232. package/src/models/__tests__/flowModel.test.ts +218 -95
  233. package/src/models/flowModel.tsx +146 -122
  234. package/src/models/forkFlowModel.ts +37 -5
  235. package/src/provider.tsx +10 -7
  236. package/src/resources/multiRecordResource.ts +2 -0
  237. package/src/resources/singleRecordResource.ts +1 -0
  238. package/src/runjs-context/contexts/FormJSFieldItemRunJSContext.ts +28 -21
  239. package/src/runjs-context/contexts/JSBlockRunJSContext.ts +46 -34
  240. package/src/runjs-context/contexts/JSCollectionActionRunJSContext.ts +15 -16
  241. package/src/runjs-context/contexts/JSColumnRunJSContext.ts +58 -0
  242. package/src/runjs-context/contexts/JSFieldRunJSContext.ts +30 -25
  243. package/src/runjs-context/contexts/JSItemRunJSContext.ts +25 -21
  244. package/src/runjs-context/contexts/JSRecordActionRunJSContext.ts +17 -18
  245. package/src/runjs-context/contexts/base.ts +155 -0
  246. package/src/runjs-context/helpers.ts +32 -30
  247. package/src/runjs-context/registry.ts +16 -47
  248. package/src/runjs-context/setup.ts +51 -0
  249. package/src/runjs-context/snippets/global/api-request.snippet.ts +38 -0
  250. package/src/runjs-context/snippets/global/clipboard-copy-text.snippet.ts +42 -0
  251. package/src/runjs-context/snippets/global/import-esm.snippet.ts +39 -0
  252. package/src/runjs-context/snippets/global/message-error.snippet.ts +6 -0
  253. package/src/runjs-context/snippets/global/message-success.snippet.ts +6 -0
  254. package/src/runjs-context/snippets/global/notification-open.snippet.ts +11 -1
  255. package/src/runjs-context/snippets/global/open-view-dialog.snippet.ts +10 -3
  256. package/src/runjs-context/snippets/global/open-view-drawer.snippet.ts +10 -3
  257. package/src/runjs-context/snippets/global/query-selector.snippet.ts +34 -0
  258. package/src/runjs-context/snippets/global/require-amd.snippet.ts +30 -0
  259. package/src/runjs-context/snippets/global/window-open.snippet.ts +11 -1
  260. package/src/runjs-context/snippets/index.ts +176 -39
  261. package/src/runjs-context/snippets/scene/{jsblock → block}/add-event-listener.snippet.ts +14 -2
  262. package/src/runjs-context/snippets/scene/block/api-fetch-render-list.snippet.ts +45 -0
  263. package/src/runjs-context/snippets/scene/block/chartjs-bar.snippet.ts +80 -0
  264. package/src/runjs-context/snippets/scene/block/echarts-init.snippet.ts +44 -0
  265. package/src/runjs-context/snippets/scene/{jsblock → block}/render-button-handler.snippet.ts +15 -6
  266. package/src/runjs-context/snippets/scene/block/render-iframe.snippet.ts +38 -0
  267. package/src/runjs-context/snippets/scene/block/render-info-card.snippet.ts +53 -0
  268. package/src/runjs-context/snippets/scene/{jsblock → block}/render-react.snippet.ts +15 -11
  269. package/src/runjs-context/snippets/scene/block/render-statistics.snippet.ts +81 -0
  270. package/src/runjs-context/snippets/scene/block/render-timeline.snippet.ts +66 -0
  271. package/src/runjs-context/snippets/scene/block/resource-example.snippet.ts +46 -0
  272. package/src/runjs-context/snippets/scene/block/three-users-orbit.snippet.ts +264 -0
  273. package/src/runjs-context/snippets/scene/block/vue-component.snippet.ts +105 -0
  274. package/src/runjs-context/snippets/scene/detail/color-by-value.snippet.ts +33 -0
  275. package/src/runjs-context/snippets/scene/detail/copy-to-clipboard.snippet.ts +45 -0
  276. package/src/runjs-context/snippets/scene/detail/format-number.snippet.ts +32 -0
  277. package/src/runjs-context/snippets/scene/detail/innerHTML-value.snippet.ts +31 -0
  278. package/src/runjs-context/snippets/scene/detail/percentage-bar.snippet.ts +63 -0
  279. package/src/runjs-context/snippets/scene/detail/relative-time.snippet.ts +61 -0
  280. package/src/runjs-context/snippets/scene/detail/status-tag.snippet.ts +55 -0
  281. package/src/runjs-context/snippets/scene/form/calculate-total.snippet.ts +44 -0
  282. package/src/runjs-context/snippets/scene/form/cascade-select.snippet.ts +62 -0
  283. package/src/runjs-context/snippets/scene/form/conditional-required.snippet.ts +45 -0
  284. package/src/runjs-context/snippets/scene/form/copy-field-values.snippet.ts +55 -0
  285. package/src/runjs-context/snippets/scene/{jsitem → form}/render-basic.snippet.ts +14 -2
  286. package/src/runjs-context/snippets/scene/{linkage → form}/set-disabled.snippet.ts +15 -3
  287. package/src/runjs-context/snippets/scene/{linkage → form}/set-field-value.snippet.ts +15 -3
  288. package/src/runjs-context/snippets/scene/{linkage → form}/set-required.snippet.ts +15 -3
  289. package/src/runjs-context/snippets/scene/form/toggle-multiple-fields.snippet.ts +48 -0
  290. package/src/runjs-context/snippets/scene/{linkage → form}/toggle-visible.snippet.ts +15 -3
  291. package/src/runjs-context/snippets/scene/table/cell-open-dialog.snippet.ts +45 -0
  292. package/src/runjs-context/snippets/scene/{actions → table}/collection-selected-count.snippet.ts +14 -2
  293. package/src/runjs-context/snippets/scene/table/concat-fields.snippet.ts +60 -0
  294. package/src/runjs-context/snippets/scene/table/destroy-selected.snippet.ts +36 -0
  295. package/src/runjs-context/snippets/scene/table/export-selected-json.snippet.ts +45 -0
  296. package/src/runjs-context/snippets/scene/{actions → table}/iterate-selected-rows.snippet.ts +14 -2
  297. package/src/runjs-context/snippets/types.ts +5 -1
  298. package/src/types.ts +13 -0
  299. package/src/utils/__tests__/safeGlobals.test.ts +22 -1
  300. package/src/utils/buildSettingsViewInputArgs.ts +72 -0
  301. package/src/utils/index.ts +2 -2
  302. package/src/utils/params-resolvers.ts +1 -1
  303. package/src/utils/safeGlobals.ts +49 -3
  304. package/src/utils/serverContextParams.ts +1 -0
  305. package/src/utils/variablesParams.ts +50 -38
  306. package/src/views/PageComponent.tsx +1 -1
  307. package/src/views/createViewMeta.ts +372 -70
  308. package/src/views/index.tsx +1 -0
  309. package/src/views/useDialog.tsx +12 -10
  310. package/src/views/useDrawer.tsx +60 -36
  311. package/src/views/usePage.tsx +13 -10
  312. package/lib/components/dnd/getMousePositionOnElement.d.ts +0 -50
  313. package/lib/components/dnd/getMousePositionOnElement.js +0 -95
  314. package/lib/components/dnd/moveBlock.d.ts +0 -33
  315. package/lib/components/dnd/moveBlock.js +0 -302
  316. package/lib/runjs-context/contexts/FlowRunJSContext.d.ts +0 -38
  317. package/lib/runjs-context/contexts/FlowRunJSContext.js +0 -217
  318. package/lib/runjs-context/contexts/LinkageRunJSContext.js +0 -62
  319. package/lib/runjs-context/index.d.ts +0 -19
  320. package/lib/runjs-context/index.js +0 -57
  321. package/lib/runjs-context/snippets/global/api-request-get.snippet.d.ts +0 -16
  322. package/lib/runjs-context/snippets/global/api-request-get.snippet.js +0 -42
  323. package/lib/runjs-context/snippets/global/api-request-post.snippet.d.ts +0 -16
  324. package/lib/runjs-context/snippets/global/api-request-post.snippet.js +0 -42
  325. package/lib/runjs-context/snippets/global/console-log-ctx.snippet.d.ts +0 -16
  326. package/lib/runjs-context/snippets/global/console-log-ctx.snippet.js +0 -41
  327. package/lib/runjs-context/snippets/global/sleep.snippet.d.ts +0 -16
  328. package/lib/runjs-context/snippets/global/sleep.snippet.js +0 -43
  329. package/lib/runjs-context/snippets/global/try-catch-async.snippet.d.ts +0 -16
  330. package/lib/runjs-context/snippets/global/try-catch-async.snippet.js +0 -44
  331. package/lib/runjs-context/snippets/libs/echarts-init.snippet.d.ts +0 -15
  332. package/lib/runjs-context/snippets/scene/actions/collection-selected-count.snippet.d.ts +0 -15
  333. package/lib/runjs-context/snippets/scene/actions/iterate-selected-rows.snippet.d.ts +0 -15
  334. package/lib/runjs-context/snippets/scene/actions/record-id-message.snippet.d.ts +0 -15
  335. package/lib/runjs-context/snippets/scene/actions/record-id-message.snippet.js +0 -43
  336. package/lib/runjs-context/snippets/scene/actions/run-action-basic.snippet.d.ts +0 -15
  337. package/lib/runjs-context/snippets/scene/actions/run-action-basic.snippet.js +0 -40
  338. package/lib/runjs-context/snippets/scene/jsblock/add-event-listener.snippet.d.ts +0 -15
  339. package/lib/runjs-context/snippets/scene/jsblock/append-style.snippet.d.ts +0 -15
  340. package/lib/runjs-context/snippets/scene/jsblock/append-style.snippet.js +0 -42
  341. package/lib/runjs-context/snippets/scene/jsblock/jsx-mount.snippet.d.ts +0 -15
  342. package/lib/runjs-context/snippets/scene/jsblock/jsx-unmount.snippet.d.ts +0 -15
  343. package/lib/runjs-context/snippets/scene/jsblock/jsx-unmount.snippet.js +0 -41
  344. package/lib/runjs-context/snippets/scene/jsblock/render-basic.snippet.d.ts +0 -15
  345. package/lib/runjs-context/snippets/scene/jsblock/render-basic.snippet.js +0 -41
  346. package/lib/runjs-context/snippets/scene/jsblock/render-button-handler.snippet.d.ts +0 -15
  347. package/lib/runjs-context/snippets/scene/jsblock/render-card.snippet.js +0 -45
  348. package/lib/runjs-context/snippets/scene/jsblock/render-react.snippet.d.ts +0 -15
  349. package/lib/runjs-context/snippets/scene/jsfield/color-by-value.snippet.d.ts +0 -15
  350. package/lib/runjs-context/snippets/scene/jsfield/format-number.snippet.d.ts +0 -15
  351. package/lib/runjs-context/snippets/scene/jsfield/innerHTML-value.snippet.d.ts +0 -15
  352. package/lib/runjs-context/snippets/scene/jsitem/render-basic.snippet.d.ts +0 -15
  353. package/lib/runjs-context/snippets/scene/linkage/set-disabled.snippet.d.ts +0 -15
  354. package/lib/runjs-context/snippets/scene/linkage/set-field-value.snippet.d.ts +0 -15
  355. package/lib/runjs-context/snippets/scene/linkage/set-required.snippet.d.ts +0 -15
  356. package/lib/runjs-context/snippets/scene/linkage/toggle-visible.snippet.d.ts +0 -15
  357. package/src/components/dnd/getMousePositionOnElement.ts +0 -115
  358. package/src/components/dnd/moveBlock.ts +0 -379
  359. package/src/runjs-context/contexts/FlowRunJSContext.ts +0 -190
  360. package/src/runjs-context/contexts/LinkageRunJSContext.ts +0 -35
  361. package/src/runjs-context/index.ts +0 -20
  362. package/src/runjs-context/snippets/global/api-request-get.snippet.ts +0 -20
  363. package/src/runjs-context/snippets/global/api-request-post.snippet.ts +0 -20
  364. package/src/runjs-context/snippets/global/console-log-ctx.snippet.ts +0 -19
  365. package/src/runjs-context/snippets/global/copy-record-json.snippet.ts +0 -21
  366. package/src/runjs-context/snippets/global/copy-to-clipboard.snippet.ts +0 -21
  367. package/src/runjs-context/snippets/global/log-json-record.snippet.ts +0 -21
  368. package/src/runjs-context/snippets/global/requireAsync.snippet.ts +0 -24
  369. package/src/runjs-context/snippets/global/sleep.snippet.ts +0 -21
  370. package/src/runjs-context/snippets/global/try-catch-async.snippet.ts +0 -22
  371. package/src/runjs-context/snippets/global/view-navigation-push.snippet.ts +0 -23
  372. package/src/runjs-context/snippets/libs/echarts-init.snippet.ts +0 -24
  373. package/src/runjs-context/snippets/scene/actions/record-id-message.snippet.ts +0 -21
  374. package/src/runjs-context/snippets/scene/actions/run-action-basic.snippet.ts +0 -18
  375. package/src/runjs-context/snippets/scene/jsblock/append-style.snippet.ts +0 -20
  376. package/src/runjs-context/snippets/scene/jsblock/jsx-mount.snippet.ts +0 -24
  377. package/src/runjs-context/snippets/scene/jsblock/jsx-unmount.snippet.ts +0 -19
  378. package/src/runjs-context/snippets/scene/jsblock/render-basic.snippet.ts +0 -24
  379. package/src/runjs-context/snippets/scene/jsblock/render-card.snippet.ts +0 -30
  380. package/src/runjs-context/snippets/scene/jsfield/color-by-value.snippet.ts +0 -20
  381. package/src/runjs-context/snippets/scene/jsfield/format-number.snippet.ts +0 -19
  382. package/src/runjs-context/snippets/scene/jsfield/innerHTML-value.snippet.ts +0 -18
  383. /package/lib/runjs-context/snippets/global/{copy-record-json.snippet.d.ts → api-request.snippet.d.ts} +0 -0
  384. /package/lib/runjs-context/snippets/global/{copy-to-clipboard.snippet.d.ts → clipboard-copy-text.snippet.d.ts} +0 -0
  385. /package/lib/runjs-context/snippets/global/{log-json-record.snippet.d.ts → import-esm.snippet.d.ts} +0 -0
  386. /package/lib/runjs-context/snippets/global/{view-navigation-push.snippet.d.ts → query-selector.snippet.d.ts} +0 -0
  387. /package/lib/runjs-context/snippets/scene/{jsblock/render-card.snippet.d.ts → block/echarts-init.snippet.d.ts} +0 -0
@@ -0,0 +1,45 @@
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 type { SnippetModule } from '../../types';
11
+ import { JSColumnRunJSContext } from '../../../contexts/JSColumnRunJSContext';
12
+
13
+ const snippet: SnippetModule = {
14
+ contexts: [JSColumnRunJSContext],
15
+ prefix: 'sn-col-open-dialog',
16
+ label: 'Cell dialog with row data',
17
+ description: 'Render a button in cell to open dialog via ctx.openView with current row context',
18
+ locales: {
19
+ 'zh-CN': {
20
+ label: '单元格对话框(显示行数据)',
21
+ description: '在单元格渲染按钮,点击后通过 ctx.openView 打开弹窗并传入当前行上下文',
22
+ },
23
+ },
24
+ content: `
25
+ // Render a button inside the cell
26
+ ctx.element.innerHTML = '<button class="nb-cell-btn" style="padding:4px 8px">' + ctx.t('View') + '</button>';
27
+
28
+ const button = ctx.element.querySelector('.nb-cell-btn');
29
+ const popupUid = ctx.model.uid + '-1'; // popupUid should be stable and better bound to ctx.model.uid
30
+ const primaryKey = ctx.collection?.primaryKey || 'id';
31
+
32
+ button?.addEventListener('click', async () => {
33
+ await ctx.openView(popupUid, {
34
+ mode: 'dialog',
35
+ title: ctx.t('Row detail'),
36
+ params: {
37
+ filterByTk: ctx.record?.[primaryKey],
38
+ record: ctx.record,
39
+ },
40
+ });
41
+ });
42
+ `,
43
+ };
44
+
45
+ export default snippet;
@@ -7,10 +7,20 @@
7
7
  * For more information, please refer to: https://www.nocobase.com/agreement.
8
8
  */
9
9
 
10
- export default {
11
- contexts: ['JSCollectionActionRunJSContext'],
10
+ import type { SnippetModule } from '../../types';
11
+ import { JSCollectionActionRunJSContext } from '../../../contexts/JSCollectionActionRunJSContext';
12
+
13
+ const snippet: SnippetModule = {
14
+ contexts: [JSCollectionActionRunJSContext],
12
15
  prefix: 'sn-act-selected-count',
13
16
  label: 'Selected count',
17
+ description: 'Show number of selected rows in list action',
18
+ locales: {
19
+ 'zh-CN': {
20
+ label: '选中数量',
21
+ description: '提示当前选中行的数量',
22
+ },
23
+ },
14
24
  content: `
15
25
  const rows = ctx.resource?.getSelectedRows?.() || [];
16
26
  if (!rows.length) {
@@ -20,3 +30,5 @@ if (!rows.length) {
20
30
  }
21
31
  `,
22
32
  };
33
+
34
+ export default snippet;
@@ -0,0 +1,60 @@
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 type { SnippetModule } from '../../types';
11
+ import { JSColumnRunJSContext } from '../../../contexts/JSColumnRunJSContext';
12
+
13
+ const snippet: SnippetModule = {
14
+ contexts: [JSColumnRunJSContext],
15
+ prefix: 'sn-col-concat',
16
+ label: 'Concat two fields',
17
+ description: 'Combine two field values into the current column cell',
18
+ locales: {
19
+ 'zh-CN': {
20
+ label: '拼接两个字段值',
21
+ description: '在自定义列中拼接两个字段的值作为显示内容',
22
+ },
23
+ },
24
+ content: `
25
+ // Demo helper: infer previous columns' dataIndex values based on the current column position
26
+ // In production, hardcode field names to avoid surprises when columns are reordered
27
+ function resolvePreviousDataIndexes() {
28
+ const parent = ctx.model?.parent;
29
+ const list = parent?.subModels?.columns;
30
+ if (!Array.isArray(list)) return [];
31
+ const currentUid = ctx.model?.uid;
32
+ const currentIndex = list.findIndex((item) => item?.uid === currentUid);
33
+ if (currentIndex <= 0) return [];
34
+ return list
35
+ .slice(Math.max(0, currentIndex - 2), currentIndex)
36
+ .map((item) => (item && item.props ? item.props.dataIndex : undefined))
37
+ .filter((key) => typeof key === 'string' && key.length > 0);
38
+ }
39
+
40
+ const [autoFieldA, autoFieldB] = resolvePreviousDataIndexes();
41
+
42
+ // Fallback: manually specify field keys when auto detection is not enough
43
+ const fieldA = autoFieldA || 'firstName';
44
+ const fieldB = autoFieldB || 'lastName';
45
+
46
+ const normalize = (value) => {
47
+ if (value === undefined || value === null) return '';
48
+ return String(value).trim();
49
+ };
50
+
51
+ const valueA = normalize(ctx.record?.[fieldA]);
52
+ const valueB = normalize(ctx.record?.[fieldB]);
53
+
54
+ const parts = [valueA, valueB].filter((item) => item.length > 0);
55
+
56
+ ctx.element.textContent = parts.length ? parts.join(' / ') : ctx.t('N/A');
57
+ `,
58
+ };
59
+
60
+ export default snippet;
@@ -0,0 +1,36 @@
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 type { SnippetModule } from '../../types';
11
+ import { JSCollectionActionRunJSContext } from '../../../contexts/JSCollectionActionRunJSContext';
12
+
13
+ const snippet: SnippetModule = {
14
+ contexts: [JSCollectionActionRunJSContext],
15
+ prefix: 'sn-act-destroy-selected',
16
+ label: 'Destroy selected rows',
17
+ description: 'Delete selected rows via resource.destroySelectedRows()',
18
+ locales: {
19
+ 'zh-CN': {
20
+ label: '删除选中行',
21
+ description: '通过 resource.destroySelectedRows() 删除选中行',
22
+ },
23
+ },
24
+ content: `
25
+ const rows = ctx.resource?.getSelectedRows?.() || [];
26
+ if (!rows.length) {
27
+ ctx.message.warning(ctx.t('Please select data'));
28
+ return;
29
+ }
30
+
31
+ await ctx.resource.destroySelectedRows();
32
+ ctx.message.success(ctx.t('Deleted {{count}} rows', { count: rows.length }));
33
+ `,
34
+ };
35
+
36
+ export default snippet;
@@ -0,0 +1,45 @@
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 type { SnippetModule } from '../../types';
11
+ import { JSCollectionActionRunJSContext } from '../../../contexts/JSCollectionActionRunJSContext';
12
+
13
+ const snippet: SnippetModule = {
14
+ contexts: [JSCollectionActionRunJSContext],
15
+ prefix: 'sn-act-export',
16
+ label: 'Export selected rows as JSON',
17
+ description: 'Download selected rows as a JSON file',
18
+ locales: {
19
+ 'zh-CN': {
20
+ label: '导出选中行为 JSON',
21
+ description: '将选中的行导出为 JSON 文件下载',
22
+ },
23
+ },
24
+ content: `
25
+ const rows = ctx.resource?.getSelectedRows?.() || [];
26
+ if (!rows.length) {
27
+ ctx.message.warning(ctx.t('Please select at least one row'));
28
+ return;
29
+ }
30
+
31
+ // Create JSON file and download
32
+ const jsonStr = JSON.stringify(rows, null, 2);
33
+ const blob = new Blob([jsonStr], { type: 'application/json' });
34
+ const url = URL.createObjectURL(blob);
35
+ const link = document.createElement('a');
36
+ link.href = url;
37
+ link.download = \`export-\${new Date().toISOString().split('T')[0]}.json\`;
38
+ link.click();
39
+ URL.revokeObjectURL(url);
40
+
41
+ ctx.message.success(ctx.t('Exported {{count}} records', { count: rows.length }));
42
+ `,
43
+ };
44
+
45
+ export default snippet;
@@ -7,10 +7,20 @@
7
7
  * For more information, please refer to: https://www.nocobase.com/agreement.
8
8
  */
9
9
 
10
- export default {
11
- contexts: ['JSCollectionActionRunJSContext'],
10
+ import type { SnippetModule } from '../../types';
11
+ import { JSCollectionActionRunJSContext } from '../../../contexts/JSCollectionActionRunJSContext';
12
+
13
+ const snippet: SnippetModule = {
14
+ contexts: [JSCollectionActionRunJSContext],
12
15
  prefix: 'sn-act-iterate',
13
16
  label: 'Iterate selected rows',
17
+ description: 'Loop through selected rows and process each record',
18
+ locales: {
19
+ 'zh-CN': {
20
+ label: '遍历选中行',
21
+ description: '遍历选中行并处理每条记录',
22
+ },
23
+ },
14
24
  content: `
15
25
  const rows = ctx.resource?.getSelectedRows?.() || [];
16
26
  for (const row of rows) {
@@ -19,3 +29,5 @@ for (const row of rows) {
19
29
  ctx.message.success(ctx.t('Processed {{count}} rows', { count: rows.length }));
20
30
  `,
21
31
  };
32
+
33
+ export default snippet;
@@ -7,11 +7,15 @@
7
7
  * For more information, please refer to: https://www.nocobase.com/agreement.
8
8
  */
9
9
 
10
+ export type SnippetContextSpecifier = string | { name: string } | (new (...args: any[]) => any);
11
+
10
12
  export type SnippetModule = {
11
13
  content: string;
12
- contexts?: string[]; // e.g., ['JSBlockRunJSContext'] or ['*']
14
+ contexts?: SnippetContextSpecifier[]; // e.g., [JSBlockRunJSContext] or ['*']
13
15
  versions?: string[]; // e.g., ['v1'] or ['*']
16
+ scenes?: string[]; // logical placement hints like ['form', 'table']
14
17
  prefix?: string; // completion trigger text
15
18
  label?: string; // display name in snippets list
16
19
  description?: string; // optional longer description
20
+ locales?: Record<string, { label?: string; description?: string }>;
17
21
  };
package/src/types.ts CHANGED
@@ -134,6 +134,8 @@ export enum ActionScene {
134
134
  BLOCK_LINKAGE_RULES = 1,
135
135
  /** 表单字段级联动规则可用 */
136
136
  FIELD_LINKAGE_RULES,
137
+ /** 子表单字段级联动规则可用 */
138
+ SUB_FORM_FIELD_LINKAGE_RULES,
137
139
  /** 详情字段级联动规则可用 */
138
140
  DETAILS_FIELD_LINKAGE_RULES,
139
141
  /** 按钮级联动规则可用 */
@@ -185,6 +187,16 @@ export type FlowEvent<TModel extends FlowModel = FlowModel> =
185
187
  | FlowEventName
186
188
  | { eventName: FlowEventName; defaultParams?: Record<string, any> };
187
189
 
190
+ /**
191
+ * 事件分发选项。
192
+ */
193
+ export interface DispatchEventOptions {
194
+ /** 是否顺序执行(默认并行) */
195
+ sequential?: boolean;
196
+ /** 是否使用缓存(默认 false;beforeRender 的默认值为 true,可覆盖) */
197
+ useCache?: boolean;
198
+ }
199
+
188
200
  /**
189
201
  * 事件定义:用于事件注册表(全局/模型类级)。
190
202
  */
@@ -300,6 +312,7 @@ export interface IFlowModelRepository<T extends FlowModel = FlowModel> {
300
312
  save(model: T, options?: { onlyStepParams?: boolean }): Promise<Record<string, any>>;
301
313
  destroy(uid: string): Promise<boolean>;
302
314
  move(sourceId: string, targetId: string, position: 'before' | 'after'): Promise<void>;
315
+ duplicate(uid: string): Promise<Record<string, any> | null>;
303
316
  }
304
317
 
305
318
  /**
@@ -8,7 +8,7 @@
8
8
  */
9
9
 
10
10
  import { describe, expect, it } from 'vitest';
11
- import { createSafeDocument, createSafeWindow } from '../safeGlobals';
11
+ import { createSafeDocument, createSafeWindow, createSafeNavigator } from '../safeGlobals';
12
12
 
13
13
  describe('safeGlobals', () => {
14
14
  it('createSafeWindow exposes only allowed globals and extras', () => {
@@ -26,4 +26,25 @@ describe('safeGlobals', () => {
26
26
  expect(doc.bar).toBe(true);
27
27
  expect(() => doc.cookie).toThrow(/not allowed/);
28
28
  });
29
+
30
+ it('createSafeNavigator exposes limited props and guards others', () => {
31
+ const nav: any = createSafeNavigator();
32
+ // clipboard object should always exist
33
+ expect(typeof nav.clipboard).toBe('object');
34
+ // writeText may or may not exist depending on environment
35
+ if (typeof navigator !== 'undefined' && (navigator as any).clipboard?.writeText) {
36
+ expect(typeof nav.clipboard.writeText).toBe('function');
37
+ } else {
38
+ expect(typeof nav.clipboard.writeText === 'undefined' || typeof nav.clipboard.writeText === 'function').toBe(
39
+ true,
40
+ );
41
+ }
42
+ // readable properties
43
+ expect(() => void nav.onLine).not.toThrow();
44
+ expect(() => void nav.language).not.toThrow();
45
+ expect(() => void nav.languages).not.toThrow();
46
+ // blocked properties
47
+ expect(() => (nav as any).geolocation).toThrow(/not allowed/);
48
+ expect(() => (nav as any).userAgent).toThrow(/not allowed/);
49
+ });
29
50
  });
@@ -0,0 +1,72 @@
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 type { FlowModel } from '../models';
11
+ import { inferRecordRef } from './variablesParams';
12
+
13
+ /**
14
+ * 统一构造设置弹窗 openView 的 inputArgs:
15
+ * - collectionName/dataSourceKey/filterByTk:优先从 model.context 推断;否则回退父视图 inputArgs
16
+ * - sourceId:优先从 resource.getSourceId();否则回退父视图 inputArgs
17
+ * - associationName:来自 association.resourceName 或 resource.getResourceName()
18
+ * - navigation:父视图 navigation 或传入的 navigationOverride
19
+ */
20
+ export function buildSettingsViewInputArgs(
21
+ model: FlowModel,
22
+ extra?: Record<string, any>,
23
+ options?: { navigationOverride?: any },
24
+ ): Record<string, any> {
25
+ const defaults: Record<string, any> = {};
26
+
27
+ try {
28
+ // 1) 当前记录/集合
29
+ const ref = inferRecordRef((model as any).context);
30
+ if (ref?.collection) {
31
+ defaults.collectionName = ref.collection;
32
+ defaults.dataSourceKey = ref.dataSourceKey || 'main';
33
+ defaults.filterByTk = ref.filterByTk;
34
+ }
35
+
36
+ // 2) 回退父视图 inputArgs(如在抽屉/页面中)
37
+ const parentArgs = (model as any)?.context?.view?.inputArgs || {};
38
+ if (!defaults.collectionName && parentArgs?.collectionName) {
39
+ defaults.collectionName = parentArgs.collectionName;
40
+ defaults.dataSourceKey = parentArgs.dataSourceKey || defaults.dataSourceKey || 'main';
41
+ }
42
+ if (defaults.filterByTk == null && parentArgs?.filterByTk != null) {
43
+ defaults.filterByTk = parentArgs.filterByTk;
44
+ }
45
+ if (defaults.sourceId == null && parentArgs?.sourceId != null) {
46
+ defaults.sourceId = parentArgs.sourceId;
47
+ }
48
+
49
+ // 3) 导航(用于推断“上级弹窗”)
50
+ const nav = options?.navigationOverride ?? (model as any)?.context?.view?.navigation;
51
+ if (nav) {
52
+ defaults.navigation = nav;
53
+ }
54
+
55
+ // 4) 直接从资源读取 sourceId(优先级高于父视图)
56
+ const sid = (model as any)?.context?.resource?.getSourceId?.();
57
+ if (sid !== undefined && sid !== null && String(sid) !== '') {
58
+ defaults.sourceId = sid;
59
+ }
60
+
61
+ // 5) 关联名(用于“上级记录”)
62
+ const assocName =
63
+ (model as any)?.context?.association?.resourceName || (model as any)?.context?.resource?.getResourceName?.();
64
+ if (typeof assocName === 'string' && assocName) {
65
+ defaults.associationName = assocName;
66
+ }
67
+ } catch (_) {
68
+ // 忽略推断异常
69
+ }
70
+
71
+ return { ...defaults, ...(extra || {}) };
72
+ }
@@ -48,7 +48,6 @@ export {
48
48
  createRecordMetaFactory,
49
49
  extractUsedVariableNames,
50
50
  extractUsedVariablePaths,
51
- inferParentRecordRef,
52
51
  inferRecordRef,
53
52
  type RecordParamsBuilder,
54
53
  } from './variablesParams';
@@ -58,6 +57,7 @@ export { extractPropertyPath, formatPathToVariable, isVariableExpression } from
58
57
 
59
58
  export { clearAutoFlowError, getAutoFlowError, setAutoFlowError, type AutoFlowError } from './autoFlowError';
60
59
  export { parsePathnameToViewParams, type ViewParam } from './parsePathnameToViewParams';
60
+ export { buildSettingsViewInputArgs } from './buildSettingsViewInputArgs';
61
61
 
62
62
  // 安全全局对象(window/document)
63
- export { createSafeDocument, createSafeWindow } from './safeGlobals';
63
+ export { createSafeDocument, createSafeWindow, createSafeNavigator } from './safeGlobals';
@@ -7,9 +7,9 @@
7
7
  * For more information, please refer to: https://www.nocobase.com/agreement.
8
8
  */
9
9
 
10
+ import { getValuesByPath } from '@nocobase/shared';
10
11
  import _ from 'lodash';
11
12
  import { FlowContext, FlowModelContext, FlowRuntimeContext } from '../flowContext';
12
- import { getValuesByPath } from '@nocobase/utils/client';
13
13
  import type { FlowModel } from '../models';
14
14
  import type { ServerContextParams } from './serverContextParams';
15
15
 
@@ -8,9 +8,10 @@
8
8
  */
9
9
 
10
10
  /**
11
- * 统一的安全全局对象代理:window/document
12
- * - 默认仅允许常用的定时器、console、Math、Date、addEventListener(绑定原 window)
13
- * - document 仅允许 createElement/querySelector/querySelectorAll
11
+ * 统一的安全全局对象代理:window/document/navigator
12
+ * - window:仅允许常用的定时器、console、Math、Date、addEventListener、open(安全包装)、location(安全代理)
13
+ * - document:仅允许 createElement/querySelector/querySelectorAll
14
+ * - navigator:仅提供极少量低风险能力(clipboard.writeText、onLine、language、languages)
14
15
  * - 不允许随意访问未声明的属性,最小权限原则
15
16
  */
16
17
 
@@ -186,3 +187,48 @@ export function createSafeDocument(extra?: Record<string, any>) {
186
187
  },
187
188
  );
188
189
  }
190
+
191
+ export function createSafeNavigator(extra?: Record<string, any>) {
192
+ const nav: any = (typeof window !== 'undefined' && window.navigator) || undefined;
193
+
194
+ // 始终提供 clipboard 对象,避免可选链访问时抛错
195
+ const clipboard: Record<string, any> = {};
196
+ const writeText = nav?.clipboard?.writeText;
197
+ if (typeof writeText === 'function') {
198
+ clipboard.writeText = writeText.bind(nav.clipboard);
199
+ }
200
+
201
+ const allowed: Record<string, any> = {
202
+ clipboard,
203
+ };
204
+
205
+ // 只读常用标识,避免泄露更多指纹信息
206
+ Object.defineProperty(allowed, 'onLine', {
207
+ get: () => !!nav?.onLine,
208
+ enumerable: true,
209
+ configurable: false,
210
+ });
211
+ Object.defineProperty(allowed, 'language', {
212
+ get: () => nav?.language,
213
+ enumerable: true,
214
+ configurable: false,
215
+ });
216
+ Object.defineProperty(allowed, 'languages', {
217
+ get: () => (nav?.languages ? [...nav.languages] : undefined),
218
+ enumerable: true,
219
+ configurable: false,
220
+ });
221
+
222
+ // 允许额外注入(例如自定义能力的受控暴露)
223
+ Object.assign(allowed, extra || {});
224
+
225
+ return new Proxy(
226
+ {},
227
+ {
228
+ get(_t, prop: string) {
229
+ if (prop in allowed) return (allowed as any)[prop];
230
+ throw new Error(`Access to navigator property "${String(prop)}" is not allowed.`);
231
+ },
232
+ },
233
+ );
234
+ }
@@ -14,6 +14,7 @@ export type RecordRef = {
14
14
  id?: any; // primary key value
15
15
  filterByTk?: any; // alias for id
16
16
  dataSourceKey?: string;
17
+ sourceId?: any;
17
18
  fields?: string[];
18
19
  appends?: string[];
19
20
  record?: any; // full record object (try to infer pk from it)
@@ -7,15 +7,15 @@
7
7
  * For more information, please refer to: https://www.nocobase.com/agreement.
8
8
  */
9
9
 
10
- import type { FlowContext, PropertyMeta, PropertyMetaFactory } from '../flowContext';
11
- import type { JSONValue } from './params-resolvers';
12
- import type { Collection } from '../data-source';
13
- import { createCollectionContextMeta } from './createCollectionContextMeta';
14
- import { buildServerContextParams, type RecordRef, type ServerContextParams } from '../utils/serverContextParams';
15
10
  import {
16
11
  extractUsedVariableNames as _extractUsedVariableNames,
17
12
  extractUsedVariablePaths as _extractUsedVariablePaths,
18
- } from '@nocobase/utils/client';
13
+ } from '@nocobase/shared';
14
+ import type { Collection } from '../data-source';
15
+ import type { FlowContext, PropertyMeta, PropertyMetaFactory } from '../flowContext';
16
+ import { buildServerContextParams, type RecordRef, type ServerContextParams } from '../utils/serverContextParams';
17
+ import { createCollectionContextMeta } from './createCollectionContextMeta';
18
+ import type { JSONValue } from './params-resolvers';
19
19
 
20
20
  // Narrowest resource shape we rely on for inference
21
21
  type ResourceLike = {
@@ -45,6 +45,7 @@ function getCollection(ctx: FlowContext): CollectionShape | undefined {
45
45
  return undefined;
46
46
  }
47
47
 
48
+ // 从 FlowContext 中推断当前记录的 context params 信息
48
49
  export function inferRecordRef(ctx: FlowContext): RecordRef | undefined {
49
50
  const resource = getResource(ctx);
50
51
  const collectionObj = getCollection(ctx);
@@ -59,13 +60,26 @@ export function inferRecordRef(ctx: FlowContext): RecordRef | undefined {
59
60
  return { collection, dataSourceKey, filterByTk };
60
61
  }
61
62
 
63
+ // 从 FlowContext.view 中推断记录的 context params 信息
64
+ export function inferViewRecordRef(ctx: FlowContext): RecordRef | undefined {
65
+ const view = ctx.view;
66
+ if (!view) return undefined;
67
+ const inputArgs = (view as any)?.inputArgs || {};
68
+ const collection = inputArgs?.collectionName || (view as any)?.record?.collection;
69
+ const dataSourceKey = inputArgs?.dataSourceKey || (view as any)?.record?.dataSourceKey || 'main';
70
+ const filterByTk = inputArgs?.filterByTk || (view as any)?.record?.filterByTk;
71
+ const sourceId = inputArgs?.sourceId;
72
+ if (!collection || typeof filterByTk === 'undefined' || filterByTk === null) return undefined;
73
+ return { collection, dataSourceKey, filterByTk, sourceId };
74
+ }
75
+
62
76
  export function inferParentRecordRef(ctx: FlowContext): RecordRef | undefined {
63
77
  const resource = getResource(ctx);
64
78
  const dataSourceKey = getCollection(ctx)?.dataSourceKey || resource?.getDataSourceKey?.();
65
- const rn = resource?.getResourceName?.();
79
+ const resourceName = resource?.getResourceName?.();
66
80
  const sourceId = resource?.getSourceId?.();
67
- if (!rn || typeof sourceId === 'undefined' || sourceId === null) return undefined;
68
- const parts = String(rn).split('.');
81
+ if (!resourceName || typeof sourceId === 'undefined' || sourceId === null) return undefined;
82
+ const parts = String(resourceName).split('.');
69
83
  if (parts.length < 2) return undefined;
70
84
  return { collection: parts[0], dataSourceKey, filterByTk: sourceId };
71
85
  }
@@ -110,8 +124,11 @@ export function createRecordMetaFactory(
110
124
  export function createCurrentRecordMetaFactory(
111
125
  ctx: FlowContext,
112
126
  collectionAccessor: () => Collection | null,
127
+ options?: { title?: string },
113
128
  ): PropertyMetaFactory {
114
- const title = (ctx as any)?.t?.('Current record') || 'Current record';
129
+ const title = options?.title
130
+ ? ctx.t?.(options.title) || options.title
131
+ : ctx.t?.('Current record') || 'Current record';
115
132
  return createRecordMetaFactory(collectionAccessor, title, (c) => inferRecordRef(c));
116
133
  }
117
134
 
@@ -141,35 +158,30 @@ export async function collectContextParamsForTemplate(
141
158
  ctx: FlowContext,
142
159
  template: JSONValue,
143
160
  ): Promise<ServerContextParams | undefined> {
144
- try {
145
- const usage = _extractUsedVariablePaths(template) || {};
146
- const varNames = Object.keys(usage);
147
- if (!varNames.length) return undefined;
148
-
149
- const input: Record<string, any> = {};
150
- for (const key of varNames) {
151
- const opt = (ctx as any).getPropertyOptions?.(key);
152
- const meta: PropertyMeta | (() => Promise<PropertyMeta | null> | PropertyMeta | null) | undefined = opt?.meta;
153
- if (!meta) continue;
154
- let built: any;
155
- try {
156
- const resolvedMeta = typeof meta === 'function' ? await (meta as any)() : (meta as any);
157
- const builder = resolvedMeta?.buildVariablesParams;
158
- if (typeof builder === 'function') {
159
- built = await builder(ctx);
160
- }
161
- } catch (err) {
162
- // 忽略构建变量参数时的异常,继续处理其他变量
163
- // 使用 void 引用以避免 no-unused-vars,同时避免空代码块触发 no-empty
164
- void err;
165
- continue;
166
- }
167
- if (built) {
168
- input[key] = built;
161
+ const usage = _extractUsedVariablePaths(template) || {};
162
+ const varNames = Object.keys(usage);
163
+ if (!varNames.length) return undefined;
164
+
165
+ const input: Record<string, any> = {};
166
+ for (const key of varNames) {
167
+ const opt = ctx.getPropertyOptions?.(key);
168
+ const meta: PropertyMeta | (() => Promise<PropertyMeta | null> | PropertyMeta | null) | undefined = opt?.meta;
169
+ if (!meta) continue;
170
+ let built: any;
171
+ try {
172
+ const resolvedMeta = typeof meta === 'function' ? await (meta as any)() : (meta as any);
173
+ const builder = resolvedMeta?.buildVariablesParams;
174
+ if (typeof builder === 'function') {
175
+ built = await builder(ctx);
169
176
  }
177
+ } catch (err) {
178
+ // 忽略构建变量参数时的异常,继续处理其他变量
179
+ void err;
180
+ continue;
181
+ }
182
+ if (built) {
183
+ input[key] = built;
170
184
  }
171
- return buildServerContextParams(ctx, input);
172
- } catch (_) {
173
- return undefined;
174
185
  }
186
+ return buildServerContextParams(ctx, input);
175
187
  }
@@ -24,7 +24,7 @@ export const PageComponent = forwardRef((props: any, ref) => {
24
24
  hidden,
25
25
  title: _title,
26
26
  styles = {},
27
- zIndex,
27
+ zIndex = 4, // 这个默认值是为了防止表格的阴影显示到子页面上面
28
28
  } = mergedProps;
29
29
  const closedRef = useRef(false);
30
30
  const flowEngine = useFlowEngine();