@pisell/private-materials 6.12.166 → 6.12.168

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (115) hide show
  1. package/build/lowcode/assets-daily.json +11 -11
  2. package/build/lowcode/assets-dev.json +2 -2
  3. package/build/lowcode/assets-prod.json +11 -11
  4. package/build/lowcode/meta.js +1 -1
  5. package/build/lowcode/render/default/view.js +11 -11
  6. package/build/lowcode/view.js +11 -11
  7. package/es/components/HDLKiosk/app/ScreenRenderer.js +7 -7
  8. package/es/components/HDLKiosk/app/views.js +2 -1
  9. package/es/components/HDLKiosk/app/workflow/barcode.js +12 -35
  10. package/es/components/HDLKiosk/app/workflow/{guards.js → predicates.js} +9 -9
  11. package/es/components/HDLKiosk/app/workflow/quick.js +3 -6
  12. package/es/components/HDLKiosk/app/workflow/registry.js +1 -1
  13. package/es/components/HDLKiosk/app/workflow/scale.js +3 -12
  14. package/es/components/HDLKiosk/components/shell/HDLKioskBottomBarHost/index.js +12 -10
  15. package/es/components/HDLKiosk/components/shell/HDLKioskShell/index.js +1 -0
  16. package/es/components/HDLKiosk/docs/00-/346/226/207/344/273/266/345/257/274/350/210/252.md +7 -7
  17. 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 +47 -40
  18. 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 +3 -3
  19. package/es/components/HDLKiosk/docs/05-/344/272/244/346/230/223/345/256/211/345/205/250.md +1 -1
  20. package/es/components/HDLKiosk/docs/07-/345/220/216/347/273/255/345/267/245/344/275/234.md +1 -1
  21. package/es/components/HDLKiosk/docs/README.md +2 -2
  22. package/es/components/HDLKiosk/docs//345/256/236/346/226/275/350/277/233/345/272/246.md +3 -3
  23. package/es/components/HDLKiosk/docs//346/236/266/346/236/204/350/256/276/350/256/241.md +11 -11
  24. package/es/components/HDLKiosk/index.js +0 -1
  25. package/es/components/HDLKiosk/kernel/README.md +8 -9
  26. package/es/components/HDLKiosk/kernel/application/defineApplication.js +18 -19
  27. package/es/components/HDLKiosk/kernel/application/defineSlice.js +8 -13
  28. package/es/components/HDLKiosk/kernel/workflow/actor.js +118 -28
  29. package/es/components/HDLKiosk/kernel/workflow/compiler.js +35 -41
  30. package/es/components/HDLKiosk/kernel/workflow/selectors.js +9 -0
  31. package/es/components/HDLKiosk/runtime/HDLKioskWorkflowView.js +10 -9
  32. package/es/components/HDLKiosk/runtime/controllers/useHDLKioskCustomerController.js +1 -1
  33. package/es/components/HDLKiosk/runtime/createWorkflowSession.js +3 -3
  34. package/es/components/HDLKiosk/runtime/domainTransitionRunner.js +9 -9
  35. package/es/components/HDLKiosk/runtime/workflowEvent.js +9 -4
  36. package/es/components/HDLKiosk/runtime/workflowLifecycle.js +3 -3
  37. package/es/components/HDLKiosk/slices/catalog/PrimaryProductPromptDialog/index.js +1 -2
  38. package/es/components/HDLKiosk/slices/catalog/Screen/index.js +11 -38
  39. package/es/components/HDLKiosk/slices/catalog/Screen/model.js +1 -5
  40. package/es/components/HDLKiosk/slices/catalog/slice.js +4 -16
  41. package/es/components/HDLKiosk/slices/catalog/view.js +4 -6
  42. package/es/components/HDLKiosk/slices/customization/Screen/index.js +9 -11
  43. package/es/components/HDLKiosk/slices/customization/operation.js +23 -4
  44. package/es/components/HDLKiosk/slices/customization/slice.js +5 -9
  45. package/es/components/HDLKiosk/slices/customization/view.js +3 -2
  46. package/es/components/HDLKiosk/slices/fulfillment/Screen/index.js +6 -6
  47. package/es/components/HDLKiosk/slices/fulfillment/slice.js +5 -8
  48. package/es/components/HDLKiosk/slices/identity/Screen/index.js +18 -12
  49. package/es/components/HDLKiosk/slices/identity/slice.js +4 -11
  50. package/es/components/HDLKiosk/slices/index.js +3 -2
  51. package/es/components/HDLKiosk/slices/payment/Screen/index.js +5 -5
  52. package/es/components/HDLKiosk/slices/payment/slice.js +7 -8
  53. package/es/components/HDLKiosk/slices/primaryProductPrompt/slice.js +14 -0
  54. package/es/components/HDLKiosk/slices/primaryProductPrompt/view.js +23 -0
  55. package/es/components/HDLKiosk/utils.js +3 -2
  56. package/es/components/bigSale/templates/HDLKiosk/auth/HDLKioskIdentityAuthPanel.js +17 -2
  57. package/es/pro/Login2.0/Login2.d.ts +2 -0
  58. package/es/pro/Login2.0/Login2.js +9 -1
  59. package/es/pro/Login2.0/Register2.d.ts +2 -0
  60. package/es/pro/Login2.0/Register2.js +9 -1
  61. package/lib/components/HDLKiosk/app/ScreenRenderer.js +7 -7
  62. package/lib/components/HDLKiosk/app/views.js +2 -1
  63. package/lib/components/HDLKiosk/app/workflow/barcode.js +11 -34
  64. package/lib/components/HDLKiosk/app/workflow/{guards.js → predicates.js} +9 -9
  65. package/lib/components/HDLKiosk/app/workflow/quick.js +3 -6
  66. package/lib/components/HDLKiosk/app/workflow/registry.js +1 -1
  67. package/lib/components/HDLKiosk/app/workflow/scale.js +3 -12
  68. package/lib/components/HDLKiosk/components/shell/HDLKioskBottomBarHost/index.js +12 -10
  69. package/lib/components/HDLKiosk/components/shell/HDLKioskShell/index.js +1 -0
  70. package/lib/components/HDLKiosk/docs/00-/346/226/207/344/273/266/345/257/274/350/210/252.md +7 -7
  71. 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 +47 -40
  72. 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 +3 -3
  73. package/lib/components/HDLKiosk/docs/05-/344/272/244/346/230/223/345/256/211/345/205/250.md +1 -1
  74. package/lib/components/HDLKiosk/docs/07-/345/220/216/347/273/255/345/267/245/344/275/234.md +1 -1
  75. package/lib/components/HDLKiosk/docs/README.md +2 -2
  76. package/lib/components/HDLKiosk/docs//345/256/236/346/226/275/350/277/233/345/272/246.md +3 -3
  77. package/lib/components/HDLKiosk/docs//346/236/266/346/236/204/350/256/276/350/256/241.md +11 -11
  78. package/lib/components/HDLKiosk/index.js +0 -1
  79. package/lib/components/HDLKiosk/kernel/README.md +8 -9
  80. package/lib/components/HDLKiosk/kernel/application/defineApplication.js +18 -19
  81. package/lib/components/HDLKiosk/kernel/application/defineSlice.js +8 -14
  82. package/lib/components/HDLKiosk/kernel/workflow/actor.js +118 -28
  83. package/lib/components/HDLKiosk/kernel/workflow/compiler.js +35 -41
  84. package/lib/components/HDLKiosk/kernel/workflow/selectors.js +10 -0
  85. package/lib/components/HDLKiosk/runtime/HDLKioskWorkflowView.js +10 -9
  86. package/lib/components/HDLKiosk/runtime/controllers/useHDLKioskCustomerController.js +1 -1
  87. package/lib/components/HDLKiosk/runtime/createWorkflowSession.js +3 -3
  88. package/lib/components/HDLKiosk/runtime/domainTransitionRunner.js +9 -9
  89. package/lib/components/HDLKiosk/runtime/workflowEvent.js +9 -4
  90. package/lib/components/HDLKiosk/runtime/workflowLifecycle.js +3 -3
  91. package/lib/components/HDLKiosk/slices/catalog/PrimaryProductPromptDialog/index.js +1 -2
  92. package/lib/components/HDLKiosk/slices/catalog/Screen/index.js +13 -40
  93. package/lib/components/HDLKiosk/slices/catalog/Screen/model.js +0 -5
  94. package/lib/components/HDLKiosk/slices/catalog/slice.js +2 -15
  95. package/lib/components/HDLKiosk/slices/catalog/view.js +4 -6
  96. package/lib/components/HDLKiosk/slices/customization/Screen/index.js +9 -11
  97. package/lib/components/HDLKiosk/slices/customization/operation.js +23 -3
  98. package/lib/components/HDLKiosk/slices/customization/slice.js +3 -7
  99. package/lib/components/HDLKiosk/slices/customization/view.js +3 -2
  100. package/lib/components/HDLKiosk/slices/fulfillment/Screen/index.js +6 -6
  101. package/lib/components/HDLKiosk/slices/fulfillment/slice.js +4 -7
  102. package/lib/components/HDLKiosk/slices/identity/Screen/index.js +17 -11
  103. package/lib/components/HDLKiosk/slices/identity/slice.js +4 -11
  104. package/lib/components/HDLKiosk/slices/index.js +2 -1
  105. package/lib/components/HDLKiosk/slices/payment/Screen/index.js +5 -5
  106. package/lib/components/HDLKiosk/slices/payment/slice.js +6 -7
  107. package/lib/components/HDLKiosk/slices/primaryProductPrompt/slice.js +14 -0
  108. package/lib/components/HDLKiosk/slices/primaryProductPrompt/view.js +25 -0
  109. package/lib/components/HDLKiosk/utils.js +3 -2
  110. package/lib/components/bigSale/templates/HDLKiosk/auth/HDLKioskIdentityAuthPanel.js +16 -1
  111. package/lib/pro/Login2.0/Login2.d.ts +2 -0
  112. package/lib/pro/Login2.0/Login2.js +9 -1
  113. package/lib/pro/Login2.0/Register2.d.ts +2 -0
  114. package/lib/pro/Login2.0/Register2.js +9 -1
  115. package/package.json +4 -4
