@pisell/private-materials 6.12.167 → 6.12.169

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 (231) hide show
  1. package/build/lowcode/assets-daily.json +11 -11
  2. package/build/lowcode/assets-dev.json +2 -2
  3. package/build/lowcode/assets-prod.json +11 -11
  4. package/build/lowcode/meta.js +1 -1
  5. package/build/lowcode/render/default/view.css +1 -1
  6. package/build/lowcode/render/default/view.js +10 -10
  7. package/build/lowcode/view.css +1 -1
  8. package/build/lowcode/view.js +10 -10
  9. package/es/components/HDLKiosk/{contracts → app/contracts}/config.js +1 -1
  10. package/es/components/HDLKiosk/app/manifest.js +11 -11
  11. package/es/components/HDLKiosk/app/operations.js +92 -0
  12. package/es/components/HDLKiosk/app/workflow/barcode.js +11 -13
  13. package/es/components/HDLKiosk/app/workflow/index.js +16 -0
  14. package/es/components/HDLKiosk/app/workflow/predicates.js +1 -1
  15. package/es/components/HDLKiosk/app/workflow/quick.js +1 -1
  16. package/es/components/HDLKiosk/app/workflow/registry.js +4 -4
  17. package/es/components/HDLKiosk/app/workflow/scale.js +5 -1
  18. package/es/components/HDLKiosk/docs/00-/346/226/207/344/273/266/345/257/274/350/210/252.md +104 -167
  19. package/es/components/HDLKiosk/docs/01-/346/240/270/345/277/203/350/277/220/350/241/214/346/234/272/345/210/266.md +105 -101
  20. package/es/components/HDLKiosk/docs/03-/344/270/232/345/212/241/346/265/201/347/250/213/344/270/216/344/272/244/344/272/222/350/247/204/345/210/231.md +2 -2
  21. package/es/components/HDLKiosk/docs/04-/350/256/276/345/244/207/344/270/216/347/247/260/351/207/215.md +43 -26
  22. package/es/components/HDLKiosk/docs/05-/344/272/244/346/230/223/345/256/211/345/205/250.md +2 -0
  23. package/es/components/HDLKiosk/docs/07-/345/220/216/347/273/255/345/267/245/344/275/234.md +1 -1
  24. package/es/components/HDLKiosk/docs/08-/346/227/240/345/244/264Application/350/277/220/350/241/214/346/227/266/351/207/215/346/236/204/350/256/276/350/256/241.md +719 -0
  25. package/es/components/HDLKiosk/docs/09-Entry/350/256/276/345/244/207/344/272/213/344/273/266/351/207/215/346/236/204/344/277/256/345/244/215/346/212/245/345/221/212.md +187 -0
  26. package/es/components/HDLKiosk/docs/README.md +6 -2
  27. package/es/components/HDLKiosk/docs//345/256/236/346/226/275/350/277/233/345/272/246.md +8 -7
  28. package/es/components/HDLKiosk/docs//346/236/266/346/236/204/350/256/276/350/256/241.md +16 -18
  29. package/es/components/HDLKiosk/index.js +22 -28
  30. package/es/components/HDLKiosk/index.less +1 -1
  31. package/es/components/HDLKiosk/kernel/README.md +14 -13
  32. package/es/components/HDLKiosk/kernel/application/defineApplication.js +63 -24
  33. package/es/components/HDLKiosk/kernel/application/defineSlice.js +6 -6
  34. package/es/components/HDLKiosk/kernel/application/runtime.js +237 -0
  35. package/es/components/HDLKiosk/kernel/operations/coordinator.js +1 -1
  36. package/es/components/HDLKiosk/kernel/operations/registry.js +3 -3
  37. package/es/components/HDLKiosk/kernel/operations/sessionEpoch.js +1 -1
  38. package/es/components/HDLKiosk/kernel/operations/types.js +7 -3
  39. package/es/components/HDLKiosk/kernel/workflow/actor.js +51 -22
  40. package/es/components/HDLKiosk/kernel/workflow/compiler.js +23 -30
  41. package/es/components/HDLKiosk/runtime/createRuntime.js +238 -0
  42. package/es/components/HDLKiosk/{devices → runtime/devices}/dedupeStore.js +1 -1
  43. package/es/components/HDLKiosk/{devices → runtime/devices}/scaleIngress.js +1 -1
  44. package/es/components/HDLKiosk/{devices/scale/runtime.js → runtime/devices/scaleStore.js} +18 -24
  45. package/es/components/HDLKiosk/{devices → runtime/devices}/scannerIngress.js +1 -1
  46. package/es/components/HDLKiosk/runtime/devices/scannerSessionPort.js +60 -0
  47. package/es/components/HDLKiosk/runtime/devices/scannerSessionRouter.js +212 -0
  48. package/es/components/HDLKiosk/runtime/operations/barcode.js +18 -0
  49. package/es/components/HDLKiosk/runtime/operations/cart.js +44 -0
  50. package/es/components/HDLKiosk/{app → runtime}/operations/cartConsistency.js +1 -1
  51. package/es/components/HDLKiosk/{app → runtime}/operations/checkout.js +95 -110
  52. package/es/components/HDLKiosk/{app → runtime}/operations/checkoutRequirements.js +1 -1
  53. package/es/components/HDLKiosk/{app → runtime}/operations/checkoutSafety.js +1 -1
  54. package/es/components/HDLKiosk/{app → runtime}/operations/coordinator.js +2 -2
  55. package/es/components/HDLKiosk/runtime/operations/customization.js +70 -0
  56. package/es/components/HDLKiosk/{app → runtime}/operations/errors.js +1 -1
  57. package/es/components/HDLKiosk/runtime/operations/fulfillment.js +6 -0
  58. package/es/components/HDLKiosk/runtime/operations/identity.js +55 -0
  59. package/es/components/HDLKiosk/runtime/operations/registry.js +34 -0
  60. package/es/components/HDLKiosk/runtime/operations/session.js +29 -0
  61. package/es/components/HDLKiosk/runtime/operations/types.js +13 -0
  62. package/es/components/HDLKiosk/runtime/session/blockPolicy.js +14 -0
  63. package/es/components/HDLKiosk/runtime/{createWorkflowSession.js → session/createSession.js} +67 -17
  64. package/es/components/HDLKiosk/runtime/{domainTransitionRunner.js → session/transitionRunner.js} +10 -5
  65. package/es/components/HDLKiosk/runtime/{workflowContext.js → session/workflowContext.js} +2 -2
  66. package/es/components/HDLKiosk/runtime/{workflowLifecycle.js → session/workflowLifecycle.js} +2 -2
  67. package/es/components/HDLKiosk/runtime/triggers.js +28 -0
  68. package/es/components/HDLKiosk/slices/catalog/Screen/index.js +15 -8
  69. package/es/components/HDLKiosk/slices/catalog/Screen/index.less +74 -13
  70. package/es/components/HDLKiosk/slices/catalog/slice.js +2 -2
  71. package/es/components/HDLKiosk/slices/customization/Screen/index.js +37 -38
  72. package/es/components/HDLKiosk/slices/customization/Screen/index.less +5 -0
  73. package/es/components/HDLKiosk/slices/customization/slice.js +3 -4
  74. package/es/components/HDLKiosk/slices/fulfillment/slice.js +2 -2
  75. package/es/components/HDLKiosk/slices/fulfillment/view.js +1 -1
  76. package/es/components/HDLKiosk/slices/identity/Screen/index.js +2 -2
  77. package/es/components/HDLKiosk/slices/identity/slice.js +3 -3
  78. package/es/components/HDLKiosk/slices/identity/view.js +1 -1
  79. package/es/components/HDLKiosk/slices/payment/slice.js +3 -3
  80. package/es/components/HDLKiosk/slices/primaryProductPrompt/slice.js +2 -2
  81. package/es/components/HDLKiosk/slices/primaryProductPrompt/view.js +2 -2
  82. package/es/components/HDLKiosk/{runtime → ui}/HDLKioskWorkflowView.js +45 -131
  83. package/es/components/HDLKiosk/ui/ScaleSimulatorConsole/index.js +387 -0
  84. package/es/components/HDLKiosk/ui/ScaleSimulatorConsole/index.less +621 -0
  85. package/es/components/HDLKiosk/{app → ui}/ScreenRenderer.js +7 -7
  86. package/es/components/HDLKiosk/ui/controllers/useHDLKioskActionDispatcher.js +66 -0
  87. package/es/components/HDLKiosk/{runtime → ui}/controllers/useHDLKioskCustomerController.js +1 -1
  88. package/es/components/HDLKiosk/ui/controllers/useHDLKioskDeviceController.js +25 -0
  89. package/es/components/HDLKiosk/ui/controllers/useHDLKioskExitController.js +53 -0
  90. package/es/components/HDLKiosk/{runtime → ui}/controllers/useHDLKioskScreenData.js +1 -1
  91. package/es/components/HDLKiosk/ui/controllers/useHDLKioskSessionController.js +39 -0
  92. package/es/components/HDLKiosk/{app → ui}/entry/Screen/index.js +8 -6
  93. package/es/components/HDLKiosk/{app → ui}/entry/model.js +2 -2
  94. package/es/components/HDLKiosk/ui/scale.js +20 -0
  95. package/es/components/HDLKiosk/{runtime/useHostSnapshot.js → ui/snapshots.js} +6 -8
  96. package/es/components/HDLKiosk/{app → ui}/views.js +1 -1
  97. package/es/components/HDLKiosk/{runtime → ui}/workflowEvent.js +1 -1
  98. package/es/components/HDLKiosk/utils.js +4 -4
  99. package/es/components/bigSale/templates/HDLKiosk/adapter/HDLKioskPaymentRuntime.js +2 -1
  100. package/es/components/bigSale/templates/HDLKiosk/adapter/capabilities.js +1 -1
  101. package/es/components/bigSale/templates/HDLKiosk/adapter/projection.js +21 -11
  102. package/es/components/bigSale/templates/HDLKiosk/adapter/sales.js +21 -3
  103. package/es/components/bigSale/templates/HDLKiosk/adapter/scaleTrigger.js +20 -5
  104. package/es/components/bigSale/templates/HDLKiosk/adapter/useBigSaleHDLKioskHost.js +3 -0
  105. package/es/components/bigSale/templates/HDLKiosk/index.js +3 -3
  106. package/lib/components/HDLKiosk/{contracts → app/contracts}/config.js +1 -1
  107. package/lib/components/HDLKiosk/app/manifest.js +18 -19
  108. package/lib/components/HDLKiosk/app/operations.js +105 -0
  109. package/lib/components/HDLKiosk/app/workflow/barcode.js +11 -13
  110. package/lib/components/HDLKiosk/app/workflow/index.js +16 -0
  111. package/lib/components/HDLKiosk/app/workflow/predicates.js +1 -0
  112. package/lib/components/HDLKiosk/app/workflow/quick.js +1 -1
  113. package/lib/components/HDLKiosk/app/workflow/registry.js +3 -3
  114. package/lib/components/HDLKiosk/app/workflow/scale.js +5 -1
  115. package/lib/components/HDLKiosk/docs/00-/346/226/207/344/273/266/345/257/274/350/210/252.md +104 -167
  116. package/lib/components/HDLKiosk/docs/01-/346/240/270/345/277/203/350/277/220/350/241/214/346/234/272/345/210/266.md +105 -101
  117. package/lib/components/HDLKiosk/docs/03-/344/270/232/345/212/241/346/265/201/347/250/213/344/270/216/344/272/244/344/272/222/350/247/204/345/210/231.md +2 -2
  118. package/lib/components/HDLKiosk/docs/04-/350/256/276/345/244/207/344/270/216/347/247/260/351/207/215.md +43 -26
  119. package/lib/components/HDLKiosk/docs/05-/344/272/244/346/230/223/345/256/211/345/205/250.md +2 -0
  120. package/lib/components/HDLKiosk/docs/07-/345/220/216/347/273/255/345/267/245/344/275/234.md +1 -1
  121. package/lib/components/HDLKiosk/docs/08-/346/227/240/345/244/264Application/350/277/220/350/241/214/346/227/266/351/207/215/346/236/204/350/256/276/350/256/241.md +719 -0
  122. package/lib/components/HDLKiosk/docs/09-Entry/350/256/276/345/244/207/344/272/213/344/273/266/351/207/215/346/236/204/344/277/256/345/244/215/346/212/245/345/221/212.md +187 -0
  123. package/lib/components/HDLKiosk/docs/README.md +6 -2
  124. package/lib/components/HDLKiosk/docs//345/256/236/346/226/275/350/277/233/345/272/246.md +8 -7
  125. package/lib/components/HDLKiosk/docs//346/236/266/346/236/204/350/256/276/350/256/241.md +16 -18
  126. package/lib/components/HDLKiosk/index.js +25 -31
  127. package/lib/components/HDLKiosk/index.less +1 -1
  128. package/lib/components/HDLKiosk/kernel/README.md +14 -13
  129. package/lib/components/HDLKiosk/kernel/application/defineApplication.js +65 -25
  130. package/lib/components/HDLKiosk/kernel/application/defineSlice.js +6 -6
  131. package/lib/components/HDLKiosk/kernel/application/runtime.js +237 -0
  132. package/lib/components/HDLKiosk/kernel/operations/coordinator.js +1 -1
  133. package/lib/components/HDLKiosk/kernel/operations/registry.js +3 -3
  134. package/lib/components/HDLKiosk/kernel/operations/sessionEpoch.js +1 -1
  135. package/lib/components/HDLKiosk/kernel/operations/types.js +8 -3
  136. package/lib/components/HDLKiosk/kernel/workflow/actor.js +51 -22
  137. package/lib/components/HDLKiosk/kernel/workflow/compiler.js +23 -30
  138. package/lib/components/HDLKiosk/runtime/createRuntime.js +239 -0
  139. package/lib/components/HDLKiosk/{devices → runtime/devices}/dedupeStore.js +1 -1
  140. package/lib/components/HDLKiosk/{devices → runtime/devices}/scaleIngress.js +1 -1
  141. package/lib/components/HDLKiosk/{devices/scale/runtime.js → runtime/devices/scaleStore.js} +17 -27
  142. package/lib/components/HDLKiosk/{devices → runtime/devices}/scannerIngress.js +1 -1
  143. package/lib/components/HDLKiosk/runtime/devices/scannerSessionPort.js +60 -0
  144. package/lib/components/HDLKiosk/runtime/devices/scannerSessionRouter.js +212 -0
  145. package/lib/components/HDLKiosk/runtime/operations/barcode.js +17 -0
  146. package/lib/components/HDLKiosk/runtime/operations/cart.js +46 -0
  147. package/lib/components/HDLKiosk/{app → runtime}/operations/cartConsistency.js +1 -1
  148. package/lib/components/HDLKiosk/{app → runtime}/operations/checkout.js +97 -112
  149. package/lib/components/HDLKiosk/{app → runtime}/operations/checkoutRequirements.js +1 -1
  150. package/lib/components/HDLKiosk/{app → runtime}/operations/checkoutSafety.js +1 -1
  151. package/lib/components/HDLKiosk/{app → runtime}/operations/coordinator.js +2 -2
  152. package/lib/components/HDLKiosk/runtime/operations/customization.js +73 -0
  153. package/lib/components/HDLKiosk/{app → runtime}/operations/errors.js +1 -1
  154. package/lib/components/HDLKiosk/runtime/operations/fulfillment.js +5 -0
  155. package/lib/components/HDLKiosk/runtime/operations/identity.js +55 -0
  156. package/lib/components/HDLKiosk/runtime/operations/registry.js +34 -0
  157. package/lib/components/HDLKiosk/runtime/operations/session.js +30 -0
  158. package/lib/components/HDLKiosk/runtime/operations/types.js +14 -0
  159. package/lib/components/HDLKiosk/runtime/session/blockPolicy.js +14 -0
  160. package/lib/components/HDLKiosk/runtime/{createWorkflowSession.js → session/createSession.js} +71 -21
  161. package/lib/components/HDLKiosk/runtime/{domainTransitionRunner.js → session/transitionRunner.js} +10 -5
  162. package/lib/components/HDLKiosk/runtime/{workflowContext.js → session/workflowContext.js} +2 -2
  163. package/lib/components/HDLKiosk/runtime/{workflowLifecycle.js → session/workflowLifecycle.js} +2 -2
  164. package/lib/components/HDLKiosk/runtime/triggers.js +28 -0
  165. package/lib/components/HDLKiosk/slices/catalog/Screen/index.js +15 -8
  166. package/lib/components/HDLKiosk/slices/catalog/Screen/index.less +74 -13
  167. package/lib/components/HDLKiosk/slices/catalog/slice.js +3 -3
  168. package/lib/components/HDLKiosk/slices/customization/Screen/index.js +38 -39
  169. package/lib/components/HDLKiosk/slices/customization/Screen/index.less +5 -0
  170. package/lib/components/HDLKiosk/slices/customization/slice.js +5 -6
  171. package/lib/components/HDLKiosk/slices/fulfillment/slice.js +3 -3
  172. package/lib/components/HDLKiosk/slices/fulfillment/view.js +1 -1
  173. package/lib/components/HDLKiosk/slices/identity/Screen/index.js +2 -2
  174. package/lib/components/HDLKiosk/slices/identity/slice.js +4 -4
  175. package/lib/components/HDLKiosk/slices/identity/view.js +1 -1
  176. package/lib/components/HDLKiosk/slices/payment/slice.js +5 -5
  177. package/lib/components/HDLKiosk/slices/primaryProductPrompt/slice.js +2 -2
  178. package/lib/components/HDLKiosk/slices/primaryProductPrompt/view.js +2 -2
  179. package/lib/components/HDLKiosk/{runtime → ui}/HDLKioskWorkflowView.js +46 -132
  180. package/lib/components/HDLKiosk/ui/ScaleSimulatorConsole/index.js +390 -0
  181. package/lib/components/HDLKiosk/ui/ScaleSimulatorConsole/index.less +621 -0
  182. package/lib/components/HDLKiosk/{app → ui}/ScreenRenderer.js +7 -7
  183. package/lib/components/HDLKiosk/ui/controllers/useHDLKioskActionDispatcher.js +67 -0
  184. package/lib/components/HDLKiosk/{runtime → ui}/controllers/useHDLKioskCustomerController.js +1 -1
  185. package/lib/components/HDLKiosk/ui/controllers/useHDLKioskDeviceController.js +26 -0
  186. package/lib/components/HDLKiosk/ui/controllers/useHDLKioskExitController.js +54 -0
  187. package/lib/components/HDLKiosk/{runtime → ui}/controllers/useHDLKioskScreenData.js +1 -1
  188. package/lib/components/HDLKiosk/ui/controllers/useHDLKioskSessionController.js +40 -0
  189. package/lib/components/HDLKiosk/{app → ui}/entry/Screen/index.js +8 -6
  190. package/lib/components/HDLKiosk/{app → ui}/entry/model.js +2 -2
  191. package/lib/components/HDLKiosk/ui/scale.js +24 -0
  192. package/lib/components/HDLKiosk/{runtime/useHostSnapshot.js → ui/snapshots.js} +6 -7
  193. package/lib/components/HDLKiosk/{app → ui}/views.js +1 -1
  194. package/lib/components/HDLKiosk/{runtime → ui}/workflowEvent.js +1 -1
  195. package/lib/components/HDLKiosk/utils.js +4 -4
  196. package/lib/components/bigSale/templates/HDLKiosk/adapter/HDLKioskPaymentRuntime.js +2 -1
  197. package/lib/components/bigSale/templates/HDLKiosk/adapter/capabilities.js +1 -1
  198. package/lib/components/bigSale/templates/HDLKiosk/adapter/projection.js +21 -10
  199. package/lib/components/bigSale/templates/HDLKiosk/adapter/sales.js +20 -2
  200. package/lib/components/bigSale/templates/HDLKiosk/adapter/scaleTrigger.js +19 -4
  201. package/lib/components/bigSale/templates/HDLKiosk/adapter/useBigSaleHDLKioskHost.js +3 -0
  202. package/lib/components/bigSale/templates/HDLKiosk/index.js +4 -4
  203. package/package.json +2 -2
  204. package/es/components/HDLKiosk/app/constants.js +0 -9
  205. package/es/components/HDLKiosk/app/operations/barcode.js +0 -22
  206. package/es/components/HDLKiosk/app/operations/cart.js +0 -60
  207. package/es/components/HDLKiosk/app/operations/fulfillment.js +0 -11
  208. package/es/components/HDLKiosk/app/operations/session.js +0 -41
  209. package/es/components/HDLKiosk/app/operations/types.js +0 -11
  210. package/es/components/HDLKiosk/devices/entryArbiter.js +0 -33
  211. package/es/components/HDLKiosk/runtime/controllers/useHDLKioskDeviceController.js +0 -75
  212. package/es/components/HDLKiosk/runtime/controllers/useHDLKioskScannerController.js +0 -160
  213. package/es/components/HDLKiosk/runtime/controllers/useHDLKioskSessionController.js +0 -185
  214. package/es/components/HDLKiosk/runtime/useWorkflowSnapshot.js +0 -12
  215. package/es/components/HDLKiosk/slices/customization/operation.js +0 -80
  216. package/es/components/HDLKiosk/slices/identity/operation.js +0 -60
  217. package/lib/components/HDLKiosk/app/constants.js +0 -9
  218. package/lib/components/HDLKiosk/app/operations/barcode.js +0 -21
  219. package/lib/components/HDLKiosk/app/operations/cart.js +0 -62
  220. package/lib/components/HDLKiosk/app/operations/fulfillment.js +0 -10
  221. package/lib/components/HDLKiosk/app/operations/session.js +0 -42
  222. package/lib/components/HDLKiosk/app/operations/types.js +0 -12
  223. package/lib/components/HDLKiosk/devices/entryArbiter.js +0 -33
  224. package/lib/components/HDLKiosk/runtime/controllers/useHDLKioskDeviceController.js +0 -76
  225. package/lib/components/HDLKiosk/runtime/controllers/useHDLKioskScannerController.js +0 -161
  226. package/lib/components/HDLKiosk/runtime/controllers/useHDLKioskSessionController.js +0 -186
  227. package/lib/components/HDLKiosk/runtime/useWorkflowSnapshot.js +0 -13
  228. package/lib/components/HDLKiosk/slices/customization/operation.js +0 -83
  229. package/lib/components/HDLKiosk/slices/identity/operation.js +0 -60
  230. /package/es/components/HDLKiosk/{app → ui}/entry/Screen/index.less +0 -0
  231. /package/lib/components/HDLKiosk/{app → ui}/entry/Screen/index.less +0 -0
