@pisell/private-materials 6.11.645 → 6.11.646

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 (44) 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/preview.js +1 -1
  6. package/build/lowcode/render/default/view.js +18 -18
  7. package/build/lowcode/view.js +18 -18
  8. package/es/components/bigSale/index.js +1 -0
  9. package/es/components/bigSale/templates/Kiosk/index.js +104 -47
  10. package/es/components/kioskSale/index.js +1 -1
  11. package/es/plus/salesSdk/bookingEditService/BookingEditHolderField.js +6 -6
  12. package/es/plus/salesSdk/components/SalesSdkConfirmHolderModal.js +2 -4
  13. package/es/plus/salesSdk/context/SalesSdkCartContext.js +28 -21
  14. package/es/plus/salesSdk/context/SalesSdkHolderContext.js +104 -22
  15. package/es/plus/salesSdk/context/SalesSdkProvider.js +3 -12
  16. package/es/plus/salesSdk/hosts/ConfirmHolderHostRenderer.js +14 -5
  17. package/es/plus/salesSdk/normalProductDetail/NormalProductDetailHostRenderer.js +5 -2
  18. package/es/plus/salesSdk/types.d.ts +16 -1
  19. package/es/plus/salesSdk/utils/customerAuthGate.js +1 -4
  20. package/es/plus/salesSdk/utils/enrichCacheItemBeforeAdd.js +1 -1
  21. package/es/plus/salesSdk/utils/ensureCustomerAuthBeforeAdd.js +6 -6
  22. package/es/plus/salesSdk/utils/holderSubmitValidation.js +3 -4
  23. package/es/plus/salesSdk/utils/productHolderConfig.js +3 -17
  24. package/es/plus/salesSdk/utils/runAddProductFlow.js +14 -5
  25. package/es/pro/skuDetailModal/flow/modules/holder/index.js +4 -1
  26. package/lib/components/bigSale/index.js +1 -0
  27. package/lib/components/bigSale/templates/Kiosk/index.js +104 -47
  28. package/lib/components/kioskSale/index.js +1 -1
  29. package/lib/plus/salesSdk/bookingEditService/BookingEditHolderField.js +5 -5
  30. package/lib/plus/salesSdk/components/SalesSdkConfirmHolderModal.js +2 -4
  31. package/lib/plus/salesSdk/context/SalesSdkCartContext.js +28 -21
  32. package/lib/plus/salesSdk/context/SalesSdkHolderContext.js +104 -22
  33. package/lib/plus/salesSdk/context/SalesSdkProvider.js +3 -12
  34. package/lib/plus/salesSdk/hosts/ConfirmHolderHostRenderer.js +14 -5
  35. package/lib/plus/salesSdk/normalProductDetail/NormalProductDetailHostRenderer.js +5 -2
  36. package/lib/plus/salesSdk/types.d.ts +16 -1
  37. package/lib/plus/salesSdk/utils/customerAuthGate.js +1 -4
  38. package/lib/plus/salesSdk/utils/enrichCacheItemBeforeAdd.js +1 -1
  39. package/lib/plus/salesSdk/utils/ensureCustomerAuthBeforeAdd.js +6 -6
  40. package/lib/plus/salesSdk/utils/holderSubmitValidation.js +3 -4
  41. package/lib/plus/salesSdk/utils/productHolderConfig.js +3 -17
  42. package/lib/plus/salesSdk/utils/runAddProductFlow.js +14 -5
  43. package/lib/pro/skuDetailModal/flow/modules/holder/index.js +4 -1
  44. package/package.json +4 -4
@@ -13,6 +13,11 @@ let react = require("react");
13
13
  react = require_runtime.__toESM(react);
14
14
  let ahooks = require("ahooks");
15
15
  //#region src/plus/salesSdk/context/SalesSdkHolderContext.tsx
16
+ const HOLDER_ACCESS_ALLOWED = {
17
+ allowed: true,
18
+ loginOpened: false,
19
+ loginClosed: false
20
+ };
16
21
  const SalesSdkHolderContext = (0, react.createContext)(null);
17
22
  SalesSdkHolderContext.displayName = "SalesSdkHolderContext";
18
23
  const EMPTY_HOLDER_OPTIONS = [];
@@ -110,31 +115,49 @@ const SalesSdkHolderProvider = ({ children }) => {
110
115
  }
111
116
  return true;
112
117
  }));
