@nocobase/flow-engine 2.0.0-alpha.9 → 2.0.0-beta.2

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 (305) hide show
  1. package/lib/BlockScopedFlowEngine.d.ts +23 -0
  2. package/lib/BlockScopedFlowEngine.js +92 -0
  3. package/lib/FlowDefinition.d.ts +6 -4
  4. package/lib/JSRunner.js +3 -0
  5. package/lib/ViewScopedFlowEngine.js +15 -1
  6. package/lib/acl/Acl.d.ts +12 -12
  7. package/lib/acl/Acl.js +78 -30
  8. package/lib/components/DynamicFlowsEditor.js +2 -4
  9. package/lib/components/FieldModelRenderer.js +10 -8
  10. package/lib/components/FieldSkeleton.d.ts +10 -0
  11. package/lib/components/FieldSkeleton.js +64 -0
  12. package/lib/components/FlowContextSelector.js +19 -3
  13. package/lib/components/FlowModelRenderer.d.ts +2 -1
  14. package/lib/components/FlowModelRenderer.js +34 -12
  15. package/lib/components/FormItem.js +5 -1
  16. package/lib/components/MobilePopup.d.ts +20 -0
  17. package/lib/components/MobilePopup.js +102 -0
  18. package/lib/components/MobilePopup.style.d.ts +17 -0
  19. package/lib/components/MobilePopup.style.js +186 -0
  20. package/lib/components/common/withFlowDesignMode.d.ts +1 -1
  21. package/lib/components/common/withFlowDesignMode.js +5 -5
  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 +71 -53
  25. package/lib/components/settings/wrappers/component/SelectWithTitle.d.ts +19 -0
  26. package/lib/components/settings/wrappers/component/SelectWithTitle.js +136 -0
  27. package/lib/components/settings/wrappers/component/SwitchWithTitle.d.ts +10 -0
  28. package/lib/components/settings/wrappers/component/SwitchWithTitle.js +110 -0
  29. package/lib/components/settings/wrappers/contextual/DefaultSettingsIcon.js +221 -93
  30. package/lib/components/settings/wrappers/contextual/FlowsContextMenu.js +71 -54
  31. package/lib/components/settings/wrappers/contextual/FlowsFloatContextMenu.d.ts +2 -2
  32. package/lib/components/settings/wrappers/contextual/FlowsFloatContextMenu.js +63 -23
  33. package/lib/components/settings/wrappers/contextual/StepSettingsDialog.js +11 -6
  34. package/lib/components/settings/wrappers/embedded/FlowSettings.js +42 -28
  35. package/lib/components/settings/wrappers/embedded/FlowsSettings.js +3 -3
  36. package/lib/components/settings/wrappers/embedded/FlowsSettingsContent.js +52 -32
  37. package/lib/components/subModel/AddSubModelButton.d.ts +7 -0
  38. package/lib/components/subModel/AddSubModelButton.js +78 -8
  39. package/lib/components/subModel/LazyDropdown.js +14 -15
  40. package/lib/components/subModel/utils.d.ts +1 -1
  41. package/lib/components/subModel/utils.js +21 -11
  42. package/lib/components/variables/VariableInput.js +5 -3
  43. package/lib/components/variables/types.d.ts +2 -0
  44. package/lib/components/variables/utils.js +4 -2
  45. package/lib/data-source/index.d.ts +43 -4
  46. package/lib/data-source/index.js +104 -11
  47. package/lib/data-source/jioToJoiSchema.js +1 -0
  48. package/lib/emitter.d.ts +6 -0
  49. package/lib/emitter.js +12 -0
  50. package/lib/executor/FlowExecutor.js +48 -7
  51. package/lib/flow-registry/GlobalFlowRegistry.d.ts +1 -0
  52. package/lib/flow-registry/GlobalFlowRegistry.js +3 -0
  53. package/lib/flow-registry/InstanceFlowRegistry.d.ts +1 -0
  54. package/lib/flow-registry/InstanceFlowRegistry.js +3 -0
  55. package/lib/flowContext.d.ts +6 -0
  56. package/lib/flowContext.js +111 -30
  57. package/lib/flowEngine.d.ts +49 -0
  58. package/lib/flowEngine.js +265 -10
  59. package/lib/flowSettings.d.ts +4 -3
  60. package/lib/flowSettings.js +33 -11
  61. package/lib/hooks/useApplyAutoFlows.d.ts +1 -0
  62. package/lib/hooks/useApplyAutoFlows.js +2 -2
  63. package/lib/index.d.ts +4 -2
  64. package/lib/index.js +11 -5
  65. package/lib/locale/de-DE.json +62 -0
  66. package/lib/locale/en-US.json +57 -45
  67. package/lib/locale/es-ES.json +62 -0
  68. package/lib/locale/fr-FR.json +62 -0
  69. package/lib/locale/hu-HU.json +62 -0
  70. package/lib/locale/id-ID.json +62 -0
  71. package/lib/locale/index.d.ts +114 -90
  72. package/lib/locale/it-IT.json +62 -0
  73. package/lib/locale/ja-JP.json +62 -0
  74. package/lib/locale/ko-KR.json +62 -0
  75. package/lib/locale/nl-NL.json +62 -0
  76. package/lib/locale/pt-BR.json +62 -0
  77. package/lib/locale/ru-RU.json +62 -0
  78. package/lib/locale/tr-TR.json +62 -0
  79. package/lib/locale/uk-UA.json +62 -0
  80. package/lib/locale/vi-VN.json +62 -0
  81. package/lib/locale/zh-CN.json +58 -46
  82. package/lib/locale/zh-TW.json +62 -0
  83. package/lib/models/CollectionFieldModel.d.ts +6 -2
  84. package/lib/models/CollectionFieldModel.js +60 -14
  85. package/lib/models/flowModel.d.ts +43 -4
  86. package/lib/models/flowModel.js +128 -26
  87. package/lib/models/forkFlowModel.d.ts +6 -2
  88. package/lib/models/forkFlowModel.js +9 -2
  89. package/lib/provider.d.ts +3 -1
  90. package/lib/provider.js +4 -3
  91. package/lib/reactive/index.d.ts +10 -0
  92. package/lib/reactive/index.js +41 -0
  93. package/lib/reactive/observer.d.ts +19 -0
  94. package/lib/reactive/observer.js +109 -0
  95. package/lib/resources/baseRecordResource.d.ts +1 -0
  96. package/lib/resources/baseRecordResource.js +14 -3
  97. package/lib/resources/multiRecordResource.d.ts +4 -2
  98. package/lib/resources/multiRecordResource.js +15 -6
  99. package/lib/resources/singleRecordResource.js +6 -3
  100. package/lib/resources/sqlResource.d.ts +1 -0
  101. package/lib/resources/sqlResource.js +22 -25
  102. package/lib/runjs-context/contexts/base.js +42 -6
  103. package/lib/runjs-context/snippets/global/clipboard-copy-text.snippet.d.ts +11 -0
  104. package/lib/runjs-context/snippets/global/clipboard-copy-text.snippet.js +61 -0
  105. package/lib/runjs-context/snippets/index.js +3 -0
  106. package/lib/runjs-context/snippets/scene/block/render-antd-icons.snippet.d.ts +11 -0
  107. package/lib/runjs-context/snippets/scene/block/render-antd-icons.snippet.js +65 -0
  108. package/lib/runjs-context/snippets/scene/block/render-button-handler.snippet.js +6 -4
  109. package/lib/runjs-context/snippets/scene/block/render-info-card.snippet.js +15 -16
  110. package/lib/runjs-context/snippets/scene/block/render-react-jsx.snippet.d.ts +11 -0
  111. package/lib/runjs-context/snippets/scene/block/render-react-jsx.snippet.js +58 -0
  112. package/lib/runjs-context/snippets/scene/block/render-react.snippet.js +7 -7
  113. package/lib/runjs-context/snippets/scene/block/render-statistics.snippet.js +24 -29
  114. package/lib/runjs-context/snippets/scene/block/render-timeline.snippet.js +20 -21
  115. package/lib/scheduler/ModelOperationScheduler.d.ts +51 -0
  116. package/lib/scheduler/ModelOperationScheduler.js +262 -0
  117. package/lib/types.d.ts +42 -7
  118. package/lib/types.js +4 -3
  119. package/lib/utils/associationObjectVariable.d.ts +32 -0
  120. package/lib/utils/associationObjectVariable.js +157 -0
  121. package/lib/utils/createCollectionContextMeta.d.ts +1 -1
  122. package/lib/utils/createCollectionContextMeta.js +8 -4
  123. package/lib/utils/createEphemeralContext.d.ts +13 -0
  124. package/lib/utils/createEphemeralContext.js +140 -0
  125. package/lib/utils/flows.d.ts +10 -0
  126. package/lib/utils/flows.js +48 -0
  127. package/lib/utils/index.d.ts +7 -3
  128. package/lib/utils/index.js +20 -0
  129. package/lib/utils/jsxTransform.d.ts +15 -0
  130. package/lib/utils/jsxTransform.js +68 -0
  131. package/lib/utils/params-resolvers.js +3 -3
  132. package/lib/utils/parsePathnameToViewParams.d.ts +1 -1
  133. package/lib/utils/parsePathnameToViewParams.js +41 -5
  134. package/lib/utils/pruneFilter.d.ts +21 -0
  135. package/lib/utils/pruneFilter.js +52 -0
  136. package/lib/utils/safeGlobals.d.ts +5 -3
  137. package/lib/utils/safeGlobals.js +42 -1
  138. package/lib/utils/schema-utils.d.ts +6 -0
  139. package/lib/utils/schema-utils.js +71 -6
  140. package/lib/utils/serverContextParams.d.ts +3 -0
  141. package/lib/utils/serverContextParams.js +2 -0
  142. package/lib/utils/translation.d.ts +4 -1
  143. package/lib/utils/translation.js +6 -2
  144. package/lib/utils/variablesParams.d.ts +21 -5
  145. package/lib/utils/variablesParams.js +103 -34
  146. package/lib/views/DialogComponent.js +1 -5
  147. package/lib/views/DrawerComponent.js +18 -9
  148. package/lib/views/PageComponent.js +3 -4
  149. package/lib/views/ViewNavigation.d.ts +11 -15
  150. package/lib/views/ViewNavigation.js +37 -19
  151. package/lib/views/createViewMeta.d.ts +3 -2
  152. package/lib/views/createViewMeta.js +164 -53
  153. package/lib/views/useDialog.d.ts +2 -1
  154. package/lib/views/useDialog.js +36 -30
  155. package/lib/views/useDrawer.d.ts +2 -1
  156. package/lib/views/useDrawer.js +33 -26
  157. package/lib/views/usePage.d.ts +2 -1
  158. package/lib/views/usePage.js +40 -29
  159. package/package.json +6 -3
  160. package/src/BlockScopedFlowEngine.ts +88 -0
  161. package/src/JSRunner.ts +3 -0
  162. package/src/ViewScopedFlowEngine.ts +16 -0
  163. package/src/__tests__/JSRunner.test.ts +62 -53
  164. package/src/__tests__/blockScopedFlowEngine.test.ts +154 -0
  165. package/src/__tests__/createViewMeta.popup.test.ts +142 -0
  166. package/src/__tests__/flow-engine.test.ts +3 -0
  167. package/src/__tests__/flowContext.test.ts +70 -0
  168. package/src/__tests__/flowEngine.destroyModel.test.ts +74 -0
  169. package/src/__tests__/flowEngine.moveModel.test.ts +43 -0
  170. package/src/__tests__/flowEngine.removeModel.test.ts +72 -0
  171. package/src/__tests__/flowEngine.saveModel.test.ts +4 -0
  172. package/src/__tests__/flowModel.openView.navigation.test.ts +3 -2
  173. package/src/__tests__/flowSettings.open.test.tsx +2 -0
  174. package/src/__tests__/flowSettings.test.ts +2 -0
  175. package/src/__tests__/globalFlowRegistry.test.ts +1 -1
  176. package/src/__tests__/modelOperationScheduler.test.ts +346 -0
  177. package/src/__tests__/objectVariable.test.ts +464 -0
  178. package/src/__tests__/runjsRuntimeFeatures.test.ts +12 -0
  179. package/src/__tests__/viewScopedFlowEngine.test.ts +98 -0
  180. package/src/acl/Acl.tsx +85 -31
  181. package/src/acl/__tests__/Acl.test.tsx +43 -1
  182. package/src/components/DynamicFlowsEditor.tsx +0 -10
  183. package/src/components/FieldModelRenderer.tsx +15 -8
  184. package/src/components/FieldSkeleton.tsx +27 -0
  185. package/src/components/FlowContextSelector.tsx +20 -2
  186. package/src/components/FlowModelRenderer.tsx +46 -12
  187. package/src/components/FormItem.tsx +8 -1
  188. package/src/components/MobilePopup.style.ts +220 -0
  189. package/src/components/MobilePopup.tsx +86 -0
  190. package/src/components/__tests__/FlowModelRenderer.test.tsx +89 -0
  191. package/src/components/__tests__/flow-model-render-error-fallback.test.tsx +1 -1
  192. package/src/components/common/withFlowDesignMode.tsx +5 -5
  193. package/src/components/index.ts +1 -0
  194. package/src/components/settings/independents/dropdown/FlowsDropdownButton.tsx +34 -17
  195. package/src/components/settings/wrappers/component/SelectWithTitle.tsx +110 -0
  196. package/src/components/settings/wrappers/component/SwitchWithTitle.tsx +82 -0
  197. package/src/components/settings/wrappers/contextual/DefaultSettingsIcon.tsx +260 -121
  198. package/src/components/settings/wrappers/contextual/FlowsContextMenu.tsx +34 -18
  199. package/src/components/settings/wrappers/contextual/FlowsFloatContextMenu.tsx +56 -18
  200. package/src/components/settings/wrappers/contextual/StepSettings.tsx +1 -2
  201. package/src/components/settings/wrappers/contextual/StepSettingsDialog.tsx +12 -6
  202. package/src/components/settings/wrappers/contextual/__tests__/DefaultSettingsIcon.test.tsx +565 -0
  203. package/src/components/settings/wrappers/embedded/FlowSettings.tsx +47 -35
  204. package/src/components/settings/wrappers/embedded/FlowsSettings.tsx +1 -1
  205. package/src/components/settings/wrappers/embedded/FlowsSettingsContent.tsx +64 -42
  206. package/src/components/subModel/AddSubModelButton.tsx +104 -9
  207. package/src/components/subModel/LazyDropdown.tsx +14 -14
  208. package/src/components/subModel/__tests__/AddSubModelButton.test.tsx +168 -7
  209. package/src/components/subModel/__tests__/utils.test.ts +12 -12
  210. package/src/components/subModel/utils.ts +25 -6
  211. package/src/components/variables/VariableInput.tsx +5 -3
  212. package/src/components/variables/types.ts +2 -0
  213. package/src/components/variables/utils.ts +7 -3
  214. package/src/data-source/index.ts +169 -11
  215. package/src/data-source/jioToJoiSchema.ts +1 -0
  216. package/src/emitter.ts +14 -0
  217. package/src/executor/FlowExecutor.ts +56 -8
  218. package/src/executor/__tests__/ctx-defs-injection.test.ts +197 -0
  219. package/src/flow-registry/GlobalFlowRegistry.ts +1 -0
  220. package/src/flow-registry/InstanceFlowRegistry.ts +1 -0
  221. package/src/flow-registry/__tests__/globalFlowRegistry.test.ts +54 -0
  222. package/src/flowContext.ts +144 -29
  223. package/src/flowEngine.ts +328 -8
  224. package/src/flowSettings.ts +47 -19
  225. package/src/hooks/useApplyAutoFlows.ts +3 -3
  226. package/src/index.ts +4 -2
  227. package/src/locale/de-DE.json +62 -0
  228. package/src/locale/en-US.json +57 -45
  229. package/src/locale/es-ES.json +62 -0
  230. package/src/locale/fr-FR.json +62 -0
  231. package/src/locale/hu-HU.json +62 -0
  232. package/src/locale/id-ID.json +62 -0
  233. package/src/locale/it-IT.json +62 -0
  234. package/src/locale/ja-JP.json +62 -0
  235. package/src/locale/ko-KR.json +62 -0
  236. package/src/locale/nl-NL.json +62 -0
  237. package/src/locale/pt-BR.json +62 -0
  238. package/src/locale/ru-RU.json +62 -0
  239. package/src/locale/tr-TR.json +62 -0
  240. package/src/locale/uk-UA.json +62 -0
  241. package/src/locale/vi-VN.json +62 -0
  242. package/src/locale/zh-CN.json +58 -46
  243. package/src/locale/zh-TW.json +62 -0
  244. package/src/models/CollectionFieldModel.tsx +79 -17
  245. package/src/models/__tests__/dispatchEvent.behavior.test.ts +169 -0
  246. package/src/models/__tests__/flowEngine.resolveUse.test.ts +170 -0
  247. package/src/models/__tests__/flowModel.getFlows.sort.test.ts +29 -5
  248. package/src/models/__tests__/flowModel.scheduleModelOperation.test.tsx +129 -0
  249. package/src/models/__tests__/flowModel.test.ts +65 -27
  250. package/src/models/__tests__/forkFlowModel.test.ts +40 -7
  251. package/src/models/flowModel.tsx +192 -30
  252. package/src/models/forkFlowModel.ts +11 -3
  253. package/src/provider.tsx +5 -5
  254. package/src/reactive/__tests__/observer.test.tsx +211 -0
  255. package/src/reactive/index.ts +11 -0
  256. package/src/reactive/observer.tsx +101 -0
  257. package/src/resources/baseRecordResource.ts +15 -3
  258. package/src/resources/multiRecordResource.ts +17 -8
  259. package/src/resources/singleRecordResource.ts +6 -3
  260. package/src/resources/sqlResource.ts +22 -26
  261. package/src/runjs-context/contexts/base.ts +47 -6
  262. package/src/runjs-context/snippets/global/clipboard-copy-text.snippet.ts +42 -0
  263. package/src/runjs-context/snippets/index.ts +3 -0
  264. package/src/runjs-context/snippets/scene/block/render-antd-icons.snippet.ts +46 -0
  265. package/src/runjs-context/snippets/scene/block/render-button-handler.snippet.ts +6 -4
  266. package/src/runjs-context/snippets/scene/block/render-info-card.snippet.ts +15 -16
  267. package/src/runjs-context/snippets/scene/block/render-react-jsx.snippet.ts +39 -0
  268. package/src/runjs-context/snippets/scene/block/render-react.snippet.ts +7 -7
  269. package/src/runjs-context/snippets/scene/block/render-statistics.snippet.ts +24 -29
  270. package/src/runjs-context/snippets/scene/block/render-timeline.snippet.ts +20 -21
  271. package/src/scheduler/ModelOperationScheduler.ts +304 -0
  272. package/src/types.ts +50 -4
  273. package/src/utils/__tests__/createCollectionContextMeta.test.ts +51 -0
  274. package/src/utils/__tests__/flows.test.ts +65 -0
  275. package/src/utils/__tests__/jsxTransform.test.ts +38 -0
  276. package/src/utils/__tests__/parsePathnameToViewParams.test.ts +25 -0
  277. package/src/utils/__tests__/pruneFilter.test.ts +38 -0
  278. package/src/utils/__tests__/safeGlobals.test.ts +23 -1
  279. package/src/utils/__tests__/utils.test.ts +114 -15
  280. package/src/utils/__tests__/variablesParams.test.ts +120 -0
  281. package/src/utils/associationObjectVariable.ts +180 -0
  282. package/src/utils/createCollectionContextMeta.ts +8 -3
  283. package/src/utils/createEphemeralContext.ts +142 -0
  284. package/src/utils/flows.ts +23 -0
  285. package/src/utils/index.ts +11 -2
  286. package/src/utils/jsxTransform.ts +39 -0
  287. package/src/utils/params-resolvers.ts +2 -2
  288. package/src/utils/parsePathnameToViewParams.ts +50 -6
  289. package/src/utils/pruneFilter.ts +41 -0
  290. package/src/utils/safeGlobals.ts +51 -4
  291. package/src/utils/schema-utils.ts +81 -3
  292. package/src/utils/serverContextParams.ts +5 -0
  293. package/src/utils/translation.ts +7 -2
  294. package/src/utils/variablesParams.ts +125 -42
  295. package/src/views/DialogComponent.tsx +1 -4
  296. package/src/views/DrawerComponent.tsx +19 -7
  297. package/src/views/PageComponent.tsx +2 -4
  298. package/src/views/ViewNavigation.ts +49 -43
  299. package/src/views/__tests__/FlowView.usePage.test.tsx +133 -0
  300. package/src/views/__tests__/ViewNavigation.test.ts +54 -34
  301. package/src/views/__tests__/useDialog.closeDestroy.test.tsx +132 -0
  302. package/src/views/createViewMeta.ts +179 -42
  303. package/src/views/useDialog.tsx +36 -24
  304. package/src/views/useDrawer.tsx +37 -24
  305. package/src/views/usePage.tsx +46 -27
