@pisell/pisellos 2.2.189 → 2.2.191

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/dist/model/strategy/adapter/promotion/index.js +0 -9
  2. package/dist/modules/BookingContext/utils/buildCacheItemFromOrderLine.js +2 -1
  3. package/dist/modules/BookingContext/utils/buildNormalProductCacheItemFromOrderLine.js +2 -7
  4. package/dist/modules/Cart/utils/cartProduct.js +13 -2
  5. package/dist/modules/Order/index.d.ts +1 -3
  6. package/dist/modules/Order/index.js +88 -114
  7. package/dist/modules/Order/types.d.ts +10 -6
  8. package/dist/modules/Order/utils.d.ts +9 -2
  9. package/dist/modules/Order/utils.js +36 -13
  10. package/dist/modules/SalesSummary/types.d.ts +3 -1
  11. package/dist/modules/SalesSummary/utils.js +7 -3
  12. package/dist/server/modules/order/index.d.ts +126 -6
  13. package/dist/server/modules/order/index.js +1204 -285
  14. package/dist/server/modules/order/types.d.ts +0 -2
  15. package/dist/server/modules/products/index.d.ts +90 -6
  16. package/dist/server/modules/products/index.js +1017 -361
  17. package/dist/solution/BaseSales/index.js +54 -39
  18. package/dist/solution/BaseSales/types.d.ts +8 -5
  19. package/dist/solution/BaseSales/types.js +2 -3
  20. package/dist/solution/BaseSales/utils/cartPromotion.js +7 -7
  21. package/dist/solution/BaseSales/utils/transformBaseProductToOrderProduct.d.ts +1 -0
  22. package/dist/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +29 -14
  23. package/dist/solution/BaseSales/utils.d.ts +1 -1
  24. package/dist/solution/BaseSales/utils.js +22 -19
  25. package/dist/solution/BookingByStep/index.d.ts +1 -1
  26. package/dist/solution/ScanOrder/index.js +7 -5
  27. package/dist/solution/ScanOrder/types.d.ts +8 -5
  28. package/dist/solution/ScanOrder/types.js +2 -3
  29. package/dist/solution/ScanOrder/utils.d.ts +1 -1
  30. package/dist/solution/ScanOrder/utils.js +26 -23
  31. package/dist/solution/VenueBooking/index.js +5 -3
  32. package/dist/solution/VenueBooking/sales-section-4-annotated.json +0 -2
  33. package/lib/model/strategy/adapter/promotion/index.js +0 -49
  34. package/lib/modules/BookingContext/utils/buildCacheItemFromOrderLine.js +2 -1
  35. package/lib/modules/BookingContext/utils/buildNormalProductCacheItemFromOrderLine.js +2 -1
  36. package/lib/modules/Cart/utils/cartProduct.js +9 -2
  37. package/lib/modules/Order/index.d.ts +1 -3
  38. package/lib/modules/Order/index.js +50 -63
  39. package/lib/modules/Order/types.d.ts +10 -6
  40. package/lib/modules/Order/utils.d.ts +9 -2
  41. package/lib/modules/Order/utils.js +41 -10
  42. package/lib/modules/SalesSummary/types.d.ts +3 -1
  43. package/lib/modules/SalesSummary/utils.js +5 -3
  44. package/lib/server/modules/order/index.d.ts +126 -6
  45. package/lib/server/modules/order/index.js +722 -42
  46. package/lib/server/modules/order/types.d.ts +0 -2
  47. package/lib/server/modules/products/index.d.ts +90 -6
  48. package/lib/server/modules/products/index.js +492 -30
  49. package/lib/solution/BaseSales/index.js +26 -8
  50. package/lib/solution/BaseSales/types.d.ts +8 -5
  51. package/lib/solution/BaseSales/utils/cartPromotion.js +6 -6
  52. package/lib/solution/BaseSales/utils/transformBaseProductToOrderProduct.d.ts +1 -0
  53. package/lib/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +32 -16
  54. package/lib/solution/BaseSales/utils.d.ts +1 -1
  55. package/lib/solution/BaseSales/utils.js +11 -7
  56. package/lib/solution/BookingByStep/index.d.ts +1 -1
  57. package/lib/solution/ScanOrder/index.js +4 -4
  58. package/lib/solution/ScanOrder/types.d.ts +8 -5
  59. package/lib/solution/ScanOrder/utils.d.ts +1 -1
  60. package/lib/solution/ScanOrder/utils.js +12 -8
  61. package/lib/solution/VenueBooking/index.js +2 -2
  62. package/lib/solution/VenueBooking/sales-section-4-annotated.json +0 -2
  63. package/package.json +1 -1
  64. package/dist/solution/Checkout/appointmentDemo.json +0 -1
  65. package/lib/solution/Checkout/appointmentDemo.json +0 -1
@@ -1,17 +1,17 @@
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 ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
3
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
4
+ 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; } } }; }
2
5
  function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
3
6
  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
7
  function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
5
8
  function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
6
9
  function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
7
10
  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; }