@@ -1,15 +1,16 @@
1
- import { catalogSlice, catalogWithPrimaryProductPromptSlice } from "./catalog/slice.js";
1
+ import { catalogSlice } from "./catalog/slice.js";
2
2
  import { customizationSlice } from "./customization/slice.js";
3
3
  import { fulfillmentSlice } from "./fulfillment/slice.js";
4
4
  import { identitySlice } from "./identity/slice.js";
5
5
  import { paymentCompletedSlice, paymentMethodSlice } from "./payment/slice.js";
6
+ import { primaryProductPromptSlice } from "./primaryProductPrompt/slice.js";
6
7
  //#region src/components/HDLKiosk/slices/index.ts
7
8
  const hdlKioskSlices = Object.freeze([
8
9
  identitySlice,
9
10
  fulfillmentSlice,
10
11
  customizationSlice,
11
12
  catalogSlice,
12
- catalogWithPrimaryProductPromptSlice,
13
+ primaryProductPromptSlice,
13
14
  paymentMethodSlice,
14
15
  paymentCompletedSlice
15
16
  ]);
@@ -42,8 +42,8 @@ function PaymentMethodIcon({ code, type }) {
42
42
  function CheckoutScreen({ model, orderBar, send }) {
43
43
  var _model$paymentFeedbac;
44
44
  const goBack = useCallback(() => send({
45
- kind: "outcome",
46
- outcome: "back"
45
+ kind: "navigation",
46
+ direction: "back"
47
47
  }), [send]);
48
48
  const hasOrder = Boolean(orderBar && orderBar.cartLineCount > 0);
49
49
  const cartMutable = hasOrder && model.canLeavePayment;
@@ -174,9 +174,9 @@ function CheckoutScreen({ model, orderBar, send }) {
174
174
  dismissCurrentFeedback();
175
175
  if (eftpos) {
176
176
  send({
177
- kind: "outcome",
178
- outcome: "eftposSelected",
179
- operationInput: { paymentMethodId: method.id }
177
+ kind: "command",
178
+ command: "checkout.payEftpos",
179
+ input: { paymentMethodId: method.id }
180
180
  });
181
181
  return;
182
182
  }
@@ -1,22 +1,21 @@
1
- import { back, defineSlice, effect, guard } from "../../kernel/application/defineSlice.js";
1
+ import { defineSlice, intentPrecondition } from "../../kernel/application/defineSlice.js";
2
2
  import { checkoutPayEftposOperation, checkoutRequestStaffPaymentApprovalOperation } from "../../app/operations/checkout.js";
3
3
  //#region src/components/HDLKiosk/slices/payment/slice.ts
4
4
  /** Payment Slice:声明卡/现金选择、支付派发与 Host 成功确认;支付不确定不作成功处理。 */
5
5
  const paymentMethodSlice = defineSlice({
6
6
  id: "paymentMethod",
7
7
  screen: { id: "checkout" },
8
- commands: { requestStaffPaymentApproval: checkoutRequestStaffPaymentApprovalOperation },
9
- outcomes: {
10
- eftposSelected: effect(checkoutPayEftposOperation),
11
- confirmed: guard("payment.succeeded", { navigate: "next" }),
12
- back: back()
13
- }
8
+ commands: {
9
+ payEftpos: checkoutPayEftposOperation,
10
+ requestStaffPaymentApproval: checkoutRequestStaffPaymentApprovalOperation
11
+ },
12
+ intents: { complete: intentPrecondition("payment.succeeded", { navigate: "next" }) }
14
13
  });
15
14
  /** 支付完成仍复用 Checkout Screen,仅作为 Workflow 的成功终态。 */
16
15
  const paymentCompletedSlice = defineSlice({
17
16
  id: "paymentCompleted",
18
17
  screen: { id: "checkout" },
19
- outcomes: {}
18
+ intents: {}
20
19
  });
21
20
  //#endregion
22
21
  export { paymentCompletedSlice, paymentMethodSlice };
@@ -0,0 +1,14 @@
1
+ import { defineSlice, intentPrecondition } from "../../kernel/application/defineSlice.js";
2
+ //#region src/components/HDLKiosk/slices/primaryProductPrompt/slice.ts
3
+ /** 主商品询问 Slice:只表达是否进入称重定制,不承担 Catalog 页面职责。 */
4
+ const primaryProductPromptSlice = defineSlice({
5
+ id: "primaryProductPrompt",
6
+ screen: { id: "primaryProductPrompt" },
7
+ presentation: "modal",
8
+ intents: {
9
+ complete: intentPrecondition("cart.notEmpty", { navigate: "next" }),
10
+ omit: intentPrecondition("cart.notEmpty")
11
+ }
12
+ });
13
+ //#endregion
14
+ export { primaryProductPromptSlice };
@@ -0,0 +1,23 @@
1
+ import { PrimaryProductPromptDialog } from "../catalog/PrimaryProductPromptDialog/index.js";
2
+ import React from "react";
3
+ //#region src/components/HDLKiosk/slices/primaryProductPrompt/view.tsx
4
+ /** 主商品询问展示:将用户选择转换为标准 complete/omit 结果。 */
5
+ function PrimaryProductPromptView({ busy, send }) {
6
+ return /* @__PURE__ */ React.createElement(PrimaryProductPromptDialog, {
7
+ busy,
8
+ onDecline: () => send({
9
+ kind: "intent",
10
+ intent: "omit"
11
+ }),
12
+ onAccept: () => send({
13
+ kind: "intent",
14
+ intent: "complete"
15
+ })
16
+ });
17
+ }
18
+ const renderPrimaryProductPrompt = ({ viewSnapshot, bindActivity }) => /* @__PURE__ */ React.createElement(PrimaryProductPromptView, {
19
+ busy: viewSnapshot.status === "running",
20
+ send: bindActivity("primaryProductPrompt")
21
+ });
22
+ //#endregion
23
+ export { renderPrimaryProductPrompt };
@@ -1,3 +1,4 @@
1
+ import { canNavigateBack } from "./kernel/workflow/selectors.js";
1
2
  import { formatAmount, locales } from "@pisell/utils";
2
3
  //#region src/components/HDLKiosk/utils.ts
3
4
  function fallbackErrorMessage(surface) {
@@ -94,8 +95,8 @@ function createActivityScreenModel(screenId, snapshot, node, sales, businessMode
94
95
  title,
95
96
  description,
96
97
  busy: snapshot.status === "running",
97
- canContinue: snapshot.status === "idle" && canReviewCatalog && !placeholderBlocked && Boolean(node.on.completed || node.on.detected),
98
- canGoBack: snapshot.status === "idle" && Boolean(node.on.back),
98
+ canContinue: snapshot.status === "idle" && canReviewCatalog && !placeholderBlocked && Boolean(node.on.complete),
99
+ canGoBack: snapshot.status === "idle" && canNavigateBack(snapshot),
99
100
  placeholder,
100
101
  placeholderBlocked,
101
102
  errorMessage: error === null || error === void 0 ? void 0 : error.message,
@@ -3,7 +3,7 @@ import { _asyncToGenerator } from "../../../../../_virtual/_@oxc-project_runtime
3
3
  import useEngineContext from "../../../../../hooks/useEngineContext.js";
4
4
  import Login2 from "../../../../../pro/Login2.0/Login2.js";
5
5
  import Register2 from "../../../../../pro/Login2.0/Register2.js";
6
- import React, { useMemo, useState } from "react";
6
+ import React, { useEffect, useMemo, useState } from "react";
7
7
  //#region src/components/bigSale/templates/HDLKiosk/auth/HDLKioskIdentityAuthPanel.tsx
8
8
  /**
9
9
  * 文件角色:把 BigSale 的 Login2/Register2 表单适配为 HDLKiosk Identity 认证 UI。
@@ -136,12 +136,25 @@ function _resolveCustomerFromAuthResult() {
136
136
  });
137
137
  return _resolveCustomerFromAuthResult.apply(this, arguments);
138
138
  }
139
- function HDLKioskIdentityAuthPanel({ context, registerAndLoginModuleName, disabled, onAuthenticated, onAuthError, onCustomerResolved }) {
139
+ function HDLKioskIdentityAuthPanel({ context, registerAndLoginModuleName, disabled, onAuthenticated, onAuthError, onBusyChange, onCustomerResolved }) {
140
140
  const engineContext = useEngineContext();
141
141
  const [view, setView] = useState("login");
142
142
  const [submitting, setSubmitting] = useState(false);
143
+ const [authLoading, setAuthLoading] = useState(false);
143
144
  const loginConfig = useMemo(buildLoginConfig, []);
144
145
  const registerConfig = useMemo(buildRegisterConfig, []);
146
+ useEffect(() => {
147
+ onBusyChange === null || onBusyChange === void 0 || onBusyChange(submitting || authLoading);
148
+ }, [
149
+ authLoading,
150
+ onBusyChange,
151
+ submitting
152
+ ]);
153
+ useEffect(() => {
154
+ return () => {
155
+ onBusyChange === null || onBusyChange === void 0 || onBusyChange(false);
156
+ };
157
+ }, [onBusyChange]);
145
158
  const completeWithCustomer = function() {
146
159
  var _ref11 = _asyncToGenerator(function* (originResult, _method, authFormData) {
147
160
  if (submitting || disabled || !registerAndLoginModuleName) return;
@@ -175,6 +188,7 @@ function HDLKioskIdentityAuthPanel({ context, registerAndLoginModuleName, disabl
175
188
  config: loginConfig,
176
189
  visible: true,
177
190
  registerAndLoginModuleName,
191
+ onLoadingChange: setAuthLoading,
178
192
  onSwitchToRegister: () => setView("register"),
179
193
  onLogin: completeWithCustomer,
180
194
  onError: onAuthError
@@ -182,6 +196,7 @@ function HDLKioskIdentityAuthPanel({ context, registerAndLoginModuleName, disabl
182
196
  config: registerConfig,
183
197
  visible: true,
184
198
  registerAndLoginModuleName,
199
+ onLoadingChange: setAuthLoading,
185
200
  onGoToLogin: () => setView("login"),
186
201
  onRegister: completeWithCustomer,
187
202
  onError: onAuthError
@@ -24,6 +24,8 @@ interface Login2Config {
24
24
  }
25
25
  /** 登录组件事件 */
26
26
  interface Login2Events {
27
+ /** 内部异步认证任务的执行状态 */
28
+ onLoadingChange?: (loading: boolean) => void;
27
29
  /** 登录回调 */
28
30
  onLogin?: (originResult: any, method: AuthMethodType, data: LoginFormData, channel?: string) => Promise<void> | void;
29
31
  /** 三方登录回调 */
@@ -24,7 +24,7 @@ import "./index.less";
24
24
  * 支持邮箱、手机、三方登录
25
25
  * 组件宽度固定 360px
26
26
  */
27
- const Login2 = ({ config, visible = true, onClose, className, style, onLogin, onOAuthLogin, onSendVerificationCode, onForgotPassword, onSwitchToRegister, onError, registerAndLoginModule, registerAndLoginModuleName }) => {
27
+ const Login2 = ({ config, visible = true, onClose, className, style, onLogin, onOAuthLogin, onSendVerificationCode, onForgotPassword, onSwitchToRegister, onError, onLoadingChange, registerAndLoginModule, registerAndLoginModuleName }) => {
28
28
  var _context$appHelper, _config$ui, _config$emailLinkVeri, _config$emailLinkVeri2, _config$emailLinkVeri4;
29
29
  const [form] = Form.useForm();
30
30
  const [loading, setLoading] = useState(false);
@@ -34,6 +34,14 @@ const Login2 = ({ config, visible = true, onClose, className, style, onLogin, on
34
34
  const registerAndLogin = registerAndLoginModule !== null && registerAndLoginModule !== void 0 ? registerAndLoginModule : pisellOS === null || pisellOS === void 0 ? void 0 : pisellOS.getModule(registerAndLoginModuleName || "registerAndLogin");
35
35
  const context = useEngineContext();
36
36
  const storage = context === null || context === void 0 || (_context$appHelper = context.appHelper) === null || _context$appHelper === void 0 || (_context$appHelper = _context$appHelper.utils) === null || _context$appHelper === void 0 ? void 0 : _context$appHelper.storage;
37
+ useEffect(() => {
38
+ onLoadingChange === null || onLoadingChange === void 0 || onLoadingChange(loading);
39
+ }, [loading, onLoadingChange]);
40
+ useEffect(() => {
41
+ return () => {
42
+ onLoadingChange === null || onLoadingChange === void 0 || onLoadingChange(false);
43
+ };
44
+ }, [onLoadingChange]);
37
45
  const rememberMeWatch = Form.useWatch("remember_me", form);
38
46
  useEffect(() => {
39
47
  if (typeof rememberMeWatch === "boolean" && !rememberMeWatch) {
@@ -27,6 +27,8 @@ interface Register2Config {
27
27
  }
28
28
  /** 注册组件事件 */
29
29
  interface Register2Events {
30
+ /** 内部异步认证任务的执行状态 */
31
+ onLoadingChange?: (loading: boolean) => void;
30
32
  /** 注册回调 */
31
33
  onRegister?: (originResult: any, method: AuthMethodType, data: RegisterFormData, channel?: string) => Promise<void> | void;
32
34
  /** 三方登录回调 */
@@ -33,7 +33,7 @@ import "./steps/steps.less";
33
33
  * 支持邮箱、手机、三方注册
34
34
  * 组件宽度固定 360px
35
35
  */
36
- const Register2 = ({ config, visible = true, onClose, className, style, onRegister, onOAuthLogin, onSendVerificationCode, onEmailLinkExpired, onGoToLogin, onError, registerAndLoginModule, registerAndLoginModuleName }) => {
36
+ const Register2 = ({ config, visible = true, onClose, className, style, onRegister, onOAuthLogin, onSendVerificationCode, onEmailLinkExpired, onGoToLogin, onError, onLoadingChange, registerAndLoginModule, registerAndLoginModuleName }) => {
37
37
  var _context$appHelper, _utils$getStore, _utils$getStore$getSt, _config$ui, _config$emailLinkVeri3, _config$ui4, _config$ui5, _config$ui6, _config$ui7, _config$ui8, _config$ui9;
38
38
  const [form] = Form.useForm();
39
39
  const [loading, setLoading] = useState(false);
@@ -42,6 +42,14 @@ const Register2 = ({ config, visible = true, onClose, className, style, onRegist
42
42
  const [codeError, setCodeError] = useState("");
43
43
  const pisellOS = usePisellOS();
44
44
  const registerAndLogin = registerAndLoginModule !== null && registerAndLoginModule !== void 0 ? registerAndLoginModule : pisellOS === null || pisellOS === void 0 ? void 0 : pisellOS.getModule(registerAndLoginModuleName || "registerAndLogin");
45
+ useEffect(() => {
46
+ onLoadingChange === null || onLoadingChange === void 0 || onLoadingChange(loading);
47
+ }, [loading, onLoadingChange]);
48
+ useEffect(() => {
49
+ return () => {
50
+ onLoadingChange === null || onLoadingChange === void 0 || onLoadingChange(false);
51
+ };
52
+ }, [onLoadingChange]);
45
53
  const context = useEngineContext();
46
54
  const utils = (context === null || context === void 0 || (_context$appHelper = context.appHelper) === null || _context$appHelper === void 0 ? void 0 : _context$appHelper.utils) || {};
47
55
  const shopId = ((_utils$getStore = utils.getStore) === null || _utils$getStore === void 0 || (_utils$getStore = _utils$getStore.call(utils)) === null || _utils$getStore === void 0 || (_utils$getStore$getSt = _utils$getStore.getState) === null || _utils$getStore$getSt === void 0 || (_utils$getStore$getSt = _utils$getStore$getSt.call(_utils$getStore)) === null || _utils$getStore$getSt === void 0 || (_utils$getStore$getSt = _utils$getStore$getSt.global) === null || _utils$getStore$getSt === void 0 || (_utils$getStore$getSt = _utils$getStore$getSt.shop) === null || _utils$getStore$getSt === void 0 ? void 0 : _utils$getStore$getSt.id) || 9;
@@ -8,8 +8,8 @@ let _pisell_utils = require("@pisell/utils");
8
8
  //#region src/components/HDLKiosk/app/ScreenRenderer.tsx
9
9
  /**
10
10
  * 文件角色:把当前 Workflow Node 交给其 Slice 自有 View 渲染。
11
- * 运行机制:从应用 View 注册表按 Activity 读取同步组件;Modal 节点先渲染 base
12
- * Slice,再叠加当前 Slice View。
11
+ * 运行机制:从应用 View 注册表按 Activity 读取同步组件;先渲染 Actor
12
+ * Surface 保留的 Page,再按顺序叠加 Modal Slice View。
13
13
  * 边界:只组装 View Context,不调用 Host、不创建 ViewModel、不决定下一节点。
14
14
  */
15
15
  function ScreenRenderer({ definition, snapshot, sales, send, commandState = { busy: false }, resetting, capabilities, businessMode = "prototype", scaleMinimumWeightKg = .01, renderIdentityAuth, memberAction = {
@@ -24,12 +24,12 @@ function ScreenRenderer({ definition, snapshot, sales, send, commandState = { bu
24
24
  methods: [],
25
25
  loading: false
26
26
  } }) {
27
- var _activeNode$presentat, _commandState$error;
27
+ var _definition$nodes$sna, _commandState$error;
28
28
  const activeNode = definition.nodes[snapshot.nodeId];
29
- const modalBaseNodeId = ((_activeNode$presentat = activeNode.presentation) === null || _activeNode$presentat === void 0 ? void 0 : _activeNode$presentat.mode) === "modal" ? activeNode.presentation.base : void 0;
30
- const renderedNode = definition.nodes[modalBaseNodeId !== null && modalBaseNodeId !== void 0 ? modalBaseNodeId : snapshot.nodeId];
29
+ const pageNode = (_definition$nodes$sna = definition.nodes[snapshot.surface.pageStepId]) !== null && _definition$nodes$sna !== void 0 ? _definition$nodes$sna : activeNode;
30
+ const overlayNodes = snapshot.surface.overlays.map((stepId) => definition.nodes[stepId]).filter((node) => Boolean(node));
31
31
  const bindActivity = (activityId) => (action) => {
32
- send(action.kind === "outcome" ? require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, action), {}, { activityId }) : action);
32
+ send(action.kind === "intent" || action.kind === "navigation" ? require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, action), {}, { activityId }) : action);
33
33
  };
34
34
  const viewSnapshot = commandState.busy || commandState.error ? require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, snapshot), {}, {
35
35
  status: commandState.busy ? "running" : snapshot.status,
@@ -66,7 +66,7 @@ function ScreenRenderer({ definition, snapshot, sales, send, commandState = { bu
66
66
  };
67
67
  return /* @__PURE__ */ react.default.createElement(SliceView, context);
68
68
  };
69
- return /* @__PURE__ */ react.default.createElement(react.default.Fragment, null, renderNode(renderedNode), modalBaseNodeId ? renderNode(activeNode) : null);
69
+ return /* @__PURE__ */ react.default.createElement(react.default.Fragment, null, renderNode(pageNode), overlayNodes.map((node) => /* @__PURE__ */ react.default.createElement(react.default.Fragment, { key: node.id }, renderNode(node))));
70
70
  }
71
71
  //#endregion
72
72
  exports.ScreenRenderer = ScreenRenderer;
@@ -3,13 +3,14 @@ const require_view$1 = require("../slices/customization/view.js");
3
3
  const require_view$2 = require("../slices/fulfillment/view.js");
4
4
  const require_view$3 = require("../slices/identity/view.js");
5
5
  const require_view$4 = require("../slices/payment/view.js");
6
+ const require_view$5 = require("../slices/primaryProductPrompt/view.js");
6
7
  //#region src/components/HDLKiosk/app/views.ts
7
8
  const hdlKioskViews = Object.freeze({
8
9
  identity: require_view$3.renderIdentity,
9
10
  fulfillment: require_view$2.renderFulfillment,
10
11
  customization: require_view$1.renderCustomization,
11
12
  catalog: require_view.renderCatalog,
12
- catalogWithPrimaryProductPrompt: require_view.renderCatalog,
13
+ primaryProductPrompt: require_view$5.renderPrimaryProductPrompt,
13
14
  paymentMethod: require_view$4.renderPayment,
14
15
  paymentCompleted: require_view$4.renderPayment
15
16
  });
@@ -3,52 +3,29 @@ const require_slice = require("../../slices/catalog/slice.js");
3
3
  const require_slice$1 = require("../../slices/customization/slice.js");
4
4
  const require_slice$2 = require("../../slices/fulfillment/slice.js");
5
5
  const require_slice$3 = require("../../slices/payment/slice.js");
6
+ const require_slice$4 = require("../../slices/primaryProductPrompt/slice.js");
6
7
  //#region src/components/HDLKiosk/app/workflow/barcode.ts
7
8
  /**
8
9
  * 文件角色:声明 Barcode 入口的有序业务步骤。
9
10
  * 运行机制:Workflow 从 Catalog 开始;首码在 Session readyForCommands 后由全局 Scanner
10
- * Controller 消费。Catalog 先询问是否需要麻辣烫,需要时进入 Customization;
11
- * 最终统一在 Payment 前确认 Fulfillment。
11
+ * Controller 消费。Catalog 完成补充购物后进入独立的主商品询问 Modal,需要时进入
12
+ * Customization;无论选择或拒绝,最终都直接进入 Fulfillment。
12
13
  * 边界:设备扫码属于 Session 输入,不是可前进/后退的 Activity;支付 prepare 由支付
13
14
  * Operation 在 dispatch 前统一保证,不绑定 Catalog transition。
14
15
  */
15
16
  const barcodeWorkflow = require_defineApplication.defineWorkflow({
16
17
  id: "hdl.barcode",
17
18
  steps: [
19
+ require_slice.catalogSlice,
18
20
  {
19
- slice: require_slice.catalogWithPrimaryProductPromptSlice,
20
- on: {
21
- completed: "fulfillment",
22
- primaryProductRequested: "customization"
23
- }
24
- },
25
- {
26
- slice: require_slice$1.customizationSlice,
27
- on: {
28
- completed: {
29
- target: "catalogWithPrimaryProductPrompt",
30
- repeat: {
31
- max: 1,
32
- exceeded: "blocked"
33
- }
34
- },
35
- skipped: {
36
- target: "catalogWithPrimaryProductPrompt",
37
- repeat: {
38
- max: 1,
39
- exceeded: "blocked"
40
- }
41
- }
42
- }
43
- },
44
- {
45
- slice: require_slice$2.fulfillmentSlice,
46
- on: { back: "catalogWithPrimaryProductPrompt" }
47
- },
48
- {
49
- slice: require_slice$3.paymentMethodSlice,
50
- on: { eftposSelected: "paymentCompleted" }
21
+ slice: require_slice$4.primaryProductPromptSlice,
22
+ presentation: { mode: "modal" },
23
+ visitPolicy: "once",
24
+ on: { omit: "fulfillment" }
51
25
  },
26
+ require_slice$1.customizationSlice,
27
+ require_slice$2.fulfillmentSlice,
28
+ require_slice$3.paymentMethodSlice,
52
29
  {
53
30
  slice: require_slice$3.paymentCompletedSlice,
54
31
  end: "success"
@@ -1,6 +1,6 @@
1
1
  const require_objectSpread2 = require("../../../../_virtual/_@oxc-project_runtime@0.122.0/helpers/objectSpread2.js");
2
- //#region src/components/HDLKiosk/app/workflow/guards.ts
3
- const DEFAULT_GUARDS = Object.freeze({
2
+ //#region src/components/HDLKiosk/app/workflow/predicates.ts
3
+ const DEFAULT_PREDICATES = Object.freeze({
4
4
  "cart.notEmpty": ({ sales }) => sales.cart.lineCount > 0,
5
5
  "cart.noPendingMutation": ({ sales }) => !sales.cart.consistencyPending,
6
6
  "identity.satisfied": ({ sales }) => sales.customer !== void 0,
@@ -9,15 +9,15 @@ const DEFAULT_GUARDS = Object.freeze({
9
9
  "payment.notPending": ({ sales }) => sales.payment.status !== "pending" && sales.payment.status !== "unknown",
10
10
  "payment.succeeded": ({ sales }) => sales.payment.status === "succeeded"
11
11
  });
12
- function createGuardRegistry(overrides = {}) {
13
- const guards = Object.freeze(require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, DEFAULT_GUARDS), overrides));
14
- const ids = Object.freeze(Object.keys(guards));
12
+ function createPredicateRegistry(overrides = {}) {
13
+ const predicates = Object.freeze(require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, DEFAULT_PREDICATES), overrides));
14
+ const ids = Object.freeze(Object.keys(predicates));
15
15
  return Object.freeze({
16
16
  ids,
17
- has: (id) => Object.prototype.hasOwnProperty.call(guards, id),
18
- evaluate: (id, context) => guards[id](context)
17
+ has: (id) => Object.prototype.hasOwnProperty.call(predicates, id),
18
+ evaluate: (id, context) => predicates[id](context)
19
19
  });
20
20
  }
21
- const defaultGuardRegistry = createGuardRegistry();
21
+ const defaultPredicateRegistry = createPredicateRegistry();
22
22
  //#endregion
23
- exports.defaultGuardRegistry = defaultGuardRegistry;
23
+ exports.defaultPredicateRegistry = defaultPredicateRegistry;
@@ -8,22 +8,19 @@ const require_slice$4 = require("../../slices/payment/slice.js");
8
8
  /**
9
9
  * 文件角色:声明 Quick 入口的有序业务步骤。
10
10
  * 运行机制:数组顺序就是主路径;这里只保留偏离相邻前进/返回的特殊分支。
11
- * 边界:Guard、Command、Screen 与失败策略均由本地 Activity Contract 提供。
11
+ * 边界:Predicate、Command、Screen 与失败策略均由本地 Activity Contract 提供。
12
12
  */
13
13
  const quickOrderWorkflow = require_defineApplication.defineWorkflow({
14
14
  id: "hdl.quick",
15
15
  steps: [
16
16
  {
17
17
  slice: require_slice$3.identitySlice,
18
- useGuards: ["beforeEnter"]
18
+ visitPolicy: "once"
19
19
  },
20
20
  require_slice$1.customizationSlice,
21
21
  require_slice.catalogSlice,
22
22
  require_slice$2.fulfillmentSlice,
23
- {
24
- slice: require_slice$4.paymentMethodSlice,
25
- on: { eftposSelected: "paymentCompleted" }
26
- },
23
+ require_slice$4.paymentMethodSlice,
27
24
  {
28
25
  slice: require_slice$4.paymentCompletedSlice,
29
26
  end: "success"
@@ -7,7 +7,7 @@ const defaultActivityRegistry = Object.freeze({
7
7
  has: (id) => manifestRegistry.has(id),
8
8
  get: (id) => manifestRegistry.has(id) ? manifestRegistry.require(id) : void 0,
9
9
  require: (id) => manifestRegistry.require(id),
10
- accepts: (id, outcome) => manifestRegistry.require(id).outcomes.includes(outcome)
10
+ accepts: (id, intent) => manifestRegistry.require(id).intents.some((availableIntent) => availableIntent === intent)
11
11
  });
12
12
  const BUILT_IN_WORKFLOW_DEFINITIONS = Object.freeze({
13
13
  quick: require_defineApplication.normalizeKioskWorkflow(require_manifest.hdlKioskApplication.workflows.quick),
@@ -14,19 +14,10 @@ const require_slice$3 = require("../../slices/payment/slice.js");
14
14
  const scaleWorkflow = require_defineApplication.defineWorkflow({
15
15
  id: "hdl.scale",
16
16
  steps: [
17
- {
18
- slice: require_slice$1.customizationSlice,
19
- on: { skipped: "$next" }
20
- },
21
- {
22
- slice: require_slice.catalogSlice,
23
- on: { back: "customization" }
24
- },
17
+ require_slice$1.customizationSlice,
18
+ require_slice.catalogSlice,
25
19
  require_slice$2.fulfillmentSlice,
26
- {
27
- slice: require_slice$3.paymentMethodSlice,
28
- on: { eftposSelected: "paymentCompleted" }
29
- },
20
+ require_slice$3.paymentMethodSlice,
30
21
  {
31
22
  slice: require_slice$3.paymentCompletedSlice,
32
23
  end: "success"
@@ -1,6 +1,5 @@
1
1
  const require_runtime = require("../../../../../_virtual/_rolldown/runtime.js");
2
2
  const require_objectSpread2 = require("../../../../../_virtual/_@oxc-project_runtime@0.122.0/helpers/objectSpread2.js");
3
- const require_objectWithoutProperties = require("../../../../../_virtual/_@oxc-project_runtime@0.122.0/helpers/objectWithoutProperties.js");
4
3
  const require_index = require("../HDLKioskFloatingBar/index.js");
5
4
  const require_index$1 = require("../HDLKioskCartBarActions/index.js");
6
5
  let react = require("react");
@@ -12,11 +11,6 @@ react = require_runtime.__toESM(react);
12
11
  * 并区分 Modal 下可见的 masked 状态与不可导航时的 hidden 状态。
13
12
  * 边界:不计算购物车/金额;声明数据必须来自 ViewModel/Projection。
14
13
  */
15
- const _excluded = [
16
- "overlayActive",
17
- "cartEnabled",
18
- "cartOpenBar"
19
- ];
20
14
  const HDLKioskBottomBarContext = (0, react.createContext)(null);
21
15
  const HDLKioskCartDrawerContext = (0, react.createContext)(null);
22
16
  const noop = () => void 0;
@@ -42,6 +36,17 @@ function useHDLKioskBottomBar(declaration) {
42
36
  }, [context, declaration]);
43
37
  (0, react.useLayoutEffect)(() => () => context === null || context === void 0 ? void 0 : context.unregister(owner.current), [context]);
44
38
  }
39
+ function toFloatingBarProps(declaration) {
40
+ const { ariaLabel, className, leading, summary, trailing, variant } = declaration;
41
+ return {
42
+ ariaLabel,
43
+ className,
44
+ leading,
45
+ summary,
46
+ trailing,
47
+ variant
48
+ };
49
+ }
45
50
  function resolveHDLKioskBottomBarState(mode, screenOverlayActive = false) {
46
51
  const effectiveMode = mode === "hidden" ? "hidden" : mode === "masked" || screenOverlayActive ? "masked" : "visible";
47
52
  return {
@@ -113,10 +118,7 @@ function HDLKioskBottomBarHost({ children, mode = "visible", fallback, cartOverl
113
118
  }),
114
119
  className: `hdl-floating-bar--cart-open${cartBarDeclaration.className ? ` ${cartBarDeclaration.className}` : ""}`
115
120
  }) : renderedDeclaration;
116
- const floatingBarDeclaration = activeBarDeclaration ? (() => {
117
- const { overlayActive: _overlayActive, cartEnabled: _cartEnabled, cartOpenBar: _cartOpenBar } = activeBarDeclaration;
118
- return require_objectWithoutProperties._objectWithoutProperties(activeBarDeclaration, _excluded);
119
- })() : void 0;
121
+ const floatingBarDeclaration = activeBarDeclaration ? toFloatingBarProps(activeBarDeclaration) : void 0;
120
122
  (0, react.useEffect)(() => {
121
123
  if (presentation.drawerBlocked || !drawerAvailable) setCartOpen(false);
122
124
  }, [drawerAvailable, presentation.drawerBlocked]);
@@ -14,6 +14,7 @@ const INLINE_SCREEN_OPERATIONS = new Set([
14
14
  "cart.updateQuantity",
15
15
  "cart.removeLine",
16
16
  "product.syncPrimaryWeightedProduct",
17
+ "product.removePrimaryProduct",
17
18
  "checkout.requestStaffPaymentApproval",
18
19
  "checkout.payEftpos"
19
20
  ]);
@@ -46,7 +46,7 @@ HDLKiosk/
46
46
  | --- | --- |
47
47
  | `manifest.ts` | 唯一应用清单;收集 Slice 提供的 Activity/Operation,并绑定三条 Workflow |
48
48
  | `constants.ts` | `HDL_WORKFLOW_IDS` 等应用常量 |
49
- | `events.ts` | HDLKiosk Activity Outcome 的强类型事件联合 |
49
+ | `events.ts` | HDLKiosk Activity Intent 与 Back Navigation 的强类型事件联合 |
50
50
  | `operations.ts` | 共享 Operation 的唯一公共导入入口 |
51
51
  | `operations/` | `operations.ts` 背后的私有实现、Coordinator 策略和测试;外部代码不要逐文件跨层引用 |
52
52
  | `views.ts` | 应用层 Activity → React View 的完整同步注册表;不进入 Slice/Workflow/Kernel |
@@ -54,7 +54,7 @@ HDLKiosk/
54
54
  | `workflow/barcode.ts` | Barcode 的有序 Activity 列表与特殊转移 |
55
55
  | `workflow/scale.ts` | Scale 的有序 Activity 列表与特殊转移 |
56
56
  | `workflow/registry.ts` | 从 Manifest 派生 Activity Registry,并提供内置流程查询 |
57
- | `workflow/guards.ts` | HDLKiosk 本地 Guard Registry |
57
+ | `workflow/predicates.ts` | HDLKiosk 本地 Predicate Registry |
58
58
  | `workflow/policy.ts` | 支付门禁等商家应用策略校验;结构编译仍属于 Kernel |
59
59
  | `ScreenRenderer.tsx` | 按当前 Activity 从 `views.ts` 取 View;处理 modal base 叠加和缺失 View 的阻断呈现 |
60
60
  | `entry/model.ts` | 派生 Workflow 之外三个入口的可用性和展示模型 |
@@ -75,7 +75,7 @@ slices/<name>/
75
75
  └── model.ts # 仅本 Slice 使用的纯模型;按需存在
76
76
  ```
77
77
 
78
- 当前 Slice:`identity`、`fulfillment`、`customization`、`catalog`、`paymentMethod`、`paymentCompleted`。`paymentCompleted` 只是支付成功终态,与 `paymentMethod` 共用 Checkout Screen/View,不存在独立 Result Screen。
78
+ 当前 Slice:`identity`、`fulfillment`、`customization`、`catalog`、`primaryProductPrompt`、`paymentMethod`、`paymentCompleted`。`primaryProductPrompt` 是以 Catalog 为 base 的 Modal;`paymentCompleted` 是支付成功终态,与 `paymentMethod` 共用 Checkout Screen/View。
79
79
 
80
80
  - `slices/index.ts` 只汇总各目录导出的 `defineSlice` 结果,并统一约束 `screen.id` 必须是 HDLKiosk `ScreenId`;
81
81
  - 每个 `slice.ts` 只通过 `screen: { id }` 声明页面类别;实际 View 在 `app/views.ts` 中按 Activity 单独、完整地注册,使用同步本地组件引用;
@@ -84,7 +84,7 @@ slices/<name>/
84
84
 
85
85
  `Slice` 是作者侧唯一业务能力概念:`defineSlice` 定义能力,`application.slices` 收集能力,Workflow 的 `slice` 字段引用能力;运行期再编译为 Activity Contract。
86
86
 
87
- 命名关系必须保持单向:Slice `id` 是业务 Activity;`screen.id` 是页面类别;`app/views.ts` 按 Activity 注册实际 UI。`catalog` 和 `catalogWithPrimaryProductPrompt` 可以共享 Catalog Screen 与 View,但仍是不同的业务 Slice。非 EFTPOS 店员支付授权是 `paymentMethod` 页面内 Command,不创建 Kiosk 等待 Activity 或弹窗。
87
+ 命名关系必须保持单向:Slice `id` 是业务 Activity;`screen.id` 是页面类别;`app/views.ts` 按 Activity 注册实际 UI。`catalog` 负责商品浏览,`primaryProductPrompt` 负责主商品询问;Prompt 以 Modal 覆盖 Actor Surface 中当前实际 Page,不引用固定背景 Step。支付派发和店员支付授权是 `paymentMethod` 页面内 Command,不创建流程 Intent。
88
88
 
89
89
  ## 5. `components/`:共享展示能力
90
90
 
@@ -103,7 +103,7 @@ slices/<name>/
103
103
  | `createWorkflowSession.ts` | 读取内置 Definition,直接编译、校验并创建 Actor/Coordinator |
104
104
  | `HDLKioskWorkflowView.tsx` | 活跃会话的 React 组合层;连接 Shell、Renderer 和 Controllers |
105
105
  | `domainTransitionRunner.ts` | 将 Actor 的 exit effect 交给 Operation Coordinator |
106
- | `workflowContext.ts` | 只归并经过 Activity Outcome 确认的流程上下文 |
106
+ | `workflowContext.ts` | 只归并经过 Activity Intent 成功提交的流程上下文 |
107
107
  | `workflowLifecycle.ts` | Actor blocked/finished 的 Host 遥测与生命周期钩子 |
108
108
  | `useHostSnapshot.ts` | 订阅 Host Projection |
109
109
  | `useWorkflowSnapshot.ts` | 订阅 Actor Snapshot |
@@ -126,7 +126,7 @@ BigSale 专用 H5 登录实现位于 `bigSale/templates/HDLKiosk/auth/`。独立
126
126
  | 位置 | 角色 |
127
127
  | --- | --- |
128
128
  | `application/` | `defineSlice`、`defineKioskApplication`、Slice 收集和 authoring normalization |
129
- | `workflow/compiler.ts` | 编译有序 Step 数组,校验 ID、Outcome、可达性、modal base 和有界循环 |
129
+ | `workflow/compiler.ts` | 编译有序 Step 数组,校验 ID、Intent、可达性、modal base 和有界循环 |
130
130
  | `workflow/actor.ts` | 单会话串行状态机,拒绝迟到 Activity/Step 事件 |
131
131
  | `workflow/transition.ts` | advance/stay/blocked 等转移结果原语 |
132
132
  | `operations/coordinator.ts` | 通用排队、去重、timeout、dispose 和 epoch 协调 |
@@ -164,7 +164,7 @@ import {
164
164
  - `host.ts`:Host 总入口和 capabilities;
165
165
  - `sales.ts`:标准 ProductData、OS 加购流、购物车、客户、履约、支付和 Projection;
166
166
  - `devices.ts`:scanner/scale port;
167
- - `workflow*.ts`:Activity、Definition 和 Guard 协议;
167
+ - `workflow*.ts`:Activity、Definition、Predicate 和 Navigation Guard 协议;
168
168
  - `operations.ts`:允许请求的 Operation ID 与输入映射;
169
169
  - `results.ts` / `errors.ts` / `telemetry.ts`:结果、错误与观测。
170
170