@@ -17,6 +17,7 @@ import DialogComponent from './DialogComponent';
17
17
  import usePatchElement from './usePatchElement';
18
18
  import { FlowEngineProvider } from '../provider';
19
19
  import { createViewScopedEngine } from '../ViewScopedFlowEngine';
20
+ import { createViewRecordResolveOnServer, getViewRecordFromParent } from '../utils/variablesParams';
20
21
 
21
22
  let uuid = 0;
22
23
 
@@ -73,20 +74,43 @@ export function useDialog() {
73
74
  return null; // Header 组件本身不渲染内容
74
75
  };
75
76
 
77
+ const ctx = new FlowContext();
78
+ // 为当前视图创建作用域引擎(隔离实例与缓存)
79
+ const scopedEngine = createViewScopedEngine(flowContext.engine);
80
+ ctx.defineProperty('engine', { value: scopedEngine });
81
+ ctx.addDelegate(scopedEngine.context);
82
+ if (config.inheritContext !== false) {
83
+ ctx.addDelegate(flowContext);
84
+ } else {
85
+ ctx.addDelegate(flowContext.engine.context);
86
+ }
87
+
76
88
  // 构造 currentDialog 实例
77
89
  const currentDialog = {
78
90
  type: 'dialog' as const,
79
91
  inputArgs: config.inputArgs || {},
80
92
  preventClose: !!config.preventClose,
81
- destroy: () => dialogRef.current?.destroy(),
93
+ destroy: (result?: any) => {
94
+ config.onClose?.();
95
+ dialogRef.current?.destroy();
96
+ closeFunc?.();
97
+ resolvePromise?.(result);
98
+ // 关闭时修正 previous/next 指针
99
+ scopedEngine.unlinkFromStack();
100
+ },
82
101
  update: (newConfig) => dialogRef.current?.update(newConfig),
83
102
  close: (result?: any, force?: boolean) => {
84
103
  if (config.preventClose && !force) {
85
104
  return;
86
105
  }
87
- dialogRef.current?.destroy();
88
- closeFunc?.();
89
- resolvePromise?.(result);
106
+
107
+ if (config.triggerByRouter && config.inputArgs?.navigation?.back) {
108
+ // 交由路由系统来销毁当前视图
109
+ config.inputArgs.navigation.back();
110
+ return;
111
+ }
112
+
113
+ currentDialog.destroy(result);
90
114
  },
91
115
  Footer: FooterComponent,
92
116
  Header: HeaderComponent,
@@ -99,23 +123,15 @@ export function useDialog() {
99
123
  dialogRef.current?.setHeader(header);
100
124
  },
101
125
  navigation: config.inputArgs?.navigation,
126
+ get record() {
127
+ return getViewRecordFromParent(flowContext, ctx);
128
+ },
102
129
  };