10
- function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
11
- function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
12
- 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; } } }; }
13
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); }
14
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; }
13
+ 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; } }
14
+ function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
15
15
  function _regeneratorRuntime() { "use strict"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = "function" == typeof Symbol ? Symbol : {}, a = i.iterator || "@@iterator", c = i.asyncIterator || "@@asyncIterator", u = i.toStringTag || "@@toStringTag"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, ""); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, "_invoke", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: "normal", arg: t.call(e, r) }; } catch (t) { return { type: "throw", arg: t }; } } e.wrap = wrap; var h = "suspendedStart", l = "suspendedYield", f = "executing", s = "completed", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { ["next", "throw", "return"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if ("throw" !== c.type) { var u = c.arg, h = u.value; return h && "object" == _typeof(h) && n.call(h, "__await") ? e.resolve(h.__await).then(function (t) { invoke("next", t, i, a); }, function (t) { invoke("throw", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke("throw", t, i, a); }); } a(c.arg); } var r; o(this, "_invoke", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw new Error("Generator is already running"); if (o === s) { if ("throw" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if ("next" === n.method) n.sent = n._sent = n.arg;else if ("throw" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else "return" === n.method && n.abrupt("return", n.arg); o = f; var p = tryCatch(e, r, n); if ("normal" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } "throw" === p.type && (o = s, n.method = "throw", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, "throw" === n && e.iterator.return && (r.method = "return", r.arg = t, maybeInvokeDelegate(e, r), "throw" === r.method) || "return" !== n && (r.method = "throw", r.arg = new TypeError("The iterator does not provide a '" + n + "' method")), y; var i = tryCatch(o, e.iterator, r.arg); if ("throw" === i.type) return r.method = "throw", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, "return" !== r.method && (r.method = "next", r.arg = t), r.delegate = null, y) : a : (r.method = "throw", r.arg = new TypeError("iterator result is not an object"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = "normal", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: "root" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || "" === e) { var r = e[a]; if (r) return r.call(e); if ("function" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + " is not iterable"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, "constructor", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, "constructor", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, "GeneratorFunction"), e.isGeneratorFunction = function (t) { var e = "function" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || "GeneratorFunction" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, "GeneratorFunction")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, "Generator"), define(g, a, function () { return this; }), define(g, "toString", function () { return "[object Generator]"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = "next", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) "t" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if ("throw" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = "throw", a.arg = e, r.next = n, o && (r.method = "next", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if ("root" === i.tryLoc) return handle("end"); if (i.tryLoc <= this.prev) { var c = n.call(i, "catchLoc"), u = n.call(i, "finallyLoc"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw new Error("try statement without catch or finally"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, "finallyLoc") && this.prev < o.finallyLoc) { var i = o; break; } } i && ("break" === t || "continue" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = "next", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if ("throw" === t.type) throw t.arg; return "break" === t.type || "continue" === t.type ? this.next = t.arg : "return" === t.type ? (this.rval = this.arg = t.arg, this.method = "return", this.next = "end") : "normal" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, catch: function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if ("throw" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw new Error("illegal catch attempt"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, "next" === this.method && (this.arg = t), y; } }, e; }
16
16
  function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
17
17
  function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
@@ -37,9 +37,20 @@ import { applyDetailValueToProducts, applyPriceDataToProducts, applyI18nToProduc
37
37
  * IndexDB 存储名称
38
38
  */
39
39
  var INDEXDB_STORE_NAME = 'products';
40
+ /** window 上挂载的商品流程调试日志 key */
41
+ var PRODUCT_FLOW_LOG_WINDOW_KEY = '__productModuleFlowLogs';
42
+ /** window 上按商品 id 聚合的 IndexDB 写入统计 key */
43
+ var PRODUCT_WRITE_STATS_WINDOW_KEY = '__productModuleWriteStats';
44
+ var PRODUCT_FLOW_LOG_MAX_LENGTH = 1000;
45
+
46
+ /** 商品模块流程调试日志条目 */
47
+
48
+ /** 单个商品 IndexDB 写入记录 */
40
49
 
41
50
  /** 商品同步防抖时间(毫秒) */
42
51
  var PRODUCT_SYNC_DEBOUNCE_MS = 10000;
52
+ /** silentRefresh 最小间隔,避免 preload 后立即全量重拉 */
53
+ var PRODUCT_SILENT_REFRESH_MIN_INTERVAL_MS = 30000;
43
54
 
44
55
  /**
45
56
  * Products 模块 - 用于获取和管理完整的商品详细数据
@@ -80,6 +91,14 @@ export var ProductsModule = /*#__PURE__*/function (_BaseModule) {
80
91
  _defineProperty(_assertThisInitialized(_this), "productDataSource", void 0);
81
92
  _defineProperty(_assertThisInitialized(_this), "pendingSyncMessages", []);
82
93
  _defineProperty(_assertThisInitialized(_this), "syncTimer", void 0);
94
+ /** IndexDB 写入序号,便于日志关联 */
95
+ _defineProperty(_assertThisInitialized(_this), "productFlowWriteSeq", 0);
96
+ /** 最近一次 SSE 全量拉取完成时间 */
97
+ _defineProperty(_assertThisInitialized(_this), "lastServerFullFetchAtMs", 0);
98
+ /** 最近一次 preload 完成时间(含 IndexDB 命中) */
99
+ _defineProperty(_assertThisInitialized(_this), "lastPreloadCompletedAtMs", 0);
100
+ /** IndexDB 写入串行队列,避免快照与 patch 并发交错 */
101
+ _defineProperty(_assertThisInitialized(_this), "productIndexDBSaveQueue", Promise.resolve());
83
102
  return _this;
84
103
  }
85
104
  _createClass(ProductsModule, [{
@@ -126,12 +145,18 @@ export var ProductsModule = /*#__PURE__*/function (_BaseModule) {
126
145
 
127
146
  // 初始化商品数据同步(pubsub 订阅)
128
147
  this.setupProductSync();
148
+ this.initProductFlowLogs();
149
+ this.pushProductFlowLog('initialize.complete', {
150
+ hasDbManager: !!this.dbManager,
151
+ hasLogger: !!this.logger,
152
+ initialProductCount: this.store.list.length
153
+ });
129
154
  this.logInfo('模块初始化完成', {
130
155
  hasDbManager: !!this.dbManager,
131
156
  hasLogger: !!this.logger,
132
157
  initialProductCount: this.store.list.length
133
158
  });
134
- case 11:
159
+ case 13:
135
160
  case "end":
136
161
  return _context.stop();
137
162
  }
@@ -203,6 +228,163 @@ export var ProductsModule = /*#__PURE__*/function (_BaseModule) {
203
228
  } catch (_unused3) {
204
229
  // 日志记录失败不影响主流程
205
230
  }
231
+ this.pushProductFlowLog("error.".concat(title), metadata);
232
+ }
233
+
234
+ /**
235
+ * 初始化 window 上的商品流程调试日志。
236
+ *
237
+ * @example
238
+ * window.clearProductModuleFlowLogs()
239
+ * copy(window.exportProductModuleFlowLogs?.() || '[]')
240
+ */
241
+ }, {
242
+ key: "initProductFlowLogs",
243
+ value: function initProductFlowLogs() {
244
+ var _this2 = this;
245
+ try {
246
+ var win = typeof globalThis !== 'undefined' ? globalThis.window : undefined;
247
+ if (!win) return;
248
+ win[PRODUCT_FLOW_LOG_WINDOW_KEY] = [];
249
+ win[PRODUCT_WRITE_STATS_WINDOW_KEY] = {};
250
+ win.clearProductModuleFlowLogs = function () {
251
+ win[PRODUCT_FLOW_LOG_WINDOW_KEY] = [];
252
+ win[PRODUCT_WRITE_STATS_WINDOW_KEY] = {};
253
+ _this2.productFlowWriteSeq = 0;
254
+ _this2.pushProductFlowLog('debug.clear', {});
255
+ };
256
+ win.exportProductModuleFlowLogs = function () {
257
+ var logs = win[PRODUCT_FLOW_LOG_WINDOW_KEY] || [];
258
+ return JSON.stringify(logs, null, 2);
259
+ };
260
+ win.exportProductModuleWriteStats = function () {
261
+ var stats = win[PRODUCT_WRITE_STATS_WINDOW_KEY] || {};
262
+ return JSON.stringify(stats, null, 2);
263
+ };
264
+ win.summarizeProductModuleWrites = function () {
265
+ var topN = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 20;
266
+ var stats = win[PRODUCT_WRITE_STATS_WINDOW_KEY] || {};
267
+ return Object.entries(stats).map(function (_ref) {
268
+ var _ref2 = _slicedToArray(_ref, 2),
269
+ productId = _ref2[0],
270
+ entries = _ref2[1];
271
+ var list = entries || [];
272
+ var sources = _toConsumableArray(new Set(list.map(function (item) {
273
+ return item.source;
274
+ })));
275
+ var last = list[list.length - 1];
276
+ return {
277
+ productId: Number(productId),
278
+ writeCount: list.length,
279
+ sources: sources,
280
+ lastWriteAt: (last === null || last === void 0 ? void 0 : last.ts) || ''
281
+ };
282
+ }).sort(function (a, b) {
283
+ return b.writeCount - a.writeCount;
284
+ }).slice(0, topN);
285
+ };
286
+ this.pushProductFlowLog('debug.init', {
287
+ logKey: PRODUCT_FLOW_LOG_WINDOW_KEY,
288
+ writeStatsKey: PRODUCT_WRITE_STATS_WINDOW_KEY,
289
+ indexDbStrategy: '全量 replaceProductsSnapshotInIndexDB + 增量 patchProductsInIndexDB',
290
+ helpers: ['clearProductModuleFlowLogs', 'exportProductModuleFlowLogs', 'exportProductModuleWriteStats', 'summarizeProductModuleWrites']
291
+ });
292
+ } catch (_unused4) {
293
+ // window 不可用时忽略
294
+ }
295
+ }
296
+
297
+ /**
298
+ * 写入 window 商品流程调试日志。
299
+ *
300
+ * @example
301
+ * this.pushProductFlowLog('mergeProductsToStore.start', { count: 3 })
302
+ */
303
+ }, {
304
+ key: "pushProductFlowLog",
305
+ value: function pushProductFlowLog(step, metadata) {
306
+ try {
307
+ var win = typeof globalThis !== 'undefined' ? globalThis.window : undefined;
308
+ if (!win) return;
309
+ if (!Array.isArray(win[PRODUCT_FLOW_LOG_WINDOW_KEY])) {
310
+ win[PRODUCT_FLOW_LOG_WINDOW_KEY] = [];
311
+ }
312
+ var entry = {
313
+ ts: new Date().toISOString(),
314
+ step: step,
315
+ metadata: metadata || {}
316
+ };
317
+ win[PRODUCT_FLOW_LOG_WINDOW_KEY].push(entry);
318
+ var logs = win[PRODUCT_FLOW_LOG_WINDOW_KEY];
319
+ if (logs.length > PRODUCT_FLOW_LOG_MAX_LENGTH) {
320
+ logs.splice(0, logs.length - PRODUCT_FLOW_LOG_MAX_LENGTH);
321
+ }
322
+ console.log("[ProductFlow] ".concat(step), metadata || {});
323
+ } catch (_unused5) {
324
+ // 调试日志失败不影响主流程
325
+ }
326
+ }
327
+
328
+ /** 当前内存 store 快照,供流程日志使用 */
329
+ }, {
330
+ key: "getProductStoreSnapshot",
331
+ value: function getProductStoreSnapshot() {
332
+ return {
333
+ storeListCount: this.store.list.length,
334
+ storeMapCount: this.store.map.size,
335
+ pendingSyncCount: this.pendingSyncMessages.length
336
+ };
337
+ }
338
+
339
+ /**
340
+ * 记录 IndexDB 写入统计(按 productId 聚合)。
341
+ *
342
+ * @example
343
+ * this.trackProductWrite('pubsub.mergeProductsToStore', 'clear+bulkUpdate', products, { 1: 'update' })
344
+ */
345
+ }, {
346
+ key: "trackProductWrite",
347
+ value: function trackProductWrite(source, writeMethod, products) {
348
+ var mergeActions = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
349
+ var defaultMergeAction = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 'update';
350
+ this.productFlowWriteSeq += 1;
351
+ var writeSeq = this.productFlowWriteSeq;
352
+ try {
353
+ var win = typeof globalThis !== 'undefined' ? globalThis.window : undefined;
354
+ if (!win) return writeSeq;
355
+ if (!win[PRODUCT_WRITE_STATS_WINDOW_KEY]) {
356
+ win[PRODUCT_WRITE_STATS_WINDOW_KEY] = {};
357
+ }
358
+ var stats = win[PRODUCT_WRITE_STATS_WINDOW_KEY];
359
+ var _iterator = _createForOfIteratorHelper(products),
360
+ _step;
361
+ try {
362
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
363
+ var product = _step.value;
364
+ var productId = product === null || product === void 0 ? void 0 : product.id;
365
+ if (productId === undefined || productId === null) continue;
366
+ var mergeAction = mergeActions[productId] || defaultMergeAction;
367
+ var entry = {
368
+ ts: new Date().toISOString(),
369
+ writeSeq: writeSeq,
370
+ source: source,
371
+ writeMethod: writeMethod,
372
+ productId: productId,
373
+ mergeAction: mergeAction
374
+ };
375
+ var key = String(productId);
376
+ if (!stats[key]) stats[key] = [];
377
+ stats[key].push(entry);
378
+ }
379
+ } catch (err) {
380
+ _iterator.e(err);
381
+ } finally {
382
+ _iterator.f();
383
+ }
384
+ } catch (_unused6) {
385
+ // 统计失败不影响主流程
386
+ }
387
+ return writeSeq;
206
388
  }
207
389
 
208
390
  /**
@@ -212,13 +394,13 @@ export var ProductsModule = /*#__PURE__*/function (_BaseModule) {
212
394
  }, {
213
395
  key: "loadProductsPrice",
214
396
  value: (function () {
215
- var _loadProductsPrice = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee2(_ref) {
216
- var _this2 = this;
217
- var _ref$ids, ids, schedule_date, schedule_datetime, customer_id, startTime, datetime, idSet, products, priceData, duration, _duration, errorMessage;
397
+ var _loadProductsPrice = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee2(_ref3) {
398
+ var _this3 = this;
399
+ var _ref3$ids, ids, schedule_date, schedule_datetime, customer_id, startTime, datetime, idSet, products, priceData, duration, _duration, errorMessage;
218
400
  return _regeneratorRuntime().wrap(function _callee2$(_context2) {
219
401
  while (1) switch (_context2.prev = _context2.next) {
220
402
  case 0:
221
- _ref$ids = _ref.ids, ids = _ref$ids === void 0 ? [] : _ref$ids, schedule_date = _ref.schedule_date, schedule_datetime = _ref.schedule_datetime, customer_id = _ref.customer_id;
403
+ _ref3$ids = _ref3.ids, ids = _ref3$ids === void 0 ? [] : _ref3$ids, schedule_date = _ref3.schedule_date, schedule_datetime = _ref3.schedule_datetime, customer_id = _ref3.customer_id;
222
404
  this.logInfo('开始加载商品价格', {
223
405
  productCount: ids.length,
224
406
  schedule_date: schedule_date,
@@ -236,7 +418,7 @@ export var ProductsModule = /*#__PURE__*/function (_BaseModule) {
236
418
  return idSet.has(product.id);
237
419
  });
238
420
  priceData = products.map(function (product) {
239
- return _this2.buildPriceDataFromQuotation(product, datetime, customer_id);
421
+ return _this3.buildPriceDataFromQuotation(product, datetime, customer_id);
240
422
  });
241
423
  duration = Date.now() - startTime;
242
424
  this.logInfo('加载商品价格成功', {
@@ -310,17 +492,17 @@ export var ProductsModule = /*#__PURE__*/function (_BaseModule) {
310
492
  if (!hasLoadedScheduleList) {
311
493
  var _params$scheduleModul, _params$scheduleModul2;
312
494
  var scheduleList = ((_params$scheduleModul = (_params$scheduleModul2 = params.scheduleModule).getScheduleList) === null || _params$scheduleModul === void 0 ? void 0 : _params$scheduleModul.call(_params$scheduleModul2)) || [];
313
- var _iterator = _createForOfIteratorHelper(scheduleList),
314
- _step;
495
+ var _iterator2 = _createForOfIteratorHelper(scheduleList),
496
+ _step2;
315
497
  try {
316
- for (_iterator.s(); !(_step = _iterator.n()).done;) {
317
- var schedule = _step.value;
498
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
499
+ var schedule = _step2.value;
318
500
  scheduleCache.set(String(schedule.id), schedule);
319
501
  }
320
502
  } catch (err) {
321
- _iterator.e(err);
503
+ _iterator2.e(err);
322
504
  } finally {
323
- _iterator.f();
505
+ _iterator2.f();
324
506
  }
325
507
  hasLoadedScheduleList = true;
326
508
  }
@@ -353,7 +535,7 @@ export var ProductsModule = /*#__PURE__*/function (_BaseModule) {
353
535
  key: "refreshQuotationPriceBridge",
354
536
  value: (function () {
355
537
  var _refreshQuotationPriceBridge = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee4(params) {
356
- var _this3 = this;
538
+ var _this4 = this;
357
539
  var refreshKey;
358
540
  return _regeneratorRuntime().wrap(function _callee4$(_context4) {
359
541
  while (1) switch (_context4.prev = _context4.next) {
@@ -385,10 +567,10 @@ export var ProductsModule = /*#__PURE__*/function (_BaseModule) {
385
567
  this.quotationBridgeRefreshPromise = this.quotationPriceBridge.loadQuotations({
386
568
  channel: this.quotationBridgeChannel
387
569
  }).then(function () {
388
- _this3.quotationBridgeLoadedKey = refreshKey;
570
+ _this4.quotationBridgeLoadedKey = refreshKey;
389
571
  }).finally(function () {
390
- _this3.quotationBridgeRefreshPromise = undefined;
391
- _this3.quotationBridgeRefreshKey = undefined;
572
+ _this4.quotationBridgeRefreshPromise = undefined;
573
+ _this4.quotationBridgeRefreshKey = undefined;
392
574
  });
393
575
  _context4.next = 14;
394
576
  return this.quotationBridgeRefreshPromise;
@@ -457,14 +639,14 @@ export var ProductsModule = /*#__PURE__*/function (_BaseModule) {
457
639
  }, {
458
640
  key: "buildPriceDataFromQuotation",
459
641
  value: function buildPriceDataFromQuotation(product, datetime, customerId) {
460
- var _this$quotationPriceB, _ref2, _ref3;
642
+ var _this$quotationPriceB, _ref4, _ref5;
461
643
  var quotedPrice = (_this$quotationPriceB = this.quotationPriceBridge) === null || _this$quotationPriceB === void 0 ? void 0 : _this$quotationPriceB.getPriceForProduct({
462
644
  productId: product.id,
463
645
  datetime: datetime,
464
646
  customer_id: customerId
465
647
  });
466
648
  var productPrice = quotedPrice !== null && quotedPrice !== void 0 ? quotedPrice : product.price;
467
- var productBasePrice = (_ref2 = (_ref3 = quotedPrice !== null && quotedPrice !== void 0 ? quotedPrice : product.base_price) !== null && _ref3 !== void 0 ? _ref3 : product.price) !== null && _ref2 !== void 0 ? _ref2 : 0;
649
+ var productBasePrice = (_ref4 = (_ref5 = quotedPrice !== null && quotedPrice !== void 0 ? quotedPrice : product.base_price) !== null && _ref5 !== void 0 ? _ref5 : product.price) !== null && _ref4 !== void 0 ? _ref4 : 0;
468
650
  return {
469
651
  id: product.id,
470
652
  price: String(productPrice !== null && productPrice !== void 0 ? productPrice : 0),
@@ -476,18 +658,18 @@ export var ProductsModule = /*#__PURE__*/function (_BaseModule) {
476
658
  }, {
477
659
  key: "buildVariantPriceData",
478
660
  value: function buildVariantPriceData(product, datetime, customerId) {
479
- var _this4 = this;
661
+ var _this5 = this;
480
662
  if (!Array.isArray(product.variant)) return [];
481
663
  return product.variant.map(function (variant) {
482
- var _this4$quotationPrice, _ref4, _ref5, _ref6, _ref7, _ref8, _ref9, _variant$product_id;
483
- var quotedPrice = (_this4$quotationPrice = _this4.quotationPriceBridge) === null || _this4$quotationPrice === void 0 ? void 0 : _this4$quotationPrice.getPriceForProduct({
664
+ var _this5$quotationPrice, _ref6, _ref7, _ref8, _ref9, _ref10, _ref11, _variant$product_id;
665
+ var quotedPrice = (_this5$quotationPrice = _this5.quotationPriceBridge) === null || _this5$quotationPrice === void 0 ? void 0 : _this5$quotationPrice.getPriceForProduct({
484
666
  productId: product.id,
485
667
  variantId: Number(variant.id),
486
668
  datetime: datetime,
487
669
  customer_id: customerId
488
670
  });
489
- var price = (_ref4 = (_ref5 = quotedPrice !== null && quotedPrice !== void 0 ? quotedPrice : variant.price) !== null && _ref5 !== void 0 ? _ref5 : product.price) !== null && _ref4 !== void 0 ? _ref4 : 0;
490
- var basePrice = (_ref6 = (_ref7 = (_ref8 = (_ref9 = quotedPrice !== null && quotedPrice !== void 0 ? quotedPrice : variant.base_price) !== null && _ref9 !== void 0 ? _ref9 : variant.price) !== null && _ref8 !== void 0 ? _ref8 : product.base_price) !== null && _ref7 !== void 0 ? _ref7 : product.price) !== null && _ref6 !== void 0 ? _ref6 : 0;
671
+ var price = (_ref6 = (_ref7 = quotedPrice !== null && quotedPrice !== void 0 ? quotedPrice : variant.price) !== null && _ref7 !== void 0 ? _ref7 : product.price) !== null && _ref6 !== void 0 ? _ref6 : 0;
672
+ var basePrice = (_ref8 = (_ref9 = (_ref10 = (_ref11 = quotedPrice !== null && quotedPrice !== void 0 ? quotedPrice : variant.base_price) !== null && _ref11 !== void 0 ? _ref11 : variant.price) !== null && _ref10 !== void 0 ? _ref10 : product.base_price) !== null && _ref9 !== void 0 ? _ref9 : product.price) !== null && _ref8 !== void 0 ? _ref8 : 0;
491
673
  return {
492
674
  id: Number(variant.id),
493
675
  product_id: Number((_variant$product_id = variant.product_id) !== null && _variant$product_id !== void 0 ? _variant$product_id : product.id),
@@ -499,23 +681,23 @@ export var ProductsModule = /*#__PURE__*/function (_BaseModule) {
499
681
  }, {
500
682
  key: "buildBundleGroupPriceData",
501
683
  value: function buildBundleGroupPriceData(product, datetime, customerId) {
502
- var _this5 = this;
684
+ var _this6 = this;
503
685
  if (!Array.isArray(product.bundle_group)) return [];
504
686
  return product.bundle_group.map(function (group) {
505
687
  return {
506
688
  id: Number(group.id),
507
689
  bundle_item: (group.bundle_item || []).map(function (item) {
508
- var _this5$quotationPrice, _ref10, _ref11, _ref12, _item$product_id, _item$group_id;
690
+ var _this6$quotationPrice, _ref12, _ref13, _ref14, _item$product_id, _item$group_id;
509
691
  var bundleProductId = Number(item.bundle_product_id);
510
692
  var bundleVariantId = Number(item.bundle_variant_id || 0);
511
- var quotedPrice = (_this5$quotationPrice = _this5.quotationPriceBridge) === null || _this5$quotationPrice === void 0 ? void 0 : _this5$quotationPrice.getPriceForProduct({
693
+ var quotedPrice = (_this6$quotationPrice = _this6.quotationPriceBridge) === null || _this6$quotationPrice === void 0 ? void 0 : _this6$quotationPrice.getPriceForProduct({
512
694
  productId: bundleProductId,
513
695
  variantId: bundleVariantId,
514
696
  datetime: datetime,
515
697
  customer_id: customerId
516
698
  });
517
- var price = (_ref10 = quotedPrice !== null && quotedPrice !== void 0 ? quotedPrice : item.price) !== null && _ref10 !== void 0 ? _ref10 : 0;
518
- var basePrice = (_ref11 = (_ref12 = quotedPrice !== null && quotedPrice !== void 0 ? quotedPrice : item.base_price) !== null && _ref12 !== void 0 ? _ref12 : item.price) !== null && _ref11 !== void 0 ? _ref11 : 0;
699
+ var price = (_ref12 = quotedPrice !== null && quotedPrice !== void 0 ? quotedPrice : item.price) !== null && _ref12 !== void 0 ? _ref12 : 0;
700
+ var basePrice = (_ref13 = (_ref14 = quotedPrice !== null && quotedPrice !== void 0 ? quotedPrice : item.base_price) !== null && _ref14 !== void 0 ? _ref14 : item.price) !== null && _ref13 !== void 0 ? _ref13 : 0;
519
701
  return {
520
702
  id: Number(item.id),
521
703
  product_id: Number((_item$product_id = item.product_id) !== null && _item$product_id !== void 0 ? _item$product_id : product.id),
@@ -548,7 +730,7 @@ export var ProductsModule = /*#__PURE__*/function (_BaseModule) {
548
730
  value: (function () {
549
731
  var _getProductsWithPrice = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee6(schedule_date, extraContext, options) {
550
732
  var _options$changedIds;
551
- var t0, scopedProductIds, cacheKey, scopedProductIdSet, changedIds, cachedProducts, updatedProducts, updatedMap, mergedCache, _iterator2, _step2, p, _iterator3, _step3, _p, errorMessage, result;
733
+ var t0, scopedProductIds, cacheKey, scopedProductIdSet, changedIds, cachedProducts, updatedProducts, updatedMap, mergedCache, _iterator3, _step3, p, _iterator4, _step4, _p, errorMessage, result;
552
734
  return _regeneratorRuntime().wrap(function _callee6$(_context6) {
553
735
  while (1) switch (_context6.prev = _context6.next) {
554
736
  case 0:
@@ -589,10 +771,10 @@ export var ProductsModule = /*#__PURE__*/function (_BaseModule) {
589
771
  return [p.id, p];
590
772
  }));
591
773
  mergedCache = [];
592
- _iterator2 = _createForOfIteratorHelper(cachedProducts);
774
+ _iterator3 = _createForOfIteratorHelper(cachedProducts);
593
775
  try {
594
- for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
595
- p = _step2.value;
776
+ for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
777
+ p = _step3.value;
596
778
  if (updatedMap.has(p.id)) {
597
779
  mergedCache.push(updatedMap.get(p.id));
598
780
  updatedMap.delete(p.id);
@@ -602,20 +784,20 @@ export var ProductsModule = /*#__PURE__*/function (_BaseModule) {
602
784
  }
603
785
  // 剩余的是新增商品(create 场景)
604
786
  } catch (err) {
605
- _iterator2.e(err);
787
+ _iterator3.e(err);
606
788
  } finally {
607
- _iterator2.f();
789
+ _iterator3.f();
608
790
  }
609
- _iterator3 = _createForOfIteratorHelper(updatedMap.values());
791
+ _iterator4 = _createForOfIteratorHelper(updatedMap.values());
610
792
  try {
611
- for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
612
- _p = _step3.value;
793
+ for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
794
+ _p = _step4.value;
613
795
  mergedCache.push(_p);
614
796
  }
615
797
  } catch (err) {
616
- _iterator3.e(err);
798
+ _iterator4.e(err);
617
799
  } finally {
618
- _iterator3.f();
800
+ _iterator4.f();
619
801
  }
620
802
  this.productsPriceCache.set(cacheKey, mergedCache);
621
803
  this.logInfo('增量更新完成', {
@@ -850,25 +1032,25 @@ export var ProductsModule = /*#__PURE__*/function (_BaseModule) {
850
1032
  }
851
1033
  if (productIds.length === 0 && collectionIds.length === 0) return [];
852
1034
  var result = new Set();
853
- var _iterator4 = _createForOfIteratorHelper(productIds),
854
- _step4;
1035
+ var _iterator5 = _createForOfIteratorHelper(productIds),
1036
+ _step5;
855
1037
  try {
856
- for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
857
- var id = _step4.value;
1038
+ for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
1039
+ var id = _step5.value;
858
1040
  if (this.store.map.has(id)) result.add(id);
859
1041
  }
860
1042
  } catch (err) {
861
- _iterator4.e(err);
1043
+ _iterator5.e(err);
862
1044
  } finally {
863
- _iterator4.f();
1045
+ _iterator5.f();
864
1046
  }
865
1047
  if (collectionIds.length === 0) return Array.from(result);
866
1048
  var collectionIdSet = new Set(collectionIds);
867
- var _iterator5 = _createForOfIteratorHelper(this.getProductsRef()),
868
- _step5;
1049
+ var _iterator6 = _createForOfIteratorHelper(this.getProductsRef()),
1050
+ _step6;
869
1051
  try {
870
- for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
871
- var product = _step5.value;
1052
+ for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {
1053
+ var product = _step6.value;
872
1054
  if (result.has(product.id)) continue;
873
1055
  if (!Array.isArray(product.collection)) continue;
874
1056
  var isInCollection = product.collection.some(function (collection) {
@@ -877,9 +1059,9 @@ export var ProductsModule = /*#__PURE__*/function (_BaseModule) {
877
1059
  if (isInCollection) result.add(product.id);
878
1060
  }
879
1061
  } catch (err) {
880
- _iterator5.e(err);
1062
+ _iterator6.e(err);
881
1063
  } finally {
882
- _iterator5.f();
1064
+ _iterator6.f();
883
1065
  }
884
1066
  return Array.from(result);
885
1067
  }
@@ -1098,37 +1280,48 @@ export var ProductsModule = /*#__PURE__*/function (_BaseModule) {
1098
1280
  this.logWarning('loadProductsByServer: ProductDataSource 不可用');
1099
1281
  return _context9.abrupt("return", []);
1100
1282
  case 3:
1283
+ this.pushProductFlowLog('loadProductsByServer.start', this.getProductStoreSnapshot());
1101
1284
  this.logInfo('开始通过 DataSource SSE 加载商品列表');
1102
1285
  t0 = performance.now();
1103
- _context9.prev = 5;
1286
+ _context9.prev = 6;
1104
1287
  tSSE = performance.now();
1105
- _context9.next = 9;
1288
+ _context9.next = 10;
1106
1289
  return this.productDataSource.run({
1107
1290
  sse: {}
1108
1291
  });
1109
- case 9:
1292
+ case 10:
1110
1293
  productList = _context9.sent;
1111
1294
  list = productList || [];
1112
1295
  perfMark('loadProductsByServer.SSE', performance.now() - tSSE, {
1113
1296
  count: list.length
1114
1297
  });
1298
+ this.pushProductFlowLog('loadProductsByServer.sseSuccess', {
1299
+ count: list.length
1300
+ });
1115
1301
  this.logInfo('通过 DataSource SSE 加载商品列表成功', {
1116
1302
  productCount: list.length,
1117
1303
  duration: "".concat(Math.round(performance.now() - t0), "ms")
1118
1304
  });
1119
- _context9.next = 15;
1120
- return this.saveProductsToIndexDB(list);
1121
- case 15:
1122
1305
  _context9.next = 17;
1123
- return this.core.effects.emit(ProductsHooks.onProductsLoaded, list);
1306
+ return this.replaceProductsSnapshotInIndexDB(list, 'loadProductsByServer');
1124
1307
  case 17:
1308
+ this.lastServerFullFetchAtMs = Date.now();
1309
+ _context9.next = 20;
1310
+ return this.core.effects.emit(ProductsHooks.onProductsLoaded, list);
1311
+ case 20:
1312
+ this.pushProductFlowLog('loadProductsByServer.done', _objectSpread({
1313
+ count: list.length
1314
+ }, this.getProductStoreSnapshot()));
1125
1315
  perfMark('loadProductsByServer', performance.now() - t0, {
1126
1316
  count: list.length
1127
1317
  });
1128
1318
  return _context9.abrupt("return", list);
1129
- case 21:
1130
- _context9.prev = 21;
1131
- _context9.t0 = _context9["catch"](5);
1319
+ case 25:
1320
+ _context9.prev = 25;
1321
+ _context9.t0 = _context9["catch"](6);
1322
+ this.pushProductFlowLog('loadProductsByServer.failed', {
1323
+ error: _context9.t0 instanceof Error ? _context9.t0.message : String(_context9.t0)
1324
+ });
1132
1325
  duration = Math.round(performance.now() - t0);
1133
1326
  errorMessage = _context9.t0 instanceof Error ? _context9.t0.message : String(_context9.t0);
1134
1327
  console.error('[Products] 加载商品数据失败:', _context9.t0);
@@ -1137,11 +1330,11 @@ export var ProductsModule = /*#__PURE__*/function (_BaseModule) {
1137
1330
  error: errorMessage
1138
1331
  });
1139
1332
  return _context9.abrupt("return", []);
1140
- case 28:
1333
+ case 33:
1141
1334
  case "end":
1142
1335
  return _context9.stop();
1143
1336
  }
1144
- }, _callee9, this, [[5, 21]]);
1337
+ }, _callee9, this, [[6, 25]]);
1145
1338
  }));
1146
1339
  function loadProductsByServer() {
1147
1340
  return _loadProductsByServer.apply(this, arguments);
@@ -1158,11 +1351,11 @@ export var ProductsModule = /*#__PURE__*/function (_BaseModule) {
1158
1351
  key: "fetchProductsByHttp",
1159
1352
  value: (function () {
1160
1353
  var _fetchProductsByHttp = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee10(params) {
1161
- var _ref13, _ref13$category_ids, category_ids, _ref13$product_ids, product_ids, _ref13$collection, collection, customer_id, cacheId, startTime, _this$otherParams3, _productsData$data, productsData, productList, duration, _duration2, errorMessage;
1354
+ var _ref15, _ref15$category_ids, category_ids, _ref15$product_ids, product_ids, _ref15$collection, collection, customer_id, cacheId, startTime, _this$otherParams3, _productsData$data, productsData, productList, duration, _duration2, errorMessage;
1162
1355
  return _regeneratorRuntime().wrap(function _callee10$(_context10) {
1163
1356
  while (1) switch (_context10.prev = _context10.next) {
1164
1357
  case 0:
1165
- _ref13 = params || {}, _ref13$category_ids = _ref13.category_ids, category_ids = _ref13$category_ids === void 0 ? [] : _ref13$category_ids, _ref13$product_ids = _ref13.product_ids, product_ids = _ref13$product_ids === void 0 ? [] : _ref13$product_ids, _ref13$collection = _ref13.collection, collection = _ref13$collection === void 0 ? [] : _ref13$collection, customer_id = _ref13.customer_id, cacheId = _ref13.cacheId;
1358
+ _ref15 = params || {}, _ref15$category_ids = _ref15.category_ids, category_ids = _ref15$category_ids === void 0 ? [] : _ref15$category_ids, _ref15$product_ids = _ref15.product_ids, product_ids = _ref15$product_ids === void 0 ? [] : _ref15$product_ids, _ref15$collection = _ref15.collection, collection = _ref15$collection === void 0 ? [] : _ref15$collection, customer_id = _ref15.customer_id, cacheId = _ref15.cacheId;
1166
1359
  this.logInfo('fetchProductsByHttp: 开始请求', {
1167
1360
  categoryIdsCount: category_ids.length,
1168
1361
  productIdsCount: product_ids.length,
@@ -1237,22 +1430,29 @@ export var ProductsModule = /*#__PURE__*/function (_BaseModule) {
1237
1430
  return _regeneratorRuntime().wrap(function _callee11$(_context11) {
1238
1431
  while (1) switch (_context11.prev = _context11.next) {
1239
1432
  case 0:
1240
- _context11.next = 2;
1433
+ this.pushProductFlowLog('loadProductsByServerHttp.start', _objectSpread({
1434
+ params: params || {}
1435
+ }, this.getProductStoreSnapshot()));
1436
+ _context11.next = 3;
1241
1437
  return this.fetchProductsByHttp(params);
1242
- case 2:
1438
+ case 3:
1243
1439
  productList = _context11.sent;
1244
1440
  if (!(productList.length > 0)) {
1245
- _context11.next = 8;
1441
+ _context11.next = 10;
1246
1442
  break;
1247
1443
  }
1248
- _context11.next = 6;
1249
- return this.saveProductsToIndexDB(productList);
1250
- case 6:
1251
- _context11.next = 8;
1444
+ _context11.next = 7;
1445
+ return this.replaceProductsSnapshotInIndexDB(productList, 'loadProductsByServerHttp');
1446
+ case 7:
1447
+ this.lastServerFullFetchAtMs = Date.now();
1448
+ _context11.next = 10;
1252
1449
  return this.core.effects.emit(ProductsHooks.onProductsLoaded, productList);
1253
- case 8:
1450
+ case 10:
1451
+ this.pushProductFlowLog('loadProductsByServerHttp.done', _objectSpread({
1452
+ count: productList.length
1453
+ }, this.getProductStoreSnapshot()));
1254
1454
  return _context11.abrupt("return", productList);
1255
- case 9:
1455
+ case 12:
1256
1456
  case "end":
1257
1457
  return _context11.stop();
1258
1458
  }
@@ -1310,18 +1510,18 @@ export var ProductsModule = /*#__PURE__*/function (_BaseModule) {
1310
1510
  key: "getProductsRefByIds",
1311
1511
  value: function getProductsRefByIds(ids) {
1312
1512
  var products = [];
1313
- var _iterator6 = _createForOfIteratorHelper(ids),
1314
- _step6;
1513
+ var _iterator7 = _createForOfIteratorHelper(ids),
1514
+ _step7;
1315
1515
  try {
1316
- for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {
1317
- var id = _step6.value;
1516
+ for (_iterator7.s(); !(_step7 = _iterator7.n()).done;) {
1517
+ var id = _step7.value;
1318
1518
  var product = this.store.map.get(id);
1319
1519
  if (product) products.push(product);
1320
1520
  }
1321
1521
  } catch (err) {
1322
- _iterator6.e(err);
1522
+ _iterator7.e(err);
1323
1523
  } finally {
1324
- _iterator6.f();
1524
+ _iterator7.f();
1325
1525
  }
1326
1526
  return products;
1327
1527
  }
@@ -1360,11 +1560,16 @@ export var ProductsModule = /*#__PURE__*/function (_BaseModule) {
1360
1560
  key: "removeProductsByIds",
1361
1561
  value: (function () {
1362
1562
  var _removeProductsByIds = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee14(ids) {
1363
- var idSet, _iterator7, _step7, _id, _iterator8, _step8, id, errorMessage, _iterator9, _step9, _step9$value, dateKey, cachedProducts;
1563
+ var idSet, _iterator8, _step8, _id, _iterator9, _step9, id, errorMessage, _iterator10, _step10, _step10$value, dateKey, cachedProducts;
1364
1564
  return _regeneratorRuntime().wrap(function _callee14$(_context14) {
1365
1565
  while (1) switch (_context14.prev = _context14.next) {
1366
1566
  case 0:
1367
1567
  idSet = new Set(ids);
1568
+ this.pushProductFlowLog('removeProductsByIds.start', _objectSpread({
1569
+ ids: ids,
1570
+ count: ids.length,
1571
+ writeStrategy: 'delete-by-id'
1572
+ }, this.getProductStoreSnapshot()));
1368
1573
  this.logInfo('removeProductsByIds', {
1369
1574
  ids: ids,
1370
1575
  count: ids.length
@@ -1372,81 +1577,91 @@ export var ProductsModule = /*#__PURE__*/function (_BaseModule) {
1372
1577
  this.store.list = this.store.list.filter(function (p) {
1373
1578
  return !idSet.has(p.id);
1374
1579
  });
1375
- _iterator7 = _createForOfIteratorHelper(ids);
1580
+ _iterator8 = _createForOfIteratorHelper(ids);
1376
1581
  try {
1377
- for (_iterator7.s(); !(_step7 = _iterator7.n()).done;) {
1378
- _id = _step7.value;
1582
+ for (_iterator8.s(); !(_step8 = _iterator8.n()).done;) {
1583
+ _id = _step8.value;
1379
1584
  this.store.map.delete(_id);
1380
1585
  }
1381
1586
  } catch (err) {
1382
- _iterator7.e(err);
1587
+ _iterator8.e(err);
1383
1588
  } finally {
1384
- _iterator7.f();
1589
+ _iterator8.f();
1385
1590
  }
1386
1591
  if (!this.dbManager) {
1387
- _context14.next = 30;
1592
+ _context14.next = 32;
1388
1593
  break;
1389
1594
  }
1390
- _context14.prev = 6;
1391
- _iterator8 = _createForOfIteratorHelper(ids);
1392
- _context14.prev = 8;
1393
- _iterator8.s();
1394
- case 10:
1395
- if ((_step8 = _iterator8.n()).done) {
1396
- _context14.next = 16;
1595
+ _context14.prev = 7;
1596
+ _iterator9 = _createForOfIteratorHelper(ids);
1597
+ _context14.prev = 9;
1598
+ _iterator9.s();
1599
+ case 11:
1600
+ if ((_step9 = _iterator9.n()).done) {
1601
+ _context14.next = 17;
1397
1602
  break;
1398
1603
  }
1399
- id = _step8.value;
1400
- _context14.next = 14;
1604
+ id = _step9.value;
1605
+ _context14.next = 15;
1401
1606
  return this.dbManager.delete(INDEXDB_STORE_NAME, id);
1402
- case 14:
1403
- _context14.next = 10;
1607
+ case 15:
1608
+ _context14.next = 11;
1404
1609
  break;
1405
- case 16:
1406
- _context14.next = 21;
1610
+ case 17:
1611
+ _context14.next = 22;
1407
1612
  break;
1408
- case 18:
1409
- _context14.prev = 18;
1410
- _context14.t0 = _context14["catch"](8);
1411
- _iterator8.e(_context14.t0);
1412
- case 21:
1413
- _context14.prev = 21;
1414
- _iterator8.f();
1415
- return _context14.finish(21);
1416
- case 24:
1417
- _context14.next = 30;
1613
+ case 19:
1614
+ _context14.prev = 19;
1615
+ _context14.t0 = _context14["catch"](9);
1616
+ _iterator9.e(_context14.t0);
1617
+ case 22:
1618
+ _context14.prev = 22;
1619
+ _iterator9.f();
1620
+ return _context14.finish(22);
1621
+ case 25:
1622
+ this.trackProductWrite('pubsub.removeProductsByIds', 'delete', ids.map(function (id) {
1623
+ return {
1624
+ id: id
1625
+ };
1626
+ }), Object.fromEntries(ids.map(function (id) {
1627
+ return [id, 'delete'];
1628
+ })), 'delete');
1629
+ _context14.next = 32;
1418
1630
  break;
1419
- case 26:
1420
- _context14.prev = 26;
1421
- _context14.t1 = _context14["catch"](6);
1631
+ case 28:
1632
+ _context14.prev = 28;
1633
+ _context14.t1 = _context14["catch"](7);
1422
1634
  errorMessage = _context14.t1 instanceof Error ? _context14.t1.message : String(_context14.t1);
1423
1635
  this.logError('removeProductsByIds: IndexDB 删除失败', {
1424
1636
  ids: ids,
1425
1637
  error: errorMessage
1426
1638
  });
1427
- case 30:
1428
- _iterator9 = _createForOfIteratorHelper(this.productsPriceCache.entries());
1639
+ case 32:
1640
+ _iterator10 = _createForOfIteratorHelper(this.productsPriceCache.entries());
1429
1641
  try {
1430
- for (_iterator9.s(); !(_step9 = _iterator9.n()).done;) {
1431
- _step9$value = _slicedToArray(_step9.value, 2), dateKey = _step9$value[0], cachedProducts = _step9$value[1];
1642
+ for (_iterator10.s(); !(_step10 = _iterator10.n()).done;) {
1643
+ _step10$value = _slicedToArray(_step10.value, 2), dateKey = _step10$value[0], cachedProducts = _step10$value[1];
1432
1644
  this.productsPriceCache.set(dateKey, cachedProducts.filter(function (p) {
1433
1645
  return !idSet.has(p.id);
1434
1646
  }));
1435
1647
  }
1436
1648
  } catch (err) {
1437
- _iterator9.e(err);
1649
+ _iterator10.e(err);
1438
1650
  } finally {
1439
- _iterator9.f();
1651
+ _iterator10.f();
1440
1652
  }
1441
1653
  this.core.effects.emit(ProductsHooks.onProductsChanged, this.store.list);
1654
+ this.pushProductFlowLog('removeProductsByIds.done', _objectSpread({
1655
+ ids: ids
1656
+ }, this.getProductStoreSnapshot()));
1442
1657
  this.logInfo('removeProductsByIds 完成', {
1443
1658
  remaining: this.store.list.length
1444
1659
  });
1445
- case 34:
1660
+ case 37:
1446
1661
  case "end":
1447
1662
  return _context14.stop();
1448
1663
  }
1449
- }, _callee14, this, [[6, 26], [8, 18, 21, 24]]);
1664
+ }, _callee14, this, [[7, 28], [9, 19, 22, 25]]);
1450
1665
  }));
1451
1666
  function removeProductsByIds(_x18) {
1452
1667
  return _removeProductsByIds.apply(this, arguments);
@@ -1467,10 +1682,11 @@ export var ProductsModule = /*#__PURE__*/function (_BaseModule) {
1467
1682
  while (1) switch (_context15.prev = _context15.next) {
1468
1683
  case 0:
1469
1684
  tTotal = performance.now();
1685
+ this.pushProductFlowLog('refreshProducts.start', this.getProductStoreSnapshot());
1470
1686
  this.logInfo('refreshProducts 开始');
1471
- _context15.next = 4;
1687
+ _context15.next = 5;
1472
1688
  return this.loadProductsByServer();
1473
- case 4:
1689
+ case 5:
1474
1690
  products = _context15.sent;
1475
1691
  if (products && products.length > 0) {
1476
1692
  // 服务器返回的数据已经是全新的,无需 cloneDeep
@@ -1486,8 +1702,12 @@ export var ProductsModule = /*#__PURE__*/function (_BaseModule) {
1486
1702
  perfMark('refreshProducts', performance.now() - tTotal, {
1487
1703
  count: this.store.list.length
1488
1704
  });
1705
+ this.pushProductFlowLog('refreshProducts.done', _objectSpread({
1706
+ count: this.store.list.length,
1707
+ durationMs: Math.round(performance.now() - tTotal)
1708
+ }, this.getProductStoreSnapshot()));
1489
1709
  return _context15.abrupt("return", this.store.list);
1490
- case 8:
1710
+ case 10:
1491
1711
  case "end":
1492
1712
  return _context15.stop();
1493
1713
  }
@@ -1606,64 +1826,302 @@ export var ProductsModule = /*#__PURE__*/function (_BaseModule) {
1606
1826
  return loadProductsFromIndexDB;
1607
1827
  }()
1608
1828
  /**
1609
- * 保存商品数据到 IndexDB(平铺存储)
1610
- * @private
1829
+ * 串行执行商品 IndexDB 写入,避免快照替换与增量 patch 并发交错。
1830
+ *
1831
+ * @example
1832
+ * await this.runInProductIndexDBSaveQueue(async () => {
1833
+ * await this.dbManager.bulkUpdate(INDEXDB_STORE_NAME, products)
1834
+ * })
1611
1835
  */
1612
1836
  )
1613
1837
  }, {
1614
- key: "saveProductsToIndexDB",
1838
+ key: "runInProductIndexDBSaveQueue",
1615
1839
  value: (function () {
1616
- var _saveProductsToIndexDB = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee18(products) {
1617
- var t0, errorMessage;
1840
+ var _runInProductIndexDBSaveQueue = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee18(task) {
1841
+ var queuedTask;
1618
1842
  return _regeneratorRuntime().wrap(function _callee18$(_context18) {
1619
1843
  while (1) switch (_context18.prev = _context18.next) {
1844
+ case 0:
1845
+ queuedTask = this.productIndexDBSaveQueue.then(task, task);
1846
+ this.productIndexDBSaveQueue = queuedTask.then(function () {
1847
+ return undefined;
1848
+ }, function () {
1849
+ return undefined;
1850
+ });
1851
+ return _context18.abrupt("return", queuedTask);
1852
+ case 3:
1853
+ case "end":
1854
+ return _context18.stop();
1855
+ }
1856
+ }, _callee18, this);
1857
+ }));
1858
+ function runInProductIndexDBSaveQueue(_x19) {
1859
+ return _runInProductIndexDBSaveQueue.apply(this, arguments);
1860
+ }
1861
+ return runInProductIndexDBSaveQueue;
1862
+ }()
1863
+ /**
1864
+ * 全量快照写入 IndexDB:clear + bulkUpdate,仅用于 SSE/HTTP 全量拉取。
1865
+ *
1866
+ * @example
1867
+ * await this.replaceProductsSnapshotInIndexDB(list, 'loadProductsByServer')
1868
+ */
1869
+ )
1870
+ }, {
1871
+ key: "replaceProductsSnapshotInIndexDB",
1872
+ value: (function () {
1873
+ var _replaceProductsSnapshotInIndexDB = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee20(products, source) {
1874
+ var _this7 = this;
1875
+ var errorMessage;
1876
+ return _regeneratorRuntime().wrap(function _callee20$(_context20) {
1877
+ while (1) switch (_context20.prev = _context20.next) {
1620
1878
  case 0:
1621
1879
  if (this.dbManager) {
1622
- _context18.next = 3;
1880
+ _context20.next = 4;
1623
1881
  break;
1624
1882
  }
1625
- this.logWarning('saveProductsToIndexDB: dbManager 不可用');
1626
- return _context18.abrupt("return");
1627
- case 3:
1628
- this.logInfo('开始保存商品数据到 IndexDB', {
1629
- productCount: products.length
1630
- });
1631
- _context18.prev = 4;
1632
- t0 = performance.now();
1633
- _context18.next = 8;
1634
- return this.dbManager.clear(INDEXDB_STORE_NAME);
1635
- case 8:
1636
- _context18.next = 10;
1637
- return this.dbManager.bulkUpdate(INDEXDB_STORE_NAME, products);
1638
- case 10:
1639
- perfMark('saveProductsToIndexDB', performance.now() - t0, {
1640
- count: products.length
1641
- });
1642
- console.log("[Products] \u5DF2\u5C06 ".concat(products.length, " \u4E2A\u5546\u54C1\u5E73\u94FA\u4FDD\u5B58\u5230 IndexDB"));
1643
- this.logInfo('商品数据已保存到 IndexDB', {
1644
- productCount: products.length
1883
+ this.pushProductFlowLog('replaceProductsSnapshotInIndexDB.skip', {
1884
+ source: source,
1885
+ reason: 'no_dbManager',
1886
+ inputCount: products.length
1645
1887
  });
1646
- _context18.next = 20;
1888
+ this.logWarning('replaceProductsSnapshotInIndexDB: dbManager 不可用');
1889
+ return _context20.abrupt("return");
1890
+ case 4:
1891
+ _context20.prev = 4;
1892
+ _context20.next = 7;
1893
+ return this.runInProductIndexDBSaveQueue( /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee19() {
1894
+ var t0, writeSeq;
1895
+ return _regeneratorRuntime().wrap(function _callee19$(_context19) {
1896
+ while (1) switch (_context19.prev = _context19.next) {
1897
+ case 0:
1898
+ _this7.pushProductFlowLog('replaceProductsSnapshotInIndexDB.start', {
1899
+ source: source,
1900
+ writeStrategy: 'clear+bulkUpdate',
1901
+ inputCount: products.length,
1902
+ storeListCount: _this7.store.list.length
1903
+ });
1904
+ _this7.logInfo('replaceProductsSnapshotInIndexDB 开始', {
1905
+ source: source,
1906
+ productCount: products.length
1907
+ });
1908
+ t0 = performance.now();
1909
+ _context19.next = 5;
1910
+ return _this7.dbManager.clear(INDEXDB_STORE_NAME);
1911
+ case 5:
1912
+ _this7.pushProductFlowLog('replaceProductsSnapshotInIndexDB.cleared', {
1913
+ source: source,
1914
+ inputCount: products.length
1915
+ });
1916
+ if (!(products.length > 0)) {
1917
+ _context19.next = 9;
1918
+ break;
1919
+ }
1920
+ _context19.next = 9;
1921
+ return _this7.dbManager.bulkUpdate(INDEXDB_STORE_NAME, products);
1922
+ case 9:
1923
+ writeSeq = _this7.trackProductWrite(source, 'clear+bulkUpdate', products, {}, 'snapshot');
1924
+ perfMark('replaceProductsSnapshotInIndexDB', performance.now() - t0, {
1925
+ count: products.length
1926
+ });
1927
+ _this7.pushProductFlowLog('replaceProductsSnapshotInIndexDB.done', {
1928
+ source: source,
1929
+ writeSeq: writeSeq,
1930
+ count: products.length
1931
+ });
1932
+ _this7.logInfo('replaceProductsSnapshotInIndexDB 完成', {
1933
+ source: source,
1934
+ productCount: products.length
1935
+ });
1936
+ case 13:
1937
+ case "end":
1938
+ return _context19.stop();
1939
+ }
1940
+ }, _callee19);
1941
+ })));
1942
+ case 7:
1943
+ _context20.next = 14;
1647
1944
  break;
1648
- case 15:
1649
- _context18.prev = 15;
1650
- _context18.t0 = _context18["catch"](4);
1651
- errorMessage = _context18.t0 instanceof Error ? _context18.t0.message : String(_context18.t0);
1652
- console.error('[Products] 保存数据到 IndexDB 失败:', _context18.t0);
1653
- this.logError('保存数据到 IndexDB 失败', {
1945
+ case 9:
1946
+ _context20.prev = 9;
1947
+ _context20.t0 = _context20["catch"](4);
1948
+ errorMessage = _context20.t0 instanceof Error ? _context20.t0.message : String(_context20.t0);
1949
+ this.pushProductFlowLog('replaceProductsSnapshotInIndexDB.error', {
1950
+ source: source,
1654
1951
  productCount: products.length,
1655
1952
  error: errorMessage
1656
1953
  });
1657
- case 20:
1954
+ this.logError('全量保存商品到 IndexDB 失败', {
1955
+ source: source,
1956
+ productCount: products.length,
1957
+ error: errorMessage
1958
+ });
1959
+ case 14:
1658
1960
  case "end":
1659
- return _context18.stop();
1961
+ return _context20.stop();
1962
+ }
1963
+ }, _callee20, this, [[4, 9]]);
1964
+ }));
1965
+ function replaceProductsSnapshotInIndexDB(_x20, _x21) {
1966
+ return _replaceProductsSnapshotInIndexDB.apply(this, arguments);
1967
+ }
1968
+ return replaceProductsSnapshotInIndexDB;
1969
+ }()
1970
+ /**
1971
+ * 增量 upsert 商品到 IndexDB,不清空表;用于 pubsub 批次合并后的变更商品。
1972
+ *
1973
+ * @example
1974
+ * await this.patchProductsInIndexDB(changedProducts, 'pubsub.processProductSyncMessages', mergeActions)
1975
+ */
1976
+ )
1977
+ }, {
1978
+ key: "patchProductsInIndexDB",
1979
+ value: (function () {
1980
+ var _patchProductsInIndexDB = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee22(products, source) {
1981
+ var _this8 = this;
1982
+ var mergeActions,
1983
+ validProducts,
1984
+ errorMessage,
1985
+ _args22 = arguments;
1986
+ return _regeneratorRuntime().wrap(function _callee22$(_context22) {
1987
+ while (1) switch (_context22.prev = _context22.next) {
1988
+ case 0:
1989
+ mergeActions = _args22.length > 2 && _args22[2] !== undefined ? _args22[2] : {};
1990
+ if (!(!this.dbManager || products.length === 0)) {
1991
+ _context22.next = 4;
1992
+ break;
1993
+ }
1994
+ this.pushProductFlowLog('patchProductsInIndexDB.skip', {
1995
+ source: source,
1996
+ hasDbManager: !!this.dbManager,
1997
+ inputCount: products.length
1998
+ });
1999
+ return _context22.abrupt("return");
2000
+ case 4:
2001
+ validProducts = products.filter(function (p) {
2002
+ return (p === null || p === void 0 ? void 0 : p.id) !== undefined && (p === null || p === void 0 ? void 0 : p.id) !== null;
2003
+ });
2004
+ if (!(validProducts.length === 0)) {
2005
+ _context22.next = 8;
2006
+ break;
2007
+ }
2008
+ this.pushProductFlowLog('patchProductsInIndexDB.skipNoId', {
2009
+ source: source,
2010
+ inputCount: products.length
2011
+ });
2012
+ return _context22.abrupt("return");
2013
+ case 8:
2014
+ _context22.prev = 8;
2015
+ _context22.next = 11;
2016
+ return this.runInProductIndexDBSaveQueue( /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee21() {
2017
+ var writeMethod, t0, _iterator11, _step11, product, writeSeq;
2018
+ return _regeneratorRuntime().wrap(function _callee21$(_context21) {
2019
+ while (1) switch (_context21.prev = _context21.next) {
2020
+ case 0:
2021
+ writeMethod = 'none';
2022
+ _this8.pushProductFlowLog('patchProductsInIndexDB.start', {
2023
+ source: source,
2024
+ writeStrategy: 'bulkUpdate-patch',
2025
+ count: validProducts.length,
2026
+ productIds: validProducts.map(function (p) {
2027
+ return p.id;
2028
+ }),
2029
+ storeListCount: _this8.store.list.length
2030
+ });
2031
+ _this8.logInfo('patchProductsInIndexDB 开始', {
2032
+ source: source,
2033
+ count: validProducts.length
2034
+ });
2035
+ t0 = performance.now();
2036
+ if (!(typeof _this8.dbManager.bulkUpdate === 'function')) {
2037
+ _context21.next = 10;
2038
+ break;
2039
+ }
2040
+ writeMethod = 'bulkUpdate';
2041
+ _context21.next = 8;
2042
+ return _this8.dbManager.bulkUpdate(INDEXDB_STORE_NAME, validProducts);
2043
+ case 8:
2044
+ _context21.next = 29;
2045
+ break;
2046
+ case 10:
2047
+ if (!(typeof _this8.dbManager.update === 'function')) {
2048
+ _context21.next = 29;
2049
+ break;
2050
+ }
2051
+ writeMethod = 'update';
2052
+ _iterator11 = _createForOfIteratorHelper(validProducts);
2053
+ _context21.prev = 13;
2054
+ _iterator11.s();
2055
+ case 15:
2056
+ if ((_step11 = _iterator11.n()).done) {
2057
+ _context21.next = 21;
2058
+ break;
2059
+ }
2060
+ product = _step11.value;
2061
+ _context21.next = 19;
2062
+ return _this8.dbManager.update(INDEXDB_STORE_NAME, product);
2063
+ case 19:
2064
+ _context21.next = 15;
2065
+ break;
2066
+ case 21:
2067
+ _context21.next = 26;
2068
+ break;
2069
+ case 23:
2070
+ _context21.prev = 23;
2071
+ _context21.t0 = _context21["catch"](13);
2072
+ _iterator11.e(_context21.t0);
2073
+ case 26:
2074
+ _context21.prev = 26;
2075
+ _iterator11.f();
2076
+ return _context21.finish(26);
2077
+ case 29:
2078
+ writeSeq = _this8.trackProductWrite(source, writeMethod, validProducts, mergeActions);
2079
+ perfMark('patchProductsInIndexDB', performance.now() - t0, {
2080
+ count: validProducts.length
2081
+ });
2082
+ _this8.pushProductFlowLog('patchProductsInIndexDB.done', {
2083
+ source: source,
2084
+ writeSeq: writeSeq,
2085
+ writeMethod: writeMethod,
2086
+ count: validProducts.length
2087
+ });
2088
+ _this8.logInfo('patchProductsInIndexDB 完成', {
2089
+ source: source,
2090
+ count: validProducts.length
2091
+ });
2092
+ case 33:
2093
+ case "end":
2094
+ return _context21.stop();
2095
+ }
2096
+ }, _callee21, null, [[13, 23, 26, 29]]);
2097
+ })));
2098
+ case 11:
2099
+ _context22.next = 18;
2100
+ break;
2101
+ case 13:
2102
+ _context22.prev = 13;
2103
+ _context22.t0 = _context22["catch"](8);
2104
+ errorMessage = _context22.t0 instanceof Error ? _context22.t0.message : String(_context22.t0);
2105
+ this.pushProductFlowLog('patchProductsInIndexDB.error', {
2106
+ source: source,
2107
+ error: errorMessage,
2108
+ productCount: validProducts.length
2109
+ });
2110
+ this.logError('增量保存商品到 IndexDB 失败', {
2111
+ source: source,
2112
+ error: errorMessage,
2113
+ productCount: validProducts.length
2114
+ });
2115
+ case 18:
2116
+ case "end":
2117
+ return _context22.stop();
1660
2118
  }
1661
- }, _callee18, this, [[4, 15]]);
2119
+ }, _callee22, this, [[8, 13]]);
1662
2120
  }));
1663
- function saveProductsToIndexDB(_x19) {
1664
- return _saveProductsToIndexDB.apply(this, arguments);
2121
+ function patchProductsInIndexDB(_x22, _x23) {
2122
+ return _patchProductsInIndexDB.apply(this, arguments);
1665
2123
  }
1666
- return saveProductsToIndexDB;
2124
+ return patchProductsInIndexDB;
1667
2125
  }()
1668
2126
  /**
1669
2127
  * 同步更新商品 Map 缓存
@@ -1676,17 +2134,17 @@ export var ProductsModule = /*#__PURE__*/function (_BaseModule) {
1676
2134
  value: function syncProductsMap() {
1677
2135
  var t0 = performance.now();
1678
2136
  this.store.map.clear();
1679
- var _iterator10 = _createForOfIteratorHelper(this.store.list),
1680
- _step10;
2137
+ var _iterator12 = _createForOfIteratorHelper(this.store.list),
2138
+ _step12;
1681
2139
  try {
1682
- for (_iterator10.s(); !(_step10 = _iterator10.n()).done;) {
1683
- var product = _step10.value;
2140
+ for (_iterator12.s(); !(_step12 = _iterator12.n()).done;) {
2141
+ var product = _step12.value;
1684
2142
  this.store.map.set(product.id, product);
1685
2143
  }
1686
2144
  } catch (err) {
1687
- _iterator10.e(err);
2145
+ _iterator12.e(err);
1688
2146
  } finally {
1689
- _iterator10.f();
2147
+ _iterator12.f();
1690
2148
  }
1691
2149
  perfMark('syncProductsMap', performance.now() - t0, {
1692
2150
  count: this.store.map.size
@@ -1700,26 +2158,27 @@ export var ProductsModule = /*#__PURE__*/function (_BaseModule) {
1700
2158
  }, {
1701
2159
  key: "preload",
1702
2160
  value: (function () {
1703
- var _preload = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee19() {
2161
+ var _preload = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee23() {
1704
2162
  var _products$length3;
1705
2163
  var tTotal, _cachedData$length, tIndexDB, cachedData, tSync, errorMessage, tServer, products, _tSync;
1706
- return _regeneratorRuntime().wrap(function _callee19$(_context19) {
1707
- while (1) switch (_context19.prev = _context19.next) {
2164
+ return _regeneratorRuntime().wrap(function _callee23$(_context23) {
2165
+ while (1) switch (_context23.prev = _context23.next) {
1708
2166
  case 0:
1709
2167
  console.log('[Products] 开始预加载数据...');
1710
2168
  tTotal = performance.now();
2169
+ this.pushProductFlowLog('preload.start', this.getProductStoreSnapshot());
1711
2170
  this.logInfo('开始预加载数据');
1712
- _context19.prev = 3;
2171
+ _context23.prev = 4;
1713
2172
  tIndexDB = performance.now();
1714
- _context19.next = 7;
2173
+ _context23.next = 8;
1715
2174
  return this.loadProductsFromIndexDB();
1716
- case 7:
1717
- cachedData = _context19.sent;
2175
+ case 8:
2176
+ cachedData = _context23.sent;
1718
2177
  perfMark('preload.loadFromIndexDB', performance.now() - tIndexDB, {
1719
2178
  count: (_cachedData$length = cachedData === null || cachedData === void 0 ? void 0 : cachedData.length) !== null && _cachedData$length !== void 0 ? _cachedData$length : 0
1720
2179
  });
1721
2180
  if (!(cachedData && cachedData.length > 0)) {
1722
- _context19.next = 19;
2181
+ _context23.next = 22;
1723
2182
  break;
1724
2183
  }
1725
2184
  console.log("[Products] \u4ECE IndexDB \u52A0\u8F7D\u4E86 ".concat(cachedData.length, " \u4E2A\u5546\u54C1"));
@@ -1740,26 +2199,31 @@ export var ProductsModule = /*#__PURE__*/function (_BaseModule) {
1740
2199
  duration: "".concat(Math.round(performance.now() - tTotal), "ms"),
1741
2200
  source: 'IndexDB'
1742
2201
  });
1743
- return _context19.abrupt("return");
1744
- case 19:
2202
+ this.pushProductFlowLog('preload.done', _objectSpread({
2203
+ source: 'IndexDB',
2204
+ loadedCount: cachedData.length
2205
+ }, this.getProductStoreSnapshot()));
2206
+ this.lastPreloadCompletedAtMs = Date.now();
2207
+ return _context23.abrupt("return");
2208
+ case 22:
1745
2209
  console.log('[Products] IndexDB 中没有缓存数据,从服务器加载...');
1746
2210
  this.logInfo('IndexDB 中没有缓存数据,准备从服务器加载');
1747
- _context19.next = 28;
2211
+ _context23.next = 31;
1748
2212
  break;
1749
- case 23:
1750
- _context19.prev = 23;
1751
- _context19.t0 = _context19["catch"](3);
1752
- errorMessage = _context19.t0 instanceof Error ? _context19.t0.message : String(_context19.t0);
1753
- console.warn('[Products] 从 IndexDB 加载数据失败:', _context19.t0);
2213
+ case 26:
2214
+ _context23.prev = 26;
2215
+ _context23.t0 = _context23["catch"](4);
2216
+ errorMessage = _context23.t0 instanceof Error ? _context23.t0.message : String(_context23.t0);
2217
+ console.warn('[Products] 从 IndexDB 加载数据失败:', _context23.t0);
1754
2218
  this.logWarning('从 IndexDB 加载数据失败,准备从服务器加载', {
1755
2219
  error: errorMessage
1756
2220
  });
1757
- case 28:
2221
+ case 31:
1758
2222
  tServer = performance.now();
1759
- _context19.next = 31;
2223
+ _context23.next = 34;
1760
2224
  return this.loadProductsByServer();
1761
- case 31:
1762
- products = _context19.sent;
2225
+ case 34:
2226
+ products = _context23.sent;
1763
2227
  perfMark('preload.loadFromServer', performance.now() - tServer, {
1764
2228
  count: (_products$length3 = products === null || products === void 0 ? void 0 : products.length) !== null && _products$length3 !== void 0 ? _products$length3 : 0
1765
2229
  });
@@ -1781,7 +2245,13 @@ export var ProductsModule = /*#__PURE__*/function (_BaseModule) {
1781
2245
  duration: "".concat(Math.round(performance.now() - tTotal), "ms"),
1782
2246
  source: 'Server'
1783
2247
  });
2248
+ this.pushProductFlowLog('preload.done', _objectSpread({
2249
+ source: 'Server',
2250
+ loadedCount: products.length
2251
+ }, this.getProductStoreSnapshot()));
2252
+ this.lastPreloadCompletedAtMs = Date.now();
1784
2253
  } else {
2254
+ this.pushProductFlowLog('preload.empty', this.getProductStoreSnapshot());
1785
2255
  perfMark('preload(empty)', performance.now() - tTotal, {
1786
2256
  source: 'empty'
1787
2257
  });
@@ -1789,11 +2259,11 @@ export var ProductsModule = /*#__PURE__*/function (_BaseModule) {
1789
2259
  duration: "".concat(Math.round(performance.now() - tTotal), "ms")
1790
2260
  });
1791
2261
  }
1792
- case 34:
2262
+ case 37:
1793
2263
  case "end":
1794
- return _context19.stop();
2264
+ return _context23.stop();
1795
2265
  }
1796
- }, _callee19, this, [[3, 23]]);
2266
+ }, _callee23, this, [[4, 26]]);
1797
2267
  }));
1798
2268
  function preload() {
1799
2269
  return _preload.apply(this, arguments);
@@ -1828,7 +2298,7 @@ export var ProductsModule = /*#__PURE__*/function (_BaseModule) {
1828
2298
  }, {
1829
2299
  key: "setupProductSync",
1830
2300
  value: function setupProductSync() {
1831
- var _this6 = this;
2301
+ var _this9 = this;
1832
2302
  if (!this.productDataSource) {
1833
2303
  this.logWarning('setupProductSync: ProductDataSource 不可用,跳过同步初始化');
1834
2304
  return;
@@ -1838,20 +2308,31 @@ export var ProductsModule = /*#__PURE__*/function (_BaseModule) {
1838
2308
  var data = (message === null || message === void 0 ? void 0 : message.data) || message;
1839
2309
  if (!data) return;
1840
2310
  console.log("[ProductsModule] \u6536\u5230\u540C\u6B65\u6D88\u606F [".concat(channelKey, "]:"), data);
1841
- _this6.logInfo('收到同步消息', {
2311
+ _this9.logInfo('收到同步消息', {
1842
2312
  channelKey: channelKey,
1843
2313
  action: data.action,
1844
2314
  id: data.id,
1845
2315
  action_filed: data.action_filed
1846
2316
  });
1847
- _this6.pendingSyncMessages.push(_objectSpread(_objectSpread({}, data), {}, {
2317
+ _this9.pendingSyncMessages.push(_objectSpread(_objectSpread({}, data), {}, {
1848
2318
  _channelKey: channelKey
1849
2319
  }));
1850
- if (_this6.syncTimer) {
1851
- clearTimeout(_this6.syncTimer);
2320
+ _this9.pushProductFlowLog('pubsub.messageEnqueued', {
2321
+ channelKey: channelKey,
2322
+ action: data.action,
2323
+ operation: data.operation,
2324
+ id: data.id,
2325
+ ids: data.ids,
2326
+ hasBody: !!data.body,
2327
+ changeTypes: data.change_types,
2328
+ pendingSyncCount: _this9.pendingSyncMessages.length,
2329
+ debounceMs: PRODUCT_SYNC_DEBOUNCE_MS
2330
+ });
2331
+ if (_this9.syncTimer) {
2332
+ clearTimeout(_this9.syncTimer);
1852
2333
  }
1853
- _this6.syncTimer = setTimeout(function () {
1854
- _this6.processProductSyncMessages();
2334
+ _this9.syncTimer = setTimeout(function () {
2335
+ _this9.processProductSyncMessages();
1855
2336
  }, PRODUCT_SYNC_DEBOUNCE_MS);
1856
2337
  };
1857
2338
  };
@@ -1859,7 +2340,7 @@ export var ProductsModule = /*#__PURE__*/function (_BaseModule) {
1859
2340
  pubsub: {
1860
2341
  callback: function callback(res) {
1861
2342
  console.log('sse_products_callback', res);
1862
- _this6.logInfo('sse_products_callback: 收到同步消息', {
2343
+ _this9.logInfo('sse_products_callback: 收到同步消息', {
1863
2344
  data: res === null || res === void 0 ? void 0 : res.data
1864
2345
  });
1865
2346
  if (!(res !== null && res !== void 0 && res.data)) return;
@@ -1869,7 +2350,7 @@ export var ProductsModule = /*#__PURE__*/function (_BaseModule) {
1869
2350
  }
1870
2351
  }
1871
2352
  }).catch(function (err) {
1872
- _this6.logError('setupProductSync: DataSource run 出错', {
2353
+ _this9.logError('setupProductSync: DataSource run 出错', {
1873
2354
  error: err instanceof Error ? err.message : String(err)
1874
2355
  });
1875
2356
  });
@@ -1897,19 +2378,22 @@ export var ProductsModule = /*#__PURE__*/function (_BaseModule) {
1897
2378
  }, {
1898
2379
  key: "processProductSyncMessages",
1899
2380
  value: (function () {
1900
- var _processProductSyncMessages = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee20() {
1901
- var messages, deleteIds, bodyUpdates, sseRefreshIds, priceRefreshIds, shouldClearPriceCache, _iterator11, _step11, msg, channelKey, _msg$relation_product, _msg$change_types, _msg$ids2, _msg$ids, ids, bodyId, _bodyId, _msg$relation_product2, _msg$relation_product3, uniqueDeleteIds, uniqueSSEIds, uniquePriceIds, freshProducts, allChangedIds, hasChanges, errorMessage;
1902
- return _regeneratorRuntime().wrap(function _callee20$(_context20) {
1903
- while (1) switch (_context20.prev = _context20.next) {
2381
+ var _processProductSyncMessages = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee24() {
2382
+ var messages, deleteIds, bodyUpdates, sseRefreshIds, priceRefreshIds, shouldClearPriceCache, _iterator13, _step13, msg, channelKey, _msg$relation_product, _msg$change_types, _msg$ids2, _msg$ids, ids, bodyId, _bodyId, _msg$relation_product2, _msg$relation_product3, uniqueDeleteIds, uniqueSSEIds, uniquePriceIds, patchProductMap, patchMergeActions, storeMutated, bodyResult, _iterator14, _step14, product, freshProducts, mergeResult, _iterator15, _step15, _product, patchProducts, allChangedIds, hasChanges, errorMessage;
2383
+ return _regeneratorRuntime().wrap(function _callee24$(_context24) {
2384
+ while (1) switch (_context24.prev = _context24.next) {
1904
2385
  case 0:
1905
2386
  messages = _toConsumableArray(this.pendingSyncMessages);
1906
2387
  this.pendingSyncMessages = [];
1907
2388
  if (!(messages.length === 0)) {
1908
- _context20.next = 4;
2389
+ _context24.next = 4;
1909
2390
  break;
1910
2391
  }
1911
- return _context20.abrupt("return");
2392
+ return _context24.abrupt("return");
1912
2393
  case 4:
2394
+ this.pushProductFlowLog('processProductSyncMessages.start', _objectSpread({
2395
+ messageCount: messages.length
2396
+ }, this.getProductStoreSnapshot()));
1913
2397
  this.logInfo('processProductSyncMessages: 开始处理', {
1914
2398
  count: messages.length
1915
2399
  });
@@ -1918,18 +2402,18 @@ export var ProductsModule = /*#__PURE__*/function (_BaseModule) {
1918
2402
  sseRefreshIds = [];
1919
2403
  priceRefreshIds = [];
1920
2404
  shouldClearPriceCache = false;
1921
- _iterator11 = _createForOfIteratorHelper(messages);
1922
- _context20.prev = 11;
1923
- _iterator11.s();
1924
- case 13:
1925
- if ((_step11 = _iterator11.n()).done) {
1926
- _context20.next = 36;
2405
+ _iterator13 = _createForOfIteratorHelper(messages);
2406
+ _context24.prev = 12;
2407
+ _iterator13.s();
2408
+ case 14:
2409
+ if ((_step13 = _iterator13.n()).done) {
2410
+ _context24.next = 37;
1927
2411
  break;
1928
2412
  }
1929
- msg = _step11.value;
2413
+ msg = _step13.value;
1930
2414
  channelKey = msg._channelKey || msg.module || 'product';
1931
2415
  if (!(channelKey === 'product')) {
1932
- _context20.next = 33;
2416
+ _context24.next = 34;
1933
2417
  break;
1934
2418
  }
1935
2419
  if ((_msg$relation_product = msg.relation_product_ids) !== null && _msg$relation_product !== void 0 && _msg$relation_product.length) {
@@ -1937,14 +2421,14 @@ export var ProductsModule = /*#__PURE__*/function (_BaseModule) {
1937
2421
  }
1938
2422
  // 1. 删除场景:operation === 'delete' 或 action === 'delete'
1939
2423
  if (!(msg.operation === 'delete' || msg.action === 'delete')) {
1940
- _context20.next = 21;
2424
+ _context24.next = 22;
1941
2425
  break;
1942
2426
  }
1943
2427
  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);
1944
- return _context20.abrupt("continue", 34);
1945
- case 21:
2428
+ return _context24.abrupt("continue", 35);
2429
+ case 22:
1946
2430
  if (!((_msg$change_types = msg.change_types) !== null && _msg$change_types !== void 0 && _msg$change_types.includes('price'))) {
1947
- _context20.next = 26;
2431
+ _context24.next = 27;
1948
2432
  break;
1949
2433
  }
1950
2434
  ids = msg.ids || (msg.id ? [msg.id] : []);
@@ -1953,25 +2437,25 @@ export var ProductsModule = /*#__PURE__*/function (_BaseModule) {
1953
2437
  bodyId = msg.body.id;
1954
2438
  if (bodyId) bodyUpdates.set(bodyId, msg.body);
1955
2439
  }
1956
- return _context20.abrupt("continue", 34);
1957
- case 26:
2440
+ return _context24.abrupt("continue", 35);
2441
+ case 27:
1958
2442
  if (!msg.body) {
1959
- _context20.next = 30;
2443
+ _context24.next = 31;
1960
2444
  break;
1961
2445
  }
1962
2446
  _bodyId = msg.body.id || msg.id;
1963
2447
  if (_bodyId) bodyUpdates.set(_bodyId, msg.body);
1964
- return _context20.abrupt("continue", 34);
1965
- case 30:
2448
+ return _context24.abrupt("continue", 35);
2449
+ case 31:
1966
2450
  // 4. 其他情况(有 ids 无 body 无 change_types)→ SSE 拉取
1967
2451
  if ((_msg$ids2 = msg.ids) !== null && _msg$ids2 !== void 0 && _msg$ids2.length) {
1968
2452
  sseRefreshIds.push.apply(sseRefreshIds, _toConsumableArray(msg.ids));
1969
2453
  } else if (msg.id) {
1970
2454
  sseRefreshIds.push(msg.id);
1971
2455
  }
1972
- _context20.next = 34;
2456
+ _context24.next = 35;
1973
2457
  break;
1974
- case 33:
2458
+ case 34:
1975
2459
  if (channelKey === 'product_quotation') {
1976
2460
  // 报价单变更影响范围大,标记清除全量价格缓存
1977
2461
  shouldClearPriceCache = true;
@@ -1983,58 +2467,128 @@ export var ProductsModule = /*#__PURE__*/function (_BaseModule) {
1983
2467
  sseRefreshIds.push.apply(sseRefreshIds, _toConsumableArray(msg.relation_product_ids));
1984
2468
  }
1985
2469
  }
1986
- case 34:
1987
- _context20.next = 13;
2470
+ case 35:
2471
+ _context24.next = 14;
1988
2472
  break;
1989
- case 36:
1990
- _context20.next = 41;
2473
+ case 37:
2474
+ _context24.next = 42;
1991
2475
  break;
1992
- case 38:
1993
- _context20.prev = 38;
1994
- _context20.t0 = _context20["catch"](11);
1995
- _iterator11.e(_context20.t0);
1996
- case 41:
1997
- _context20.prev = 41;
1998
- _iterator11.f();
1999
- return _context20.finish(41);
2000
- case 44:
2476
+ case 39:
2477
+ _context24.prev = 39;
2478
+ _context24.t0 = _context24["catch"](12);
2479
+ _iterator13.e(_context24.t0);
2480
+ case 42:
2481
+ _context24.prev = 42;
2482
+ _iterator13.f();
2483
+ return _context24.finish(42);
2484
+ case 45:
2001
2485
  uniqueDeleteIds = _toConsumableArray(new Set(deleteIds));
2002
2486
  uniqueSSEIds = _toConsumableArray(new Set(sseRefreshIds));
2003
- uniquePriceIds = _toConsumableArray(new Set(priceRefreshIds)); // 1. 处理删除
2487
+ uniquePriceIds = _toConsumableArray(new Set(priceRefreshIds));
2488
+ this.pushProductFlowLog('processProductSyncMessages.parsed', {
2489
+ deleteIds: uniqueDeleteIds,
2490
+ bodyUpdateIds: _toConsumableArray(bodyUpdates.keys()),
2491
+ sseRefreshIds: uniqueSSEIds,
2492
+ priceRefreshIds: uniquePriceIds,
2493
+ shouldClearPriceCache: shouldClearPriceCache
2494
+ });
2495
+
2496
+ // 1. 处理删除
2004
2497
  if (!(uniqueDeleteIds.length > 0)) {
2005
- _context20.next = 50;
2498
+ _context24.next = 52;
2006
2499
  break;
2007
2500
  }
2008
- _context20.next = 50;
2501
+ _context24.next = 52;
2009
2502
  return this.removeProductsByIds(uniqueDeleteIds);
2010
- case 50:
2503
+ case 52:
2504
+ /** 本批次待 patch 的商品(按 id 去重,SSE 覆盖 body) */
2505
+ patchProductMap = new Map();
2506
+ patchMergeActions = {};
2507
+ storeMutated = uniqueDeleteIds.length > 0; // 2. 处理 body 直接覆盖(仅内存,IndexDB 批次末统一 patch)
2011
2508
  if (!(bodyUpdates.size > 0)) {
2012
- _context20.next = 53;
2509
+ _context24.next = 62;
2013
2510
  break;
2014
2511
  }
2015
- _context20.next = 53;
2016
- return this.applyBodyUpdatesToStore(bodyUpdates);
2017
- case 53:
2512
+ _context24.next = 58;
2513
+ return this.applyBodyUpdatesToStore(bodyUpdates, {
2514
+ skipIndexDB: true,
2515
+ skipEmit: true
2516
+ });
2517
+ case 58:
2518
+ bodyResult = _context24.sent;
2519
+ _iterator14 = _createForOfIteratorHelper(bodyResult.changedProducts);
2520
+ try {
2521
+ for (_iterator14.s(); !(_step14 = _iterator14.n()).done;) {
2522
+ product = _step14.value;
2523
+ patchProductMap.set(product.id, product);
2524
+ patchMergeActions[product.id] = bodyResult.mergeActions[product.id];
2525
+ }
2526
+ } catch (err) {
2527
+ _iterator14.e(err);
2528
+ } finally {
2529
+ _iterator14.f();
2530
+ }
2531
+ storeMutated = true;
2532
+ case 62:
2533
+ // 3. 处理 SSE 增量拉取(仅内存,IndexDB 批次末统一 patch)
2534
+ freshProducts = [];
2018
2535
  if (!(uniqueSSEIds.length > 0)) {
2019
- _context20.next = 61;
2536
+ _context24.next = 75;
2020
2537
  break;
2021
2538
  }
2022
- _context20.next = 56;
2539
+ _context24.next = 66;
2023
2540
  return this.fetchProductsBySSE(uniqueSSEIds);
2024
- case 56:
2025
- freshProducts = _context20.sent;
2541
+ case 66:
2542
+ freshProducts = _context24.sent;
2026
2543
  if (!(freshProducts.length > 0)) {
2027
- _context20.next = 60;
2544
+ _context24.next = 74;
2028
2545
  break;
2029
2546
  }
2030
- _context20.next = 60;
2031
- return this.mergeProductsToStore(freshProducts);
2032
- case 60:
2547
+ _context24.next = 70;
2548
+ return this.mergeProductsToStore(freshProducts, {
2549
+ skipIndexDB: true,
2550
+ skipEmit: true
2551
+ });
2552
+ case 70:
2553
+ mergeResult = _context24.sent;
2554
+ _iterator15 = _createForOfIteratorHelper(mergeResult.changedProducts);
2555
+ try {
2556
+ for (_iterator15.s(); !(_step15 = _iterator15.n()).done;) {
2557
+ _product = _step15.value;
2558
+ patchProductMap.set(_product.id, _product);
2559
+ patchMergeActions[_product.id] = mergeResult.mergeActions[_product.id];
2560
+ }
2561
+ } catch (err) {
2562
+ _iterator15.e(err);
2563
+ } finally {
2564
+ _iterator15.f();
2565
+ }
2566
+ storeMutated = true;
2567
+ case 74:
2033
2568
  this.logInfo('processProductSyncMessages: SSE 增量更新完成123', {
2034
2569
  requestedCount: uniqueSSEIds.length,
2035
2570
  receivedCount: freshProducts.length
2036
2571
  });
2037
- case 61:
2572
+ case 75:
2573
+ patchProducts = _toConsumableArray(patchProductMap.values());
2574
+ if (!(patchProducts.length > 0)) {
2575
+ _context24.next = 80;
2576
+ break;
2577
+ }
2578
+ _context24.next = 79;
2579
+ return this.patchProductsInIndexDB(patchProducts, 'pubsub.processProductSyncMessages', patchMergeActions);
2580
+ case 79:
2581
+ this.pushProductFlowLog('processProductSyncMessages.patchDone', {
2582
+ patchCount: patchProducts.length,
2583
+ patchProductIds: patchProducts.map(function (p) {
2584
+ return p.id;
2585
+ })
2586
+ });
2587
+ case 80:
2588
+ if (storeMutated) {
2589
+ this.core.effects.emit(ProductsHooks.onProductsChanged, this.store.list);
2590
+ }
2591
+
2038
2592
  // 收集所有非 delete 的变更 IDs(body + SSE + price),用于增量更新价格缓存
2039
2593
  allChangedIds = _toConsumableArray(new Set([].concat(_toConsumableArray(Array.from(bodyUpdates.keys())), _toConsumableArray(uniqueSSEIds), _toConsumableArray(uniquePriceIds))));
2040
2594
  this.logInfo('processProductSyncMessages: 处理完成123', {
@@ -2047,41 +2601,50 @@ export var ProductsModule = /*#__PURE__*/function (_BaseModule) {
2047
2601
  });
2048
2602
  hasChanges = uniqueDeleteIds.length > 0 || allChangedIds.length > 0 || shouldClearPriceCache;
2049
2603
  if (hasChanges) {
2050
- _context20.next = 67;
2604
+ _context24.next = 88;
2051
2605
  break;
2052
2606
  }
2607
+ this.pushProductFlowLog('processProductSyncMessages.noChanges', {});
2053
2608
  this.logInfo('processProductSyncMessages: 没有变更,不触发 onProductsSyncCompleted');
2054
- return _context20.abrupt("return");
2055
- case 67:
2609
+ return _context24.abrupt("return");
2610
+ case 88:
2056
2611
  if (!shouldClearPriceCache) {
2057
- _context20.next = 78;
2612
+ _context24.next = 99;
2058
2613
  break;
2059
2614
  }
2060
- _context20.prev = 68;
2061
- _context20.next = 71;
2615
+ _context24.prev = 89;
2616
+ _context24.next = 92;
2062
2617
  return this.refreshQuotationPriceBridge();
2063
- case 71:
2064
- _context20.next = 77;
2618
+ case 92:
2619
+ _context24.next = 98;
2065
2620
  break;
2066
- case 73:
2067
- _context20.prev = 73;
2068
- _context20.t1 = _context20["catch"](68);
2069
- errorMessage = _context20.t1 instanceof Error ? _context20.t1.message : String(_context20.t1);
2621
+ case 94:
2622
+ _context24.prev = 94;
2623
+ _context24.t1 = _context24["catch"](89);
2624
+ errorMessage = _context24.t1 instanceof Error ? _context24.t1.message : String(_context24.t1);
2070
2625
  this.logError('报价单桥接刷新失败,将继续清理价格缓存', {
2071
2626
  error: errorMessage
2072
2627
  });
2073
- case 77:
2628
+ case 98:
2074
2629
  this.clearPriceCache();
2075
- case 78:
2076
- _context20.next = 80;
2630
+ case 99:
2631
+ _context24.next = 101;
2077
2632
  return this.core.effects.emit(ProductsHooks.onProductsSyncCompleted, {
2078
2633
  changedIds: allChangedIds
2079
2634
  });
2080
- case 80:
2635
+ case 101:
2636
+ this.pushProductFlowLog('processProductSyncMessages.done', _objectSpread({
2637
+ deleteCount: uniqueDeleteIds.length,
2638
+ bodyUpdateCount: bodyUpdates.size,
2639
+ sseRefreshCount: uniqueSSEIds.length,
2640
+ allChangedIds: allChangedIds,
2641
+ shouldClearPriceCache: shouldClearPriceCache
2642
+ }, this.getProductStoreSnapshot()));
2643
+ case 102:
2081
2644
  case "end":
2082
- return _context20.stop();
2645
+ return _context24.stop();
2083
2646
  }
2084
- }, _callee20, this, [[11, 38, 41, 44], [68, 73]]);
2647
+ }, _callee24, this, [[12, 39, 42, 45], [89, 94]]);
2085
2648
  }));
2086
2649
  function processProductSyncMessages() {
2087
2650
  return _processProductSyncMessages.apply(this, arguments);
@@ -2096,25 +2659,25 @@ export var ProductsModule = /*#__PURE__*/function (_BaseModule) {
2096
2659
  }, {
2097
2660
  key: "fetchProductsBySSE",
2098
2661
  value: (function () {
2099
- var _fetchProductsBySSE = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee21(ids) {
2662
+ var _fetchProductsBySSE = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee25(ids) {
2100
2663
  var t0, productList, list, errorMessage;
2101
- return _regeneratorRuntime().wrap(function _callee21$(_context21) {
2102
- while (1) switch (_context21.prev = _context21.next) {
2664
+ return _regeneratorRuntime().wrap(function _callee25$(_context25) {
2665
+ while (1) switch (_context25.prev = _context25.next) {
2103
2666
  case 0:
2104
2667
  if (this.productDataSource) {
2105
- _context21.next = 3;
2668
+ _context25.next = 3;
2106
2669
  break;
2107
2670
  }
2108
2671
  this.logWarning('fetchProductsBySSE: ProductDataSource 不可用');
2109
- return _context21.abrupt("return", []);
2672
+ return _context25.abrupt("return", []);
2110
2673
  case 3:
2111
2674
  this.logInfo('fetchProductsBySSE: 开始', {
2112
2675
  ids: ids,
2113
2676
  count: ids.length
2114
2677
  });
2115
2678
  t0 = performance.now();
2116
- _context21.prev = 5;
2117
- _context21.next = 8;
2679
+ _context25.prev = 5;
2680
+ _context25.next = 8;
2118
2681
  return this.productDataSource.run({
2119
2682
  sse: {
2120
2683
  query: {
@@ -2124,7 +2687,7 @@ export var ProductsModule = /*#__PURE__*/function (_BaseModule) {
2124
2687
  }
2125
2688
  });
2126
2689
  case 8:
2127
- productList = _context21.sent;
2690
+ productList = _context25.sent;
2128
2691
  list = productList || [];
2129
2692
  perfMark('fetchProductsBySSE', performance.now() - t0, {
2130
2693
  count: list.length
@@ -2134,23 +2697,23 @@ export var ProductsModule = /*#__PURE__*/function (_BaseModule) {
2134
2697
  receivedCount: list.length,
2135
2698
  duration: "".concat(Math.round(performance.now() - t0), "ms")
2136
2699
  });
2137
- return _context21.abrupt("return", list);
2700
+ return _context25.abrupt("return", list);
2138
2701
  case 15:
2139
- _context21.prev = 15;
2140
- _context21.t0 = _context21["catch"](5);
2141
- errorMessage = _context21.t0 instanceof Error ? _context21.t0.message : String(_context21.t0);
2702
+ _context25.prev = 15;
2703
+ _context25.t0 = _context25["catch"](5);
2704
+ errorMessage = _context25.t0 instanceof Error ? _context25.t0.message : String(_context25.t0);
2142
2705
  this.logError('fetchProductsBySSE: 失败', {
2143
2706
  ids: ids,
2144
2707
  error: errorMessage
2145
2708
  });
2146
- return _context21.abrupt("return", []);
2709
+ return _context25.abrupt("return", []);
2147
2710
  case 20:
2148
2711
  case "end":
2149
- return _context21.stop();
2712
+ return _context25.stop();
2150
2713
  }
2151
- }, _callee21, this, [[5, 15]]);
2714
+ }, _callee25, this, [[5, 15]]);
2152
2715
  }));
2153
- function fetchProductsBySSE(_x20) {
2716
+ function fetchProductsBySSE(_x24) {
2154
2717
  return _fetchProductsBySSE.apply(this, arguments);
2155
2718
  }
2156
2719
  return fetchProductsBySSE;
@@ -2158,63 +2721,96 @@ export var ProductsModule = /*#__PURE__*/function (_BaseModule) {
2158
2721
  /**
2159
2722
  * 将 body 完整数据直接覆盖到本地 store(不调用报价单接口)
2160
2723
  * 已存在的 → 直接替换;不存在的 → 追加
2161
- * 同时更新 Map 缓存、IndexDB,触发 onProductsChanged
2162
- * 价格缓存由 processProductSyncMessages 末尾统一清除
2724
+ *
2725
+ * @example
2726
+ * await this.applyBodyUpdatesToStore(bodyUpdates, { skipIndexDB: true })
2163
2727
  */
2164
2728
  )
2165
2729
  }, {
2166
2730
  key: "applyBodyUpdatesToStore",
2167
2731
  value: (function () {
2168
- var _applyBodyUpdatesToStore = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee22(bodyUpdates) {
2169
- var updatedCount, newCount, appliedIds, _iterator12, _step12, _step12$value, id, body;
2170
- return _regeneratorRuntime().wrap(function _callee22$(_context22) {
2171
- while (1) switch (_context22.prev = _context22.next) {
2732
+ var _applyBodyUpdatesToStore = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee26(bodyUpdates, options) {
2733
+ var changedProductIds, updatedCount, newCount, appliedIds, mergeActions, changedProducts, _iterator16, _step16, _step16$value, id, body;
2734
+ return _regeneratorRuntime().wrap(function _callee26$(_context26) {
2735
+ while (1) switch (_context26.prev = _context26.next) {
2172
2736
  case 0:
2737
+ changedProductIds = _toConsumableArray(bodyUpdates.keys());
2738
+ this.pushProductFlowLog('applyBodyUpdatesToStore.start', _objectSpread({
2739
+ changedProductIds: changedProductIds,
2740
+ count: bodyUpdates.size,
2741
+ skipIndexDB: !!(options !== null && options !== void 0 && options.skipIndexDB)
2742
+ }, this.getProductStoreSnapshot()));
2173
2743
  this.logInfo('applyBodyUpdatesToStore: 开始', {
2174
2744
  count: bodyUpdates.size
2175
2745
  });
2176
2746
  updatedCount = 0;
2177
2747
  newCount = 0;
2178
2748
  appliedIds = new Set();
2749
+ mergeActions = {};
2750
+ changedProducts = [];
2179
2751
  this.store.list = this.store.list.map(function (p) {
2180
2752
  if (bodyUpdates.has(p.id)) {
2181
2753
  updatedCount++;
2182
2754
  appliedIds.add(p.id);
2183
- return bodyUpdates.get(p.id);
2755
+ mergeActions[p.id] = 'update';
2756
+ var next = bodyUpdates.get(p.id);
2757
+ changedProducts.push(next);
2758
+ return next;
2184
2759
  }
2185
2760
  return p;
2186
2761
  });
2187
- _iterator12 = _createForOfIteratorHelper(bodyUpdates);
2762
+ _iterator16 = _createForOfIteratorHelper(bodyUpdates);
2188
2763
  try {
2189
- for (_iterator12.s(); !(_step12 = _iterator12.n()).done;) {
2190
- _step12$value = _slicedToArray(_step12.value, 2), id = _step12$value[0], body = _step12$value[1];
2764
+ for (_iterator16.s(); !(_step16 = _iterator16.n()).done;) {
2765
+ _step16$value = _slicedToArray(_step16.value, 2), id = _step16$value[0], body = _step16$value[1];
2191
2766
  if (!appliedIds.has(id)) {
2192
2767
  this.store.list.push(body);
2193
2768
  newCount++;
2769
+ mergeActions[id] = 'insert';
2770
+ changedProducts.push(body);
2194
2771
  }
2195
2772
  }
2196
2773
  } catch (err) {
2197
- _iterator12.e(err);
2774
+ _iterator16.e(err);
2198
2775
  } finally {
2199
- _iterator12.f();
2776
+ _iterator16.f();
2200
2777
  }
2201
2778
  this.syncProductsMap();
2202
- _context22.next = 10;
2203
- return this.saveProductsToIndexDB(this.store.list);
2204
- case 10:
2205
- this.core.effects.emit(ProductsHooks.onProductsChanged, this.store.list);
2779
+ if (options !== null && options !== void 0 && options.skipIndexDB) {
2780
+ _context26.next = 15;
2781
+ break;
2782
+ }
2783
+ _context26.next = 15;
2784
+ return this.patchProductsInIndexDB(changedProducts, 'pubsub.bodyUpdate', mergeActions);
2785
+ case 15:
2786
+ if (!(options !== null && options !== void 0 && options.skipEmit)) {
2787
+ this.core.effects.emit(ProductsHooks.onProductsChanged, this.store.list);
2788
+ }
2789
+ this.pushProductFlowLog('applyBodyUpdatesToStore.done', {
2790
+ changedProductIds: changedProductIds,
2791
+ updatedCount: updatedCount,
2792
+ newCount: newCount,
2793
+ totalCount: this.store.list.length,
2794
+ indexDbPatchCount: options !== null && options !== void 0 && options.skipIndexDB ? 0 : changedProducts.length
2795
+ });
2206
2796
  this.logInfo('applyBodyUpdatesToStore: 完成', {
2207
2797
  updatedCount: updatedCount,
2208
2798
  newCount: newCount,
2209
2799
  totalCount: this.store.list.length
2210
2800
  });
2211
- case 12:
2801
+ return _context26.abrupt("return", {
2802
+ changedProducts: changedProducts,
2803
+ mergeActions: mergeActions,
2804
+ updatedCount: updatedCount,
2805
+ newCount: newCount
2806
+ });
2807
+ case 19:
2212
2808
  case "end":
2213
- return _context22.stop();
2809
+ return _context26.stop();
2214
2810
  }
2215
- }, _callee22, this);
2811
+ }, _callee26, this);
2216
2812
  }));
2217
- function applyBodyUpdatesToStore(_x21) {
2813
+ function applyBodyUpdatesToStore(_x25, _x26) {
2218
2814
  return _applyBodyUpdatesToStore.apply(this, arguments);
2219
2815
  }
2220
2816
  return applyBodyUpdatesToStore;
@@ -2222,68 +2818,103 @@ export var ProductsModule = /*#__PURE__*/function (_BaseModule) {
2222
2818
  /**
2223
2819
  * 将增量拉取的商品合并到 store
2224
2820
  * 已存在的 → 替换;新的 → 追加
2225
- * 同时更新 store.map、IndexDB,触发 onProductsChanged
2821
+ *
2822
+ * @example
2823
+ * await this.mergeProductsToStore(freshProducts, { skipIndexDB: true })
2226
2824
  */
2227
2825
  )
2228
2826
  }, {
2229
2827
  key: "mergeProductsToStore",
2230
2828
  value: (function () {
2231
- var _mergeProductsToStore = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee23(freshProducts) {
2232
- var freshMap, _iterator13, _step13, p, updatedList, newCount, _iterator14, _step14, _p2, updatedCount;
2233
- return _regeneratorRuntime().wrap(function _callee23$(_context23) {
2234
- while (1) switch (_context23.prev = _context23.next) {
2829
+ var _mergeProductsToStore = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee27(freshProducts, options) {
2830
+ var freshMap, _iterator17, _step17, p, mergeActions, changedProducts, updatedList, newCount, _iterator18, _step18, _p2, updatedCount, changedProductIds;
2831
+ return _regeneratorRuntime().wrap(function _callee27$(_context27) {
2832
+ while (1) switch (_context27.prev = _context27.next) {
2235
2833
  case 0:
2236
2834
  freshMap = new Map();
2237
- _iterator13 = _createForOfIteratorHelper(freshProducts);
2835
+ _iterator17 = _createForOfIteratorHelper(freshProducts);
2238
2836
  try {
2239
- for (_iterator13.s(); !(_step13 = _iterator13.n()).done;) {
2240
- p = _step13.value;
2837
+ for (_iterator17.s(); !(_step17 = _iterator17.n()).done;) {
2838
+ p = _step17.value;
2241
2839
  freshMap.set(p.id, p);
2242
2840
  }
2243
2841
  } catch (err) {
2244
- _iterator13.e(err);
2842
+ _iterator17.e(err);
2245
2843
  } finally {
2246
- _iterator13.f();
2844
+ _iterator17.f();
2247
2845
  }
2846
+ mergeActions = {};
2847
+ changedProducts = [];
2248
2848
  updatedList = this.store.list.map(function (p) {
2249
2849
  if (freshMap.has(p.id)) {
2250
2850
  var fresh = freshMap.get(p.id);
2251
2851
  freshMap.delete(p.id);
2852
+ mergeActions[p.id] = 'update';
2853
+ changedProducts.push(fresh);
2252
2854
  return fresh;
2253
2855
  }
2254
2856
  return p;
2255
2857
  }); // freshMap 中剩余的是新商品(create 场景)
2256
2858
  newCount = freshMap.size;
2257
- _iterator14 = _createForOfIteratorHelper(freshMap.values());
2859
+ _iterator18 = _createForOfIteratorHelper(freshMap.values());
2258
2860
  try {
2259
- for (_iterator14.s(); !(_step14 = _iterator14.n()).done;) {
2260
- _p2 = _step14.value;
2861
+ for (_iterator18.s(); !(_step18 = _iterator18.n()).done;) {
2862
+ _p2 = _step18.value;
2261
2863
  updatedList.push(_p2);
2864
+ mergeActions[_p2.id] = 'insert';
2865
+ changedProducts.push(_p2);
2262
2866
  }
2263
2867
  } catch (err) {
2264
- _iterator14.e(err);
2868
+ _iterator18.e(err);
2265
2869
  } finally {
2266
- _iterator14.f();
2870
+ _iterator18.f();
2267
2871
  }
2268
2872
  updatedCount = freshProducts.length - newCount;
2873
+ changedProductIds = freshProducts.map(function (p) {
2874
+ return p.id;
2875
+ });
2876
+ this.pushProductFlowLog('mergeProductsToStore.start', _objectSpread({
2877
+ changedProductIds: changedProductIds,
2878
+ incomingCount: freshProducts.length,
2879
+ skipIndexDB: !!(options !== null && options !== void 0 && options.skipIndexDB)
2880
+ }, this.getProductStoreSnapshot()));
2269
2881
  this.store.list = updatedList;
2270
2882
  this.syncProductsMap();
2271
- _context23.next = 12;
2272
- return this.saveProductsToIndexDB(this.store.list);
2273
- case 12:
2883
+ if (options !== null && options !== void 0 && options.skipIndexDB) {
2884
+ _context27.next = 17;
2885
+ break;
2886
+ }
2887
+ _context27.next = 17;
2888
+ return this.patchProductsInIndexDB(changedProducts, 'pubsub.mergeProductsToStore', mergeActions);
2889
+ case 17:
2890
+ if (!(options !== null && options !== void 0 && options.skipEmit)) {
2891
+ this.core.effects.emit(ProductsHooks.onProductsChanged, this.store.list);
2892
+ }
2893
+ this.pushProductFlowLog('mergeProductsToStore.done', {
2894
+ changedProductIds: changedProductIds,
2895
+ updatedCount: updatedCount,
2896
+ newCount: newCount,
2897
+ totalCount: this.store.list.length,
2898
+ indexDbPatchCount: options !== null && options !== void 0 && options.skipIndexDB ? 0 : changedProducts.length
2899
+ });
2274
2900
  this.logInfo('mergeProductsToStore: 合并完成', {
2275
2901
  updatedCount: updatedCount,
2276
2902
  newCount: newCount,
2277
2903
  totalCount: this.store.list.length
2278
2904
  });
2279
- this.core.effects.emit(ProductsHooks.onProductsChanged, this.store.list);
2280
- case 14:
2905
+ return _context27.abrupt("return", {
2906
+ changedProducts: changedProducts,
2907
+ mergeActions: mergeActions,
2908
+ updatedCount: updatedCount,
2909
+ newCount: newCount
2910
+ });
2911
+ case 21:
2281
2912
  case "end":
2282
- return _context23.stop();
2913
+ return _context27.stop();
2283
2914
  }
2284
- }, _callee23, this);
2915
+ }, _callee27, this);
2285
2916
  }));
2286
- function mergeProductsToStore(_x22) {
2917
+ function mergeProductsToStore(_x27, _x28) {
2287
2918
  return _mergeProductsToStore.apply(this, arguments);
2288
2919
  }
2289
2920
  return mergeProductsToStore;
@@ -2297,56 +2928,81 @@ export var ProductsModule = /*#__PURE__*/function (_BaseModule) {
2297
2928
  }, {
2298
2929
  key: "silentRefresh",
2299
2930
  value: (function () {
2300
- var _silentRefresh = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee24() {
2301
- var t0, products, errorMessage;
2302
- return _regeneratorRuntime().wrap(function _callee24$(_context24) {
2303
- while (1) switch (_context24.prev = _context24.next) {
2931
+ var _silentRefresh = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee28() {
2932
+ var t0, now, elapsedSincePreload, elapsedSinceFullFetch, products, errorMessage;
2933
+ return _regeneratorRuntime().wrap(function _callee28$(_context28) {
2934
+ while (1) switch (_context28.prev = _context28.next) {
2304
2935
  case 0:
2305
2936
  t0 = performance.now();
2937
+ now = Date.now();
2938
+ elapsedSincePreload = now - this.lastPreloadCompletedAtMs;
2939
+ elapsedSinceFullFetch = now - this.lastServerFullFetchAtMs;
2940
+ if (!(this.lastPreloadCompletedAtMs > 0 && elapsedSincePreload < PRODUCT_SILENT_REFRESH_MIN_INTERVAL_MS || this.lastServerFullFetchAtMs > 0 && elapsedSinceFullFetch < PRODUCT_SILENT_REFRESH_MIN_INTERVAL_MS)) {
2941
+ _context28.next = 7;
2942
+ break;
2943
+ }
2944
+ this.pushProductFlowLog('silentRefresh.skipped', _objectSpread({
2945
+ elapsedSincePreloadMs: this.lastPreloadCompletedAtMs > 0 ? elapsedSincePreload : null,
2946
+ elapsedSinceFullFetchMs: this.lastServerFullFetchAtMs > 0 ? elapsedSinceFullFetch : null,
2947
+ minIntervalMs: PRODUCT_SILENT_REFRESH_MIN_INTERVAL_MS
2948
+ }, this.getProductStoreSnapshot()));
2949
+ return _context28.abrupt("return", this.store.list);
2950
+ case 7:
2951
+ this.pushProductFlowLog('silentRefresh.start', _objectSpread({
2952
+ note: '会调用 loadProductsByServer → replaceProductsSnapshotInIndexDB'
2953
+ }, this.getProductStoreSnapshot()));
2306
2954
  this.logInfo('silentRefresh 开始');
2307
- _context24.prev = 2;
2308
- _context24.next = 5;
2955
+ _context28.prev = 9;
2956
+ _context28.next = 12;
2309
2957
  return this.loadProductsByServer();
2310
- case 5:
2311
- products = _context24.sent;
2958
+ case 12:
2959
+ products = _context28.sent;
2312
2960
  if (!(products && products.length > 0)) {
2313
- _context24.next = 16;
2961
+ _context28.next = 24;
2314
2962
  break;
2315
2963
  }
2316
2964
  this.store.list = products;
2317
2965
  this.syncProductsMap();
2318
2966
  this.clearPriceCache();
2319
2967
  this.core.effects.emit(ProductsHooks.onProductsChanged, this.store.list);
2320
- _context24.next = 13;
2968
+ _context28.next = 20;
2321
2969
  return this.core.effects.emit(ProductsHooks.onProductsSyncCompleted, null);
2322
- case 13:
2970
+ case 20:
2971
+ this.pushProductFlowLog('silentRefresh.done', _objectSpread({
2972
+ productCount: products.length,
2973
+ durationMs: Math.round(performance.now() - t0)
2974
+ }, this.getProductStoreSnapshot()));
2323
2975
  this.logInfo('silentRefresh 完成', {
2324
2976
  productCount: products.length,
2325
2977
  duration: "".concat(Math.round(performance.now() - t0), "ms")
2326
2978
  });
2327
- _context24.next = 17;
2979
+ _context28.next = 26;
2328
2980
  break;
2329
- case 16:
2981
+ case 24:
2982
+ this.pushProductFlowLog('silentRefresh.empty', {});
2330
2983
  this.logWarning('silentRefresh: 服务器未返回数据');
2331
- case 17:
2984
+ case 26:
2332
2985
  perfMark('silentRefresh', performance.now() - t0, {
2333
2986
  count: this.store.list.length
2334
2987
  });
2335
- return _context24.abrupt("return", this.store.list);
2336
- case 21:
2337
- _context24.prev = 21;
2338
- _context24.t0 = _context24["catch"](2);
2339
- errorMessage = _context24.t0 instanceof Error ? _context24.t0.message : String(_context24.t0);
2988
+ return _context28.abrupt("return", this.store.list);
2989
+ case 30:
2990
+ _context28.prev = 30;
2991
+ _context28.t0 = _context28["catch"](9);
2992
+ errorMessage = _context28.t0 instanceof Error ? _context28.t0.message : String(_context28.t0);
2993
+ this.pushProductFlowLog('silentRefresh.failed', {
2994
+ error: errorMessage
2995
+ });
2340
2996
  this.logError('silentRefresh 失败', {
2341
2997
  duration: "".concat(Math.round(performance.now() - t0), "ms"),
2342
2998
  error: errorMessage
2343
2999
  });
2344
- return _context24.abrupt("return", this.store.list);
2345
- case 26:
3000
+ return _context28.abrupt("return", this.store.list);
3001
+ case 36:
2346
3002
  case "end":
2347
- return _context24.stop();
3003
+ return _context28.stop();
2348
3004
  }
2349
- }, _callee24, this, [[2, 21]]);
3005
+ }, _callee28, this, [[9, 30]]);
2350
3006
  }));
2351
3007
  function silentRefresh() {
2352
3008
  return _silentRefresh.apply(this, arguments);