@@ -0,0 +1,66 @@
1
+ import { createWorkflowEvent } from "../workflowEvent.js";
2
+ import { useCallback, useEffect, useRef, useState } from "react";
3
+ //#region src/components/HDLKiosk/ui/controllers/useHDLKioskActionDispatcher.ts
4
+ /**
5
+ * 文件角色:把 Slice UI Action 适配为当前 Workflow Session 的 Event 或 Command。
6
+ * 运行机制:统一生成 intent ID,并只投影当前节点发起的 Screen Command 状态。
7
+ * 边界:不决定业务跳转、不解释 Operation 结果,也不拥有 Session 生命周期。
8
+ */
9
+ function useHDLKioskActionDispatcher({ session, snapshot, activityId, resetSession }) {
10
+ const intentSequence = useRef(0);
11
+ const commandSequence = useRef(0);
12
+ const commandGeneration = useRef(0);
13
+ const pendingCommands = useRef(/* @__PURE__ */ new Map());
14
+ const [commandState, setCommandState] = useState({ busy: false });
15
+ useEffect(() => {
16
+ commandGeneration.current += 1;
17
+ pendingCommands.current.clear();
18
+ setCommandState({ busy: false });
19
+ return () => {
20
+ commandGeneration.current += 1;
21
+ pendingCommands.current.clear();
22
+ };
23
+ }, [session, snapshot.nodeId]);
24
+ return {
25
+ send: useCallback((action) => {
26
+ if (action.kind === "session") {
27
+ resetSession();
28
+ return;
29
+ }
30
+ intentSequence.current += 1;
31
+ const intentId = `ui:${snapshot.sessionEpoch}:${intentSequence.current}`;
32
+ if (action.kind === "intent" || action.kind === "navigation") {
33
+ const event = createWorkflowEvent(action, activityId, snapshot.nodeId, intentId);
34
+ if (event) session.dispatch(event);
35
+ return;
36
+ }
37
+ commandSequence.current += 1;
38
+ const execution = commandSequence.current;
39
+ const generation = commandGeneration.current;
40
+ pendingCommands.current.set(execution, action.command);
41
+ setCommandState({
42
+ busy: true,
43
+ commandId: action.command
44
+ });
45
+ session.executeCommand(action.command, action.input, intentId).then((result) => {
46
+ if (generation !== commandGeneration.current) return;
47
+ pendingCommands.current.delete(execution);
48
+ const remaining = [...pendingCommands.current.values()];
49
+ setCommandState({
50
+ busy: remaining.length > 0,
51
+ commandId: remaining[remaining.length - 1],
52
+ error: result.status === "failed" || result.status === "partialFailure" || result.status === "unknown" ? result.error : void 0
53
+ });
54
+ });
55
+ }, [
56
+ activityId,
57
+ resetSession,
58
+ session,
59
+ snapshot.nodeId,
60
+ snapshot.sessionEpoch
61
+ ]),
62
+ commandState
63
+ };
64
+ }
65
+ //#endregion
66
+ export { useHDLKioskActionDispatcher };
@@ -1,6 +1,6 @@
1
1
  import { _asyncToGenerator } from "../../../../_virtual/_@oxc-project_runtime@0.122.0/helpers/asyncToGenerator.js";
