@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.
- 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 +11 -13
- 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 +105 -101
- 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
- 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/07-/345/220/216/347/273/255/345/267/245/344/275/234.md +1 -1
- 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 +14 -13
- 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 +51 -22
- package/es/components/HDLKiosk/kernel/workflow/compiler.js +23 -30
- 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 +37 -38
- package/es/components/HDLKiosk/slices/customization/Screen/index.less +5 -0
- package/es/components/HDLKiosk/slices/customization/slice.js +3 -4
- 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/Screen/index.js +2 -2
- package/es/components/HDLKiosk/slices/identity/slice.js +3 -3
- 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 +2 -2
- package/es/components/HDLKiosk/slices/primaryProductPrompt/view.js +2 -2
- package/es/components/HDLKiosk/{runtime → ui}/HDLKioskWorkflowView.js +45 -131
- 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 +7 -7
- 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/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/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 +11 -13
- 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 +105 -101
- 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
- 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/07-/345/220/216/347/273/255/345/267/245/344/275/234.md +1 -1
- 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 +14 -13
- 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 +51 -22
- package/lib/components/HDLKiosk/kernel/workflow/compiler.js +23 -30
- 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 +38 -39
- 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/Screen/index.js +2 -2
- 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 +2 -2
- package/lib/components/HDLKiosk/slices/primaryProductPrompt/view.js +2 -2
- package/lib/components/HDLKiosk/{runtime → ui}/HDLKioskWorkflowView.js +46 -132
- 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 +7 -7
- 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 +2 -2
- 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/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
|
@@ -32,7 +32,7 @@ Screen Renderer 根据当前节点与最新 Projection 渲染
|
|
|
32
32
|
|
|
33
33
|
| 状态类型 | 例子 | 所有者 | 为什么不能混用 |
|
|
34
34
|
| -------- | -------------------------------------------------- | ---------------- | -------------------------------------------- |
|
|
35
|
-
| 业务事实 | Cart、Customer、Summary、Payment
|
|
35
|
+
| 业务事实 | Cart、Customer、Summary、Payment | Host/OS | 前端推测会产生重复支付、假优惠或脏订单 |
|
|
36
36
|
| 流程状态 | entry、nodeId、fulfillment 本地选择、session epoch | Workflow Runtime | 只回答“顾客处于哪一步”,不能证明订单已写成功 |
|
|
37
37
|
| 展示输入 | options 选中项、搜索词、Modal 内选择 | Screen | 可以随页面销毁,不得成为结账依据 |
|
|
38
38
|
|
|
@@ -40,31 +40,31 @@ Screen Renderer 根据当前节点与最新 Projection 渲染
|
|
|
40
40
|
|
|
41
41
|
## 2. 目录与运行时角色
|
|
42
42
|
|
|
43
|
-
| 目录/文件
|
|
44
|
-
|
|
|
45
|
-
| [`contracts/`](../contracts)
|
|
46
|
-
| [`kernel/`](../kernel)
|
|
47
|
-
| [`slices/`](../slices)
|
|
48
|
-
| [`app/manifest.ts`](../app/manifest.ts)
|
|
49
|
-
| [`app/workflow/`](../app/workflow)
|
|
50
|
-
| [`runtime/
|
|
51
|
-
| [`app/workflow/registry.ts`](../app/workflow/registry.ts)
|
|
52
|
-
| [`kernel/workflow/compiler.ts`](../kernel/workflow/compiler.ts)
|
|
53
|
-
| [`app/workflow/policy.ts`](../app/workflow/policy.ts)
|
|
54
|
-
| [`kernel/workflow/actor.ts`](../kernel/workflow/actor.ts)
|
|
55
|
-
| [`runtime/
|
|
56
|
-
| [`runtime/workflowLifecycle.ts`](../runtime/workflowLifecycle.ts) | 已提交状态的业务生命周期出口
|
|
57
|
-
| [`kernel/operations/coordinator.ts`](../kernel/operations/coordinator.ts)
|
|
58
|
-
| [`
|
|
59
|
-
| [`
|
|
60
|
-
| [`
|
|
61
|
-
| [`
|
|
62
|
-
| [`
|
|
63
|
-
| [`devices/`](../devices)
|
|
64
|
-
| [`devices/scale/`](../devices/scale)
|
|
65
|
-
| [`
|
|
66
|
-
| [`components/`](../components)
|
|
67
|
-
| [`testing/`](../testing)
|
|
43
|
+
| 目录/文件 | 运行时角色 | 输入 | 输出 | 解决的问题 |
|
|
44
|
+
| --------------------------------------------------------------------------------------------- | ---------------------------------- | ----------------------------------------------- | -------------------------------------------------- | ---------------------------------------------------- |
|
|
45
|
+
| [`app/contracts/`](../app/contracts) | Application 与任意 Host 的最小协议 | 无宿主实现 | DTO、Port、Capability、Result、Workflow schema | 防止 BigSale/SalesSDK 类型渗入应用层 |
|
|
46
|
+
| [`kernel/`](../kernel) | 无 UI 运行内核 | 注入的 Registry、Policy、Runner、Lifecycle | Application API、Compiler、Actor、通用 Coordinator | 复用执行机制,同时阻断商家业务和 Host 反向依赖 |
|
|
47
|
+
| [`slices/`](../slices) | HDLKiosk 业务切片 | Slice 定义、View、Screen/Dialog | 可复用业务能力与其本地界面 | 一个业务能力的规则、私有写入和界面同置 |
|
|
48
|
+
| [`app/manifest.ts`](../app/manifest.ts) | 应用唯一装配点 | Slices、Workflows、应用级 Operations | Activity/Operation/Workflow Manifest | 自动收集依赖并在启动前验证引用完整性 |
|
|
49
|
+
| [`app/workflow/`](../app/workflow) | 三入口业务编排与本地策略 | Activity 数组与特殊分支 | Quick/Barcode/Scale Definition | 流程顺序集中在应用目录,不和 Slice 实现混杂 |
|
|
50
|
+
| [`runtime/session/createSession.ts`](../runtime/session/createSession.ts) | 一次点餐会话的组合根 | entry、Host、locale、可选 Lifecycle 扩展 | Kernel 组合与 Payment Projection 桥接 | 避免页面创建状态机或驱动业务流程 |
|
|
51
|
+
| [`app/workflow/registry.ts`](../app/workflow/registry.ts) | Activity Registry 类型视图 | Application Manifest | 带 HDLKiosk 字面量类型的 Registry | Runtime 不再维护第二份 Activity 清单 |
|
|
52
|
+
| [`kernel/workflow/compiler.ts`](../kernel/workflow/compiler.ts) | Definition 结构校验 | Workflow Definition + 注入的 Registry | 冻结后的可执行 Definition 或 issues | 防止未知 Intent、非法跳转和无界循环进入 Actor |
|
|
53
|
+
| [`app/workflow/policy.ts`](../app/workflow/policy.ts) | HDLKiosk 业务策略校验 | 编译后的 Definition | 支付门禁等业务 issues | 结构规则不与具体交易策略混在一起 |
|
|
54
|
+
| [`kernel/workflow/actor.ts`](../kernel/workflow/actor.ts) | 单会话流程执行器 | Activity Intent、Navigation、Definition、Runner | WorkflowSnapshot、Transition | 解决双击、乱序导航和 Exit Command 完成前跳页 |
|
|
55
|
+
| [`runtime/session/transitionRunner.ts`](../runtime/session/transitionRunner.ts) | Activity 离开策略执行器 | Exit Policy、Host Projection、Coordinator | advance/stay/blocked、支付回执 | Actor 不理解 Predicate、购物车和支付 Operation |
|
|
56
|
+
| [`runtime/session/workflowLifecycle.ts`](../runtime/session/workflowLifecycle.ts) | 已提交状态的业务生命周期出口 | Actor 提交后的 Snapshot | telemetry | 诊断不进入状态机内核 |
|
|
57
|
+
| [`kernel/operations/coordinator.ts`](../kernel/operations/coordinator.ts) | 通用副作用调度器 | Operation request + 应用 Policy | 规范化 OperationResult | 解决重复 intent、排队、超时和旧 Promise;不认识支付 |
|
|
58
|
+
| [`runtime/index.ts`](../runtime/index.ts) | 共享 Runtime 公共入口 | Operation Handler 与 Session Factory | 稳定的统一导出面 | 避免消费者穿透私有实现目录 |
|
|
59
|
+
| [`runtime/operations/coordinator.ts`](../runtime/operations/coordinator.ts) | HDLKiosk Operation Policy | Host、支付门禁、冲突域、遥测 | 绑定业务语义的 Coordinator | 把交易规则留在应用层而不是通用 Kernel |
|
|
60
|
+
| [`runtime/operations/checkoutRequirements.ts`](../runtime/operations/checkoutRequirements.ts) | 支付前业务要求注册 | Requirement ID、Workflow Context、Projection | 当前适用 ID 与校验结果 | 新增采集事实时不改 Checkout 主流程 |
|
|
61
|
+
| [`ui/controllers/`](../ui/controllers) | React 生命周期协调 | Host、Config、Projection、Actor | session/device/customer 状态 | 将根组件中的生命周期职责拆开 |
|
|
62
|
+
| [`ui/HDLKioskWorkflowView.tsx`](../ui/HDLKioskWorkflowView.tsx) | 活跃会话 UI 编排 | Controllers、Projection、Actor snapshot | Renderer、Shell、全局 Dialog props | 防止根组件和具体 Screen 混入运行时协调逻辑 |
|
|
63
|
+
| [`devices/`](../devices) | 设备入口治理 | 标准化扫码/称重事件 | accept/reject、entry claim | 解决首页多入口竞争、重复事件和错误页面消费 |
|
|
64
|
+
| [`devices/scale/`](../devices/scale) | 顶层称重快照 | Adapter 发布的秤状态 | 全生命周期统一 Scale Snapshot | 让 Entry 和详情页共享同一秤连接,不反复挂卸原生 Hook |
|
|
65
|
+
| [`ui/ScreenRenderer.tsx`](../ui/ScreenRenderer.tsx) | Workflow 到 Slice View 装配 | Definition、Snapshot、View Context | 当前 View 与 modal base | 页面不参与中央流程判断 |
|
|
66
|
+
| [`components/`](../components) | 共享 Shell、Overlay 与控件 | 只读 ViewModel、语义 callback | 跨 Slice React UI | 共享视觉能力不反向拥有商家流程 |
|
|
67
|
+
| [`testing/`](../testing) | 可替换 Host | fixture、可控异步结果 | Fake Host、调用记录 | 不启动 BigSale 也能确定性验证 Core |
|
|
68
68
|
|
|
69
69
|
## 3. Root 与 Session 如何装配
|
|
70
70
|
|
|
@@ -83,26 +83,28 @@ Screen Renderer 根据当前节点与最新 Projection 渲染
|
|
|
83
83
|
|
|
84
84
|
```text
|
|
85
85
|
SessionController.start(request)
|
|
86
|
-
→ 校验 enabledEntries / capability / production readiness
|
|
87
|
-
→
|
|
88
|
-
→
|
|
86
|
+
→ HDLKiosk Runtime 校验 enabledEntries / capability / production readiness
|
|
87
|
+
→ Application Runtime manual/automatic Trigger
|
|
88
|
+
→ Runtime Admission(HDLKiosk 最多一个活跃 Session)
|
|
89
|
+
→ HDLKiosk Session Factory
|
|
90
|
+
→ createHDLKioskWorkflowSession(entry, host, options)
|
|
89
91
|
→ hdlKioskApplication Manifest
|
|
90
|
-
→ createHDLKioskOperationRegistry()(从
|
|
92
|
+
→ createHDLKioskOperationRegistry()(从 Runtime Binding 收集 Handler)
|
|
91
93
|
→ compileWorkflowStructure(builtInDefinition)
|
|
92
94
|
→ validateHDLKioskWorkflowPolicy(definition)
|
|
93
95
|
→ createOperationCoordinator(host, registry)
|
|
94
96
|
→ createHDLKioskTransitionRunner(host, coordinator)
|
|
95
97
|
→ createWorkflowActor(definition, runner, lifecycle)
|
|
96
|
-
→ session.ensure
|
|
97
|
-
→
|
|
98
|
-
→ 入口准备成功后发布 active session;失败则释放入口 claim
|
|
98
|
+
→ session.ensure
|
|
99
|
+
→ Runtime Registry 发布 active Session;失败则不注册
|
|
99
100
|
```
|
|
100
101
|
|
|
101
102
|
重要细节:
|
|
102
103
|
|
|
103
|
-
- 同一个入口的并发 `start`
|
|
104
|
+
- 同一个入口的并发 `start` 由 HDLKiosk Runtime 共享一个 Promise,跨入口竞争由 Runtime Admission 拒绝;
|
|
105
|
+
- Runtime snapshot 是 Session / starting / start error 的唯一状态源,React Controller 只做生命周期适配,不再镜像 Registry 状态;
|
|
104
106
|
- Barcode/Scale 是会话的外部入口,不是 Workflow Activity。Barcode Workflow 天然从 Catalog 开始,Scale Workflow 天然从 Fulfillment 开始;首个业务页 Back 因此落入会话级清单并回 Entry,无需“入口节点不可回访”或 history skip 特例;
|
|
105
|
-
- Host
|
|
107
|
+
- Host 引用变化会 dispose 旧 Runtime/Actor,并重置 ingress;
|
|
106
108
|
- capability 变化不会要求 Host 引用变化,因此不应销毁订单;
|
|
107
109
|
- session reset 只有在 Host 写入器确认空订单且 consistency barrier 完成后,才 dispose Actor、释放入口并回到 Entry;React Projection 只负责随后收敛展示,不反向否定 Host receipt。
|
|
108
110
|
|
|
@@ -160,7 +162,7 @@ Projection 的职责是“读取和标准化”,不是新 Store:
|
|
|
160
162
|
- 不把 callback 成功直接变成支付成功;
|
|
161
163
|
- 不把本地 fingerprint 当成服务端 revision。
|
|
162
164
|
|
|
163
|
-
[`
|
|
165
|
+
[`ui/snapshots.ts`](../ui/snapshots.ts) 用 `useSyncExternalStore` 消费 Projection。BigSale 接入主要依赖父级 Context rerender,其他外部事实可通过 Adapter 的显式订阅触发。
|
|
164
166
|
|
|
165
167
|
## 6. Slice、Workflow 与 Actor
|
|
166
168
|
|
|
@@ -175,16 +177,14 @@ Workflow 用有序 Slice 数组描述静态编排。数组顺序是默认主路
|
|
|
175
177
|
catalogSlice,
|
|
176
178
|
{
|
|
177
179
|
slice: primaryProductPromptSlice,
|
|
178
|
-
presentation: { mode: 'modal'
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
{
|
|
182
|
-
slice: customizationSlice,
|
|
183
|
-
on: { complete: 'fulfillment', skip: 'fulfillment' },
|
|
180
|
+
presentation: { mode: 'modal' },
|
|
181
|
+
visitPolicy: 'once',
|
|
182
|
+
on: { omit: 'fulfillment' },
|
|
184
183
|
},
|
|
184
|
+
customizationSlice,
|
|
185
185
|
fulfillmentSlice,
|
|
186
186
|
paymentMethodSlice,
|
|
187
|
-
{ slice: paymentCompletedSlice,
|
|
187
|
+
{ slice: paymentCompletedSlice, isTerminal: true },
|
|
188
188
|
],
|
|
189
189
|
}
|
|
190
190
|
```
|
|
@@ -200,13 +200,13 @@ Workflow 作者不会填写 Screen、Predicate、Operation 或 failureTarget;
|
|
|
200
200
|
|
|
201
201
|
Slice 在一条流程只出现一次时,Step ID 默认就是 Slice ID;同一 Slice 多次出现时,每次必须显式使用 `slice:用途`,例如 `catalog:initial`、`catalog:final`。这样既保持常规流程易读,也不会把复用能力误认为同一个运行位置。
|
|
202
202
|
|
|
203
|
-
Slice Intent 使用 `next()`,或在 `intentPrecondition/effect` 上声明 `navigate: 'next'`,决定相邻 Step 的默认移动。不会自动前进的 Intent 只在 Workflow `on` 中指定目标。Back 是独立 Navigation,由 Actor 的实际页面历史解析。没有下一项的 Step
|
|
203
|
+
Slice Intent 使用 `next()`,或在 `intentPrecondition/effect` 上声明 `navigate: 'next'`,决定相邻 Step 的默认移动。不会自动前进的 Intent 只在 Workflow `on` 中指定目标。Back 是独立 Navigation,由 Actor 的实际页面历史解析。没有下一项的 Step 不会被自动推测为合法终点,必须声明 `isTerminal: true`。`isTerminal` 只表达 Workflow 图结构,不表达具体业务的成功或失败结果。
|
|
204
204
|
|
|
205
205
|
Predicate 是本地可信的纯真假判断,例如 `cart.notEmpty`;Intent Precondition 表示某个 Intent 提交前必须满足的 Predicate。作者 API 使用 `intentPrecondition(predicateId)`,底层行为记录 `{ kind: 'precondition', predicate }`,编译后存入 `exitPolicy.precondition`。Predicate 只返回 boolean;它与能返回 `allow | bypass | cancel | redirect | defer | block` 的 Navigation Guard 是两套独立能力。
|
|
206
206
|
|
|
207
207
|
业务 Workflow 当前不启用 Slice `beforeEnter` 守卫。Actor 仍保留全局 `beforeEach` 管线,用于 `sessionExit` 等会话安全策略;它不承载 Identity、Fulfillment 等步骤的业务进入条件。
|
|
208
208
|
|
|
209
|
-
Actor 分别记录已成功向前离开的 Step、每个 Step 已提交的 `complete |
|
|
209
|
+
Actor 分别记录已成功向前离开的 Step、每个 Step 已提交的 `complete | omit` Resolution,以及用户实际访问过的页面历史。`complete` 保留页面的 Back 路径;`omit` 表示将该 Step 从当前流程路径中排除,后续遇到时沿已提交的 `omit` transition 继续,也不写入 Back 历史。Modal 不写入页面历史;历史为空时 Back 进入会话退出导航。Workflow occurrence 只有 `visitPolicy: 'always' | 'once'`:`always` 保留已 `complete` Step 的正常访问,`once` 表示任意 Resolution 提交后不再进入且不写入 Back 历史。用户通过 Back 退出一个已解决页面时,其旧 Resolution 失效。导航在执行 Activity Exit Effect 之前完成解析;被 cancel/defer 的导航不会先写 Host。
|
|
210
210
|
|
|
211
211
|
退出流程也是导航目标 `{ kind: 'sessionExit' }`。全局 `beforeEach` 对它返回 `defer({ kind: 'confirmEndOrder' })`,Actor 保存带唯一 `navigationId` 的 `pendingNavigation`。Shell 只根据该 request 展示确认;旧 ID 不能恢复后来的导航。
|
|
212
212
|
|
|
@@ -216,7 +216,7 @@ Step ID 只标识“一次出现”。Runtime 判断加载哪类数据、是否
|
|
|
216
216
|
|
|
217
217
|
[`slices/<name>/slice.ts`](../slices) 是本地可信 Slice 定义,每个 Slice 声明:
|
|
218
218
|
|
|
219
|
-
- 业务 Activity 使用哪个 `
|
|
219
|
+
- 业务 Activity 使用哪个 `surface.id`,以及该 Screen 的 `view`;
|
|
220
220
|
- 可以接受哪些 Intent;
|
|
221
221
|
- 支持 page 还是 modal;
|
|
222
222
|
- 某个 Intent 是否需要纯 Predicate 作为 Precondition;
|
|
@@ -224,31 +224,33 @@ Step ID 只标识“一次出现”。Runtime 判断加载哪类数据、是否
|
|
|
224
224
|
- Screen 内有哪些不会离开节点的 Command;
|
|
225
225
|
- 使用该 Slice 的流程在支付前需要哪些业务事实。
|
|
226
226
|
|
|
227
|
-
例如 `identity.complete` / `identity.
|
|
227
|
+
例如 `identity.complete` / `identity.omit` 可在携带输入时执行 `identity.sync`,`customization.complete` 执行主商品同步,`paymentMethod.complete` 检查 Host 已确认支付成功。EFTPOS 派发和店员支付授权是 Payment 页面 Command,不作为流程 Intent。`defineApplication` 从 Slice 自动生成 Activity Contract 与 Operation 注册信息;远端定义只看到 `Slice ID + 标准 Intent → target`,不能替换这些安全规则。
|
|
228
228
|
|
|
229
|
-
Slice 的业务定义与 React View
|
|
229
|
+
Slice 的业务定义与 React View 文件分离但按 feature 并置:Slice `id` 是 Workflow 和 Actor 使用的业务 Activity;`surface.id` 会被 Compiler 复制为 Workflow Node 的 `surfaceId`,供 Shell、Controller 和数据加载策略使用;`ui/views.ts` 按 Activity 注册本地可信 View。各 Slice 的 `view.tsx` 仍负责 ViewModel 派生与组件装配,但不会进入 `defineSlice` 或 Workflow Definition。
|
|
230
230
|
|
|
231
|
-
| Slice 定义
|
|
232
|
-
|
|
|
233
|
-
| `id`
|
|
234
|
-
| `
|
|
235
|
-
| `
|
|
231
|
+
| Slice 定义 | 编译/运行期形态 | 唯一用途 |
|
|
232
|
+
| -------------------------------- | ---------------- | ---------------------------------- |
|
|
233
|
+
| `id` | Node `activity` | 业务状态、Intent 和流程编排 |
|
|
234
|
+
| `surface.id` | Node `surfaceId` | Shell 变体、数据加载和页面类别判断 |
|
|
235
|
+
| `ui/views.ts` 中的 Activity 映射 | 仅应用展示层使用 | React UI 渲染 |
|
|
236
236
|
|
|
237
|
-
因此 `id`、`screen` 和 `view` 不互相替代:`catalog` 是商品浏览页面,`primaryProductPrompt` 是覆盖在 Catalog 上的独立 Modal Slice。店员支付授权不改变当前页面,因此是 `paymentMethod` 的 Screen Command,而不是独立 Activity。Application Manifest 是业务运行 Contract 的唯一索引,`
|
|
237
|
+
因此 `id`、`screen` 和 `view` 不互相替代:`catalog` 是商品浏览页面,`primaryProductPrompt` 是覆盖在 Catalog 上的独立 Modal Slice。店员支付授权不改变当前页面,因此是 `paymentMethod` 的 Screen Command,而不是独立 Activity。Application Manifest 是业务运行 Contract 的唯一索引,`ui/views.ts` 是展示实现的唯一索引。View 使用同步本地组件引用,不产生运行期 UI chunk;纯 Compiler/Actor 依赖链也不会加载该注册表。Renderer 若发现 View 缺失,仍使用 `BlockingNotice` fail closed,且不会改变 Workflow。
|
|
238
238
|
|
|
239
|
-
`slices/index.ts` 对整套 Slice 清单执行一次类型约束:`
|
|
239
|
+
`slices/index.ts` 对整套 Slice 清单执行一次类型约束:`surface.id` 只能取 HDLKiosk 的非 Entry `ScreenId`。`ui/views.ts` 使用完整的 `Record<ActivityId, HDLKioskSliceView>`,因此新增 Activity 若没有注册 View 会产生类型错误。Kernel 的 `defineSlice` 同时拒绝空 `surface.id`。
|
|
240
240
|
|
|
241
|
-
Compiler 从实际使用的 Slice 汇总 Checkout Requirement ID,但不把判断函数或 Host 字段写入 Workflow。当前 HDLKiosk 默认注册表为空;未来增加其他业务要求时仍由 [`checkoutRequirements.ts`](../
|
|
241
|
+
Compiler 从实际使用的 Slice 汇总 Checkout Requirement ID,但不把判断函数或 Host 字段写入 Workflow。当前 HDLKiosk 默认注册表为空;未来增加其他业务要求时仍由 [`checkoutRequirements.ts`](../runtime/operations/checkoutRequirements.ts) 集中判断。
|
|
242
242
|
|
|
243
|
-
`WorkflowEvent` 同时约束 Activity、Intent 和必要输入:例如 `identity.
|
|
243
|
+
`WorkflowEvent` 同时约束 Activity、Intent 和必要输入:例如 `identity.omit` 必须携带身份输入,`fulfillment.complete` 必须携带 fulfillment context patch。Back 使用不携带业务输入的 `NAVIGATE_BACK`。Barcode 入口的条码输入不是 Workflow Event,而是 Session Controller 在发布会话前交给 `barcode.consume` 的 Command 输入。Screen Command 由 `OperationInputMap` 约束 Command ID 与输入类型。
|
|
244
244
|
|
|
245
245
|
Step 可选声明 Modal 展示关系:
|
|
246
246
|
|
|
247
247
|
```ts
|
|
248
|
-
presentation: {
|
|
248
|
+
presentation: {
|
|
249
|
+
mode: 'modal';
|
|
250
|
+
}
|
|
249
251
|
```
|
|
250
252
|
|
|
251
|
-
这只控制渲染层级。Compiler
|
|
253
|
+
这只控制渲染层级。Actor Surface 保留进入 Modal 前实际展示的 Page,Workflow 不指定背景 Step。Compiler 会拒绝以 Modal 作为首节点或 Modal 直接进入另一个 Modal。
|
|
252
254
|
|
|
253
255
|
### 6.3 结构 Compiler 与业务 Policy 校验
|
|
254
256
|
|
|
@@ -263,7 +265,7 @@ presentation: { mode: 'modal', base: 'customization' }
|
|
|
263
265
|
- 指向自身或更早 Step 的非 Back 跳转是否声明有限 `repeat`;
|
|
264
266
|
- Modal presentation 引用是否合法。
|
|
265
267
|
|
|
266
|
-
结构校验通过后,Compiler 还会将所有 Step 对应 Activity
|
|
268
|
+
结构校验通过后,Compiler 还会将所有 Step 对应 Activity 的通用 `requirements` 去重汇总到编译结果。Kernel 不解释这些 ID;HDLKiosk Domain 再把其中的 Checkout Requirement 交给本地注册表校验。该字段是 Activity Contract 的派生值,不是 Workflow Definition 的作者输入。
|
|
267
269
|
|
|
268
270
|
随后 `policy.ts` 校验 HDLKiosk 交易规则,例如 `checkout.open` 必须来自
|
|
269
271
|
`paymentMethod`,并且该支付步骤必须具有本地 Checkout Prepare 门禁。两类校验都在
|
|
@@ -275,7 +277,7 @@ session 创建前完成,但结构错误与业务安全错误保持独立。
|
|
|
275
277
|
|
|
276
278
|
Actor 使用单 mailbox:
|
|
277
279
|
|
|
278
|
-
1. 忽略
|
|
280
|
+
1. 忽略 terminal、blocked 或 disposed 后的新事件;
|
|
279
281
|
2. 同时校验事件的 `stepId` 和 `activityId`,拒绝旧 Screen 或同类 Activity 旧实例的迟到回调;
|
|
280
282
|
3. 校验 Intent 是否由当前 Activity 暴露,并查找 Transition;Back 则读取页面历史;
|
|
281
283
|
4. 通过注入的 Context Reducer 合并受限 contextPatch;
|
|
@@ -287,15 +289,15 @@ Actor 使用单 mailbox:
|
|
|
287
289
|
|
|
288
290
|
结果到节点的映射:
|
|
289
291
|
|
|
290
|
-
| OperationResult | Actor 行为
|
|
291
|
-
| ---------------- |
|
|
292
|
-
| `succeeded` | 进入 target
|
|
293
|
-
| `cancelled` | 留在当前 Step
|
|
294
|
-
| `failed` | 留在当前 Step,并展示可恢复错误
|
|
295
|
-
| `partialFailure` | 保留当前 Step
|
|
296
|
-
| `unknown` | 保留当前 Step
|
|
292
|
+
| OperationResult | Actor 行为 |
|
|
293
|
+
| ---------------- | --------------------------------------------------------------------------------- |
|
|
294
|
+
| `succeeded` | 进入 target |
|
|
295
|
+
| `cancelled` | 留在当前 Step |
|
|
296
|
+
| `failed` | 留在当前 Step,并展示可恢复错误 |
|
|
297
|
+
| `partialFailure` | 保留当前 Step 并展示错误;仅支付派发或 reset 等 P0 副作用进入 blocked |
|
|
298
|
+
| `unknown` | 保留当前 Step 并展示错误;仅可能重复扣款、跨订单污染或 reset 不完整时进入 blocked |
|
|
297
299
|
|
|
298
|
-
`blocked`
|
|
300
|
+
`blocked` 是运行时 P0 安全状态,不是可编排的 Activity。UI 在 Actor 阻塞时统一覆盖安全提示,因此 Workflow 中不存在为了显示错误而设置的伪业务节点。普通 Cart、Customer、Fulfillment 和支付前置校验的模糊结果停留原页并允许显式重试,不锁死整个 Actor。
|
|
299
301
|
|
|
300
302
|
## 7. Operation Registry 与 Coordinator
|
|
301
303
|
|
|
@@ -312,17 +314,17 @@ partialFailure/unknown 的 Screen Command 会通过 Actor 的 system block 入
|
|
|
312
314
|
|
|
313
315
|
当前 Operation 组:
|
|
314
316
|
|
|
315
|
-
| Operation | scope | timeout | 核心职责
|
|
316
|
-
| ------------------------------------ | -------- | ------- |
|
|
317
|
-
| `session.ensure/reset` | session | 15s | 建立/清理订单并验证 reset
|
|
318
|
-
| `identity.sync` | customer | 15s | 按 `customerId` 有无应用认证客户或清除订单客户,并执行 consistency、重报价和写后观察
|
|
319
|
-
| `barcode.consume` | cart | — | 调宿主扫码 Flow;规格选择完成前不启动写后一致性检查
|
|
320
|
-
| `cart.addProduct` | cart | — | 调宿主商品 Flow,等待规格或其它业务选择后验证写入
|
|
321
|
-
| `cart.update/remove` | cart | 15s | 数量修改/删除、summary 重算和目标行验证
|
|
322
|
-
| `product.syncPrimaryWeightedProduct` | cart | — | 首次写入可能等待 OS 额外业务弹窗;更新或写入后验证重量/options 和写后证据
|
|
323
|
-
| `product.removePrimaryProduct` | cart | 15s | 将主商品置为不存在;本来不存在时直接成功,存在时验证删除结果
|
|
324
|
-
| `checkout.prepare*` | checkout | 20s | fulfillment、cart、summary 稳定性与 token
|
|
325
|
-
| `checkout.open` | checkout | 120s | 消费 token、冻结危险写并打开 Host 支付
|
|
317
|
+
| Operation | scope | timeout | 核心职责 |
|
|
318
|
+
| ------------------------------------ | -------- | ------- | ------------------------------------------------------------------------------------ |
|
|
319
|
+
| `session.ensure/reset` | session | 15s | 建立/清理订单并验证 reset |
|
|
320
|
+
| `identity.sync` | customer | 15s | 按 `customerId` 有无应用认证客户或清除订单客户,并执行 consistency、重报价和写后观察 |
|
|
321
|
+
| `barcode.consume` | cart | — | 调宿主扫码 Flow;规格选择完成前不启动写后一致性检查 |
|
|
322
|
+
| `cart.addProduct` | cart | — | 调宿主商品 Flow,等待规格或其它业务选择后验证写入 |
|
|
323
|
+
| `cart.update/remove` | cart | 15s | 数量修改/删除、summary 重算和目标行验证 |
|
|
324
|
+
| `product.syncPrimaryWeightedProduct` | cart | — | 首次写入可能等待 OS 额外业务弹窗;更新或写入后验证重量/options 和写后证据 |
|
|
325
|
+
| `product.removePrimaryProduct` | cart | 15s | 将主商品置为不存在;本来不存在时直接成功,存在时验证删除结果 |
|
|
326
|
+
| `checkout.prepare*` | checkout | 20s | fulfillment、cart、summary 稳定性与 token |
|
|
327
|
+
| `checkout.open` | checkout | 120s | 消费 token、冻结危险写并打开 Host 支付 |
|
|
326
328
|
|
|
327
329
|
### 7.2 冲突矩阵
|
|
328
330
|
|
|
@@ -346,7 +348,7 @@ none ↔ 不参与互斥
|
|
|
346
348
|
- session epoch 变化后丢弃旧结果;
|
|
347
349
|
- 调用应用注入的冲突、错误、Context 和生命周期 Policy。
|
|
348
350
|
|
|
349
|
-
[`
|
|
351
|
+
[`runtime/operations/coordinator.ts`](../runtime/operations/coordinator.ts) 只负责 HDLKiosk 交易语义:
|
|
350
352
|
|
|
351
353
|
- 注入 `HDLKioskHost` 和最新 Workflow Context;
|
|
352
354
|
- 定义 session/cart/customer/checkout 的冲突矩阵;
|
|
@@ -412,7 +414,7 @@ BigSale Login2/Register2
|
|
|
412
414
|
→ 成功后进入下一节点
|
|
413
415
|
```
|
|
414
416
|
|
|
415
|
-
认证 UI 通过 HDLKiosk 应用展示层插槽注入,不进入 `defineSlice`、View 注册表或 Kernel。Slice 的 `complete` 在携带输入时执行 `identity.sync`;已登录客户的自动略过使用 `
|
|
417
|
+
认证 UI 通过 HDLKiosk 应用展示层插槽注入,不进入 `defineSlice`、View 注册表或 Kernel。Slice 的 `complete` 在携带输入时执行 `identity.sync`;已登录客户的自动略过使用 `omit` 且不携带输入,因此不会重复写客户。
|
|
416
418
|
|
|
417
419
|
Shell 登录不是 Workflow 跳转,而是 session-level 插入 Operation:
|
|
418
420
|
|
|
@@ -429,11 +431,11 @@ Shell Login
|
|
|
429
431
|
|
|
430
432
|
### 8.4 Screen Data Controller
|
|
431
433
|
|
|
432
|
-
只在相关节点加载 Catalog、Weighted Product 或 Customization DTO;使用 AbortController 防止离开页面后的结果写回。Modal
|
|
434
|
+
只在相关节点加载 Catalog、Weighted Product 或 Customization DTO;使用 AbortController 防止离开页面后的结果写回。Modal 激活时,Screen Data Controller 继续使用 Actor Surface 中保留的 `pageStepId`,底层 Page 保持挂载和原数据,不按 Modal Activity 清空或重新加载。
|
|
433
435
|
|
|
434
436
|
### 8.5 返回 Entry 能力接口
|
|
435
437
|
|
|
436
|
-
当前物料不维护 idle 计时器或警告弹窗。Payment 成功展示在 Checkout Screen 内,10 秒倒计时或手动返回都调用 `returnToEntry(reason?)`:它对并发请求去重,执行 `session.reset
|
|
438
|
+
当前物料不维护 idle 计时器或警告弹窗。Payment 成功展示在 Checkout Screen 内,10 秒倒计时或手动返回都调用 `returnToEntry(reason?)`:它对并发请求去重,执行 `session.reset`,并通过 Runtime snapshot 统一发布 `returning/returnError`;验证 Host 空订单和一致性后,再释放 Actor、Ingress 与 session epoch。
|
|
437
439
|
|
|
438
440
|
未来应用级生命周期策略可以决定何时调用该接口,但不能直接清 React 状态或只切换页面。支付 pending/unknown、reset 失败等情况仍由既有安全策略 fail closed。
|
|
439
441
|
|
|
@@ -478,7 +480,7 @@ Core:Entry Ingress 负责去重、仲裁和启动会话;活跃 Screen 只消
|
|
|
478
480
|
```text
|
|
479
481
|
HDLKiosk root
|
|
480
482
|
→ HDLKioskWorkflowView(运行时状态转 props)
|
|
481
|
-
→
|
|
483
|
+
→ ui/ScreenRenderer(按 Activity 查询 ui/views.ts 中的本地 View)
|
|
482
484
|
→ slices/<name>/view + Screen/Dialog
|
|
483
485
|
→ components/shell + components/overlays + components/common
|
|
484
486
|
→ Activity Action callback
|
|
@@ -530,7 +532,7 @@ Workflow View 负责控制器组合、自动推进和会话级 Dialog;Renderer
|
|
|
530
532
|
|
|
531
533
|
OS 加购过程中的内部弹窗和业务判断不属于 HDLKiosk Activity、Host Contract 或 Checkout Requirement。HDLKiosk 不读写相关业务事实,只根据主商品加购操作的最终结果决定是否跳转。
|
|
532
534
|
|
|
533
|
-
Barcode 的主商品询问是独立 `primaryProductPrompt` Modal Slice:Yes 发出 `complete`,No 发出 `
|
|
535
|
+
Barcode 的主商品询问是独立 `primaryProductPrompt` Modal Slice:Yes 发出 `complete`,No 发出 `omit`。Prompt 声明 `visitPolicy: 'once'`,因此任一选择成功提交后不再询问;关闭 Modal 只执行 Back,没有 Resolution,下次仍会展示。Customization 使用缺省 `always`:`complete` 后保留 Back 编辑能力;`omit` 会先通过本地 Exit Effect 删除已有主商品,再将该 Step 从后续路径和 Back 历史中排除。
|
|
534
536
|
|
|
535
537
|
## 11. 四条端到端调用链
|
|
536
538
|
|
|
@@ -550,7 +552,7 @@ Entry click
|
|
|
550
552
|
|
|
551
553
|
```text
|
|
552
554
|
CatalogScreen command(cart.addProduct)
|
|
553
|
-
→
|
|
555
|
+
→ useHDLKioskActionDispatcher
|
|
554
556
|
→ session.executeCommand
|
|
555
557
|
→ Coordinator: cart.addProduct
|
|
556
558
|
→ Operation: Host addProduct
|
|
@@ -585,24 +587,26 @@ Scale 与 Quick 复用同一套称重商品原子操作和页面,差异只保
|
|
|
585
587
|
→ checkout.open consumes token
|
|
586
588
|
→ Checkout Safety freezes dangerous writes
|
|
587
589
|
→ Host result + Payment Projection
|
|
588
|
-
→
|
|
590
|
+
→ Session Payment Projection bridge
|
|
591
|
+
→ paymentMethod.complete 本地门禁
|
|
592
|
+
→ paymentCompleted / failed / blocked
|
|
589
593
|
```
|
|
590
594
|
|
|
591
595
|
## 12. 修改需求应该落在哪里
|
|
592
596
|
|
|
593
|
-
| 需求 | 首选位置
|
|
594
|
-
| --------------------- |
|
|
595
|
-
| 调整节点顺序 | `app/workflow/*.ts`
|
|
596
|
-
| 新增跨 Slice 副作用 | `contracts` + `
|
|
597
|
-
| 新增 BigSale 字段映射 | BigSale Adapter
|
|
598
|
-
| 新增设备来源 | Adapter Device Port
|
|
599
|
-
| 修改入口消费条件 | Device/Session Controller
|
|
600
|
-
| 修改页面局部交互 | `slices/<name>/Screen` + `view.tsx`
|
|
601
|
-
| 新增业务 Dialog | Slice `presentation` + `slices/<name>/Dialog`
|
|
602
|
-
| 修改会话级 UI 协调 | `
|
|
603
|
-
| 新增审计或持久化观察 | 外层 `WorkflowLifecycle` 扩展
|
|
604
|
-
| 新增跨刷新恢复 | Kernel 外初始化决策模块 + Actor 初始状态
|
|
605
|
-
| 调整支付安全 | Kernel `checkoutSafety` + 业务 `checkout`
|
|
597
|
+
| 需求 | 首选位置 | 同步检查 |
|
|
598
|
+
| --------------------- | -------------------------------------------------- | ----------------------------------------- |
|
|
599
|
+
| 调整节点顺序 | `app/workflow/*.ts` | 03 文档、definition/actor 测试 |
|
|
600
|
+
| 新增跨 Slice 副作用 | `app/contracts` + `runtime/operations` + Host Port | conflict scope、timeout、unknown、adapter |
|
|
601
|
+
| 新增 BigSale 字段映射 | BigSale Adapter | Core DTO 是否真的需要扩展 |
|
|
602
|
+
| 新增设备来源 | Adapter Device Port | Core Ingress 是否已有相同语义 |
|
|
603
|
+
| 修改入口消费条件 | Device/Session Controller | capability、payment freeze、dedupe |
|
|
604
|
+
| 修改页面局部交互 | `slices/<name>/Screen` + `view.tsx` | 不得直接调用 Host;样式留在组件目录 |
|
|
605
|
+
| 新增业务 Dialog | Slice `presentation` + `slices/<name>/Dialog` | 不新增第二套导航状态 |
|
|
606
|
+
| 修改会话级 UI 协调 | `ui/HDLKioskWorkflowView.tsx` | 不把 Controller/Actor 传入具体组件 |
|
|
607
|
+
| 新增审计或持久化观察 | 外层 `WorkflowLifecycle` 扩展 | 不得让 Kernel 依赖存储或恢复策略 |
|
|
608
|
+
| 新增跨刷新恢复 | Kernel 外初始化决策模块 + Actor 初始状态 | OS 事实、隐私、支付优先级、人工处置 |
|
|
609
|
+
| 调整支付安全 | Kernel `checkoutSafety` + 业务 `checkout` | 必须更新 05 文档与集成测试 |
|
|
606
610
|
|
|
607
611
|
## 13. 当前刻意不做的抽象
|
|
608
612
|
|
|
@@ -26,7 +26,7 @@ Entry → Identity → Customization → Catalog → Fulfillment
|
|
|
26
26
|
→ Payment Method / Payment Completed → Entry
|
|
27
27
|
```
|
|
28
28
|
|
|
29
|
-
- Quick 的 Identity occurrence 显式声明 `visitPolicy: 'once'`。登录或
|
|
29
|
+
- Quick 的 Identity occurrence 显式声明 `visitPolicy: 'once'`。登录或 Omit 成功后,该 Step 在本会话不再进入,也不写入 Back 页面历史。当没有更早的已访问页面时,Back 的导航目标为 `sessionExit`;全局会话策略返回 `defer(confirmEndOrder)` 并打开结束订单确认。确认后返回 Entry,取消则留在当前页。
|
|
30
30
|
- Fulfillment 统一位于 Payment 之前确认堂食/外带。
|
|
31
31
|
- Customization 只在稳定正净重且必选 options 完整时启用 Next。
|
|
32
32
|
- “I don't need Malatang” 直接跳过主商品并进入 Catalog;如果正在编辑已确认主商品,则先移除该行。
|
|
@@ -67,7 +67,7 @@ Entry 消费第一个有效重量边沿后启动以 Fulfillment 为首节点的
|
|
|
67
67
|
|
|
68
68
|
## 6. 会员中途插入
|
|
69
69
|
|
|
70
|
-
Identity 的
|
|
70
|
+
Identity 的 Omit 只表示当前以 Guest 继续。Shell 可在本地策略允许的页面执行 `identity.sync`。登录、Customer 写入、重报价和 Projection 验证成功后仍留在原节点;`partial`/`unknown` 不得带着未确认价格继续。
|
|
71
71
|
|
|
72
72
|
## 7. UI 和修改规则
|
|
73
73
|
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
- 仅允许商品码。现有通用扫码 API 会执行多种业务码,必须补充“先分类后执行”或商品专用 API;
|
|
16
16
|
- 不记录、持久化或写入遥测原始条码。
|
|
17
17
|
|
|
18
|
-
截至 2026-08-
|
|
18
|
+
截至 2026-08-24,无头 ScannerSessionRouter、5 项统一 FIFO、pending Session 归属、Session 发布后首码消费,以及支付 dispatch 前的版本化 `ensurePrepared` 已落地。商品码专用 Host 契约、`requiresSelection` 完成协议、全局扫码反馈和跨 SalesSDK 的 scan/payment activity bridge 仍待生产化补齐。
|
|
19
19
|
|
|
20
20
|
## 2. 当前实现审计
|
|
21
21
|
|
|
@@ -24,13 +24,12 @@
|
|
|
24
24
|
```text
|
|
25
25
|
Native scanner / pubsub
|
|
26
26
|
→ BigSale scanner adapter
|
|
27
|
-
→ useHDLKioskScannerController(HDLKiosk active 生命周期常驻)
|
|
28
27
|
→ ScannerIngress.accept
|
|
29
|
-
→ bounded FIFO
|
|
30
|
-
→
|
|
31
|
-
├─
|
|
32
|
-
└─
|
|
33
|
-
→
|
|
28
|
+
→ ScannerSessionRouter(Entry / starting / Flow 共用 bounded FIFO)
|
|
29
|
+
├─ idle:首码触发 onScan → ensure → Registry started
|
|
30
|
+
├─ starting:后续扫码追加到同一 FIFO
|
|
31
|
+
└─ active:Flow 扫码继续追加到同一 FIFO
|
|
32
|
+
→ onStarted.bindSession(startId, ScannerSessionPort)
|
|
34
33
|
→ barcode.consume(eventId-scoped intent)
|
|
35
34
|
```
|
|
36
35
|
|
|
@@ -38,7 +37,7 @@ Native scanner / pubsub
|
|
|
38
37
|
|
|
39
38
|
- Scanner adapter 优先申请 `hdl-kiosk` 扫码焦点,无法使用焦点栈时才回退 pubsub;
|
|
40
39
|
- ScannerIngress 已有 eventId/LRU 去重、350ms 降级指纹去重和 payment freeze 门禁;
|
|
41
|
-
-
|
|
40
|
+
- ScannerSessionRouter 使用真实未完成任务数做 5 项背压,Quick/Scale 启动期间的扫码会等待同一个 pending Session;
|
|
42
41
|
- `barcode.consume` 使用 cart scope,且不设置 Operation 超时;`added` 才执行写后 cart consistency、Summary 和 receipt/fingerprint 验证,`requiresSelection` 等待 Host 选择流程;
|
|
43
42
|
- Catalog transition 不再执行 prepare;支付 Operation 通过 Checkout freshness 检查复用或重建当前事实版本的 token;
|
|
44
43
|
- 本地 cart/customer 写入会把 Prepared 状态标记为 `stale`,外部写入由 fingerprint/Summary/requirement 复验识别。
|
|
@@ -54,21 +53,24 @@ Native scanner / pubsub
|
|
|
54
53
|
|
|
55
54
|
## 3. 目标架构
|
|
56
55
|
|
|
57
|
-
|
|
56
|
+
Scanner 属于无头 Runtime 设备层,与 React Entry/Workflow View 解耦:
|
|
58
57
|
|
|
59
58
|
```text
|
|
60
|
-
|
|
61
|
-
├─
|
|
62
|
-
├─
|
|
63
|
-
├─ HDLKioskScannerController
|
|
59
|
+
Application Runtime
|
|
60
|
+
├─ Trigger / Admission / Session Registry
|
|
61
|
+
├─ ScannerSessionRouter
|
|
64
62
|
│ ├─ scanner focus / subscription
|
|
65
63
|
│ ├─ ingress validation + dedupe
|
|
66
64
|
│ ├─ bounded task queue
|
|
67
|
-
│ ├─
|
|
68
|
-
│
|
|
69
|
-
|
|
70
|
-
├─
|
|
71
|
-
|
|
65
|
+
│ ├─ startId / activation generation
|
|
66
|
+
│ └─ bind/release ScannerSessionPort
|
|
67
|
+
├─ ScannerSessionPort
|
|
68
|
+
│ ├─ cart/payment policy
|
|
69
|
+
│ ├─ navigation policy
|
|
70
|
+
│ └─ barcode.consume dispatcher
|
|
71
|
+
└─ React Session Controller(只订阅 Registry)
|
|
72
|
+
├─ Entry View
|
|
73
|
+
└─ Workflow View
|
|
72
74
|
├─ Header
|
|
73
75
|
├─ current Slice
|
|
74
76
|
├─ Cart Overlay
|
|
@@ -99,7 +101,7 @@ ScanPolicyDecision
|
|
|
99
101
|
|
|
100
102
|
## 4. 设备所有权与生命周期
|
|
101
103
|
|
|
102
|
-
- HDLKiosk active 时由
|
|
104
|
+
- HDLKiosk active 时由 ScannerSessionRouter 申请焦点;KeepAlive 隐藏、unmount 或 capability 消失时释放。
|
|
103
105
|
- 页面切换不重建订阅,Session 切换只更新扫码策略和任务归属。
|
|
104
106
|
- Scanner adapter 必须成为 HDLKiosk 生命周期内唯一的物理消费者。
|
|
105
107
|
- 有焦点栈时,HDLKiosk 持有焦点,会员登录等更高优先级的本地交互可暂时抢占。
|
|
@@ -116,11 +118,11 @@ Entry 收到合法商品扫码事件时:
|
|
|
116
118
|
4. 创建 Barcode Session,并把首码任务绑定到该 `sessionEpoch`;
|
|
117
119
|
5. `setSession`,由 Session Controller 完成 Actor、Operation Coordinator、Host binding 和 Projection subscription 的安装;
|
|
118
120
|
6. Session Runtime 进入 `active` 并发布与 Screen 无关的 `sessionReadyForCommands`,同时由交易策略给出独立的 `sessionCartWritable`;
|
|
119
|
-
7.
|
|
121
|
+
7. ScannerSessionRouter 把首码交给该 Session,串行执行 `barcode.consume`;
|
|
120
122
|
8. 成功后刷新 Projection/Summary;失败则留在该 Session 的当前页面展示可恢复错误,不回退到 Entry;
|
|
121
123
|
9. 只有无法建立安全 Session 时才释放 claim 并返回 Entry。
|
|
122
124
|
|
|
123
|
-
`sessionReadyForCommands` 是 Session Runtime 的生命周期状态,不由 Catalog 或任意 Screen 的 mount/commit 事件驱动。未来某类 Workflow 即使以 Identity、Fulfillment 或其他页面作为首屏,也不需要改
|
|
125
|
+
`sessionReadyForCommands` 是 Session Runtime 的生命周期状态,不由 Catalog 或任意 Screen 的 mount/commit 事件驱动。未来某类 Workflow 即使以 Identity、Fulfillment 或其他页面作为首屏,也不需要改 ScannerSessionRouter。
|
|
124
126
|
|
|
125
127
|
这里应区分三个概念:
|
|
126
128
|
|
|
@@ -161,15 +163,17 @@ Customization 需额外识别当前主称重商品:扫描同一主商品不能
|
|
|
161
163
|
|
|
162
164
|
## 7. 队列、去重与背压
|
|
163
165
|
|
|
164
|
-
|
|
166
|
+
ScannerSessionRouter 维护真实的有限 FIFO 队列:
|
|
165
167
|
|
|
166
168
|
- 同一 Session 内最多保留建议 5 个待处理任务,running/waitingSelection 也计入占用;
|
|
167
169
|
- 队列满时立即拒绝,并提示等待当前商品处理完成;
|
|
168
|
-
- 不同 Session
|
|
170
|
+
- 不同 Session 的任务不得串用;启动以 startId 绑定,激活和 Session generation
|
|
171
|
+
变化时隔离旧结果;
|
|
169
172
|
- 同 eventId 只接受一次;无稳定 eventId 的设备继续使用非明文 350ms fingerprint 作为降级方案;
|
|
170
173
|
- cart mutation scope 串行执行,不在多个 Screen 中并行调用 `barcode.consume`;
|
|
171
174
|
- 将真实 `pendingEventCount` 传入 ScannerIngress,删除固定 `0`;
|
|
172
|
-
- `requiresSelection`
|
|
175
|
+
- `requiresSelection` 拒绝在选择态建立前已经排队的旧任务并结束本轮 drain;选择弹层
|
|
176
|
+
通过 Scanner focus stack 临时接管物理扫码,关闭后新扫码按正常准入重新进入队列。
|
|
173
177
|
|
|
174
178
|
## 8. 只消费商品码
|
|
175
179
|
|
|
@@ -285,7 +289,7 @@ checkoutCoordinator.ensurePrepared(currentVersion)
|
|
|
285
289
|
|
|
286
290
|
### Phase 1:移动所有权并支持页面内扫码(已完成)
|
|
287
291
|
|
|
288
|
-
-
|
|
292
|
+
- 新建无头 ScannerSessionRouter;
|
|
289
293
|
- 订阅生命周期从“仅 Entry 无 Session”改为“HDLKiosk active”;
|
|
290
294
|
- 建立 scan policy、真实队列和 session epoch;
|
|
291
295
|
- Quick/Scale/Barcode 的可写页面共用 `barcode.consume`;
|
|
@@ -341,6 +345,19 @@ useNativeScale(一次)
|
|
|
341
345
|
└─ CustomizationScreen:持续读取毛重/皮重/净重/稳定态
|
|
342
346
|
```
|
|
343
347
|
|
|
344
|
-
Runtime
|
|
348
|
+
Runtime 只保存 owner 发布的最新快照和递增 `sampleSequence`。断连、停止监听、读取错误、
|
|
349
|
+
负重或超载会立即使当前采样失效;重连后必须收到新的 native `onChange` 帧才能重新
|
|
350
|
+
启用提交。稳定读数不会因为顾客花时间选择规格而按固定秒数过期。
|
|
351
|
+
|
|
352
|
+
Entry 仍允许有效正重边沿(包括正在趋稳的读数)启动 Flow;这一步不写购物车。
|
|
353
|
+
Customization 必须同时满足当前连接周期已有新采样、连接并监听、状态 stable、无错误和
|
|
354
|
+
正净重阈值。点击 Next 时同步读取 Runtime 最新快照并冻结点击当下重量,避免 React 旧
|
|
355
|
+
render 与断连/抖动同批发生时提交旧值;捕获成功后顾客可以正常取走商品。
|
|
356
|
+
|
|
357
|
+
`SkuDetailModal` 属于有员工操作的通用商品场景,继续保留 Manual 和编辑态冻结快照;
|
|
358
|
+
但启动实时 Auto 后同样只有 `liveData + listening + connected + stable` 才输出
|
|
359
|
+
`is_valid=true`。两处共享安全原则,不强行共享不同的业务交互策略。
|
|
360
|
+
|
|
361
|
+
Scanner 与 Scale 共用 Entry Arbiter,但进入 Session 后互不抢占业务消费权。
|
|
345
362
|
|
|
346
363
|
`CustomizationScreen` 只维护称重和 options 草稿;点击 Next 后才由 `product.syncPrimaryWeightedProduct` 交给 OS 加购。最终金额、订单行和 Summary 始终以 Host Projection 为准。
|
|
@@ -77,6 +77,8 @@ Prepare 检查:
|
|
|
77
77
|
|
|
78
78
|
“We are checking your order” 表示支付或副作用最终结果无法确认,不是普通 loading。页面必须展示 trace reference,不能提供再次支付按钮。
|
|
79
79
|
|
|
80
|
+
硬阻断只保留给 P0 副作用:支付可能已派发/扣款、支付最终化无法确认,或 reset 可能部分完成。购物车、会员、履约、定制和 checkout 派发前的短暂不稳定停留当前页、显示 reference 并允许重试,不再将整个 Workflow 转为 blocked。
|
|
81
|
+
|
|
80
82
|
## 6. 会话边界与未来扩展
|
|
81
83
|
|
|
82
84
|
当前 Session、Coordinator Epoch、Prepare Token 和 Checkout Safety 都是页面生命周期内状态。刷新页面不会恢复原 Workflow 节点,也不会用浏览器存储推断支付结果。
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
### P1-1 商品和 Catalog
|
|
36
36
|
|
|
37
37
|
- 将模板内临时固定商品 ID 改为租户/门店正式称重商品配置;商品结构已经切换为 OS `queryProducts`,不得恢复本地 fallback;
|
|
38
|
-
- 确认 Quick
|
|
38
|
+
- 确认 Quick 是否允许排除称重主商品;若不允许,从 `customization` Activity Contract/Workflow 中移除 `omit` Intent;
|
|
39
39
|
- 大目录分页/虚拟滚动与分类切换性能;分类、子分类和本地搜索首版已完成;
|
|
40
40
|
- 缺货、下架、菜单不可用、价格变化;
|
|
41
41
|
- Barcode 细分 added/requiresSelection/notFound/cancelled;
|