@pisell/pisellos 2.2.93 → 2.2.94

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 (69) hide show
  1. package/dist/core/index.d.ts +0 -1
  2. package/dist/core/index.js +0 -7
  3. package/dist/modules/Customer/index.d.ts +0 -1
  4. package/dist/modules/Customer/index.js +12 -28
  5. package/dist/plugins/app-types/app/app.d.ts +1 -0
  6. package/dist/server/index.d.ts +55 -5
  7. package/dist/server/index.js +832 -236
  8. package/dist/server/modules/index.d.ts +6 -0
  9. package/dist/server/modules/index.js +7 -0
  10. package/dist/server/modules/order/index.d.ts +87 -0
  11. package/dist/server/modules/order/index.js +916 -0
  12. package/dist/server/modules/order/types.d.ts +530 -0
  13. package/dist/server/modules/order/types.js +141 -0
  14. package/dist/server/modules/order/utils/filterBookings.d.ts +6 -0
  15. package/dist/server/modules/order/utils/filterBookings.js +350 -0
  16. package/dist/server/modules/order/utils/filterOrders.d.ts +15 -0
  17. package/dist/server/modules/order/utils/filterOrders.js +226 -0
  18. package/dist/server/modules/products/index.d.ts +24 -19
  19. package/dist/server/modules/products/index.js +600 -429
  20. package/dist/server/modules/products/types.d.ts +0 -1
  21. package/dist/server/modules/resource/index.d.ts +88 -0
  22. package/dist/server/modules/resource/index.js +1202 -0
  23. package/dist/server/modules/resource/types.d.ts +121 -0
  24. package/dist/server/modules/resource/types.js +47 -0
  25. package/dist/server/utils/product.d.ts +0 -4
  26. package/dist/server/utils/product.js +0 -34
  27. package/dist/solution/BookingTicket/index.d.ts +1 -1
  28. package/dist/solution/Sales/index.d.ts +96 -0
  29. package/dist/solution/Sales/index.js +510 -0
  30. package/dist/solution/Sales/types.d.ts +65 -0
  31. package/dist/solution/Sales/types.js +26 -0
  32. package/dist/solution/index.d.ts +1 -0
  33. package/dist/solution/index.js +2 -1
  34. package/dist/types/index.d.ts +0 -2
  35. package/lib/core/index.d.ts +0 -1
  36. package/lib/core/index.js +0 -4
  37. package/lib/modules/Customer/index.d.ts +0 -1
  38. package/lib/modules/Customer/index.js +6 -21
  39. package/lib/plugins/app-types/app/app.d.ts +1 -0
  40. package/lib/server/index.d.ts +55 -5
  41. package/lib/server/index.js +350 -28
  42. package/lib/server/modules/index.d.ts +6 -0
  43. package/lib/server/modules/index.js +16 -2
  44. package/lib/server/modules/order/index.d.ts +87 -0
  45. package/lib/server/modules/order/index.js +543 -0
  46. package/lib/server/modules/order/types.d.ts +530 -0
  47. package/lib/server/modules/order/types.js +34 -0
  48. package/lib/server/modules/order/utils/filterBookings.d.ts +6 -0
  49. package/lib/server/modules/order/utils/filterBookings.js +320 -0
  50. package/lib/server/modules/order/utils/filterOrders.d.ts +15 -0
  51. package/lib/server/modules/order/utils/filterOrders.js +197 -0
  52. package/lib/server/modules/products/index.d.ts +24 -19
  53. package/lib/server/modules/products/index.js +150 -151
  54. package/lib/server/modules/products/types.d.ts +0 -1
  55. package/lib/server/modules/resource/index.d.ts +88 -0
  56. package/lib/server/modules/resource/index.js +571 -0
  57. package/lib/server/modules/resource/types.d.ts +121 -0
  58. package/lib/server/modules/resource/types.js +35 -0
  59. package/lib/server/utils/product.d.ts +0 -4
  60. package/lib/server/utils/product.js +0 -27
  61. package/lib/solution/BookingTicket/index.d.ts +1 -1
  62. package/lib/solution/Sales/index.d.ts +96 -0
  63. package/lib/solution/Sales/index.js +358 -0
  64. package/lib/solution/Sales/types.d.ts +65 -0
  65. package/lib/solution/Sales/types.js +35 -0
  66. package/lib/solution/index.d.ts +1 -0
  67. package/lib/solution/index.js +3 -1
  68. package/lib/types/index.d.ts +0 -2
  69. package/package.json +1 -1
