@pisell/pisellos 0.10.3 → 0.10.4

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.
@@ -11,6 +11,13 @@ export declare enum UnifiedBookingSalesHooks {
11
11
  export interface UnifiedBookingSalesState extends BookingTicketState {
12
12
  resourcePlanner: ResourcePlannerModule;
13
13
  }
14
+ export interface UnifiedBookingSalesOtherParams extends Record<string, any> {
15
+ /**
16
+ * Persist the active order workspace in sessionStorage, partitioned by cacheId.
17
+ * Disabled by default and ignored when cacheId is missing.
18
+ */
19
+ enableSessionStoragePersist?: boolean;
20
+ }
14
21
  /** Explicit OpenData target used by page-level UnifiedBookingSales skins. */
15
22
  export interface UnifiedBookingSalesLoadOpenDataParams {
16
23
  businessCode: string;
@@ -0,0 +1,51 @@
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
20
+ // If the importer is in node compatibility mode or this is not an ESM
21
+ // file that has been converted to a CommonJS file using a Babel-
22
+ // compatible transform (i.e. "__esModule" has not been set), then set
23
+ // "default" to the CommonJS "module.exports" for node compatibility.
24
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
25
+ mod
26
+ ));
27
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
28
+
29
+ // src/model/strategy/adapter/promotion/index.ts
30
+ var promotion_exports = {};
31
+ __export(promotion_exports, {
32
+ BUY_X_GET_Y_FREE_STRATEGY: () => import_examples.BUY_X_GET_Y_FREE_STRATEGY,
33
+ ITEM_REWARD_STRATEGY: () => import_examples.ITEM_REWARD_STRATEGY,
34
+ PromotionAdapter: () => import_adapter.PromotionAdapter,
35
+ PromotionEvaluator: () => import_evaluator.PromotionEvaluator,
36
+ X_ITEMS_FOR_Y_PRICE_STRATEGY: () => import_examples.X_ITEMS_FOR_Y_PRICE_STRATEGY,
37
+ default: () => import_adapter2.default
38
+ });
39
+ module.exports = __toCommonJS(promotion_exports);
40
+ var import_evaluator = require("./evaluator");
41
+ var import_adapter = require("./adapter");
42
+ var import_adapter2 = __toESM(require("./adapter"));
43
+ var import_examples = require("./examples");
44
+ // Annotate the CommonJS export names for ESM import in node:
45
+ 0 && (module.exports = {
46
+ BUY_X_GET_Y_FREE_STRATEGY,
47
+ ITEM_REWARD_STRATEGY,
48
+ PromotionAdapter,
49
+ PromotionEvaluator,
50
+ X_ITEMS_FOR_Y_PRICE_STRATEGY
51
+ });
@@ -8,6 +8,7 @@ export declare class BaseModule {
8
8
  protected core: PisellCore;
9
9
  constructor(name?: string, version?: string);
10
10
  destroy(): void;
11
+ private isRecord;
11
12
  checkSaveCache({ cacheId, fatherModule, store, cacheKey, }: {
12
13
  cacheId: string | undefined;
13
14
  fatherModule: string | undefined;
@@ -34,6 +34,9 @@ var BaseModule = class {
34
34
  this.core.effects.offByModuleDestroy(this.name);
35
35
  this.core.unregisterModule(this);
36
36
  }
37
+ isRecord(value) {
38
+ return !!value && typeof value === "object" && !Array.isArray(value);
39
+ }
37
40
  // 提供统一的缓存 module 里的数据的方法
38
41
  checkSaveCache({
39
42
  cacheId,
@@ -41,45 +44,29 @@ var BaseModule = class {
41
44
  store,
42
45
  cacheKey
43
46
  }) {
44
- const window = this.core.getPlugin("window");
45
- if (cacheId) {
47
+ if (!cacheId)
48
+ return;
49
+ try {
50
+ const window = this.core.getPlugin("window");
51
+ const sessionStorage = window == null ? void 0 : window.sessionStorage;
52
+ if (!sessionStorage)
53
+ return;
54
+ const storageKey = fatherModule || cacheId;
55
+ const rawCacheData = sessionStorage.getItem(storageKey);
56
+ const parsedCacheData = rawCacheData ? JSON.parse(rawCacheData) : {};
57
+ if (!this.isRecord(parsedCacheData))
58
+ return;
59
+ const cacheBucket = fatherModule ? this.isRecord(parsedCacheData[cacheId]) ? parsedCacheData[cacheId] : {} : parsedCacheData;
60
+ const moduleBucket = this.isRecord(cacheBucket[this.name]) ? cacheBucket[this.name] : {};
61
+ cacheKey.forEach((key) => {
62
+ moduleBucket[key] = store == null ? void 0 : store[key];
63
+ });
64
+ cacheBucket[this.name] = moduleBucket;
46
65
  if (fatherModule) {
47
- const currentCacheData = window.sessionStorage.getItem(fatherModule);
48
- let currentCacheDataObj = JSON.parse(currentCacheData || "{}");
49
- if (!currentCacheData || !currentCacheDataObj[cacheId]) {
50
- currentCacheDataObj = {
51
- [cacheId]: {
52
- [this.name]: {}
53
- }
54
- };
55
- }
56
- if (!currentCacheDataObj[cacheId][this.name]) {
57
- currentCacheDataObj[cacheId][this.name] = {};
58
- }
59
- cacheKey.forEach((key) => {
60
- currentCacheDataObj[cacheId][this.name][key] = store == null ? void 0 : store[key];
61
- });
62
- window.sessionStorage.setItem(
63
- fatherModule,
64
- JSON.stringify(currentCacheDataObj)
65
- );
66
- } else {
67
- let currentCacheData = window.sessionStorage.getItem(cacheId);
68
- let currentCacheDataObj = JSON.parse(currentCacheData || "{}");
69
- if (!currentCacheDataObj) {
70
- currentCacheDataObj = {};
71
- }
72
- if (!currentCacheDataObj[this.name]) {
73
- currentCacheDataObj[this.name] = {};
74
- }
75
- cacheKey.forEach((key) => {
76
- currentCacheDataObj[this.name][key] = store[key];
77
- });
78
- window.sessionStorage.setItem(
79
- cacheId,
80
- JSON.stringify(currentCacheDataObj)
81
- );
66
+ parsedCacheData[cacheId] = cacheBucket;
82
67
  }
68
+ sessionStorage.setItem(storageKey, JSON.stringify(parsedCacheData));
69
+ } catch {
83
70
  }
84
71
  }
85
72
  effectsOn(eventType, callback) {
@@ -16,6 +16,10 @@ export declare class OrderModule extends BaseModule implements Module, OrderModu
16
16
  private window;
17
17
  private appPlugin;
18
18
  private cacheId;
19
+ private fatherModule;
20
+ private openCache;
21
+ private sessionStoragePersistEnabled;
22
+ private sessionStorageRestoreRecord;
19
23
  private salesSummaryModuleName;
20
24
  private rulesHooksOverride?;
21
25
  private moduleHooksOverride?;
@@ -46,6 +50,7 @@ export declare class OrderModule extends BaseModule implements Module, OrderModu
46
50
  static populateSavedAmounts(productList: Array<Record<string, any>>, discountList: Array<Record<string, any>>): void;
47
51
  private applyProductDiscountPrices;
48
52
  constructor(name?: string, version?: string);
53
+ private syncSessionStorageOptions;
49
54
  initialize(core: PisellCore, options: ModuleOptions): Promise<void>;
50
55
  destroy(): Promise<void>;
51
56
  /**
@@ -137,7 +142,8 @@ export declare class OrderModule extends BaseModule implements Module, OrderModu
137
142
  }): void;
138
143
  /**
139
144
  * 控制 IndexedDB 草稿(saveDraft)是否写入。
140
- * localStorage tempOrder 持久化已废弃,此方法仅影响 saveDraft。
145
+ * 此开关仅影响 saveDraft;可选 sessionStorage 会话恢复由
146
+ * enableSessionStoragePersist 独立控制。
141
147
  *
142
148
  * @example
143
149
  * order.setEnableTempOrderPersist(false); // BigSale 弹窗:跳过 ~1s 的 dbUpdate
@@ -145,8 +151,12 @@ export declare class OrderModule extends BaseModule implements Module, OrderModu
145
151
  setEnableTempOrderPersist(enabled: boolean): void;
146
152
  /** 是否允许 saveDraft 写入 IndexedDB 草稿。 */
147
153
  isTempOrderPersistEnabled(): boolean;
148
- /** @deprecated OrderModule 不再负责 tempOrder localStorage 持久化;草稿保存请使用 IndexedDB saveDraft。 */
154
+ /**
155
+ * 在 UnifiedBookingSales 显式开启会话恢复时,将完整 tempOrder 写入
156
+ * sessionStorage 的 cacheId 分桶。写入失败由 BaseModule 静默降级。
157
+ */
149
158
  persistTempOrder(): void;
159
+ consumeSessionStorageRestore(): Record<string, any> | null;
150
160
  notifyTempOrderChanged(): void;
151
161
  private createDefaultTempOrderInstance;
152
162
  private createExternalSaleNumber;
@@ -537,6 +547,7 @@ export declare class OrderModule extends BaseModule implements Module, OrderModu
537
547
  */
538
548
  hydrateTempOrderFromRecord(record: Record<string, any>, options?: {
539
549
  recalcOnHydrate?: boolean;
550
+ source?: 'salesDetail' | 'sessionStorage';
540
551
  }): Promise<OrderTempOrder>;
541
552
  /**
542
553
  * 兼容后端详情将 holder 放在 metadata.holder 的历史形态,统一补到运行时展示路径。
@@ -113,6 +113,9 @@ var OrderModule = class extends import_BaseModule.BaseModule {
113
113
  super(name || "order", version);
114
114
  this.defaultName = "order";
115
115
  this.defaultVersion = "1.0.0";
116
+ this.openCache = false;
117
+ this.sessionStoragePersistEnabled = false;
118
+ this.sessionStorageRestoreRecord = null;
116
119
  // ─── 促销/赠品 ────────────────────────────────────
117
120
  /** 评估器引用;由 SalesSdkProvider 注入,未注入时 applyPromotion 静默跳过 */
118
121
  this.promotionEvaluator = null;
@@ -327,11 +330,32 @@ var OrderModule = class extends import_BaseModule.BaseModule {
327
330
  return product;
328
331
  });
329
332
  }
333
+ syncSessionStorageOptions(otherParams) {
334
+ this.cacheId = otherParams.cacheId;
335
+ this.fatherModule = otherParams.fatherModule;
336
+ this.openCache = Boolean(
337
+ this.cacheId && otherParams.openCache !== false
338
+ );
339
+ this.sessionStoragePersistEnabled = Boolean(
340
+ this.openCache && otherParams.enableSessionStoragePersist === true
341
+ );
342
+ }
330
343
  async initialize(core, options) {
331
344
  var _a, _b, _c, _d;
332
345
  this.core = core;
333
346
  this.store = options.store;
334
- if (!this.store.tempOrder) {
347
+ const otherParams = options.otherParams || {};
348
+ this.syncSessionStorageOptions(otherParams);
349
+ if (this.sessionStoragePersistEnabled) {
350
+ const cachedTempOrder = this.store.tempOrder;
351
+ this.sessionStorageRestoreRecord = (0, import_utils.isTempOrder)(cachedTempOrder) ? (0, import_lodash_es.cloneDeep)(cachedTempOrder) : null;
352
+ this.store.tempOrder = null;
353
+ this.store.summary = (0, import_utils.createEmptySummary)();
354
+ this.store.availableWalletIds = [];
355
+ this.store.lastOrderInfo = void 0;
356
+ this.store.syncState = void 0;
357
+ this.store.discountList = [];
358
+ } else if (!this.store.tempOrder) {
335
359
  this.store.tempOrder = null;
336
360
  }
337
361
  if (!this.store.summary) {
@@ -348,8 +372,6 @@ var OrderModule = class extends import_BaseModule.BaseModule {
348
372
  const app = (_a = appPlugin == null ? void 0 : appPlugin.getApp) == null ? void 0 : _a.call(appPlugin);
349
373
  this.logger = app == null ? void 0 : app.logger;
350
374
  this.window = this.core.getPlugin("window");
351
- const otherParams = options.otherParams || {};
352
- this.cacheId = otherParams.cacheId;
353
375
  this.salesSummaryModuleName = otherParams.salesSummaryModuleName;
354
376
  this.rulesHooksOverride = (_b = otherParams.rules) == null ? void 0 : _b.hooks;
355
377
  this.moduleHooksOverride = options.hooks;
@@ -360,6 +382,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
360
382
  }
361
383
  async destroy() {
362
384
  var _a, _b;
385
+ this.sessionStorageRestoreRecord = null;
363
386
  const childModules = [(_a = this.store) == null ? void 0 : _a.discount, (_b = this.store) == null ? void 0 : _b.rules];
364
387
  for (const childModule of childModules) {
365
388
  if (!childModule || typeof childModule.destroy !== "function")
@@ -389,7 +412,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
389
412
  updateOtherParams(params) {
390
413
  var _a, _b, _c;
391
414
  const otherParams = params || {};
392
- this.cacheId = otherParams.cacheId;
415
+ this.syncSessionStorageOptions(otherParams);
393
416
  this.salesSummaryModuleName = otherParams.salesSummaryModuleName;
394
417
  this.rulesHooksOverride = (_a = otherParams.rules) == null ? void 0 : _a.hooks;
395
418
  this.orderHooks = this.moduleHooksOverride || ((_b = otherParams.order) == null ? void 0 : _b.hooks) || ((_c = otherParams.hooks) == null ? void 0 : _c.order);
@@ -434,14 +457,14 @@ var OrderModule = class extends import_BaseModule.BaseModule {
434
457
  // ─── Discount: 子模块注册 ───
435
458
  registerDiscountModules(options) {
436
459
  let targetCacheData = {};
437
- if (this.cacheId && this.window) {
438
- const sessionData = this.window.sessionStorage.getItem(this.name);
439
- if (sessionData) {
440
- try {
460
+ if (!this.sessionStoragePersistEnabled && this.openCache && this.cacheId && this.window) {
461
+ try {
462
+ const sessionData = this.window.sessionStorage.getItem(this.name);
463
+ if (sessionData) {
441
464
  const data = JSON.parse(sessionData);
442
465
  targetCacheData = (data == null ? void 0 : data[this.cacheId]) || {};
443
- } catch {
444
466
  }
467
+ } catch {
445
468
  }
446
469
  }
447
470
  const discount = new import_Discount.DiscountModule(`${this.name}_discount`);
@@ -449,7 +472,8 @@ var OrderModule = class extends import_BaseModule.BaseModule {
449
472
  initialState: targetCacheData == null ? void 0 : targetCacheData[discount.name],
450
473
  otherParams: {
451
474
  fatherModule: this.name,
452
- openCache: !!this.cacheId,
475
+ // Unified 的单快照由 Order 管理;其他 Solution 保持原有 Discount 缓存语义。
476
+ openCache: this.openCache && !this.sessionStoragePersistEnabled,
453
477
  cacheId: this.cacheId
454
478
  }
455
479
  });
@@ -865,7 +889,8 @@ var OrderModule = class extends import_BaseModule.BaseModule {
865
889
  }
866
890
  /**
867
891
  * 控制 IndexedDB 草稿(saveDraft)是否写入。
868
- * localStorage tempOrder 持久化已废弃,此方法仅影响 saveDraft。
892
+ * 此开关仅影响 saveDraft;可选 sessionStorage 会话恢复由
893
+ * enableSessionStoragePersist 独立控制。
869
894
  *
870
895
  * @example
871
896
  * order.setEnableTempOrderPersist(false); // BigSale 弹窗:跳过 ~1s 的 dbUpdate
@@ -877,8 +902,24 @@ var OrderModule = class extends import_BaseModule.BaseModule {
877
902
  isTempOrderPersistEnabled() {
878
903
  return this.draftPersistEnabled;
879
904
  }
880
- /** @deprecated OrderModule 不再负责 tempOrder localStorage 持久化;草稿保存请使用 IndexedDB saveDraft。 */
905
+ /**
906
+ * 在 UnifiedBookingSales 显式开启会话恢复时,将完整 tempOrder 写入
907
+ * sessionStorage 的 cacheId 分桶。写入失败由 BaseModule 静默降级。
908
+ */
881
909
  persistTempOrder() {
910
+ if (!this.sessionStoragePersistEnabled || !this.store.tempOrder)
911
+ return;
912
+ this.checkSaveCache({
913
+ cacheId: this.cacheId,
914
+ fatherModule: this.fatherModule,
915
+ store: { tempOrder: this.store.tempOrder },
916
+ cacheKey: ["tempOrder"]
917
+ });
918
+ }
919
+ consumeSessionStorageRestore() {
920
+ const record = this.sessionStorageRestoreRecord;
921
+ this.sessionStorageRestoreRecord = null;
922
+ return record ? (0, import_lodash_es.cloneDeep)(record) : null;
882
923
  }
883
924
  notifyTempOrderChanged() {
884
925
  if (!this.store.tempOrder)
@@ -1733,6 +1774,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1733
1774
  restoreOrder() {
1734
1775
  var _a, _b;
1735
1776
  this.logInfo("restoreOrder start", {});
1777
+ this.sessionStorageRestoreRecord = null;
1736
1778
  const freshTempOrder = this.createDefaultTempOrderInstance();
1737
1779
  this.ensureExternalSaleNumber(freshTempOrder);
1738
1780
  this.store.tempOrder = freshTempOrder;
@@ -1751,6 +1793,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1751
1793
  if (!(0, import_utils.isTempOrder)(tempOrder)) {
1752
1794
  throw new Error("无效的 tempOrder 数据");
1753
1795
  }
1796
+ this.sessionStorageRestoreRecord = null;
1754
1797
  const nextTempOrder = this.normalizeTempOrderForRuntime(
1755
1798
  (0, import_lodash_es.cloneDeep)(tempOrder),
1756
1799
  { ensureIdentity: false }
@@ -4257,7 +4300,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
4257
4300
  * 例如数组字段、商品行唯一值、价格 metadata、summary 派生状态和 _extend。
4258
4301
  */
4259
4302
  async hydrateTempOrderFromRecord(record, options) {
4260
- var _a, _b, _c;
4303
+ var _a, _b, _c, _d, _e;
4261
4304
  const sourceRaw = record && typeof record === "object" && record.data && record.order_id == null ? record.data : record || {};
4262
4305
  const identityReadySource = this.seedAnonymousBookingUidsFromProducts(
4263
4306
  sourceRaw
@@ -4287,8 +4330,37 @@ var OrderModule = class extends import_BaseModule.BaseModule {
4287
4330
  );
4288
4331
  }
4289
4332
  }
4290
- const nextTempOrder = this.normalizeTempOrderForRuntime(raw, { makeEditMark: true });
4291
- const sourceLastOrderInfo = raw.lastOrderInfo || raw;
4333
+ const isSessionStorageHydrate = (options == null ? void 0 : options.source) === "sessionStorage";
4334
+ const nextTempOrder = this.normalizeTempOrderForRuntime(raw, {
4335
+ makeEditMark: !isSessionStorageHydrate
4336
+ });
4337
+ this.store.tempOrder = nextTempOrder;
4338
+ if (isSessionStorageHydrate) {
4339
+ const restoredSessionDiscounts = Array.isArray(raw.discount_list) ? (0, import_lodash_es.cloneDeep)(raw.discount_list) : [];
4340
+ const nextExtend = { ...nextTempOrder._extend || {} };
4341
+ delete nextExtend.originalSalesSnapshot;
4342
+ nextTempOrder._extend = nextExtend;
4343
+ nextTempOrder.products.forEach((product) => {
4344
+ if (product.metadata) {
4345
+ delete product.metadata.is_edit_for_runtime;
4346
+ }
4347
+ });
4348
+ nextTempOrder.discount_list = restoredSessionDiscounts;
4349
+ this.store.summary = (0, import_utils.createEmptySummary)();
4350
+ this.store.lastOrderInfo = void 0;
4351
+ await ((_a = this.store.discount) == null ? void 0 : _a.setOriginalDiscountList(
4352
+ (0, import_lodash_es.cloneDeep)(restoredSessionDiscounts)
4353
+ ));
4354
+ await ((_b = this.store.discount) == null ? void 0 : _b.setDiscountList(
4355
+ (0, import_lodash_es.cloneDeep)(restoredSessionDiscounts)
4356
+ ));
4357
+ if (options == null ? void 0 : options.recalcOnHydrate) {
4358
+ await this.recalculateSummary({ createIfMissing: false });
4359
+ }
4360
+ this.persistTempOrder();
4361
+ return nextTempOrder;
4362
+ }
4363
+ const sourceLastOrderInfo = sourceRaw.lastOrderInfo || sourceRaw;
4292
4364
  const isDraftOrder = Number(nextTempOrder.is_draft_order || 0) === 1;
4293
4365
  const syntheticIdentityOptions = {
4294
4366
  isDraftOrder,
@@ -4296,7 +4368,6 @@ var OrderModule = class extends import_BaseModule.BaseModule {
4296
4368
  };
4297
4369
  const rawSummary = raw.summary && typeof raw.summary === "object" ? raw.summary : {};
4298
4370
  const summarySurcharges = Array.isArray(rawSummary.surcharges) ? rawSummary.surcharges.map((s) => ({ ...s || {} })) : (0, import_lodash_es.cloneDeep)(nextTempOrder.surcharges || []);
4299
- this.store.tempOrder = nextTempOrder;
4300
4371
  this.store.summary = {
4301
4372
  ...(0, import_utils.createEmptySummary)(),
4302
4373
  ...rawSummary,
@@ -4323,7 +4394,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
4323
4394
  this.store.syncState = "local";
4324
4395
  }
4325
4396
  const hydratedEditDiscounts = this.collectHydratedEditDiscounts(nextTempOrder.products);
4326
- const currentDiscounts = typeof ((_a = this.store.discount) == null ? void 0 : _a.getDiscountList) === "function" ? this.store.discount.getDiscountList() || [] : [];
4397
+ const currentDiscounts = typeof ((_c = this.store.discount) == null ? void 0 : _c.getDiscountList) === "function" ? this.store.discount.getDiscountList() || [] : [];
4327
4398
  const currentScanDiscounts = currentDiscounts.filter((discount) => discount == null ? void 0 : discount.isScan);
4328
4399
  const hydratedDiscountIds = new Set(
4329
4400
  hydratedEditDiscounts.map((discount) => discount == null ? void 0 : discount.id)
@@ -4341,8 +4412,8 @@ var OrderModule = class extends import_BaseModule.BaseModule {
4341
4412
  nextTempOrder.products,
4342
4413
  nextDiscounts
4343
4414
  );
4344
- await ((_b = this.store.discount) == null ? void 0 : _b.setOriginalDiscountList(nextDiscounts));
4345
- await ((_c = this.store.discount) == null ? void 0 : _c.setDiscountList(nextDiscounts));
4415
+ await ((_d = this.store.discount) == null ? void 0 : _d.setOriginalDiscountList(nextDiscounts));
4416
+ await ((_e = this.store.discount) == null ? void 0 : _e.setDiscountList(nextDiscounts));
4346
4417
  }
4347
4418
  if (options == null ? void 0 : options.recalcOnHydrate) {
4348
4419
  await this.recalculateSummary({ createIfMissing: false });
@@ -561,6 +561,10 @@ export interface LoadSalesDetailParams {
561
561
  * 存在时 loadSalesDetail 会跳过远端 lookup,直接复用 hydrate 后半段逻辑。
562
562
  */
563
563
  preloadedSalesDetail?: Record<string, any>;
564
+ /**
565
+ * sessionStorage 快照复用详情 hydrate 时使用;不带该值时保持既有编辑订单语义。
566
+ */
567
+ hydrateSource?: 'sessionStorage';
564
568
  forceRemote?: boolean;
565
569
  merge?: boolean;
566
570
  }
@@ -731,8 +735,10 @@ export interface OrderModuleAPI {
731
735
  removeProductFromOrder: (identity: OrderProductIdentity) => Promise<OrderProduct[]>;
732
736
  /** 批量删除购物车行,末尾仅触发一次促销重算与 summary 刷新 */
733
737
  removeProductsFromOrder: (identities: OrderProductIdentity[]) => Promise<OrderProduct[]>;
734
- /** @deprecated no-op;OrderModule 不再负责 tempOrder localStorage 持久化。 */
738
+ /** 在显式开启时保存当前 tempOrder sessionStorage 会话快照。 */
735
739
  persistTempOrder: () => void;
740
+ /** 取出一次待恢复的 sessionStorage tempOrder 快照。 */
741
+ consumeSessionStorageRestore: () => Record<string, any> | null;
736
742
  /**
737
743
  * 控制 IndexedDB 草稿(saveDraft)开关;localStorage tempOrder 持久化已废弃。
738
744
  * BigSale 弹窗等场景传 false 可跳过 saveDraft。
@@ -790,6 +796,7 @@ export interface OrderModuleAPI {
790
796
  saveDraft: () => Promise<void>;
791
797
  hydrateTempOrderFromRecord: (record: Record<string, any>, options?: {
792
798
  recalcOnHydrate?: boolean;
799
+ source?: 'salesDetail' | 'sessionStorage';
793
800
  }) => Promise<OrderTempOrder>;
794
801
  syncPaymentsToOrder: <T = any>(params: SyncPaymentsToOrderParams) => Promise<SyncPaymentsToOrderResult<T>>;
795
802
  getSalesOrderByLookup: (params: SalesOrderLookupParams) => Promise<any>;
@@ -131,7 +131,9 @@ export declare class BaseSalesImpl extends BaseModule implements Module {
131
131
  * const params = this.buildSubModuleOtherParams();
132
132
  * this.core.registerModule(orderModule, { otherParams: params });
133
133
  */
134
- protected buildSubModuleOtherParams(): Record<string, any>;
134
+ protected isSessionStoragePersistEnabled(): boolean;
135
+ protected shouldUseSessionStorageForSubModule(_moduleName?: string): boolean;
136
+ protected buildSubModuleOtherParams(moduleName?: string): Record<string, any>;
135
137
  /**
136
138
  * 将父级 otherParams 的变更显式同步给已注册的子模块。
137
139
  *
@@ -588,7 +588,7 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
588
588
  });
589
589
  });
590
590
  }
591
- async hydrateLatestLoadedSalesDetail(record, loadSequence) {
591
+ async hydrateLatestLoadedSalesDetail(record, loadSequence, hydrateSource) {
592
592
  let hydratedSales = null;
593
593
  let skippedBeforeHydrate = false;
594
594
  const hydrateTask = async () => {
@@ -598,9 +598,10 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
598
598
  }
599
599
  if (!this.store.order)
600
600
  throw new Error("order 模块未初始化");
601
- const sales = await this.store.order.hydrateTempOrderFromRecord(record, {
602
- recalcOnHydrate: false
603
- });
601
+ const sales = await this.store.order.hydrateTempOrderFromRecord(
602
+ record,
603
+ hydrateSource === "sessionStorage" ? { recalcOnHydrate: true, source: "sessionStorage" } : { recalcOnHydrate: false }
604
+ );
604
605
  hydratedSales = sales;
605
606
  if (loadSequence !== this.salesDetailLoadSequence)
606
607
  return;
@@ -891,12 +892,18 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
891
892
  * const params = this.buildSubModuleOtherParams();
892
893
  * this.core.registerModule(orderModule, { otherParams: params });
893
894
  */
894
- buildSubModuleOtherParams() {
895
+ isSessionStoragePersistEnabled() {
896
+ return Boolean(this.cacheId);
897
+ }
898
+ shouldUseSessionStorageForSubModule(_moduleName) {
899
+ return this.isSessionStoragePersistEnabled();
900
+ }
901
+ buildSubModuleOtherParams(moduleName) {
895
902
  return {
896
903
  ...this.otherParams,
897
904
  salesSummaryModuleName: `${this.name}_salesSummary`,
898
905
  fatherModule: this.name,
899
- openCache: this.cacheId ? true : false,
906
+ openCache: this.shouldUseSessionStorageForSubModule(moduleName),
900
907
  cacheId: this.cacheId
901
908
  };
902
909
  }
@@ -907,7 +914,6 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
907
914
  * await this.syncOtherParamsToSubModules({ channel: 'pos' });
908
915
  */
909
916
  async syncOtherParamsToSubModules(changedParams, { cover = false } = {}) {
910
- const nextSubModuleOtherParams = this.buildSubModuleOtherParams();
911
917
  await Promise.all(
912
918
  Object.entries(this.store).map(async ([moduleName, subModule]) => {
913
919
  if (this.reusedSharedSubModuleNames.has(moduleName)) {
@@ -917,6 +923,7 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
917
923
  if (!targetModule || typeof targetModule.updateOtherParams !== "function") {
918
924
  return;
919
925
  }
926
+ const nextSubModuleOtherParams = this.buildSubModuleOtherParams(moduleName);
920
927
  await targetModule.updateOtherParams(nextSubModuleOtherParams, {
921
928
  changedParams,
922
929
  cover
@@ -929,14 +936,16 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
929
936
  * sessionStorage 损坏时静默忽略,按空状态注册。
930
937
  */
931
938
  readSessionCacheData() {
932
- if (!this.cacheId || !this.window)
939
+ const cacheId = this.cacheId;
940
+ if (!cacheId || !this.isSessionStoragePersistEnabled() || !this.window) {
933
941
  return {};
942
+ }
934
943
  try {
935
944
  const sessionData = this.window.sessionStorage.getItem(this.name);
936
945
  if (!sessionData)
937
946
  return {};
938
947
  const data = JSON.parse(sessionData);
939
- return data && data[this.cacheId] || {};
948
+ return data && data[cacheId] || {};
940
949
  } catch {
941
950
  return {};
942
951
  }
@@ -1038,9 +1047,9 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
1038
1047
  const hooks = this.getSubModuleHooks(step);
1039
1048
  this.store[step] = targetModule;
1040
1049
  this.core.registerModule(targetModule, {
1041
- initialState: (targetCacheData == null ? void 0 : targetCacheData[targetModule.name]) || {},
1050
+ initialState: this.shouldUseSessionStorageForSubModule(step) ? (targetCacheData == null ? void 0 : targetCacheData[targetModule.name]) || {} : {},
1042
1051
  ...hooks ? { hooks } : {},
1043
- otherParams: this.buildSubModuleOtherParams()
1052
+ otherParams: this.buildSubModuleOtherParams(step)
1044
1053
  });
1045
1054
  });
1046
1055
  if (this.store.schedule && !this.isScheduleListLoaded(this.store.schedule)) {
@@ -1107,17 +1116,21 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
1107
1116
  const message = loadedRecord && (loadedRecord.message || loadedRecord.msg) || `加载销售详情失败: ${lookup}`;
1108
1117
  throw new Error(message);
1109
1118
  }
1110
- const remoteRecord = filterPendingPaymentsFromLoadedSalesDetail(
1111
- preloadedSalesDetail ?? loadedRecord.data
1112
- );
1119
+ const loadedSalesDetail = preloadedSalesDetail ?? loadedRecord.data;
1120
+ const shouldFilterPendingPayments = params.hydrateSource !== "sessionStorage";
1121
+ const remoteRecord = shouldFilterPendingPayments ? filterPendingPaymentsFromLoadedSalesDetail(loadedSalesDetail) : loadedSalesDetail;
1113
1122
  const currentTempOrder = params.merge ? this.store.order.getTempOrder() : null;
1114
1123
  const mergedRecord = params.merge ? mergeSalesDetailRecordWithTempOrder(
1115
1124
  currentTempOrder,
1116
1125
  remoteRecord,
1117
1126
  "preserve-local"
1118
1127
  ) : remoteRecord;
1119
- const record = filterPendingPaymentsFromLoadedSalesDetail(mergedRecord);
1120
- return await this.hydrateLatestLoadedSalesDetail(record, loadSequence);
1128
+ const record = shouldFilterPendingPayments ? filterPendingPaymentsFromLoadedSalesDetail(mergedRecord) : mergedRecord;
1129
+ return await this.hydrateLatestLoadedSalesDetail(
1130
+ record,
1131
+ loadSequence,
1132
+ params.hydrateSource
1133
+ );
1121
1134
  } finally {
1122
1135
  this.salesDetailLoadInFlightCount = Math.max(
1123
1136
  0,
@@ -326,7 +326,7 @@ export declare class BookingByStepImpl extends BaseModule implements Module {
326
326
  date: string;
327
327
  status: string;
328
328
  week: string;
329
- weekNum: 0 | 2 | 1 | 5 | 4 | 3 | 6;
329
+ weekNum: 0 | 1 | 2 | 3 | 4 | 5 | 6;
330
330
  }[]>;
331
331
  submitTimeSlot(timeSlots: TimeSliceItem): void;
332
332
  private getScheduleDataByIds;
@@ -445,19 +445,7 @@ export declare class BookingTicketImpl extends BaseSalesImpl implements Module {
445
445
  * 加车两阶段主决策(规格弹窗 / 资源编辑 / 直接加车)。
446
446
  * 与 ticketBooking `handleSelectProduct` + `handleBooking4Service` 等价。
447
447
  */
448
- decideAddProduct(item: any, options?: Partial<AddProductDecideContext>): {
449
- action: "reloadCatalog";
450
- } | {
451
- action: "add";
452
- cacheItem: any;
453
- } | {
454
- action: "requiresDetail";
455
- payload: AddProductRequiresDetailPayload;
456
- } | {
457
- action: "requiresBookingEdit";
458
- cacheItem: any;
459
- payload: import("./utils/addProductDecision").AddProductRequiresBookingEditPayload;
460
- };
448
+ decideAddProduct(item: any, options?: Partial<AddProductDecideContext>): import("./utils/addProductDecision").AddProductDecision;
461
449
  /** 规格弹窗 callback 后的第二段决策。 */
462
450
  decideAfterDetail(cacheItem: any, options?: Partial<AddProductDecideContext>): import("./utils/addProductDecision").AddProductDecision;
463
451
  /**
@@ -63,6 +63,8 @@ export declare class UnifiedBookingSalesImpl extends BookingTicket {
63
63
  private openDataTarget;
64
64
  private loadOpenDataInFlight;
65
65
  private loadOpenDataInFlightTarget;
66
+ protected isSessionStoragePersistEnabled(): boolean;
67
+ protected shouldUseSessionStorageForSubModule(moduleName?: string): boolean;
66
68
  /**
67
69
  * Kiosk 不能把已收款订单留在本地等待重试:默认直接等待云端 checkout。
68
70
  * 兼容仍需要 WebPOS 待同步模式的入口可显式传 checkoutSyncTaskEnabled: true。
@@ -72,6 +74,7 @@ export declare class UnifiedBookingSalesImpl extends BookingTicket {
72
74
  protected getDefaultCheckoutSmallTicketDataFlag(): number;
73
75
  protected getRegisteredModuleNames(): readonly string[];
74
76
  protected createSubModule(moduleName: string): Module | null;
77
+ addNewOrder(): Promise<import("../../modules/Order/types").OrderTempOrder>;
75
78
  /**
76
79
  * Loads OpenData without borrowing BookingTicket. Cache ownership is tied to the exact
77
80
  * business/channel target so a reused solution instance cannot leak another entry's menus.