@pisell/pisellos 0.0.567 → 0.0.568

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 (228) hide show
  1. package/dist/core/index.js +6 -9
  2. package/dist/model/strategy/adapter/walletPass/evaluator.js +0 -2
  3. package/dist/model/strategy/adapter/walletPass/example.js +3 -26
  4. package/dist/model/strategy/adapter/walletPass/utils.js +0 -3
  5. package/dist/model/strategy/strategy-example.js +5 -19
  6. package/dist/modules/Cart/index.js +0 -3
  7. package/dist/modules/Cart/utils/cartProduct.js +0 -1
  8. package/dist/modules/Date/index.js +1 -5
  9. package/dist/modules/Discount/index.js +1 -4
  10. package/dist/modules/OpenData/index.js +0 -2
  11. package/dist/modules/Order/index.d.ts +1 -1
  12. package/dist/modules/Order/index.js +14 -41
  13. package/dist/modules/Payment/index.js +142 -270
  14. package/dist/modules/Payment/walletpass.js +4 -5
  15. package/dist/modules/Rules/index.js +0 -7
  16. package/dist/modules/Schedule/utils.js +0 -1
  17. package/dist/modules/Step/index.js +0 -1
  18. package/dist/plugins/request.js +1 -4
  19. package/dist/plugins/window.js +2 -6
  20. package/dist/server/index.js +88 -121
  21. package/dist/server/modules/menu/index.js +32 -41
  22. package/dist/server/modules/products/index.js +29 -49
  23. package/dist/server/modules/quotation/index.js +29 -38
  24. package/dist/server/modules/resource/index.js +3 -4
  25. package/dist/server/modules/schedule/index.js +32 -40
  26. package/dist/server/utils/product.js +0 -1
  27. package/dist/solution/BookingByStep/index.d.ts +1 -1
  28. package/dist/solution/BookingByStep/index.js +7 -59
  29. package/dist/solution/BookingByStep/utils/capacity.js +1 -11
  30. package/dist/solution/BookingByStep/utils/resources.js +1 -3
  31. package/dist/solution/BookingByStep/utils/timeslots.js +2 -43
  32. package/dist/solution/BookingTicket/index.d.ts +1 -1
  33. package/dist/solution/BookingTicket/index.js +5 -7
  34. package/dist/solution/BookingTicket/utils/scan/handleScan.js +25 -31
  35. package/dist/solution/BookingTicket/utils/scan/index.js +6 -10
  36. package/dist/solution/BuyTickets/index.js +9 -12
  37. package/dist/solution/Checkout/index.js +177 -246
  38. package/dist/solution/Checkout/utils/index.js +4 -16
  39. package/dist/solution/RegisterAndLogin/index.js +30 -76
  40. package/dist/solution/ScanOrder/index.js +50 -60
  41. package/dist/solution/ShopDiscount/index.js +2 -7
  42. package/dist/solution/VenueBooking/index.d.ts +5 -0
  43. package/dist/solution/VenueBooking/index.js +364 -327
  44. package/dist/utils/task.js +15 -18
  45. package/dist/utils/watch.js +0 -1
  46. package/lib/apis/picoding.js +2 -0
  47. package/lib/core/index.js +130 -131
  48. package/lib/effects/index.js +46 -57
  49. package/lib/index.js +92 -53
  50. package/lib/model/index.js +14 -21
  51. package/lib/model/strategy/adapter/dataVariant/adapter.js +38 -50
  52. package/lib/model/strategy/adapter/dataVariant/evaluator.js +162 -236
  53. package/lib/model/strategy/adapter/dataVariant/examples.js +229 -237
  54. package/lib/model/strategy/adapter/dataVariant/index.js +39 -34
  55. package/lib/model/strategy/adapter/dataVariant/type.js +57 -28
  56. package/lib/model/strategy/adapter/index.js +100 -64
  57. package/lib/model/strategy/adapter/itemRule/adapter.js +156 -144
  58. package/lib/model/strategy/adapter/itemRule/evaluator.js +36 -48
  59. package/lib/model/strategy/adapter/itemRule/examples.js +295 -225
  60. package/lib/model/strategy/adapter/itemRule/index.js +83 -57
  61. package/lib/model/strategy/adapter/itemRule/type.js +97 -36
  62. package/lib/model/strategy/adapter/promotion/adapter.js +84 -63
  63. package/lib/model/strategy/adapter/promotion/evaluator.js +381 -231
  64. package/lib/model/strategy/adapter/promotion/examples.js +139 -159
  65. package/lib/model/strategy/adapter/promotion/index.js +1 -49
  66. package/lib/model/strategy/adapter/promotion/type.js +199 -35
  67. package/lib/model/strategy/adapter/type.js +4 -16
  68. package/lib/model/strategy/adapter/walletPass/evaluator.js +180 -152
  69. package/lib/model/strategy/adapter/walletPass/example.js +217 -190
  70. package/lib/model/strategy/adapter/walletPass/index.js +75 -51
  71. package/lib/model/strategy/adapter/walletPass/locales.js +36 -58
  72. package/lib/model/strategy/adapter/walletPass/type.js +4 -16
  73. package/lib/model/strategy/adapter/walletPass/utils.js +652 -402
  74. package/lib/model/strategy/engine.js +270 -168
  75. package/lib/model/strategy/index.js +49 -34
  76. package/lib/model/strategy/strategy-example.js +243 -239
  77. package/lib/model/strategy/type.js +100 -40
  78. package/lib/modules/Account/index.js +39 -53
  79. package/lib/modules/Account/types.js +20 -33
  80. package/lib/modules/AccountList/index.js +116 -154
  81. package/lib/modules/AccountList/types.js +30 -31
  82. package/lib/modules/AccountList/utils.js +18 -30
  83. package/lib/modules/BaseModule.js +22 -45
  84. package/lib/modules/Cart/index.js +170 -124
  85. package/lib/modules/Cart/types.js +46 -51
  86. package/lib/modules/Cart/utils/cartAccount.js +40 -39
  87. package/lib/modules/Cart/utils/cartDate.js +56 -61
  88. package/lib/modules/Cart/utils/cartDiscount.js +28 -33
  89. package/lib/modules/Cart/utils/cartNote.js +27 -32
  90. package/lib/modules/Cart/utils/cartProduct.js +306 -241
  91. package/lib/modules/Cart/utils/cartRelationForms.js +29 -35
  92. package/lib/modules/Cart/utils/cartResource.js +72 -78
  93. package/lib/modules/Cart/utils/changePrice.js +26 -62
  94. package/lib/modules/Cart/utils/index.js +106 -48
  95. package/lib/modules/Customer/constants.js +13 -34
  96. package/lib/modules/Customer/index.js +216 -153
  97. package/lib/modules/Customer/types.js +38 -35
  98. package/lib/modules/Date/index.js +116 -115
  99. package/lib/modules/Date/types.js +16 -28
  100. package/lib/modules/Date/utils.js +174 -123
  101. package/lib/modules/Discount/index.js +117 -113
  102. package/lib/modules/Discount/types.js +9 -31
  103. package/lib/modules/Guests/index.js +30 -56
  104. package/lib/modules/Guests/types.js +23 -33
  105. package/lib/modules/Holder/index.js +209 -189
  106. package/lib/modules/Holder/types.js +4 -16
  107. package/lib/modules/Holder/utils.js +20 -49
  108. package/lib/modules/OpenData/index.js +63 -74
  109. package/lib/modules/OpenData/types.js +4 -16
  110. package/lib/modules/OpenData/utils.js +44 -78
  111. package/lib/modules/Order/index.d.ts +1 -1
  112. package/lib/modules/Order/index.js +332 -320
  113. package/lib/modules/Order/types.js +24 -33
  114. package/lib/modules/Order/utils.js +350 -284
  115. package/lib/modules/Payment/cash.js +20 -33
  116. package/lib/modules/Payment/cashRecommendationAlgorithm.js +145 -76
  117. package/lib/modules/Payment/eftpos.js +16 -30
  118. package/lib/modules/Payment/index.js +566 -432
  119. package/lib/modules/Payment/mx51.js +1 -0
  120. package/lib/modules/Payment/types.js +216 -107
  121. package/lib/modules/Payment/utils.js +50 -47
  122. package/lib/modules/Payment/walletpass.js +221 -203
  123. package/lib/modules/Product/index.js +51 -46
  124. package/lib/modules/Product/types.js +4 -16
  125. package/lib/modules/Product/utils.js +32 -33
  126. package/lib/modules/ProductList/index.js +111 -110
  127. package/lib/modules/ProductList/types.js +9 -31
  128. package/lib/modules/Quotation/index.js +60 -82
  129. package/lib/modules/Quotation/types.js +4 -16
  130. package/lib/modules/Resource/index.js +27 -59
  131. package/lib/modules/Resource/types.js +22 -32
  132. package/lib/modules/Resource/utils.js +30 -38
  133. package/lib/modules/Rules/index.js +1172 -872
  134. package/lib/modules/Rules/types.js +17 -40
  135. package/lib/modules/SalesSummary/index.js +59 -68
  136. package/lib/modules/SalesSummary/types.js +4 -16
  137. package/lib/modules/SalesSummary/utils.js +176 -193
  138. package/lib/modules/ScanOrderLogger/index.js +59 -79
  139. package/lib/modules/ScanOrderLogger/providers/feishu.js +54 -78
  140. package/lib/modules/ScanOrderLogger/providers/grafana.js +13 -36
  141. package/lib/modules/ScanOrderLogger/types.js +4 -16
  142. package/lib/modules/Schedule/getDateIsInSchedule.js +334 -167
  143. package/lib/modules/Schedule/index.js +97 -107
  144. package/lib/modules/Schedule/type.js +4 -16
  145. package/lib/modules/Schedule/types.js +4 -16
  146. package/lib/modules/Schedule/utils.js +433 -291
  147. package/lib/modules/Step/index.js +40 -52
  148. package/lib/modules/Step/tyeps.js +4 -16
  149. package/lib/modules/Summary/index.js +66 -70
  150. package/lib/modules/Summary/types.js +4 -16
  151. package/lib/modules/Summary/utils.js +782 -429
  152. package/lib/modules/index.js +212 -57
  153. package/lib/plugins/app.js +4 -16
  154. package/lib/plugins/index.js +36 -25
  155. package/lib/plugins/request.js +137 -126
  156. package/lib/plugins/shopStore.js +4 -16
  157. package/lib/plugins/user.js +4 -16
  158. package/lib/plugins/window.js +171 -179
  159. package/lib/server/index.js +882 -623
  160. package/lib/server/modules/index.js +85 -59
  161. package/lib/server/modules/menu/index.js +146 -122
  162. package/lib/server/modules/menu/types.js +18 -31
  163. package/lib/server/modules/order/index.js +195 -231
  164. package/lib/server/modules/order/types.js +107 -32
  165. package/lib/server/modules/order/utils/filterBookings.js +174 -140
  166. package/lib/server/modules/order/utils/filterOrders.js +89 -60
  167. package/lib/server/modules/products/index.js +430 -335
  168. package/lib/server/modules/products/types.js +41 -34
  169. package/lib/server/modules/quotation/index.js +76 -77
  170. package/lib/server/modules/quotation/types.js +21 -31
  171. package/lib/server/modules/resource/index.js +216 -187
  172. package/lib/server/modules/resource/types.js +42 -33
  173. package/lib/server/modules/schedule/index.js +134 -119
  174. package/lib/server/modules/schedule/types.js +14 -21
  175. package/lib/server/modules/schedule/utils.js +334 -163
  176. package/lib/server/types.js +4 -16
  177. package/lib/server/utils/index.js +25 -23
  178. package/lib/server/utils/product.js +196 -139
  179. package/lib/server/utils/schedule.js +34 -41
  180. package/lib/server/utils/time.js +40 -49
  181. package/lib/solution/BookingByStep/index.d.ts +1 -1
  182. package/lib/solution/BookingByStep/index.js +1530 -1343
  183. package/lib/solution/BookingByStep/types.js +40 -99
  184. package/lib/solution/BookingByStep/utils/capacity.js +192 -160
  185. package/lib/solution/BookingByStep/utils/products.js +42 -52
  186. package/lib/solution/BookingByStep/utils/resources.js +527 -330
  187. package/lib/solution/BookingByStep/utils/stock.js +65 -44
  188. package/lib/solution/BookingByStep/utils/timeslots.js +129 -131
  189. package/lib/solution/BookingTicket/index.d.ts +1 -1
  190. package/lib/solution/BookingTicket/index.js +147 -122
  191. package/lib/solution/BookingTicket/types.js +38 -64
  192. package/lib/solution/BookingTicket/utils/scan/cloudSearch.js +64 -80
  193. package/lib/solution/BookingTicket/utils/scan/handleScan.js +82 -80
  194. package/lib/solution/BookingTicket/utils/scan/index.js +90 -94
  195. package/lib/solution/BookingTicket/utils/scan/scanCache.js +90 -43
  196. package/lib/solution/BuyTickets/index.js +67 -70
  197. package/lib/solution/BuyTickets/types.js +22 -38
  198. package/lib/solution/Checkout/index.js +1451 -1158
  199. package/lib/solution/Checkout/types.js +91 -61
  200. package/lib/solution/Checkout/utils/index.js +227 -158
  201. package/lib/solution/PlaceOrder/index.js +55 -0
  202. package/lib/solution/RegisterAndLogin/config.js +493 -460
  203. package/lib/solution/RegisterAndLogin/index.js +633 -630
  204. package/lib/solution/RegisterAndLogin/types.js +189 -76
  205. package/lib/solution/RegisterAndLogin/utils.js +183 -125
  206. package/lib/solution/Sales/index.js +218 -200
  207. package/lib/solution/Sales/types.js +27 -33
  208. package/lib/solution/ScanOrder/index.js +803 -840
  209. package/lib/solution/ScanOrder/types.js +34 -34
  210. package/lib/solution/ScanOrder/utils.js +372 -331
  211. package/lib/solution/ShopDiscount/index.js +230 -236
  212. package/lib/solution/ShopDiscount/types.js +15 -37
  213. package/lib/solution/ShopDiscount/utils.js +309 -172
  214. package/lib/solution/VenueBooking/index.d.ts +5 -0
  215. package/lib/solution/VenueBooking/index.js +886 -929
  216. package/lib/solution/VenueBooking/types.js +20 -40
  217. package/lib/solution/VenueBooking/utils/dateSummary.js +22 -54
  218. package/lib/solution/VenueBooking/utils/resource.js +31 -54
  219. package/lib/solution/VenueBooking/utils/slotMerge.js +88 -106
  220. package/lib/solution/VenueBooking/utils/smartPricing.js +112 -100
  221. package/lib/solution/VenueBooking/utils/timeSlot.js +133 -132
  222. package/lib/solution/VenueBooking/utils.js +130 -67
  223. package/lib/solution/index.js +102 -37
  224. package/lib/store/createStore.js +32 -29
  225. package/lib/types/index.js +4 -16
  226. package/lib/utils/task.js +36 -36
  227. package/lib/utils/watch.js +81 -47
  228. package/package.json +2 -1