103
130
 
104
- const ctx = new FlowContext();
105
- // 为当前视图创建作用域引擎(隔离实例与缓存)
106
- const scopedEngine = createViewScopedEngine(flowContext.engine);
107
- ctx.defineProperty('engine', { value: scopedEngine });
108
- ctx.addDelegate(scopedEngine.context);
109
- if (config.inheritContext !== false) {
110
- ctx.addDelegate(flowContext);
111
- } else {
112
- ctx.addDelegate(flowContext.engine.context);
113
- }
114
-
115
131
  ctx.defineProperty('view', {
116
132
  get: () => currentDialog,
117
133
  // meta: createViewMeta(ctx),
118
- resolveOnServer: (p: string) => p === 'record' || p.startsWith('record.'),
134
+ resolveOnServer: createViewRecordResolveOnServer(ctx, () => getViewRecordFromParent(flowContext, ctx)),
119
135
  });
120
136
  // 顶层 popup 变量:弹窗记录/数据源/上级弹窗链(去重封装)
121
137
  registerPopupVariable(ctx, currentDialog);
@@ -146,18 +162,13 @@ export function useDialog() {
146
162
  return (
147
163
  <DialogComponent
148
164
  className="nb-dialog-overflow-hidden"
149
- key={`dialog-${uuid}`}
150
165
  ref={dialogRef}
151
166
  hidden={config.inputArgs?.hidden?.value}
152
167
  {...config}
153
168
  footer={currentFooter}
154
169
  header={currentHeader}
155
- afterClose={() => {
156
- closeFunc?.();
157
- config.onClose?.();
158
- resolvePromise?.(config.result);
159
- // 关闭时修正 previous/next 指针
160
- scopedEngine.unlinkFromStack();
170
+ onCancel={() => {
171
+ currentDialog.close(config.result);
161
172
  }}
162
173
  >
163
174
  {content}
@@ -169,8 +180,9 @@ export function useDialog() {
169
180
  },
170
181
  );
171
182
 
183
+ const key = config?.inputArgs?.viewUid || `page-${uuid}`;
172
184
  const dialog = (
173
- <FlowEngineProvider engine={scopedEngine}>
185
+ <FlowEngineProvider key={key} engine={scopedEngine}>
174
186
  <FlowViewContextProvider context={ctx}>
175
187
  <DialogWithContext />
176
188
  </FlowViewContextProvider>
@@ -17,6 +17,7 @@ import DrawerComponent from './DrawerComponent';
17
17
  import usePatchElement from './usePatchElement';
18
18
  import { FlowEngineProvider } from '../provider';
19
19
  import { createViewScopedEngine } from '../ViewScopedFlowEngine';
20
+ import { createViewRecordResolveOnServer, getViewRecordFromParent } from '../utils/variablesParams';
20
21
 
21
22
  export function useDrawer() {
22
23
  const holderRef = React.useRef(null);
@@ -101,20 +102,44 @@ export function useDrawer() {
101
102
  return null; // Header 组件本身不渲染内容
102
103
  };
103
104
 
105
+ const ctx = new FlowContext();
106
+ // 为当前视图创建作用域引擎(隔离实例与缓存)
107
+ const scopedEngine = createViewScopedEngine(flowContext.engine);
108
+ // 先将引擎暴露给视图上下文,再按需继承父上下文
109
+ ctx.defineProperty('engine', { value: scopedEngine });
110
+ ctx.addDelegate(scopedEngine.context);
111
+ if (config.inheritContext !== false) {
112
+ ctx.addDelegate(flowContext);
113
+ } else {
114
+ ctx.addDelegate(flowContext.engine.context);
115
+ }
116
+
104
117
  // 构造 currentDrawer 实例
105
118
  const currentDrawer = {
106
119
  type: 'drawer' as const,
107
120
  inputArgs: config.inputArgs || {},
108
121
  preventClose: !!config.preventClose,
109
- destroy: () => drawerRef.current?.destroy(),
122
+ destroy: (result?: any) => {
123
+ config.onClose?.();
124
+ drawerRef.current?.destroy();
125
+ closeFunc?.();
126
+ resolvePromise?.(result);
127
+ // 关闭时修正 previous/next 指针
128
+ scopedEngine.unlinkFromStack();
129
+ },
110
130
  update: (newConfig) => drawerRef.current?.update(newConfig),
111
131
  close: (result?: any, force?: boolean) => {
112
132
  if (config.preventClose && !force) {
113
133
  return;
114
134
  }
115
- drawerRef.current?.destroy();
116
- closeFunc?.();
117
- resolvePromise?.(result);
135
+
136
+ if (config.triggerByRouter && config.inputArgs?.navigation?.back) {
137
+ // 交由路由系统来销毁当前视图
138
+ config.inputArgs.navigation.back();
139
+ return;
140
+ }
141
+
142
+ currentDrawer.destroy(result);
118
143
  },
119
144
  Footer: FooterComponent,
120
145
  Header: HeaderComponent,
@@ -127,24 +152,15 @@ export function useDrawer() {
127
152
  drawerRef.current?.setHeader(header);
128
153
  },
129
154
  navigation: config.inputArgs?.navigation,
155
+ get record() {
156
+ return getViewRecordFromParent(flowContext, ctx);
157
+ },
130
158
  };
131
159
 
132
- const ctx = new FlowContext();
133
- // 为当前视图创建作用域引擎(隔离实例与缓存)
134
- const scopedEngine = createViewScopedEngine(flowContext.engine);
135
- // 先将引擎暴露给视图上下文,再按需继承父上下文
136
- ctx.defineProperty('engine', { value: scopedEngine });
137
- ctx.addDelegate(scopedEngine.context);
138
- if (config.inheritContext !== false) {
139
- ctx.addDelegate(flowContext);
140
- } else {
141
- ctx.addDelegate(flowContext.engine.context);
142
- }
143
-
144
160
  ctx.defineProperty('view', {
145
161
  get: () => currentDrawer,
146
162
  // meta: createViewMeta(ctx),
147
- resolveOnServer: (p: string) => p === 'record' || p.startsWith('record.'),
163
+ resolveOnServer: createViewRecordResolveOnServer(ctx, () => getViewRecordFromParent(flowContext, ctx)),
148
164
  });
149
165
  // 顶层 popup 变量:弹窗记录/数据源/上级弹窗链(去重封装)
150
166
  registerPopupVariable(ctx, currentDrawer);
@@ -178,15 +194,12 @@ export function useDrawer() {
178
194
  ref={drawerRef}
179
195
  {...config}
180
196
  footer={currentFooter}
181
- header={currentHeader}
197
+ header={config.header || currentHeader}
182
198
  hidden={config.inputArgs?.hidden?.value}
183
- afterClose={() => {
184
- closeFunc?.();
185
- config.onClose?.();
186
- resolvePromise?.(config.result);
187
- // 关闭时修正 previous/next 指针
188
- scopedEngine.unlinkFromStack();
199
+ onClose={() => {
200
+ currentDrawer.close(config.result);
189
201
  }}
202
+ isMobile={ctx.isMobileLayout}
190
203
  >
191
204
  {content}
192
205
  {props.children}
@@ -17,6 +17,7 @@ import { PageComponent } from './PageComponent';
17
17
  import usePatchElement from './usePatchElement';
18
18
  import { FlowEngineProvider } from '../provider';
19
19
  import { createViewScopedEngine } from '../ViewScopedFlowEngine';
20
+ import { createViewRecordResolveOnServer, getViewRecordFromParent } from '../utils/variablesParams';
20
21
 
21
22
  let uuid = 0;
22
23
 
@@ -25,6 +26,7 @@ const PageElementsHolder = React.memo(
25
26
  React.forwardRef((props: any, ref: any) => {
26
27
  const [elements, patchElement] = usePatchElement();
27
28
  React.useImperativeHandle(ref, () => ({ patchElement }), [patchElement]);
29
+ console.log('[NocoBase] Rendering PageElementsHolder with elements count:', elements.length);
28
30
  return <>{elements}</>;
29
31
  }),
30
32
  );
@@ -73,22 +75,45 @@ export function usePage() {
73
75
  return null; // Header 组件本身不渲染内容
74
76
  };
75
77
 
76
- const { target, content, preventClose, inheritContext = true, ...restConfig } = config;
78
+ const { target, content, preventClose, inheritContext = true, inputArgs, ...restConfig } = config;
79
+
80
+ const ctx = new FlowContext();
81
+ // 为当前视图创建作用域引擎(隔离实例与缓存)
82
+ const scopedEngine = createViewScopedEngine(flowContext.engine);
83
+ ctx.defineProperty('engine', { value: scopedEngine });
84
+ ctx.addDelegate(scopedEngine.context);
85
+ if (inheritContext) {
86
+ ctx.addDelegate(flowContext);
87
+ } else {
88
+ ctx.addDelegate(flowContext.engine.context);
89
+ }
77
90
 
78
91
  // 构造 currentPage 实例
79
92
  const currentPage = {
80
93
  type: 'embed' as const,
81
94
  inputArgs: config.inputArgs || {},
82
95
  preventClose: !!config.preventClose,
83
- destroy: () => pageRef.current?.destroy(),
96
+ destroy: (result?: any) => {
97
+ config.onClose?.();
98
+ resolvePromise?.(result);
99
+ pageRef.current?.destroy();
100
+ closeFunc?.();
101
+ // 关闭时修正 previous/next 指针
102
+ scopedEngine.unlinkFromStack();
103
+ },
84
104
  update: (newConfig) => pageRef.current?.update(newConfig),
85
105
  close: (result?: any, force?: boolean) => {
86
106
  if (preventClose && !force) {
87
107
  return;
88
108
  }
89
- resolvePromise?.(result);
90
- pageRef.current?.destroy();
91
- closeFunc?.();
109
+
110
+ if (config.triggerByRouter && config.inputArgs?.navigation?.back) {
111
+ // 交由路由系统来销毁当前视图
112
+ config.inputArgs.navigation.back();
113
+ return;
114
+ }
115
+
116
+ currentPage.destroy(result);
92
117
  },
93
118
  Header: HeaderComponent,
94
119
  Footer: FooterComponent,
@@ -99,23 +124,17 @@ export function usePage() {
99
124
  pageRef.current?.setHeader(header);
100
125
  },
101
126
  navigation: config.inputArgs?.navigation,
127
+ get record() {
128
+ // 当视图正在查看与父 record 同一条记录时,复用父记录深拷贝;否则走服务端解析
129
+ return getViewRecordFromParent(flowContext, ctx);
130
+ },
102
131
  };
103
132
 
104
- const ctx = new FlowContext();
105
- // 为当前视图创建作用域引擎(隔离实例与缓存)
106
- const scopedEngine = createViewScopedEngine(flowContext.engine);
107
- ctx.defineProperty('engine', { value: scopedEngine });
108
- ctx.addDelegate(scopedEngine.context);
109
- if (inheritContext) {
110
- ctx.addDelegate(flowContext);
111
- } else {
112
- ctx.addDelegate(flowContext.engine.context);
113
- }
114
-
115
133
  ctx.defineProperty('view', {
116
134
  get: () => currentPage,
117
135
  // meta: createViewMeta(ctx),
118
- resolveOnServer: (p: string) => p === 'record' || p.startsWith('record.'),
136
+ // 仅当访问关联字段或前端无本地记录数据时,才交给服务端解析
137
+ resolveOnServer: createViewRecordResolveOnServer(ctx, () => getViewRecordFromParent(flowContext, ctx)),
119
138
  });
120
139
  // 顶层 popup 变量:弹窗记录/数据源/上级弹窗链(去重封装)
121
140
  registerPopupVariable(ctx, currentPage);
@@ -125,7 +144,11 @@ export function usePage() {
125
144
  // eslint-disable-next-line react-hooks/rules-of-hooks
126
145
  const mountedRef = React.useRef(false);
127
146
  // 支持 content 为函数,传递 currentPage
128
- const pageContent = typeof content === 'function' ? content(currentPage, ctx) : content;
147
+ // eslint-disable-next-line react-hooks/rules-of-hooks
148
+ const pageContent = React.useMemo(
149
+ () => (typeof content === 'function' ? content(currentPage, ctx) : content),
150
+ [],
151
+ );
129
152
  // 响应themeToken的响应式更新
130
153
  void ctx.themeToken;
131
154
  // eslint-disable-next-line react-hooks/rules-of-hooks
@@ -141,16 +164,11 @@ export function usePage() {
141
164
 
142
165
  return (
143
166
  <PageComponent
144
- key={`page-${uuid}`}
145
167
  ref={pageRef}
146
168
  hidden={config.inputArgs?.hidden?.value}
147
169
  {...restConfig}
148
- afterClose={() => {
149
- closeFunc?.();
150
- config.onClose?.();
151
- resolvePromise?.(config.result);
152
- // 关闭时修正 previous/next 指针
153
- scopedEngine.unlinkFromStack();
170
+ onClose={() => {
171
+ currentPage.close(config.result);
154
172
  }}
155
173
  >
156
174
  {pageContent}
@@ -162,8 +180,9 @@ export function usePage() {
162
180
  },
163
181
  );
164
182
 
183
+ const key = inputArgs?.viewUid || `page-${uuid}`;
165
184
  const page = (
166
- <FlowEngineProvider engine={scopedEngine}>
185
+ <FlowEngineProvider key={key} engine={scopedEngine}>
167
186
  <FlowViewContextProvider context={ctx}>
168
187
  <PageWithContext />
169
188
  </FlowViewContextProvider>
@@ -171,7 +190,7 @@ export function usePage() {
171
190
  );
172
191
 
173
192
  if (target && target instanceof HTMLElement) {
174
- closeFunc = holderRef.current?.patchElement(ReactDOM.createPortal(page, target));
193
+ closeFunc = holderRef.current?.patchElement(ReactDOM.createPortal(page, target, key));
175
194
  } else {
176
195
  closeFunc = holderRef.current?.patchElement(page);
177
196
  }