@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
@@ -0,0 +1,41 @@
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
+ /**
11
+ * 递归清理筛选对象中的“空值”。
12
+ *
13
+ * 规则:
14
+ * - 移除:`null`、`undefined`、空字符串 `''`、空数组 `[]`、空对象 `{}`;
15
+ * - 保留:`false`、`0` 等有意义的“假值”。
16
+ *
17
+ * 注意:当清理后整体变为空结构时,返回 `undefined`,用于表示无需下发该条件。
18
+ *
19
+ * @param input 任意筛选对象/数组/原始值
20
+ * @returns 清理后的对象;若为空则返回 `undefined`
21
+ */
22
+ export function pruneFilter<T = any>(input: T): T | undefined {
23
+ // Arrays: prune items and drop empty arrays
24
+ if (Array.isArray(input)) {
25
+ const arr = (input as unknown[]).map((v) => pruneFilter(v)).filter((v) => v !== undefined);
26
+ return (arr.length ? (arr as unknown as T) : undefined) as any;
27
+ }
28
+
29
+ // Objects: prune properties and drop empty objects
30
+ if (input && typeof input === 'object') {
31
+ const out: Record<string, any> = {};
32
+ Object.keys(input as Record<string, any>).forEach((k) => {
33
+ const v = pruneFilter((input as any)[k]);
34
+ if (v !== undefined) out[k] = v;
35
+ });
36
+ return (Object.keys(out).length ? (out as unknown as T) : undefined) as any;
37
+ }
38
+
39
+ // Primitives: keep false/0; drop null/undefined/''
40
+ return input === null || input === undefined || (typeof input === 'string' && input === '') ? undefined : input;
41
+ }
@@ -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
+ }
@@ -181,7 +181,7 @@ export async function resolveStepUiSchema<TModel extends FlowModel = FlowModel>(
181
181
 
182
182
  if (step.use) {
183
183
  try {
184
- const action = model.flowEngine?.getAction?.(step.use);
184
+ const action = model.getAction?.(step.use);
185
185
  if (action && action.uiSchema) {
186
186
  stepUiSchema = stepUiSchema || action.uiSchema;
187
187
  }
@@ -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)
@@ -27,11 +27,16 @@ export function getT(model: FlowModel): (key: string, options?: any) => string {
27
27
  return (key: string) => key;
28
28
  }
29
29
 
30
- export function escapeT(text: TFuncKey | TFuncKey[], options?: TOptions) {
30
+ export function tExpr(text: TFuncKey | TFuncKey[], options?: TOptions) {
31
31
  if (options) {
32
32
  return `{{t(${JSON.stringify(text)}, ${JSON.stringify(options)})}}`;
33
33
  }
34
34
  return `{{t(${JSON.stringify(text)})}}`;
35
35
  }
36
36
 
37
- export { escapeT as tExpr };
37
+ /**
38
+ * @deprecated use tExpr from `@nocobase/flow-engine` instead
39
+ */
40
+ export function escapeT(text: TFuncKey | TFuncKey[], options?: TOptions) {
41
+ return tExpr(text, options);
42
+ }
@@ -7,15 +7,17 @@
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 { createAssociationSubpathResolver } from './associationObjectVariable';
19
+ import type { JSONValue } from './params-resolvers';
20
+ import _ from 'lodash';
19
21
 
20
22
  // Narrowest resource shape we rely on for inference
21
23
  type ResourceLike = {
@@ -45,6 +47,7 @@ function getCollection(ctx: FlowContext): CollectionShape | undefined {
45
47
  return undefined;
46
48
  }
47
49
 
50
+ // 从 FlowContext 中推断当前记录的 context params 信息
48
51
  export function inferRecordRef(ctx: FlowContext): RecordRef | undefined {
49
52
  const resource = getResource(ctx);
50
53
  const collectionObj = getCollection(ctx);
@@ -59,13 +62,130 @@ export function inferRecordRef(ctx: FlowContext): RecordRef | undefined {
59
62
  return { collection, dataSourceKey, filterByTk };
60
63
  }
61
64
 
65
+ // 从 FlowContext.view 中推断记录的 context params 信息
66
+ export function inferViewRecordRef(ctx: FlowContext): RecordRef | undefined {
67
+ const view = ctx.view;
68
+ if (!view) return undefined;
69
+ const inputArgs = (view as any)?.inputArgs || {};
70
+ const collection = inputArgs?.collectionName || (view as any)?.record?.collection;
71
+ const dataSourceKey = inputArgs?.dataSourceKey || (view as any)?.record?.dataSourceKey || 'main';
72
+ const filterByTk = inputArgs?.filterByTk || (view as any)?.record?.filterByTk;
73
+ const sourceId = inputArgs?.sourceId;
74
+ if (!collection || typeof filterByTk === 'undefined' || filterByTk === null) return undefined;
75
+ return { collection, dataSourceKey, filterByTk, sourceId };
76
+ }
77
+
78
+ // 统一视图场景中“视图记录”的本地复用逻辑:
79
+ // - 当视图 inputArgs.filterByTk 与父 FlowContext.record.filterByTk 一致时,
80
+ // 认为视图正在查看同一条记录,此时返回父记录的深拷贝作为 view.record;
81
+ // - 否则视为不同记录,不复用父记录(返回 undefined,让后续逻辑走服务端解析)。
82
+
83
+ export function getViewRecordFromParent(flowContext: FlowContext, viewContext: FlowContext): unknown {
84
+ const parentRecord = flowContext.inputArgs?.record;
85
+ const parentTk = flowContext.collection?.filterTargetKey;
86
+ if (!parentRecord || !parentTk) return undefined;
87
+
88
+ const view = viewContext.view;
89
+ const viewFilterByTk = view?.inputArgs?.filterByTk;
90
+ const recordFilterByTk = parentRecord[parentTk];
91
+
92
+ // 仅当视图的 filterByTk 与父记录的 filterByTk 一致时,才复用父记录,
93
+ // 否则视为不同记录,不返回本地记录(统一走服务端解析)。
94
+ if (viewFilterByTk == null || recordFilterByTk == null) return undefined;
95
+ if (viewFilterByTk !== recordFilterByTk) return undefined;
96
+
97
+ return _.cloneDeep(parentRecord);
98
+ }
99
+
100
+ // 针对视图场景(Page/Dialog/Drawer),创建用于 view.resolveOnServer 的判定函数
101
+ export function createViewRecordResolveOnServer(
102
+ ctx: FlowContext,
103
+ getLocalRecord: () => unknown,
104
+ ): (subPath: string) => boolean {
105
+ return (p: string) => {
106
+ if (!(p === 'record' || p.startsWith('record.'))) return false;
107
+ const local = getLocalRecord();
108
+ // 前端没有可用记录数据:统一走服务端
109
+ if (!local) return true;
110
+
111
+ // 直接访问整个 record 对象,使用前端值
112
+ if (p === 'record') return false;
113
+
114
+ // 仅在访问关联字段子路径时走服务端;非关联字段使用前端值
115
+ const ref = inferViewRecordRef(ctx);
116
+ const colName = ref?.collection;
117
+ const dsKey = ref?.dataSourceKey || 'main';
118
+ if (!colName) return true; // 未能推断集合,保守起见走服务端
119
+ const ds = (
120
+ ctx as FlowContext & { dataSourceManager?: { getDataSource?: (key: string) => any } }
121
+ ).dataSourceManager?.getDataSource?.(dsKey);
122
+ const collection = ds?.collectionManager?.getCollection?.(colName);
123
+ if (!collection) return true; // 未找到集合定义,保守走服务端
124
+
125
+ const resolver = createAssociationSubpathResolver(
126
+ () => collection as Collection,
127
+ () => local,
128
+ );
129
+ const subPath = p.startsWith('record.') ? p.slice('record.'.length) : '';
130
+ if (!subPath) return false;
131
+ return resolver(subPath);
132
+ };
133
+ }
134
+
135
+ /**
136
+ * 创建一个用于 “ctx.record” 变量的 resolveOnServer 判定函数:
137
+ * - 若本地 record 不存在:统一走服务端;
138
+ * - 若本地 record 存在:
139
+ * - 访问空子路径("{{ ctx.record }}")时使用本地值,不走服务端;
140
+ * - 访问非关联字段(如 id/title):使用本地值;
141
+ * - 访问关联字段:
142
+ * - 若本地该字段无值(undefined/null),则交给服务端解析(无论是 "author" 还是 "author.name");
143
+ * - 若本地已有值,则仅在访问子属性且本地缺少该子属性值时交给服务端。
144
+ */
145
+ export function createRecordResolveOnServerWithLocal(
146
+ collectionAccessor: () => Collection | null,
147
+ valueAccessor: () => unknown,
148
+ ): (subPath: string) => boolean {
149
+ const assocSubpathResolver = createAssociationSubpathResolver(collectionAccessor, () => valueAccessor());
150
+ return (p: string) => {
151
+ const local = valueAccessor();
152
+ if (!local) return true;
153
+ if (!p) return false;
154
+
155
+ const collection = collectionAccessor() as any;
156
+
157
+ // 访问关联字段整体:当本地该字段无值时,统一交给服务端
158
+ if (!p.includes('.')) {
159
+ const name = p;
160
+ let field: any;
161
+ if (collection) {
162
+ if (typeof collection.getField === 'function') {
163
+ field = collection.getField(name);
164
+ }
165
+ if (!field && typeof collection.getFields === 'function') {
166
+ const fields = collection.getFields() || [];
167
+ field = fields.find((f: any) => f?.name === name);
168
+ }
169
+ }
170
+ const isAssoc = !!field?.isAssociationField?.();
171
+ if (!isAssoc) return false;
172
+ const value = (local as any)?.[name];
173
+ if (value === undefined || value === null) return true;
174
+ return false;
175
+ }
176
+
177
+ // 访问关联字段子属性:复用 associationSubpathResolver 的“本地优先 + 关联字段才走服务端”逻辑
178
+ return assocSubpathResolver(p);
179
+ };
180
+ }
181
+
62
182
  export function inferParentRecordRef(ctx: FlowContext): RecordRef | undefined {
63
183
  const resource = getResource(ctx);
64
184
  const dataSourceKey = getCollection(ctx)?.dataSourceKey || resource?.getDataSourceKey?.();
65
- const rn = resource?.getResourceName?.();
185
+ const resourceName = resource?.getResourceName?.();
66
186
  const sourceId = resource?.getSourceId?.();
67
- if (!rn || typeof sourceId === 'undefined' || sourceId === null) return undefined;
68
- const parts = String(rn).split('.');
187
+ if (!resourceName || typeof sourceId === 'undefined' || sourceId === null) return undefined;
188
+ const parts = String(resourceName).split('.');
69
189
  if (parts.length < 2) return undefined;
70
190
  return { collection: parts[0], dataSourceKey, filterByTk: sourceId };
71
191
  }
@@ -110,8 +230,11 @@ export function createRecordMetaFactory(
110
230
  export function createCurrentRecordMetaFactory(
111
231
  ctx: FlowContext,
112
232
  collectionAccessor: () => Collection | null,
233
+ options?: { title?: string },
113
234
  ): PropertyMetaFactory {
114
- const title = (ctx as any)?.t?.('Current record') || 'Current record';
235
+ const title = options?.title
236
+ ? ctx.t?.(options.title) || options.title
237
+ : ctx.t?.('Current record') || 'Current record';
115
238
  return createRecordMetaFactory(collectionAccessor, title, (c) => inferRecordRef(c));
116
239
  }
117
240
 
@@ -141,35 +264,30 @@ export async function collectContextParamsForTemplate(
141
264
  ctx: FlowContext,
142
265
  template: JSONValue,
143
266
  ): 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;
267
+ const usage = _extractUsedVariablePaths(template) || {};
268
+ const varNames = Object.keys(usage);
269
+ if (!varNames.length) return undefined;
270
+
271
+ const input: Record<string, any> = {};
272
+ for (const key of varNames) {
273
+ const opt = ctx.getPropertyOptions?.(key);
274
+ const meta: PropertyMeta | (() => Promise<PropertyMeta | null> | PropertyMeta | null) | undefined = opt?.meta;
275
+ if (!meta) continue;
276
+ let built: any;
277
+ try {
278
+ const resolvedMeta = typeof meta === 'function' ? await (meta as any)() : (meta as any);
279
+ const builder = resolvedMeta?.buildVariablesParams;
280
+ if (typeof builder === 'function') {
281
+ built = await builder(ctx);
169
282
  }
283
+ } catch (err) {
284
+ // 忽略构建变量参数时的异常,继续处理其他变量
285
+ void err;
286
+ continue;
287
+ }
288
+ if (built) {
289
+ input[key] = built;
170
290
  }
171
- return buildServerContextParams(ctx, input);
172
- } catch (_) {
173
- return undefined;
174
291
  }
292
+ return buildServerContextParams(ctx, input);
175
293
  }
@@ -10,12 +10,13 @@
10
10
  // components/drawer/useDrawer/DrawerComponent.tsx
11
11
  import { Drawer } from 'antd';
12
12
  import * as React from 'react';
13
+ import { MobilePopup } from '../components/MobilePopup';
13
14
 
14
15
  const DrawerComponent = React.forwardRef((props: any, ref) => {
15
- const { children, footer: initialFooter, title, extra, hidden, ...drawerProps } = props;
16
+ const { children, footer: initialFooter, title, extra, hidden, isMobile, ...drawerProps } = props;
16
17
  const [open, setOpen] = React.useState(true);
17
18
  const [footer, setFooter] = React.useState(() => initialFooter);
18
- const [header, setHeader] = React.useState({ title, extra });
19
+ const [header, setHeader] = React.useState({ title, extra, ...drawerProps.header });
19
20
 
20
21
  React.useImperativeHandle(
21
22
  ref,
@@ -46,6 +47,24 @@ const DrawerComponent = React.forwardRef((props: any, ref) => {
46
47
  return document.querySelector('#nocobase-app-container');
47
48
  }, []);
48
49
 
50
+ if (isMobile) {
51
+ return (
52
+ <MobilePopup
53
+ className={hidden ? 'nb-hidden' : ''}
54
+ visible={open}
55
+ {...drawerProps}
56
+ footer={footer}
57
+ {...header}
58
+ onClose={() => {
59
+ setOpen(false);
60
+ drawerProps.afterClose?.();
61
+ }}
62
+ >
63
+ {children}
64
+ </MobilePopup>
65
+ );
66
+ }
67
+
49
68
  return (
50
69
  <Drawer
51
70
  rootClassName={hidden ? 'nb-hidden' : ''}
@@ -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();
@@ -8,16 +8,21 @@
8
8
  */
9
9
 
10
10
  import { FlowEngineContext } from '../flowContext';
11
-
12
- interface ViewParam {
13
- /** 视图唯一标识符,一般为某个 Model 实例的 uid */
14
- viewUid?: string;
15
- /** 标签页唯一标识符 */
16
- tabUid?: string;
17
- /** 弹窗记录的 id */
18
- filterByTk?: string;
19
- /** source Id */
20
- sourceId?: string;
11
+ import { ViewParam as SharedViewParam } from '../utils';
12
+
13
+ type ViewParam = Omit<SharedViewParam, 'viewUid'> & { viewUid?: string };
14
+
15
+ function encodeFilterByTk(val: SharedViewParam['filterByTk']): string {
16
+ if (val === undefined || val === null) return '';
17
+ // 1.x 兼容:对象按 key1=v1&key2=v2 拼接后整体 encodeURIComponent
18
+ if (val && typeof val === 'object' && !Array.isArray(val)) {
19
+ const pairs = Object.entries(val).map(([k, v]) => {
20
+ return `${encodeURIComponent(String(k))}=${encodeURIComponent(String(v))}`;
21
+ });
22
+ return encodeURIComponent(pairs.join('&'));
23
+ }
24
+ // 其它情况按原单值编码(字符串)
25
+ return encodeURIComponent(String(val));
21
26
  }
22
27
 
23
28
  /**
@@ -53,8 +58,11 @@ export function generatePathnameFromViewParams(viewParams: ViewParam[]): string
53
58
  if (viewParam.tabUid) {
54
59
  segments.push('tab', viewParam.tabUid);
55
60
  }
56
- if (viewParam.filterByTk) {
57
- segments.push('filterbytk', viewParam.filterByTk);
61
+ if (viewParam.filterByTk != null) {
62
+ const encoded = encodeFilterByTk(viewParam.filterByTk);
63
+ if (encoded) {
64
+ segments.push('filterbytk', encoded);
65
+ }
58
66
  }
59
67
  if (viewParam.sourceId) {
60
68
  segments.push('sourceid', viewParam.sourceId);
@@ -173,6 +173,16 @@ describe('generatePathnameFromViewParams', () => {
173
173
  );
174
174
  });
175
175
 
176
+ it('should encode object filterByTk as encoded key-value string', () => {
177
+ const path = generatePathnameFromViewParams([{ viewUid: 'xxx', filterByTk: { id: 1, tenant: 'ac' } }]);
178
+ expect(path).toBe('/admin/xxx/filterbytk/' + encodeURIComponent('id=1&tenant=ac'));
179
+ });
180
+
181
+ it('should omit filterByTk segment for empty string or when absent', () => {
182
+ expect(generatePathnameFromViewParams([{ viewUid: 'xxx' }])).toBe('/admin/xxx');
183
+ expect(generatePathnameFromViewParams([{ viewUid: 'xxx', filterByTk: '' }])).toBe('/admin/xxx');
184
+ });
185
+
176
186
  it('should match parsePathnameToViewParams test cases', () => {
177
187
  // Test cases from parsePathnameToViewParams.test.ts
178
188
  expect(generatePathnameFromViewParams([{ viewUid: 'xxx' }])).toBe('/admin/xxx');