@pisell/private-materials 6.3.139 → 6.3.140

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 (47) 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/index.js +1 -1
  5. package/build/lowcode/meta.js +1 -1
  6. package/build/lowcode/preview.js +5 -5
  7. package/build/lowcode/render/default/view.css +1 -1
  8. package/build/lowcode/render/default/view.js +7 -7
  9. package/build/lowcode/view.css +1 -1
  10. package/build/lowcode/view.js +6 -6
  11. package/es/components/scanOrder/components/Cart/index.js +127 -56
  12. package/es/components/scanOrder/components/Cart/index.less +11 -5
  13. package/es/components/scanOrder/components/Check/index.js +85 -80
  14. package/es/components/scanOrder/components/Content/index.js +345 -162
  15. package/es/components/scanOrder/components/Menu/index.d.ts +11 -0
  16. package/es/components/scanOrder/components/Menu/index.js +140 -169
  17. package/es/components/scanOrder/components/Voucher/index.d.ts +8 -0
  18. package/es/components/scanOrder/components/Voucher/index.js +250 -0
  19. package/es/components/scanOrder/context.js +38 -13
  20. package/es/components/scanOrder/hooks.js +4 -1
  21. package/es/components/scanOrder/locales.d.ts +65 -0
  22. package/es/components/scanOrder/locales.js +65 -0
  23. package/es/components/scanOrder/types.d.ts +10 -0
  24. package/es/components/scanOrder/utils/toShoppingCartProducts.d.ts +1 -0
  25. package/es/components/scanOrder/utils/toShoppingCartProducts.js +137 -9
  26. package/es/components/scanOrder/utils/transformProductDetail.js +21 -4
  27. package/es/components/venueBooking/components/Addons/index.js +42 -33
  28. package/es/components/venueBooking/components/Cart/index.js +26 -14
  29. package/lib/components/scanOrder/components/Cart/index.js +79 -24
  30. package/lib/components/scanOrder/components/Cart/index.less +11 -5
  31. package/lib/components/scanOrder/components/Check/index.js +28 -23
  32. package/lib/components/scanOrder/components/Content/index.js +132 -42
  33. package/lib/components/scanOrder/components/Menu/index.d.ts +11 -0
  34. package/lib/components/scanOrder/components/Menu/index.js +23 -36
  35. package/lib/components/scanOrder/components/Voucher/index.d.ts +8 -0
  36. package/lib/components/scanOrder/components/Voucher/index.js +162 -0
  37. package/lib/components/scanOrder/context.js +21 -10
  38. package/lib/components/scanOrder/hooks.js +4 -1
  39. package/lib/components/scanOrder/locales.d.ts +65 -0
  40. package/lib/components/scanOrder/locales.js +65 -0
  41. package/lib/components/scanOrder/types.d.ts +10 -0
  42. package/lib/components/scanOrder/utils/toShoppingCartProducts.d.ts +1 -0
  43. package/lib/components/scanOrder/utils/toShoppingCartProducts.js +88 -6
  44. package/lib/components/scanOrder/utils/transformProductDetail.js +10 -3
  45. package/lib/components/venueBooking/components/Addons/index.js +15 -8
  46. package/lib/components/venueBooking/components/Cart/index.js +8 -2
  47. package/package.json +1 -1
@@ -37,9 +37,12 @@ var import_materials = require("@pisell/materials");
37
37
  var import_utils = require("@pisell/utils");
38
38
  var import_shoppingCart = __toESM(require("../../../shoppingCart"));
39
39
  var import_context = require("../../context");
40
+ var import_useEngineContext = __toESM(require("../../../../hooks/useEngineContext"));
40
41
  var import_subTotal = __toESM(require("../../../subTotal"));
42
+ var import_Voucher = __toESM(require("../Voucher"));
41
43
  var import_index = require("./index.less");