113
- const ensureHolderRequestAccess = (0, ahooks.useMemoizedFn)(() => {
118
+ const ensureHolderRequestAccess = (0, ahooks.useMemoizedFn)((options) => {
114
119
  const normalizedPlatform = String(platform || "").trim().toLowerCase();
115
- if (normalizedPlatform !== "pc" && normalizedPlatform !== "h5") return Promise.resolve(true);
120
+ if (normalizedPlatform !== "pc" && normalizedPlatform !== "h5") return Promise.resolve(HOLDER_ACCESS_ALLOWED);
116
121
  const currentCustomerId = resolveHolderCustomerId(bookingTicket);
117
122
  const loggedIn = isLoggedIn();
118
- if (loggedIn && !isUnboundHolderCustomerId(currentCustomerId)) return Promise.resolve(true);
123
+ if (!isUnboundHolderCustomerId(currentCustomerId) && (loggedIn || (options === null || options === void 0 ? void 0 : options.allowBoundCustomerAccess) === true)) return Promise.resolve(HOLDER_ACCESS_ALLOWED);
119
124
  if (holderAccessPromiseRef.current) return holderAccessPromiseRef.current;
120
- const accessPromise = loggedIn ? syncAuthenticatedHolderCustomer() : new Promise((resolve) => {
125
+ const accessPromise = loggedIn ? syncAuthenticatedHolderCustomer().then((allowed) => ({
126
+ allowed,
127
+ loginOpened: false,
128
+ loginClosed: false
129
+ })) : new Promise((resolve) => {
121
130
  let settled = false;
122
- const finish = (allowed) => {
131
+ const finish = (result) => {
123
132
  if (settled) return;
124
133
  settled = true;
125
- resolve(allowed);
134
+ resolve(result);
126
135
  };
127
136
  if (!openLoginModal({ callback: (status) => {
128
137
  if (settled) return;
129
138
  if (status !== "success") {
130
- finish(false);
139
+ finish({
140
+ allowed: false,
141
+ loginOpened: true,
142
+ loginClosed: true
143
+ });
131
144
  return;
132
145
  }
133
146
  settled = true;
134
- syncAuthenticatedHolderCustomer().then(resolve);
147
+ syncAuthenticatedHolderCustomer().then((allowed) => {
148
+ resolve({
149
+ allowed,
150
+ loginOpened: true,
151
+ loginClosed: false
152
+ });
153
+ });
135
154
  } })) {
136
155
  console.warn("[SalesSdk] holder request blocked: login modal is unavailable");
137
- finish(false);
156
+ finish({
157
+ allowed: false,
158
+ loginOpened: false,
159
+ loginClosed: false
160
+ });
138
161
  }
139
162
  });
140
163
  holderAccessPromiseRef.current = accessPromise;
@@ -186,14 +209,30 @@ const SalesSdkHolderProvider = ({ children }) => {
186
209
  }, {});
187
210
  });
188
211
  });
189
- const ensureHolderOptionsForSource = (0, ahooks.useMemoizedFn)(function() {
190
- var _ref = require_asyncToGenerator._asyncToGenerator(function* (source) {
212
+ const prepareHolderOptionsForSource = (0, ahooks.useMemoizedFn)(function() {
213
+ var _ref = require_asyncToGenerator._asyncToGenerator(function* (source, options) {
191
214
  const holderConfig = require_productHolderConfig.resolveEffectiveHolderConfig(source, bookingConfig);
192
- if (!holderConfig.enabled || holderConfig.formId === void 0) return EMPTY_HOLDER_OPTIONS;
193
- if (!(yield ensureHolderRequestAccess())) return EMPTY_HOLDER_OPTIONS;
215
+ if (!holderConfig.enabled || holderConfig.formId === void 0) return {
216
+ options: EMPTY_HOLDER_OPTIONS,
217
+ accessAllowed: true,
218
+ loginOpened: false,
219
+ loginClosed: false
220
+ };
221
+ const access = yield ensureHolderRequestAccess(options);
222
+ if (!access.allowed) return {
223
+ options: EMPTY_HOLDER_OPTIONS,
224
+ accessAllowed: false,
225
+ loginOpened: access.loginOpened,
226
+ loginClosed: access.loginClosed
227
+ };
194
228
  const params = resolveRequestParams(source);
195
229
  const requestKey = require_enrichCartLineHolderDisplay.buildHolderListRequestKey(params);
196
- if (!params || !requestKey) return EMPTY_HOLDER_OPTIONS;
230
+ if (!params || !requestKey) return {
231
+ options: EMPTY_HOLDER_OPTIONS,
232
+ accessAllowed: true,
233
+ loginOpened: access.loginOpened,
234
+ loginClosed: access.loginClosed
235
+ };
197
236
  const cached = mergeHolderOptionsStable(optimisticHolderOptionsByKey[requestKey] || EMPTY_HOLDER_OPTIONS, serverHolderOptionsByKey[requestKey] || EMPTY_HOLDER_OPTIONS);
198
237
  if (cached.length) {
199
238
  setHolderOptionsRequestKey(requestKey);
@@ -210,9 +249,19 @@ const SalesSdkHolderProvider = ({ children }) => {
210
249
  setLoading(loadingKeysRef.current.size > 0);
211
250
  });
212
251
  }
213
- return cached;
252
+ return {
253
+ options: cached,
254
+ accessAllowed: true,
255
+ loginOpened: access.loginOpened,
256
+ loginClosed: access.loginClosed
257
+ };
214
258
  }
215
- if (loadingKeysRef.current.has(requestKey)) return cached;
259
+ if (loadingKeysRef.current.has(requestKey)) return {
260
+ options: cached,
261
+ accessAllowed: true,
262
+ loginOpened: access.loginOpened,
263
+ loginClosed: access.loginClosed
264
+ };
216
265
  loadingKeysRef.current.add(requestKey);
217
266
  setLoading(true);
218
267
  try {
@@ -220,20 +269,38 @@ const SalesSdkHolderProvider = ({ children }) => {
220
269
  const fromServer = require_formatHolderOptions.formatHolderOptions(Array.isArray(data === null || data === void 0 ? void 0 : data.list) ? data.list : []);
221
270
  setServerHolderOptionsByKey((prev) => require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, prev), {}, { [requestKey]: fromServer }));
222
271
  setHolderOptionsRequestKey(requestKey);
223
- return mergeHolderOptionsStable(optimisticHolderOptionsByKey[requestKey] || EMPTY_HOLDER_OPTIONS, fromServer);
272
+ return {
273
+ options: mergeHolderOptionsStable(optimisticHolderOptionsByKey[requestKey] || EMPTY_HOLDER_OPTIONS, fromServer),
274
+ accessAllowed: true,
275
+ loginOpened: access.loginOpened,
276
+ loginClosed: access.loginClosed
277
+ };
224
278
  } catch (err) {
225
279
  console.warn("[SalesSdk] load holderOptions failed", err);
226
280
  setHolderOptionsRequestKey(null);
227
- return EMPTY_HOLDER_OPTIONS;
281
+ return {
282
+ options: EMPTY_HOLDER_OPTIONS,
283
+ accessAllowed: true,
284
+ loginOpened: access.loginOpened,
285
+ loginClosed: access.loginClosed
286
+ };
228
287
  } finally {
229
288
  loadingKeysRef.current.delete(requestKey);
230
289
  setLoading(loadingKeysRef.current.size > 0);
231
290
  }
232
291
  });
233
- return function(_x) {
292
+ return function(_x, _x2) {
234
293
  return _ref.apply(this, arguments);
235
294
  };
236
295
  }());
296
+ const ensureHolderOptionsForSource = (0, ahooks.useMemoizedFn)(function() {
297
+ var _ref2 = require_asyncToGenerator._asyncToGenerator(function* (source) {
298
+ return (yield prepareHolderOptionsForSource(source)).options;
299
+ });
300
+ return function(_x3) {
301
+ return _ref2.apply(this, arguments);
302
+ };
303
+ }());
237
304
  (0, react.useEffect)(() => {
238
305
  return require_holderOptionsSyncBridge.registerHolderOptionsSyncBridge({
239
306
  upsertHolderOptions,
@@ -251,7 +318,7 @@ const SalesSdkHolderProvider = ({ children }) => {
251
318
  let cancelled = false;
252
319
  collectHolderSources(bookingTicket, bookingConfig).forEach((source) => {
253
320
  require_asyncToGenerator._asyncToGenerator(function* () {
254
- if (!(yield ensureHolderRequestAccess()) || cancelled) return;
321
+ if (!(yield ensureHolderRequestAccess()).allowed || cancelled) return;
255
322
  const params = resolveRequestParams(source);
256
323
  const requestKey = require_enrichCartLineHolderDisplay.buildHolderListRequestKey(params);
257
324
  if (!params || !requestKey) return;
@@ -307,6 +374,7 @@ const SalesSdkHolderProvider = ({ children }) => {
307
374
  getHolderOptionsForSource,
308
375
  getHolderOptionsRequestKeyForSource,
309
376
  ensureHolderOptionsForSource,
377
+ prepareHolderOptionsForSource,
310
378
  reload,
311
379
  upsertHolderOptions
312
380
  }), [
@@ -317,6 +385,7 @@ const SalesSdkHolderProvider = ({ children }) => {
317
385
  getHolderOptionsForSource,
318
386
  getHolderOptionsRequestKeyForSource,
319
387
  ensureHolderOptionsForSource,
388
+ prepareHolderOptionsForSource,
320
389
  reload,
321
390
  upsertHolderOptions
322
391
  ]);
@@ -335,11 +404,24 @@ function useSalesSdkHolderOptional() {
335
404
  getHolderOptionsForSource: () => EMPTY_HOLDER_OPTIONS,
336
405
  getHolderOptionsRequestKeyForSource: () => null,
337
406
  ensureHolderOptionsForSource: function() {
338
- var _ref2 = require_asyncToGenerator._asyncToGenerator(function* () {
407
+ var _ref3 = require_asyncToGenerator._asyncToGenerator(function* () {
339
408
  return EMPTY_HOLDER_OPTIONS;
340
409
  });
341
410
  return function ensureHolderOptionsForSource() {
342
- return _ref2.apply(this, arguments);
411
+ return _ref3.apply(this, arguments);
412
+ };
413
+ }(),
414
+ prepareHolderOptionsForSource: function() {
415
+ var _ref4 = require_asyncToGenerator._asyncToGenerator(function* () {
416
+ return {
417
+ options: EMPTY_HOLDER_OPTIONS,
418
+ accessAllowed: true,
419
+ loginOpened: false,
420
+ loginClosed: false
421
+ };
422
+ });
423
+ return function prepareHolderOptionsForSource() {
424
+ return _ref4.apply(this, arguments);
343
425
  };
344
426
  }(),
345
427
  reload: () => void 0,
@@ -222,7 +222,7 @@ function SalesSdkBootstrap({ autoRestoreOnInit, autoBootstrap, autoInitBookingCo
222
222
  ]);
223
223
  return null;
224
224
  }
225
- const SalesSdkProvider = ({ osKey, solution = "bookingTicket", moduleAccess = "ensure", lifecycleOwner = "provider", businessCode, bookingConfigParams, autoInitBookingContext = true, otherParams, shouldMergeProductLines, rulesHooks, orderId, preloadedSalesDetail, autoBootstrap = true, autoRestoreOnInit = true, restoreOrderAfterPaidCheckout = true, destroyOnUnmount = true, uiHosts, normalProductDetailConfig, mergeBookingLinesForDisplay = true, legacyOpenProductDetail, enableTempOrderSync = false, enableTempOrderPersist = false, syncDetailOnOrderChange = false, isActive = true, preserveProductCatalogOnInactiveCustomerClear = false, enableGlobalScanListener = false, promotionScanSuccessMessageKey, promotionItemIncreaseMessageKey, defaultProductLoadParams, children }) => {
225
+ const SalesSdkProvider = ({ osKey, solution = "bookingTicket", moduleAccess = "ensure", lifecycleOwner = "provider", businessCode, bookingConfigParams, autoInitBookingContext = true, otherParams, deferHolderAuthOnClose = false, shouldMergeProductLines, rulesHooks, orderId, preloadedSalesDetail, autoBootstrap = true, autoRestoreOnInit = true, restoreOrderAfterPaidCheckout = true, destroyOnUnmount = true, uiHosts, normalProductDetailConfig, mergeBookingLinesForDisplay = true, legacyOpenProductDetail, enableTempOrderSync = false, enableTempOrderPersist = false, syncDetailOnOrderChange = false, isActive = true, preserveProductCatalogOnInactiveCustomerClear = false, enableGlobalScanListener = false, promotionScanSuccessMessageKey, promotionItemIncreaseMessageKey, defaultProductLoadParams, children }) => {
226
226
  var _context$appHelper, _osKey$replace;
227
227
  const context = require_useEngineContext.default();
228
228
  const utils = (context === null || context === void 0 || (_context$appHelper = context.appHelper) === null || _context$appHelper === void 0 ? void 0 : _context$appHelper.utils) || {};
@@ -234,17 +234,7 @@ const SalesSdkProvider = ({ osKey, solution = "bookingTicket", moduleAccess = "e
234
234
  engineChannel: channel,
235
235
  platform: otherParams === null || otherParams === void 0 ? void 0 : otherParams.platform
236
236
  });
237
- const shouldEnableCustomerAuthModule = (0, react.useMemo)(() => [
238
- otherParams === null || otherParams === void 0 ? void 0 : otherParams.platform,
239
- otherParams === null || otherParams === void 0 ? void 0 : otherParams.channel,
240
- channel,
241
- productLoadChannel
242
- ].some((value) => String(value || "").trim().toLowerCase() === "kiosk"), [
243
- channel,
244
- otherParams === null || otherParams === void 0 ? void 0 : otherParams.channel,
245
- otherParams === null || otherParams === void 0 ? void 0 : otherParams.platform,
246
- productLoadChannel
247
- ]);
237
+ const shouldEnableCustomerAuthModule = deferHolderAuthOnClose;
248
238
  const [promotionScanItemIncreaseRevision, setPromotionScanItemIncreaseRevision] = (0, react.useState)(0);
249
239
  /** 加车 enrich 早于 BookingEdit 抽屉,须提前注入 HTTP 客户端供跨日报价等 serve 使用 */
250
240
  (0, react.useEffect)(() => {
@@ -1338,6 +1328,7 @@ const SalesSdkProvider = ({ osKey, solution = "bookingTicket", moduleAccess = "e
1338
1328
  isActive,
1339
1329
  preserveCatalogOnInactiveCustomerClear: preserveProductCatalogOnInactiveCustomerClear
1340
1330
  }, /* @__PURE__ */ react.default.createElement(require_SalesSdkSummaryContext.SalesSdkSummaryProvider, { ref: summaryProviderRef }, /* @__PURE__ */ react.default.createElement(require_SalesSdkCartContext.SalesSdkCartProvider, {
1331
+ deferHolderAuthOnClose,
1341
1332
  shouldMergeProductLines,
1342
1333
  mergeBookingLinesForDisplay
1343
1334
  }, /* @__PURE__ */ react.default.createElement(require_SalesSdkGlobalScanSubscriber.default, {
@@ -1,6 +1,7 @@
1
1
  const require_runtime = require("../../../_virtual/_rolldown/runtime.js");
2
2
  const require_asyncToGenerator = require("../../../_virtual/_@oxc-project_runtime@0.122.0/helpers/asyncToGenerator.js");
3
3
  const require_SalesSdkHostBridgesContext = require("../context/SalesSdkHostBridgesContext.js");
4
+ const require_productHolderConfig = require("../utils/productHolderConfig.js");
4
5
  const require_SalesSdkHolderContext = require("../context/SalesSdkHolderContext.js");
5
6
  const require_SalesSdkUIHostsContext = require("../context/SalesSdkUIHostsContext.js");
6
7
  const require_assignHolderToCartLine = require("../utils/assignHolderToCartLine.js");
@@ -30,14 +31,16 @@ const ConfirmHolderHostRenderer = () => {
30
31
  const ctx = pending === null || pending === void 0 ? void 0 : pending.ctx;
31
32
  const open = Boolean((pending === null || pending === void 0 ? void 0 : pending.open) && ctx);
32
33
  const snapshotLineKeys = (_ctx$snapshotLineKeys = ctx === null || ctx === void 0 ? void 0 : ctx.snapshotLineKeys) !== null && _ctx$snapshotLineKeys !== void 0 ? _ctx$snapshotLineKeys : [];
33
- const liveUnassignedCount = (0, react.useMemo)(() => {
34
- if (!open || !bookingTicket) return 0;
35
- return require_holderSubmitValidation.calculateUnassignedHolderCount(require_holderSubmitValidation.collectUnassignedHolderLines(bookingTicket));
34
+ const liveUnassignedLines = (0, react.useMemo)(() => {
35
+ if (!open || !bookingTicket) return [];
36
+ return require_holderSubmitValidation.collectUnassignedHolderLines(bookingTicket);
36
37
  }, [
37
38
  bookingTicket,
38
39
  open,
39
40
  refreshKey
40
41
  ]);
42
+ const liveUnassignedCount = (0, react.useMemo)(() => require_holderSubmitValidation.calculateUnassignedHolderCount(liveUnassignedLines), [liveUnassignedLines]);
43
+ const canSkip = liveUnassignedLines.length > 0 && !liveUnassignedLines.some((line) => require_productHolderConfig.isProductHolderRequired(line.cacheItem));
41
44
  const lines = (0, react.useMemo)(() => {
42
45
  if (!open || !bookingTicket || !snapshotLineKeys.length) return [];
43
46
  return require_holderSubmitValidation.buildHolderConfirmDisplayLines({
@@ -87,8 +90,14 @@ const ConfirmHolderHostRenderer = () => {
87
90
  holderConfirm.complete();
88
91
  }, [holderConfirm, liveUnassignedCount]);
89
92
  const handleSkip = (0, react.useCallback)(() => {
93
+ if (!canSkip) {
94
+ (0, _pisell_materials.PisellToast)({ content: _pisell_utils.locales.getText("pisell2.text.press-card-assign-holder") });
95
+ setRefreshKey((key) => key + 1);
96
+ holderConfirm.refresh();
97
+ return;
98
+ }
90
99
  holderConfirm.complete();
91
- }, [holderConfirm]);
100
+ }, [canSkip, holderConfirm]);
92
101
  const handleDismissConfirmed = (0, react.useCallback)(() => {
93
102
  holderConfirm.cancel();
94
103
  }, [holderConfirm]);
@@ -97,7 +106,7 @@ const ConfirmHolderHostRenderer = () => {
97
106
  open,
98
107
  lines,
99
108
  liveUnassignedCount,
100
- bookingConfig: ctx.bookingConfig,
109
+ canSkip,
101
110
  onAssign: handleAssign,
102
111
  onConfirm: handleConfirm,
103
112
  onSkip: handleSkip,
@@ -220,6 +220,7 @@ const NormalProductDetailHostRenderer = ({ defaultSkuDetailConfig }) => {
220
220
  var _ref17 = require_asyncToGenerator._asyncToGenerator(function* () {
221
221
  var _bookingTicket$getBoo3, _bookingTicket$getBoo4;
222
222
  const payload = capturedPending.payload;
223
+ const deferHolderUntilSubmit = payload.mode === "create" ? payload.requiresDetailPayload.deferHolderUntilSubmit === true : payload.mode === "booking-create" ? payload.requiresBookingEditPayload.deferHolderUntilSubmit === true : false;
223
224
  let openArgs;
224
225
  let bookingConfig = (_bookingTicket$getBoo3 = bookingTicket === null || bookingTicket === void 0 || (_bookingTicket$getBoo4 = bookingTicket.getBookingConfig) === null || _bookingTicket$getBoo4 === void 0 ? void 0 : _bookingTicket$getBoo4.call(bookingTicket)) !== null && _bookingTicket$getBoo3 !== void 0 ? _bookingTicket$getBoo3 : null;
225
226
  let bookingState = null;
@@ -336,7 +337,8 @@ const NormalProductDetailHostRenderer = ({ defaultSkuDetailConfig }) => {
336
337
  const refreshHolderContextFromHydratedProduct = function() {
337
338
  var _ref6 = require_asyncToGenerator._asyncToGenerator(function* ({ productData }) {
338
339
  holderSource = productData;
339
- try {
340
+ if (deferHolderUntilSubmit) holderOptions = getHolderOptionsForSource(productData);
341
+ else try {
340
342
  holderOptions = yield ensureHolderOptionsForSource(productData);
341
343
  } catch (error) {
342
344
  console.warn("[SalesSdk] 水合后 Holder 字典加载失败,沿用当前分源缓存", error);
@@ -350,7 +352,7 @@ const NormalProductDetailHostRenderer = ({ defaultSkuDetailConfig }) => {
350
352
  } catch (error) {
351
353
  console.warn("[SalesSdk] 水合后预约配置加载失败,沿用当前 isFranchisee", error);
352
354
  }
353
- if (bookingState) bookingState = require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, bookingState), {}, {
355
+ if (bookingState) bookingState = require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, bookingState), deferHolderUntilSubmit ? { deferHolderUntilSubmit: true } : {}), {}, {
354
356
  isFranchisee: hydratedIsFranchisee,
355
357
  otherParams: hydratedOtherParams,
356
358
  pet: require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, bookingState.pet || {}), {}, { holders: holderOptions })
@@ -571,6 +573,7 @@ const NormalProductDetailHostRenderer = ({ defaultSkuDetailConfig }) => {
571
573
  };
572
574
  }
573
575
  if (!isCurrentPending()) return;
576
+ if (bookingState && deferHolderUntilSubmit) bookingState = require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, bookingState), {}, { deferHolderUntilSubmit: true });
574
577
  setPreparedOpen({
575
578
  pending: capturedPending,
576
579
  openArgs,
@@ -1324,6 +1324,8 @@ interface SalesSdkAddProductRequiresDetailPayload {
1324
1324
  initialQuantity?: number;
1325
1325
  /** @internal 本次详情 Flow 的 Holder 初始选择。 */
1326
1326
  initialHolderIds?: Array<number | string>;
1327
+ /** @internal 登录被关闭后,仅把 Holder 必填延后到提交前校验。 */
1328
+ deferHolderUntilSubmit?: boolean;
1327
1329
  }
1328
1330
  /**
1329
1331
  * `requiresBookingEdit` 时 UI 打开资源 / 时间编辑抽屉所需 payload。
@@ -1334,6 +1336,8 @@ interface SalesSdkRequiresBookingEditPayload {
1334
1336
  date: string | null;
1335
1337
  /** @internal 仅供加车前 Selection Flow 初始化 Holder 草稿。 */
1336
1338
  initialHolderIds?: Array<number | string>;
1339
+ /** @internal 登录被关闭后,仅把 Holder 必填延后到提交前校验。 */
1340
+ deferHolderUntilSubmit?: boolean;
1337
1341
  /**
1338
1342
  * 已加车行「编辑资源」:强制打开抽屉,忽略 cacheItem.autoClose。
1339
1343
  * 加车链路(requiresBookingEdit)不传此字段;autoClose=true 时自动 confirm 跳过抽屉。
@@ -1529,7 +1533,8 @@ interface SalesSdkConfirmDetailInput {
1529
1533
  quantity?: number;
1530
1534
  notShowToast?: boolean; /** Holder 弹窗的初始选中项;最终仍以用户确认结果为准 */
1531
1535
  initialHolderIds?: Array<number | string>; /** 跨日弹窗确认后的区间(规格弹窗之后注入) */
1532
- multiDayRange?: SalesSdkMultiDaySelectResult;
1536
+ multiDayRange?: SalesSdkMultiDaySelectResult; /** @internal 当前确认延后 Holder 到提交前补录。 */
1537
+ deferHolderUntilSubmit?: boolean;
1533
1538
  };
1534
1539
  }
1535
1540
  /**
@@ -1639,6 +1644,11 @@ interface SalesSdkAddProductWithFlowOptions {
1639
1644
  * @internal 由 createAddProductWithFlowDebounced 注入,业务调用方勿传。
1640
1645
  */
1641
1646
  preparedCacheItem?: any;
1647
+ /**
1648
+ * 当前商品 Flow 已关闭登录;详情/加购阶段延后 Holder,提交前仍按原配置校验。
1649
+ * @internal 由 Kiosk 模板登录门禁注入,业务调用方勿传。
1650
+ */
1651
+ deferHolderUntilSubmit?: boolean;
1642
1652
  }
1643
1653
  /**
1644
1654
  * 资源不可用原因(与 OS `BookingContext.ResourceUnavailableReason` 一比一对齐)。
@@ -1701,6 +1711,11 @@ interface SalesSdkProviderProps {
1701
1711
  autoInitBookingContext?: boolean;
1702
1712
  /** 透传给 OS 注册时的 otherParams(platform / type / channel / dineInConfig 等) */
1703
1713
  otherParams?: Record<string, any>;
1714
+ /**
1715
+ * Kiosk 模板专用:用户关闭商品 Holder 登录后继续详情/加购,并延后到提交前补录。
1716
+ * @internal 由 BigSale 根据 resolvedTemplate 注入。
1717
+ */
1718
+ deferHolderAuthOnClose?: boolean;
1704
1719
  /**
1705
1720
  * 运行时商品行合并策略;返回 false 时快速加购不做防抖合并,OS 始终新增商品行,
1706
1721
  * 预约商品也保持独立展示。默认合并。
@@ -14,15 +14,12 @@ function isTruthyRequired(value) {
14
14
  function normalizeText(value) {
15
15
  return value == null ? "" : String(value).trim().toLowerCase();
16
16
  }
17
- function isKioskRuntime(params) {
18
- return normalizeText(params.platform) === "kiosk" || normalizeText(params.channel) === "kiosk";
19
- }
20
17
  function isHolderRequiredProduct(product) {
21
18
  const holderConfig = product === null || product === void 0 ? void 0 : product.holder_config;
22
19
  return normalizeText(holderConfig === null || holderConfig === void 0 ? void 0 : holderConfig.status) === "enable" && isTruthyRequired(holderConfig === null || holderConfig === void 0 ? void 0 : holderConfig.required);
23
20
  }
24
21
  function shouldPromptCustomerAuthForProduct(params) {
25
- return isKioskRuntime(params) && isHolderRequiredProduct(params.product) && !isValidOrderCustomerId(params.currentCustomerId);
22
+ return params.enabled === true && isHolderRequiredProduct(params.product) && !isValidOrderCustomerId(params.currentCustomerId);
26
23
  }
27
24
  function normalizeCustomerAuthCustomer(value) {
28
25
  if (!value || typeof value !== "object") return null;
@@ -20,7 +20,7 @@ function _enrichCacheItemBeforeAdd() {
20
20
  const customerId = require_buildBookingEditDrawerState.resolveAddFlowCustomerId(input.tempOrder, input.customerId);
21
21
  const holderSource = (_input$catalogItem2 = input.catalogItem) !== null && _input$catalogItem2 !== void 0 ? _input$catalogItem2 : cacheItem;
22
22
  const effectiveHolderConfig = require_productHolderConfig.resolveEffectiveHolderConfig(holderSource, input.bookingConfig);
23
- if (require_shouldPromptHolderOnAddCart.shouldPromptHolderOnAddCart({
23
+ if (!input.deferHolderUntilSubmit && require_shouldPromptHolderOnAddCart.shouldPromptHolderOnAddCart({
24
24
  cacheItem,
25
25
  bookingConfig: input.bookingConfig,
26
26
  productSource: holderSource,
@@ -6,10 +6,10 @@ function ensureCustomerAuthBeforeAdd(_x) {
6
6
  }
7
7
  function _ensureCustomerAuthBeforeAdd() {
8
8
  _ensureCustomerAuthBeforeAdd = require_asyncToGenerator._asyncToGenerator(function* (params) {
9
- if (!require_customerAuthGate.shouldPromptCustomerAuthForProduct(params)) return true;
9
+ if (!require_customerAuthGate.shouldPromptCustomerAuthForProduct(params)) return { status: "ready" };
10
10
  if (!params.openCustomerAuth) {
11
11
  console.warn("[SalesSdk] Kiosk holder-required product needs customer auth, but openCustomerAuth is unavailable");
12
- return false;
12
+ return { status: "fallback" };
13
13
  }
14
14
  try {
15
15
  const result = yield params.openCustomerAuth({
@@ -17,16 +17,16 @@ function _ensureCustomerAuthBeforeAdd() {
17
17
  product: params.product,
18
18
  currentCustomerId: params.currentCustomerId
19
19
  });
20
- if (!(result === null || result === void 0 ? void 0 : result.customer)) return false;
20
+ if (!(result === null || result === void 0 ? void 0 : result.customer)) return { status: "deferred" };
21
21
  if (typeof params.setOrderCustomer !== "function") {
22
22
  console.warn("[SalesSdk] Customer auth succeeded, but setOrderCustomer is unavailable");
23
- return false;
23
+ return { status: "fallback" };
24
24
  }
25
25
  yield params.setOrderCustomer(result.customer);
26
- return true;
26
+ return { status: "ready" };
27
27
  } catch (error) {
28
28
  console.warn("[SalesSdk] Customer auth before add failed", error);
29
- return false;
29
+ return { status: "fallback" };
30
30
  }
31
31
  });
32
32
  return _ensureCustomerAuthBeforeAdd.apply(this, arguments);
@@ -104,9 +104,8 @@ function collectUnassignedHolderLines(bookingTicket) {
104
104
  const orderLine = (_bookingView$_extend = bookingView._extend) === null || _bookingView$_extend === void 0 ? void 0 : _bookingView$_extend.product;
105
105
  if (!orderLine) return;
106
106
  const sourceProduct = (_catalog$find = catalog.find((p) => String(p.id) === String(orderLine.product_id))) !== null && _catalog$find !== void 0 ? _catalog$find : null;
107
- const holderSource = (_ref = sourceProduct !== null && sourceProduct !== void 0 ? sourceProduct : orderLine) !== null && _ref !== void 0 ? _ref : bookingView;
108
- const effectiveHolderConfig = require_productHolderConfig.resolveEffectiveHolderConfig(holderSource, bookingConfig);
109
- if (!(effectiveHolderConfig.source === "product" ? effectiveHolderConfig.required : effectiveHolderConfig.enabled)) return;
107
+ const effectiveHolderConfig = require_productHolderConfig.resolveEffectiveHolderConfig((_ref = sourceProduct !== null && sourceProduct !== void 0 ? sourceProduct : orderLine) !== null && _ref !== void 0 ? _ref : bookingView, bookingConfig);
108
+ if (!effectiveHolderConfig.enabled) return;
110
109
  const cacheItem = buildCacheItemFromOrderLine({
111
110
  product: orderLine,
112
111
  booking: bookingView,
@@ -115,7 +114,7 @@ function collectUnassignedHolderLines(bookingTicket) {
115
114
  if (require_utils.isNormalProductByDurationSchedule(cacheItem)) return;
116
115
  if (hasHolderAssigned(cacheItem)) return;
117
116
  rawLines.push({
118
- cacheItem: require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, cacheItem), require_productHolderConfig.isProductHolderRequired(cacheItem) ? {} : { holder_config: holderSource === null || holderSource === void 0 ? void 0 : holderSource.holder_config }),
117
+ cacheItem: require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, cacheItem), require_productHolderConfig.isProductHolderRequired(cacheItem) ? {} : { holder_config: effectiveHolderConfig.raw }),
119
118
  booking: bookingView,
120
119
  orderLine
121
120
  });
@@ -30,26 +30,12 @@ function resolveProductHolderConfig(source) {
30
30
  }, formId !== void 0 && formId !== null && formId !== "" ? { formId } : {}), {}, { raw });
31
31
  }
32
32
  /**
33
- * 统一解析 Holder 配置:商品只要明确携带 holder_config(包括 disable),
34
- * 就完全以商品级配置为准;只有商品没有该字段时才回退旧 appointment_subject。
35
- *
36
- * 这样既允许新商品单独关闭店铺级 Holder,也能继续兼容尚未迁移的旧预约商品。
33
+ * 统一解析 Holder 配置:保留旧函数签名以减少调用方改动,
34
+ * 启用与必填判断不再回退 bookingConfig。
37
35
  */
38
- function resolveEffectiveHolderConfig(source, bookingConfig) {
39
- var _bookingConfig$config;
36
+ function resolveEffectiveHolderConfig(source, _bookingConfig) {
40
37
  const productConfig = resolveProductHolderConfig(source);
41
38
  if (productConfig.raw) return require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, productConfig), {}, { source: "product" });
42
- const basicConfig = bookingConfig === null || bookingConfig === void 0 || (_bookingConfig$config = bookingConfig.config) === null || _bookingConfig$config === void 0 ? void 0 : _bookingConfig$config.basic;
43
- const appointmentSubject = basicConfig === null || basicConfig === void 0 ? void 0 : basicConfig.appointment_subject;
44
- const legacyEnabled = (appointmentSubject === null || appointmentSubject === void 0 ? void 0 : appointmentSubject.type) === "form" && (appointmentSubject === null || appointmentSubject === void 0 ? void 0 : appointmentSubject.show_hold_on_add_cart) !== 0;
45
- const legacyFormId = appointmentSubject === null || appointmentSubject === void 0 ? void 0 : appointmentSubject.form_id;
46
- if (appointmentSubject) return require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({
47
- enabled: legacyEnabled,
48
- required: legacyEnabled && (basicConfig === null || basicConfig === void 0 ? void 0 : basicConfig.subject_require) === "require"
49
- }, legacyFormId !== void 0 && legacyFormId !== null && legacyFormId !== "" ? { formId: legacyFormId } : {}), {}, {
50
- raw: null,
51
- source: "legacy"
52
- });
53
39
  return {
54
40
  enabled: false,
55
41
  required: false,
@@ -42,7 +42,8 @@ function _openBookingEditAfterEnrich() {
42
42
  cacheItem,
43
43
  catalogProduct: catalogProduct !== null && catalogProduct !== void 0 ? catalogProduct : payload.catalogProduct,
44
44
  customerId: drawerCustomerId,
45
- initialHolderIds: flowOptions.initialHolderIds
45
+ initialHolderIds: flowOptions.initialHolderIds,
46
+ deferHolderUntilSubmit: flowOptions.deferHolderUntilSubmit
46
47
  }));
47
48
  if (selectionResult.status === "cancelled") return { status: "cancelled" };
48
49
  if (selectionResult.status === "committed") {
@@ -65,6 +66,7 @@ function _openBookingEditAfterEnrich() {
65
66
  customerId: (_flowOptions$customer2 = flowOptions.customerId) !== null && _flowOptions$customer2 !== void 0 ? _flowOptions$customer2 : payload.customerId,
66
67
  initialHolderIds: flowOptions.initialHolderIds,
67
68
  holderOptions: flowOptions.holderOptions,
69
+ deferHolderUntilSubmit: flowOptions.deferHolderUntilSubmit,
68
70
  date: payload.date,
69
71
  locale: flowOptions.locale,
70
72
  mode: "drawer"
@@ -104,6 +106,7 @@ function _openBookingEditAfterEnrich() {
104
106
  customerId: (_flowOptions$customer3 = flowOptions.customerId) !== null && _flowOptions$customer3 !== void 0 ? _flowOptions$customer3 : payload.customerId,
105
107
  initialHolderIds: flowOptions.initialHolderIds,
106
108
  holderOptions: flowOptions.holderOptions,
109
+ deferHolderUntilSubmit: flowOptions.deferHolderUntilSubmit,
107
110
  date: payload.date,
108
111
  locale: flowOptions.locale,
109
112
  mode: "drawer"
@@ -112,12 +115,16 @@ function _openBookingEditAfterEnrich() {
112
115
  const openEdit = hosts === null || hosts === void 0 ? void 0 : hosts.openBookingEdit;
113
116
  if (!openEdit) return {
114
117
  status: "requiresBookingEdit",
115
- payload: require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, payload), {}, { cacheItem: enriched.cacheItem })
118
+ payload: require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, payload), {}, {
119
+ cacheItem: enriched.cacheItem,
120
+ deferHolderUntilSubmit: flowOptions.deferHolderUntilSubmit
121
+ })
116
122
  };
117
123
  const edited = yield openEdit(require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, payload), {}, {
118
124
  cacheItem: enriched.cacheItem,
119
125
  catalogProduct: catalogProduct !== null && catalogProduct !== void 0 ? catalogProduct : payload.catalogProduct,
120
- customerId: drawerCustomerId
126
+ customerId: drawerCustomerId,
127
+ deferHolderUntilSubmit: flowOptions.deferHolderUntilSubmit
121
128
  }));
122
129
  if (!edited) return { status: "cancelled" };
123
130
  const { products } = yield cart.confirmBookingEdit({
@@ -151,7 +158,8 @@ function _runAddProductFlow() {
151
158
  if (!openDetail) return result;
152
159
  const detailResult = yield openDetail(require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, result.payload), {}, {
153
160
  initialQuantity: (_flowOptions$quantity = flowOptions.quantity) !== null && _flowOptions$quantity !== void 0 ? _flowOptions$quantity : result.payload.initialQuantity,
154
- initialHolderIds: (_flowOptions$initialH = flowOptions.initialHolderIds) !== null && _flowOptions$initialH !== void 0 ? _flowOptions$initialH : result.payload.initialHolderIds
161
+ initialHolderIds: (_flowOptions$initialH = flowOptions.initialHolderIds) !== null && _flowOptions$initialH !== void 0 ? _flowOptions$initialH : result.payload.initialHolderIds,
162
+ deferHolderUntilSubmit: flowOptions.deferHolderUntilSubmit
155
163
  }));
156
164
  if (!detailResult) return { status: "cancelled" };
157
165
  if (detailResult._committedProducts) {
@@ -191,7 +199,8 @@ function _runAddProductFlow() {
191
199
  options: flowOptions
192
200
  }),
193
201
  initialHolderIds: flowOptions.initialHolderIds,
194
- multiDayRange: multiDayRange || void 0
202
+ multiDayRange: multiDayRange || void 0,
203
+ deferHolderUntilSubmit: flowOptions.deferHolderUntilSubmit
195
204
  }
196
205
  };
197
206
  result = yield cart.confirmDetail(confirmInput);
@@ -64,7 +64,8 @@ const HolderFlowModuleComponent = ({ context, module, registerHandle }) => {
64
64
  const holderIds = context.draft.booking.holderIds;
65
65
  const quantity = context.draft.quantity || 1;
66
66
  const bookingState = context.hostContext;
67
- const required = resolveFlowHolderConfig(productData, bookingState).required;
67
+ const deferHolderUntilSubmit = (bookingState === null || bookingState === void 0 ? void 0 : bookingState.deferHolderUntilSubmit) === true;
68
+ const required = resolveFlowHolderConfig(productData, bookingState).required && !deferHolderUntilSubmit;
68
69
  const unsupportedReason = require_utils.isMultiDayProduct(productData) ? void 0 : require_index.getUnsupportedBookingFlowReason(productData);
69
70
  const customerId = getCustomerId(bookingState);
70
71
  const [hostError, setHostError] = (0, react.useState)(null);
@@ -170,9 +171,11 @@ const holderFlowModule = {
170
171
  "booking.customerId"
171
172
  ],
172
173
  isApplicable: (context) => {
174
+ var _context$hostContext;
173
175
  const productData = context.draft.productData;
174
176
  if (require_utils$1.isNormalProductByDurationSchedule(productData)) return false;
175
177
  if (!resolveFlowHolderConfig(productData, context.hostContext).enabled) return false;
178
+ if (((_context$hostContext = context.hostContext) === null || _context$hostContext === void 0 ? void 0 : _context$hostContext.deferHolderUntilSubmit) === true) return false;
176
179
  if (!context.hostContext) return true;
177
180
  return !require_utils$2.isWalkIn(getCustomerId(context.hostContext));
178
181
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pisell/private-materials",
3
- "version": "6.11.645",
3
+ "version": "6.11.646",
4
4
  "main": "./lib/index.js",
5
5
  "module": "./es/index.js",
6
6
  "types": "./lib/index.d.ts",
@@ -69,11 +69,11 @@
69
69
  "react-zoom-pan-pinch": "^3.7.0",
70
70
  "styled-components": "^6.0.0-rc.3",
71
71
  "use-sync-external-store": "^1.6.0",
72
- "@pisell/materials": "6.11.254",
72
+ "@pisell/pi-payment-sdk": "0.0.3",
73
73
  "@pisell/utils": "3.0.4",
74
- "@pisell/date-picker": "3.0.10",
75
74
  "@pisell/icon": "0.0.11",
76
- "@pisell/pi-payment-sdk": "0.0.3"
75
+ "@pisell/materials": "6.11.254",
76
+ "@pisell/date-picker": "3.0.10"
77
77
  },
78
78
  "peerDependencies": {
79
79
  "react": "^18.0.0",