@pisell/pisellos 2.2.78 → 2.2.79

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.
@@ -1,4 +1,12 @@
1
1
  function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
2
+ function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
3
+ function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
4
+ function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
5
+ function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
6
+ function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
7
+ function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
8
+ function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
9
+ function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
2
10
  function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
3
11
  function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
4
12
  function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
@@ -21,16 +29,18 @@ function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key i
21
29
  function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
22
30
  function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
23
31
  import { BaseModule } from "../../../modules/BaseModule";
24
- import { cloneDeep } from 'lodash-es';
25
32
  import { RequestModeENUM } from "../../../plugins";
26
33
  import { ProductsHooks } from "./types";
27
- import { applyDetailValueToProducts, applyPriceDataToProducts } from "../../utils/product";
34
+ import { applyDetailValueToProducts, applyPriceDataToProducts, perfMark } from "../../utils/product";
28
35
 
29
36
  /**
30
37
  * IndexDB 存储名称
31
38
  */
32
39
  var INDEXDB_STORE_NAME = 'products';
33
40
 
41
+ /** 商品同步防抖时间(毫秒) */
42
+ var PRODUCT_SYNC_DEBOUNCE_MS = 10000;
43
+
34
44
  /**
35
45
  * Products 模块 - 用于获取和管理完整的商品详细数据
36
46
  * 相比 ProductList 模块,Products 会获取所有详细信息并缓存
@@ -60,6 +70,10 @@ export var ProductsModule = /*#__PURE__*/function (_BaseModule) {
60
70
  _defineProperty(_assertThisInitialized(_this), "formatters", []);
61
71
  // 是否已注册内置价格格式化器
62
72
  _defineProperty(_assertThisInitialized(_this), "isPriceFormatterRegistered", false);
73
+ // ---- 商品数据同步相关 ----
74
+ _defineProperty(_assertThisInitialized(_this), "productDataSource", void 0);
75
+ _defineProperty(_assertThisInitialized(_this), "pendingSyncMessages", []);
76
+ _defineProperty(_assertThisInitialized(_this), "syncTimer", void 0);
63
77
  return _this;
64
78
  }
