@pisell/private-materials 6.12.168 → 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.
- package/build/lowcode/assets-daily.json +11 -11
- package/build/lowcode/assets-dev.json +2 -2
- package/build/lowcode/assets-prod.json +11 -11
- package/build/lowcode/meta.js +1 -1
- package/build/lowcode/render/default/view.css +1 -1
- package/build/lowcode/render/default/view.js +10 -10
- package/build/lowcode/view.css +1 -1
- package/build/lowcode/view.js +10 -10
- package/es/components/HDLKiosk/{contracts → app/contracts}/config.js +1 -1
- package/es/components/HDLKiosk/app/manifest.js +11 -11
- package/es/components/HDLKiosk/app/operations.js +92 -0
- package/es/components/HDLKiosk/app/workflow/barcode.js +7 -3
- package/es/components/HDLKiosk/app/workflow/index.js +16 -0
- package/es/components/HDLKiosk/app/workflow/predicates.js +1 -1
- package/es/components/HDLKiosk/app/workflow/quick.js +1 -1
- package/es/components/HDLKiosk/app/workflow/registry.js +4 -4
- package/es/components/HDLKiosk/app/workflow/scale.js +5 -1
- package/es/components/HDLKiosk/docs/00-/346/226/207/344/273/266/345/257/274/350/210/252.md +104 -167
- 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 +95 -89
- package/es/components/HDLKiosk/docs/04-/350/256/276/345/244/207/344/270/216/347/247/260/351/207/215.md +43 -26
- package/es/components/HDLKiosk/docs/05-/344/272/244/346/230/223/345/256/211/345/205/250.md +2 -0
- 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
- 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
- package/es/components/HDLKiosk/docs/README.md +6 -2
- package/es/components/HDLKiosk/docs//345/256/236/346/226/275/350/277/233/345/272/246.md +8 -7
- package/es/components/HDLKiosk/docs//346/236/266/346/236/204/350/256/276/350/256/241.md +16 -18
- package/es/components/HDLKiosk/index.js +22 -28
- package/es/components/HDLKiosk/index.less +1 -1
- package/es/components/HDLKiosk/kernel/README.md +13 -12
- package/es/components/HDLKiosk/kernel/application/defineApplication.js +63 -24
- package/es/components/HDLKiosk/kernel/application/defineSlice.js +6 -6
- package/es/components/HDLKiosk/kernel/application/runtime.js +237 -0
- package/es/components/HDLKiosk/kernel/operations/coordinator.js +1 -1
- package/es/components/HDLKiosk/kernel/operations/registry.js +3 -3
- package/es/components/HDLKiosk/kernel/operations/sessionEpoch.js +1 -1
- package/es/components/HDLKiosk/kernel/operations/types.js +7 -3
- package/es/components/HDLKiosk/kernel/workflow/actor.js +16 -17
- package/es/components/HDLKiosk/kernel/workflow/compiler.js +14 -16
- package/es/components/HDLKiosk/runtime/createRuntime.js +238 -0
- package/es/components/HDLKiosk/{devices → runtime/devices}/dedupeStore.js +1 -1
- package/es/components/HDLKiosk/{devices → runtime/devices}/scaleIngress.js +1 -1
- package/es/components/HDLKiosk/{devices/scale/runtime.js → runtime/devices/scaleStore.js} +18 -24
- package/es/components/HDLKiosk/{devices → runtime/devices}/scannerIngress.js +1 -1
- package/es/components/HDLKiosk/runtime/devices/scannerSessionPort.js +60 -0
- package/es/components/HDLKiosk/runtime/devices/scannerSessionRouter.js +212 -0
- package/es/components/HDLKiosk/runtime/operations/barcode.js +18 -0
- package/es/components/HDLKiosk/runtime/operations/cart.js +44 -0
- package/es/components/HDLKiosk/{app → runtime}/operations/cartConsistency.js +1 -1
- package/es/components/HDLKiosk/{app → runtime}/operations/checkout.js +95 -110
- package/es/components/HDLKiosk/{app → runtime}/operations/checkoutRequirements.js +1 -1
- package/es/components/HDLKiosk/{app → runtime}/operations/checkoutSafety.js +1 -1
- package/es/components/HDLKiosk/{app → runtime}/operations/coordinator.js +2 -2
- package/es/components/HDLKiosk/runtime/operations/customization.js +70 -0
- package/es/components/HDLKiosk/{app → runtime}/operations/errors.js +1 -1
- package/es/components/HDLKiosk/runtime/operations/fulfillment.js +6 -0
- package/es/components/HDLKiosk/runtime/operations/identity.js +55 -0
- package/es/components/HDLKiosk/runtime/operations/registry.js +34 -0
- package/es/components/HDLKiosk/runtime/operations/session.js +29 -0
- package/es/components/HDLKiosk/runtime/operations/types.js +13 -0
- package/es/components/HDLKiosk/runtime/session/blockPolicy.js +14 -0
- package/es/components/HDLKiosk/runtime/{createWorkflowSession.js → session/createSession.js} +67 -17
- package/es/components/HDLKiosk/runtime/{domainTransitionRunner.js → session/transitionRunner.js} +10 -5
- package/es/components/HDLKiosk/runtime/{workflowContext.js → session/workflowContext.js} +2 -2
- package/es/components/HDLKiosk/runtime/{workflowLifecycle.js → session/workflowLifecycle.js} +2 -2
- package/es/components/HDLKiosk/runtime/triggers.js +28 -0
- package/es/components/HDLKiosk/slices/catalog/Screen/index.js +15 -8
- package/es/components/HDLKiosk/slices/catalog/Screen/index.less +74 -13
- package/es/components/HDLKiosk/slices/catalog/slice.js +2 -2
- package/es/components/HDLKiosk/slices/customization/Screen/index.js +34 -35
- package/es/components/HDLKiosk/slices/customization/Screen/index.less +5 -0
- package/es/components/HDLKiosk/slices/customization/slice.js +2 -3
- package/es/components/HDLKiosk/slices/fulfillment/slice.js +2 -2
- package/es/components/HDLKiosk/slices/fulfillment/view.js +1 -1
- package/es/components/HDLKiosk/slices/identity/slice.js +2 -2
- package/es/components/HDLKiosk/slices/identity/view.js +1 -1
- package/es/components/HDLKiosk/slices/payment/slice.js +3 -3
- package/es/components/HDLKiosk/slices/primaryProductPrompt/slice.js +1 -1
- package/es/components/HDLKiosk/{runtime → ui}/HDLKioskWorkflowView.js +43 -129
- package/es/components/HDLKiosk/ui/ScaleSimulatorConsole/index.js +387 -0
- package/es/components/HDLKiosk/ui/ScaleSimulatorConsole/index.less +621 -0
- package/es/components/HDLKiosk/{app → ui}/ScreenRenderer.js +1 -1
- package/es/components/HDLKiosk/ui/controllers/useHDLKioskActionDispatcher.js +66 -0
- package/es/components/HDLKiosk/{runtime → ui}/controllers/useHDLKioskCustomerController.js +1 -1
- package/es/components/HDLKiosk/ui/controllers/useHDLKioskDeviceController.js +25 -0
- package/es/components/HDLKiosk/ui/controllers/useHDLKioskExitController.js +53 -0
- package/es/components/HDLKiosk/{runtime → ui}/controllers/useHDLKioskScreenData.js +1 -1
- package/es/components/HDLKiosk/ui/controllers/useHDLKioskSessionController.js +39 -0
- package/es/components/HDLKiosk/{app → ui}/entry/Screen/index.js +8 -6
- package/es/components/HDLKiosk/{app → ui}/entry/model.js +2 -2
- package/es/components/HDLKiosk/ui/scale.js +20 -0
- package/es/components/HDLKiosk/{runtime/useHostSnapshot.js → ui/snapshots.js} +6 -8
- package/es/components/HDLKiosk/{app → ui}/views.js +1 -1
- package/es/components/HDLKiosk/{runtime → ui}/workflowEvent.js +1 -1
- package/es/components/HDLKiosk/utils.js +4 -4
- package/es/components/bigSale/components/BookingFloatingPanel/useBookingPanelController.js +1 -0
- package/es/components/bigSale/components/TimeBar/index.js +1 -0
- package/es/components/bigSale/dialog.js +1 -0
- package/es/components/bigSale/hooks/useBigSaleContext.js +1 -0
- package/es/components/bigSale/hooks/useSelectFloorMapResourceForBigSale.js +1 -0
- package/es/components/bigSale/index.js +1 -0
- package/es/components/bigSale/templates/HDLKiosk/adapter/HDLKioskPaymentRuntime.js +2 -1
- package/es/components/bigSale/templates/HDLKiosk/adapter/capabilities.js +1 -1
- package/es/components/bigSale/templates/HDLKiosk/adapter/projection.js +21 -11
- package/es/components/bigSale/templates/HDLKiosk/adapter/sales.js +21 -3
- package/es/components/bigSale/templates/HDLKiosk/adapter/scaleTrigger.js +20 -5
- package/es/components/bigSale/templates/HDLKiosk/adapter/useBigSaleHDLKioskHost.js +3 -0
- package/es/components/bigSale/templates/HDLKiosk/index.js +3 -3
- package/es/components/bigSale/templates/Kiosk/index.js +1 -0
- package/es/components/sharedSecondaryBigSale/SharedSecondaryBigSaleReceiver.js +1 -0
- package/es/index.js +2 -0
- package/es/plus/pisellReservation/data/bookingToReservationTables.js +1 -1
- package/es/plus/pisellReservation/floorMap/floorPlanApi.js +1 -1
- package/es/plus/pisellReservation/floorMap/reservationMock.js +1 -1
- package/es/plus/pisellReservation/index.js +17 -0
- package/es/plus/saleDetail/Base.js +1 -0
- package/es/plus/saleDetail/components/Client/hooks/useClientSelectorProps.js +1 -0
- package/es/plus/saleDetail/components/DetailActions/index.js +1 -0
- package/es/plus/saleDetail/components/SummaryFinancialSections/index.js +1 -0
- package/es/plus/saleDetail/index.js +1 -0
- package/es/plus/saleDetail/tmpl/B/components/Dish/index.js +1 -0
- package/es/plus/saleDetail/tmpl/B/index.js +1 -0
- package/es/plus/salesSdk/index.js +52 -0
- package/es/plus/salesSdk/utils/addProductWithFlowDebounced.js +1 -1
- package/es/plus/salesSdk/utils/bookingDate.js +1 -1
- package/es/plus/salesSdk/utils/customerAuthGate.js +1 -1
- package/es/plus/salesSdk/utils/enrichCartLineHolderDisplay.js +1 -1
- package/es/pro/Login2.0/AuthModal.d.ts +1 -1
- package/es/pro/Login2.0/index.d.ts +2 -1
- package/es/pro/Login2.0/shared/types.d.ts +1 -1
- package/lib/components/HDLKiosk/{contracts → app/contracts}/config.js +1 -1
- package/lib/components/HDLKiosk/app/manifest.js +18 -19
- package/lib/components/HDLKiosk/app/operations.js +105 -0
- package/lib/components/HDLKiosk/app/workflow/barcode.js +7 -3
- package/lib/components/HDLKiosk/app/workflow/index.js +16 -0
- package/lib/components/HDLKiosk/app/workflow/predicates.js +1 -0
- package/lib/components/HDLKiosk/app/workflow/quick.js +1 -1
- package/lib/components/HDLKiosk/app/workflow/registry.js +3 -3
- package/lib/components/HDLKiosk/app/workflow/scale.js +5 -1
- package/lib/components/HDLKiosk/docs/00-/346/226/207/344/273/266/345/257/274/350/210/252.md +104 -167
- 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 +95 -89
- package/lib/components/HDLKiosk/docs/04-/350/256/276/345/244/207/344/270/216/347/247/260/351/207/215.md +43 -26
- package/lib/components/HDLKiosk/docs/05-/344/272/244/346/230/223/345/256/211/345/205/250.md +2 -0
- 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
- 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
- package/lib/components/HDLKiosk/docs/README.md +6 -2
- package/lib/components/HDLKiosk/docs//345/256/236/346/226/275/350/277/233/345/272/246.md +8 -7
- package/lib/components/HDLKiosk/docs//346/236/266/346/236/204/350/256/276/350/256/241.md +16 -18
- package/lib/components/HDLKiosk/index.js +25 -31
- package/lib/components/HDLKiosk/index.less +1 -1
- package/lib/components/HDLKiosk/kernel/README.md +13 -12
- package/lib/components/HDLKiosk/kernel/application/defineApplication.js +65 -25
- package/lib/components/HDLKiosk/kernel/application/defineSlice.js +6 -6
- package/lib/components/HDLKiosk/kernel/application/runtime.js +237 -0
- package/lib/components/HDLKiosk/kernel/operations/coordinator.js +1 -1
- package/lib/components/HDLKiosk/kernel/operations/registry.js +3 -3
- package/lib/components/HDLKiosk/kernel/operations/sessionEpoch.js +1 -1
- package/lib/components/HDLKiosk/kernel/operations/types.js +8 -3
- package/lib/components/HDLKiosk/kernel/workflow/actor.js +16 -17
- package/lib/components/HDLKiosk/kernel/workflow/compiler.js +14 -16
- package/lib/components/HDLKiosk/runtime/createRuntime.js +239 -0
- package/lib/components/HDLKiosk/{devices → runtime/devices}/dedupeStore.js +1 -1
- package/lib/components/HDLKiosk/{devices → runtime/devices}/scaleIngress.js +1 -1
- package/lib/components/HDLKiosk/{devices/scale/runtime.js → runtime/devices/scaleStore.js} +17 -27
- package/lib/components/HDLKiosk/{devices → runtime/devices}/scannerIngress.js +1 -1
- package/lib/components/HDLKiosk/runtime/devices/scannerSessionPort.js +60 -0
- package/lib/components/HDLKiosk/runtime/devices/scannerSessionRouter.js +212 -0
- package/lib/components/HDLKiosk/runtime/operations/barcode.js +17 -0
- package/lib/components/HDLKiosk/runtime/operations/cart.js +46 -0
- package/lib/components/HDLKiosk/{app → runtime}/operations/cartConsistency.js +1 -1
- package/lib/components/HDLKiosk/{app → runtime}/operations/checkout.js +97 -112
- package/lib/components/HDLKiosk/{app → runtime}/operations/checkoutRequirements.js +1 -1
- package/lib/components/HDLKiosk/{app → runtime}/operations/checkoutSafety.js +1 -1
- package/lib/components/HDLKiosk/{app → runtime}/operations/coordinator.js +2 -2
- package/lib/components/HDLKiosk/runtime/operations/customization.js +73 -0
- package/lib/components/HDLKiosk/{app → runtime}/operations/errors.js +1 -1
- package/lib/components/HDLKiosk/runtime/operations/fulfillment.js +5 -0
- package/lib/components/HDLKiosk/runtime/operations/identity.js +55 -0
- package/lib/components/HDLKiosk/runtime/operations/registry.js +34 -0
- package/lib/components/HDLKiosk/runtime/operations/session.js +30 -0
- package/lib/components/HDLKiosk/runtime/operations/types.js +14 -0
- package/lib/components/HDLKiosk/runtime/session/blockPolicy.js +14 -0
- package/lib/components/HDLKiosk/runtime/{createWorkflowSession.js → session/createSession.js} +71 -21
- package/lib/components/HDLKiosk/runtime/{domainTransitionRunner.js → session/transitionRunner.js} +10 -5
- package/lib/components/HDLKiosk/runtime/{workflowContext.js → session/workflowContext.js} +2 -2
- package/lib/components/HDLKiosk/runtime/{workflowLifecycle.js → session/workflowLifecycle.js} +2 -2
- package/lib/components/HDLKiosk/runtime/triggers.js +28 -0
- package/lib/components/HDLKiosk/slices/catalog/Screen/index.js +15 -8
- package/lib/components/HDLKiosk/slices/catalog/Screen/index.less +74 -13
- package/lib/components/HDLKiosk/slices/catalog/slice.js +3 -3
- package/lib/components/HDLKiosk/slices/customization/Screen/index.js +35 -36
- package/lib/components/HDLKiosk/slices/customization/Screen/index.less +5 -0
- package/lib/components/HDLKiosk/slices/customization/slice.js +5 -6
- package/lib/components/HDLKiosk/slices/fulfillment/slice.js +3 -3
- package/lib/components/HDLKiosk/slices/fulfillment/view.js +1 -1
- package/lib/components/HDLKiosk/slices/identity/slice.js +4 -4
- package/lib/components/HDLKiosk/slices/identity/view.js +1 -1
- package/lib/components/HDLKiosk/slices/payment/slice.js +5 -5
- package/lib/components/HDLKiosk/slices/primaryProductPrompt/slice.js +1 -1
- package/lib/components/HDLKiosk/{runtime → ui}/HDLKioskWorkflowView.js +44 -130
- package/lib/components/HDLKiosk/ui/ScaleSimulatorConsole/index.js +390 -0
- package/lib/components/HDLKiosk/ui/ScaleSimulatorConsole/index.less +621 -0
- package/lib/components/HDLKiosk/{app → ui}/ScreenRenderer.js +1 -1
- package/lib/components/HDLKiosk/ui/controllers/useHDLKioskActionDispatcher.js +67 -0
- package/lib/components/HDLKiosk/{runtime → ui}/controllers/useHDLKioskCustomerController.js +1 -1
- package/lib/components/HDLKiosk/ui/controllers/useHDLKioskDeviceController.js +26 -0
- package/lib/components/HDLKiosk/ui/controllers/useHDLKioskExitController.js +54 -0
- package/lib/components/HDLKiosk/{runtime → ui}/controllers/useHDLKioskScreenData.js +1 -1
- package/lib/components/HDLKiosk/ui/controllers/useHDLKioskSessionController.js +40 -0
- package/lib/components/HDLKiosk/{app → ui}/entry/Screen/index.js +8 -6
- package/lib/components/HDLKiosk/{app → ui}/entry/model.js +2 -2
- package/lib/components/HDLKiosk/ui/scale.js +24 -0
- package/lib/components/HDLKiosk/{runtime/useHostSnapshot.js → ui/snapshots.js} +6 -7
- package/lib/components/HDLKiosk/{app → ui}/views.js +1 -1
- package/lib/components/HDLKiosk/{runtime → ui}/workflowEvent.js +1 -1
- package/lib/components/HDLKiosk/utils.js +4 -4
- package/lib/components/bigSale/templates/HDLKiosk/adapter/HDLKioskPaymentRuntime.js +2 -1
- package/lib/components/bigSale/templates/HDLKiosk/adapter/capabilities.js +1 -1
- package/lib/components/bigSale/templates/HDLKiosk/adapter/projection.js +21 -10
- package/lib/components/bigSale/templates/HDLKiosk/adapter/sales.js +20 -2
- package/lib/components/bigSale/templates/HDLKiosk/adapter/scaleTrigger.js +19 -4
- package/lib/components/bigSale/templates/HDLKiosk/adapter/useBigSaleHDLKioskHost.js +3 -0
- package/lib/components/bigSale/templates/HDLKiosk/index.js +4 -4
- package/package.json +3 -3
- package/es/components/HDLKiosk/app/constants.js +0 -9
- package/es/components/HDLKiosk/app/operations/barcode.js +0 -22
- package/es/components/HDLKiosk/app/operations/cart.js +0 -60
- package/es/components/HDLKiosk/app/operations/fulfillment.js +0 -11
- package/es/components/HDLKiosk/app/operations/session.js +0 -41
- package/es/components/HDLKiosk/app/operations/types.js +0 -11
- package/es/components/HDLKiosk/devices/entryArbiter.js +0 -33
- package/es/components/HDLKiosk/runtime/controllers/useHDLKioskDeviceController.js +0 -75
- package/es/components/HDLKiosk/runtime/controllers/useHDLKioskScannerController.js +0 -160
- package/es/components/HDLKiosk/runtime/controllers/useHDLKioskSessionController.js +0 -185
- package/es/components/HDLKiosk/runtime/useWorkflowSnapshot.js +0 -12
- package/es/components/HDLKiosk/slices/customization/operation.js +0 -80
- package/es/components/HDLKiosk/slices/identity/operation.js +0 -60
- package/es/private-materials/lowcode/authmodal/meta.d.ts +0 -1
- package/lib/components/HDLKiosk/app/constants.js +0 -9
- package/lib/components/HDLKiosk/app/operations/barcode.js +0 -21
- package/lib/components/HDLKiosk/app/operations/cart.js +0 -62
- package/lib/components/HDLKiosk/app/operations/fulfillment.js +0 -10
- package/lib/components/HDLKiosk/app/operations/session.js +0 -42
- package/lib/components/HDLKiosk/app/operations/types.js +0 -12
- package/lib/components/HDLKiosk/devices/entryArbiter.js +0 -33
- package/lib/components/HDLKiosk/runtime/controllers/useHDLKioskDeviceController.js +0 -76
- package/lib/components/HDLKiosk/runtime/controllers/useHDLKioskScannerController.js +0 -161
- package/lib/components/HDLKiosk/runtime/controllers/useHDLKioskSessionController.js +0 -186
- package/lib/components/HDLKiosk/runtime/useWorkflowSnapshot.js +0 -13
- package/lib/components/HDLKiosk/slices/customization/operation.js +0 -83
- package/lib/components/HDLKiosk/slices/identity/operation.js +0 -60
- /package/es/components/HDLKiosk/{app → ui}/entry/Screen/index.less +0 -0
- /package/lib/components/HDLKiosk/{app → ui}/entry/Screen/index.less +0 -0
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
# Entry 设备事件重构修复报告
|
|
2
|
+
|
|
3
|
+
## 1. 背景
|
|
4
|
+
|
|
5
|
+
本次检查对照 `sc/260817/beta-HDLKiosk` 的 Entry/Flow 设备事件实现,复核无头
|
|
6
|
+
Application Runtime 重构后的扫码与称重链路。目标行为为:
|
|
7
|
+
|
|
8
|
+
- Entry 首码先创建并发布 Catalog Session,再执行 `barcode.consume`;
|
|
9
|
+
- Session 启动期间的后续扫码归属于该 pending Session,不丢码、不另起流程;
|
|
10
|
+
- Scanner 在 Entry、Session 启动中和 Flow 内由同一个无头路由持有;称重由 Entry
|
|
11
|
+
Trigger 与共享 Scale Runtime 分别负责边沿触发和连续状态;
|
|
12
|
+
- inactive、支付完成和 reset 阶段不得由设备事件启动新 Session。
|
|
13
|
+
|
|
14
|
+
## 2. 发现的问题
|
|
15
|
+
|
|
16
|
+
### 2.1 Runtime 在 Kiosk inactive 时仍激活
|
|
17
|
+
|
|
18
|
+
Session Controller 无条件激活 Application Runtime,导致隐藏状态仍订阅 Scanner/Scale。
|
|
19
|
+
除了可能抢占其他页面的扫码焦点,设备事件还可能先执行 `session.ensure`,再被 UI 层销毁。
|
|
20
|
+
|
|
21
|
+
### 2.2 Session 启动窗口内扫码丢失
|
|
22
|
+
|
|
23
|
+
重构后 Entry Trigger 和 Flow Scanner Controller 分开。Session 尚未发布时,Flow
|
|
24
|
+
Controller 因没有 `sessionRef` 忽略扫码;Application Runtime 又因已有 pending start
|
|
25
|
+
拒绝新的自动入口,导致 Barcode 连扫以及 Quick/Scale 启动期间扫码丢失。
|
|
26
|
+
|
|
27
|
+
### 2.3 finished Session 不再占用准入名额
|
|
28
|
+
|
|
29
|
+
Runtime 原先只统计 `session.isActive()`。PaymentCompleted 会让 Actor 进入 `finished`,但
|
|
30
|
+
UI 仍展示支付结果并持有该 Session。在自动 reset 前,扫码或称重可能启动新流程。
|
|
31
|
+
|
|
32
|
+
### 2.4 finished Session 无法显式释放
|
|
33
|
+
|
|
34
|
+
`disposeSession` 对 `isActive() === false` 直接返回,导致 PaymentCompleted reset 后 Actor
|
|
35
|
+
和 Registry 记录没有按调用方预期释放。
|
|
36
|
+
|
|
37
|
+
### 2.5 Entry 与 Flow 同时消费同一设备 Port
|
|
38
|
+
|
|
39
|
+
Application Trigger Adapter 和 Flow Scanner Controller 使用两套 Ingress/支付策略接收
|
|
40
|
+
同一事件。虽然 Operation Coordinator 能避免直接并发写购物车,但会产生重复准入、
|
|
41
|
+
遥测缺口和后续策略漂移风险。
|
|
42
|
+
|
|
43
|
+
### 2.6 Barcode-only 配置不激活 Scale Runtime
|
|
44
|
+
|
|
45
|
+
Barcode Workflow 可以进入 Customization,但 BigSale Scale Runtime 只在 Quick/Scale
|
|
46
|
+
入口启用。仅开启 Barcode 时,称重详情无法取得有效秤快照。
|
|
47
|
+
|
|
48
|
+
## 3. 修复方案
|
|
49
|
+
|
|
50
|
+
### 3.1 可逆 Runtime 生命周期
|
|
51
|
+
|
|
52
|
+
Application Runtime 新增 `deactivate()`:释放 Trigger Adapter cleanup,但保留现有
|
|
53
|
+
Session。Session Controller 根据 `isActive` 激活或停用 Runtime。每次 activate 同时推进
|
|
54
|
+
`activationEpoch`;旧激活周期创建的 Session 即使在重新 active 后才完成,也会被识别为
|
|
55
|
+
迟到结果并 dispose,不会跨生命周期发布。
|
|
56
|
+
|
|
57
|
+
### 3.2 显式 Session 所有权准入
|
|
58
|
+
|
|
59
|
+
Runtime 使用 owned Session 集合控制 `maxActiveSessions`。Session 即使自然 finished,
|
|
60
|
+
在显式 `disposeSession` 前仍占用名额。`disposeSession` 现在允许释放 finished Session。
|
|
61
|
+
|
|
62
|
+
### 3.3 单一 ScannerSessionRouter
|
|
63
|
+
|
|
64
|
+
移除组合层 `PendingStartupScan` 和 React `useHDLKioskScannerController`。无头
|
|
65
|
+
`ScannerSessionRouter` 唯一订阅 Scanner,并用一条 FIFO 覆盖三种阶段:
|
|
66
|
+
|
|
67
|
+
- `idle`:首码入队后同步进入 `starting`,再发出 `onScan` 启动请求;
|
|
68
|
+
- `starting`:Quick/Scale/Barcode 启动期间的扫码继续追加到同一队列;
|
|
69
|
+
- `active`:Flow 新扫码仍追加到同一队列,并由当前 Session 串行消费。
|
|
70
|
+
|
|
71
|
+
因此启动窗口的 B 码一定早于 Session 发布后到达的 C 码,不再存在两条队列交叉导致
|
|
72
|
+
`A → C → B` 的可能。
|
|
73
|
+
|
|
74
|
+
每次启动以 `cause.correlationId` 作为 `startId`。`begin/bind/fail` 必须携带相同 startId,
|
|
75
|
+
旧启动的迟到 rejected 无权清理新启动队列。
|
|
76
|
+
|
|
77
|
+
队列最多容纳 5 个未完成任务(running 也计入);超限、启动失败、inactive、Session
|
|
78
|
+
dispose 或前一任务结果不确定时,剩余任务都会收到结构化拒绝遥测,且不记录原始条码。
|
|
79
|
+
当 Host 返回 `requiresSelection` 时,拒绝选择态建立前已经排队的旧任务并结束本轮
|
|
80
|
+
drain。Router 不为尚不存在的 Host 完成协议维护永久冻结状态;选择弹层由 Scanner
|
|
81
|
+
focus stack 临时接管物理扫码,关闭后新扫码重新按正常准入处理。
|
|
82
|
+
|
|
83
|
+
### 3.4 `onStarted` 回归生命周期职责
|
|
84
|
+
|
|
85
|
+
`onStarted` 只调用 `scannerRouter.bindSession(session)`。它不保存队列、不解释
|
|
86
|
+
`barcode.consume`,也不直接执行业务。Router 只有在 Registry 已发布 `started` 后才开始
|
|
87
|
+
drain,保留“先进入 Flow,再消费 code”的业务时序。Session 显式 dispose 后 Router
|
|
88
|
+
release 并回到 `idle`。
|
|
89
|
+
|
|
90
|
+
### 3.5 Router 与业务 Command 解耦
|
|
91
|
+
|
|
92
|
+
Router 只依赖 `ScannerSessionPort`,不再 import `HDLKioskWorkflowSession`,也不包含
|
|
93
|
+
`barcode.consume`、支付 Operation ID 或页面 Activity。具体可写策略、导航取消和
|
|
94
|
+
Command 映射集中在 `scannerSessionPort.ts` 适配层,并增加架构边界测试防止回流。
|
|
95
|
+
|
|
96
|
+
### 3.6 执行中任务的取消与代际隔离
|
|
97
|
+
|
|
98
|
+
Session dispose 现在同时 dispose Operation Coordinator,触发其 AbortController,避免
|
|
99
|
+
仍在执行的扫码 Command 泄漏到已销毁 Session。单纯 inactive 会保留 Session,因此不
|
|
100
|
+
强杀可能已经写入 Host 的操作;Router 会推进 generation,并把迟到结果标为 stale,
|
|
101
|
+
禁止它冻结、清理或继续驱动新激活周期的队列。
|
|
102
|
+
|
|
103
|
+
### 3.7 选择态的最小处理
|
|
104
|
+
|
|
105
|
+
`requiresSelection` 只承担当前已知事实:拒绝此前积压任务并停止本轮 drain。不新增
|
|
106
|
+
无生产调用方的 resume API,也不维护无法被当前 Host 协议可靠解除的冻结状态。未来若
|
|
107
|
+
Host 提供正式完成事件,再按实际契约补充等待语义。
|
|
108
|
+
|
|
109
|
+
### 3.8 Barcode Scale Runtime
|
|
110
|
+
|
|
111
|
+
BigSale Scale Runtime 的激活条件补充 Barcode 入口,确保 Barcode Flow 进入
|
|
112
|
+
Customization 后仍能获得实时秤快照。
|
|
113
|
+
|
|
114
|
+
BigSale Scanner focus 保持标准栈语义,不设置永久高优先级:HDLKiosk active 时位于全局
|
|
115
|
+
扫码监听之上,后打开的选择或搜索弹层仍可临时接管,关闭后自然恢复。同步修正了遗留
|
|
116
|
+
测试对 `priority: 100` 的错误预期。
|
|
117
|
+
|
|
118
|
+
### 3.9 Scale 提交安全补强
|
|
119
|
+
|
|
120
|
+
Scale Runtime 增加唯一的 `sampleSequence`,仅由 NativeScale 的真实 `onChange` 帧
|
|
121
|
+
推进。断连、停止监听、读取错误、负重或超载会使当前采样失效;重连但未收到新帧时不
|
|
122
|
+
恢复 Next。这里没有增加固定读数超时:顾客将商品放稳后长时间选择规格属于正常场景。
|
|
123
|
+
|
|
124
|
+
Customization 的展示与提交复用同一个纯校验,提交回调不再信任上一次 React render,
|
|
125
|
+
而是在点击 Next 时同步读取 Runtime 最新快照并冻结当下稳定重量。SkuDetailModal 的
|
|
126
|
+
实时 Auto 模式同步收紧为只有 liveData、listening、connected、stable 且无错误时有效;
|
|
127
|
+
员工 Manual 和编辑态尚未 re-read 的历史快照行为保持不变。
|
|
128
|
+
|
|
129
|
+
## 4. 修复后的关键时序
|
|
130
|
+
|
|
131
|
+
```text
|
|
132
|
+
Entry 首码
|
|
133
|
+
→ ScannerIngress
|
|
134
|
+
→ ScannerSessionRouter FIFO
|
|
135
|
+
→ onScan occurrence
|
|
136
|
+
→ session.ensure
|
|
137
|
+
→ Registry started(Catalog 已发布)
|
|
138
|
+
→ onStarted.bindSession
|
|
139
|
+
→ barcode.consume(同一 FIFO 串行 drain)
|
|
140
|
+
|
|
141
|
+
Flow 内扫码
|
|
142
|
+
→ 同一个 ScannerSessionRouter FIFO
|
|
143
|
+
→ barcode.consume
|
|
144
|
+
|
|
145
|
+
Entry 称重
|
|
146
|
+
→ ScaleIngress
|
|
147
|
+
→ onWeight occurrence
|
|
148
|
+
→ Scale Session / Customization
|
|
149
|
+
|
|
150
|
+
Flow 内称重
|
|
151
|
+
→ BigSale Scale owner
|
|
152
|
+
→ HDLScaleRuntime snapshot
|
|
153
|
+
→ Customization measurement
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
## 5. 验证
|
|
157
|
+
|
|
158
|
+
新增或补强以下回归覆盖:
|
|
159
|
+
|
|
160
|
+
- Runtime deactivate/re-activate 与 Adapter cleanup;
|
|
161
|
+
- 旧 activation epoch 的迟到 Session 不会在重新激活后发布;
|
|
162
|
+
- 旧 startId 的迟到失败不会清理新启动队列;
|
|
163
|
+
- finished Session 在 dispose 前继续阻止准入;
|
|
164
|
+
- finished Session 可被显式 dispose;
|
|
165
|
+
- Barcode 首码先发布 Catalog,再加购;
|
|
166
|
+
- Barcode 启动期间连续扫码按顺序消费;
|
|
167
|
+
- 启动窗口旧码与 Flow 新码严格保持单一 FIFO 顺序;
|
|
168
|
+
- Quick 启动期间扫码绑定 Quick Session;
|
|
169
|
+
- Quick-only 配置仍允许 Flow 内扫码,但不允许扫码作为 Entry;
|
|
170
|
+
- `requiresSelection` 拒绝旧队列任务,但不会永久冻结 Session 的后续扫码;
|
|
171
|
+
- inactive 前已执行的扫码结果按 generation 隔离,不影响重新激活后的队列;
|
|
172
|
+
- Session dispose 会取消仍在执行的 Operation;
|
|
173
|
+
- owned/finished Session 阶段扫码和称重不能启动新流程;
|
|
174
|
+
- inactive Runtime 不持有设备订阅、不执行 `session.ensure`;
|
|
175
|
+
- React Session Controller 随 `isActive` 激活/释放 Trigger。
|
|
176
|
+
|
|
177
|
+
扩展轻量测试结果:HDLKiosk 50 个测试文件、271 项测试全部通过;BigSale HDLKiosk
|
|
178
|
+
适配层 11 个测试文件、73 项测试全部通过。
|
|
179
|
+
|
|
180
|
+
Scale 安全补强后再次合并运行 HDLKiosk、BigSale HDLKiosk Adapter 与
|
|
181
|
+
`pro/skuDetailModal`:68 个测试文件、429 项测试全部通过。
|
|
182
|
+
|
|
183
|
+
补充 `tsc --noEmit` 未能形成有效项目级结论:当前安装的
|
|
184
|
+
`node_modules/@types/react/index.d.ts` 在 `HTMLAttributes` 附近存在结构损坏,且仓库内
|
|
185
|
+
已有 `.ts` 测试文件包含 JSX,编译在进入本次修改源码前即失败。
|
|
186
|
+
|
|
187
|
+
未运行 `pnpm`/`npm` webpack build,符合本工作区 Material 项目的验证约束。
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# HDLKiosk 文档导航
|
|
2
2
|
|
|
3
3
|
> 当前阶段:架构骨架已完成,后续重点是正式 Host 业务契约、真实设备/支付验收和 UI 还原。
|
|
4
|
-
> 更新日期:2026-08-
|
|
4
|
+
> 更新日期:2026-08-23
|
|
5
5
|
|
|
6
6
|
## 1. 从哪里开始
|
|
7
7
|
|
|
@@ -15,6 +15,8 @@
|
|
|
15
15
|
6. [03-业务流程与交互规则.md](./03-业务流程与交互规则.md):理解三入口和当前权威流程;
|
|
16
16
|
7. [07-后续工作.md](./07-后续工作.md):选择下一项业务或 UI 工作。
|
|
17
17
|
|
|
18
|
+
理解或修改无头 Application Runtime 时,阅读 [08-无头 Application Runtime 重构设计.md](./08-无头Application运行时重构设计.md)。该文档同时记录已实现边界和剩余工作。
|
|
19
|
+
|
|
18
20
|
按任务类型阅读:
|
|
19
21
|
|
|
20
22
|
| 任务 | 必读文档 |
|
|
@@ -24,6 +26,7 @@
|
|
|
24
26
|
| 修改扫码、称重或入口自动触发 | `04-设备与称重`、`03-业务流程与交互规则` |
|
|
25
27
|
| 还原 UI、文案和交互 | `03-业务流程与交互规则`、原型 `kiosk/app/page.tsx` |
|
|
26
28
|
| 编写测试或准备实机验收 | `06-测试与验收`、`07-后续工作` |
|
|
29
|
+
| 实施无头 Application、Trigger 或 Runtime | `08-无头 Application Runtime 重构设计`、`01-核心运行机制` |
|
|
27
30
|
|
|
28
31
|
## 2. 常驻文档
|
|
29
32
|
|
|
@@ -39,6 +42,7 @@
|
|
|
39
42
|
| [06-测试与验收.md](./06-测试与验收.md) | 自动测试层级、异常矩阵、实机门禁 | 项目排期 |
|
|
40
43
|
| [07-后续工作.md](./07-后续工作.md) | 未完成业务、UI 和生产化优先级 | 已完成历史 |
|
|
41
44
|
| [实施进度.md](./实施进度.md) | 当前事实快照、临时开关、最近关键变更 | 完整设计论证 |
|
|
45
|
+
| [08-无头Application运行时重构设计.md](./08-无头Application运行时重构设计.md) | Application/Runtime/Session、Trigger Channel、Contract/Binding 的实现边界与状态 | 具体业务流程 |
|
|
42
46
|
|
|
43
47
|
## 3. 事实优先级
|
|
44
48
|
|
|
@@ -62,4 +66,4 @@
|
|
|
62
66
|
- Workflow 节点顺序改变:先更新 `03-业务流程与交互规则.md`,再改代码;
|
|
63
67
|
- 新增临时兼容策略:必须在 `实施进度.md` 登记开关、影响、退出条件和风险;
|
|
64
68
|
- 已完成的分步清单、一次性论证和测试流水不再新建独立文档;
|
|
65
|
-
- 文档不复制大段类型定义,详细字段以 `components/HDLKiosk/contracts` 为准。
|
|
69
|
+
- 文档不复制大段类型定义,详细字段以 `components/HDLKiosk/app/contracts` 为准。
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
| Operation/Coordinator | 本地完成 | 冲突、去重、epoch、timeout、freeze | 真实 OS 时序验证 |
|
|
33
33
|
| 表现层目录与边界 | 本地完成 | Screen/Dialog/Layout 独立目录与样式;Renderer/View Model 集中在 Presentation;Shell 通过 BottomBarHost 唯一挂载 FloatingBar/CartDrawer | 后续逐 Screen 声明 BottomBar,不在 Screen 内重复挂载容器 |
|
|
34
34
|
| Quick 主商品 | 待实机 | 模板临时商品 ID 通过 OS query 获取;Fulfillment 后进入 Customization,本地保留称重/options 草稿,Next 才交给 OS 加购,价格只消费 OS Projection | 正式商品 ID 配置、真秤及真实折扣验收 |
|
|
35
|
-
| Barcode | 待实机 |
|
|
35
|
+
| Barcode | 待实机 | 无头 ScannerSessionRouter 在 active 生命周期常驻;Entry、启动中和 Flow 共用 5 项 FIFO,首码等待 Session 发布后串行加购且不导航 | 商品码专用 Host API、选择态闭环、稳定 eventId、全局反馈与实机 |
|
|
36
36
|
| Scale | 待实机 | 顶层 Runtime、自动入口;有效重量先进入 Fulfillment,再进入与 Quick 共用的 Customization,本地草稿在 Next 时提交 | 真秤全矩阵、正式商品 |
|
|
37
37
|
| Catalog | 待实机 | HDLKiosk 模板驱动现有 retail Product Provider 正式 load 后读取快照;分类/搜索/商品卡、连续加购、订单悬浮栏及购物车 Drawer 已完成 | 大目录虚拟化、复杂规格接管、实机视觉 |
|
|
38
38
|
| Cart Overlay | 待业务/实机 | 已替代独立 Review/Voucher Slice;复用全局 BottomBar,展示 Host 商品、数量、卡券入口、小计和备注能力 | 称重/定制重新编辑、价格变化反馈、促销/税/节省明细 |
|
|
@@ -94,8 +94,8 @@
|
|
|
94
94
|
- BigSale 公共边界收缩后,Adapter 纯逻辑定向回归 4 个测试文件、42 个用例通过;Hook 用例因工作区缺少 `@testing-library/react` 未能启动,完整 `tsc` 仍被本地 `node_modules/@types/react/index.d.ts` 的既有语法损坏阻断;本轮变更文件已通过 esbuild 语法转换检查;
|
|
95
95
|
- Entry 首版复用了原型主视觉和 SVG 动效,在 1080×1920 画布与原型逐项对照:Quick 卡原型 `y=773.0`、当前 `y=769.8`,卡片宽高、三卡总高度与底部工具区位置一致;同时增加 1280×720 横屏降级布局;
|
|
96
96
|
- Entry 的英文/简中切换与 Reach Mode 已在独立预览中验证;Reach Mode 将主操作区从约 `y=604` 下移到 `y=849`,不改变 Workflow/设备入口语义;Less 编译和 Entry esbuild bundle 通过,入口与共享展示投影 7 个用例通过;React 组件测试仍被工作区缺少 `@testing-library/react` 阻断;
|
|
97
|
-
- 表现层按所有权组织:业务私有 Screen/Dialog、ViewModel 与 `slice.ts`、`view.tsx` 同置于 `slices/<name>/`;跨 Slice 的 Shell、Overlay 和公共控件位于 `components/`,公共类型与纯方法分别位于根 `types.ts`、`utils.ts`;活跃会话 UI 编排位于 `
|
|
98
|
-
- 组件依赖门禁递归覆盖 `slices/`、`components/` 与 `
|
|
97
|
+
- 表现层按所有权组织:业务私有 Screen/Dialog、ViewModel 与 `slice.ts`、`view.tsx` 同置于 `slices/<name>/`;跨 Slice 的 Shell、Overlay 和公共控件位于 `components/`,公共类型与纯方法分别位于根 `types.ts`、`utils.ts`;活跃会话 UI 编排位于 `ui/HDLKioskWorkflowView.tsx`;
|
|
98
|
+
- 组件依赖门禁递归覆盖 `slices/`、`components/` 与 `ui/entry`;Slice 业务定义不依赖 React,Workflow/Operation 纯逻辑测试不会加载物料 UI;
|
|
99
99
|
- Identity 已从通用 Step 拆成独立 Screen,并按原型还原沉浸式品牌区、会员利益标题、App QR、SMS 和 Skip;Shell 使用显式 `identityGate` 变体隐藏常规页头/页脚。SMS 无业务 handler,Skip 复用既有 Guest `identity.sync`;109 个纯逻辑用例、Less 编译和根入口 esbuild bundle 继续通过;
|
|
100
100
|
- Fulfillment 已从通用 Step 拆成独立 Screen,完成堂食/外带卡片及自动前进;BottomBar 不再假定该节点位于空订单阶段,实时购物车有商品时组合通用 `HDLKioskOrderSummary` 和可编辑 CartDrawer,显示 OS 确认的数量/金额;空车时仅保留 Back。Drawer 在此节点不伪造 Next,用户仍需在页面选择堂食或外带;
|
|
101
101
|
- Customization 已完成称重主商品详情首版并按原型校准:Hero 固定,只有 options 区滚动;称重栏保留状态标识与 Unit Price/Weight/Tare;规格分组 Tab 在 HDLKiosk 作用域隐藏,不修改共享 `SKUOptionsSelection`。重量/options 只保留页面本地草稿,Next 才交给 OS `addProductWithFlow`,成功后前进;底栏和 Drawer 只使用 OS `summary.due`,不自行估算折扣;
|
|
@@ -112,17 +112,18 @@
|
|
|
112
112
|
- Barcode 当前使用“激活 Session → 消费首码 → Catalog → 缺主商品时询问 → Yes 时 Fulfillment → 称重详情 → Next/OS 加购成功 → Catalog”的路径;No 保持在 Catalog 且不要求 Fulfillment,Cart Overlay 完成订单复核与卡券操作;
|
|
113
113
|
- 移除遗留 `hdl-shell__footer` 与 `resolveScreenBottomBar`:Fulfillment、Customization、Catalog 改为声明实时 BottomBar,由 Shell 内唯一 `HDLKioskBottomBarHost` 渲染。BottomBar 当前区分 `visible / masked / hidden`:退出确认及 Catalog 主商品询问等普通 Modal 保留底栏并由遮罩阻止交互,同时自动收起 CartDrawer;只有等待员工、支付未决和 blocked 等不可导航状态才隐藏。购物车图标已接入基于 `CompensatedPisellContainer` 的底部 Drawer,展示 Host 已确认的商品、定制摘要、数量和金额,并在三个 Catalog workflow 中复用既有改数量/删除 Operation;
|
|
114
114
|
- Workflow 使用线性优先的 Slice 数组:数组表达主路径,Slice Intent 通过 `next()` 或 `navigate: 'next'` 补齐默认前进,`on` 只描述分支、合流和跳跃;Back 是独立 Navigation,并按实际页面历史解析。同一 Slice 可用 `slice:用途` 多次出现,回路必须声明有限 repeat,Actor 超限即阻塞;Intent 同时携带 `stepId/activityId`,避免同类 Activity 的迟到实例误触发当前 Step。支付不确定是 Actor blocked 状态,不作为业务节点;
|
|
115
|
-
- `slices/<name>/slice.ts` 是各业务能力唯一导出的 `defineSlice` 结果:Slice `id` 标识业务 Activity,`
|
|
116
|
-
- Kernel 已不依赖 HDLKiosk contracts:结构 Compiler、Actor 和通用 Coordinator 位于 `kernel
|
|
115
|
+
- `slices/<name>/slice.ts` 是各业务能力唯一导出的 `defineSlice` 结果:Slice `id` 标识业务 Activity,`surface.id` 标识页面类别;`view.tsx` 就地完成该 Slice 的 ViewModel 派生和组件装配,`ui/views.ts` 单独维护完整的 Activity → View 本地注册表,`ScreenRenderer` 进行同步解析。Kernel、Slice 和 Workflow 不依赖 React View;公共类型与跨 Slice 纯方法分别集中在根 `types.ts`、`utils.ts`;
|
|
116
|
+
- Kernel 已不依赖 HDLKiosk contracts:结构 Compiler、Actor 和通用 Coordinator 位于 `kernel/`;Application 契约位于 `app/contracts`,具体 Host Handler 与 Coordinator 位于 `runtime/operations/`,其中注入 HDLKioskHost、冲突矩阵、支付冻结、错误分类和遥测;
|
|
117
117
|
- HDLKiosk 阻断式 Dialog 已统一到 `HDLKioskModal → PisellModal`,默认层级高于 CartDrawer;BottomBar 的三态解析、组件依赖边界、Checkout 安全及现有 Dialog/Screen 定向用例通过,HDLKiosk 汇总 Less 编译、变更组件 esbuild 语法转换和 `git diff --check` 通过;
|
|
118
118
|
- Shell 中途登录统一走 `executeCommand(identity.sync)`;明确失败可在原页重试,客户写入/重报价 `partial/unknown` 会阻塞 Actor。物料不维护 idle 警告或倒计时 UI;Session Controller 提供验证式 `returnToEntry` 接口,未来由应用级策略决定是否和何时触发;
|
|
119
119
|
- Checkout 前置业务要求由 Activity Contract 声明 ID,Compiler 按当前流程汇总,Requirement Registry 结合 Workflow Context 和 Host Projection 判断适用性与满足状态。当前默认 Registry 为空;
|
|
120
120
|
- 称重页的 Next 携带点击当下的商品/重量/options 草稿;点击前不同步 Host。详情页与 Scale 入口共用最小有效重量,稳定的微小残留不会启用 Next;
|
|
121
|
+
- Scale Runtime 以 NativeScale `onChange` 的递增采样序号区分真实新帧:断连、停止监听、读取错误、负重或超载后必须收到新帧才恢复;稳定读数不使用固定超时。Next 点击时同步复核 Runtime 最新快照,SkuDetailModal 实时 Auto 同步要求 live/stable/connected/listening;
|
|
121
122
|
- Barcode/Scale 已收敛为会话外部入口,不再伪装成可前进/后退的 Workflow Activity。Barcode 首码在 Session `readyForCommands && cartWritable` 后消费,不依赖首屏类型;Scale Workflow 当前从 Fulfillment 开始。两者的首页 Back 因无 Workflow 前驱而自然落入会话级清单并回 Entry,无需“入口节点不可回访”特例;
|
|
122
|
-
- Scanner
|
|
123
|
+
- Scanner 订阅已收敛到无头 `ScannerSessionRouter`;Entry、pending Quick/Scale 和 Flow 扫码共享同一有限 FIFO,`onStarted` 只绑定已发布 Session,React 不再持有扫码硬件。Catalog transition 不再绑定 `checkout.prepare`,EFTPOS、店员授权和通用 checkout 在 dispatch 前统一检查 Prepared freshness;
|
|
123
124
|
- 临时 live-debug reporter、密钥、日志和 Collector 已清理;
|
|
124
125
|
- 日常验证遵守工作区规则,未使用 pnpm/npm 运行 material webpack build。
|
|
125
|
-
- 当前目录职责为 `
|
|
126
|
+
- 当前目录职责为 `kernel / app / slices / runtime / ui / components / testing`;共享阻断表面使用 `BlockingNotice`,履约写入由 Checkout Prepare 统一完成。
|
|
126
127
|
|
|
127
128
|
本地 `468867` 参考文件不再参与运行时 import;无需恢复或维护为可执行 mock。
|
|
128
129
|
|
|
@@ -60,11 +60,11 @@ flowchart TB
|
|
|
60
60
|
POLICY["HDLKiosk Workflow Policy"]
|
|
61
61
|
RUNNER["HDLKiosk Transition Runner"]
|
|
62
62
|
LIFECYCLE["Workflow Lifecycle"]
|
|
63
|
-
OPS["
|
|
63
|
+
OPS["runtime/operations<br/>Host Operation Handlers"]
|
|
64
64
|
OP_POLICY["HDLKiosk Operation Policy<br/>Host Context / Conflict / Telemetry"]
|
|
65
65
|
SAFETY["Checkout Safety"]
|
|
66
66
|
REQUIREMENT["Checkout Requirement Registry"]
|
|
67
|
-
VIEW["
|
|
67
|
+
VIEW["ui/views Registry<br/>ScreenRenderer"]
|
|
68
68
|
UI["Slice Screens / Shared Components"]
|
|
69
69
|
|
|
70
70
|
HOST --> PROJ
|
|
@@ -107,17 +107,18 @@ Kernel ✕ HDLKiosk contracts / BigSale / SalesSDK / merchant workflows / Screen
|
|
|
107
107
|
| Contracts/Ports | HDLKiosk 自有 DTO、能力和结果语义 | BigSale 字段兼容 |
|
|
108
108
|
| Projection | 标准化 Host 可观察事实 | 发业务命令 |
|
|
109
109
|
| Slice | 将 Screen、合法 Intent、局部 Command、退出 Effect 和 Requirement 收敛为业务能力 | 前后节点和 Host 实现 |
|
|
110
|
-
| Application
|
|
110
|
+
| Application Definition | 汇总 Activity、Workflow、Trigger 与 Operation Contract | Handler、React 生命周期和订单事实 |
|
|
111
|
+
| Application Runtime | Trigger 路由、Admission、Session Registry 和无头启动 | 业务方法实现和 React Presentation |
|
|
111
112
|
| Structural Compiler | Step ID、相邻导航、可达性、终点、Modal 和有界循环 | 支付和购物车策略 |
|
|
112
113
|
| HDLKiosk Policy | 编译后检查支付来源和 Checkout Prepare 等交易约束 | 修改节点结构 |
|
|
113
114
|
| Workflow Actor | mailbox、step/activity 防迟到、running/blocked、节点提交和循环计数 | Host、Predicate、Operation、支付解释和持久化 |
|
|
114
115
|
| Transition Runner | 求值 Predicate/执行 Exit Command,将结果归一为 advance/stay/blocked | React、节点数组位置 |
|
|
115
|
-
|
|
|
116
|
+
| Operation Bindings | 为 Contract 注入 Host Command 和写后验证 | Screen 导航、Workflow 拓扑 |
|
|
116
117
|
| Requirement Registry | 判断支付前业务要求对当前订单是否适用,并校验 Host Projection | Workflow 节点编排和 UI |
|
|
117
118
|
| Kernel Coordinator | 用应用注入的 Context/Scope/Policy 处理冲突、去重、timeout 和 epoch | 支付含义、Host、业务错误和节点目标 |
|
|
118
119
|
| HDLKiosk Operation Policy | 注入 Host Context、冲突矩阵、支付 freeze、错误分类和遥测 | Screen 导航 |
|
|
119
120
|
| Workflow | 用有序 Slice 数组表达主路径,以 `on` 描述分支、合流和受限回路 | Screen 内部动作和订单事实 |
|
|
120
|
-
| Controllers |
|
|
121
|
+
| Controllers | React/设备输入适配和验证式 `returnToEntry` | 创建 Actor、拥有 Runtime Session Registry |
|
|
121
122
|
| View assembly | 把 Activity 节点和 Projection 转换为组件输入,并路由 Intent/Navigation/Command | 决定目标节点 |
|
|
122
123
|
| Screens/Dialogs/Layouts | 展示、局部输入、Screen Command、Activity Intent 和 Back Navigation | 直接调用 Host、Actor 或 Controller |
|
|
123
124
|
| BigSale Adapter | DTO 转换、callback、插件、capability | 决定流程节点 |
|
|
@@ -158,7 +159,7 @@ Screen:输入和展示状态
|
|
|
158
159
|
1. Core 不 import BigSale、SalesSDK、Engine plugin 或 raw tempOrder。
|
|
159
160
|
2. Adapter 不决定 Workflow 目标节点。
|
|
160
161
|
3. Screen 不直接调用 Host;内部写操作发送 Command,离开步骤发送 Activity Intent,返回发送 Navigation。
|
|
161
|
-
4. Slice 是
|
|
162
|
+
4. Activity/Slice 是 Intent、Command 和退出策略的业务定义;Screen 可选,Operation 只引用 Contract,Handler Registry 位于 Runtime Binding。
|
|
162
163
|
5. Workflow 作者只排列已注册 Slice;规范化后的运行结构不得包含 Screen、Predicate、Operation 或 failureTarget。重复 Slice 必须使用 `slice:用途` 标识每次出现。
|
|
163
164
|
6. 只有可被业务编排者独立排序或分支的里程碑才成为节点;Dialog 内部询问、选择和等待阶段留在 Activity 内。
|
|
164
165
|
7. Operation 不渲染 UI,不直接切 Screen。
|
|
@@ -221,23 +222,20 @@ HDLKiosk 无法独立保证:
|
|
|
221
222
|
|
|
222
223
|
```text
|
|
223
224
|
components/HDLKiosk/
|
|
224
|
-
├──
|
|
225
|
-
|
|
226
|
-
│ ├──
|
|
227
|
-
│
|
|
228
|
-
|
|
225
|
+
├── kernel/ # Application / Workflow / Operation 通用执行原语
|
|
226
|
+
├── app/ # HDLKiosk Contracts、Manifest、Workflow 与 Operation Contract
|
|
227
|
+
│ ├── contracts/ # DTO / Ports / Config / Result / Error
|
|
228
|
+
│ └── workflow/ # Quick / Barcode / Scale + registry / guards / policy
|
|
229
|
+
├── runtime/ # 可脱离 React 的 Host Handler、Trigger、Devices 与 Session
|
|
230
|
+
│ ├── operations/ # HDLKiosk 业务 Operation 与安全策略
|
|
231
|
+
│ ├── devices/ # Scanner/Scale ingress、去重与 Scale Store
|
|
232
|
+
│ └── session/ # Session / Actor / Context / Lifecycle 组合
|
|
233
|
+
├── ui/ # React View Registry、Entry、Controller 与订阅 hooks
|
|
229
234
|
├── slices/ # 业务纵向切片:slice + operation + view + Screen/Dialog
|
|
230
235
|
├── components/ # 只承载跨 Slice 共享 UI 与样式
|
|
231
236
|
│ ├── shell/ # Shell / Header / BottomBarHost / FloatingBar
|
|
232
237
|
│ ├── overlays/ # CartDrawer / 会话 Dialog / PisellModal 统一壳
|
|
233
238
|
│ └── common/ # 跨 Slice 视觉控件与 BlockingNotice
|
|
234
|
-
├── runtime/ # Controllers / Projection subscriptions / active workflow view
|
|
235
|
-
├── contracts/ # DTO / Ports / Config / Result / Error
|
|
236
|
-
├── devices/ # Ingress / Arbiter / Dedupe / shared scale runtime
|
|
237
|
-
├── kernel/ # 不依赖 HDLKiosk contracts 的通用执行原语
|
|
238
|
-
│ ├── application/ # Slice / Workflow / Application 作者 API
|
|
239
|
-
│ ├── workflow/ # Structural compiler / Actor / transition primitives
|
|
240
|
-
│ └── operations/ # Generic coordinator / registry / epoch
|
|
241
239
|
├── testing/ # Fake Host / Fixtures
|
|
242
240
|
├── types.ts # 公共 Props、Action、ViewModel 与 Slice View Context
|
|
243
241
|
├── utils.ts # 跨 Slice 共享的纯方法和错误呈现
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import { _objectWithoutProperties } from "../../_virtual/_@oxc-project_runtime@0.122.0/helpers/objectWithoutProperties.js";
|
|
2
2
|
import { HDLKioskErrorBoundary } from "./components/shell/HDLKioskErrorBoundary/index.js";
|
|
3
3
|
import localeTexts from "./locales.js";
|
|
4
|
-
import { useHDLKioskDeviceController } from "./
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import { EntryScreen } from "./
|
|
11
|
-
import { createEntryScreenModel } from "./
|
|
4
|
+
import { useHDLKioskDeviceController } from "./ui/controllers/useHDLKioskDeviceController.js";
|
|
5
|
+
import { useHDLKioskSessionController } from "./ui/controllers/useHDLKioskSessionController.js";
|
|
6
|
+
import { createHDLScaleRuntime } from "./runtime/devices/scaleStore.js";
|
|
7
|
+
import { HDLScaleRuntimeProvider } from "./ui/scale.js";
|
|
8
|
+
import { useHostSnapshot } from "./ui/snapshots.js";
|
|
9
|
+
import { HDLKioskWorkflowView } from "./ui/HDLKioskWorkflowView.js";
|
|
10
|
+
import { EntryScreen } from "./ui/entry/Screen/index.js";
|
|
11
|
+
import { createEntryScreenModel } from "./ui/entry/model.js";
|
|
12
|
+
import ScaleSimulatorConsole, { isScaleSimulatorApiAvailable } from "./ui/ScaleSimulatorConsole/index.js";
|
|
12
13
|
import React, { useCallback, useEffect, useMemo, useState } from "react";
|
|
13
14
|
import { locales } from "@pisell/utils";
|
|
14
15
|
import "./index.less";
|
|
@@ -32,6 +33,7 @@ function HDLKiosk(_ref) {
|
|
|
32
33
|
}
|
|
33
34
|
function HDLKioskContent({ host, config, isActive = true, entryDataPreparing = false, locale, onLocaleChange, onTechnicalSupportClick, renderIdentityAuth, renderCartContent, cartOverlayActions }) {
|
|
34
35
|
const [activeLocale, setActiveLocale] = useState(locale || "en");
|
|
36
|
+
const [scaleSimulatorAuthOpen, setScaleSimulatorAuthOpen] = useState(false);
|
|
35
37
|
const sales = useHostSnapshot(host);
|
|
36
38
|
locales.init(localeTexts, activeLocale);
|
|
37
39
|
useEffect(() => {
|
|
@@ -41,31 +43,17 @@ function HDLKioskContent({ host, config, isActive = true, entryDataPreparing = f
|
|
|
41
43
|
setActiveLocale(nextLocale);
|
|
42
44
|
onLocaleChange === null || onLocaleChange === void 0 || onLocaleChange(nextLocale);
|
|
43
45
|
}, [onLocaleChange]);
|
|
44
|
-
const
|
|
46
|
+
const handleScaleSimulatorRequest = useCallback(() => {
|
|
47
|
+
if (isScaleSimulatorApiAvailable()) setScaleSimulatorAuthOpen(true);
|
|
48
|
+
}, []);
|
|
49
|
+
const { session, starting, startErrorReference, returning, returnError, start, returnToEntry } = useHDLKioskSessionController({
|
|
45
50
|
host,
|
|
46
51
|
config,
|
|
47
52
|
isActive
|
|
48
53
|
});
|
|
49
54
|
const { scaleConnectionState } = useHDLKioskDeviceController({
|
|
50
55
|
host,
|
|
51
|
-
|
|
52
|
-
isActive,
|
|
53
|
-
starting,
|
|
54
|
-
sessionRef,
|
|
55
|
-
activeRef,
|
|
56
|
-
scaleIngress,
|
|
57
|
-
start
|
|
58
|
-
});
|
|
59
|
-
useHDLKioskScannerController({
|
|
60
|
-
host,
|
|
61
|
-
config,
|
|
62
|
-
isActive,
|
|
63
|
-
starting,
|
|
64
|
-
sessionRef,
|
|
65
|
-
activeRef,
|
|
66
|
-
scannerIngress,
|
|
67
|
-
start,
|
|
68
|
-
waitForReadySession
|
|
56
|
+
isActive
|
|
69
57
|
});
|
|
70
58
|
return /* @__PURE__ */ React.createElement("div", {
|
|
71
59
|
className: "pisell-hdl-kiosk",
|
|
@@ -80,6 +68,8 @@ function HDLKioskContent({ host, config, isActive = true, entryDataPreparing = f
|
|
|
80
68
|
sales,
|
|
81
69
|
config,
|
|
82
70
|
isActive,
|
|
71
|
+
returning,
|
|
72
|
+
returnError,
|
|
83
73
|
returnToEntry,
|
|
84
74
|
renderIdentityAuth,
|
|
85
75
|
renderCartContent,
|
|
@@ -89,6 +79,7 @@ function HDLKioskContent({ host, config, isActive = true, entryDataPreparing = f
|
|
|
89
79
|
model: createEntryScreenModel(config, host.capabilities, scaleConnectionState, sales.hostStatus, entryDataPreparing),
|
|
90
80
|
onLocaleChange: handleLocaleChange,
|
|
91
81
|
onTechnicalSupportClick,
|
|
82
|
+
onScaleSimulatorRequest: handleScaleSimulatorRequest,
|
|
92
83
|
onSelect: (entry) => {
|
|
93
84
|
if (entry === "quick") start({ entry });
|
|
94
85
|
},
|
|
@@ -98,7 +89,10 @@ function HDLKioskContent({ host, config, isActive = true, entryDataPreparing = f
|
|
|
98
89
|
}), starting ? /* @__PURE__ */ React.createElement("div", {
|
|
99
90
|
className: "hdl-operation-overlay",
|
|
100
91
|
role: "status"
|
|
101
|
-
}, /* @__PURE__ */ React.createElement("span", { className: "hdl-operation-overlay__spinner" }), /* @__PURE__ */ React.createElement("strong", null, locales.getText("pisell2.hdl-kiosk.working"))) : null))
|
|
92
|
+
}, /* @__PURE__ */ React.createElement("span", { className: "hdl-operation-overlay__spinner" }), /* @__PURE__ */ React.createElement("strong", null, locales.getText("pisell2.hdl-kiosk.working"))) : null)), /* @__PURE__ */ React.createElement(ScaleSimulatorConsole, {
|
|
93
|
+
authOpen: scaleSimulatorAuthOpen,
|
|
94
|
+
onAuthClose: () => setScaleSimulatorAuthOpen(false)
|
|
95
|
+
}));
|
|
102
96
|
}
|
|
103
97
|
//#endregion
|
|
104
98
|
export { HDLKiosk as default };
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Workflow Kernel
|
|
2
2
|
|
|
3
3
|
`kernel/` 是放在 HDLKiosk 目录内的无 UI 运行内核。它不依赖 `HDLKioskHost`、海底捞流程、支付模型、React、BigSale 或 SalesSDK,`dependencyBoundary.test.ts` 会检查这个约束。
|
|
4
4
|
|
|
5
5
|
## 开发一套 kiosk 时使用什么
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
业务开发者主要使用相邻 `../app/` 层的四类 API:
|
|
8
8
|
|
|
9
9
|
```ts
|
|
10
10
|
const identity = defineSlice({
|
|
11
11
|
id: 'identity',
|
|
12
|
-
|
|
12
|
+
surface: { id: 'identity' },
|
|
13
13
|
intents: {
|
|
14
14
|
complete: effect(identifyCustomer, { navigate: 'next' }),
|
|
15
15
|
omit: next(),
|
|
@@ -21,10 +21,10 @@ const identity = defineSlice({
|
|
|
21
21
|
|
|
22
22
|
const order = defineWorkflow({
|
|
23
23
|
id: 'merchant.order',
|
|
24
|
-
steps: [identity, catalog, { slice: result,
|
|
24
|
+
steps: [identity, catalog, { slice: result, isTerminal: true }],
|
|
25
25
|
});
|
|
26
26
|
|
|
27
|
-
const application =
|
|
27
|
+
const application = defineApplication({
|
|
28
28
|
id: 'merchant-kiosk',
|
|
29
29
|
slices: [identity, catalog, result],
|
|
30
30
|
workflows: { order },
|
|
@@ -41,30 +41,31 @@ const views = {
|
|
|
41
41
|
- `defineSlice`:把业务 Activity、Screen 描述、语义出口、Screen 内 Command 和离开时 Effect 放在一起;
|
|
42
42
|
- `next()`:声明默认前进;Back 由独立 Navigation 和页面历史处理;
|
|
43
43
|
- `defineWorkflow`:数组只表达 Slice 顺序,`on` 只处理跳跃、分支、合流和有界回路;
|
|
44
|
-
- `
|
|
44
|
+
- `defineApplication`:汇总 Slice、Workflow 与应用级 Operation,并自动生成 Activity/Operation Manifest。
|
|
45
45
|
|
|
46
46
|
Slice 的 `intents` 是“业务活动请求流程执行的意图”,不是按钮或 DOM 事件。Back 使用独立 Navigation;不会离开 Screen 的动作放进 `commands`。支付门禁、设备监听、购物车写入验证等商家规则不进入 Kernel。
|
|
47
47
|
|
|
48
|
-
|
|
48
|
+
Slice `id` 是 Workflow 引用的业务 Activity;可选 `surface.id` 是由外层解释的稳定展示键;React View 由具体 Presentation 按 Activity 单独注册。Kernel 只复制 `surfaceId`,不理解页面类别。
|
|
49
49
|
|
|
50
|
-
Compiler 只把 `
|
|
50
|
+
Compiler 只把 `surface.id` 复制为节点的 `surfaceId`。Renderer 再按节点的 Activity 查询 Presentation View 注册表。因此远端 Workflow 只能编排 Slice,不能替换本地页面实现;Kernel 也不依赖 React。
|
|
51
51
|
|
|
52
52
|
## 目录职责
|
|
53
53
|
|
|
54
54
|
| 目录 | 负责 | 由应用注入 |
|
|
55
55
|
| --- | --- | --- |
|
|
56
|
-
| `application/` | Slice/Workflow/Application 作者 API、Manifest 生成 | Screen 描述、Intent、Operation 引用 |
|
|
57
56
|
| `workflow/` | 结构编译、Actor mailbox、节点提交、有界循环 | Activity Registry、Predicate Registry、Navigation Guard Registry、Transition Runner、Context Reducer |
|
|
58
57
|
| `operations/` | 排队、冲突仲裁、intent 去重、timeout、Abort、session epoch | Context factory、错误分类、冲突规则、业务 Policy、观察器 |
|
|
59
58
|
| `lifecycle.ts` | 组合 Actor 提交后的只读观察器 | telemetry、审计或持久化观察器 |
|
|
60
59
|
|
|
61
|
-
Kernel Operation 只认识泛型 `Context / Error / Scope
|
|
60
|
+
Kernel Operation 只认识泛型 `Context / Error / Scope`。通用 Application 定义与运行时位于
|
|
61
|
+
`../app/`;HDLKiosk 再在外层 `domain/operations/types.ts` 与
|
|
62
|
+
`domain/operations/coordinator.ts` 注入 `HDLKioskHost`、冲突矩阵、支付冻结和遥测。
|
|
62
63
|
|
|
63
64
|
## 从定义到运行
|
|
64
65
|
|
|
65
66
|
```text
|
|
66
67
|
Slice ─┐
|
|
67
|
-
├─
|
|
68
|
+
├─ defineApplication ─ Manifest ─ Activity/Operation Registry
|
|
68
69
|
Workflow ┘ │
|
|
69
70
|
▼
|
|
70
71
|
Structural Compiler ─ Actor
|
|
@@ -83,4 +84,4 @@ Activity Intent ─ Transition Runner ────────────┘
|
|
|
83
84
|
- BigSale Adapter、插件检测、兼容开关;
|
|
84
85
|
- UI 文案、错误展示和远端配置拉取。
|
|
85
86
|
|
|
86
|
-
最小独立定义见
|
|
87
|
+
最小独立定义见 `../app/application.test.ts`。该测试不导入任何 HDLKiosk 业务模块,并完成 Slice 收集、Operation 自动注册和 Workflow 编译。
|