@@ -177,7 +177,7 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
177
177
  duration: `${duration}ms`,
178
178
  error: errorMessage
179
179
  });
180
- return [];
180
+ throw error;
181
181
  }
182
182
  }
183
183
  /**
@@ -186,70 +186,13 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
186
186
  * 缓存的是已经应用了价格的完整商品列表,避免重复转换
187
187
  * @param schedule_date 日期
188
188
  * @param extraContext 额外的上下文数据(可选,由 Server 层传入)
189
- * @param options 可选参数
190
- * @param options.changedIds 变更的商品 IDs,非空时仅对这些商品增量执行 prepare 并更新缓存
191
189
  * @returns 应用了价格的商品列表
192
190
  */
193
- async getProductsWithPrice(schedule_date, extraContext, options) {
191
+ async getProductsWithPrice(schedule_date, extraContext) {
194
192
  const t0 = performance.now();
195
193
  const cacheKey = schedule_date;
196
- const changedIds = options == null ? void 0 : options.changedIds;
197
194
  if (this.productsPriceCache.has(cacheKey)) {
198
195
  const cachedProducts = this.productsPriceCache.get(cacheKey);
199
- if (changedIds && changedIds.length > 0) {
200
- this.logInfo("商品价格缓存命中,增量更新变更商品", {
201
- cacheKey,
202
- changedIds,
203
- cachedProductCount: cachedProducts.length
204
- });
205
- try {
206
- const updatedProducts = await this.prepareProductsWithPrice(
207
- schedule_date,
208
- extraContext,
209
- { productIds: changedIds }
210
- );
211
- if (updatedProducts.length > 0) {
212
- const updatedMap = new Map(updatedProducts.map((p) => [p.id, p]));
213
- const mergedCache = [];
214
- for (const p of cachedProducts) {
215
- if (updatedMap.has(p.id)) {
216
- mergedCache.push(updatedMap.get(p.id));
217
- updatedMap.delete(p.id);
218
- } else {
219
- mergedCache.push(p);
220
- }
221
- }
222
- for (const p of updatedMap.values()) {
223
- mergedCache.push(p);
224
- }
225
- this.productsPriceCache.set(cacheKey, mergedCache);
226
- this.logInfo("增量更新完成", {
227
- cacheKey,
228
- changedCount: updatedProducts.length,
229
- totalCount: mergedCache.length
230
- });
231
- (0, import_product.perfMark)("getProductsWithPrice(incrementalUpdate)", performance.now() - t0, {
232
- cacheKey,
233
- changedCount: changedIds.length,
234
- count: mergedCache.length
235
- });
236
- return mergedCache;
237
- }
238
- } catch (error) {
239
- const errorMessage = error instanceof Error ? error.message : String(error);
240
- this.logError("增量更新失败,返回现有缓存", {
241
- cacheKey,
242
- changedIds,
243
- error: errorMessage
244
- });
245
- }
246
- (0, import_product.perfMark)("getProductsWithPrice(incrementalUpdate)", performance.now() - t0, {
247
- cacheKey,
248
- changedCount: changedIds.length,
249
- count: cachedProducts.length
250
- });
251
- return cachedProducts;
252
- }
253
196
  (0, import_product.perfMark)("getProductsWithPrice(cacheHit)", performance.now() - t0, {
254
197
  cacheKey,
255
198
  count: cachedProducts.length
@@ -278,38 +221,21 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
278
221
  * 准备带价格的商品数据(通过格式化器流程处理)
279
222
  * @param schedule_date 日期
280
223
  * @param extraContext 额外的上下文数据(可选)
281
- * @param options 可选参数
282
- * @param options.productIds 指定商品 IDs,仅处理这些商品;不传则处理全量
283
- * @returns 处理后的商品列表
224
+ * @returns 完整处理后的商品列表
284
225
  * @private
285
226
  */
286
- async prepareProductsWithPrice(schedule_date, extraContext, options) {
287
- var _a, _b;
227
+ async prepareProductsWithPrice(schedule_date, extraContext) {
288
228
  const tTotal = performance.now();
289
- const targetIds = options == null ? void 0 : options.productIds;
290
- const isIncremental = targetIds && targetIds.length > 0;
291
- this.logInfo("prepareProductsWithPrice 开始处理", {
292
- schedule_date,
293
- mode: isIncremental ? "incremental" : "full",
294
- targetIdsCount: targetIds == null ? void 0 : targetIds.length
295
- });
229
+ this.logInfo("prepareProductsWithPrice 开始处理", { schedule_date });
296
230
  try {
297
- let products;
298
- let ids;
299
- if (isIncremental) {
300
- const idSet = new Set(targetIds);
301
- products = this.getProductsRef().filter((p) => idSet.has(p.id));
302
- ids = products.map((p) => p.id);
303
- } else {
304
- products = this.getProductsRef();
305
- const tIds = performance.now();
306
- ids = new Array(products.length);
307
- for (let i = 0; i < products.length; i++) {
308
- ids[i] = products[i].id;
309
- }
310
- (0, import_product.perfMark)("prepareProducts.extractIds", performance.now() - tIds, { count: ids.length });
231
+ const allProducts = this.getProductsRef();
232
+ this.logInfo("获取到商品列表", { productCount: allProducts.length });
233
+ const tIds = performance.now();
234
+ const ids = new Array(allProducts.length);
235
+ for (let i = 0; i < allProducts.length; i++) {
236
+ ids[i] = allProducts[i].id;
311
237
  }
312
- this.logInfo("获取到商品列表", { productCount: products.length });
238
+ (0, import_product.perfMark)("prepareProducts.extractIds", performance.now() - tIds, { count: ids.length });
313
239
  const tPrice = performance.now();
314
240
  const priceData = await this.loadProductsPrice({
315
241
  ids,
@@ -320,31 +246,26 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
320
246
  const context = {
321
247
  schedule_date,
322
248
  priceData,
323
- locale: (_b = (_a = this.core) == null ? void 0 : _a.context) == null ? void 0 : _b.locale,
324
249
  ...extraContext
325
250
  };
326
251
  const tFormat = performance.now();
327
- const processedProducts = await this.applyFormatters(products, context);
252
+ const processedProducts = await this.applyFormatters(allProducts, context);
328
253
  (0, import_product.perfMark)("prepareProducts.applyFormatters", performance.now() - tFormat, {
329
- count: products.length,
254
+ count: allProducts.length,
330
255
  formatterCount: this.formatters.length
331
256
  });
332
257
  this.logInfo("prepareProductsWithPrice 处理完成", {
333
- mode: isIncremental ? "incremental" : "full",
334
- originalProductCount: products.length,
258
+ originalProductCount: allProducts.length,
335
259
  processedProductCount: processedProducts.length,
336
260
  formatterCount: this.formatters.length
337
261
  });
338
- if (!isIncremental) {
339
- await this.core.effects.emit(
340
- import_types.ProductsHooks.onProductsPriceApplied,
341
- processedProducts
342
- );
343
- }
262
+ await this.core.effects.emit(
263
+ import_types.ProductsHooks.onProductsPriceApplied,
264
+ processedProducts
265
+ );
344
266
  (0, import_product.perfMark)("prepareProductsWithPrice", performance.now() - tTotal, {
345
- productCount: products.length,
346
- formatterCount: this.formatters.length,
347
- mode: isIncremental ? "incremental" : "full"
267
+ productCount: allProducts.length,
268
+ formatterCount: this.formatters.length
348
269
  });
349
270
  return processedProducts;
350
271
  } catch (err) {
@@ -419,14 +340,10 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
419
340
  console.log(`[ProductsModule] 💰 应用价格数据到 ${products.length} 个商品`);
420
341
  return (0, import_product.applyPriceDataToProducts)(products, context.priceData);
421
342
  };
422
- const i18nFormatter = (products, context) => {
423
- return (0, import_product.applyI18nToProducts)(products, context.locale);
424
- };
425
343
  const detailValueFormatter = (products, context) => {
426
344
  return (0, import_product.applyDetailValueToProducts)(products, context);
427
345
  };
428
346
  this.formatters.unshift(priceFormatter);
429
- this.formatters.push(i18nFormatter);
430
347
  this.formatters.push(detailValueFormatter);
431
348
  this.isPriceFormatterRegistered = true;
432
349
  console.log("[ProductsModule] ✅ 内置价格格式化器已注册(第 1 个)");
@@ -687,6 +604,29 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
687
604
  (0, import_product.perfMark)("refreshProducts", performance.now() - tTotal, { count: this.store.list.length });
688
605
  return this.store.list;
689
606
  }
607
+ /**
608
+ * 局部更新指定商品的报价单价格
609
+ * 遍历所有已缓存的日期,为目标商品重新获取价格并覆盖到缓存中
610
+ */
611
+ async updateProductPriceByIds(ids) {
612
+ this.logInfo("updateProductPriceByIds", { ids });
613
+ for (const [dateKey, cachedProducts] of this.productsPriceCache.entries()) {
614
+ try {
615
+ const priceData = await this.loadProductsPrice({
616
+ ids,
617
+ schedule_date: dateKey
618
+ });
619
+ if (priceData && priceData.length > 0) {
620
+ const updatedProducts = (0, import_product.applyPriceDataToProducts)(cachedProducts, priceData);
621
+ this.productsPriceCache.set(dateKey, updatedProducts);
622
+ this.logInfo("updateProductPriceByIds: 缓存已更新", { dateKey, priceDataCount: priceData.length });
623
+ }
624
+ } catch (error) {
625
+ const errorMessage = error instanceof Error ? error.message : String(error);
626
+ this.logError("updateProductPriceByIds: 失败", { dateKey, ids, error: errorMessage });
627
+ }
628
+ }
629
+ }
690
630
  /**
691
631
  * 清空缓存
692
632
  */
@@ -748,7 +688,7 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
748
688
  try {
749
689
  const t0 = performance.now();
750
690
  await this.dbManager.clear(INDEXDB_STORE_NAME);
751
- await this.dbManager.bulkUpdate(INDEXDB_STORE_NAME, products);
691
+ await this.dbManager.bulkAdd(INDEXDB_STORE_NAME, products);
752
692
  (0, import_product.perfMark)("saveProductsToIndexDB", performance.now() - t0, { count: products.length });
753
693
  console.log(
754
694
  `[Products] 已将 ${products.length} 个商品平铺保存到 IndexDB`
@@ -913,21 +853,18 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
913
853
  *
914
854
  * product 模块:
915
855
  * - operation === 'delete' → 本地删除
916
- * - change_types 包含 price → 仅收集变更 IDs(不拉商品数据)
917
- * - bodybody 完整数据直接覆盖本地
918
- * - 其他SSE 增量拉取
856
+ * - body(无 price change_types) body 完整数据直接覆盖本地
857
+ * - change_types 包含 price SSE 增量拉取 + 刷新报价单价格缓存
858
+ * - change_types 仅 stock 跳过(暂不响应)
919
859
  *
920
- * product_collection / product_category:
860
+ * product_collection / product_category / product_quotation
921
861
  * - 按 relation_product_ids SSE 拉取受影响商品
862
+ * - product_quotation 额外刷新报价单价格缓存
922
863
  *
923
- * product_quotation:
924
- * - 报价单变更影响范围大,直接清除价格缓存走全量重建
925
- *
926
- * 处理完成后 emit onProductsSyncCompleted(携带 changedIds),
927
- * Server 层监听该事件后对变更商品增量执行 prepareProductsWithPrice 并更新缓存
864
+ * 处理完成后 emit onProductsSyncCompleted 通知 Server 层
928
865
  */
929
866
  async processProductSyncMessages() {
930
- var _a, _b, _c, _d, _e, _f;
867
+ var _a, _b, _c, _d, _e;
931
868
  const messages = [...this.pendingSyncMessages];
932
869
  this.pendingSyncMessages = [];
933
870
  if (messages.length === 0)
@@ -937,28 +874,24 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
937
874
  const bodyUpdates = /* @__PURE__ */ new Map();
938
875
  const sseRefreshIds = [];
939
876
  const priceRefreshIds = [];
940
- let shouldClearPriceCache = false;
941
877
  for (const msg of messages) {
942
878
  const channelKey = msg._channelKey || msg.module || "product";
943
879
  if (channelKey === "product") {
944
- if ((_a = msg.relation_product_ids) == null ? void 0 : _a.length) {
945
- sseRefreshIds.push(...msg.relation_product_ids);
946
- }
947
880
  if (msg.operation === "delete" || msg.action === "delete") {
948
- if ((_b = msg.ids) == null ? void 0 : _b.length)
881
+ if ((_a = msg.ids) == null ? void 0 : _a.length)
949
882
  deleteIds.push(...msg.ids);
950
883
  else if (msg.id)
951
884
  deleteIds.push(msg.id);
952
885
  continue;
953
886
  }
887
+ if (((_b = msg.change_types) == null ? void 0 : _b.length) && msg.change_types.every((t) => t === "stock")) {
888
+ this.logInfo("跳过仅库存变更", { ids: msg.ids });
889
+ continue;
890
+ }
954
891
  if ((_c = msg.change_types) == null ? void 0 : _c.includes("price")) {
955
892
  const ids = msg.ids || (msg.id ? [msg.id] : []);
893
+ sseRefreshIds.push(...ids);
956
894
  priceRefreshIds.push(...ids);
957
- if (msg.body) {
958
- const bodyId = msg.body.id;
959
- if (bodyId)
960
- bodyUpdates.set(bodyId, msg.body);
961
- }
962
895
  continue;
963
896
  }
964
897
  if (msg.body) {
@@ -972,14 +905,13 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
972
905
  } else if (msg.id) {
973
906
  sseRefreshIds.push(msg.id);
974
907
  }
975
- } else if (channelKey === "product_quotation") {
976
- shouldClearPriceCache = true;
908
+ } else if (["product_collection", "product_category", "product_quotation"].includes(channelKey)) {
977
909
  if ((_e = msg.relation_product_ids) == null ? void 0 : _e.length) {
978
910
  sseRefreshIds.push(...msg.relation_product_ids);
979
- }
980
- } else if (["product_collection", "product_category"].includes(channelKey)) {
981
- if ((_f = msg.relation_product_ids) == null ? void 0 : _f.length) {
982
- sseRefreshIds.push(...msg.relation_product_ids);
911
+ if (channelKey === "product_quotation") {
912
+ this.clearPriceCache();
913
+ priceRefreshIds.push(...msg.relation_product_ids);
914
+ }
983
915
  }
984
916
  }
985
917
  }
@@ -996,36 +928,29 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
996
928
  const freshProducts = await this.fetchProductsBySSE(uniqueSSEIds);
997
929
  if (freshProducts.length > 0) {
998
930
  await this.mergeProductsToStore(freshProducts);
931
+ await this.updatePriceCacheForProducts(freshProducts);
999
932
  }
1000
- this.logInfo("processProductSyncMessages: SSE 增量更新完成123", {
933
+ this.logInfo("processProductSyncMessages: SSE 增量更新完成", {
1001
934
  requestedCount: uniqueSSEIds.length,
1002
935
  receivedCount: freshProducts.length
1003
936
  });
1004
937
  }
1005
- const allChangedIds = [.../* @__PURE__ */ new Set([
1006
- ...Array.from(bodyUpdates.keys()),
1007
- ...uniqueSSEIds,
1008
- ...uniquePriceIds
1009
- ])];
1010
- this.logInfo("processProductSyncMessages: 处理完成123", {
938
+ const sseHandledSet = new Set(uniqueSSEIds);
939
+ const remainingPriceIds = uniquePriceIds.filter((id) => !sseHandledSet.has(id));
940
+ if (remainingPriceIds.length > 0) {
941
+ await this.updateProductPriceByIds(remainingPriceIds);
942
+ }
943
+ this.logInfo("processProductSyncMessages: 处理完成", {
1011
944
  deleteCount: uniqueDeleteIds.length,
1012
945
  bodyUpdateCount: bodyUpdates.size,
1013
946
  sseRefreshCount: uniqueSSEIds.length,
1014
- priceRefreshCount: uniquePriceIds.length,
1015
- allChangedIdsCount: allChangedIds.length,
1016
- shouldClearPriceCache
947
+ priceRefreshCount: uniquePriceIds.length
1017
948
  });
1018
- const hasChanges = uniqueDeleteIds.length > 0 || allChangedIds.length > 0 || shouldClearPriceCache;
1019
- if (!hasChanges) {
949
+ if (uniqueDeleteIds.length === 0 && bodyUpdates.size === 0 && uniqueSSEIds.length === 0 && uniquePriceIds.length === 0) {
1020
950
  this.logInfo("processProductSyncMessages: 没有变更,不触发 onProductsSyncCompleted");
1021
951
  return;
1022
952
  }
1023
- if (shouldClearPriceCache) {
1024
- this.clearPriceCache();
1025
- }
1026
- await this.core.effects.emit(import_types.ProductsHooks.onProductsSyncCompleted, {
1027
- changedIds: allChangedIds
1028
- });
953
+ await this.core.effects.emit(import_types.ProductsHooks.onProductsSyncCompleted, null);
1029
954
  }
1030
955
  /**
1031
956
  * 通过 SSE 按 ids 增量拉取商品数据
@@ -1059,8 +984,7 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
1059
984
  /**
1060
985
  * 将 body 完整数据直接覆盖到本地 store(不调用报价单接口)
1061
986
  * 已存在的 → 直接替换;不存在的 → 追加
1062
- * 同时更新 Map 缓存、IndexDB,触发 onProductsChanged
1063
- * 价格缓存由 processProductSyncMessages 末尾统一清除
987
+ * 同时更新 Map 缓存、IndexDB,清空价格缓存,触发 onProductsChanged
1064
988
  */
1065
989
  async applyBodyUpdatesToStore(bodyUpdates) {
1066
990
  this.logInfo("applyBodyUpdatesToStore: 开始", { count: bodyUpdates.size });
@@ -1083,6 +1007,7 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
1083
1007
  }
1084
1008
  this.syncProductsMap();
1085
1009
  await this.saveProductsToIndexDB(this.store.list);
1010
+ await this.updatePriceCacheForProducts([...bodyUpdates.values()]);
1086
1011
  this.core.effects.emit(import_types.ProductsHooks.onProductsChanged, this.store.list);
1087
1012
  this.logInfo("applyBodyUpdatesToStore: 完成", {
1088
1013
  updatedCount,
@@ -1123,6 +1048,80 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
1123
1048
  });
1124
1049
  this.core.effects.emit(import_types.ProductsHooks.onProductsChanged, this.store.list);
1125
1050
  }
1051
+ /**
1052
+ * 增量更新价格缓存中变更的商品
1053
+ * 对每个已缓存的日期 key:替换/追加最新商品数据,重新拉取这些 ID 的价格并应用
1054
+ */
1055
+ async updatePriceCacheForProducts(freshProducts) {
1056
+ if (this.productsPriceCache.size === 0)
1057
+ return;
1058
+ const freshIds = freshProducts.map((p) => p.id);
1059
+ const freshMap = /* @__PURE__ */ new Map();
1060
+ for (const p of freshProducts) {
1061
+ freshMap.set(p.id, p);
1062
+ }
1063
+ this.logInfo("updatePriceCacheForProducts: 开始", {
1064
+ freshIds,
1065
+ cachedDateCount: this.productsPriceCache.size
1066
+ });
1067
+ for (const [dateKey, cachedProducts] of this.productsPriceCache.entries()) {
1068
+ try {
1069
+ const updatedList = cachedProducts.map((p) => {
1070
+ const fresh = freshMap.get(p.id);
1071
+ return fresh ? { ...fresh } : p;
1072
+ });
1073
+ const existingIds = new Set(cachedProducts.map((p) => p.id));
1074
+ for (const p of freshProducts) {
1075
+ if (!existingIds.has(p.id)) {
1076
+ updatedList.push({ ...p });
1077
+ }
1078
+ }
1079
+ const priceData = await this.loadProductsPrice({
1080
+ ids: freshIds,
1081
+ schedule_date: dateKey
1082
+ });
1083
+ const result = priceData && priceData.length > 0 ? (0, import_product.applyPriceDataToProducts)(updatedList, priceData) : updatedList;
1084
+ this.productsPriceCache.set(dateKey, result);
1085
+ this.logInfo("updatePriceCacheForProducts: 日期缓存已更新", {
1086
+ dateKey,
1087
+ updatedIds: freshIds
1088
+ });
1089
+ } catch (error) {
1090
+ const errorMessage = error instanceof Error ? error.message : String(error);
1091
+ this.logError("updatePriceCacheForProducts: 失败", { dateKey, error: errorMessage });
1092
+ }
1093
+ }
1094
+ }
1095
+ /**
1096
+ * 全量重新拉取报价单价格并重建价格缓存
1097
+ * 遍历当前已缓存的所有日期 key,对每个日期重新调用 loadProductsPrice
1098
+ */
1099
+ async refreshAllPriceCache() {
1100
+ const allProducts = this.getProductsRef();
1101
+ if (allProducts.length === 0)
1102
+ return;
1103
+ const ids = allProducts.map((p) => p.id);
1104
+ const dateKeys = Array.from(this.productsPriceCache.keys());
1105
+ this.clearPriceCache();
1106
+ if (dateKeys.length === 0) {
1107
+ this.logInfo("refreshAllPriceCache: 无已缓存日期,跳过");
1108
+ return;
1109
+ }
1110
+ this.logInfo("refreshAllPriceCache: 开始重新拉取", { dateKeys, productCount: ids.length });
1111
+ for (const dateKey of dateKeys) {
1112
+ try {
1113
+ const priceData = await this.loadProductsPrice({ ids, schedule_date: dateKey });
1114
+ if (priceData && priceData.length > 0) {
1115
+ const updatedProducts = (0, import_product.applyPriceDataToProducts)(allProducts, priceData);
1116
+ this.productsPriceCache.set(dateKey, updatedProducts);
1117
+ }
1118
+ this.logInfo("refreshAllPriceCache: 日期缓存已更新", { dateKey });
1119
+ } catch (error) {
1120
+ const errorMessage = error instanceof Error ? error.message : String(error);
1121
+ this.logError("refreshAllPriceCache: 失败", { dateKey, error: errorMessage });
1122
+ }
1123
+ }
1124
+ }
1126
1125
  /**
1127
1126
  * 静默全量刷新:后台重新拉取全量 SSE 数据并更新本地
1128
1127
  * 拿到完整数据后一次性替换 store,清除价格缓存,触发 onProductsSyncCompleted
@@ -109,7 +109,6 @@ export interface ProductFormatterContext {
109
109
  schedule_date: string;
110
110
  priceData?: LoadProductsPriceData[];
111
111
  scheduleModule?: any;
112
- locale?: string;
113
112
  }
114
113
  /**
115
114
  * 商品格式化器类型
@@ -0,0 +1,88 @@
1
+ import { Module, ModuleOptions, PisellCore } from '../../../types';
2
+ import { BaseModule } from '../../../modules/BaseModule';
3
+ import { type ResourceBooking, type ResourceData, type ResourceId, type QueryOptions } from './types';
4
+ /**
5
+ * Resource 模块
6
+ */
7
+ export declare class ResourceModule extends BaseModule implements Module {
8
+ protected defaultName: string;
9
+ protected defaultVersion: string;
10
+ private store;
11
+ private dbManager;
12
+ private logger;
13
+ private resourceDataSource;
14
+ /** 倒排索引: resourceId -> ResourceBooking[] */
15
+ private resourceIdIndex;
16
+ /** 待处理的同步消息队列 */
17
+ private pendingSyncMessages;
18
+ private syncTimer?;
19
+ constructor(name?: string, version?: string);
20
+ initialize(core: PisellCore, options?: ModuleOptions): Promise<void>;
21
+ private logInfo;
22
+ private logError;
23
+ preload(): Promise<void>;
24
+ getRoutes(): never[];
25
+ destroy(): void;
26
+ /**
27
+ * 获取所有资源(支持 includeBookings 附加预订信息)
28
+ */
29
+ getResources(queryOptions?: QueryOptions): ResourceData[];
30
+ /**
31
+ * 根据 ID 获取单个资源
32
+ */
33
+ getResourceById(id: ResourceId, queryOptions?: QueryOptions): ResourceData | undefined;
34
+ /**
35
+ * 创建资源
36
+ */
37
+ createResource(data: Partial<ResourceData>): ResourceData;
38
+ /**
39
+ * 更新资源
40
+ */
41
+ updateResource(id: ResourceId, data: Partial<ResourceData>): ResourceData | undefined;
42
+ /**
43
+ * 删除资源
44
+ */
45
+ deleteResource(id: ResourceId): boolean;
46
+ /**
47
+ * 根据资源 ID 获取预订列表
48
+ */
49
+ getBookingsByResourceId(resourceId: ResourceId): ResourceBooking[];
50
+ /**
51
+ * 创建预订
52
+ */
53
+ createBooking(booking: Partial<ResourceBooking>): ResourceBooking;
54
+ /**
55
+ * 更新预订
56
+ */
57
+ updateBooking(id: ResourceId, data: Partial<ResourceBooking>): ResourceBooking | undefined;
58
+ /**
59
+ * 删除预订
60
+ */
61
+ deleteBooking(id: ResourceId): boolean;
62
+ /**
63
+ * 清空缓存
64
+ */
65
+ clear(): Promise<void>;
66
+ private attachBookingsToResource;
67
+ private normalizeResource;
68
+ private safeEmit;
69
+ private syncResourcesMap;
70
+ private syncBookingsIndex;
71
+ private rebuildBookingsIndex;
72
+ private getIdKey;
73
+ private loadResourcesByServer;
74
+ private loadResourcesFromSQLite;
75
+ private saveResourcesToSQLite;
76
+ private loadBookingsFromSQLite;
77
+ private saveBookingsToSQLite;
78
+ private initResourceDataSource;
79
+ private setupResourceSync;
80
+ private processSyncMessages;
81
+ private fetchResourcesBySSE;
82
+ private removeResourcesByIds;
83
+ private mergeResourcesToStore;
84
+ private uniqueResourceIds;
85
+ }
86
+ export declare const resourceModule: ResourceModule;
87
+ export type { ResourceData, ResourceBooking, ResourceState, ResourceId, ResourcePageQuery, ResourcePageResult, QueryOptions, ScheduleEventResource, } from './types';
88
+ export { ResourceHooks } from './types';