42
44
  function Cart(props) {
45
+ var _a, _b, _c, _d, _e, _f;
43
46
  const {
44
47
  open,
45
48
  onCancel,
@@ -52,16 +55,24 @@ function Cart(props) {
52
55
  disabled = false
53
56
  } = props;
54
57
  const { runModuleAction, refreshViewModel, scanOrderModule } = (0, import_context.useScanOrderContext)();
58
+ const engineContext = (0, import_useEngineContext.default)();
59
+ const businessUtils = (_b = (_a = engineContext == null ? void 0 : engineContext.appHelper) == null ? void 0 : _a.utils) == null ? void 0 : _b.businessUtils;
60
+ const locale = ((_d = (_c = engineContext == null ? void 0 : engineContext.engine) == null ? void 0 : _c.props) == null ? void 0 : _d.locale) || "en";
61
+ const hasGoodPassApp = !!((_e = businessUtils == null ? void 0 : businessUtils.getAppByModal) == null ? void 0 : _e.call(businessUtils, "goodpass"));
62
+ const hasDiscountCardApp = !!((_f = businessUtils == null ? void 0 : businessUtils.getAppByModal) == null ? void 0 : _f.call(businessUtils, "discountcard"));
63
+ const showVoucher = hasGoodPassApp || hasDiscountCardApp;
55
64
  const isVisible = embedded || open;
56
65
  if (!isVisible) return null;
57
66
  const [dineInConfig, setDineInConfig] = (0, import_react.useState)(null);
58
- const getConfig = async () => {
67
+ const getConfig = (0, import_react.useCallback)(async () => {
59
68
  const otherParams = await runModuleAction("getOtherParams");
60
69
  console.log("otherParams >>>>> ", otherParams);
61
70
  const dineInConfig2 = (otherParams == null ? void 0 : otherParams.dineInConfig) ?? {};
62
71
  setDineInConfig(dineInConfig2);
63
- };
64
- getConfig();
72
+ }, [runModuleAction]);
73
+ (0, import_react.useEffect)(() => {
74
+ getConfig();
75
+ }, []);
65
76
  const isShowNote = (0, import_react.useMemo)(() => {
66
77
  return dineInConfig == null ? void 0 : dineInConfig["sale.allow_item_notes"];
67
78
  }, [dineInConfig]);
@@ -75,11 +86,11 @@ function Cart(props) {
75
86
  import_utils.locales.getText("pisell2.scan.order.action.confirm.order") || import_utils.locales.getText("pisell2.event.confirm") || "Confirm"
76
87
  );
77
88
  const subTotalList = (0, import_react.useMemo)(() => {
78
- var _a;
89
+ var _a2;
79
90
  const subTotal = Number((summary == null ? void 0 : summary.product_amount) ?? 0);
80
91
  const totalTaxFee = Number((summary == null ? void 0 : summary.tax_fee) ?? 0);
81
92
  const total = Number((summary == null ? void 0 : summary.total_amount) ?? (summary == null ? void 0 : summary.expect_amount) ?? 0);
82
- const tempOrder = (_a = scanOrderModule == null ? void 0 : scanOrderModule.getTempOrder) == null ? void 0 : _a.call(scanOrderModule);
93
+ const tempOrder = (_a2 = scanOrderModule == null ? void 0 : scanOrderModule.getTempOrder) == null ? void 0 : _a2.call(scanOrderModule);
83
94
  const tempSummary = (tempOrder == null ? void 0 : tempOrder.summary) || {};
84
95
  const taxTitle = String(
85
96
  (tempSummary == null ? void 0 : tempSummary.tax_title) || (summary == null ? void 0 : summary.tax_title) || "GST/Tax"
@@ -89,11 +100,21 @@ function Cart(props) {
89
100
  const isPriceIncludeTax = Boolean(
90
101
  (tempSummary == null ? void 0 : tempSummary.is_price_include_tax) ?? (tempSummary == null ? void 0 : tempSummary.isPriceIncludeTax) ?? (summary == null ? void 0 : summary.is_price_include_tax)
91
102
  );
103
+ const surchargeItems = ((summary == null ? void 0 : summary.surcharges) || []).filter((s) => Number(s == null ? void 0 : s.amount) > 0).map((s) => {
104
+ const labelObj = (s == null ? void 0 : s.label) || (s == null ? void 0 : s.name) || {};
105
+ const label = labelObj[locale] || labelObj.en || labelObj.original || (s == null ? void 0 : s.key) || "";
106
+ return {
107
+ key: (s == null ? void 0 : s.key) || `surcharge_${s == null ? void 0 : s.surcharge_id}`,
108
+ label,
109
+ value: Number(s == null ? void 0 : s.amount)
110
+ };
111
+ });
92
112
  return [
93
113
  {
94
114
  key: "sub_total",
95
115
  value: Number.isNaN(subTotal) ? 0 : subTotal
96
116
  },
117
+ ...surchargeItems,
97
118
  {
98
119
  key: "tax",
99
120
  value: Number.isNaN(totalTaxFee) ? 0 : totalTaxFee,
@@ -111,25 +132,58 @@ function Cart(props) {
111
132
  bold: true
112
133
  }
113
134
  ];
114
- }, [summary, scanOrderModule]);
135
+ }, [summary, scanOrderModule, locale]);
115
136
  const handleCartChange = async (item, type) => {
116
- if (type !== "delete") return;
117
- const productId = (item == null ? void 0 : item.product_id) ?? (item == null ? void 0 : item.id) ?? null;
118
- const productVariantId = Number((item == null ? void 0 : item.product_variant_id) ?? 0);
119
- const identityKey = (item == null ? void 0 : item.identity_key) || (item == null ? void 0 : item.rowKey) || void 0;
120
- if (productId === null && Number.isNaN(productVariantId)) return;
121
- try {
122
- await runModuleAction("removeProductFromOrder", {
137
+ if (type === "note") {
138
+ const productId = (item == null ? void 0 : item.product_id) ?? (item == null ? void 0 : item.id) ?? null;
139
+ const productVariantId = Number((item == null ? void 0 : item.product_variant_id) ?? 0);
140
+ const identityKey = item == null ? void 0 : item.identity_key;
141
+ if (productId === null && Number.isNaN(productVariantId)) return;
142
+ const identity = {
123
143
  product_id: productId,
124
- product_variant_id: Number.isNaN(productVariantId) ? 0 : productVariantId,
125
- identity_key: identityKey
126
- });
127
- await refreshViewModel();
128
- } catch (error) {
129
- console.error("[scanOrder] removeProductFromOrder failed", {
130
- error,
131
- item
132
- });
144
+ product_variant_id: Number.isNaN(productVariantId) ? 0 : productVariantId
145
+ };
146
+ if (typeof identityKey === "string" && identityKey.length > 0) {
147
+ identity.identity_key = identityKey;
148
+ }
149
+ try {
150
+ await runModuleAction(
151
+ "setOrderProductLineNote",
152
+ identity,
153
+ String((item == null ? void 0 : item.note) ?? "")
154
+ );
155
+ await refreshViewModel();
156
+ } catch (error) {
157
+ console.error("[scanOrder] setOrderProductLineNote failed", {
158
+ error,
159
+ item
160
+ });
161
+ }
162
+ return;
163
+ } else if (type === "delete") {
164
+ const productId = (item == null ? void 0 : item.product_id) ?? (item == null ? void 0 : item.id) ?? null;
165
+ const productVariantId = Number((item == null ? void 0 : item.product_variant_id) ?? 0);
166
+ const identityKey = item == null ? void 0 : item.identity_key;
167
+ if (productId === null && Number.isNaN(productVariantId)) return;
168
+ if (typeof identityKey !== "string" || identityKey.length === 0) {
169
+ console.error("[scanOrder] removeProductFromOrder skipped: missing identity_key", {
170
+ item
171
+ });
172
+ return;
173
+ }
174
+ try {
175
+ await runModuleAction("removeProductFromOrder", {
176
+ product_id: productId,
177
+ product_variant_id: Number.isNaN(productVariantId) ? 0 : productVariantId,
178
+ identity_key: identityKey
179
+ });
180
+ await refreshViewModel();
181
+ } catch (error) {
182
+ console.error("[scanOrder] removeProductFromOrder failed", {
183
+ error,
184
+ item
185
+ });
186
+ }
133
187
  }
134
188
  };
135
189
  (0, import_react.useEffect)(() => {
@@ -157,8 +211,9 @@ function Cart(props) {
157
211
  onChange: handleCartChange
158
212
  }
159
213
  );
160
- const cartSubtotalSection = /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, /* @__PURE__ */ import_react.default.createElement(import_subTotal.default, { list: subTotalList, style: { padding: 0 } }), extraContent ? /* @__PURE__ */ import_react.default.createElement("div", { className: "pisell-scan-order-cart-extra-content" }, extraContent) : null);
161
- const cartBodyContent = /* @__PURE__ */ import_react.default.createElement("div", { className: "pisell-scan-order-cart-body" }, cartLineItems, cartSubtotalSection);
214
+ const cartSubtotalSection = /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, showVoucher ? /* @__PURE__ */ import_react.default.createElement(import_Voucher.default, null) : null, /* @__PURE__ */ import_react.default.createElement(import_subTotal.default, { list: subTotalList, style: { padding: 0 } }), extraContent ? /* @__PURE__ */ import_react.default.createElement("div", { className: "pisell-scan-order-cart-extra-content" }, extraContent) : null);
215
+ const cartBodyClassName = embedded ? "pisell-scan-order-cart-body pisell-scan-order-cart-body-embedded" : "pisell-scan-order-cart-body";
216
+ const cartBodyContent = /* @__PURE__ */ import_react.default.createElement("div", { className: cartBodyClassName }, cartLineItems, cartSubtotalSection);
162
217
  if (embedded) {
163
218
  return /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, cartBodyContent, /* @__PURE__ */ import_react.default.createElement("div", { className: "pisell-scan-order-cart-embedded-footer" }, /* @__PURE__ */ import_react.default.createElement(
164
219
  import_materials.Button,
@@ -118,16 +118,22 @@
118
118
  cursor: not-allowed;
119
119
  }
120
120
 
121
+ /* 移动端:结算内嵌卡 — 与 pisell-scan-order-content-mobile-wrap 的底部留白配合;
122
+ * 不再在 cart-body 上重复 96px,否则与外层叠加会出现大块空白,sticky 在整页滚动时也会与内容同步位移 */
121
123
  .pisell-scan-order-content-mobile-wrap {
122
- .pisell-scan-order-cart-body {
123
- padding-bottom: 96px;
124
+ .pisell-scan-order-cart-body-embedded {
125
+ padding-bottom: 16px;
124
126
  }
125
127
 
126
128
  .pisell-scan-order-cart-embedded-footer {
127
- position: sticky;
129
+ position: fixed;
130
+ left: 0;
131
+ right: 0;
128
132
  bottom: 0;
129
- z-index: 5;
130
- padding-bottom: calc(20px + env(safe-area-inset-bottom, 0px));
133
+ z-index: 28;
134
+ padding: 12px 16px calc(20px + env(safe-area-inset-bottom, 0px));
135
+ border-top: 1px solid #eaecf0;
136
+ background: #fff;
131
137
  box-shadow: 0 -4px 10px rgba(16, 24, 40, 0.06);
132
138
  }
133
139
  }
@@ -35,7 +35,6 @@ module.exports = __toCommonJS(Check_exports);
35
35
  var import_react = __toESM(require("react"));
36
36
  var import_antd = require("antd");
37
37
  var import_utils = require("@pisell/utils");
38
- var import_materials = require("@pisell/materials");
39
38
  var import_Cart = __toESM(require("../Cart"));
40
39
  var import_FulfillmentMode = __toESM(require("../FulfillmentMode"));
41
40
  var import_ManualPickupRefModal = __toESM(require("../ManualPickupRefModal"));
@@ -50,13 +49,15 @@ function Check() {
50
49
  const [pickupRefOpen, setPickupRefOpen] = (0, import_react.useState)(false);
51
50
  const utils = (0, import_hooks.contextUtils)();
52
51
  const [dineInConfig, setDineInConfig] = (0, import_react.useState)(null);
53
- const getConfig = async () => {
52
+ const getConfig = (0, import_react.useCallback)(async () => {
54
53
  const otherParams = await runModuleAction("getOtherParams");
55
54
  console.log("otherParams >>>>> ", otherParams);
56
55
  const dineInConfig2 = (otherParams == null ? void 0 : otherParams.dineInConfig) ?? {};
57
56
  setDineInConfig(dineInConfig2);
58
- };
59
- getConfig();
57
+ }, [runModuleAction]);
58
+ (0, import_react.useEffect)(() => {
59
+ getConfig();
60
+ }, []);
60
61
  const isShowOrderNote = (0, import_react.useMemo)(() => {
61
62
  return dineInConfig == null ? void 0 : dineInConfig["sale.allow_order_notes"];
62
63
  }, [dineInConfig]);
@@ -80,41 +81,50 @@ function Check() {
80
81
  () => String(import_utils.locales.getText("pisell2.scan.order.products.title") || "Products"),
81
82
  []
82
83
  );
84
+ const showCheckStepEmptyCartTip = () => {
85
+ import_antd.message.error(import_utils.locales.getText("pisell2.scan.order.check.cart.empty.tip") || "Please go back to add products");
86
+ };
83
87
  const doSubmit = async () => {
84
- var _a, _b, _c, _d, _e, _f, _g;
88
+ var _a, _b, _c, _d, _e, _f, _g, _h;
89
+ const items = (viewModel == null ? void 0 : viewModel.cartItems) || [];
90
+ if (items.length === 0) {
91
+ showCheckStepEmptyCartTip();
92
+ setSubmitting(false);
93
+ return;
94
+ }
85
95
  try {
86
96
  setSubmitting(true);
87
97
  await runModuleAction("updateTempOrderNote", note);
88
98
  const res = await runModuleAction("submitScanOrder");
89
99
  console.log("submitScanOrder >>>>> ", res);
90
100
  clearStepCache();
91
- if (dineInConfig == null ? void 0 : dineInConfig["workflow.require_payment_on_submit"]) {
101
+ if ((dineInConfig == null ? void 0 : dineInConfig["sale.require_payment_on_submit"]) && !isAdditionalOrder) {
102
+ try {
103
+ await runModuleAction("restoreOrder");
104
+ } catch (error) {
105
+ console.warn("[scanOrder] restoreOrder after payment failed", error);
106
+ }
92
107
  utils.action({
93
108
  type: "pisell1.payment",
94
109
  data: {
95
110
  order_id: (_a = res == null ? void 0 : res.data) == null ? void 0 : _a.order_id,
96
- total_amount: (_b = viewModel == null ? void 0 : viewModel.summary) == null ? void 0 : _b.total_amount
111
+ total_amount: ((_b = res == null ? void 0 : res.data) == null ? void 0 : _b.order_wait_pay_amount) || ((_c = viewModel == null ? void 0 : viewModel.summary) == null ? void 0 : _c.total_amount)
97
112
  },
98
113
  callback: async (_e2) => {
99
- try {
100
- await runModuleAction("restoreOrder");
101
- } catch (error) {
102
- console.warn("[scanOrder] restoreOrder after payment failed", error);
103
- }
104
114
  }
105
115
  });
106
116
  } else {
107
- if ((_c = res == null ? void 0 : res.data) == null ? void 0 : _c.order_id) {
117
+ if ((_d = res == null ? void 0 : res.data) == null ? void 0 : _d.order_id) {
108
118
  try {
109
119
  await runModuleAction("restoreOrder");
110
120
  } catch (error) {
111
121
  console.warn("[scanOrder] restoreOrder before redirect failed", error);
112
122
  }
113
- const link = `/order/details?id=${(_d = res == null ? void 0 : res.data) == null ? void 0 : _d.order_id}`;
114
- const app = (_e = utils == null ? void 0 : utils.getApp) == null ? void 0 : _e.call(utils);
115
- if ((_f = app == null ? void 0 : app.history) == null ? void 0 : _f.replace) {
123
+ const link = `/order/details?id=${(_e = res == null ? void 0 : res.data) == null ? void 0 : _e.order_id}`;
124
+ const app = (_f = utils == null ? void 0 : utils.getApp) == null ? void 0 : _f.call(utils);
125
+ if ((_g = app == null ? void 0 : app.history) == null ? void 0 : _g.replace) {
116
126
  app.history.replace(link);
117
- } else if ((_g = app == null ? void 0 : app.history) == null ? void 0 : _g.push) {
127
+ } else if ((_h = app == null ? void 0 : app.history) == null ? void 0 : _h.push) {
118
128
  app.history.push(link);
119
129
  } else {
120
130
  location.replace(link);
@@ -133,12 +143,7 @@ function Check() {
133
143
  if (submitting) return;
134
144
  const cartItems = (viewModel == null ? void 0 : viewModel.cartItems) || [];
135
145
  if (cartItems.length === 0) {
136
- (0, import_materials.PisellToast)({
137
- content: String(
138
- import_utils.locales.getText("pisell2.scan.order.products.empty.tip") || "Please select products"
139
- ),
140
- duration: 2
141
- });
146
+ showCheckStepEmptyCartTip();
142
147
  return;
143
148
  }
144
149
  if (isAdditionalOrder) {
@@ -91,7 +91,9 @@ function ReadyState() {
91
91
  scanOrderModule,
92
92
  isCacheHydrated,
93
93
  markGate,
94
- isGatePassed
94
+ isGatePassed,
95
+ resumeStep,
96
+ consumeResumeStep
95
97
  } = (0, import_context.useScanOrderContext)();
96
98
  const { isLogin, openLoginModal } = (0, import_hooks.useScanOrderLogin)();
97
99
  const utils = (0, import_hooks.contextUtils)();
@@ -109,14 +111,55 @@ function ReadyState() {
109
111
  content: null
110
112
  });
111
113
  const [pendingFormPayload, setPendingFormPayload] = (0, import_react.useState)(null);
114
+ const [productList, setProductList] = (0, import_react.useState)([]);
115
+ const productListLoadedRef = (0, import_react.useRef)(false);
116
+ const productListPromiseRef = (0, import_react.useRef)(null);
117
+ const ensureProductListLoaded = (0, import_react.useCallback)(async () => {
118
+ if (productListLoadedRef.current) return;
119
+ if (productListPromiseRef.current) {
120
+ await productListPromiseRef.current.catch(() => {
121
+ });
122
+ return;
123
+ }
124
+ const request = (async () => {
125
+ try {
126
+ const res = await runModuleAction("getProductList");
127
+ if (Array.isArray(res)) {
128
+ productListLoadedRef.current = true;
129
+ setProductList(res);
130
+ return;
131
+ }
132
+ import_antd.Modal.confirm({
133
+ title: res == null ? void 0 : res.message,
134
+ okText: String(import_utils.locales.getText("pisell2.event.confirm") || "OK"),
135
+ cancelButtonProps: { style: { display: "none" } },
136
+ maskClosable: false,
137
+ onOk: () => {
138
+ location.replace("/");
139
+ }
140
+ });
141
+ } catch (error) {
142
+ console.warn("[scanOrder] getProductList failed", error);
143
+ } finally {
144
+ productListPromiseRef.current = null;
145
+ }
146
+ })();
147
+ productListPromiseRef.current = request;
148
+ await request;
149
+ }, [runModuleAction]);
112
150
  const requestEntryPaxRef = (0, import_react.useRef)(0);
113
151
  const requestPaxMinRef = (0, import_react.useRef)(1);
114
152
  const requestPaxMaxRef = (0, import_react.useRef)(1);
115
153
  const tableFormRecordRef = (0, import_react.useRef)(null);
154
+ const entryPaxModalWasPresentedRef = (0, import_react.useRef)(false);
116
155
  const getLocalizedName = (nameMap) => {
117
156
  if (!nameMap) return "";
118
157
  const currentLocale = import_utils.locales.getLocale();
119
- return nameMap[currentLocale] || nameMap.original || nameMap.en || "";
158
+ const localized = nameMap[currentLocale];
159
+ if (typeof localized === "string" && localized) return localized;
160
+ const original = nameMap.original;
161
+ if (typeof original === "string" && original) return original;
162
+ return "";
120
163
  };
121
164
  const resolveLocalizedText = (value) => {
122
165
  if (value == null) return "";
@@ -140,6 +183,34 @@ function ReadyState() {
140
183
  };
141
184
  };
142
185
  const app = (_a = utils == null ? void 0 : utils.getApp) == null ? void 0 : _a.call(utils);
186
+ const navigateToHome = () => {
187
+ var _a2, _b2;
188
+ if ((_a2 = app == null ? void 0 : app.history) == null ? void 0 : _a2.replace) {
189
+ app.history.replace("/");
190
+ } else if ((_b2 = app == null ? void 0 : app.history) == null ? void 0 : _b2.push) {
191
+ app.history.push("/");
192
+ } else {
193
+ location.replace("/");
194
+ }
195
+ };
196
+ const requestEntryPaxModal = () => new Promise((resolve) => {
197
+ var _a2;
198
+ if (typeof (utils == null ? void 0 : utils.action) !== "function") {
199
+ resolve(null);
200
+ return;
201
+ }
202
+ utils.action({
203
+ type: "pisell1.handlePaxModal",
204
+ data: {
205
+ tableName: getLocalizedName((_a2 = tableFormRecordRef.current) == null ? void 0 : _a2.name),
206
+ requestPaxMin: requestPaxMinRef.current,
207
+ requestPaxMax: requestPaxMaxRef.current
208
+ },
209
+ callback: (result) => {
210
+ resolve(extractEntryPaxNumber(result));
211
+ }
212
+ });
213
+ });
143
214
  const handleOrderDetail = (order_id) => {
144
215
  var _a2, _b2;
145
216
  const link = `/order/details?id=${order_id}`;
@@ -152,7 +223,6 @@ function ReadyState() {
152
223
  }
153
224
  };
154
225
  const handleBack = () => {
155
- var _a2, _b2;
156
226
  if (currentStep !== "product") {
157
227
  prevStep();
158
228
  return;
@@ -161,13 +231,23 @@ function ReadyState() {
161
231
  handleOrderDetail(entryContext.order_id);
162
232
  return;
163
233
  }
164
- if ((_a2 = app == null ? void 0 : app.history) == null ? void 0 : _a2.replace) {
165
- app.history.replace("/");
166
- } else if ((_b2 = app == null ? void 0 : app.history) == null ? void 0 : _b2.push) {
167
- app.history.push("/");
168
- } else {
169
- location.replace("/");
234
+ if (entryPaxModalWasPresentedRef.current) {
235
+ void (async () => {
236
+ const pax = await requestEntryPaxModal();
237
+ if (pax == null) {
238
+ navigateToHome();
239
+ return;
240
+ }
241
+ try {
242
+ await runModuleAction("setEntryPaxNumber", pax);
243
+ await refreshViewModel();
244
+ } catch (error) {
245
+ console.warn("[scanOrder] setEntryPaxNumber on back pax confirm failed", error);
246
+ }
247
+ })();
248
+ return;
170
249
  }
250
+ navigateToHome();
171
251
  };
172
252
  const enterProductStep = async () => {
173
253
  try {
@@ -176,7 +256,9 @@ function ReadyState() {
176
256
  } catch (error) {
177
257
  console.warn("[scanOrder] applyItemRulePrefill failed", error);
178
258
  } finally {
179
- if (currentStep !== "check") goToStep("product");
259
+ const target = resumeStep === "check" ? "check" : "product";
260
+ if (resumeStep) consumeResumeStep();
261
+ goToStep(target);
180
262
  }
181
263
  };
182
264
  const runEntryPaxGateThenEnterProduct = async () => {
@@ -188,26 +270,10 @@ function ReadyState() {
188
270
  await enterProductStep();
189
271
  return;
190
272
  }
191
- const pax = await new Promise((resolve) => {
192
- var _a2;
193
- if (typeof (utils == null ? void 0 : utils.action) !== "function") {
194
- resolve(null);
195
- return;
196
- }
197
- utils.action({
198
- type: "pisell1.handlePaxModal",
199
- data: {
200
- tableName: getLocalizedName((_a2 = tableFormRecordRef.current) == null ? void 0 : _a2.name),
201
- requestPaxMin: requestPaxMinRef.current,
202
- requestPaxMax: requestPaxMaxRef.current
203
- },
204
- callback: (result) => {
205
- resolve(extractEntryPaxNumber(result));
206
- }
207
- });
208
- });
273
+ entryPaxModalWasPresentedRef.current = true;
274
+ const pax = await requestEntryPaxModal();
209
275
  if (pax == null) {
210
- location.replace("/");
276
+ navigateToHome();
211
277
  return;
212
278
  }
213
279
  try {
@@ -277,6 +343,7 @@ function ReadyState() {
277
343
  };
278
344
  (0, import_react.useEffect)(() => {
279
345
  const checkResourceAvailable = async () => {
346
+ var _a2;
280
347
  const hasOrderId = !!(entryContext == null ? void 0 : entryContext.order_id);
281
348
  const {
282
349
  mode,
@@ -318,19 +385,33 @@ function ReadyState() {
318
385
  }
319
386
  await runEntryPaxGateThenEnterProduct();
320
387
  } else if (isAdditionalOrder) {
321
- if (hasOrderId) {
322
- await enterProductStep();
323
- } else {
324
- handleOrderDetail(order_id);
325
- }
388
+ await enterProductStep();
326
389
  } else if (mode === "submit_disabled") {
327
390
  const tips = resolveLocalizedText(errorTips) || String(import_utils.locales.getText("pisell2.scan.order.submit.disabled.default") || "");
328
391
  setSubmitDisabledTips(tips);
329
392
  await enterProductStep();
393
+ } else if (mode === "resource_busy") {
394
+ if (!isLogin) {
395
+ (_a2 = scanOrderModule == null ? void 0 : scanOrderModule.setUIState) == null ? void 0 : _a2.call(scanOrderModule, "pendingStep", currentStep);
396
+ openLoginModal({
397
+ callback: (status) => {
398
+ var _a3, _b2;
399
+ if (status === "success") {
400
+ (_a3 = scanOrderModule == null ? void 0 : scanOrderModule.deleteUIState) == null ? void 0 : _a3.call(scanOrderModule, "pendingStep");
401
+ handleOrderDetail(order_id);
402
+ return;
403
+ }
404
+ (_b2 = scanOrderModule == null ? void 0 : scanOrderModule.deleteUIState) == null ? void 0 : _b2.call(scanOrderModule, "pendingStep");
405
+ location.replace("/");
406
+ }
407
+ });
408
+ } else {
409
+ handleOrderDetail(order_id);
410
+ }
330
411
  } else {
331
412
  let content = resolveLocalizedText(errorTips);
332
413
  if (!content) {
333
- if (mode === "resource_busy") {
414
+ if (mode === "resource_block") {
334
415
  content = String(
335
416
  import_utils.locales.getText("pisell2.scan.order.resource.status.exception") || ""
336
417
  );
@@ -342,7 +423,7 @@ function ReadyState() {
342
423
  }
343
424
  import_antd.Modal.info({
344
425
  title: import_utils.locales.getText("pisell2.scan.order.step.error"),
345
- content: String(content || "").trim(),
426
+ content: resolveLocalizedText(content).trim(),
346
427
  okText: String(import_utils.locales.getText("pisell2.event.confirm") || "OK"),
347
428
  maskClosable: false,
348
429
  onOk: () => {
@@ -375,7 +456,14 @@ function ReadyState() {
375
456
  }, [currentStep, cartValidation == null ? void 0 : cartValidation.passed]);
376
457
  const stepRegistry = {
377
458
  init: /* @__PURE__ */ import_react.default.createElement(import_Initializing.default, null),
378
- product: /* @__PURE__ */ import_react.default.createElement(import_Menu.default, { onCheckout: () => goToStep("check") }),
459
+ product: /* @__PURE__ */ import_react.default.createElement(
460
+ import_Menu.default,
461
+ {
462
+ onCheckout: () => goToStep("check"),
463
+ productList,
464
+ onEnsureProductList: ensureProductListLoaded
465
+ }
466
+ ),
379
467
  check: /* @__PURE__ */ import_react.default.createElement(import_Check.default, null),
380
468
  error: /* @__PURE__ */ import_react.default.createElement(import_ErrorState.default, { message: import_utils.locales.getText("pisell2.scan.order.store.status.exception") })
381
469
  };
@@ -420,6 +508,7 @@ function ReadyState() {
420
508
  return highlighted;
421
509
  };
422
510
  const gotoCheckOrder = async () => {
511
+ var _a2;
423
512
  if (submitDisabledTips) {
424
513
  import_antd.message.warning(submitDisabledTips, 2);
425
514
  return;
@@ -450,16 +539,17 @@ function ReadyState() {
450
539
  return;
451
540
  }
452
541
  if (!isLogin) {
542
+ (_a2 = scanOrderModule == null ? void 0 : scanOrderModule.setUIState) == null ? void 0 : _a2.call(scanOrderModule, "pendingStep", "check");
453
543
  openLoginModal({
454
544
  callback: (status) => {
455
- if (status === "success") {
456
- goToStep("check");
457
- }
545
+ var _a3;
546
+ (_a3 = scanOrderModule == null ? void 0 : scanOrderModule.deleteUIState) == null ? void 0 : _a3.call(scanOrderModule, "pendingStep");
547
+ if (status === "success") goToStep("check");
458
548
  }
459
549
  });
460
- } else {
461
- goToStep("check");
550
+ return;
462
551
  }
552
+ goToStep("check");
463
553
  };
464
554
  const isMobileView = (0, import_utils.isMobile)();
465
555
  const isShowFooter = (0, import_react.useMemo)(() => {
@@ -1,6 +1,17 @@
1
1
  /// <reference types="react" />
2
2
  interface MenuProps {
3
3
  onCheckout: () => void;
4
+ /**
5
+ * 商品列表(由上层 ReadyState 持有,配合 onEnsureProductList 做幂等拉取与持久化:
6
+ * 切 step 回到 product 时 Menu 会 remount,但 productList 在 ReadyState 不会丢)
7
+ */
8
+ productList: any[];
9
+ /**
10
+ * 幂等触发商品列表拉取。Menu mount 时调用:
11
+ * - 首次:真发请求
12
+ * - 后续(如从 check 返回 product):命中缓存,直接短路,不重复发请求
13
+ */
14
+ onEnsureProductList: () => Promise<void>;
4
15
  }
5
16
  export default function Menu(props: MenuProps): JSX.Element;
6
17
  export {};