@@ -1,85 +1,94 @@
1
- var __defProp = Object.defineProperty;
2
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
- var __getOwnPropNames = Object.getOwnPropertyNames;
4
- var __hasOwnProp = Object.prototype.hasOwnProperty;
5
- var __export = (target, all) => {
6
- for (var name in all)
7
- __defProp(target, name, { get: all[name], enumerable: true });
8
- };
9
- var __copyProps = (to, from, except, desc) => {
10
- if (from && typeof from === "object" || typeof from === "function") {
11
- for (let key of __getOwnPropNames(from))
12
- if (!__hasOwnProp.call(to, key) && key !== except)
13
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
- }
15
- return to;
16
- };
17
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
1
+ "use strict";
18
2
 
19
- // src/server/modules/products/index.ts
20
- var products_exports = {};
21
- __export(products_exports, {
22
- ProductsModule: () => ProductsModule
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
23
5
  });
24
- module.exports = __toCommonJS(products_exports);
25
- var import_BaseModule = require("../../../modules/BaseModule");
26
- var import_plugins = require("../../../plugins");
27
- var import_types = require("./types");
28
- var import_product = require("../../utils/product");
29
- var INDEXDB_STORE_NAME = "products";
30
- var PRODUCT_SYNC_DEBOUNCE_MS = 1e4;
31
- var ProductsModule = class extends import_BaseModule.BaseModule {
6
+ exports.ProductsModule = void 0;
7
+ var _BaseModule = require("../../../modules/BaseModule");
8
+ var _plugins = require("../../../plugins");
9
+ var _types = require("./types");
10
+ var _product = require("../../utils/product");
11
+ /**
12
+ * IndexDB 存储名称
13
+ */
14
+ const INDEXDB_STORE_NAME = 'products';
15
+
16
+ /** 商品同步防抖时间(毫秒) */
17
+ const PRODUCT_SYNC_DEBOUNCE_MS = 10_000;
18
+
19
+ /**
20
+ * Products 模块 - 用于获取和管理完整的商品详细数据
21
+ * 相比 ProductList 模块,Products 会获取所有详细信息并缓存
22
+ */
23
+ class ProductsModule extends _BaseModule.BaseModule {
24
+ defaultName = 'products';
25
+ defaultVersion = '1.0.0';
26
+ store;
27
+ request;
28
+ dbManager; // IndexDBManager 实例
29
+ logger; // LoggerManager 实例
30
+ otherParams = {};
31
+
32
+ // 商品价格缓存:Map<日期, 应用了价格的商品列表>
33
+ productsPriceCache = new Map();
34
+
35
+ // 缓存配置
36
+ CACHE_MAX_DAYS = 7; // 最多缓存7天
37
+
38
+ // 商品格式化器列表
39
+ formatters = [];
40
+
41
+ // 是否已注册内置价格格式化器
42
+ isPriceFormatterRegistered = false;
43
+
44
+ // ---- 商品数据同步相关 ----
45
+ productDataSource;
46
+ pendingSyncMessages = [];
47
+ syncTimer;
32
48
  constructor(name, version) {
33
49
  super(name, version);
34
- this.defaultName = "products";
35
- this.defaultVersion = "1.0.0";
36
- // LoggerManager 实例
37
- this.otherParams = {};
38
- // 商品价格缓存:Map<日期, 应用了价格的商品列表>
39
- this.productsPriceCache = /* @__PURE__ */ new Map();
40
- // 缓存配置
41
- this.CACHE_MAX_DAYS = 7;
42
- // 最多缓存7天
43
- // 商品格式化器列表
44
- this.formatters = [];
45
- // 是否已注册内置价格格式化器
46
- this.isPriceFormatterRegistered = false;
47
- this.pendingSyncMessages = [];
48
50
  }
49
51
  async initialize(core, options) {
50
- var _a;
51
52
  this.core = core;
52
53
  this.store = options.store;
53
54
  this.otherParams = options.otherParams || {};
54
- if (Array.isArray((_a = options.initialState) == null ? void 0 : _a.list)) {
55
+ if (Array.isArray(options.initialState?.list)) {
55
56
  this.store.list = options.initialState.list;
57
+ // 同步更新 Map 缓存
56
58
  this.syncProductsMap();
57
- this.core.effects.emit(import_types.ProductsHooks.onProductsChanged, this.store.list);
59
+ this.core.effects.emit(_types.ProductsHooks.onProductsChanged, this.store.list);
58
60
  } else {
59
61
  this.store.list = [];
60
- this.store.map = /* @__PURE__ */ new Map();
62
+ this.store.map = new Map();
61
63
  }
62
- this.request = core.getPlugin("request");
63
- const appPlugin = core.getPlugin("app");
64
+ this.request = core.getPlugin('request');
65
+
66
+ // 获取并存储 dbManager 和 logger
67
+ const appPlugin = core.getPlugin('app');
64
68
  if (appPlugin) {
65
69
  const app = appPlugin.getApp();
66
70
  this.dbManager = app.dbManager;
67
71
  this.logger = app.logger;
68
- if (this.dbManager) {
69
- console.log("[Products] IndexDB Manager 已初始化");
70
- } else {
71
- console.warn("[Products] IndexDB Manager 未找到");
72
+ if (this.dbManager) {} else {
73
+ console.warn('[Products] IndexDB Manager 未找到');
72
74
  }
73
75
  }
76
+
77
+ // 注册内置的价格格式化器(作为第一个格式化器)
74
78
  this.registerBuiltinPriceFormatter();
79
+
80
+ // 初始化 ProductDataSource 实例
75
81
  this.initProductDataSource();
82
+
83
+ // 初始化商品数据同步(pubsub 订阅)
76
84
  this.setupProductSync();
77
- this.logInfo("模块初始化完成", {
85
+ this.logInfo('模块初始化完成', {
78
86
  hasDbManager: !!this.dbManager,
79
87
  hasLogger: !!this.logger,
80
88
  initialProductCount: this.store.list.length
81
89
  });
82
90
  }
91
+
83
92
  /**
84
93
  * 记录信息日志
85
94
  * @param title 日志标题
@@ -89,14 +98,16 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
89
98
  try {
90
99
  if (this.logger) {
91
100
  this.logger.addLog({
92
- type: "info",
101
+ type: 'info',
93
102
  title: `[ProductsModule] ${title}`,
94
103
  metadata: metadata || {}
95
104
  });
96
105
  }
97
106
  } catch {
107
+ // 日志记录失败不影响主流程
98
108
  }
99
109
  }
110
+
100
111
  /**
101
112
  * 记录警告日志
102
113
  * @param title 日志标题
@@ -106,14 +117,16 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
106
117
  try {
107
118
  if (this.logger) {
108
119
  this.logger.addLog({
109
- type: "warning",
120
+ type: 'warning',
110
121
  title: `[ProductsModule] ${title}`,
111
122
  metadata: metadata || {}
112
123
  });
113
124
  }
114
125
  } catch {
126
+ // 日志记录失败不影响主流程
115
127
  }
116
128
  }
129
+
117
130
  /**
118
131
  * 记录错误日志
119
132
  * @param title 日志标题
@@ -123,14 +136,16 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
123
136
  try {
124
137
  if (this.logger) {
125
138
  this.logger.addLog({
126
- type: "error",
139
+ type: 'error',
127
140
  title: `[ProductsModule] ${title}`,
128
141
  metadata: metadata || {}
129
142
  });
130
143
  }
131
144
  } catch {
145
+ // 日志记录失败不影响主流程
132
146
  }
133
147
  }
148
+
134
149
  /**
135
150
  * 加载商品价格(原始方法,不带缓存)
136
151
  * @private
@@ -140,39 +155,34 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
140
155
  customer_id,
141
156
  schedule_date
142
157
  }) {
143
- var _a;
144
- this.logInfo("开始加载商品价格", {
158
+ this.logInfo('开始加载商品价格', {
145
159
  productCount: ids.length,
146
160
  schedule_date,
147
161
  customer_id
148
162
  });
149
163
  const startTime = Date.now();
150
164
  try {
151
- const productsData = await this.request.post(
152
- `/product/query/price`,
153
- {
154
- ids,
155
- customer_id,
156
- schedule_date
157
- },
158
- {
159
- cache: {
160
- mode: import_plugins.RequestModeENUM.REMOTE_LOCAL,
161
- type: "memory"
162
- }
165
+ const productsData = await this.request.post(`/product/query/price`, {
166
+ ids,
167
+ customer_id,
168
+ schedule_date
169
+ }, {
170
+ cache: {
171
+ mode: _plugins.RequestModeENUM.REMOTE_LOCAL,
172
+ type: "memory"
163
173
  }
164
- );
174
+ });
165
175
  const duration = Date.now() - startTime;
166
- this.logInfo("加载商品价格成功", {
176
+ this.logInfo('加载商品价格成功', {
167
177
  productCount: ids.length,
168
- priceDataCount: ((_a = productsData.data) == null ? void 0 : _a.length) ?? 0,
178
+ priceDataCount: productsData.data?.length ?? 0,
169
179
  duration: `${duration}ms`
170
180
  });
171
181
  return productsData.data;
172
182
  } catch (error) {
173
183
  const duration = Date.now() - startTime;
174
184
  const errorMessage = error instanceof Error ? error.message : String(error);
175
- this.logError("加载商品价格失败", {
185
+ this.logError('加载商品价格失败', {
176
186
  productCount: ids.length,
177
187
  duration: `${duration}ms`,
178
188
  error: errorMessage
@@ -180,6 +190,7 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
180
190
  return [];
181
191
  }
182
192
  }
193
+
183
194
  /**
184
195
  * 获取应用了价格的商品列表(带缓存)
185
196
  * 使用日期作为缓存 key,同一天的商品价格会被缓存
@@ -193,23 +204,24 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
193
204
  async getProductsWithPrice(schedule_date, extraContext, options) {
194
205
  const t0 = performance.now();
195
206
  const cacheKey = schedule_date;
196
- const changedIds = options == null ? void 0 : options.changedIds;
207
+ const changedIds = options?.changedIds;
197
208
  if (this.productsPriceCache.has(cacheKey)) {
198
209
  const cachedProducts = this.productsPriceCache.get(cacheKey);
210
+
211
+ // 有变更的商品 → 增量 prepare 后 merge 回缓存
199
212
  if (changedIds && changedIds.length > 0) {
200
- this.logInfo("商品价格缓存命中,增量更新变更商品", {
213
+ this.logInfo('商品价格缓存命中,增量更新变更商品', {
201
214
  cacheKey,
202
215
  changedIds,
203
216
  cachedProductCount: cachedProducts.length
204
217
  });
205
218
  try {
206
- const updatedProducts = await this.prepareProductsWithPrice(
207
- schedule_date,
208
- extraContext,
209
- { productIds: changedIds }
210
- );
219
+ const updatedProducts = await this.prepareProductsWithPrice(schedule_date, extraContext, {
220
+ productIds: changedIds
221
+ });
211
222
  if (updatedProducts.length > 0) {
212
- const updatedMap = new Map(updatedProducts.map((p) => [p.id, p]));
223
+ // merge:用更新结果替换缓存中对应的商品,新增的追加
224
+ const updatedMap = new Map(updatedProducts.map(p => [p.id, p]));
213
225
  const mergedCache = [];
214
226
  for (const p of cachedProducts) {
215
227
  if (updatedMap.has(p.id)) {
@@ -219,16 +231,17 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
219
231
  mergedCache.push(p);
220
232
  }
221
233
  }
234
+ // 剩余的是新增商品(create 场景)
222
235
  for (const p of updatedMap.values()) {
223
236
  mergedCache.push(p);
224
237
  }
225
238
  this.productsPriceCache.set(cacheKey, mergedCache);
226
- this.logInfo("增量更新完成", {
239
+ this.logInfo('增量更新完成', {
227
240
  cacheKey,
228
241
  changedCount: updatedProducts.length,
229
242
  totalCount: mergedCache.length
230
243
  });
231
- (0, import_product.perfMark)("getProductsWithPrice(incrementalUpdate)", performance.now() - t0, {
244
+ (0, _product.perfMark)('getProductsWithPrice(incrementalUpdate)', performance.now() - t0, {
232
245
  cacheKey,
233
246
  changedCount: changedIds.length,
234
247
  count: mergedCache.length
@@ -237,43 +250,46 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
237
250
  }
238
251
  } catch (error) {
239
252
  const errorMessage = error instanceof Error ? error.message : String(error);
240
- this.logError("增量更新失败,返回现有缓存", {
253
+ this.logError('增量更新失败,返回现有缓存', {
241
254
  cacheKey,
242
255
  changedIds,
243
256
  error: errorMessage
244
257
  });
245
258
  }
246
- (0, import_product.perfMark)("getProductsWithPrice(incrementalUpdate)", performance.now() - t0, {
259
+ (0, _product.perfMark)('getProductsWithPrice(incrementalUpdate)', performance.now() - t0, {
247
260
  cacheKey,
248
261
  changedCount: changedIds.length,
249
262
  count: cachedProducts.length
250
263
  });
251
264
  return cachedProducts;
252
265
  }
253
- (0, import_product.perfMark)("getProductsWithPrice(cacheHit)", performance.now() - t0, {
266
+ (0, _product.perfMark)('getProductsWithPrice(cacheHit)', performance.now() - t0, {
254
267
  cacheKey,
255
268
  count: cachedProducts.length
256
269
  });
257
- this.logInfo("商品价格缓存命中", {
270
+ this.logInfo('商品价格缓存命中', {
258
271
  cacheKey,
259
272
  productCount: cachedProducts.length
260
273
  });
261
274
  return cachedProducts;
262
275
  }
263
- this.logInfo("商品价格缓存未命中,准备获取", { cacheKey });
276
+ this.logInfo('商品价格缓存未命中,准备获取', {
277
+ cacheKey
278
+ });
264
279
  const result = await this.prepareProductsWithPrice(schedule_date, extraContext);
265
280
  this.productsPriceCache.set(cacheKey, result);
266
- this.logInfo("商品价格已缓存", {
281
+ this.logInfo('商品价格已缓存', {
267
282
  cacheKey,
268
283
  productCount: result.length
269
284
  });
270
285
  this.cleanExpiredPriceCache();
271
- (0, import_product.perfMark)("getProductsWithPrice(cacheMiss)", performance.now() - t0, {
286
+ (0, _product.perfMark)('getProductsWithPrice(cacheMiss)', performance.now() - t0, {
272
287
  cacheKey,
273
288
  count: result.length
274
289
  });
275
290
  return result;
276
291
  }
292
+
277
293
  /**
278
294
  * 准备带价格的商品数据(通过格式化器流程处理)
279
295
  * @param schedule_date 日期
@@ -284,22 +300,22 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
284
300
  * @private
285
301
  */
286
302
  async prepareProductsWithPrice(schedule_date, extraContext, options) {
287
- var _a, _b;
288
303
  const tTotal = performance.now();
289
- const targetIds = options == null ? void 0 : options.productIds;
304
+ const targetIds = options?.productIds;
290
305
  const isIncremental = targetIds && targetIds.length > 0;
291
- this.logInfo("prepareProductsWithPrice 开始处理", {
306
+ this.logInfo('prepareProductsWithPrice 开始处理', {
292
307
  schedule_date,
293
- mode: isIncremental ? "incremental" : "full",
294
- targetIdsCount: targetIds == null ? void 0 : targetIds.length
308
+ mode: isIncremental ? 'incremental' : 'full',
309
+ targetIdsCount: targetIds?.length
295
310
  });
296
311
  try {
312
+ // 1. 获取商品列表:指定 IDs 时从 store 取子集,否则取全量
297
313
  let products;
298
314
  let ids;
299
315
  if (isIncremental) {
300
316
  const idSet = new Set(targetIds);
301
- products = this.getProductsRef().filter((p) => idSet.has(p.id));
302
- ids = products.map((p) => p.id);
317
+ products = this.getProductsRef().filter(p => idSet.has(p.id));
318
+ ids = products.map(p => p.id);
303
319
  } else {
304
320
  products = this.getProductsRef();
305
321
  const tIds = performance.now();
@@ -307,56 +323,65 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
307
323
  for (let i = 0; i < products.length; i++) {
308
324
  ids[i] = products[i].id;
309
325
  }
310
- (0, import_product.perfMark)("prepareProducts.extractIds", performance.now() - tIds, { count: ids.length });
326
+ (0, _product.perfMark)('prepareProducts.extractIds', performance.now() - tIds, {
327
+ count: ids.length
328
+ });
311
329
  }
312
- this.logInfo("获取到商品列表", { productCount: products.length });
330
+ this.logInfo('获取到商品列表', {
331
+ productCount: products.length
332
+ });
333
+
334
+ // 2. 获取价格数据(网络请求)
313
335
  const tPrice = performance.now();
314
336
  const priceData = await this.loadProductsPrice({
315
337
  ids,
316
338
  schedule_date
317
339
  });
318
- (0, import_product.perfMark)("prepareProducts.loadPrice", performance.now() - tPrice, { count: ids.length });
319
- this.logInfo("获取商品报价单价格成功", { priceDataCount: (priceData == null ? void 0 : priceData.length) ?? 0 });
340
+ (0, _product.perfMark)('prepareProducts.loadPrice', performance.now() - tPrice, {
341
+ count: ids.length
342
+ });
343
+ this.logInfo('获取商品报价单价格成功', {
344
+ priceDataCount: priceData?.length ?? 0
345
+ });
320
346
  const context = {
321
347
  schedule_date,
322
348
  priceData,
323
- locale: (_b = (_a = this.core) == null ? void 0 : _a.context) == null ? void 0 : _b.locale,
349
+ locale: this.core?.context?.locale,
324
350
  ...extraContext
325
351
  };
352
+
353
+ // 3. 通过格式化器流程处理商品
326
354
  const tFormat = performance.now();
327
355
  const processedProducts = await this.applyFormatters(products, context);
328
- (0, import_product.perfMark)("prepareProducts.applyFormatters", performance.now() - tFormat, {
356
+ (0, _product.perfMark)('prepareProducts.applyFormatters', performance.now() - tFormat, {
329
357
  count: products.length,
330
358
  formatterCount: this.formatters.length
331
359
  });
332
- this.logInfo("prepareProductsWithPrice 处理完成", {
333
- mode: isIncremental ? "incremental" : "full",
360
+ this.logInfo('prepareProductsWithPrice 处理完成', {
361
+ mode: isIncremental ? 'incremental' : 'full',
334
362
  originalProductCount: products.length,
335
363
  processedProductCount: processedProducts.length,
336
364
  formatterCount: this.formatters.length
337
365
  });
338
366
  if (!isIncremental) {
339
- await this.core.effects.emit(
340
- import_types.ProductsHooks.onProductsPriceApplied,
341
- processedProducts
342
- );
367
+ await this.core.effects.emit(_types.ProductsHooks.onProductsPriceApplied, processedProducts);
343
368
  }
344
- (0, import_product.perfMark)("prepareProductsWithPrice", performance.now() - tTotal, {
369
+ (0, _product.perfMark)('prepareProductsWithPrice', performance.now() - tTotal, {
345
370
  productCount: products.length,
346
371
  formatterCount: this.formatters.length,
347
- mode: isIncremental ? "incremental" : "full"
372
+ mode: isIncremental ? 'incremental' : 'full'
348
373
  });
349
374
  return processedProducts;
350
375
  } catch (err) {
351
376
  const errorMessage = err instanceof Error ? err.message : String(err);
352
- console.log(`[ProductsModule] 🌐 ERROR`, err);
353
- this.logError("prepareProductsWithPrice 处理失败", {
377
+ this.logError('prepareProductsWithPrice 处理失败', {
354
378
  schedule_date,
355
379
  error: errorMessage
356
380
  });
357
381
  }
358
382
  return [];
359
383
  }
384
+
360
385
  /**
361
386
  * 应用所有已注册的格式化器
362
387
  * @param products 商品列表
@@ -367,11 +392,13 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
367
392
  async applyFormatters(products, context) {
368
393
  let result = products;
369
394
  if (this.formatters.length === 0) {
370
- console.warn("[ProductsModule] ⚠️ 没有注册任何格式化器");
371
- this.logWarning("没有注册任何格式化器", { productCount: products.length });
395
+ console.warn('[ProductsModule] ⚠️ 没有注册任何格式化器');
396
+ this.logWarning('没有注册任何格式化器', {
397
+ productCount: products.length
398
+ });
372
399
  return result;
373
400
  }
374
- this.logInfo("开始应用格式化器", {
401
+ this.logInfo('开始应用格式化器', {
375
402
  productCount: products.length,
376
403
  formatterCount: this.formatters.length
377
404
  });
@@ -380,7 +407,7 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
380
407
  try {
381
408
  const tF = performance.now();
382
409
  result = await formatter(result, context);
383
- (0, import_product.perfMark)(`applyFormatters[${i}]`, performance.now() - tF, {
410
+ (0, _product.perfMark)(`applyFormatters[${i}]`, performance.now() - tF, {
384
411
  index: i,
385
412
  total: this.formatters.length,
386
413
  productCount: result.length
@@ -395,12 +422,13 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
395
422
  });
396
423
  }
397
424
  }
398
- this.logInfo("所有格式化器已应用", {
425
+ this.logInfo('所有格式化器已应用', {
399
426
  formatterCount: this.formatters.length,
400
427
  resultProductCount: result.length
401
428
  });
402
429
  return result;
403
430
  }
431
+
404
432
  /**
405
433
  * 注册内置的价格格式化器
406
434
  * 这个格式化器负责将价格数据应用到商品上
@@ -408,29 +436,31 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
408
436
  */
409
437
  registerBuiltinPriceFormatter() {
410
438
  if (this.isPriceFormatterRegistered) {
411
- console.warn("[ProductsModule] 内置价格格式化器已注册,跳过");
439
+ console.warn('[ProductsModule] 内置价格格式化器已注册,跳过');
412
440
  return;
413
441
  }
442
+
443
+ // 创建价格格式化器
414
444
  const priceFormatter = (products, context) => {
415
445
  if (!context.priceData || context.priceData.length === 0) {
416
- console.log("[ProductsModule] 💰 没有价格数据,跳过价格应用");
417
446
  return products;
418
447
  }
419
- console.log(`[ProductsModule] 💰 应用价格数据到 ${products.length} 个商品`);
420
- return (0, import_product.applyPriceDataToProducts)(products, context.priceData);
448
+ return (0, _product.applyPriceDataToProducts)(products, context.priceData);
421
449
  };
422
450
  const i18nFormatter = (products, context) => {
423
- return (0, import_product.applyI18nToProducts)(products, context.locale);
451
+ return (0, _product.applyI18nToProducts)(products, context.locale);
424
452
  };
425
453
  const detailValueFormatter = (products, context) => {
426
- return (0, import_product.applyDetailValueToProducts)(products, context);
454
+ return (0, _product.applyDetailValueToProducts)(products, context);
427
455
  };
456
+
457
+ // 将价格格式化器注册为第一个格式化器
428
458
  this.formatters.unshift(priceFormatter);
429
459
  this.formatters.push(i18nFormatter);
430
460
  this.formatters.push(detailValueFormatter);
431
461
  this.isPriceFormatterRegistered = true;
432
- console.log("[ProductsModule] ✅ 内置价格格式化器已注册(第 1 个)");
433
462
  }
463
+
434
464
  /**
435
465
  * 注册商品格式化器
436
466
  * 格式化器会按注册顺序依次执行(内置价格格式化器始终是第一个)
@@ -448,28 +478,29 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
448
478
  */
449
479
  registerFormatter(formatter, prepend = false) {
450
480
  if (prepend) {
481
+ // 插入到价格格式化器之后(索引 1 的位置)
451
482
  const insertIndex = this.isPriceFormatterRegistered ? 1 : 0;
452
483
  this.formatters.splice(insertIndex, 0, formatter);
453
- console.log(`[ProductsModule] 📌 已在位置 ${insertIndex + 1} 插入格式化器,当前共 ${this.formatters.length} 个`);
454
484
  } else {
485
+ // 追加到末尾
455
486
  this.formatters.push(formatter);
456
- console.log(`[ProductsModule] 📌 已注册格式化器,当前共 ${this.formatters.length} 个`);
457
487
  }
458
488
  }
489
+
459
490
  /**
460
491
  * 清空所有格式化器(包括内置价格格式化器)
461
492
  * @param keepBuiltin 是否保留内置价格格式化器(默认 true)
462
493
  */
463
494
  clearFormatters(keepBuiltin = true) {
464
495
  if (keepBuiltin && this.isPriceFormatterRegistered) {
496
+ // 只保留第一个格式化器(内置价格格式化器)
465
497
  this.formatters = [this.formatters[0]];
466
- console.log("[ProductsModule] 🧹 已清空自定义格式化器,保留内置价格格式化器");
467
498
  } else {
468
499
  this.formatters = [];
469
500
  this.isPriceFormatterRegistered = false;
470
- console.log("[ProductsModule] 🧹 已清空所有格式化器");
471
501
  }
472
502
  }
503
+
473
504
  /**
474
505
  * 清理过期的价格缓存
475
506
  * 当缓存数量超过限制时,删除最老的缓存
@@ -480,58 +511,64 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
480
511
  const keys = Array.from(this.productsPriceCache.keys());
481
512
  const oldestKey = keys[0];
482
513
  this.productsPriceCache.delete(oldestKey);
483
- console.log(`[ProductsModule] 🧹 清理过期商品价格缓存: ${oldestKey}`);
484
514
  }
485
515
  }
516
+
486
517
  /**
487
518
  * 清空商品价格缓存
488
519
  * 可用于手动刷新价格数据
489
520
  */
490
521
  clearPriceCache() {
491
522
  this.productsPriceCache.clear();
492
- console.log("[ProductsModule] 🗑️ 商品价格缓存已清空");
493
523
  }
524
+
494
525
  /**
495
526
  * 通过 ProductDataSource SSE 加载完整商品列表
496
527
  */
497
528
  async loadProductsByServer() {
498
529
  if (!this.productDataSource) {
499
- this.logWarning("loadProductsByServer: ProductDataSource 不可用");
530
+ this.logWarning('loadProductsByServer: ProductDataSource 不可用');
500
531
  return [];
501
532
  }
502
- this.logInfo("开始通过 DataSource SSE 加载商品列表");
533
+ this.logInfo('开始通过 DataSource SSE 加载商品列表');
503
534
  const t0 = performance.now();
504
535
  try {
505
536
  const tSSE = performance.now();
506
- const productList = await this.productDataSource.run({ sse: {} });
537
+ const productList = await this.productDataSource.run({
538
+ sse: {}
539
+ });
507
540
  const list = productList || [];
508
- (0, import_product.perfMark)("loadProductsByServer.SSE", performance.now() - tSSE, { count: list.length });
509
- this.logInfo("通过 DataSource SSE 加载商品列表成功", {
541
+ (0, _product.perfMark)('loadProductsByServer.SSE', performance.now() - tSSE, {
542
+ count: list.length
543
+ });
544
+ this.logInfo('通过 DataSource SSE 加载商品列表成功', {
510
545
  productCount: list.length,
511
546
  duration: `${Math.round(performance.now() - t0)}ms`
512
547
  });
513
548
  await this.saveProductsToIndexDB(list);
514
- await this.core.effects.emit(import_types.ProductsHooks.onProductsLoaded, list);
515
- (0, import_product.perfMark)("loadProductsByServer", performance.now() - t0, { count: list.length });
549
+ await this.core.effects.emit(_types.ProductsHooks.onProductsLoaded, list);
550
+ (0, _product.perfMark)('loadProductsByServer', performance.now() - t0, {
551
+ count: list.length
552
+ });
516
553
  return list;
517
554
  } catch (error) {
518
555
  const duration = Math.round(performance.now() - t0);
519
556
  const errorMessage = error instanceof Error ? error.message : String(error);
520
- console.error("[Products] 加载商品数据失败:", error);
521
- this.logError("通过 DataSource SSE 加载商品列表失败", {
557
+ console.error('[Products] 加载商品数据失败:', error);
558
+ this.logError('通过 DataSource SSE 加载商品列表失败', {
522
559
  duration: `${duration}ms`,
523
560
  error: errorMessage
524
561
  });
525
562
  return [];
526
563
  }
527
564
  }
565
+
528
566
  /**
529
567
  * 纯请求方法:通过 HTTP 接口获取商品列表(无副作用,不触发事件、不写 IndexDB)
530
568
  * @param params 查询参数
531
569
  * @returns 商品列表
532
570
  */
533
571
  async fetchProductsByHttp(params) {
534
- var _a, _b;
535
572
  const {
536
573
  category_ids = [],
537
574
  product_ids = [],
@@ -539,7 +576,7 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
539
576
  customer_id,
540
577
  cacheId
541
578
  } = params || {};
542
- this.logInfo("fetchProductsByHttp: 开始请求", {
579
+ this.logInfo('fetchProductsByHttp: 开始请求', {
543
580
  categoryIdsCount: category_ids.length,
544
581
  productIdsCount: product_ids.length,
545
582
  collectionCount: Array.isArray(collection) ? collection.length : collection ? 1 : 0,
@@ -547,45 +584,29 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
547
584
  });
548
585
  const startTime = Date.now();
549
586
  try {
550
- const productsData = await this.request.post(
551
- `/product/query`,
552
- {
553
- open_bundle: 1,
554
- exclude_extension_type: [
555
- "product_party",
556
- "product_event",
557
- "product_series_event",
558
- "product_package_ticket",
559
- "ticket",
560
- "event_item"
561
- ],
562
- force_ignore_cache_flag: 1,
563
- with: [
564
- "category",
565
- "collection",
566
- "resourceRelation",
567
- "bundleGroup.bundleItem",
568
- "optionGroup.optionItem",
569
- "variantGroup.variantItem"
570
- ],
571
- open_deposit: 1,
572
- is_append_product_description: 1,
573
- with_count: ["bundleGroup", "optionGroup"],
574
- with_category_tree: 1,
575
- status: "published",
576
- num: 500,
577
- skip: 1,
578
- category_ids,
579
- ids: product_ids,
580
- collection,
581
- front_end_cache_id: cacheId,
582
- application_code: (_a = this.otherParams) == null ? void 0 : _a.channel
583
- },
584
- { cache: void 0 }
585
- );
586
- const productList = ((_b = productsData == null ? void 0 : productsData.data) == null ? void 0 : _b.list) || [];
587
+ const productsData = await this.request.post(`/product/query`, {
588
+ open_bundle: 1,
589
+ exclude_extension_type: ['product_party', 'product_event', 'product_series_event', 'product_package_ticket', 'ticket', 'event_item'],
590
+ force_ignore_cache_flag: 1,
591
+ with: ['category', 'collection', 'resourceRelation', 'bundleGroup.bundleItem', 'optionGroup.optionItem', 'variantGroup.variantItem'],
592
+ open_deposit: 1,
593
+ is_append_product_description: 1,
594
+ with_count: ['bundleGroup', 'optionGroup'],
595
+ with_category_tree: 1,
596
+ status: 'published',
597
+ num: 500,
598
+ skip: 1,
599
+ category_ids,
600
+ ids: product_ids,
601
+ collection,
602
+ front_end_cache_id: cacheId,
603
+ application_code: this.otherParams?.channel
604
+ }, {
605
+ cache: undefined
606
+ });
607
+ const productList = productsData?.data?.list || [];
587
608
  const duration = Date.now() - startTime;
588
- this.logInfo("fetchProductsByHttp: 请求成功", {
609
+ this.logInfo('fetchProductsByHttp: 请求成功', {
589
610
  productCount: productList.length,
590
611
  duration: `${duration}ms`
591
612
  });
@@ -593,14 +614,15 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
593
614
  } catch (error) {
594
615
  const duration = Date.now() - startTime;
595
616
  const errorMessage = error instanceof Error ? error.message : String(error);
596
- console.error("[Products] fetchProductsByHttp 失败:", error);
597
- this.logError("fetchProductsByHttp: 请求失败", {
617
+ console.error('[Products] fetchProductsByHttp 失败:', error);
618
+ this.logError('fetchProductsByHttp: 请求失败', {
598
619
  duration: `${duration}ms`,
599
620
  error: errorMessage
600
621
  });
601
622
  return [];
602
623
  }
603
624
  }
625
+
604
626
  /**
605
627
  * 加载完整商品列表通过接口(包含所有详细数据)
606
628
  * 包含副作用:保存到 IndexDB + 触发 onProductsLoaded 事件
@@ -610,19 +632,23 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
610
632
  const productList = await this.fetchProductsByHttp(params);
611
633
  if (productList.length > 0) {
612
634
  await this.saveProductsToIndexDB(productList);
613
- await this.core.effects.emit(import_types.ProductsHooks.onProductsLoaded, productList);
635
+ await this.core.effects.emit(_types.ProductsHooks.onProductsLoaded, productList);
614
636
  }
615
637
  return productList;
616
638
  }
639
+
617
640
  /**
618
641
  * 获取商品列表(深拷贝,供外部安全使用)
619
642
  */
620
643
  async getProducts() {
621
644
  const t0 = performance.now();
622
645
  const result = structuredClone(this.store.list);
623
- (0, import_product.perfMark)("ProductsModule.getProducts(structuredClone)", performance.now() - t0, { count: result.length });
646
+ (0, _product.perfMark)('ProductsModule.getProducts(structuredClone)', performance.now() - t0, {
647
+ count: result.length
648
+ });
624
649
  return result;
625
650
  }
651
+
626
652
  /**
627
653
  * 内部获取商品列表的直接引用(无拷贝)
628
654
  * 仅供内部 formatter 流程使用,因为 formatter 会创建新对象
@@ -630,22 +656,27 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
630
656
  getProductsRef() {
631
657
  return this.store.list;
632
658
  }
659
+
633
660
  /**
634
661
  * 根据ID获取单个商品(从内存缓存)
635
662
  * 使用 Map 快速查询,时间复杂度 O(1)
636
663
  */
637
664
  async getProductById(id) {
638
665
  const product = this.store.map.get(id);
639
- return product ? structuredClone(product) : void 0;
666
+ return product ? structuredClone(product) : undefined;
640
667
  }
668
+
641
669
  /**
642
670
  * 根据 ID 列表删除商品(用于 pubsub 同步删除场景)
643
671
  * 同时更新 store.list、store.map、IndexDB 和价格缓存
644
672
  */
645
673
  async removeProductsByIds(ids) {
646
674
  const idSet = new Set(ids);
647
- this.logInfo("removeProductsByIds", { ids, count: ids.length });
648
- this.store.list = this.store.list.filter((p) => !idSet.has(p.id));
675
+ this.logInfo('removeProductsByIds', {
676
+ ids,
677
+ count: ids.length
678
+ });
679
+ this.store.list = this.store.list.filter(p => !idSet.has(p.id));
649
680
  for (const id of ids) {
650
681
  this.store.map.delete(id);
651
682
  }
@@ -656,113 +687,134 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
656
687
  }
657
688
  } catch (error) {
658
689
  const errorMessage = error instanceof Error ? error.message : String(error);
659
- this.logError("removeProductsByIds: IndexDB 删除失败", { ids, error: errorMessage });
690
+ this.logError('removeProductsByIds: IndexDB 删除失败', {
691
+ ids,
692
+ error: errorMessage
693
+ });
660
694
  }
661
695
  }
662
696
  for (const [dateKey, cachedProducts] of this.productsPriceCache.entries()) {
663
- this.productsPriceCache.set(
664
- dateKey,
665
- cachedProducts.filter((p) => !idSet.has(p.id))
666
- );
697
+ this.productsPriceCache.set(dateKey, cachedProducts.filter(p => !idSet.has(p.id)));
667
698
  }
668
- this.core.effects.emit(import_types.ProductsHooks.onProductsChanged, this.store.list);
669
- this.logInfo("removeProductsByIds 完成", { remaining: this.store.list.length });
699
+ this.core.effects.emit(_types.ProductsHooks.onProductsChanged, this.store.list);
700
+ this.logInfo('removeProductsByIds 完成', {
701
+ remaining: this.store.list.length
702
+ });
670
703
  }
704
+
671
705
  /**
672
706
  * 重新从服务器加载全量商品列表并更新本地 store
673
707
  * 用于 pubsub 同步 create / update / batch_update 场景
674
708
  */
675
709
  async refreshProducts() {
676
710
  const tTotal = performance.now();
677
- this.logInfo("refreshProducts 开始");
711
+ this.logInfo('refreshProducts 开始');
678
712
  const products = await this.loadProductsByServer();
679
713
  if (products && products.length > 0) {
714
+ // 服务器返回的数据已经是全新的,无需 cloneDeep
680
715
  this.store.list = products;
681
716
  this.syncProductsMap();
682
- this.core.effects.emit(import_types.ProductsHooks.onProductsChanged, this.store.list);
683
- this.logInfo("refreshProducts 完成", { productCount: products.length });
717
+ this.core.effects.emit(_types.ProductsHooks.onProductsChanged, this.store.list);
718
+ this.logInfo('refreshProducts 完成', {
719
+ productCount: products.length
720
+ });
684
721
  } else {
685
- this.logWarning("refreshProducts: 服务器未返回数据");
722
+ this.logWarning('refreshProducts: 服务器未返回数据');
686
723
  }
687
- (0, import_product.perfMark)("refreshProducts", performance.now() - tTotal, { count: this.store.list.length });
724
+ (0, _product.perfMark)('refreshProducts', performance.now() - tTotal, {
725
+ count: this.store.list.length
726
+ });
688
727
  return this.store.list;
689
728
  }
729
+
690
730
  /**
691
731
  * 清空缓存
692
732
  */
693
733
  async clear() {
694
- this.logInfo("开始清空缓存", {
734
+ this.logInfo('开始清空缓存', {
695
735
  currentProductCount: this.store.list.length,
696
736
  priceCacheCount: this.productsPriceCache.size
697
737
  });
698
738
  this.store.list = [];
699
739
  this.store.map.clear();
740
+
741
+ // 同时清空 IndexDB 中的所有数据(包括商品和元数据)
700
742
  if (this.dbManager) {
701
743
  try {
702
744
  await this.dbManager.clear(INDEXDB_STORE_NAME);
703
- console.log("[Products] IndexDB 缓存已清空");
704
- this.logInfo("IndexDB 缓存已清空");
745
+ this.logInfo('IndexDB 缓存已清空');
705
746
  } catch (error) {
706
747
  const errorMessage = error instanceof Error ? error.message : String(error);
707
- console.error("[Products] 清空 IndexDB 缓存失败:", error);
708
- this.logError("清空 IndexDB 缓存失败", { error: errorMessage });
748
+ console.error('[Products] 清空 IndexDB 缓存失败:', error);
749
+ this.logError('清空 IndexDB 缓存失败', {
750
+ error: errorMessage
751
+ });
709
752
  }
710
753
  }
711
- console.log("[Products] 缓存已清空");
712
- this.logInfo("缓存清空完成");
754
+ this.logInfo('缓存清空完成');
713
755
  }
756
+
714
757
  /**
715
758
  * 从 IndexDB 加载商品数据
716
759
  * @private
717
760
  */
718
761
  async loadProductsFromIndexDB() {
719
762
  if (!this.dbManager) {
720
- this.logWarning("loadProductsFromIndexDB: dbManager 不可用");
763
+ this.logWarning('loadProductsFromIndexDB: dbManager 不可用');
721
764
  return [];
722
765
  }
723
766
  try {
724
767
  const t0 = performance.now();
725
768
  const products = await this.dbManager.getAll(INDEXDB_STORE_NAME);
726
- (0, import_product.perfMark)("loadProductsFromIndexDB", performance.now() - t0, { count: (products == null ? void 0 : products.length) ?? 0 });
727
- this.logInfo("从 IndexDB 加载商品数据", {
728
- productCount: (products == null ? void 0 : products.length) ?? 0
769
+ (0, _product.perfMark)('loadProductsFromIndexDB', performance.now() - t0, {
770
+ count: products?.length ?? 0
771
+ });
772
+ this.logInfo('从 IndexDB 加载商品数据', {
773
+ productCount: products?.length ?? 0
729
774
  });
730
775
  return products || [];
731
776
  } catch (error) {
732
777
  const errorMessage = error instanceof Error ? error.message : String(error);
733
- console.error("[Products] 从 IndexDB 读取数据失败:", error);
734
- this.logError("从 IndexDB 读取数据失败", { error: errorMessage });
778
+ console.error('[Products] 从 IndexDB 读取数据失败:', error);
779
+ this.logError('从 IndexDB 读取数据失败', {
780
+ error: errorMessage
781
+ });
735
782
  return [];
736
783
  }
737
784
  }
785
+
738
786
  /**
739
787
  * 保存商品数据到 IndexDB(平铺存储)
740
788
  * @private
741
789
  */
742
790
  async saveProductsToIndexDB(products) {
743
791
  if (!this.dbManager) {
744
- this.logWarning("saveProductsToIndexDB: dbManager 不可用");
792
+ this.logWarning('saveProductsToIndexDB: dbManager 不可用');
745
793
  return;
746
794
  }
747
- this.logInfo("开始保存商品数据到 IndexDB", { productCount: products.length });
795
+ this.logInfo('开始保存商品数据到 IndexDB', {
796
+ productCount: products.length
797
+ });
748
798
  try {
749
799
  const t0 = performance.now();
750
800
  await this.dbManager.clear(INDEXDB_STORE_NAME);
751
801
  await this.dbManager.bulkUpdate(INDEXDB_STORE_NAME, products);
752
- (0, import_product.perfMark)("saveProductsToIndexDB", performance.now() - t0, { count: products.length });
753
- console.log(
754
- `[Products] 已将 ${products.length} 个商品平铺保存到 IndexDB`
755
- );
756
- this.logInfo("商品数据已保存到 IndexDB", { productCount: products.length });
802
+ (0, _product.perfMark)('saveProductsToIndexDB', performance.now() - t0, {
803
+ count: products.length
804
+ });
805
+ this.logInfo('商品数据已保存到 IndexDB', {
806
+ productCount: products.length
807
+ });
757
808
  } catch (error) {
758
809
  const errorMessage = error instanceof Error ? error.message : String(error);
759
- console.error("[Products] 保存数据到 IndexDB 失败:", error);
760
- this.logError("保存数据到 IndexDB 失败", {
810
+ console.error('[Products] 保存数据到 IndexDB 失败:', error);
811
+ this.logError('保存数据到 IndexDB 失败', {
761
812
  productCount: products.length,
762
813
  error: errorMessage
763
814
  });
764
815
  }
765
816
  }
817
+
766
818
  /**
767
819
  * 同步更新商品 Map 缓存
768
820
  * 将 list 中的商品同步到 map,以 id 为 key
@@ -774,90 +826,103 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
774
826
  for (const product of this.store.list) {
775
827
  this.store.map.set(product.id, product);
776
828
  }
777
- (0, import_product.perfMark)("syncProductsMap", performance.now() - t0, { count: this.store.map.size });
829
+ (0, _product.perfMark)('syncProductsMap', performance.now() - t0, {
830
+ count: this.store.map.size
831
+ });
778
832
  }
833
+
779
834
  /**
780
835
  * 预加载模块数据(统一接口)
781
836
  * 在模块注册后自动调用
782
837
  */
783
838
  async preload() {
784
- console.log("[Products] 开始预加载数据...");
785
839
  const tTotal = performance.now();
786
- this.logInfo("开始预加载数据");
840
+ this.logInfo('开始预加载数据');
787
841
  try {
788
842
  const tIndexDB = performance.now();
789
843
  const cachedData = await this.loadProductsFromIndexDB();
790
- (0, import_product.perfMark)("preload.loadFromIndexDB", performance.now() - tIndexDB, { count: (cachedData == null ? void 0 : cachedData.length) ?? 0 });
844
+ (0, _product.perfMark)('preload.loadFromIndexDB', performance.now() - tIndexDB, {
845
+ count: cachedData?.length ?? 0
846
+ });
791
847
  if (cachedData && cachedData.length > 0) {
792
- console.log(`[Products] 从 IndexDB 加载了 ${cachedData.length} 个商品`);
848
+ // IndexDB 反序列化的数据已经是全新的,无需 cloneDeep
793
849
  this.store.list = cachedData;
794
850
  const tSync = performance.now();
795
851
  this.syncProductsMap();
796
- (0, import_product.perfMark)("preload.syncProductsMap", performance.now() - tSync, { count: cachedData.length });
797
- this.core.effects.emit(
798
- import_types.ProductsHooks.onProductsChanged,
799
- this.store.list
800
- );
801
- (0, import_product.perfMark)("preload(IndexDB)", performance.now() - tTotal, {
852
+ (0, _product.perfMark)('preload.syncProductsMap', performance.now() - tSync, {
853
+ count: cachedData.length
854
+ });
855
+ this.core.effects.emit(_types.ProductsHooks.onProductsChanged, this.store.list);
856
+ (0, _product.perfMark)('preload(IndexDB)', performance.now() - tTotal, {
802
857
  count: cachedData.length,
803
- source: "IndexDB"
858
+ source: 'IndexDB'
804
859
  });
805
- this.logInfo("预加载完成(从 IndexDB)", {
860
+ this.logInfo('预加载完成(从 IndexDB)', {
806
861
  productCount: cachedData.length,
807
862
  duration: `${Math.round(performance.now() - tTotal)}ms`,
808
- source: "IndexDB"
863
+ source: 'IndexDB'
809
864
  });
810
865
  return;
811
866
  }
812
- console.log("[Products] IndexDB 中没有缓存数据,从服务器加载...");
813
- this.logInfo("IndexDB 中没有缓存数据,准备从服务器加载");
867
+ this.logInfo('IndexDB 中没有缓存数据,准备从服务器加载');
814
868
  } catch (error) {
815
869
  const errorMessage = error instanceof Error ? error.message : String(error);
816
- console.warn("[Products] 从 IndexDB 加载数据失败:", error);
817
- this.logWarning("从 IndexDB 加载数据失败,准备从服务器加载", { error: errorMessage });
870
+ console.warn('[Products] 从 IndexDB 加载数据失败:', error);
871
+ this.logWarning('从 IndexDB 加载数据失败,准备从服务器加载', {
872
+ error: errorMessage
873
+ });
818
874
  }
819
875
  const tServer = performance.now();
820
876
  const products = await this.loadProductsByServer();
821
- (0, import_product.perfMark)("preload.loadFromServer", performance.now() - tServer, { count: (products == null ? void 0 : products.length) ?? 0 });
877
+ (0, _product.perfMark)('preload.loadFromServer', performance.now() - tServer, {
878
+ count: products?.length ?? 0
879
+ });
822
880
  if (products && products.length > 0) {
881
+ // 服务器返回的数据已经是全新的,无需 cloneDeep
823
882
  this.store.list = products;
824
883
  const tSync = performance.now();
825
884
  this.syncProductsMap();
826
- (0, import_product.perfMark)("preload.syncProductsMap", performance.now() - tSync, { count: products.length });
827
- this.core.effects.emit(import_types.ProductsHooks.onProductsChanged, this.store.list);
828
- (0, import_product.perfMark)("preload(Server)", performance.now() - tTotal, {
885
+ (0, _product.perfMark)('preload.syncProductsMap', performance.now() - tSync, {
886
+ count: products.length
887
+ });
888
+ this.core.effects.emit(_types.ProductsHooks.onProductsChanged, this.store.list);
889
+ (0, _product.perfMark)('preload(Server)', performance.now() - tTotal, {
829
890
  count: products.length,
830
- source: "Server"
891
+ source: 'Server'
831
892
  });
832
- this.logInfo("预加载完成(从服务器)", {
893
+ this.logInfo('预加载完成(从服务器)', {
833
894
  productCount: products.length,
834
895
  duration: `${Math.round(performance.now() - tTotal)}ms`,
835
- source: "Server"
896
+ source: 'Server'
836
897
  });
837
898
  } else {
838
- (0, import_product.perfMark)("preload(empty)", performance.now() - tTotal, { source: "empty" });
839
- this.logWarning("预加载完成但未获取到数据", {
899
+ (0, _product.perfMark)('preload(empty)', performance.now() - tTotal, {
900
+ source: 'empty'
901
+ });
902
+ this.logWarning('预加载完成但未获取到数据', {
840
903
  duration: `${Math.round(performance.now() - tTotal)}ms`
841
904
  });
842
905
  }
843
906
  }
907
+
844
908
  // =============================================
845
909
  // 商品数据同步(pubsub)
846
910
  // =============================================
911
+
847
912
  /**
848
913
  * 初始化 ProductDataSource 实例
849
914
  * 与 pubsub 订阅和数据获取分开,仅负责创建实例
850
915
  */
851
916
  initProductDataSource() {
852
- var _a, _b;
853
- const ProductDataSourceClass = (_b = (_a = this.core.serverOptions) == null ? void 0 : _a.All_DATA_SOURCES) == null ? void 0 : _b.ProductDataSource;
917
+ const ProductDataSourceClass = this.core.serverOptions?.All_DATA_SOURCES?.ProductDataSource;
854
918
  if (!ProductDataSourceClass) {
855
- this.logWarning("initProductDataSource: ProductDataSource 不可用");
919
+ this.logWarning('initProductDataSource: ProductDataSource 不可用');
856
920
  return;
857
921
  }
858
922
  this.productDataSource = new ProductDataSourceClass();
859
- this.logInfo("ProductDataSource 实例已创建");
923
+ this.logInfo('ProductDataSource 实例已创建');
860
924
  }
925
+
861
926
  /**
862
927
  * 初始化 pubsub 订阅,监听管理后台商品变更
863
928
  * 仅负责订阅 product / product_quotation 频道,消息通过防抖合并后批量处理
@@ -865,21 +930,22 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
865
930
  */
866
931
  setupProductSync() {
867
932
  if (!this.productDataSource) {
868
- this.logWarning("setupProductSync: ProductDataSource 不可用,跳过同步初始化");
933
+ this.logWarning('setupProductSync: ProductDataSource 不可用,跳过同步初始化');
869
934
  return;
870
935
  }
871
- const createHandler = (channelKey) => (message) => {
872
- const data = (message == null ? void 0 : message.data) || message;
873
- if (!data)
874
- return;
875
- console.log(`[ProductsModule] 收到同步消息 [${channelKey}]:`, data);
876
- this.logInfo("收到同步消息", {
936
+ const createHandler = channelKey => message => {
937
+ const data = message?.data || message;
938
+ if (!data) return;
939
+ this.logInfo('收到同步消息', {
877
940
  channelKey,
878
941
  action: data.action,
879
942
  id: data.id,
880
943
  action_filed: data.action_filed
881
944
  });
882
- this.pendingSyncMessages.push({ ...data, _channelKey: channelKey });
945
+ this.pendingSyncMessages.push({
946
+ ...data,
947
+ _channelKey: channelKey
948
+ });
883
949
  if (this.syncTimer) {
884
950
  clearTimeout(this.syncTimer);
885
951
  }
@@ -889,25 +955,24 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
889
955
  };
890
956
  this.productDataSource.run({
891
957
  pubsub: {
892
- callback: (res) => {
893
- console.log("sse_products_callback", res);
894
- this.logInfo("sse_products_callback: 收到同步消息", {
895
- data: res == null ? void 0 : res.data
958
+ callback: res => {
959
+ this.logInfo('sse_products_callback: 收到同步消息', {
960
+ data: res?.data
896
961
  });
897
- if (!(res == null ? void 0 : res.data))
898
- return;
962
+ if (!res?.data) return;
899
963
  const data = res.data;
900
- const channelKey = data.module || "product";
964
+ const channelKey = data.module || 'product';
901
965
  createHandler(channelKey)(data);
902
966
  }
903
967
  }
904
- }).catch((err) => {
905
- this.logError("setupProductSync: DataSource run 出错", {
968
+ }).catch(err => {
969
+ this.logError('setupProductSync: DataSource run 出错', {
906
970
  error: err instanceof Error ? err.message : String(err)
907
971
  });
908
972
  });
909
- this.logInfo("setupProductSync: pubsub 订阅已建立");
973
+ this.logInfo('setupProductSync: pubsub 订阅已建立');
910
974
  }
975
+
911
976
  /**
912
977
  * 处理防抖后的同步消息批次
913
978
  *
@@ -927,58 +992,61 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
927
992
  * Server 层监听该事件后对变更商品增量执行 prepareProductsWithPrice 并更新缓存
928
993
  */
929
994
  async processProductSyncMessages() {
930
- var _a, _b, _c, _d, _e, _f;
931
995
  const messages = [...this.pendingSyncMessages];
932
996
  this.pendingSyncMessages = [];
933
- if (messages.length === 0)
934
- return;
935
- this.logInfo("processProductSyncMessages: 开始处理", { count: messages.length });
997
+ if (messages.length === 0) return;
998
+ this.logInfo('processProductSyncMessages: 开始处理', {
999
+ count: messages.length
1000
+ });
936
1001
  const deleteIds = [];
937
- const bodyUpdates = /* @__PURE__ */ new Map();
1002
+ const bodyUpdates = new Map();
938
1003
  const sseRefreshIds = [];
939
1004
  const priceRefreshIds = [];
940
1005
  let shouldClearPriceCache = false;
941
1006
  for (const msg of messages) {
942
- const channelKey = msg._channelKey || msg.module || "product";
943
- if (channelKey === "product") {
944
- if ((_a = msg.relation_product_ids) == null ? void 0 : _a.length) {
1007
+ const channelKey = msg._channelKey || msg.module || 'product';
1008
+ if (channelKey === 'product') {
1009
+ if (msg.relation_product_ids?.length) {
945
1010
  sseRefreshIds.push(...msg.relation_product_ids);
946
1011
  }
947
- if (msg.operation === "delete" || msg.action === "delete") {
948
- if ((_b = msg.ids) == null ? void 0 : _b.length)
949
- deleteIds.push(...msg.ids);
950
- else if (msg.id)
951
- deleteIds.push(msg.id);
1012
+ // 1. 删除场景:operation === 'delete' 或 action === 'delete'
1013
+ if (msg.operation === 'delete' || msg.action === 'delete') {
1014
+ if (msg.ids?.length) deleteIds.push(...msg.ids);else if (msg.id) deleteIds.push(msg.id);
952
1015
  continue;
953
1016
  }
954
- if ((_c = msg.change_types) == null ? void 0 : _c.includes("price")) {
1017
+
1018
+ // 2. change_types 包含 price → 仅收集需要刷新价格的 IDs(不走 SSE 拉取)
1019
+ if (msg.change_types?.includes('price')) {
955
1020
  const ids = msg.ids || (msg.id ? [msg.id] : []);
956
1021
  priceRefreshIds.push(...ids);
957
1022
  if (msg.body) {
958
1023
  const bodyId = msg.body.id;
959
- if (bodyId)
960
- bodyUpdates.set(bodyId, msg.body);
1024
+ if (bodyId) bodyUpdates.set(bodyId, msg.body);
961
1025
  }
962
1026
  continue;
963
1027
  }
1028
+
1029
+ // 3. 有 body → 完整数据直接覆盖本地
964
1030
  if (msg.body) {
965
1031
  const bodyId = msg.body.id || msg.id;
966
- if (bodyId)
967
- bodyUpdates.set(bodyId, msg.body);
1032
+ if (bodyId) bodyUpdates.set(bodyId, msg.body);
968
1033
  continue;
969
1034
  }
970
- if ((_d = msg.ids) == null ? void 0 : _d.length) {
1035
+
1036
+ // 4. 其他情况(有 ids 无 body 无 change_types)→ SSE 拉取
1037
+ if (msg.ids?.length) {
971
1038
  sseRefreshIds.push(...msg.ids);
972
1039
  } else if (msg.id) {
973
1040
  sseRefreshIds.push(msg.id);
974
1041
  }
975
- } else if (channelKey === "product_quotation") {
1042
+ } else if (channelKey === 'product_quotation') {
1043
+ // 报价单变更影响范围大,标记清除全量价格缓存
976
1044
  shouldClearPriceCache = true;
977
- if ((_e = msg.relation_product_ids) == null ? void 0 : _e.length) {
1045
+ if (msg.relation_product_ids?.length) {
978
1046
  sseRefreshIds.push(...msg.relation_product_ids);
979
1047
  }
980
- } else if (["product_collection", "product_category"].includes(channelKey)) {
981
- if ((_f = msg.relation_product_ids) == null ? void 0 : _f.length) {
1048
+ } else if (['product_collection', 'product_category'].includes(channelKey)) {
1049
+ if (msg.relation_product_ids?.length) {
982
1050
  sseRefreshIds.push(...msg.relation_product_ids);
983
1051
  }
984
1052
  }
@@ -986,28 +1054,32 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
986
1054
  const uniqueDeleteIds = [...new Set(deleteIds)];
987
1055
  const uniqueSSEIds = [...new Set(sseRefreshIds)];
988
1056
  const uniquePriceIds = [...new Set(priceRefreshIds)];
1057
+
1058
+ // 1. 处理删除
989
1059
  if (uniqueDeleteIds.length > 0) {
990
1060
  await this.removeProductsByIds(uniqueDeleteIds);
991
1061
  }
1062
+
1063
+ // 2. 处理 body 直接覆盖(store.list 更新,价格缓存不清除)
992
1064
  if (bodyUpdates.size > 0) {
993
1065
  await this.applyBodyUpdatesToStore(bodyUpdates);
994
1066
  }
1067
+
1068
+ // 3. 处理 SSE 增量拉取(store.list 更新,价格缓存不清除)
995
1069
  if (uniqueSSEIds.length > 0) {
996
1070
  const freshProducts = await this.fetchProductsBySSE(uniqueSSEIds);
997
1071
  if (freshProducts.length > 0) {
998
1072
  await this.mergeProductsToStore(freshProducts);
999
1073
  }
1000
- this.logInfo("processProductSyncMessages: SSE 增量更新完成123", {
1074
+ this.logInfo('processProductSyncMessages: SSE 增量更新完成123', {
1001
1075
  requestedCount: uniqueSSEIds.length,
1002
1076
  receivedCount: freshProducts.length
1003
1077
  });
1004
1078
  }
1005
- const allChangedIds = [.../* @__PURE__ */ new Set([
1006
- ...Array.from(bodyUpdates.keys()),
1007
- ...uniqueSSEIds,
1008
- ...uniquePriceIds
1009
- ])];
1010
- this.logInfo("processProductSyncMessages: 处理完成123", {
1079
+
1080
+ // 收集所有非 delete 的变更 IDs(body + SSE + price),用于增量更新价格缓存
1081
+ const allChangedIds = [...new Set([...Array.from(bodyUpdates.keys()), ...uniqueSSEIds, ...uniquePriceIds])];
1082
+ this.logInfo('processProductSyncMessages: 处理完成123', {
1011
1083
  deleteCount: uniqueDeleteIds.length,
1012
1084
  bodyUpdateCount: bodyUpdates.size,
1013
1085
  sseRefreshCount: uniqueSSEIds.length,
@@ -1017,34 +1089,47 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
1017
1089
  });
1018
1090
  const hasChanges = uniqueDeleteIds.length > 0 || allChangedIds.length > 0 || shouldClearPriceCache;
1019
1091
  if (!hasChanges) {
1020
- this.logInfo("processProductSyncMessages: 没有变更,不触发 onProductsSyncCompleted");
1092
+ this.logInfo('processProductSyncMessages: 没有变更,不触发 onProductsSyncCompleted');
1021
1093
  return;
1022
1094
  }
1095
+
1096
+ // 报价单变更 → 清除全量价格缓存,后续走全量重建
1023
1097
  if (shouldClearPriceCache) {
1024
1098
  this.clearPriceCache();
1025
1099
  }
1026
- await this.core.effects.emit(import_types.ProductsHooks.onProductsSyncCompleted, {
1100
+ await this.core.effects.emit(_types.ProductsHooks.onProductsSyncCompleted, {
1027
1101
  changedIds: allChangedIds
1028
1102
  });
1029
1103
  }
1104
+
1030
1105
  /**
1031
1106
  * 通过 SSE 按 ids 增量拉取商品数据
1032
1107
  * 请求 GET /shop/core/stream?type=product&ids={ids}
1033
1108
  */
1034
1109
  async fetchProductsBySSE(ids) {
1035
1110
  if (!this.productDataSource) {
1036
- this.logWarning("fetchProductsBySSE: ProductDataSource 不可用");
1111
+ this.logWarning('fetchProductsBySSE: ProductDataSource 不可用');
1037
1112
  return [];
1038
1113
  }
1039
- this.logInfo("fetchProductsBySSE: 开始", { ids, count: ids.length });
1114
+ this.logInfo('fetchProductsBySSE: 开始', {
1115
+ ids,
1116
+ count: ids.length
1117
+ });
1040
1118
  const t0 = performance.now();
1041
1119
  try {
1042
1120
  const productList = await this.productDataSource.run({
1043
- sse: { query: { type: "product", ids } }
1121
+ sse: {
1122
+ query: {
1123
+ type: 'product',
1124
+ ids
1125
+ }
1126
+ }
1044
1127
  });
1045
1128
  const list = productList || [];
1046
- (0, import_product.perfMark)("fetchProductsBySSE", performance.now() - t0, { count: list.length });
1047
- this.logInfo("fetchProductsBySSE: 成功", {
1129
+ (0, _product.perfMark)('fetchProductsBySSE', performance.now() - t0, {
1130
+ count: list.length
1131
+ });
1132
+ this.logInfo('fetchProductsBySSE: 成功', {
1048
1133
  requestedCount: ids.length,
1049
1134
  receivedCount: list.length,
1050
1135
  duration: `${Math.round(performance.now() - t0)}ms`
@@ -1052,10 +1137,14 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
1052
1137
  return list;
1053
1138
  } catch (error) {
1054
1139
  const errorMessage = error instanceof Error ? error.message : String(error);
1055
- this.logError("fetchProductsBySSE: 失败", { ids, error: errorMessage });
1140
+ this.logError('fetchProductsBySSE: 失败', {
1141
+ ids,
1142
+ error: errorMessage
1143
+ });
1056
1144
  return [];
1057
1145
  }
1058
1146
  }
1147
+
1059
1148
  /**
1060
1149
  * 将 body 完整数据直接覆盖到本地 store(不调用报价单接口)
1061
1150
  * 已存在的 → 直接替换;不存在的 → 追加
@@ -1063,11 +1152,13 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
1063
1152
  * 价格缓存由 processProductSyncMessages 末尾统一清除
1064
1153
  */
1065
1154
  async applyBodyUpdatesToStore(bodyUpdates) {
1066
- this.logInfo("applyBodyUpdatesToStore: 开始", { count: bodyUpdates.size });
1155
+ this.logInfo('applyBodyUpdatesToStore: 开始', {
1156
+ count: bodyUpdates.size
1157
+ });
1067
1158
  let updatedCount = 0;
1068
1159
  let newCount = 0;
1069
- const appliedIds = /* @__PURE__ */ new Set();
1070
- this.store.list = this.store.list.map((p) => {
1160
+ const appliedIds = new Set();
1161
+ this.store.list = this.store.list.map(p => {
1071
1162
  if (bodyUpdates.has(p.id)) {
1072
1163
  updatedCount++;
1073
1164
  appliedIds.add(p.id);
@@ -1083,24 +1174,25 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
1083
1174
  }
1084
1175
  this.syncProductsMap();
1085
1176
  await this.saveProductsToIndexDB(this.store.list);
1086
- this.core.effects.emit(import_types.ProductsHooks.onProductsChanged, this.store.list);
1087
- this.logInfo("applyBodyUpdatesToStore: 完成", {
1177
+ this.core.effects.emit(_types.ProductsHooks.onProductsChanged, this.store.list);
1178
+ this.logInfo('applyBodyUpdatesToStore: 完成', {
1088
1179
  updatedCount,
1089
1180
  newCount,
1090
1181
  totalCount: this.store.list.length
1091
1182
  });
1092
1183
  }
1184
+
1093
1185
  /**
1094
1186
  * 将增量拉取的商品合并到 store
1095
1187
  * 已存在的 → 替换;新的 → 追加
1096
1188
  * 同时更新 store.map、IndexDB,触发 onProductsChanged
1097
1189
  */
1098
1190
  async mergeProductsToStore(freshProducts) {
1099
- const freshMap = /* @__PURE__ */ new Map();
1191
+ const freshMap = new Map();
1100
1192
  for (const p of freshProducts) {
1101
1193
  freshMap.set(p.id, p);
1102
1194
  }
1103
- const updatedList = this.store.list.map((p) => {
1195
+ const updatedList = this.store.list.map(p => {
1104
1196
  if (freshMap.has(p.id)) {
1105
1197
  const fresh = freshMap.get(p.id);
1106
1198
  freshMap.delete(p.id);
@@ -1108,6 +1200,8 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
1108
1200
  }
1109
1201
  return p;
1110
1202
  });
1203
+
1204
+ // freshMap 中剩余的是新商品(create 场景)
1111
1205
  const newCount = freshMap.size;
1112
1206
  for (const p of freshMap.values()) {
1113
1207
  updatedList.push(p);
@@ -1116,13 +1210,14 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
1116
1210
  this.store.list = updatedList;
1117
1211
  this.syncProductsMap();
1118
1212
  await this.saveProductsToIndexDB(this.store.list);
1119
- this.logInfo("mergeProductsToStore: 合并完成", {
1213
+ this.logInfo('mergeProductsToStore: 合并完成', {
1120
1214
  updatedCount,
1121
1215
  newCount,
1122
1216
  totalCount: this.store.list.length
1123
1217
  });
1124
- this.core.effects.emit(import_types.ProductsHooks.onProductsChanged, this.store.list);
1218
+ this.core.effects.emit(_types.ProductsHooks.onProductsChanged, this.store.list);
1125
1219
  }
1220
+
1126
1221
  /**
1127
1222
  * 静默全量刷新:后台重新拉取全量 SSE 数据并更新本地
1128
1223
  * 拿到完整数据后一次性替换 store,清除价格缓存,触发 onProductsSyncCompleted
@@ -1130,48 +1225,51 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
1130
1225
  */
1131
1226
  async silentRefresh() {
1132
1227
  const t0 = performance.now();
1133
- this.logInfo("silentRefresh 开始");
1228
+ this.logInfo('silentRefresh 开始');
1134
1229
  try {
1135
1230
  const products = await this.loadProductsByServer();
1136
1231
  if (products && products.length > 0) {
1137
1232
  this.store.list = products;
1138
1233
  this.syncProductsMap();
1139
1234
  this.clearPriceCache();
1140
- this.core.effects.emit(import_types.ProductsHooks.onProductsChanged, this.store.list);
1141
- await this.core.effects.emit(import_types.ProductsHooks.onProductsSyncCompleted, null);
1142
- this.logInfo("silentRefresh 完成", {
1235
+ this.core.effects.emit(_types.ProductsHooks.onProductsChanged, this.store.list);
1236
+ await this.core.effects.emit(_types.ProductsHooks.onProductsSyncCompleted, null);
1237
+ this.logInfo('silentRefresh 完成', {
1143
1238
  productCount: products.length,
1144
1239
  duration: `${Math.round(performance.now() - t0)}ms`
1145
1240
  });
1146
1241
  } else {
1147
- this.logWarning("silentRefresh: 服务器未返回数据");
1242
+ this.logWarning('silentRefresh: 服务器未返回数据');
1148
1243
  }
1149
- (0, import_product.perfMark)("silentRefresh", performance.now() - t0, { count: this.store.list.length });
1244
+ (0, _product.perfMark)('silentRefresh', performance.now() - t0, {
1245
+ count: this.store.list.length
1246
+ });
1150
1247
  return this.store.list;
1151
1248
  } catch (error) {
1152
1249
  const errorMessage = error instanceof Error ? error.message : String(error);
1153
- this.logError("silentRefresh 失败", {
1250
+ this.logError('silentRefresh 失败', {
1154
1251
  duration: `${Math.round(performance.now() - t0)}ms`,
1155
1252
  error: errorMessage
1156
1253
  });
1157
1254
  return this.store.list;
1158
1255
  }
1159
1256
  }
1257
+
1160
1258
  /**
1161
1259
  * 销毁同步资源(取消 pubsub 订阅、清除定时器)
1162
1260
  */
1163
1261
  destroyProductSync() {
1164
- var _a;
1165
1262
  if (this.syncTimer) {
1166
1263
  clearTimeout(this.syncTimer);
1167
- this.syncTimer = void 0;
1264
+ this.syncTimer = undefined;
1168
1265
  }
1169
- if ((_a = this.productDataSource) == null ? void 0 : _a.destroy) {
1266
+ if (this.productDataSource?.destroy) {
1170
1267
  this.productDataSource.destroy();
1171
1268
  }
1172
1269
  this.pendingSyncMessages = [];
1173
- this.logInfo("destroyProductSync: 同步资源已销毁");
1270
+ this.logInfo('destroyProductSync: 同步资源已销毁');
1174
1271
  }
1272
+
1175
1273
  /**
1176
1274
  * 获取模块的路由定义
1177
1275
  * Products 模块暂不提供路由,由 Server 层统一处理
@@ -1179,8 +1277,5 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
1179
1277
  getRoutes() {
1180
1278
  return [];
1181
1279
  }
1182
- };
1183
- // Annotate the CommonJS export names for ESM import in node:
1184
- 0 && (module.exports = {
1185
- ProductsModule
1186
- });
1280
+ }
1281
+ exports.ProductsModule = ProductsModule;