65
79
  _createClass(ProductsModule, [{
@@ -100,12 +114,18 @@ export var ProductsModule = /*#__PURE__*/function (_BaseModule) {
100
114
 
101
115
  // 注册内置的价格格式化器(作为第一个格式化器)
102
116
  this.registerBuiltinPriceFormatter();
117
+
118
+ // 初始化 ProductDataSource 实例
119
+ this.initProductDataSource();
120
+
121
+ // 初始化商品数据同步(pubsub 订阅)
122
+ this.setupProductSync();
103
123
  this.logInfo('模块初始化完成', {
104
124
  hasDbManager: !!this.dbManager,
105
125
  hasLogger: !!this.logger,
106
126
  initialProductCount: this.store.list.length
107
127
  });
108
- case 9:
128
+ case 11:
109
129
  case "end":
110
130
  return _context.stop();
111
131
  }
@@ -254,46 +274,46 @@ export var ProductsModule = /*#__PURE__*/function (_BaseModule) {
254
274
  key: "getProductsWithPrice",
255
275
  value: (function () {
256
276
  var _getProductsWithPrice = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee3(schedule_date, extraContext) {
257
- var cacheKey, cachedProducts, startTime, result, duration;
277
+ var t0, cacheKey, cachedProducts, result;
258
278
  return _regeneratorRuntime().wrap(function _callee3$(_context3) {
259
279
  while (1) switch (_context3.prev = _context3.next) {
260
280
  case 0:
261
- cacheKey = schedule_date; // 检查缓存
281
+ t0 = performance.now();
282
+ cacheKey = schedule_date;
262
283
  if (!this.productsPriceCache.has(cacheKey)) {
263
- _context3.next = 6;
284
+ _context3.next = 7;
264
285
  break;
265
286
  }
266
- console.log("[ProductsModule] \uD83D\uDCB0 \u5546\u54C1\u4EF7\u683C\u7F13\u5B58\u547D\u4E2D: ".concat(cacheKey));
267
287
  cachedProducts = this.productsPriceCache.get(cacheKey);
288
+ perfMark('getProductsWithPrice(cacheHit)', performance.now() - t0, {
289
+ cacheKey: cacheKey,
290
+ count: cachedProducts.length
291
+ });
268
292
  this.logInfo('商品价格缓存命中', {
269
293
  cacheKey: cacheKey,
270
294
  productCount: cachedProducts.length
271
295
  });
272
296
  return _context3.abrupt("return", cachedProducts);
273
- case 6:
274
- // 发起新请求并应用价格
275
- console.log("[ProductsModule] \uD83C\uDF10 \u83B7\u53D6\u5546\u54C1\u5E76\u5E94\u7528\u4EF7\u683C: ".concat(cacheKey));
297
+ case 7:
276
298
  this.logInfo('商品价格缓存未命中,准备获取', {
277
299
  cacheKey: cacheKey
278
300
  });
279
- startTime = Date.now();
280
- _context3.next = 11;
301
+ _context3.next = 10;
281
302
  return this.prepareProductsWithPrice(schedule_date, extraContext);
282
- case 11:
303
+ case 10:
283
304
  result = _context3.sent;
284
- duration = Date.now() - startTime; // 存入缓存
285
305
  this.productsPriceCache.set(cacheKey, result);
286
- console.log("[ProductsModule] \u2705 \u5546\u54C1\u4EF7\u683C\u5DF2\u7F13\u5B58: ".concat(cacheKey, ", \u5171 ").concat(result.length, " \u4E2A\u5546\u54C1"));
287
306
  this.logInfo('商品价格已缓存', {
288
307
  cacheKey: cacheKey,
289
- productCount: result.length,
290
- duration: "".concat(duration, "ms")
308
+ productCount: result.length
291
309
  });
292
-
293
- // 清理过期缓存
294
310
  this.cleanExpiredPriceCache();
311
+ perfMark('getProductsWithPrice(cacheMiss)', performance.now() - t0, {
312
+ cacheKey: cacheKey,
313
+ count: result.length
314
+ });
295
315
  return _context3.abrupt("return", result);
296
- case 18:
316
+ case 16:
297
317
  case "end":
298
318
  return _context3.stop();
299
319
  }
@@ -316,82 +336,88 @@ export var ProductsModule = /*#__PURE__*/function (_BaseModule) {
316
336
  key: "prepareProductsWithPrice",
317
337
  value: (function () {
318
338
  var _prepareProductsWithPrice = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee4(schedule_date, extraContext) {
319
- var _priceData$length, allProducts, priceData, context, processedProducts, errorMessage;
339
+ var tTotal, _priceData$length, allProducts, tIds, ids, i, tPrice, priceData, context, tFormat, processedProducts, errorMessage;
320
340
  return _regeneratorRuntime().wrap(function _callee4$(_context4) {
321
341
  while (1) switch (_context4.prev = _context4.next) {
322
342
  case 0:
343
+ tTotal = performance.now();
323
344
  this.logInfo('prepareProductsWithPrice 开始处理', {
324
345
  schedule_date: schedule_date
325
346
  });
326
- _context4.prev = 1;
327
- _context4.next = 4;
328
- return this.getProducts();
329
- case 4:
330
- allProducts = _context4.sent;
347
+ _context4.prev = 2;
348
+ // 1. 获取商品列表(内部引用,无拷贝 — formatter 会创建新对象)
349
+ allProducts = this.getProductsRef();
331
350
  this.logInfo('获取到商品列表', {
332
351
  productCount: allProducts.length
333
352
  });
334
- console.log("[ProductsModule] \uD83C\uDF10 \u5F00\u59CB\u83B7\u53D6\u5546\u54C1\u62A5\u4EF7\u5355\u4EF7\u683C");
335
- // 2. 获取价格数据
336
- _context4.next = 9;
353
+
354
+ // 2. 提取 IDs(预分配数组,避免 sort 开销)
355
+ tIds = performance.now();
356
+ ids = new Array(allProducts.length);
357
+ for (i = 0; i < allProducts.length; i++) {
358
+ ids[i] = allProducts[i].id;
359
+ }
360
+ perfMark('prepareProducts.extractIds', performance.now() - tIds, {
361
+ count: ids.length
362
+ });
363
+
364
+ // 3. 获取价格数据(网络请求)
365
+ tPrice = performance.now();
366
+ _context4.next = 12;
337
367
  return this.loadProductsPrice({
338
- ids: allProducts.map(function (product) {
339
- return product.id;
340
- }).sort(function (a, b) {
341
- return a - b;
342
- }),
368
+ ids: ids,
343
369
  schedule_date: schedule_date
344
370
  });
345
- case 9:
371
+ case 12:
346
372
  priceData = _context4.sent;
347
- console.log("[ProductsModule] \uD83C\uDF10 \u83B7\u53D6\u5546\u54C1\u62A5\u4EF7\u5355\u4EF7\u683C\u6210\u529F", priceData);
373
+ perfMark('prepareProducts.loadPrice', performance.now() - tPrice, {
374
+ count: ids.length
375
+ });
348
376
  this.logInfo('获取商品报价单价格成功', {
349
377
  priceDataCount: (_priceData$length = priceData === null || priceData === void 0 ? void 0 : priceData.length) !== null && _priceData$length !== void 0 ? _priceData$length : 0
350
378
  });
351
-
352
- // 3. 构建上下文(包含价格数据,合并外部传入的额外上下文)
353
379
  context = _objectSpread({
354
380
  schedule_date: schedule_date,
355
381
  priceData: priceData
356
- }, extraContext);
357
- console.log("[ProductsModule] \uD83C\uDF10 \u901A\u8FC7\u683C\u5F0F\u5316\u5668\u6D41\u7A0B\u5904\u7406\u5546\u54C1\uFF08\u5305\u62EC\u4EF7\u683C\u5E94\u7528\u3001\u5B57\u6BB5\u6269\u5C55\u7B49\uFF09");
358
- this.logInfo('开始通过格式化器流程处理商品', {
359
- formatterCount: this.formatters.length
360
- });
361
-
362
- // 4. 通过格式化器流程处理商品(包括价格应用、字段扩展等)
363
- _context4.next = 17;
382
+ }, extraContext); // 4. 通过格式化器流程处理商品
383
+ tFormat = performance.now();
384
+ _context4.next = 19;
364
385
  return this.applyFormatters(allProducts, context);
365
- case 17:
386
+ case 19:
366
387
  processedProducts = _context4.sent;
367
- console.log("[ProductsModule] \uD83C\uDF10 \u901A\u8FC7\u683C\u5F0F\u5316\u5668\u6D41\u7A0B\u5904\u7406\u5546\u54C1\uFF08\u5305\u62EC\u4EF7\u683C\u5E94\u7528\u3001\u5B57\u6BB5\u6269\u5C55\u7B49\uFF09\u6210\u529F", processedProducts);
388
+ perfMark('prepareProducts.applyFormatters', performance.now() - tFormat, {
389
+ count: allProducts.length,
390
+ formatterCount: this.formatters.length
391
+ });
368
392
  this.logInfo('prepareProductsWithPrice 处理完成', {
369
393
  originalProductCount: allProducts.length,
370
394
  processedProductCount: processedProducts.length,
371
395
  formatterCount: this.formatters.length
372
396
  });
373
-
374
- // 5. 触发钩子事件(用于外部监听)
375
- _context4.next = 22;
397
+ _context4.next = 24;
376
398
  return this.core.effects.emit(ProductsHooks.onProductsPriceApplied, processedProducts);
377
- case 22:
399
+ case 24:
400
+ perfMark('prepareProductsWithPrice', performance.now() - tTotal, {
401
+ productCount: allProducts.length,
402
+ formatterCount: this.formatters.length
403
+ });
378
404
  return _context4.abrupt("return", processedProducts);
379
- case 25:
380
- _context4.prev = 25;
381
- _context4.t0 = _context4["catch"](1);
405
+ case 28:
406
+ _context4.prev = 28;
407
+ _context4.t0 = _context4["catch"](2);
382
408
  errorMessage = _context4.t0 instanceof Error ? _context4.t0.message : String(_context4.t0);
383
409
  console.log("[ProductsModule] \uD83C\uDF10 ERROR", _context4.t0);
384
410
  this.logError('prepareProductsWithPrice 处理失败', {
385
411
  schedule_date: schedule_date,
386
412
  error: errorMessage
387
413
  });
388
- case 30:
414
+ case 33:
389
415
  return _context4.abrupt("return", []);
390
- case 31:
416
+ case 34:
391
417
  case "end":
392
418
  return _context4.stop();
393
419
  }
394
- }, _callee4, this, [[1, 25]]);
420
+ }, _callee4, this, [[2, 28]]);
395
421
  }));
396
422
  function prepareProductsWithPrice(_x6, _x7) {
397
423
  return _prepareProductsWithPrice.apply(this, arguments);
@@ -410,7 +436,7 @@ export var ProductsModule = /*#__PURE__*/function (_BaseModule) {
410
436
  key: "applyFormatters",
411
437
  value: (function () {
412
438
  var _applyFormatters = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee5(products, context) {
413
- var result, i, formatter, errorMessage;
439
+ var result, i, formatter, tF, errorMessage;
414
440
  return _regeneratorRuntime().wrap(function _callee5$(_context5) {
415
441
  while (1) switch (_context5.prev = _context5.next) {
416
442
  case 0:
@@ -429,25 +455,28 @@ export var ProductsModule = /*#__PURE__*/function (_BaseModule) {
429
455
  productCount: products.length,
430
456
  formatterCount: this.formatters.length
431
457
  });
432
-
433
- // 依次应用每个格式化器
434
458
  i = 0;
435
459
  case 7:
436
460
  if (!(i < this.formatters.length)) {
437
- _context5.next = 24;
461
+ _context5.next = 25;
438
462
  break;
439
463
  }
440
464
  formatter = this.formatters[i];
441
465
  _context5.prev = 9;
442
- console.log("[ProductsModule] \uD83D\uDCDD \u5E94\u7528\u683C\u5F0F\u5316\u5668 ".concat(i + 1, "/").concat(this.formatters.length));
466
+ tF = performance.now();
443
467
  _context5.next = 13;
444
468
  return formatter(result, context);
445
469
  case 13:
446
470
  result = _context5.sent;
447
- _context5.next = 21;
471
+ perfMark("applyFormatters[".concat(i, "]"), performance.now() - tF, {
472
+ index: i,
473
+ total: this.formatters.length,
474
+ productCount: result.length
475
+ });
476
+ _context5.next = 22;
448
477
  break;
449
- case 16:
450
- _context5.prev = 16;
478
+ case 17:
479
+ _context5.prev = 17;
451
480
  _context5.t0 = _context5["catch"](9);
452
481
  errorMessage = _context5.t0 instanceof Error ? _context5.t0.message : String(_context5.t0);
453
482
  console.error("[ProductsModule] \u274C \u683C\u5F0F\u5316\u5668 ".concat(i + 1, " \u6267\u884C\u5931\u8D25:"), _context5.t0);
@@ -456,13 +485,11 @@ export var ProductsModule = /*#__PURE__*/function (_BaseModule) {
456
485
  totalFormatters: this.formatters.length,
457
486
  error: errorMessage
458
487
  });
459
- // 继续执行后续格式化器,不中断流程
460
- case 21:
488
+ case 22:
461
489
  i++;
462
490
  _context5.next = 7;
463
491
  break;
464
- case 24:
465
- console.log("[ProductsModule] \u2705 \u6240\u6709\u683C\u5F0F\u5316\u5668\u5DF2\u5E94\u7528\uFF0C\u5171 ".concat(this.formatters.length, " \u4E2A"));
492
+ case 25:
466
493
  this.logInfo('所有格式化器已应用', {
467
494
  formatterCount: this.formatters.length,
468
495
  resultProductCount: result.length
@@ -472,7 +499,7 @@ export var ProductsModule = /*#__PURE__*/function (_BaseModule) {
472
499
  case "end":
473
500
  return _context5.stop();
474
501
  }
475
- }, _callee5, this, [[9, 16]]);
502
+ }, _callee5, this, [[9, 17]]);
476
503
  }));
477
504
  function applyFormatters(_x8, _x9) {
478
505
  return _applyFormatters.apply(this, arguments);
@@ -591,39 +618,102 @@ export var ProductsModule = /*#__PURE__*/function (_BaseModule) {
591
618
  }
592
619
 
593
620
  /**
594
- * 加载完整商品列表通过接口(包含所有详细数据)
595
- * @param params 查询参数
621
+ * 通过 ProductDataSource SSE 加载完整商品列表
596
622
  */
597
623
  }, {
598
624
  key: "loadProductsByServer",
599
625
  value: (function () {
600
- var _loadProductsByServer = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee6(params) {
601
- var _ref2, _ref2$category_ids, category_ids, _ref2$product_ids, product_ids, _ref2$collection, collection, customer_id, cacheId, startTime, _this$otherParams, _productsData$data2, productsData, productList, duration, _duration2, errorMessage;
626
+ var _loadProductsByServer = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee6() {
627
+ var t0, tSSE, productList, list, duration, errorMessage;
602
628
  return _regeneratorRuntime().wrap(function _callee6$(_context6) {
603
629
  while (1) switch (_context6.prev = _context6.next) {
630
+ case 0:
631
+ if (this.productDataSource) {
632
+ _context6.next = 3;
633
+ break;
634
+ }
635
+ this.logWarning('loadProductsByServer: ProductDataSource 不可用');
636
+ return _context6.abrupt("return", []);
637
+ case 3:
638
+ this.logInfo('开始通过 DataSource SSE 加载商品列表');
639
+ t0 = performance.now();
640
+ _context6.prev = 5;
641
+ tSSE = performance.now();
642
+ _context6.next = 9;
643
+ return this.productDataSource.run({
644
+ sse: {}
645
+ });
646
+ case 9:
647
+ productList = _context6.sent;
648
+ list = productList || [];
649
+ perfMark('loadProductsByServer.SSE', performance.now() - tSSE, {
650
+ count: list.length
651
+ });
652
+ this.logInfo('通过 DataSource SSE 加载商品列表成功', {
653
+ productCount: list.length,
654
+ duration: "".concat(Math.round(performance.now() - t0), "ms")
655
+ });
656
+ _context6.next = 15;
657
+ return this.saveProductsToIndexDB(list);
658
+ case 15:
659
+ _context6.next = 17;
660
+ return this.core.effects.emit(ProductsHooks.onProductsLoaded, list);
661
+ case 17:
662
+ perfMark('loadProductsByServer', performance.now() - t0, {
663
+ count: list.length
664
+ });
665
+ return _context6.abrupt("return", list);
666
+ case 21:
667
+ _context6.prev = 21;
668
+ _context6.t0 = _context6["catch"](5);
669
+ duration = Math.round(performance.now() - t0);
670
+ errorMessage = _context6.t0 instanceof Error ? _context6.t0.message : String(_context6.t0);
671
+ console.error('[Products] 加载商品数据失败:', _context6.t0);
672
+ this.logError('通过 DataSource SSE 加载商品列表失败', {
673
+ duration: "".concat(duration, "ms"),
674
+ error: errorMessage
675
+ });
676
+ return _context6.abrupt("return", []);
677
+ case 28:
678
+ case "end":
679
+ return _context6.stop();
680
+ }
681
+ }, _callee6, this, [[5, 21]]);
682
+ }));
683
+ function loadProductsByServer() {
684
+ return _loadProductsByServer.apply(this, arguments);
685
+ }
686
+ return loadProductsByServer;
687
+ }()
688
+ /**
689
+ * 纯请求方法:通过 HTTP 接口获取商品列表(无副作用,不触发事件、不写 IndexDB)
690
+ * @param params 查询参数
691
+ * @returns 商品列表
692
+ */
693
+ )
694
+ }, {
695
+ key: "fetchProductsByHttp",
696
+ value: (function () {
697
+ var _fetchProductsByHttp = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee7(params) {
698
+ var _ref2, _ref2$category_ids, category_ids, _ref2$product_ids, product_ids, _ref2$collection, collection, customer_id, cacheId, startTime, _this$otherParams, _productsData$data2, productsData, productList, duration, _duration2, errorMessage;
699
+ return _regeneratorRuntime().wrap(function _callee7$(_context7) {
700
+ while (1) switch (_context7.prev = _context7.next) {
604
701
  case 0:
605
702
  _ref2 = params || {}, _ref2$category_ids = _ref2.category_ids, category_ids = _ref2$category_ids === void 0 ? [] : _ref2$category_ids, _ref2$product_ids = _ref2.product_ids, product_ids = _ref2$product_ids === void 0 ? [] : _ref2$product_ids, _ref2$collection = _ref2.collection, collection = _ref2$collection === void 0 ? [] : _ref2$collection, customer_id = _ref2.customer_id, cacheId = _ref2.cacheId;
606
- this.logInfo('开始从服务器加载商品列表', {
703
+ this.logInfo('fetchProductsByHttp: 开始请求', {
607
704
  categoryIdsCount: category_ids.length,
608
705
  productIdsCount: product_ids.length,
609
706
  collectionCount: Array.isArray(collection) ? collection.length : collection ? 1 : 0,
610
707
  customer_id: customer_id
611
708
  });
612
709
  startTime = Date.now();
613
- _context6.prev = 3;
614
- _context6.next = 6;
710
+ _context7.prev = 3;
711
+ _context7.next = 6;
615
712
  return this.request.post("/product/query", {
616
713
  open_bundle: 1,
617
714
  exclude_extension_type: ['product_party', 'product_event', 'product_series_event', 'product_package_ticket', 'ticket', 'event_item'],
618
715
  force_ignore_cache_flag: 1,
619
- // 获取所有详细信息
620
- with: ['category', 'collection', 'resourceRelation',
621
- // 套餐
622
- 'bundleGroup.bundleItem',
623
- // 单规格
624
- 'optionGroup.optionItem',
625
- // 组合规格
626
- 'variantGroup.variantItem'],
716
+ with: ['category', 'collection', 'resourceRelation', 'bundleGroup.bundleItem', 'optionGroup.optionItem', 'variantGroup.variantItem'],
627
717
  open_deposit: 1,
628
718
  is_append_product_description: 1,
629
719
  with_count: ['bundleGroup', 'optionGroup'],
@@ -640,93 +730,365 @@ export var ProductsModule = /*#__PURE__*/function (_BaseModule) {
640
730
  cache: undefined
641
731
  });
642
732
  case 6:
643
- productsData = _context6.sent;
733
+ productsData = _context7.sent;
644
734
  productList = (productsData === null || productsData === void 0 || (_productsData$data2 = productsData.data) === null || _productsData$data2 === void 0 ? void 0 : _productsData$data2.list) || [];
645
735
  duration = Date.now() - startTime;
646
- this.logInfo('从服务器加载商品列表成功', {
736
+ this.logInfo('fetchProductsByHttp: 请求成功', {
647
737
  productCount: productList.length,
648
738
  duration: "".concat(duration, "ms")
649
739
  });
650
-
651
- // 保存到 IndexDB
652
- _context6.next = 12;
653
- return this.saveProductsToIndexDB(productList);
654
- case 12:
655
- _context6.next = 14;
656
- return this.core.effects.emit(ProductsHooks.onProductsLoaded, productsData.data.list);
657
- case 14:
658
- return _context6.abrupt("return", productsData.data.list);
659
- case 17:
660
- _context6.prev = 17;
661
- _context6.t0 = _context6["catch"](3);
740
+ return _context7.abrupt("return", productList);
741
+ case 13:
742
+ _context7.prev = 13;
743
+ _context7.t0 = _context7["catch"](3);
662
744
  _duration2 = Date.now() - startTime;
663
- errorMessage = _context6.t0 instanceof Error ? _context6.t0.message : String(_context6.t0);
664
- console.error('[Products] 加载商品数据失败:', _context6.t0);
665
- this.logError('从服务器加载商品列表失败', {
745
+ errorMessage = _context7.t0 instanceof Error ? _context7.t0.message : String(_context7.t0);
746
+ console.error('[Products] fetchProductsByHttp 失败:', _context7.t0);
747
+ this.logError('fetchProductsByHttp: 请求失败', {
666
748
  duration: "".concat(_duration2, "ms"),
667
749
  error: errorMessage
668
750
  });
669
- return _context6.abrupt("return", []);
670
- case 24:
751
+ return _context7.abrupt("return", []);
752
+ case 20:
671
753
  case "end":
672
- return _context6.stop();
754
+ return _context7.stop();
673
755
  }
674
- }, _callee6, this, [[3, 17]]);
756
+ }, _callee7, this, [[3, 13]]);
675
757
  }));
676
- function loadProductsByServer(_x10) {
677
- return _loadProductsByServer.apply(this, arguments);
758
+ function fetchProductsByHttp(_x10) {
759
+ return _fetchProductsByHttp.apply(this, arguments);
678
760
  }
679
- return loadProductsByServer;
761
+ return fetchProductsByHttp;
762
+ }()
763
+ /**
764
+ * 加载完整商品列表通过接口(包含所有详细数据)
765
+ * 包含副作用:保存到 IndexDB + 触发 onProductsLoaded 事件
766
+ * @param params 查询参数
767
+ */
768
+ )
769
+ }, {
770
+ key: "loadProductsByServerHttp",
771
+ value: (function () {
772
+ var _loadProductsByServerHttp = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee8(params) {
773
+ var productList;
774
+ return _regeneratorRuntime().wrap(function _callee8$(_context8) {
775
+ while (1) switch (_context8.prev = _context8.next) {
776
+ case 0:
777
+ _context8.next = 2;
778
+ return this.fetchProductsByHttp(params);
779
+ case 2:
780
+ productList = _context8.sent;
781
+ if (!(productList.length > 0)) {
782
+ _context8.next = 8;
783
+ break;
784
+ }
785
+ _context8.next = 6;
786
+ return this.saveProductsToIndexDB(productList);
787
+ case 6:
788
+ _context8.next = 8;
789
+ return this.core.effects.emit(ProductsHooks.onProductsLoaded, productList);
790
+ case 8:
791
+ return _context8.abrupt("return", productList);
792
+ case 9:
793
+ case "end":
794
+ return _context8.stop();
795
+ }
796
+ }, _callee8, this);
797
+ }));
798
+ function loadProductsByServerHttp(_x11) {
799
+ return _loadProductsByServerHttp.apply(this, arguments);
800
+ }
801
+ return loadProductsByServerHttp;
680
802
  }()
681
803
  /**
682
- * 获取商品列表(从缓存)
804
+ * 获取商品列表(深拷贝,供外部安全使用)
683
805
  */
684
806
  )
685
807
  }, {
686
808
  key: "getProducts",
687
809
  value: (function () {
688
- var _getProducts = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee7() {
689
- return _regeneratorRuntime().wrap(function _callee7$(_context7) {
690
- while (1) switch (_context7.prev = _context7.next) {
810
+ var _getProducts = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee9() {
811
+ var t0, result;
812
+ return _regeneratorRuntime().wrap(function _callee9$(_context9) {
813
+ while (1) switch (_context9.prev = _context9.next) {
691
814
  case 0:
692
- return _context7.abrupt("return", cloneDeep(this.store.list));
693
- case 1:
815
+ t0 = performance.now();
816
+ result = structuredClone(this.store.list);
817
+ perfMark('ProductsModule.getProducts(structuredClone)', performance.now() - t0, {
818
+ count: result.length
819
+ });
820
+ return _context9.abrupt("return", result);
821
+ case 4:
694
822
  case "end":
695
- return _context7.stop();
823
+ return _context9.stop();
696
824
  }
697
- }, _callee7, this);
825
+ }, _callee9, this);
698
826
  }));
699
827
  function getProducts() {
700
828
  return _getProducts.apply(this, arguments);
701
829
  }
702
830
  return getProducts;
703
831
  }()
832
+ /**
833
+ * 内部获取商品列表的直接引用(无拷贝)
834
+ * 仅供内部 formatter 流程使用,因为 formatter 会创建新对象
835
+ */
836
+ )
837
+ }, {
838
+ key: "getProductsRef",
839
+ value: function getProductsRef() {
840
+ return this.store.list;
841
+ }
842
+
704
843
  /**
705
844
  * 根据ID获取单个商品(从内存缓存)
706
845
  * 使用 Map 快速查询,时间复杂度 O(1)
707
846
  */
708
- )
709
847
  }, {
710
848
  key: "getProductById",
711
849
  value: (function () {
712
- var _getProductById = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee8(id) {
850
+ var _getProductById = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee10(id) {
713
851
  var product;
714
- return _regeneratorRuntime().wrap(function _callee8$(_context8) {
715
- while (1) switch (_context8.prev = _context8.next) {
852
+ return _regeneratorRuntime().wrap(function _callee10$(_context10) {
853
+ while (1) switch (_context10.prev = _context10.next) {
716
854
  case 0:
717
855
  product = this.store.map.get(id);
718
- return _context8.abrupt("return", product ? cloneDeep(product) : undefined);
856
+ return _context10.abrupt("return", product ? structuredClone(product) : undefined);
719
857
  case 2:
720
858
  case "end":
721
- return _context8.stop();
859
+ return _context10.stop();
722
860
  }
723
- }, _callee8, this);
861
+ }, _callee10, this);
724
862
  }));
725
- function getProductById(_x11) {
863
+ function getProductById(_x12) {
726
864
  return _getProductById.apply(this, arguments);
727
865
  }
728
866
  return getProductById;
729
867
  }()
868
+ /**
869
+ * 根据 ID 列表删除商品(用于 pubsub 同步删除场景)
870
+ * 同时更新 store.list、store.map、IndexDB 和价格缓存
871
+ */
872
+ )
873
+ }, {
874
+ key: "removeProductsByIds",
875
+ value: (function () {
876
+ var _removeProductsByIds = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee11(ids) {
877
+ var idSet, _iterator, _step, _id, _iterator2, _step2, id, errorMessage, _iterator3, _step3, _step3$value, dateKey, cachedProducts;
878
+ return _regeneratorRuntime().wrap(function _callee11$(_context11) {
879
+ while (1) switch (_context11.prev = _context11.next) {
880
+ case 0:
881
+ idSet = new Set(ids);
882
+ this.logInfo('removeProductsByIds', {
883
+ ids: ids,
884
+ count: ids.length
885
+ });
886
+ this.store.list = this.store.list.filter(function (p) {
887
+ return !idSet.has(p.id);
888
+ });
889
+ _iterator = _createForOfIteratorHelper(ids);
890
+ try {
891
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
892
+ _id = _step.value;
893
+ this.store.map.delete(_id);
894
+ }
895
+ } catch (err) {
896
+ _iterator.e(err);
897
+ } finally {
898
+ _iterator.f();
899
+ }
900
+ if (!this.dbManager) {
901
+ _context11.next = 30;
902
+ break;
903
+ }
904
+ _context11.prev = 6;
905
+ _iterator2 = _createForOfIteratorHelper(ids);
906
+ _context11.prev = 8;
907
+ _iterator2.s();
908
+ case 10:
909
+ if ((_step2 = _iterator2.n()).done) {
910
+ _context11.next = 16;
911
+ break;
912
+ }
913
+ id = _step2.value;
914
+ _context11.next = 14;
915
+ return this.dbManager.delete(INDEXDB_STORE_NAME, id);
916
+ case 14:
917
+ _context11.next = 10;
918
+ break;
919
+ case 16:
920
+ _context11.next = 21;
921
+ break;
922
+ case 18:
923
+ _context11.prev = 18;
924
+ _context11.t0 = _context11["catch"](8);
925
+ _iterator2.e(_context11.t0);
926
+ case 21:
927
+ _context11.prev = 21;
928
+ _iterator2.f();
929
+ return _context11.finish(21);
930
+ case 24:
931
+ _context11.next = 30;
932
+ break;
933
+ case 26:
934
+ _context11.prev = 26;
935
+ _context11.t1 = _context11["catch"](6);
936
+ errorMessage = _context11.t1 instanceof Error ? _context11.t1.message : String(_context11.t1);
937
+ this.logError('removeProductsByIds: IndexDB 删除失败', {
938
+ ids: ids,
939
+ error: errorMessage
940
+ });
941
+ case 30:
942
+ _iterator3 = _createForOfIteratorHelper(this.productsPriceCache.entries());
943
+ try {
944
+ for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
945
+ _step3$value = _slicedToArray(_step3.value, 2), dateKey = _step3$value[0], cachedProducts = _step3$value[1];
946
+ this.productsPriceCache.set(dateKey, cachedProducts.filter(function (p) {
947
+ return !idSet.has(p.id);
948
+ }));
949
+ }
950
+ } catch (err) {
951
+ _iterator3.e(err);
952
+ } finally {
953
+ _iterator3.f();
954
+ }
955
+ this.core.effects.emit(ProductsHooks.onProductsChanged, this.store.list);
956
+ this.logInfo('removeProductsByIds 完成', {
957
+ remaining: this.store.list.length
958
+ });
959
+ case 34:
960
+ case "end":
961
+ return _context11.stop();
962
+ }
963
+ }, _callee11, this, [[6, 26], [8, 18, 21, 24]]);
964
+ }));
965
+ function removeProductsByIds(_x13) {
966
+ return _removeProductsByIds.apply(this, arguments);
967
+ }
968
+ return removeProductsByIds;
969
+ }()
970
+ /**
971
+ * 重新从服务器加载全量商品列表并更新本地 store
972
+ * 用于 pubsub 同步 create / update / batch_update 场景
973
+ */
974
+ )
975
+ }, {
976
+ key: "refreshProducts",
977
+ value: (function () {
978
+ var _refreshProducts = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee12() {
979
+ var tTotal, products;
980
+ return _regeneratorRuntime().wrap(function _callee12$(_context12) {
981
+ while (1) switch (_context12.prev = _context12.next) {
982
+ case 0:
983
+ tTotal = performance.now();
984
+ this.logInfo('refreshProducts 开始');
985
+ _context12.next = 4;
986
+ return this.loadProductsByServer();
987
+ case 4:
988
+ products = _context12.sent;
989
+ if (products && products.length > 0) {
990
+ // 服务器返回的数据已经是全新的,无需 cloneDeep
991
+ this.store.list = products;
992
+ this.syncProductsMap();
993
+ this.core.effects.emit(ProductsHooks.onProductsChanged, this.store.list);
994
+ this.logInfo('refreshProducts 完成', {
995
+ productCount: products.length
996
+ });
997
+ } else {
998
+ this.logWarning('refreshProducts: 服务器未返回数据');
999
+ }
1000
+ perfMark('refreshProducts', performance.now() - tTotal, {
1001
+ count: this.store.list.length
1002
+ });
1003
+ return _context12.abrupt("return", this.store.list);
1004
+ case 8:
1005
+ case "end":
1006
+ return _context12.stop();
1007
+ }
1008
+ }, _callee12, this);
1009
+ }));
1010
+ function refreshProducts() {
1011
+ return _refreshProducts.apply(this, arguments);
1012
+ }
1013
+ return refreshProducts;
1014
+ }()
1015
+ /**
1016
+ * 局部更新指定商品的报价单价格
1017
+ * 遍历所有已缓存的日期,为目标商品重新获取价格并覆盖到缓存中
1018
+ */
1019
+ )
1020
+ }, {
1021
+ key: "updateProductPriceByIds",
1022
+ value: (function () {
1023
+ var _updateProductPriceByIds = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee13(ids) {
1024
+ var _iterator4, _step4, _step4$value, dateKey, cachedProducts, priceData, updatedProducts, errorMessage;
1025
+ return _regeneratorRuntime().wrap(function _callee13$(_context13) {
1026
+ while (1) switch (_context13.prev = _context13.next) {
1027
+ case 0:
1028
+ this.logInfo('updateProductPriceByIds', {
1029
+ ids: ids
1030
+ });
1031
+ _iterator4 = _createForOfIteratorHelper(this.productsPriceCache.entries());
1032
+ _context13.prev = 2;
1033
+ _iterator4.s();
1034
+ case 4:
1035
+ if ((_step4 = _iterator4.n()).done) {
1036
+ _context13.next = 19;
1037
+ break;
1038
+ }
1039
+ _step4$value = _slicedToArray(_step4.value, 2), dateKey = _step4$value[0], cachedProducts = _step4$value[1];
1040
+ _context13.prev = 6;
1041
+ _context13.next = 9;
1042
+ return this.loadProductsPrice({
1043
+ ids: ids,
1044
+ schedule_date: dateKey
1045
+ });
1046
+ case 9:
1047
+ priceData = _context13.sent;
1048
+ if (priceData && priceData.length > 0) {
1049
+ updatedProducts = applyPriceDataToProducts(cachedProducts, priceData);
1050
+ this.productsPriceCache.set(dateKey, updatedProducts);
1051
+ this.logInfo('updateProductPriceByIds: 缓存已更新', {
1052
+ dateKey: dateKey,
1053
+ priceDataCount: priceData.length
1054
+ });
1055
+ }
1056
+ _context13.next = 17;
1057
+ break;
1058
+ case 13:
1059
+ _context13.prev = 13;
1060
+ _context13.t0 = _context13["catch"](6);
1061
+ errorMessage = _context13.t0 instanceof Error ? _context13.t0.message : String(_context13.t0);
1062
+ this.logError('updateProductPriceByIds: 失败', {
1063
+ dateKey: dateKey,
1064
+ ids: ids,
1065
+ error: errorMessage
1066
+ });
1067
+ case 17:
1068
+ _context13.next = 4;
1069
+ break;
1070
+ case 19:
1071
+ _context13.next = 24;
1072
+ break;
1073
+ case 21:
1074
+ _context13.prev = 21;
1075
+ _context13.t1 = _context13["catch"](2);
1076
+ _iterator4.e(_context13.t1);
1077
+ case 24:
1078
+ _context13.prev = 24;
1079
+ _iterator4.f();
1080
+ return _context13.finish(24);
1081
+ case 27:
1082
+ case "end":
1083
+ return _context13.stop();
1084
+ }
1085
+ }, _callee13, this, [[2, 21, 24, 27], [6, 13]]);
1086
+ }));
1087
+ function updateProductPriceByIds(_x14) {
1088
+ return _updateProductPriceByIds.apply(this, arguments);
1089
+ }
1090
+ return updateProductPriceByIds;
1091
+ }()
730
1092
  /**
731
1093
  * 清空缓存
732
1094
  */
@@ -734,10 +1096,10 @@ export var ProductsModule = /*#__PURE__*/function (_BaseModule) {
734
1096
  }, {
735
1097
  key: "clear",
736
1098
  value: (function () {
737
- var _clear = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee9() {
1099
+ var _clear = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee14() {
738
1100
  var errorMessage;
739
- return _regeneratorRuntime().wrap(function _callee9$(_context9) {
740
- while (1) switch (_context9.prev = _context9.next) {
1101
+ return _regeneratorRuntime().wrap(function _callee14$(_context14) {
1102
+ while (1) switch (_context14.prev = _context14.next) {
741
1103
  case 0:
742
1104
  this.logInfo('开始清空缓存', {
743
1105
  currentProductCount: this.store.list.length,
@@ -748,22 +1110,22 @@ export var ProductsModule = /*#__PURE__*/function (_BaseModule) {
748
1110
 
749
1111
  // 同时清空 IndexDB 中的所有数据(包括商品和元数据)
750
1112
  if (!this.dbManager) {
751
- _context9.next = 16;
1113
+ _context14.next = 16;
752
1114
  break;
753
1115
  }
754
- _context9.prev = 4;
755
- _context9.next = 7;
1116
+ _context14.prev = 4;
1117
+ _context14.next = 7;
756
1118
  return this.dbManager.clear(INDEXDB_STORE_NAME);
757
1119
  case 7:
758
1120
  console.log('[Products] IndexDB 缓存已清空');
759
1121
  this.logInfo('IndexDB 缓存已清空');
760
- _context9.next = 16;
1122
+ _context14.next = 16;
761
1123
  break;
762
1124
  case 11:
763
- _context9.prev = 11;
764
- _context9.t0 = _context9["catch"](4);
765
- errorMessage = _context9.t0 instanceof Error ? _context9.t0.message : String(_context9.t0);
766
- console.error('[Products] 清空 IndexDB 缓存失败:', _context9.t0);
1125
+ _context14.prev = 11;
1126
+ _context14.t0 = _context14["catch"](4);
1127
+ errorMessage = _context14.t0 instanceof Error ? _context14.t0.message : String(_context14.t0);
1128
+ console.error('[Products] 清空 IndexDB 缓存失败:', _context14.t0);
767
1129
  this.logError('清空 IndexDB 缓存失败', {
768
1130
  error: errorMessage
769
1131
  });
@@ -772,9 +1134,9 @@ export var ProductsModule = /*#__PURE__*/function (_BaseModule) {
772
1134
  this.logInfo('缓存清空完成');
773
1135
  case 18:
774
1136
  case "end":
775
- return _context9.stop();
1137
+ return _context14.stop();
776
1138
  }
777
- }, _callee9, this, [[4, 11]]);
1139
+ }, _callee14, this, [[4, 11]]);
778
1140
  }));
779
1141
  function clear() {
780
1142
  return _clear.apply(this, arguments);
@@ -789,41 +1151,45 @@ export var ProductsModule = /*#__PURE__*/function (_BaseModule) {
789
1151
  }, {
790
1152
  key: "loadProductsFromIndexDB",
791
1153
  value: (function () {
792
- var _loadProductsFromIndexDB = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee10() {
793
- var _products$length, products, errorMessage;
794
- return _regeneratorRuntime().wrap(function _callee10$(_context10) {
795
- while (1) switch (_context10.prev = _context10.next) {
1154
+ var _loadProductsFromIndexDB = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee15() {
1155
+ var _products$length, _products$length2, t0, products, errorMessage;
1156
+ return _regeneratorRuntime().wrap(function _callee15$(_context15) {
1157
+ while (1) switch (_context15.prev = _context15.next) {
796
1158
  case 0:
797
1159
  if (this.dbManager) {
798
- _context10.next = 3;
1160
+ _context15.next = 3;
799
1161
  break;
800
1162
  }
801
1163
  this.logWarning('loadProductsFromIndexDB: dbManager 不可用');
802
- return _context10.abrupt("return", []);
1164
+ return _context15.abrupt("return", []);
803
1165
  case 3:
804
- _context10.prev = 3;
805
- _context10.next = 6;
1166
+ _context15.prev = 3;
1167
+ t0 = performance.now();
1168
+ _context15.next = 7;
806
1169
  return this.dbManager.getAll(INDEXDB_STORE_NAME);
807
- case 6:
808
- products = _context10.sent;
1170
+ case 7:
1171
+ products = _context15.sent;
1172
+ perfMark('loadProductsFromIndexDB', performance.now() - t0, {
1173
+ count: (_products$length = products === null || products === void 0 ? void 0 : products.length) !== null && _products$length !== void 0 ? _products$length : 0
1174
+ });
809
1175
  this.logInfo('从 IndexDB 加载商品数据', {
810
- productCount: (_products$length = products === null || products === void 0 ? void 0 : products.length) !== null && _products$length !== void 0 ? _products$length : 0
1176
+ productCount: (_products$length2 = products === null || products === void 0 ? void 0 : products.length) !== null && _products$length2 !== void 0 ? _products$length2 : 0
811
1177
  });
812
- return _context10.abrupt("return", products || []);
813
- case 11:
814
- _context10.prev = 11;
815
- _context10.t0 = _context10["catch"](3);
816
- errorMessage = _context10.t0 instanceof Error ? _context10.t0.message : String(_context10.t0);
817
- console.error('[Products] 从 IndexDB 读取数据失败:', _context10.t0);
1178
+ return _context15.abrupt("return", products || []);
1179
+ case 13:
1180
+ _context15.prev = 13;
1181
+ _context15.t0 = _context15["catch"](3);
1182
+ errorMessage = _context15.t0 instanceof Error ? _context15.t0.message : String(_context15.t0);
1183
+ console.error('[Products] 从 IndexDB 读取数据失败:', _context15.t0);
818
1184
  this.logError('从 IndexDB 读取数据失败', {
819
1185
  error: errorMessage
820
1186
  });
821
- return _context10.abrupt("return", []);
822
- case 17:
1187
+ return _context15.abrupt("return", []);
1188
+ case 19:
823
1189
  case "end":
824
- return _context10.stop();
1190
+ return _context15.stop();
825
1191
  }
826
- }, _callee10, this, [[3, 11]]);
1192
+ }, _callee15, this, [[3, 13]]);
827
1193
  }));
828
1194
  function loadProductsFromIndexDB() {
829
1195
  return _loadProductsFromIndexDB.apply(this, arguments);
@@ -838,55 +1204,54 @@ export var ProductsModule = /*#__PURE__*/function (_BaseModule) {
838
1204
  }, {
839
1205
  key: "saveProductsToIndexDB",
840
1206
  value: (function () {
841
- var _saveProductsToIndexDB = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee11(products) {
842
- var _this2 = this;
843
- var savePromises, errorMessage;
844
- return _regeneratorRuntime().wrap(function _callee11$(_context11) {
845
- while (1) switch (_context11.prev = _context11.next) {
1207
+ var _saveProductsToIndexDB = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee16(products) {
1208
+ var t0, errorMessage;
1209
+ return _regeneratorRuntime().wrap(function _callee16$(_context16) {
1210
+ while (1) switch (_context16.prev = _context16.next) {
846
1211
  case 0:
847
1212
  if (this.dbManager) {
848
- _context11.next = 3;
1213
+ _context16.next = 3;
849
1214
  break;
850
1215
  }
851
1216
  this.logWarning('saveProductsToIndexDB: dbManager 不可用');
852
- return _context11.abrupt("return");
1217
+ return _context16.abrupt("return");
853
1218
  case 3:
854
1219
  this.logInfo('开始保存商品数据到 IndexDB', {
855
1220
  productCount: products.length
856
1221
  });
857
- _context11.prev = 4;
858
- _context11.next = 7;
1222
+ _context16.prev = 4;
1223
+ t0 = performance.now();
1224
+ _context16.next = 8;
859
1225
  return this.dbManager.clear(INDEXDB_STORE_NAME);
860
- case 7:
861
- // 逐个保存商品(每个商品是独立的记录)
862
- savePromises = products.map(function (product) {
863
- return _this2.dbManager.add(INDEXDB_STORE_NAME, product);
864
- });
865
- _context11.next = 10;
866
- return Promise.all(savePromises);
1226
+ case 8:
1227
+ _context16.next = 10;
1228
+ return this.dbManager.bulkAdd(INDEXDB_STORE_NAME, products);
867
1229
  case 10:
1230
+ perfMark('saveProductsToIndexDB', performance.now() - t0, {
1231
+ count: products.length
1232
+ });
868
1233
  console.log("[Products] \u5DF2\u5C06 ".concat(products.length, " \u4E2A\u5546\u54C1\u5E73\u94FA\u4FDD\u5B58\u5230 IndexDB"));
869
1234
  this.logInfo('商品数据已保存到 IndexDB', {
870
1235
  productCount: products.length
871
1236
  });
872
- _context11.next = 19;
1237
+ _context16.next = 20;
873
1238
  break;
874
- case 14:
875
- _context11.prev = 14;
876
- _context11.t0 = _context11["catch"](4);
877
- errorMessage = _context11.t0 instanceof Error ? _context11.t0.message : String(_context11.t0);
878
- console.error('[Products] 保存数据到 IndexDB 失败:', _context11.t0);
1239
+ case 15:
1240
+ _context16.prev = 15;
1241
+ _context16.t0 = _context16["catch"](4);
1242
+ errorMessage = _context16.t0 instanceof Error ? _context16.t0.message : String(_context16.t0);
1243
+ console.error('[Products] 保存数据到 IndexDB 失败:', _context16.t0);
879
1244
  this.logError('保存数据到 IndexDB 失败', {
880
1245
  productCount: products.length,
881
1246
  error: errorMessage
882
1247
  });
883
- case 19:
1248
+ case 20:
884
1249
  case "end":
885
- return _context11.stop();
1250
+ return _context16.stop();
886
1251
  }
887
- }, _callee11, this, [[4, 14]]);
1252
+ }, _callee16, this, [[4, 15]]);
888
1253
  }));
889
- function saveProductsToIndexDB(_x12) {
1254
+ function saveProductsToIndexDB(_x15) {
890
1255
  return _saveProductsToIndexDB.apply(this, arguments);
891
1256
  }
892
1257
  return saveProductsToIndexDB;
@@ -900,20 +1265,23 @@ export var ProductsModule = /*#__PURE__*/function (_BaseModule) {
900
1265
  }, {
901
1266
  key: "syncProductsMap",
902
1267
  value: function syncProductsMap() {
1268
+ var t0 = performance.now();
903
1269
  this.store.map.clear();
904
- var _iterator = _createForOfIteratorHelper(this.store.list),
905
- _step;
1270
+ var _iterator5 = _createForOfIteratorHelper(this.store.list),
1271
+ _step5;
906
1272
  try {
907
- for (_iterator.s(); !(_step = _iterator.n()).done;) {
908
- var product = _step.value;
1273
+ for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
1274
+ var product = _step5.value;
909
1275
  this.store.map.set(product.id, product);
910
1276
  }
911
1277
  } catch (err) {
912
- _iterator.e(err);
1278
+ _iterator5.e(err);
913
1279
  } finally {
914
- _iterator.f();
1280
+ _iterator5.f();
915
1281
  }
916
- console.log("[Products] Map \u7F13\u5B58\u5DF2\u540C\u6B65\uFF0C\u5171 ".concat(this.store.map.size, " \u4E2A\u5546\u54C1"));
1282
+ perfMark('syncProductsMap', performance.now() - t0, {
1283
+ count: this.store.map.size
1284
+ });
917
1285
  }
918
1286
 
919
1287
  /**
@@ -923,94 +1291,862 @@ export var ProductsModule = /*#__PURE__*/function (_BaseModule) {
923
1291
  }, {
924
1292
  key: "preload",
925
1293
  value: (function () {
926
- var _preload = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee12() {
927
- var startTime, cachedData, duration, errorMessage, products, _duration3, _duration4;
928
- return _regeneratorRuntime().wrap(function _callee12$(_context12) {
929
- while (1) switch (_context12.prev = _context12.next) {
1294
+ var _preload = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee17() {
1295
+ var _products$length3;
1296
+ var tTotal, _cachedData$length, tIndexDB, cachedData, tSync, errorMessage, tServer, products, _tSync;
1297
+ return _regeneratorRuntime().wrap(function _callee17$(_context17) {
1298
+ while (1) switch (_context17.prev = _context17.next) {
930
1299
  case 0:
931
1300
  console.log('[Products] 开始预加载数据...');
932
- startTime = Date.now();
1301
+ tTotal = performance.now();
933
1302
  this.logInfo('开始预加载数据');
934
- _context12.prev = 3;
935
- _context12.next = 6;
1303
+ _context17.prev = 3;
1304
+ tIndexDB = performance.now();
1305
+ _context17.next = 7;
936
1306
  return this.loadProductsFromIndexDB();
937
- case 6:
938
- cachedData = _context12.sent;
1307
+ case 7:
1308
+ cachedData = _context17.sent;
1309
+ perfMark('preload.loadFromIndexDB', performance.now() - tIndexDB, {
1310
+ count: (_cachedData$length = cachedData === null || cachedData === void 0 ? void 0 : cachedData.length) !== null && _cachedData$length !== void 0 ? _cachedData$length : 0
1311
+ });
939
1312
  if (!(cachedData && cachedData.length > 0)) {
940
- _context12.next = 15;
1313
+ _context17.next = 19;
941
1314
  break;
942
1315
  }
943
1316
  console.log("[Products] \u4ECE IndexDB \u52A0\u8F7D\u4E86 ".concat(cachedData.length, " \u4E2A\u5546\u54C1"));
944
- // 将缓存数据放入 list
945
- this.store.list = cloneDeep(cachedData);
946
- // 同步更新 Map 缓存
1317
+ // IndexDB 反序列化的数据已经是全新的,无需 cloneDeep
1318
+ this.store.list = cachedData;
1319
+ tSync = performance.now();
947
1320
  this.syncProductsMap();
1321
+ perfMark('preload.syncProductsMap', performance.now() - tSync, {
1322
+ count: cachedData.length
1323
+ });
948
1324
  this.core.effects.emit(ProductsHooks.onProductsChanged, this.store.list);
949
- duration = Date.now() - startTime;
1325
+ perfMark('preload(IndexDB)', performance.now() - tTotal, {
1326
+ count: cachedData.length,
1327
+ source: 'IndexDB'
1328
+ });
950
1329
  this.logInfo('预加载完成(从 IndexDB)', {
951
1330
  productCount: cachedData.length,
952
- duration: "".concat(duration, "ms"),
1331
+ duration: "".concat(Math.round(performance.now() - tTotal), "ms"),
953
1332
  source: 'IndexDB'
954
1333
  });
955
- return _context12.abrupt("return");
956
- case 15:
1334
+ return _context17.abrupt("return");
1335
+ case 19:
957
1336
  console.log('[Products] IndexDB 中没有缓存数据,从服务器加载...');
958
1337
  this.logInfo('IndexDB 中没有缓存数据,准备从服务器加载');
959
- _context12.next = 24;
1338
+ _context17.next = 28;
960
1339
  break;
961
- case 19:
962
- _context12.prev = 19;
963
- _context12.t0 = _context12["catch"](3);
964
- errorMessage = _context12.t0 instanceof Error ? _context12.t0.message : String(_context12.t0);
965
- console.warn('[Products] 从 IndexDB 加载数据失败:', _context12.t0);
1340
+ case 23:
1341
+ _context17.prev = 23;
1342
+ _context17.t0 = _context17["catch"](3);
1343
+ errorMessage = _context17.t0 instanceof Error ? _context17.t0.message : String(_context17.t0);
1344
+ console.warn('[Products] 从 IndexDB 加载数据失败:', _context17.t0);
966
1345
  this.logWarning('从 IndexDB 加载数据失败,准备从服务器加载', {
967
1346
  error: errorMessage
968
1347
  });
969
- case 24:
970
- _context12.next = 26;
1348
+ case 28:
1349
+ tServer = performance.now();
1350
+ _context17.next = 31;
971
1351
  return this.loadProductsByServer();
972
- case 26:
973
- products = _context12.sent;
1352
+ case 31:
1353
+ products = _context17.sent;
1354
+ perfMark('preload.loadFromServer', performance.now() - tServer, {
1355
+ count: (_products$length3 = products === null || products === void 0 ? void 0 : products.length) !== null && _products$length3 !== void 0 ? _products$length3 : 0
1356
+ });
1357
+ if (products && products.length > 0) {
1358
+ // 服务器返回的数据已经是全新的,无需 cloneDeep
1359
+ this.store.list = products;
1360
+ _tSync = performance.now();
1361
+ this.syncProductsMap();
1362
+ perfMark('preload.syncProductsMap', performance.now() - _tSync, {
1363
+ count: products.length
1364
+ });
1365
+ this.core.effects.emit(ProductsHooks.onProductsChanged, this.store.list);
1366
+ perfMark('preload(Server)', performance.now() - tTotal, {
1367
+ count: products.length,
1368
+ source: 'Server'
1369
+ });
1370
+ this.logInfo('预加载完成(从服务器)', {
1371
+ productCount: products.length,
1372
+ duration: "".concat(Math.round(performance.now() - tTotal), "ms"),
1373
+ source: 'Server'
1374
+ });
1375
+ } else {
1376
+ perfMark('preload(empty)', performance.now() - tTotal, {
1377
+ source: 'empty'
1378
+ });
1379
+ this.logWarning('预加载完成但未获取到数据', {
1380
+ duration: "".concat(Math.round(performance.now() - tTotal), "ms")
1381
+ });
1382
+ }
1383
+ case 34:
1384
+ case "end":
1385
+ return _context17.stop();
1386
+ }
1387
+ }, _callee17, this, [[3, 23]]);
1388
+ }));
1389
+ function preload() {
1390
+ return _preload.apply(this, arguments);
1391
+ }
1392
+ return preload;
1393
+ }() // =============================================
1394
+ // 商品数据同步(pubsub)
1395
+ // =============================================
1396
+ /**
1397
+ * 初始化 ProductDataSource 实例
1398
+ * 与 pubsub 订阅和数据获取分开,仅负责创建实例
1399
+ */
1400
+ )
1401
+ }, {
1402
+ key: "initProductDataSource",
1403
+ value: function initProductDataSource() {
1404
+ var _serverOptions;
1405
+ var ProductDataSourceClass = (_serverOptions = this.core.serverOptions) === null || _serverOptions === void 0 || (_serverOptions = _serverOptions.All_DATA_SOURCES) === null || _serverOptions === void 0 ? void 0 : _serverOptions.ProductDataSource;
1406
+ if (!ProductDataSourceClass) {
1407
+ this.logWarning('initProductDataSource: ProductDataSource 不可用');
1408
+ return;
1409
+ }
1410
+ this.productDataSource = new ProductDataSourceClass();
1411
+ this.logInfo('ProductDataSource 实例已创建');
1412
+ }
1413
+
1414
+ /**
1415
+ * 初始化 pubsub 订阅,监听管理后台商品变更
1416
+ * 仅负责订阅 product / product_quotation 频道,消息通过防抖合并后批量处理
1417
+ * 数据获取由 loadProductsByServer 单独负责
1418
+ */
1419
+ }, {
1420
+ key: "setupProductSync",
1421
+ value: function setupProductSync() {
1422
+ var _this2 = this;
1423
+ if (!this.productDataSource) {
1424
+ this.logWarning('setupProductSync: ProductDataSource 不可用,跳过同步初始化');
1425
+ return;
1426
+ }
1427
+ var createHandler = function createHandler(channelKey) {
1428
+ return function (message) {
1429
+ var data = (message === null || message === void 0 ? void 0 : message.data) || message;
1430
+ if (!data) return;
1431
+ console.log("[ProductsModule] \u6536\u5230\u540C\u6B65\u6D88\u606F [".concat(channelKey, "]:"), data);
1432
+ _this2.logInfo('收到同步消息', {
1433
+ channelKey: channelKey,
1434
+ action: data.action,
1435
+ id: data.id,
1436
+ action_filed: data.action_filed
1437
+ });
1438
+ _this2.pendingSyncMessages.push(_objectSpread(_objectSpread({}, data), {}, {
1439
+ _channelKey: channelKey
1440
+ }));
1441
+ if (_this2.syncTimer) {
1442
+ clearTimeout(_this2.syncTimer);
1443
+ }
1444
+ _this2.syncTimer = setTimeout(function () {
1445
+ _this2.processProductSyncMessages();
1446
+ }, PRODUCT_SYNC_DEBOUNCE_MS);
1447
+ };
1448
+ };
1449
+ this.productDataSource.run({
1450
+ pubsub: {
1451
+ callback: function callback(res) {
1452
+ console.log('sse_products_callback', res);
1453
+ _this2.logInfo('sse_products_callback: 收到同步消息', {
1454
+ data: res === null || res === void 0 ? void 0 : res.data
1455
+ });
1456
+ if (!(res !== null && res !== void 0 && res.data)) return;
1457
+ var data = res.data;
1458
+ var channelKey = data.module || 'product';
1459
+ createHandler(channelKey)(data);
1460
+ }
1461
+ }
1462
+ }).catch(function (err) {
1463
+ _this2.logError('setupProductSync: DataSource run 出错', {
1464
+ error: err instanceof Error ? err.message : String(err)
1465
+ });
1466
+ });
1467
+ this.logInfo('setupProductSync: pubsub 订阅已建立');
1468
+ }
1469
+
1470
+ /**
1471
+ * 处理防抖后的同步消息批次
1472
+ *
1473
+ * product 模块:
1474
+ * - operation === 'delete' → 本地删除
1475
+ * - 有 body(无 price change_types) → body 完整数据直接覆盖本地
1476
+ * - change_types 包含 price → SSE 增量拉取 + 刷新报价单价格缓存
1477
+ * - change_types 仅 stock → 跳过(暂不响应)
1478
+ *
1479
+ * product_collection / product_category / product_quotation:
1480
+ * - 按 relation_product_ids SSE 拉取受影响商品
1481
+ * - product_quotation 额外刷新报价单价格缓存
1482
+ *
1483
+ * 处理完成后 emit onProductsSyncCompleted 通知 Server 层
1484
+ */
1485
+ }, {
1486
+ key: "processProductSyncMessages",
1487
+ value: (function () {
1488
+ var _processProductSyncMessages = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee18() {
1489
+ var messages, deleteIds, bodyUpdates, sseRefreshIds, priceRefreshIds, _iterator6, _step6, msg, channelKey, _msg$change_types, _msg$change_types2, _msg$ids2, _msg$ids, ids, bodyId, _msg$relation_product, uniqueDeleteIds, uniqueSSEIds, uniquePriceIds, freshProducts, sseHandledSet, remainingPriceIds;
1490
+ return _regeneratorRuntime().wrap(function _callee18$(_context18) {
1491
+ while (1) switch (_context18.prev = _context18.next) {
1492
+ case 0:
1493
+ messages = _toConsumableArray(this.pendingSyncMessages);
1494
+ this.pendingSyncMessages = [];
1495
+ if (!(messages.length === 0)) {
1496
+ _context18.next = 4;
1497
+ break;
1498
+ }
1499
+ return _context18.abrupt("return");
1500
+ case 4:
1501
+ this.logInfo('processProductSyncMessages: 开始处理', {
1502
+ count: messages.length
1503
+ });
1504
+ deleteIds = [];
1505
+ bodyUpdates = new Map();
1506
+ sseRefreshIds = [];
1507
+ priceRefreshIds = [];
1508
+ _iterator6 = _createForOfIteratorHelper(messages);
1509
+ _context18.prev = 10;
1510
+ _iterator6.s();
1511
+ case 12:
1512
+ if ((_step6 = _iterator6.n()).done) {
1513
+ _context18.next = 37;
1514
+ break;
1515
+ }
1516
+ msg = _step6.value;
1517
+ channelKey = msg._channelKey || msg.module || 'product';
1518
+ if (!(channelKey === 'product')) {
1519
+ _context18.next = 34;
1520
+ break;
1521
+ }
1522
+ if (!(msg.operation === 'delete' || msg.action === 'delete')) {
1523
+ _context18.next = 19;
1524
+ break;
1525
+ }
1526
+ if ((_msg$ids = msg.ids) !== null && _msg$ids !== void 0 && _msg$ids.length) deleteIds.push.apply(deleteIds, _toConsumableArray(msg.ids));else if (msg.id) deleteIds.push(msg.id);
1527
+ return _context18.abrupt("continue", 35);
1528
+ case 19:
1529
+ if (!((_msg$change_types = msg.change_types) !== null && _msg$change_types !== void 0 && _msg$change_types.length && msg.change_types.every(function (t) {
1530
+ return t === 'stock';
1531
+ }))) {
1532
+ _context18.next = 22;
1533
+ break;
1534
+ }
1535
+ this.logInfo('跳过仅库存变更', {
1536
+ ids: msg.ids
1537
+ });
1538
+ return _context18.abrupt("continue", 35);
1539
+ case 22:
1540
+ if (!((_msg$change_types2 = msg.change_types) !== null && _msg$change_types2 !== void 0 && _msg$change_types2.includes('price'))) {
1541
+ _context18.next = 27;
1542
+ break;
1543
+ }
1544
+ ids = msg.ids || (msg.id ? [msg.id] : []);
1545
+ sseRefreshIds.push.apply(sseRefreshIds, _toConsumableArray(ids));
1546
+ priceRefreshIds.push.apply(priceRefreshIds, _toConsumableArray(ids));
1547
+ return _context18.abrupt("continue", 35);
1548
+ case 27:
1549
+ if (!msg.body) {
1550
+ _context18.next = 31;
1551
+ break;
1552
+ }
1553
+ bodyId = msg.body.id || msg.id;
1554
+ if (bodyId) bodyUpdates.set(bodyId, msg.body);
1555
+ return _context18.abrupt("continue", 35);
1556
+ case 31:
1557
+ // 5. 其他情况(有 ids 无 body 无 change_types)→ SSE 拉取
1558
+ if ((_msg$ids2 = msg.ids) !== null && _msg$ids2 !== void 0 && _msg$ids2.length) {
1559
+ sseRefreshIds.push.apply(sseRefreshIds, _toConsumableArray(msg.ids));
1560
+ } else if (msg.id) {
1561
+ sseRefreshIds.push(msg.id);
1562
+ }
1563
+ _context18.next = 35;
1564
+ break;
1565
+ case 34:
1566
+ if (['product_collection', 'product_category', 'product_quotation'].includes(channelKey)) {
1567
+ if ((_msg$relation_product = msg.relation_product_ids) !== null && _msg$relation_product !== void 0 && _msg$relation_product.length) {
1568
+ sseRefreshIds.push.apply(sseRefreshIds, _toConsumableArray(msg.relation_product_ids));
1569
+ if (channelKey === 'product_quotation') {
1570
+ priceRefreshIds.push.apply(priceRefreshIds, _toConsumableArray(msg.relation_product_ids));
1571
+ }
1572
+ }
1573
+ }
1574
+ case 35:
1575
+ _context18.next = 12;
1576
+ break;
1577
+ case 37:
1578
+ _context18.next = 42;
1579
+ break;
1580
+ case 39:
1581
+ _context18.prev = 39;
1582
+ _context18.t0 = _context18["catch"](10);
1583
+ _iterator6.e(_context18.t0);
1584
+ case 42:
1585
+ _context18.prev = 42;
1586
+ _iterator6.f();
1587
+ return _context18.finish(42);
1588
+ case 45:
1589
+ uniqueDeleteIds = _toConsumableArray(new Set(deleteIds));
1590
+ uniqueSSEIds = _toConsumableArray(new Set(sseRefreshIds));
1591
+ uniquePriceIds = _toConsumableArray(new Set(priceRefreshIds)); // 1. 处理删除
1592
+ if (!(uniqueDeleteIds.length > 0)) {
1593
+ _context18.next = 51;
1594
+ break;
1595
+ }
1596
+ _context18.next = 51;
1597
+ return this.removeProductsByIds(uniqueDeleteIds);
1598
+ case 51:
1599
+ if (!(bodyUpdates.size > 0)) {
1600
+ _context18.next = 54;
1601
+ break;
1602
+ }
1603
+ _context18.next = 54;
1604
+ return this.applyBodyUpdatesToStore(bodyUpdates);
1605
+ case 54:
1606
+ if (!(uniqueSSEIds.length > 0)) {
1607
+ _context18.next = 64;
1608
+ break;
1609
+ }
1610
+ _context18.next = 57;
1611
+ return this.fetchProductsBySSE(uniqueSSEIds);
1612
+ case 57:
1613
+ freshProducts = _context18.sent;
1614
+ if (!(freshProducts.length > 0)) {
1615
+ _context18.next = 63;
1616
+ break;
1617
+ }
1618
+ _context18.next = 61;
1619
+ return this.mergeProductsToStore(freshProducts);
1620
+ case 61:
1621
+ _context18.next = 63;
1622
+ return this.updatePriceCacheForProducts(freshProducts);
1623
+ case 63:
1624
+ this.logInfo('processProductSyncMessages: SSE 增量更新完成', {
1625
+ requestedCount: uniqueSSEIds.length,
1626
+ receivedCount: freshProducts.length
1627
+ });
1628
+ case 64:
1629
+ // 4. 处理报价单价格刷新(排除已被第3步 SSE 处理过的 id,避免重复请求)
1630
+ sseHandledSet = new Set(uniqueSSEIds);
1631
+ remainingPriceIds = uniquePriceIds.filter(function (id) {
1632
+ return !sseHandledSet.has(id);
1633
+ });
1634
+ if (!(remainingPriceIds.length > 0)) {
1635
+ _context18.next = 69;
1636
+ break;
1637
+ }
1638
+ _context18.next = 69;
1639
+ return this.updateProductPriceByIds(remainingPriceIds);
1640
+ case 69:
1641
+ this.logInfo('processProductSyncMessages: 处理完成', {
1642
+ deleteCount: uniqueDeleteIds.length,
1643
+ bodyUpdateCount: bodyUpdates.size,
1644
+ sseRefreshCount: uniqueSSEIds.length,
1645
+ priceRefreshCount: uniquePriceIds.length
1646
+ });
1647
+ _context18.next = 72;
1648
+ return this.core.effects.emit(ProductsHooks.onProductsSyncCompleted, null);
1649
+ case 72:
1650
+ case "end":
1651
+ return _context18.stop();
1652
+ }
1653
+ }, _callee18, this, [[10, 39, 42, 45]]);
1654
+ }));
1655
+ function processProductSyncMessages() {
1656
+ return _processProductSyncMessages.apply(this, arguments);
1657
+ }
1658
+ return processProductSyncMessages;
1659
+ }()
1660
+ /**
1661
+ * 通过 SSE 按 ids 增量拉取商品数据
1662
+ * 请求 GET /shop/core/stream?type=product&ids={ids}
1663
+ */
1664
+ )
1665
+ }, {
1666
+ key: "fetchProductsBySSE",
1667
+ value: (function () {
1668
+ var _fetchProductsBySSE = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee19(ids) {
1669
+ var t0, productList, list, errorMessage;
1670
+ return _regeneratorRuntime().wrap(function _callee19$(_context19) {
1671
+ while (1) switch (_context19.prev = _context19.next) {
1672
+ case 0:
1673
+ if (this.productDataSource) {
1674
+ _context19.next = 3;
1675
+ break;
1676
+ }
1677
+ this.logWarning('fetchProductsBySSE: ProductDataSource 不可用');
1678
+ return _context19.abrupt("return", []);
1679
+ case 3:
1680
+ this.logInfo('fetchProductsBySSE: 开始', {
1681
+ ids: ids,
1682
+ count: ids.length
1683
+ });
1684
+ t0 = performance.now();
1685
+ _context19.prev = 5;
1686
+ _context19.next = 8;
1687
+ return this.productDataSource.run({
1688
+ sse: {
1689
+ query: {
1690
+ type: 'product',
1691
+ ids: ids
1692
+ }
1693
+ }
1694
+ });
1695
+ case 8:
1696
+ productList = _context19.sent;
1697
+ list = productList || [];
1698
+ perfMark('fetchProductsBySSE', performance.now() - t0, {
1699
+ count: list.length
1700
+ });
1701
+ this.logInfo('fetchProductsBySSE: 成功', {
1702
+ requestedCount: ids.length,
1703
+ receivedCount: list.length,
1704
+ duration: "".concat(Math.round(performance.now() - t0), "ms")
1705
+ });
1706
+ return _context19.abrupt("return", list);
1707
+ case 15:
1708
+ _context19.prev = 15;
1709
+ _context19.t0 = _context19["catch"](5);
1710
+ errorMessage = _context19.t0 instanceof Error ? _context19.t0.message : String(_context19.t0);
1711
+ this.logError('fetchProductsBySSE: 失败', {
1712
+ ids: ids,
1713
+ error: errorMessage
1714
+ });
1715
+ return _context19.abrupt("return", []);
1716
+ case 20:
1717
+ case "end":
1718
+ return _context19.stop();
1719
+ }
1720
+ }, _callee19, this, [[5, 15]]);
1721
+ }));
1722
+ function fetchProductsBySSE(_x16) {
1723
+ return _fetchProductsBySSE.apply(this, arguments);
1724
+ }
1725
+ return fetchProductsBySSE;
1726
+ }()
1727
+ /**
1728
+ * 将 body 完整数据直接覆盖到本地 store(不调用报价单接口)
1729
+ * 已存在的 → 直接替换;不存在的 → 追加
1730
+ * 同时更新 Map 缓存、IndexDB,清空价格缓存,触发 onProductsChanged
1731
+ */
1732
+ )
1733
+ }, {
1734
+ key: "applyBodyUpdatesToStore",
1735
+ value: (function () {
1736
+ var _applyBodyUpdatesToStore = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee20(bodyUpdates) {
1737
+ var updatedCount, newCount, appliedIds, _iterator7, _step7, _step7$value, id, body;
1738
+ return _regeneratorRuntime().wrap(function _callee20$(_context20) {
1739
+ while (1) switch (_context20.prev = _context20.next) {
1740
+ case 0:
1741
+ this.logInfo('applyBodyUpdatesToStore: 开始', {
1742
+ count: bodyUpdates.size
1743
+ });
1744
+ updatedCount = 0;
1745
+ newCount = 0;
1746
+ appliedIds = new Set();
1747
+ this.store.list = this.store.list.map(function (p) {
1748
+ if (bodyUpdates.has(p.id)) {
1749
+ updatedCount++;
1750
+ appliedIds.add(p.id);
1751
+ return bodyUpdates.get(p.id);
1752
+ }
1753
+ return p;
1754
+ });
1755
+ _iterator7 = _createForOfIteratorHelper(bodyUpdates);
1756
+ try {
1757
+ for (_iterator7.s(); !(_step7 = _iterator7.n()).done;) {
1758
+ _step7$value = _slicedToArray(_step7.value, 2), id = _step7$value[0], body = _step7$value[1];
1759
+ if (!appliedIds.has(id)) {
1760
+ this.store.list.push(body);
1761
+ newCount++;
1762
+ }
1763
+ }
1764
+ } catch (err) {
1765
+ _iterator7.e(err);
1766
+ } finally {
1767
+ _iterator7.f();
1768
+ }
1769
+ this.syncProductsMap();
1770
+ _context20.next = 10;
1771
+ return this.saveProductsToIndexDB(this.store.list);
1772
+ case 10:
1773
+ this.clearPriceCache();
1774
+ this.core.effects.emit(ProductsHooks.onProductsChanged, this.store.list);
1775
+ this.logInfo('applyBodyUpdatesToStore: 完成', {
1776
+ updatedCount: updatedCount,
1777
+ newCount: newCount,
1778
+ totalCount: this.store.list.length
1779
+ });
1780
+ case 13:
1781
+ case "end":
1782
+ return _context20.stop();
1783
+ }
1784
+ }, _callee20, this);
1785
+ }));
1786
+ function applyBodyUpdatesToStore(_x17) {
1787
+ return _applyBodyUpdatesToStore.apply(this, arguments);
1788
+ }
1789
+ return applyBodyUpdatesToStore;
1790
+ }()
1791
+ /**
1792
+ * 将增量拉取的商品合并到 store
1793
+ * 已存在的 → 替换;新的 → 追加
1794
+ * 同时更新 store.map、IndexDB,触发 onProductsChanged
1795
+ */
1796
+ )
1797
+ }, {
1798
+ key: "mergeProductsToStore",
1799
+ value: (function () {
1800
+ var _mergeProductsToStore = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee21(freshProducts) {
1801
+ var freshMap, _iterator8, _step8, p, updatedList, newCount, _iterator9, _step9, _p, updatedCount;
1802
+ return _regeneratorRuntime().wrap(function _callee21$(_context21) {
1803
+ while (1) switch (_context21.prev = _context21.next) {
1804
+ case 0:
1805
+ freshMap = new Map();
1806
+ _iterator8 = _createForOfIteratorHelper(freshProducts);
1807
+ try {
1808
+ for (_iterator8.s(); !(_step8 = _iterator8.n()).done;) {
1809
+ p = _step8.value;
1810
+ freshMap.set(p.id, p);
1811
+ }
1812
+ } catch (err) {
1813
+ _iterator8.e(err);
1814
+ } finally {
1815
+ _iterator8.f();
1816
+ }
1817
+ updatedList = this.store.list.map(function (p) {
1818
+ if (freshMap.has(p.id)) {
1819
+ var fresh = freshMap.get(p.id);
1820
+ freshMap.delete(p.id);
1821
+ return fresh;
1822
+ }
1823
+ return p;
1824
+ }); // freshMap 中剩余的是新商品(create 场景)
1825
+ newCount = freshMap.size;
1826
+ _iterator9 = _createForOfIteratorHelper(freshMap.values());
1827
+ try {
1828
+ for (_iterator9.s(); !(_step9 = _iterator9.n()).done;) {
1829
+ _p = _step9.value;
1830
+ updatedList.push(_p);
1831
+ }
1832
+ } catch (err) {
1833
+ _iterator9.e(err);
1834
+ } finally {
1835
+ _iterator9.f();
1836
+ }
1837
+ updatedCount = freshProducts.length - newCount;
1838
+ this.store.list = updatedList;
1839
+ this.syncProductsMap();
1840
+ _context21.next = 12;
1841
+ return this.saveProductsToIndexDB(this.store.list);
1842
+ case 12:
1843
+ this.logInfo('mergeProductsToStore: 合并完成', {
1844
+ updatedCount: updatedCount,
1845
+ newCount: newCount,
1846
+ totalCount: this.store.list.length
1847
+ });
1848
+ this.core.effects.emit(ProductsHooks.onProductsChanged, this.store.list);
1849
+ case 14:
1850
+ case "end":
1851
+ return _context21.stop();
1852
+ }
1853
+ }, _callee21, this);
1854
+ }));
1855
+ function mergeProductsToStore(_x18) {
1856
+ return _mergeProductsToStore.apply(this, arguments);
1857
+ }
1858
+ return mergeProductsToStore;
1859
+ }()
1860
+ /**
1861
+ * 增量更新价格缓存中变更的商品
1862
+ * 对每个已缓存的日期 key:替换/追加最新商品数据,重新拉取这些 ID 的价格并应用
1863
+ */
1864
+ )
1865
+ }, {
1866
+ key: "updatePriceCacheForProducts",
1867
+ value: (function () {
1868
+ var _updatePriceCacheForProducts = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee22(freshProducts) {
1869
+ var freshIds, freshMap, _iterator10, _step10, p, _iterator11, _step11, _step11$value, dateKey, cachedProducts, updatedList, existingIds, _iterator12, _step12, _p2, priceData, result, errorMessage;
1870
+ return _regeneratorRuntime().wrap(function _callee22$(_context22) {
1871
+ while (1) switch (_context22.prev = _context22.next) {
1872
+ case 0:
1873
+ if (!(this.productsPriceCache.size === 0)) {
1874
+ _context22.next = 2;
1875
+ break;
1876
+ }
1877
+ return _context22.abrupt("return");
1878
+ case 2:
1879
+ freshIds = freshProducts.map(function (p) {
1880
+ return p.id;
1881
+ });
1882
+ freshMap = new Map();
1883
+ _iterator10 = _createForOfIteratorHelper(freshProducts);
1884
+ try {
1885
+ for (_iterator10.s(); !(_step10 = _iterator10.n()).done;) {
1886
+ p = _step10.value;
1887
+ freshMap.set(p.id, p);
1888
+ }
1889
+ } catch (err) {
1890
+ _iterator10.e(err);
1891
+ } finally {
1892
+ _iterator10.f();
1893
+ }
1894
+ this.logInfo('updatePriceCacheForProducts: 开始', {
1895
+ freshIds: freshIds,
1896
+ cachedDateCount: this.productsPriceCache.size
1897
+ });
1898
+ _iterator11 = _createForOfIteratorHelper(this.productsPriceCache.entries());
1899
+ _context22.prev = 8;
1900
+ _iterator11.s();
1901
+ case 10:
1902
+ if ((_step11 = _iterator11.n()).done) {
1903
+ _context22.next = 31;
1904
+ break;
1905
+ }
1906
+ _step11$value = _slicedToArray(_step11.value, 2), dateKey = _step11$value[0], cachedProducts = _step11$value[1];
1907
+ _context22.prev = 12;
1908
+ // 1. 替换已有商品 / 收集新增商品
1909
+ updatedList = cachedProducts.map(function (p) {
1910
+ var fresh = freshMap.get(p.id);
1911
+ return fresh ? _objectSpread({}, fresh) : p;
1912
+ }); // 追加新增商品(缓存中不存在的 ID)
1913
+ existingIds = new Set(cachedProducts.map(function (p) {
1914
+ return p.id;
1915
+ }));
1916
+ _iterator12 = _createForOfIteratorHelper(freshProducts);
1917
+ try {
1918
+ for (_iterator12.s(); !(_step12 = _iterator12.n()).done;) {
1919
+ _p2 = _step12.value;
1920
+ if (!existingIds.has(_p2.id)) {
1921
+ updatedList.push(_objectSpread({}, _p2));
1922
+ }
1923
+ }
1924
+
1925
+ // 2. 拉取这些 ID 的最新价格并应用
1926
+ } catch (err) {
1927
+ _iterator12.e(err);
1928
+ } finally {
1929
+ _iterator12.f();
1930
+ }
1931
+ _context22.next = 19;
1932
+ return this.loadProductsPrice({
1933
+ ids: freshIds,
1934
+ schedule_date: dateKey
1935
+ });
1936
+ case 19:
1937
+ priceData = _context22.sent;
1938
+ result = priceData && priceData.length > 0 ? applyPriceDataToProducts(updatedList, priceData) : updatedList;
1939
+ this.productsPriceCache.set(dateKey, result);
1940
+ this.logInfo('updatePriceCacheForProducts: 日期缓存已更新', {
1941
+ dateKey: dateKey,
1942
+ updatedIds: freshIds
1943
+ });
1944
+ _context22.next = 29;
1945
+ break;
1946
+ case 25:
1947
+ _context22.prev = 25;
1948
+ _context22.t0 = _context22["catch"](12);
1949
+ errorMessage = _context22.t0 instanceof Error ? _context22.t0.message : String(_context22.t0);
1950
+ this.logError('updatePriceCacheForProducts: 失败', {
1951
+ dateKey: dateKey,
1952
+ error: errorMessage
1953
+ });
1954
+ case 29:
1955
+ _context22.next = 10;
1956
+ break;
1957
+ case 31:
1958
+ _context22.next = 36;
1959
+ break;
1960
+ case 33:
1961
+ _context22.prev = 33;
1962
+ _context22.t1 = _context22["catch"](8);
1963
+ _iterator11.e(_context22.t1);
1964
+ case 36:
1965
+ _context22.prev = 36;
1966
+ _iterator11.f();
1967
+ return _context22.finish(36);
1968
+ case 39:
1969
+ case "end":
1970
+ return _context22.stop();
1971
+ }
1972
+ }, _callee22, this, [[8, 33, 36, 39], [12, 25]]);
1973
+ }));
1974
+ function updatePriceCacheForProducts(_x19) {
1975
+ return _updatePriceCacheForProducts.apply(this, arguments);
1976
+ }
1977
+ return updatePriceCacheForProducts;
1978
+ }()
1979
+ /**
1980
+ * 全量重新拉取报价单价格并重建价格缓存
1981
+ * 遍历当前已缓存的所有日期 key,对每个日期重新调用 loadProductsPrice
1982
+ */
1983
+ )
1984
+ }, {
1985
+ key: "refreshAllPriceCache",
1986
+ value: (function () {
1987
+ var _refreshAllPriceCache = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee23() {
1988
+ var allProducts, ids, dateKeys, _i, _dateKeys, dateKey, priceData, updatedProducts, errorMessage;
1989
+ return _regeneratorRuntime().wrap(function _callee23$(_context23) {
1990
+ while (1) switch (_context23.prev = _context23.next) {
1991
+ case 0:
1992
+ allProducts = this.getProductsRef();
1993
+ if (!(allProducts.length === 0)) {
1994
+ _context23.next = 3;
1995
+ break;
1996
+ }
1997
+ return _context23.abrupt("return");
1998
+ case 3:
1999
+ ids = allProducts.map(function (p) {
2000
+ return p.id;
2001
+ }); // 先快照当前已缓存的日期 key,再清空缓存
2002
+ dateKeys = Array.from(this.productsPriceCache.keys());
2003
+ this.clearPriceCache();
2004
+ if (!(dateKeys.length === 0)) {
2005
+ _context23.next = 9;
2006
+ break;
2007
+ }
2008
+ this.logInfo('refreshAllPriceCache: 无已缓存日期,跳过');
2009
+ return _context23.abrupt("return");
2010
+ case 9:
2011
+ this.logInfo('refreshAllPriceCache: 开始重新拉取', {
2012
+ dateKeys: dateKeys,
2013
+ productCount: ids.length
2014
+ });
2015
+ _i = 0, _dateKeys = dateKeys;
2016
+ case 11:
2017
+ if (!(_i < _dateKeys.length)) {
2018
+ _context23.next = 28;
2019
+ break;
2020
+ }
2021
+ dateKey = _dateKeys[_i];
2022
+ _context23.prev = 13;
2023
+ _context23.next = 16;
2024
+ return this.loadProductsPrice({
2025
+ ids: ids,
2026
+ schedule_date: dateKey
2027
+ });
2028
+ case 16:
2029
+ priceData = _context23.sent;
2030
+ if (priceData && priceData.length > 0) {
2031
+ updatedProducts = applyPriceDataToProducts(allProducts, priceData);
2032
+ this.productsPriceCache.set(dateKey, updatedProducts);
2033
+ }
2034
+ this.logInfo('refreshAllPriceCache: 日期缓存已更新', {
2035
+ dateKey: dateKey
2036
+ });
2037
+ _context23.next = 25;
2038
+ break;
2039
+ case 21:
2040
+ _context23.prev = 21;
2041
+ _context23.t0 = _context23["catch"](13);
2042
+ errorMessage = _context23.t0 instanceof Error ? _context23.t0.message : String(_context23.t0);
2043
+ this.logError('refreshAllPriceCache: 失败', {
2044
+ dateKey: dateKey,
2045
+ error: errorMessage
2046
+ });
2047
+ case 25:
2048
+ _i++;
2049
+ _context23.next = 11;
2050
+ break;
2051
+ case 28:
2052
+ case "end":
2053
+ return _context23.stop();
2054
+ }
2055
+ }, _callee23, this, [[13, 21]]);
2056
+ }));
2057
+ function refreshAllPriceCache() {
2058
+ return _refreshAllPriceCache.apply(this, arguments);
2059
+ }
2060
+ return refreshAllPriceCache;
2061
+ }()
2062
+ /**
2063
+ * 静默全量刷新:后台重新拉取全量 SSE 数据并更新本地
2064
+ * 拿到完整数据后一次性替换 store,清除价格缓存,触发 onProductsSyncCompleted
2065
+ * @returns 刷新后的商品列表
2066
+ */
2067
+ )
2068
+ }, {
2069
+ key: "silentRefresh",
2070
+ value: (function () {
2071
+ var _silentRefresh = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee24() {
2072
+ var t0, products, errorMessage;
2073
+ return _regeneratorRuntime().wrap(function _callee24$(_context24) {
2074
+ while (1) switch (_context24.prev = _context24.next) {
2075
+ case 0:
2076
+ t0 = performance.now();
2077
+ this.logInfo('silentRefresh 开始');
2078
+ _context24.prev = 2;
2079
+ _context24.next = 5;
2080
+ return this.loadProductsByServer();
2081
+ case 5:
2082
+ products = _context24.sent;
974
2083
  if (!(products && products.length > 0)) {
975
- _context12.next = 37;
2084
+ _context24.next = 16;
976
2085
  break;
977
2086
  }
978
- _context12.next = 30;
979
- return this.saveProductsToIndexDB(products);
980
- case 30:
981
- this.store.list = cloneDeep(products);
982
- // 同步更新 Map 缓存
2087
+ this.store.list = products;
983
2088
  this.syncProductsMap();
2089
+ this.clearPriceCache();
984
2090
  this.core.effects.emit(ProductsHooks.onProductsChanged, this.store.list);
985
- _duration3 = Date.now() - startTime;
986
- this.logInfo('预加载完成(从服务器)', {
2091
+ _context24.next = 13;
2092
+ return this.core.effects.emit(ProductsHooks.onProductsSyncCompleted, null);
2093
+ case 13:
2094
+ this.logInfo('silentRefresh 完成', {
987
2095
  productCount: products.length,
988
- duration: "".concat(_duration3, "ms"),
989
- source: 'Server'
2096
+ duration: "".concat(Math.round(performance.now() - t0), "ms")
990
2097
  });
991
- _context12.next = 39;
2098
+ _context24.next = 17;
992
2099
  break;
993
- case 37:
994
- _duration4 = Date.now() - startTime;
995
- this.logWarning('预加载完成但未获取到数据', {
996
- duration: "".concat(_duration4, "ms")
2100
+ case 16:
2101
+ this.logWarning('silentRefresh: 服务器未返回数据');
2102
+ case 17:
2103
+ perfMark('silentRefresh', performance.now() - t0, {
2104
+ count: this.store.list.length
997
2105
  });
998
- case 39:
2106
+ return _context24.abrupt("return", this.store.list);
2107
+ case 21:
2108
+ _context24.prev = 21;
2109
+ _context24.t0 = _context24["catch"](2);
2110
+ errorMessage = _context24.t0 instanceof Error ? _context24.t0.message : String(_context24.t0);
2111
+ this.logError('silentRefresh 失败', {
2112
+ duration: "".concat(Math.round(performance.now() - t0), "ms"),
2113
+ error: errorMessage
2114
+ });
2115
+ return _context24.abrupt("return", this.store.list);
2116
+ case 26:
999
2117
  case "end":
1000
- return _context12.stop();
2118
+ return _context24.stop();
1001
2119
  }
1002
- }, _callee12, this, [[3, 19]]);
2120
+ }, _callee24, this, [[2, 21]]);
1003
2121
  }));
1004
- function preload() {
1005
- return _preload.apply(this, arguments);
2122
+ function silentRefresh() {
2123
+ return _silentRefresh.apply(this, arguments);
1006
2124
  }
1007
- return preload;
2125
+ return silentRefresh;
1008
2126
  }()
2127
+ /**
2128
+ * 销毁同步资源(取消 pubsub 订阅、清除定时器)
2129
+ */
2130
+ )
2131
+ }, {
2132
+ key: "destroyProductSync",
2133
+ value: function destroyProductSync() {
2134
+ var _this$productDataSour;
2135
+ if (this.syncTimer) {
2136
+ clearTimeout(this.syncTimer);
2137
+ this.syncTimer = undefined;
2138
+ }
2139
+ if ((_this$productDataSour = this.productDataSource) !== null && _this$productDataSour !== void 0 && _this$productDataSour.destroy) {
2140
+ this.productDataSource.destroy();
2141
+ }
2142
+ this.pendingSyncMessages = [];
2143
+ this.logInfo('destroyProductSync: 同步资源已销毁');
2144
+ }
2145
+
1009
2146
  /**
1010
2147
  * 获取模块的路由定义
1011
2148
  * Products 模块暂不提供路由,由 Server 层统一处理
1012
2149
  */
1013
- )
1014
2150
  }, {
1015
2151
  key: "getRoutes",
1016
2152
  value: function getRoutes() {