2
2
  import { useCallback, useEffect, useMemo, useRef, useState } from "react";
3
- //#region src/components/HDLKiosk/runtime/controllers/useHDLKioskCustomerController.ts
3
+ //#region src/components/HDLKiosk/ui/controllers/useHDLKioskCustomerController.ts
4
4
  /**
5
5
  * 文件角色:协调 Shell 全程可用的会员入口与插入式身份同步。
6
6
  * 运行机制:登录成功后通过 identity.sync 写入客户并触发订单一致性/重报价;再根据最新
@@ -0,0 +1,25 @@
1
+ import { useEffect, useState } from "react";
2
+ //#region src/components/HDLKiosk/ui/controllers/useHDLKioskDeviceController.ts
3
+ /**
4
+ * 文件角色:把 Scale 连接状态投影给 React Entry。
5
+ * 运行机制:只观察 connectionChanged;称重启动完全由 Runtime 的 onWeight Adapter 持有。
6
+ * 边界:不消费重量、不创建 Session,也不参与 Trigger 路由。
7
+ */
8
+ function useHDLKioskDeviceController({ host, isActive }) {
9
+ const [scaleConnectionState, setScaleConnectionState] = useState();
10
+ useEffect(() => {
11
+ setScaleConnectionState(void 0);
12
+ }, [host]);
13
+ useEffect(() => {
14
+ if (!isActive || !host.capabilities.scale.available) return void 0;
15
+ return host.devices.subscribe((event) => {
16
+ if (event.type === "connectionChanged" && event.device === "scale") {
17
+ var _event$state;
18
+ setScaleConnectionState((_event$state = event.state) !== null && _event$state !== void 0 ? _event$state : event.connected ? "connected" : "disconnected");
19
+ }
20
+ }, { sources: ["scale"] });
21
+ }, [host, isActive]);
22
+ return { scaleConnectionState };
23
+ }
24
+ //#endregion
25
+ export { useHDLKioskDeviceController };
@@ -0,0 +1,53 @@
1
+ import { useCallback, useEffect, useRef } from "react";
2
+ //#region src/components/HDLKiosk/ui/controllers/useHDLKioskExitController.ts
3
+ /**
4
+ * 文件角色:适配 Session Exit Navigation 与验证式订单重置。
5
+ * 运行机制:用户退出先经过 Actor Guard/确认;自动退出直接解析既有 Pending Navigation,
6
+ * 两者最终都调用 Runtime 提供的 returnToEntry。
7
+ * 边界:不拥有 reset pending/error,也不渲染确认弹层。
8
+ */
9
+ function useHDLKioskExitController({ session, snapshot, returnToEntry }) {
10
+ var _snapshot$pendingNavi, _snapshot$pendingNavi2;
11
+ const sequence = useRef(0);
12
+ const pendingConfirmation = ((_snapshot$pendingNavi = snapshot.pendingNavigation) === null || _snapshot$pendingNavi === void 0 ? void 0 : _snapshot$pendingNavi.request.kind) === "confirmEndOrder" ? snapshot.pendingNavigation : void 0;
13
+ const pendingAutomaticExit = ((_snapshot$pendingNavi2 = snapshot.pendingNavigation) === null || _snapshot$pendingNavi2 === void 0 ? void 0 : _snapshot$pendingNavi2.request.kind) === "performSessionExit" ? snapshot.pendingNavigation : void 0;
14
+ const resetSession = useCallback(() => {
15
+ returnToEntry("ui");
16
+ }, [returnToEntry]);
17
+ const requestEndOrder = useCallback(() => {
18
+ sequence.current += 1;
19
+ session.actor.navigate({
20
+ kind: "sessionExit",
21
+ reason: "userRequest"
22
+ }, `ui:${snapshot.sessionEpoch}:exit:${sequence.current}`);
23
+ }, [session.actor, snapshot.sessionEpoch]);
24
+ const cancelEndOrder = useCallback(() => {
25
+ if (!pendingConfirmation) return;
26
+ session.actor.resolvePendingNavigation(pendingConfirmation.navigationId, "cancel");
27
+ }, [pendingConfirmation, session.actor]);
28
+ const confirmEndOrder = useCallback(() => {
29
+ if (!pendingConfirmation || !session.actor.resolvePendingNavigation(pendingConfirmation.navigationId, "allow")) return;
30
+ resetSession();
31
+ }, [
32
+ pendingConfirmation,
33
+ resetSession,
34
+ session.actor
35
+ ]);
36
+ useEffect(() => {
37
+ if (!pendingAutomaticExit || !session.actor.resolvePendingNavigation(pendingAutomaticExit.navigationId, "allow")) return;
38
+ resetSession();
39
+ }, [
40
+ pendingAutomaticExit,
41
+ resetSession,
42
+ session.actor
43
+ ]);
44
+ return {
45
+ endOrderConfirmationOpen: Boolean(pendingConfirmation),
46
+ resetSession,
47
+ requestEndOrder,
48
+ cancelEndOrder,
49
+ confirmEndOrder
50
+ };
51
+ }
52
+ //#endregion
53
+ export { useHDLKioskExitController };
@@ -1,5 +1,5 @@
1
1
  import { useEffect, useState } from "react";
2
- //#region src/components/HDLKiosk/runtime/controllers/useHDLKioskScreenData.ts
2
+ //#region src/components/HDLKiosk/ui/controllers/useHDLKioskScreenData.ts
3
3
  /**
4
4
  * 文件角色:按当前 Screen 集中加载页面所需的 Catalog/称重/定制商品数据。
5
5
  * 运行机制:观察当前节点,调用 Host read/query 能力并输出 loading/ready/error 数据,
@@ -0,0 +1,39 @@
1
+ import { createHDLKioskApplicationRuntime } from "../../runtime/createRuntime.js";
2
+ import { useCallback, useEffect, useMemo, useSyncExternalStore } from "react";
3
+ //#region src/components/HDLKiosk/ui/controllers/useHDLKioskSessionController.ts
4
+ /**
5
+ * 文件角色:把 React Entry 状态适配到无头 Application Runtime。
6
+ * 运行机制:Controller 只处理能力/可见性和 UI pending;Trigger 路由、Session 创建、
7
+ * ensure、单会话准入与销毁均由 Runtime 持有。
8
+ * 边界:不直接创建 Actor,也不消费具体 Screen 的局部交互。
9
+ */
10
+ function useHDLKioskSessionController({ host, config, isActive }) {
11
+ const applicationRuntime = useMemo(() => createHDLKioskApplicationRuntime(host, { config }), [config, host]);
12
+ const snapshot = useSyncExternalStore(applicationRuntime.subscribe, applicationRuntime.getSnapshot, applicationRuntime.getSnapshot);
13
+ useEffect(() => {
14
+ return () => applicationRuntime.dispose();
15
+ }, [applicationRuntime]);
16
+ useEffect(() => {
17
+ if (!isActive) {
18
+ applicationRuntime.deactivate();
19
+ return;
20
+ }
21
+ applicationRuntime.activate();
22
+ return () => applicationRuntime.deactivate();
23
+ }, [applicationRuntime, isActive]);
24
+ const start = useCallback(({ entry }) => applicationRuntime.start(entry), [applicationRuntime]);
25
+ const completeReset = useCallback((completedSession) => applicationRuntime.completeReset(completedSession), [applicationRuntime]);
26
+ const returnToEntry = useCallback((reason = "application") => applicationRuntime.returnToEntry(reason), [applicationRuntime]);
27
+ return {
28
+ session: snapshot.session,
29
+ starting: snapshot.starting,
30
+ startErrorReference: snapshot.startErrorReference,
31
+ returning: snapshot.returning,
32
+ returnError: snapshot.returnError,
33
+ start,
34
+ completeReset,
35
+ returnToEntry
36
+ };
37
+ }
38
+ //#endregion
39
+ export { useHDLKioskSessionController };
@@ -1,6 +1,6 @@
1
1
  import React, { useState } from "react";
2
2
  import { locales } from "@pisell/utils";
3
- //#region src/components/HDLKiosk/app/entry/Screen/index.tsx
3
+ //#region src/components/HDLKiosk/ui/entry/Screen/index.tsx
4
4
  const LANGUAGE_OPTIONS = Object.freeze([
5
5
  {
6
6
  value: "en",
@@ -23,10 +23,12 @@ const LANGUAGE_OPTIONS = Object.freeze([
23
23
  label: "Português"
24
24
  }
25
25
  ]);
26
- function BrandMark() {
27
- return /* @__PURE__ */ React.createElement("span", {
26
+ function BrandMark({ onClick }) {
27
+ return /* @__PURE__ */ React.createElement("button", {
28
28
  className: "hdl-entry-brand-mark",
29
- "aria-label": "Hi Malatang"
29
+ type: "button",
30
+ "aria-label": "打开称重模拟器",
31
+ onClick
30
32
  }, "Hi");
31
33
  }
32
34
  function GlobeIcon() {
@@ -176,7 +178,7 @@ function EntryGraphic({ entry }) {
176
178
  if (entry === "barcode") return /* @__PURE__ */ React.createElement(BarcodeGraphic, null);
177
179
  return /* @__PURE__ */ React.createElement(ScaleGraphic, null);
178
180
  }
179
- function EntryScreen({ locale, model, onLocaleChange, onTechnicalSupportClick, onSelect, busy = false, errorReference, errorMessage = "Unable to start a safe order session." }) {
181
+ function EntryScreen({ locale, model, onLocaleChange, onTechnicalSupportClick, onScaleSimulatorRequest, onSelect, busy = false, errorReference, errorMessage = "Unable to start a safe order session." }) {
180
182
  const [reachMode, setReachMode] = useState(false);
181
183
  const entryLocale = locale || "en";
182
184
  return /* @__PURE__ */ React.createElement("section", {
@@ -202,7 +204,7 @@ function EntryScreen({ locale, model, onLocaleChange, onTechnicalSupportClick, o
202
204
  }, /* @__PURE__ */ React.createElement("path", { d: "M112 248c-52-38-43-88-5-118 33-26 40-71 3-116" })), /* @__PURE__ */ React.createElement("svg", {
203
205
  className: "hdl-entry-steam hdl-entry-steam--two",
204
206
  viewBox: "0 0 180 260"
205
- }, /* @__PURE__ */ React.createElement("path", { d: "M71 250c38-41 22-78-6-111-31-37-19-78 16-125" })), /* @__PURE__ */ React.createElement("span", null), /* @__PURE__ */ React.createElement("span", null), /* @__PURE__ */ React.createElement("span", null), /* @__PURE__ */ React.createElement("span", null), /* @__PURE__ */ React.createElement("span", null), /* @__PURE__ */ React.createElement("span", null)), /* @__PURE__ */ React.createElement("header", { className: "hdl-entry-screen__header" }, /* @__PURE__ */ React.createElement("div", { className: "hdl-entry-brand" }, /* @__PURE__ */ React.createElement(BrandMark, null), /* @__PURE__ */ React.createElement("span", { className: "hdl-entry-brand__copy" }, /* @__PURE__ */ React.createElement("strong", null, locales.getText("pisell2.hdl-kiosk.brand")), /* @__PURE__ */ React.createElement("small", null, "MALA · TANG"))), /* @__PURE__ */ React.createElement("label", { className: "hdl-entry-language" }, /* @__PURE__ */ React.createElement(GlobeIcon, null), /* @__PURE__ */ React.createElement("select", {
207
+ }, /* @__PURE__ */ React.createElement("path", { d: "M71 250c38-41 22-78-6-111-31-37-19-78 16-125" })), /* @__PURE__ */ React.createElement("span", null), /* @__PURE__ */ React.createElement("span", null), /* @__PURE__ */ React.createElement("span", null), /* @__PURE__ */ React.createElement("span", null), /* @__PURE__ */ React.createElement("span", null), /* @__PURE__ */ React.createElement("span", null)), /* @__PURE__ */ React.createElement("header", { className: "hdl-entry-screen__header" }, /* @__PURE__ */ React.createElement("div", { className: "hdl-entry-brand" }, /* @__PURE__ */ React.createElement(BrandMark, { onClick: onScaleSimulatorRequest }), /* @__PURE__ */ React.createElement("span", { className: "hdl-entry-brand__copy" }, /* @__PURE__ */ React.createElement("strong", null, locales.getText("pisell2.hdl-kiosk.brand")), /* @__PURE__ */ React.createElement("small", null, "MALA · TANG"))), /* @__PURE__ */ React.createElement("label", { className: "hdl-entry-language" }, /* @__PURE__ */ React.createElement(GlobeIcon, null), /* @__PURE__ */ React.createElement("select", {
206
208
  "aria-label": locales.getText("pisell2.hdl-kiosk.entry-language-label"),
207
209
  value: entryLocale,
208
210
  onChange: (event) => onLocaleChange === null || onLocaleChange === void 0 ? void 0 : onLocaleChange(event.target.value)
@@ -1,6 +1,6 @@
1
- import { isBuiltInWorkflowProductionReady } from "../workflow/registry.js";
1
+ import { isBuiltInWorkflowProductionReady } from "../../app/workflow/registry.js";
2
2
  import { locales } from "@pisell/utils";
3
- //#region src/components/HDLKiosk/app/entry/model.ts
3
+ //#region src/components/HDLKiosk/ui/entry/model.ts
4
4
  function createEntryScreenModel(config, capabilities, scaleConnectionState, hostStatus, entryDataPreparing = false) {
5
5
  const dataPreparing = entryDataPreparing || hostStatus === "loading";
6
6
  const hostUnavailable = hostStatus === "error";
@@ -0,0 +1,20 @@
1
+ import { createHDLScaleRuntime } from "../runtime/devices/scaleStore.js";
2
+ import React, { createContext, useContext, useSyncExternalStore } from "react";
3
+ //#region src/components/HDLKiosk/ui/scale.tsx
4
+ const HDLScaleRuntimeContext = createContext(createHDLScaleRuntime());
5
+ function HDLScaleRuntimeProvider({ runtime, children }) {
6
+ return React.createElement(HDLScaleRuntimeContext.Provider, {
7
+ value: runtime,
8
+ children
9
+ });
10
+ }
11
+ function useHDLScaleSnapshot() {
12
+ const runtime = useContext(HDLScaleRuntimeContext);
13
+ return useSyncExternalStore(runtime.subscribe, runtime.getSnapshot, runtime.getSnapshot);
14
+ }
15
+ /** 仅供提交边界同步读取点击当下的最新设备快照。 */
16
+ function useHDLScaleRuntime() {
17
+ return useContext(HDLScaleRuntimeContext);
18
+ }
19
+ //#endregion
20
+ export { HDLScaleRuntimeProvider, useHDLScaleRuntime, useHDLScaleSnapshot };
@@ -1,11 +1,6 @@
1
1
  import { useCallback, useRef, useSyncExternalStore } from "react";
2
- //#region src/components/HDLKiosk/runtime/useHostSnapshot.ts
3
- /**
4
- * 文件角色:将 Host Sales Projection 安全接入 React。
5
- * 运行机制:通过 useSyncExternalStore 订阅统一快照,确保同一次 render 读取一致事实并
6
- * 兼容 Host 对象身份稳定、内部来源变化的情况。
7
- * 边界:只读,不触发 load/recalc,也不复制一份 React 订单状态。
8
- */
2
+ //#region src/components/HDLKiosk/ui/snapshots.ts
3
+ /** 将纯 Host 与 Workflow 快照安全接入 React,不发送命令或派生业务事实。 */
9
4
  function useHostSnapshot(host) {
10
5
  const cacheRef = useRef();
11
6
  const getSnapshot = useCallback(() => {
@@ -20,5 +15,8 @@ function useHostSnapshot(host) {
20
15
  }, [host]);
21
16
  return useSyncExternalStore(host.sales.subscribe, getSnapshot, getSnapshot);
22
17
  }
18
+ function useWorkflowSnapshot(actor) {
19
+ return useSyncExternalStore(actor.subscribe, actor.getSnapshot, actor.getSnapshot);
20
+ }
23
21
  //#endregion
24
- export { useHostSnapshot };
22
+ export { useHostSnapshot, useWorkflowSnapshot };
@@ -4,7 +4,7 @@ import { renderFulfillment } from "../slices/fulfillment/view.js";
4
4
  import { renderIdentity } from "../slices/identity/view.js";
5
5
  import { renderPayment } from "../slices/payment/view.js";
6
6
  import { renderPrimaryProductPrompt } from "../slices/primaryProductPrompt/view.js";
7
- //#region src/components/HDLKiosk/app/views.ts
7
+ //#region src/components/HDLKiosk/ui/views.ts
8
8
  const hdlKioskViews = Object.freeze({
9
9
  identity: renderIdentity,
10
10
  fulfillment: renderFulfillment,
@@ -1,6 +1,6 @@
1
1
  import { _objectSpread2 } from "../../../_virtual/_@oxc-project_runtime@0.122.0/helpers/objectSpread2.js";
2
2
  import { _objectWithoutProperties } from "../../../_virtual/_@oxc-project_runtime@0.122.0/helpers/objectWithoutProperties.js";
3
- //#region src/components/HDLKiosk/runtime/workflowEvent.ts
3
+ //#region src/components/HDLKiosk/ui/workflowEvent.ts
4
4
  const _excluded = ["kind"];
5
5
  function createWorkflowEvent(action, currentActivity, stepId, intentId) {
6
6
  if (action.activityId !== currentActivity) return void 0;
@@ -56,10 +56,10 @@ function createCartDrawerModel(sales, primaryWeightedProductId) {
56
56
  totalLabel: totalText ? locales.getText("pisell2.hdl-kiosk.total") : locales.getText("pisell2.hdl-kiosk.total-calculating")
57
57
  });
58
58
  }
59
- function createActivityScreenModel(screenId, snapshot, node, sales, businessMode = "prototype") {
59
+ function createActivityScreenModel(surfaceId, snapshot, node, sales, businessMode = "prototype") {
60
60
  let title;
61
61
  let description;
62
- switch (screenId) {
62
+ switch (surfaceId) {
63
63
  case "entry":
64
64
  title = locales.getText("pisell2.hdl-kiosk.entry-title");
65
65
  description = locales.getText("pisell2.hdl-kiosk.entry-supporting");
@@ -85,12 +85,12 @@ function createActivityScreenModel(screenId, snapshot, node, sales, businessMode
85
85
  description = locales.getText("pisell2.hdl-kiosk.checkout-title");
86
86
  break;
87
87
  }
88
- const canReviewCatalog = screenId !== "catalog" || sales.cart.lineCount > 0;
88
+ const canReviewCatalog = surfaceId !== "catalog" || sales.cart.lineCount > 0;
89
89
  const placeholder = node.readiness === "placeholder";
90
90
  const placeholderBlocked = placeholder && businessMode === "production";
91
91
  const error = resolveHDLKioskErrorPresentation({ error: snapshot.lastError });
92
92
  return Object.freeze({
93
- screenId,
93
+ surfaceId,
94
94
  activity: node.activity,
95
95
  title,
96
96
  description,
@@ -105,7 +105,7 @@ function HDLKioskPaymentRuntime({ context, controllerRef }) {
105
105
  const amount = currentAmount(context);
106
106
  if (amount <= 0) return failed("paymentAmountInvalid", "back");
107
107
  const runtime = runtimeRef.current;
108
- if (!runtime) return unknown("paymentRuntimeUnavailable");
108
+ if (!runtime) return failed("paymentRuntimeUnavailable", "retry");
109
109
  const piProvider = resolvePiPaymentProvider(method.code, Boolean((_engineContext$appHel2 = engineContext.appHelper) === null || _engineContext$appHel2 === void 0 || (_engineContext$appHel2 = _engineContext$appHel2.utils) === null || _engineContext$appHel2 === void 0 || (_engineContext$appHel2 = _engineContext$appHel2.businessUtils) === null || _engineContext$appHel2 === void 0 || (_engineContext$appHel3 = _engineContext$appHel2.isPiPaymentEnabled) === null || _engineContext$appHel3 === void 0 ? void 0 : _engineContext$appHel3.call(_engineContext$appHel2)));
110
110
  let prepared;
111
111
  let shouldDiscardPrepared = false;
@@ -182,6 +182,7 @@ function HDLKioskPaymentRuntime({ context, controllerRef }) {
182
182
  } catch (discardError) {
183
183
  return unknown("eftposPendingRollbackFailed", discardError);
184
184
  }
185
+ if (prepared && !shouldDiscardPrepared) return unknown("eftposPaymentFinalizationUnresolved", error);
185
186
  return failed("eftposPaymentFailed", "retry", error);
186
187
  }
187
188
  });
@@ -6,7 +6,7 @@ function resolveBigSaleHDLKioskCapabilities(context, options = {}) {
6
6
  const canUpdateCustomizedProduct = typeof context.cart.updateItem === "function" && typeof (bookingTicket === null || bookingTicket === void 0 ? void 0 : bookingTicket.transformDetailToProductAndBooking) === "function";
7
7
  return {
8
8
  session: {
9
- ensure: typeof context.sales.createNew === "function",
9
+ ensure: typeof context.sales.createNew === "function" && typeof context.sales.clearCartAndReset === "function",
10
10
  reset: typeof context.sales.clearCartAndReset === "function"
11
11
  },
12
12
  cart: {
@@ -8,6 +8,15 @@ import Decimal from "decimal.js";
8
8
  * 仅在语义变化时推进 observationId。
9
9
  * 边界:Projection 只读且不是第二个 Store;不得在这里执行 load、写入或前端定价。
10
10
  */
11
+ /**
12
+ * 交易门禁必须优先读取 OS 同步真源。SalesSDK reset 已完成但 React RootSnapshot
13
+ * 尚未提交时,context.tempOrder 可能仍是上一笔 paid 订单。
14
+ */
15
+ function resolveBigSaleLiveTempOrder(context) {
16
+ const bookingTicket = context.sales.bookingTicket;
17
+ if (typeof (bookingTicket === null || bookingTicket === void 0 ? void 0 : bookingTicket.getTempOrder) === "function") return bookingTicket.getTempOrder();
18
+ return context.sales.tempOrder;
19
+ }
11
20
  function getProduct(line) {
12
21
  return "product_id" in line ? line : line._extend.product;
13
22
  }
@@ -93,9 +102,10 @@ function projectBigSaleCartLine(line) {
93
102
  });
94
103
  }
95
104
  function normalizePayment(context, cartLineCount) {
96
- var _context$sales$tempOr, _context$sales$tempOr2, _context$sales$tempOr3, _context$summary$summ;
97
- const paymentStatus = String((_context$sales$tempOr = (_context$sales$tempOr2 = context.sales.tempOrder) === null || _context$sales$tempOr2 === void 0 ? void 0 : _context$sales$tempOr2.payment_status) !== null && _context$sales$tempOr !== void 0 ? _context$sales$tempOr : "").toLowerCase();
98
- const orderId = (_context$sales$tempOr3 = context.sales.tempOrder) === null || _context$sales$tempOr3 === void 0 ? void 0 : _context$sales$tempOr3.order_id;
105
+ var _tempOrder$payment_st, _context$summary$summ;
106
+ const tempOrder = resolveBigSaleLiveTempOrder(context);
107
+ const paymentStatus = String((_tempOrder$payment_st = tempOrder === null || tempOrder === void 0 ? void 0 : tempOrder.payment_status) !== null && _tempOrder$payment_st !== void 0 ? _tempOrder$payment_st : "").toLowerCase();
108
+ const orderId = tempOrder === null || tempOrder === void 0 ? void 0 : tempOrder.order_id;
99
109
  const amount = (_context$summary$summ = context.summary.summary) === null || _context$summary$summ === void 0 ? void 0 : _context$summary$summ.total_amount;
100
110
  if (paymentStatus === "paid" && orderId != null && amount != null) return Object.freeze({
101
111
  status: "succeeded",
@@ -118,19 +128,19 @@ function resolveHDLKioskPickupReferenceMode(openData) {
118
128
  return (openData === null || openData === void 0 ? void 0 : openData["fulfillment.fulfillment_ref_mode"]) === "sale_number" ? "sale_number" : "short_number";
119
129
  }
120
130
  function resolvePickupNumber(context, mode) {
121
- var _context$sales$tempOr4;
131
+ var _context$sales$tempOr;
122
132
  const field = mode === "sale_number" ? "shop_order_number" : "shop_full_order_number";
123
- return ((_context$sales$tempOr4 = context.sales.tempOrder) === null || _context$sales$tempOr4 === void 0 ? void 0 : _context$sales$tempOr4[field]) || void 0;
133
+ return ((_context$sales$tempOr = context.sales.tempOrder) === null || _context$sales$tempOr === void 0 ? void 0 : _context$sales$tempOr[field]) || void 0;
124
134
  }
125
135
  function buildSnapshot(context, observationId, pickupReferenceMode) {
126
- var _context$cart$display, _context$sales$tempOr5, _context$sales$tempOr6, _context$sales$tempOr7, _context$sales$tempOr8, _context$customer$sel, _context$customer$sel2, _context$sales$tempOr9, _context$sales$tempOr10, _customer$customerId, _context$sales$tempOr11;
136
+ var _context$cart$display, _context$sales$tempOr2, _context$sales$tempOr3, _context$sales$tempOr4, _context$sales$tempOr5, _context$customer$sel, _context$customer$sel2, _context$sales$tempOr6, _context$sales$tempOr7, _customer$customerId, _context$sales$tempOr8;
127
137
  const rawLines = (_context$cart$display = context.cart.displayLines) !== null && _context$cart$display !== void 0 ? _context$cart$display : context.cart.items;
128
138
  const lines = Object.freeze(rawLines.map(projectBigSaleCartLine).filter((line) => line !== null));
129
139
  const summary = context.summary.summary;
130
140
  const normalizedSummary = summary ? Object.freeze({
131
141
  status: "ready",
132
- currency: String((_context$sales$tempOr5 = (_context$sales$tempOr6 = context.sales.tempOrder) === null || _context$sales$tempOr6 === void 0 ? void 0 : _context$sales$tempOr6.currency_code) !== null && _context$sales$tempOr5 !== void 0 ? _context$sales$tempOr5 : ""),
133
- currencySymbol: String((_context$sales$tempOr7 = (_context$sales$tempOr8 = context.sales.tempOrder) === null || _context$sales$tempOr8 === void 0 ? void 0 : _context$sales$tempOr8.currency_symbol) !== null && _context$sales$tempOr7 !== void 0 ? _context$sales$tempOr7 : ""),
142
+ currency: String((_context$sales$tempOr2 = (_context$sales$tempOr3 = context.sales.tempOrder) === null || _context$sales$tempOr3 === void 0 ? void 0 : _context$sales$tempOr3.currency_code) !== null && _context$sales$tempOr2 !== void 0 ? _context$sales$tempOr2 : ""),
143
+ currencySymbol: String((_context$sales$tempOr4 = (_context$sales$tempOr5 = context.sales.tempOrder) === null || _context$sales$tempOr5 === void 0 ? void 0 : _context$sales$tempOr5.currency_symbol) !== null && _context$sales$tempOr4 !== void 0 ? _context$sales$tempOr4 : ""),
134
144
  total: String(summary.total_amount),
135
145
  due: String(summary.expect_amount)
136
146
  }) : context.sales.status === "loading" ? Object.freeze({ status: "calculating" }) : Object.freeze({ status: "missing" });
@@ -144,7 +154,7 @@ function buildSnapshot(context, observationId, pickupReferenceMode) {
144
154
  ""
145
155
  ].includes(String((_context$customer$sel2 = context.customer.selected.id) !== null && _context$customer$sel2 !== void 0 ? _context$customer$sel2 : "")) })) : void 0;
146
156
  const fingerprintValue = [
147
- (_context$sales$tempOr9 = (_context$sales$tempOr10 = context.sales.tempOrder) === null || _context$sales$tempOr10 === void 0 ? void 0 : _context$sales$tempOr10.order_id) !== null && _context$sales$tempOr9 !== void 0 ? _context$sales$tempOr9 : "",
157
+ (_context$sales$tempOr6 = (_context$sales$tempOr7 = context.sales.tempOrder) === null || _context$sales$tempOr7 === void 0 ? void 0 : _context$sales$tempOr7.order_id) !== null && _context$sales$tempOr6 !== void 0 ? _context$sales$tempOr6 : "",
148
158
  ...lines.map((line) => `${line.lineId}:${line.quantity}`),
149
159
  normalizedSummary.status === "ready" ? normalizedSummary.due : "",
150
160
  (_customer$customerId = customer === null || customer === void 0 ? void 0 : customer.customerId) !== null && _customer$customerId !== void 0 ? _customer$customerId : ""
@@ -152,7 +162,7 @@ function buildSnapshot(context, observationId, pickupReferenceMode) {
152
162
  return Object.freeze({
153
163
  observationId,
154
164
  hostStatus: context.sales.status,
155
- orderId: ((_context$sales$tempOr11 = context.sales.tempOrder) === null || _context$sales$tempOr11 === void 0 ? void 0 : _context$sales$tempOr11.order_id) == null ? void 0 : String(context.sales.tempOrder.order_id),
165
+ orderId: ((_context$sales$tempOr8 = context.sales.tempOrder) === null || _context$sales$tempOr8 === void 0 ? void 0 : _context$sales$tempOr8.order_id) == null ? void 0 : String(context.sales.tempOrder.order_id),
156
166
  pickupNumber: resolvePickupNumber(context, pickupReferenceMode),
157
167
  cart: Object.freeze({
158
168
  lines,
@@ -183,4 +193,4 @@ function createBigSaleProjectionReader(getContext, getPickupReferenceMode = () =
183
193
  };
184
194
  }
185
195
  //#endregion
186
- export { createBigSaleProjectionReader, projectBigSaleCartLine, resolveBigSaleLineId, resolveHDLKioskPickupReferenceMode };
196
+ export { createBigSaleProjectionReader, projectBigSaleCartLine, resolveBigSaleLineId, resolveBigSaleLiveTempOrder, resolveHDLKioskPickupReferenceMode };
@@ -5,7 +5,7 @@ import { buildProductSkuPatch, resolvePatchProductOptions } from "../../../../..
5
5
  import { pickIdentity } from "../../../../../plus/salesSdk/utils/identity.js";
6
6
  import { buildProductLineUpdates } from "../../../../../plus/salesSdk/utils/buildProductLineUpdates.js";
7
7
  import { resolveHDLWeightedProduct } from "../../../../HDLKiosk/product.js";
8
- import { projectBigSaleCartLine, resolveBigSaleLineId } from "./projection.js";
8
+ import { projectBigSaleCartLine, resolveBigSaleLineId, resolveBigSaleLiveTempOrder } from "./projection.js";
9
9
  import { failed, isRecord, partialFailure, readPath, unknown } from "./normalize.js";
10
10
  import { createHDLPrimaryWeightedPreparedProduct } from "./customizationProduct.js";
11
11
  import Decimal from "decimal.js";
@@ -22,6 +22,18 @@ function cancelled(reason) {
22
22
  reason
23
23
  };
24
24
  }
25
+ const PAYMENT_WRITE_FROZEN_STATUSES = new Set(["payment_pending", "processing"]);
26
+ function readPaymentStatus(order) {
27
+ var _order$payment_status;
28
+ return String((_order$payment_status = order === null || order === void 0 ? void 0 : order.payment_status) !== null && _order$payment_status !== void 0 ? _order$payment_status : "").trim().toLowerCase();
29
+ }
30
+ function hasCommittedOrderIdentity(order) {
31
+ const orderId = order === null || order === void 0 ? void 0 : order.order_id;
32
+ return orderId !== null && orderId !== void 0 && String(orderId).trim() !== "";
33
+ }
34
+ function isCommittedPaidOrder(order) {
35
+ return readPaymentStatus(order) === "paid" && hasCommittedOrderIdentity(order);
36
+ }
25
37
  function findCartLine(context, lineId) {
26
38
  var _context$cart$display;
27
39
  return ((_context$cart$display = context.cart.displayLines) !== null && _context$cart$display !== void 0 ? _context$cart$display : context.cart.items).find((line) => resolveBigSaleLineId(line) === lineId);
@@ -272,13 +284,19 @@ function createBigSaleSalesPort({ getContext, getSnapshot, executeScan, writeFul
272
284
  var _ref7 = _asyncToGenerator(function* (signal) {
273
285
  if (signal.aborted) return { status: "cancelled" };
274
286
  const context = getContext();
275
- if (context.sales.tempOrder) return {
287
+ const currentOrder = resolveBigSaleLiveTempOrder(context);
288
+ const currentPaymentStatus = readPaymentStatus(currentOrder);
289
+ if (PAYMENT_WRITE_FROZEN_STATUSES.has(currentPaymentStatus)) return unknown("ensureSessionPaymentInProgress");
290
+ if (currentOrder && !isCommittedPaidOrder(currentOrder)) return {
276
291
  status: "succeeded",
277
292
  data: void 0
278
293
  };
279
294
  try {
280
- yield context.sales.createNew();
295
+ const createdOrder = isCommittedPaidOrder(currentOrder) ? yield context.sales.clearCartAndReset() : yield context.sales.createNew();
281
296
  if (signal.aborted) return unknown("ensureSessionAbortedAfterDispatch");
297
+ const liveCreatedOrder = resolveBigSaleLiveTempOrder(getContext());
298
+ const createdPaymentStatus = readPaymentStatus(liveCreatedOrder !== null && liveCreatedOrder !== void 0 ? liveCreatedOrder : createdOrder);
299
+ if (isCommittedPaidOrder(liveCreatedOrder !== null && liveCreatedOrder !== void 0 ? liveCreatedOrder : createdOrder) || PAYMENT_WRITE_FROZEN_STATUSES.has(createdPaymentStatus)) return unknown("ensureSessionNotWritable");
282
300
  return {
283
301
  status: "succeeded",
284
302
  data: void 0
@@ -1,6 +1,6 @@
1
1
  import { _defineProperty } from "../../../../../_virtual/_@oxc-project_runtime@0.122.0/helpers/defineProperty.js";
2
2
  import { _objectSpread2 } from "../../../../../_virtual/_@oxc-project_runtime@0.122.0/helpers/objectSpread2.js";
3
- import React, { Component, useEffect, useRef } from "react";
3
+ import React, { Component, useCallback, useEffect, useRef, useState } from "react";
4
4
  //#region src/components/bigSale/templates/HDLKiosk/adapter/scaleTrigger.tsx
5
5
  /**
6
6
  * 文件角色:拥有 BigSale 的 useNativeScale Hook,并桥接到 HDLKiosk 全局 Scale Runtime。
@@ -86,11 +86,21 @@ function ActiveScaleRuntimeOwner({ active, hub, minimumWeightKg, ownerId, runtim
86
86
  const consumedReadingRef = useRef(false);
87
87
  const lastConnectionStateRef = useRef();
88
88
  const eventSequenceRef = useRef(0);
89
+ const [sample, setSample] = useState({
90
+ sequence: 0,
91
+ receivedAt: 0
92
+ });
89
93
  const scale = useNativeScale({
90
94
  unit: "KILOGRAMS",
91
95
  precision: 3,
92
96
  tareWeight: 0,
93
- autoStart: active
97
+ autoStart: active,
98
+ onChange: useCallback(() => {
99
+ setSample((current) => ({
100
+ sequence: current.sequence + 1,
101
+ receivedAt: Date.now()
102
+ }));
103
+ }, [])
94
104
  });
95
105
  const inspection = inspectScaleEntrySnapshot(scale, minimumWeightKg);
96
106
  useEffect(() => {
@@ -109,7 +119,8 @@ function ActiveScaleRuntimeOwner({ active, hub, minimumWeightKg, ownerId, runtim
109
119
  connectionState: scale.connectionState,
110
120
  rawData: scale.rawData,
111
121
  isListening: scale.isListening,
112
- error: scale.error
122
+ error: scale.error,
123
+ sampleSequence: sample.sequence
113
124
  });
114
125
  }, [
115
126
  active,
@@ -120,7 +131,8 @@ function ActiveScaleRuntimeOwner({ active, hub, minimumWeightKg, ownerId, runtim
120
131
  scale.grossWeight,
121
132
  scale.isListening,
122
133
  scale.rawData,
123
- scale.status
134
+ scale.status,
135
+ sample.sequence
124
136
  ]);
125
137
  useEffect(() => {
126
138
  if (!active) {
@@ -148,11 +160,12 @@ function ActiveScaleRuntimeOwner({ active, hub, minimumWeightKg, ownerId, runtim
148
160
  return;
149
161
  }
150
162
  if (consumedReadingRef.current) return;
163
+ if (!runtime.getSnapshot().hasLiveSample) return;
151
164
  const grossWeight = inspection.validGrossWeightKg;
152
165
  if (grossWeight === void 0) return;
153
166
  consumedReadingRef.current = true;
154
167
  eventSequenceRef.current += 1;
155
- const occurredAt = Date.now();
168
+ const occurredAt = sample.receivedAt || Date.now();
156
169
  hub.publishWeightChange({
157
170
  eventId: `native-scale-change:${occurredAt}:${eventSequenceRef.current}`,
158
171
  occurredAt,
@@ -168,6 +181,8 @@ function ActiveScaleRuntimeOwner({ active, hub, minimumWeightKg, ownerId, runtim
168
181
  hub,
169
182
  inspection.belowTriggerThreshold,
170
183
  inspection.validGrossWeightKg,
184
+ runtime,
185
+ sample.receivedAt,
171
186
  scale.status
172
187
  ]);
173
188
  return null;
@@ -75,6 +75,9 @@ function useBigSaleHDLKioskHost(context, businessCode, bridge, scaleSourceAvaila
75
75
  }
76
76
  }
77
77
  });
78
+ useEffect(() => {
79
+ projectionListenersRef.current.forEach((listener) => listener());
80
+ });
78
81
  return hostRef.current;
79
82
  }
80
83
  //#endregion
@@ -6,9 +6,9 @@ import { buildVoucherViews } from "../../../../plus/saleDetail/components/Promot
6
6
  import { createSaleWalletAssetsCleanupCoordinator } from "../../../../plus/saleDetail/components/PromotionWalletPanels/useSaleWalletAssets.js";
7
7
  import Base_default from "../../../../plus/saleDetail/Base.js";
8
8
  import localeTexts from "../../../HDLKiosk/locales.js";
9
- import { createHDLScaleRuntime } from "../../../HDLKiosk/devices/scale/runtime.js";
9
+ import { createHDLScaleRuntime } from "../../../HDLKiosk/runtime/devices/scaleStore.js";
10
10
  import HDLKiosk from "../../../HDLKiosk/index.js";
11
- import { resolveHDLKioskConfig } from "../../../HDLKiosk/contracts/config.js";
11
+ import { resolveHDLKioskConfig } from "../../../HDLKiosk/app/contracts/config.js";
12
12
  import { useBigSaleHDLKioskHost } from "./adapter/useBigSaleHDLKioskHost.js";
13
13
  import { useHDLKioskEntryPreparationToast } from "./adapter/useHDLKioskEntryPreparationToast.js";
14
14
  import { HDLKioskPaymentRuntime } from "./adapter/HDLKioskPaymentRuntime.js";
@@ -219,7 +219,7 @@ function HDLKioskBigSaleTemplate({ isActive = true, context, businessCode, local
219
219
  skipsCatalogLoad
220
220
  ]);
221
221
  return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(BigSaleScaleRuntimeOwner, {
222
- active: isActive && (config.enabledEntries.includes("scale") || config.enabledEntries.includes("quick")) && Boolean(config.primaryWeightedProductId),
222
+ active: isActive && (config.enabledEntries.includes("scale") || config.enabledEntries.includes("quick") || config.enabledEntries.includes("barcode")) && Boolean(config.primaryWeightedProductId),
223
223
  hub: scaleTriggerHub,
224
224
  nativeScaleTools,
225
225
  minimumWeightKg: config.scaleTriggerMinimumWeightKg,
@@ -1,4 +1,4 @@
1
- //#region src/components/HDLKiosk/contracts/config.ts
1
+ //#region src/components/HDLKiosk/app/contracts/config.ts
2
2
  const ALL_ENTRY_MODES = Object.freeze([
3
3
  "quick",
4
4
  "barcode",