@pisell/pisellos 2.2.80 → 2.2.82
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.
- package/dist/core/index.d.ts +2 -2
- package/dist/modules/ProductList/index.d.ts +0 -3
- package/dist/modules/ProductList/index.js +7 -9
- package/dist/plugins/request.d.ts +0 -2
- package/dist/server/index.d.ts +2 -27
- package/dist/server/index.js +295 -499
- package/dist/server/modules/products/index.d.ts +3 -101
- package/dist/server/modules/products/index.js +242 -1381
- package/dist/server/modules/products/types.d.ts +1 -24
- package/dist/server/modules/products/types.js +0 -3
- package/dist/server/utils/product.d.ts +0 -1
- package/dist/server/utils/product.js +25 -35
- package/dist/solution/BookingTicket/index.d.ts +2 -10
- package/dist/solution/BookingTicket/index.js +28 -41
- package/dist/types/index.d.ts +0 -3
- package/lib/core/index.d.ts +2 -2
- package/lib/modules/ProductList/index.d.ts +0 -3
- package/lib/modules/ProductList/index.js +2 -2
- package/lib/plugins/request.d.ts +0 -2
- package/lib/server/index.d.ts +2 -27
- package/lib/server/index.js +95 -172
- package/lib/server/modules/products/index.d.ts +3 -101
- package/lib/server/modules/products/index.js +52 -596
- package/lib/server/modules/products/types.d.ts +1 -24
- package/lib/server/modules/products/types.js +0 -1
- package/lib/server/utils/product.d.ts +0 -1
- package/lib/server/utils/product.js +11 -27
- package/lib/solution/BookingTicket/index.d.ts +2 -10
- package/lib/solution/BookingTicket/index.js +2 -10
- package/lib/types/index.d.ts +0 -3
- package/package.json +1 -1
|
@@ -23,11 +23,11 @@ __export(products_exports, {
|
|
|
23
23
|
});
|
|
24
24
|
module.exports = __toCommonJS(products_exports);
|
|
25
25
|
var import_BaseModule = require("../../../modules/BaseModule");
|
|
26
|
+
var import_lodash_es = require("lodash-es");
|
|
26
27
|
var import_plugins = require("../../../plugins");
|
|
27
28
|
var import_types = require("./types");
|
|
28
29
|
var import_product = require("../../utils/product");
|
|
29
30
|
var INDEXDB_STORE_NAME = "products";
|
|
30
|
-
var PRODUCT_SYNC_DEBOUNCE_MS = 1e4;
|
|
31
31
|
var ProductsModule = class extends import_BaseModule.BaseModule {
|
|
32
32
|
constructor(name, version) {
|
|
33
33
|
super(name, version);
|
|
@@ -44,7 +44,6 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
|
|
|
44
44
|
this.formatters = [];
|
|
45
45
|
// 是否已注册内置价格格式化器
|
|
46
46
|
this.isPriceFormatterRegistered = false;
|
|
47
|
-
this.pendingSyncMessages = [];
|
|
48
47
|
}
|
|
49
48
|
async initialize(core, options) {
|
|
50
49
|
var _a;
|
|
@@ -72,8 +71,6 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
|
|
|
72
71
|
}
|
|
73
72
|
}
|
|
74
73
|
this.registerBuiltinPriceFormatter();
|
|
75
|
-
this.initProductDataSource();
|
|
76
|
-
this.setupProductSync();
|
|
77
74
|
this.logInfo("模块初始化完成", {
|
|
78
75
|
hasDbManager: !!this.dbManager,
|
|
79
76
|
hasLogger: !!this.logger,
|
|
@@ -189,32 +186,29 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
|
|
|
189
186
|
* @returns 应用了价格的商品列表
|
|
190
187
|
*/
|
|
191
188
|
async getProductsWithPrice(schedule_date, extraContext) {
|
|
192
|
-
const t0 = performance.now();
|
|
193
189
|
const cacheKey = schedule_date;
|
|
194
190
|
if (this.productsPriceCache.has(cacheKey)) {
|
|
191
|
+
console.log(`[ProductsModule] 💰 商品价格缓存命中: ${cacheKey}`);
|
|
195
192
|
const cachedProducts = this.productsPriceCache.get(cacheKey);
|
|
196
|
-
(0, import_product.perfMark)("getProductsWithPrice(cacheHit)", performance.now() - t0, {
|
|
197
|
-
cacheKey,
|
|
198
|
-
count: cachedProducts.length
|
|
199
|
-
});
|
|
200
193
|
this.logInfo("商品价格缓存命中", {
|
|
201
194
|
cacheKey,
|
|
202
195
|
productCount: cachedProducts.length
|
|
203
196
|
});
|
|
204
197
|
return cachedProducts;
|
|
205
198
|
}
|
|
199
|
+
console.log(`[ProductsModule] 🌐 获取商品并应用价格: ${cacheKey}`);
|
|
206
200
|
this.logInfo("商品价格缓存未命中,准备获取", { cacheKey });
|
|
201
|
+
const startTime = Date.now();
|
|
207
202
|
const result = await this.prepareProductsWithPrice(schedule_date, extraContext);
|
|
203
|
+
const duration = Date.now() - startTime;
|
|
208
204
|
this.productsPriceCache.set(cacheKey, result);
|
|
205
|
+
console.log(`[ProductsModule] ✅ 商品价格已缓存: ${cacheKey}, 共 ${result.length} 个商品`);
|
|
209
206
|
this.logInfo("商品价格已缓存", {
|
|
210
207
|
cacheKey,
|
|
211
|
-
productCount: result.length
|
|
208
|
+
productCount: result.length,
|
|
209
|
+
duration: `${duration}ms`
|
|
212
210
|
});
|
|
213
211
|
this.cleanExpiredPriceCache();
|
|
214
|
-
(0, import_product.perfMark)("getProductsWithPrice(cacheMiss)", performance.now() - t0, {
|
|
215
|
-
cacheKey,
|
|
216
|
-
count: result.length
|
|
217
|
-
});
|
|
218
212
|
return result;
|
|
219
213
|
}
|
|
220
214
|
/**
|
|
@@ -225,35 +219,27 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
|
|
|
225
219
|
* @private
|
|
226
220
|
*/
|
|
227
221
|
async prepareProductsWithPrice(schedule_date, extraContext) {
|
|
228
|
-
const tTotal = performance.now();
|
|
229
222
|
this.logInfo("prepareProductsWithPrice 开始处理", { schedule_date });
|
|
230
223
|
try {
|
|
231
|
-
const allProducts = this.
|
|
224
|
+
const allProducts = await this.getProducts();
|
|
232
225
|
this.logInfo("获取到商品列表", { productCount: allProducts.length });
|
|
233
|
-
|
|
234
|
-
const ids = new Array(allProducts.length);
|
|
235
|
-
for (let i = 0; i < allProducts.length; i++) {
|
|
236
|
-
ids[i] = allProducts[i].id;
|
|
237
|
-
}
|
|
238
|
-
(0, import_product.perfMark)("prepareProducts.extractIds", performance.now() - tIds, { count: ids.length });
|
|
239
|
-
const tPrice = performance.now();
|
|
226
|
+
console.log(`[ProductsModule] 🌐 开始获取商品报价单价格`);
|
|
240
227
|
const priceData = await this.loadProductsPrice({
|
|
241
|
-
ids,
|
|
228
|
+
ids: allProducts.map((product) => product.id).sort((a, b) => a - b),
|
|
242
229
|
schedule_date
|
|
243
230
|
});
|
|
244
|
-
|
|
231
|
+
console.log(`[ProductsModule] 🌐 获取商品报价单价格成功`, priceData);
|
|
245
232
|
this.logInfo("获取商品报价单价格成功", { priceDataCount: (priceData == null ? void 0 : priceData.length) ?? 0 });
|
|
246
233
|
const context = {
|
|
247
234
|
schedule_date,
|
|
248
235
|
priceData,
|
|
249
236
|
...extraContext
|
|
237
|
+
// 合并 Server 层传入的额外数据(如 scheduleList)
|
|
250
238
|
};
|
|
251
|
-
|
|
239
|
+
console.log(`[ProductsModule] 🌐 通过格式化器流程处理商品(包括价格应用、字段扩展等)`);
|
|
240
|
+
this.logInfo("开始通过格式化器流程处理商品", { formatterCount: this.formatters.length });
|
|
252
241
|
const processedProducts = await this.applyFormatters(allProducts, context);
|
|
253
|
-
|
|
254
|
-
count: allProducts.length,
|
|
255
|
-
formatterCount: this.formatters.length
|
|
256
|
-
});
|
|
242
|
+
console.log(`[ProductsModule] 🌐 通过格式化器流程处理商品(包括价格应用、字段扩展等)成功`, processedProducts);
|
|
257
243
|
this.logInfo("prepareProductsWithPrice 处理完成", {
|
|
258
244
|
originalProductCount: allProducts.length,
|
|
259
245
|
processedProductCount: processedProducts.length,
|
|
@@ -263,10 +249,6 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
|
|
|
263
249
|
import_types.ProductsHooks.onProductsPriceApplied,
|
|
264
250
|
processedProducts
|
|
265
251
|
);
|
|
266
|
-
(0, import_product.perfMark)("prepareProductsWithPrice", performance.now() - tTotal, {
|
|
267
|
-
productCount: allProducts.length,
|
|
268
|
-
formatterCount: this.formatters.length
|
|
269
|
-
});
|
|
270
252
|
return processedProducts;
|
|
271
253
|
} catch (err) {
|
|
272
254
|
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
@@ -299,13 +281,8 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
|
|
|
299
281
|
for (let i = 0; i < this.formatters.length; i++) {
|
|
300
282
|
const formatter = this.formatters[i];
|
|
301
283
|
try {
|
|
302
|
-
|
|
284
|
+
console.log(`[ProductsModule] 📝 应用格式化器 ${i + 1}/${this.formatters.length}`);
|
|
303
285
|
result = await formatter(result, context);
|
|
304
|
-
(0, import_product.perfMark)(`applyFormatters[${i}]`, performance.now() - tF, {
|
|
305
|
-
index: i,
|
|
306
|
-
total: this.formatters.length,
|
|
307
|
-
productCount: result.length
|
|
308
|
-
});
|
|
309
286
|
} catch (error) {
|
|
310
287
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
311
288
|
console.error(`[ProductsModule] ❌ 格式化器 ${i + 1} 执行失败:`, error);
|
|
@@ -316,6 +293,7 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
|
|
|
316
293
|
});
|
|
317
294
|
}
|
|
318
295
|
}
|
|
296
|
+
console.log(`[ProductsModule] ✅ 所有格式化器已应用,共 ${this.formatters.length} 个`);
|
|
319
297
|
this.logInfo("所有格式化器已应用", {
|
|
320
298
|
formatterCount: this.formatters.length,
|
|
321
299
|
resultProductCount: result.length
|
|
@@ -409,45 +387,10 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
|
|
|
409
387
|
console.log("[ProductsModule] 🗑️ 商品价格缓存已清空");
|
|
410
388
|
}
|
|
411
389
|
/**
|
|
412
|
-
*
|
|
413
|
-
*/
|
|
414
|
-
async loadProductsByServer() {
|
|
415
|
-
if (!this.productDataSource) {
|
|
416
|
-
this.logWarning("loadProductsByServer: ProductDataSource 不可用");
|
|
417
|
-
return [];
|
|
418
|
-
}
|
|
419
|
-
this.logInfo("开始通过 DataSource SSE 加载商品列表");
|
|
420
|
-
const t0 = performance.now();
|
|
421
|
-
try {
|
|
422
|
-
const tSSE = performance.now();
|
|
423
|
-
const productList = await this.productDataSource.run({ sse: {} });
|
|
424
|
-
const list = productList || [];
|
|
425
|
-
(0, import_product.perfMark)("loadProductsByServer.SSE", performance.now() - tSSE, { count: list.length });
|
|
426
|
-
this.logInfo("通过 DataSource SSE 加载商品列表成功", {
|
|
427
|
-
productCount: list.length,
|
|
428
|
-
duration: `${Math.round(performance.now() - t0)}ms`
|
|
429
|
-
});
|
|
430
|
-
await this.saveProductsToIndexDB(list);
|
|
431
|
-
await this.core.effects.emit(import_types.ProductsHooks.onProductsLoaded, list);
|
|
432
|
-
(0, import_product.perfMark)("loadProductsByServer", performance.now() - t0, { count: list.length });
|
|
433
|
-
return list;
|
|
434
|
-
} catch (error) {
|
|
435
|
-
const duration = Math.round(performance.now() - t0);
|
|
436
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
437
|
-
console.error("[Products] 加载商品数据失败:", error);
|
|
438
|
-
this.logError("通过 DataSource SSE 加载商品列表失败", {
|
|
439
|
-
duration: `${duration}ms`,
|
|
440
|
-
error: errorMessage
|
|
441
|
-
});
|
|
442
|
-
return [];
|
|
443
|
-
}
|
|
444
|
-
}
|
|
445
|
-
/**
|
|
446
|
-
* 纯请求方法:通过 HTTP 接口获取商品列表(无副作用,不触发事件、不写 IndexDB)
|
|
390
|
+
* 加载完整商品列表通过接口(包含所有详细数据)
|
|
447
391
|
* @param params 查询参数
|
|
448
|
-
* @returns 商品列表
|
|
449
392
|
*/
|
|
450
|
-
async
|
|
393
|
+
async loadProductsByServer(params) {
|
|
451
394
|
var _a, _b;
|
|
452
395
|
const {
|
|
453
396
|
category_ids = [],
|
|
@@ -456,7 +399,7 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
|
|
|
456
399
|
customer_id,
|
|
457
400
|
cacheId
|
|
458
401
|
} = params || {};
|
|
459
|
-
this.logInfo("
|
|
402
|
+
this.logInfo("开始从服务器加载商品列表", {
|
|
460
403
|
categoryIdsCount: category_ids.length,
|
|
461
404
|
productIdsCount: product_ids.length,
|
|
462
405
|
collectionCount: Array.isArray(collection) ? collection.length : collection ? 1 : 0,
|
|
@@ -477,12 +420,16 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
|
|
|
477
420
|
"event_item"
|
|
478
421
|
],
|
|
479
422
|
force_ignore_cache_flag: 1,
|
|
423
|
+
// 获取所有详细信息
|
|
480
424
|
with: [
|
|
481
425
|
"category",
|
|
482
426
|
"collection",
|
|
483
427
|
"resourceRelation",
|
|
428
|
+
// 套餐
|
|
484
429
|
"bundleGroup.bundleItem",
|
|
430
|
+
// 单规格
|
|
485
431
|
"optionGroup.optionItem",
|
|
432
|
+
// 组合规格
|
|
486
433
|
"variantGroup.variantItem"
|
|
487
434
|
],
|
|
488
435
|
open_deposit: 1,
|
|
@@ -502,16 +449,21 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
|
|
|
502
449
|
);
|
|
503
450
|
const productList = ((_b = productsData == null ? void 0 : productsData.data) == null ? void 0 : _b.list) || [];
|
|
504
451
|
const duration = Date.now() - startTime;
|
|
505
|
-
this.logInfo("
|
|
452
|
+
this.logInfo("从服务器加载商品列表成功", {
|
|
506
453
|
productCount: productList.length,
|
|
507
454
|
duration: `${duration}ms`
|
|
508
455
|
});
|
|
509
|
-
|
|
456
|
+
await this.saveProductsToIndexDB(productList);
|
|
457
|
+
await this.core.effects.emit(
|
|
458
|
+
import_types.ProductsHooks.onProductsLoaded,
|
|
459
|
+
productsData.data.list
|
|
460
|
+
);
|
|
461
|
+
return productsData.data.list;
|
|
510
462
|
} catch (error) {
|
|
511
463
|
const duration = Date.now() - startTime;
|
|
512
464
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
513
|
-
console.error("[Products]
|
|
514
|
-
this.logError("
|
|
465
|
+
console.error("[Products] 加载商品数据失败:", error);
|
|
466
|
+
this.logError("从服务器加载商品列表失败", {
|
|
515
467
|
duration: `${duration}ms`,
|
|
516
468
|
error: errorMessage
|
|
517
469
|
});
|
|
@@ -519,33 +471,10 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
|
|
|
519
471
|
}
|
|
520
472
|
}
|
|
521
473
|
/**
|
|
522
|
-
*
|
|
523
|
-
* 包含副作用:保存到 IndexDB + 触发 onProductsLoaded 事件
|
|
524
|
-
* @param params 查询参数
|
|
525
|
-
*/
|
|
526
|
-
async loadProductsByServerHttp(params) {
|
|
527
|
-
const productList = await this.fetchProductsByHttp(params);
|
|
528
|
-
if (productList.length > 0) {
|
|
529
|
-
await this.saveProductsToIndexDB(productList);
|
|
530
|
-
await this.core.effects.emit(import_types.ProductsHooks.onProductsLoaded, productList);
|
|
531
|
-
}
|
|
532
|
-
return productList;
|
|
533
|
-
}
|
|
534
|
-
/**
|
|
535
|
-
* 获取商品列表(深拷贝,供外部安全使用)
|
|
474
|
+
* 获取商品列表(从缓存)
|
|
536
475
|
*/
|
|
537
476
|
async getProducts() {
|
|
538
|
-
|
|
539
|
-
const result = structuredClone(this.store.list);
|
|
540
|
-
(0, import_product.perfMark)("ProductsModule.getProducts(structuredClone)", performance.now() - t0, { count: result.length });
|
|
541
|
-
return result;
|
|
542
|
-
}
|
|
543
|
-
/**
|
|
544
|
-
* 内部获取商品列表的直接引用(无拷贝)
|
|
545
|
-
* 仅供内部 formatter 流程使用,因为 formatter 会创建新对象
|
|
546
|
-
*/
|
|
547
|
-
getProductsRef() {
|
|
548
|
-
return this.store.list;
|
|
477
|
+
return (0, import_lodash_es.cloneDeep)(this.store.list);
|
|
549
478
|
}
|
|
550
479
|
/**
|
|
551
480
|
* 根据ID获取单个商品(从内存缓存)
|
|
@@ -553,79 +482,7 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
|
|
|
553
482
|
*/
|
|
554
483
|
async getProductById(id) {
|
|
555
484
|
const product = this.store.map.get(id);
|
|
556
|
-
return product ?
|
|
557
|
-
}
|
|
558
|
-
/**
|
|
559
|
-
* 根据 ID 列表删除商品(用于 pubsub 同步删除场景)
|
|
560
|
-
* 同时更新 store.list、store.map、IndexDB 和价格缓存
|
|
561
|
-
*/
|
|
562
|
-
async removeProductsByIds(ids) {
|
|
563
|
-
const idSet = new Set(ids);
|
|
564
|
-
this.logInfo("removeProductsByIds", { ids, count: ids.length });
|
|
565
|
-
this.store.list = this.store.list.filter((p) => !idSet.has(p.id));
|
|
566
|
-
for (const id of ids) {
|
|
567
|
-
this.store.map.delete(id);
|
|
568
|
-
}
|
|
569
|
-
if (this.dbManager) {
|
|
570
|
-
try {
|
|
571
|
-
for (const id of ids) {
|
|
572
|
-
await this.dbManager.delete(INDEXDB_STORE_NAME, id);
|
|
573
|
-
}
|
|
574
|
-
} catch (error) {
|
|
575
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
576
|
-
this.logError("removeProductsByIds: IndexDB 删除失败", { ids, error: errorMessage });
|
|
577
|
-
}
|
|
578
|
-
}
|
|
579
|
-
for (const [dateKey, cachedProducts] of this.productsPriceCache.entries()) {
|
|
580
|
-
this.productsPriceCache.set(
|
|
581
|
-
dateKey,
|
|
582
|
-
cachedProducts.filter((p) => !idSet.has(p.id))
|
|
583
|
-
);
|
|
584
|
-
}
|
|
585
|
-
this.core.effects.emit(import_types.ProductsHooks.onProductsChanged, this.store.list);
|
|
586
|
-
this.logInfo("removeProductsByIds 完成", { remaining: this.store.list.length });
|
|
587
|
-
}
|
|
588
|
-
/**
|
|
589
|
-
* 重新从服务器加载全量商品列表并更新本地 store
|
|
590
|
-
* 用于 pubsub 同步 create / update / batch_update 场景
|
|
591
|
-
*/
|
|
592
|
-
async refreshProducts() {
|
|
593
|
-
const tTotal = performance.now();
|
|
594
|
-
this.logInfo("refreshProducts 开始");
|
|
595
|
-
const products = await this.loadProductsByServer();
|
|
596
|
-
if (products && products.length > 0) {
|
|
597
|
-
this.store.list = products;
|
|
598
|
-
this.syncProductsMap();
|
|
599
|
-
this.core.effects.emit(import_types.ProductsHooks.onProductsChanged, this.store.list);
|
|
600
|
-
this.logInfo("refreshProducts 完成", { productCount: products.length });
|
|
601
|
-
} else {
|
|
602
|
-
this.logWarning("refreshProducts: 服务器未返回数据");
|
|
603
|
-
}
|
|
604
|
-
(0, import_product.perfMark)("refreshProducts", performance.now() - tTotal, { count: this.store.list.length });
|
|
605
|
-
return this.store.list;
|
|
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
|
-
}
|
|
485
|
+
return product ? (0, import_lodash_es.cloneDeep)(product) : void 0;
|
|
629
486
|
}
|
|
630
487
|
/**
|
|
631
488
|
* 清空缓存
|
|
@@ -661,9 +518,7 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
|
|
|
661
518
|
return [];
|
|
662
519
|
}
|
|
663
520
|
try {
|
|
664
|
-
const t0 = performance.now();
|
|
665
521
|
const products = await this.dbManager.getAll(INDEXDB_STORE_NAME);
|
|
666
|
-
(0, import_product.perfMark)("loadProductsFromIndexDB", performance.now() - t0, { count: (products == null ? void 0 : products.length) ?? 0 });
|
|
667
522
|
this.logInfo("从 IndexDB 加载商品数据", {
|
|
668
523
|
productCount: (products == null ? void 0 : products.length) ?? 0
|
|
669
524
|
});
|
|
@@ -686,10 +541,11 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
|
|
|
686
541
|
}
|
|
687
542
|
this.logInfo("开始保存商品数据到 IndexDB", { productCount: products.length });
|
|
688
543
|
try {
|
|
689
|
-
const t0 = performance.now();
|
|
690
544
|
await this.dbManager.clear(INDEXDB_STORE_NAME);
|
|
691
|
-
|
|
692
|
-
|
|
545
|
+
const savePromises = products.map(
|
|
546
|
+
(product) => this.dbManager.add(INDEXDB_STORE_NAME, product)
|
|
547
|
+
);
|
|
548
|
+
await Promise.all(savePromises);
|
|
693
549
|
console.log(
|
|
694
550
|
`[Products] 已将 ${products.length} 个商品平铺保存到 IndexDB`
|
|
695
551
|
);
|
|
@@ -709,12 +565,11 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
|
|
|
709
565
|
* @private
|
|
710
566
|
*/
|
|
711
567
|
syncProductsMap() {
|
|
712
|
-
const t0 = performance.now();
|
|
713
568
|
this.store.map.clear();
|
|
714
569
|
for (const product of this.store.list) {
|
|
715
570
|
this.store.map.set(product.id, product);
|
|
716
571
|
}
|
|
717
|
-
|
|
572
|
+
console.log(`[Products] Map 缓存已同步,共 ${this.store.map.size} 个商品`);
|
|
718
573
|
}
|
|
719
574
|
/**
|
|
720
575
|
* 预加载模块数据(统一接口)
|
|
@@ -722,29 +577,22 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
|
|
|
722
577
|
*/
|
|
723
578
|
async preload() {
|
|
724
579
|
console.log("[Products] 开始预加载数据...");
|
|
725
|
-
const
|
|
580
|
+
const startTime = Date.now();
|
|
726
581
|
this.logInfo("开始预加载数据");
|
|
727
582
|
try {
|
|
728
|
-
const tIndexDB = performance.now();
|
|
729
583
|
const cachedData = await this.loadProductsFromIndexDB();
|
|
730
|
-
(0, import_product.perfMark)("preload.loadFromIndexDB", performance.now() - tIndexDB, { count: (cachedData == null ? void 0 : cachedData.length) ?? 0 });
|
|
731
584
|
if (cachedData && cachedData.length > 0) {
|
|
732
585
|
console.log(`[Products] 从 IndexDB 加载了 ${cachedData.length} 个商品`);
|
|
733
|
-
this.store.list = cachedData;
|
|
734
|
-
const tSync = performance.now();
|
|
586
|
+
this.store.list = (0, import_lodash_es.cloneDeep)(cachedData);
|
|
735
587
|
this.syncProductsMap();
|
|
736
|
-
(0, import_product.perfMark)("preload.syncProductsMap", performance.now() - tSync, { count: cachedData.length });
|
|
737
588
|
this.core.effects.emit(
|
|
738
589
|
import_types.ProductsHooks.onProductsChanged,
|
|
739
590
|
this.store.list
|
|
740
591
|
);
|
|
741
|
-
|
|
742
|
-
count: cachedData.length,
|
|
743
|
-
source: "IndexDB"
|
|
744
|
-
});
|
|
592
|
+
const duration = Date.now() - startTime;
|
|
745
593
|
this.logInfo("预加载完成(从 IndexDB)", {
|
|
746
594
|
productCount: cachedData.length,
|
|
747
|
-
duration: `${
|
|
595
|
+
duration: `${duration}ms`,
|
|
748
596
|
source: "IndexDB"
|
|
749
597
|
});
|
|
750
598
|
return;
|
|
@@ -756,416 +604,24 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
|
|
|
756
604
|
console.warn("[Products] 从 IndexDB 加载数据失败:", error);
|
|
757
605
|
this.logWarning("从 IndexDB 加载数据失败,准备从服务器加载", { error: errorMessage });
|
|
758
606
|
}
|
|
759
|
-
const tServer = performance.now();
|
|
760
607
|
const products = await this.loadProductsByServer();
|
|
761
|
-
(0, import_product.perfMark)("preload.loadFromServer", performance.now() - tServer, { count: (products == null ? void 0 : products.length) ?? 0 });
|
|
762
608
|
if (products && products.length > 0) {
|
|
763
|
-
this.
|
|
764
|
-
|
|
609
|
+
await this.saveProductsToIndexDB(products);
|
|
610
|
+
this.store.list = (0, import_lodash_es.cloneDeep)(products);
|
|
765
611
|
this.syncProductsMap();
|
|
766
|
-
(0, import_product.perfMark)("preload.syncProductsMap", performance.now() - tSync, { count: products.length });
|
|
767
612
|
this.core.effects.emit(import_types.ProductsHooks.onProductsChanged, this.store.list);
|
|
768
|
-
|
|
769
|
-
count: products.length,
|
|
770
|
-
source: "Server"
|
|
771
|
-
});
|
|
613
|
+
const duration = Date.now() - startTime;
|
|
772
614
|
this.logInfo("预加载完成(从服务器)", {
|
|
773
615
|
productCount: products.length,
|
|
774
|
-
duration: `${
|
|
616
|
+
duration: `${duration}ms`,
|
|
775
617
|
source: "Server"
|
|
776
618
|
});
|
|
777
619
|
} else {
|
|
778
|
-
|
|
620
|
+
const duration = Date.now() - startTime;
|
|
779
621
|
this.logWarning("预加载完成但未获取到数据", {
|
|
780
|
-
duration: `${
|
|
781
|
-
});
|
|
782
|
-
}
|
|
783
|
-
}
|
|
784
|
-
// =============================================
|
|
785
|
-
// 商品数据同步(pubsub)
|
|
786
|
-
// =============================================
|
|
787
|
-
/**
|
|
788
|
-
* 初始化 ProductDataSource 实例
|
|
789
|
-
* 与 pubsub 订阅和数据获取分开,仅负责创建实例
|
|
790
|
-
*/
|
|
791
|
-
initProductDataSource() {
|
|
792
|
-
var _a, _b;
|
|
793
|
-
const ProductDataSourceClass = (_b = (_a = this.core.serverOptions) == null ? void 0 : _a.All_DATA_SOURCES) == null ? void 0 : _b.ProductDataSource;
|
|
794
|
-
if (!ProductDataSourceClass) {
|
|
795
|
-
this.logWarning("initProductDataSource: ProductDataSource 不可用");
|
|
796
|
-
return;
|
|
797
|
-
}
|
|
798
|
-
this.productDataSource = new ProductDataSourceClass();
|
|
799
|
-
this.logInfo("ProductDataSource 实例已创建");
|
|
800
|
-
}
|
|
801
|
-
/**
|
|
802
|
-
* 初始化 pubsub 订阅,监听管理后台商品变更
|
|
803
|
-
* 仅负责订阅 product / product_quotation 频道,消息通过防抖合并后批量处理
|
|
804
|
-
* 数据获取由 loadProductsByServer 单独负责
|
|
805
|
-
*/
|
|
806
|
-
setupProductSync() {
|
|
807
|
-
if (!this.productDataSource) {
|
|
808
|
-
this.logWarning("setupProductSync: ProductDataSource 不可用,跳过同步初始化");
|
|
809
|
-
return;
|
|
810
|
-
}
|
|
811
|
-
const createHandler = (channelKey) => (message) => {
|
|
812
|
-
const data = (message == null ? void 0 : message.data) || message;
|
|
813
|
-
if (!data)
|
|
814
|
-
return;
|
|
815
|
-
console.log(`[ProductsModule] 收到同步消息 [${channelKey}]:`, data);
|
|
816
|
-
this.logInfo("收到同步消息", {
|
|
817
|
-
channelKey,
|
|
818
|
-
action: data.action,
|
|
819
|
-
id: data.id,
|
|
820
|
-
action_filed: data.action_filed
|
|
821
|
-
});
|
|
822
|
-
this.pendingSyncMessages.push({ ...data, _channelKey: channelKey });
|
|
823
|
-
if (this.syncTimer) {
|
|
824
|
-
clearTimeout(this.syncTimer);
|
|
825
|
-
}
|
|
826
|
-
this.syncTimer = setTimeout(() => {
|
|
827
|
-
this.processProductSyncMessages();
|
|
828
|
-
}, PRODUCT_SYNC_DEBOUNCE_MS);
|
|
829
|
-
};
|
|
830
|
-
this.productDataSource.run({
|
|
831
|
-
pubsub: {
|
|
832
|
-
callback: (res) => {
|
|
833
|
-
console.log("sse_products_callback", res);
|
|
834
|
-
this.logInfo("sse_products_callback: 收到同步消息", {
|
|
835
|
-
data: res == null ? void 0 : res.data
|
|
836
|
-
});
|
|
837
|
-
if (!(res == null ? void 0 : res.data))
|
|
838
|
-
return;
|
|
839
|
-
const data = res.data;
|
|
840
|
-
const channelKey = data.module || "product";
|
|
841
|
-
createHandler(channelKey)(data);
|
|
842
|
-
}
|
|
843
|
-
}
|
|
844
|
-
}).catch((err) => {
|
|
845
|
-
this.logError("setupProductSync: DataSource run 出错", {
|
|
846
|
-
error: err instanceof Error ? err.message : String(err)
|
|
847
|
-
});
|
|
848
|
-
});
|
|
849
|
-
this.logInfo("setupProductSync: pubsub 订阅已建立");
|
|
850
|
-
}
|
|
851
|
-
/**
|
|
852
|
-
* 处理防抖后的同步消息批次
|
|
853
|
-
*
|
|
854
|
-
* product 模块:
|
|
855
|
-
* - operation === 'delete' → 本地删除
|
|
856
|
-
* - 有 body(无 price change_types) → body 完整数据直接覆盖本地
|
|
857
|
-
* - change_types 包含 price → SSE 增量拉取 + 刷新报价单价格缓存
|
|
858
|
-
* - change_types 仅 stock → 跳过(暂不响应)
|
|
859
|
-
*
|
|
860
|
-
* product_collection / product_category / product_quotation:
|
|
861
|
-
* - 按 relation_product_ids SSE 拉取受影响商品
|
|
862
|
-
* - product_quotation 额外刷新报价单价格缓存
|
|
863
|
-
*
|
|
864
|
-
* 处理完成后 emit onProductsSyncCompleted 通知 Server 层
|
|
865
|
-
*/
|
|
866
|
-
async processProductSyncMessages() {
|
|
867
|
-
var _a, _b, _c, _d, _e;
|
|
868
|
-
const messages = [...this.pendingSyncMessages];
|
|
869
|
-
this.pendingSyncMessages = [];
|
|
870
|
-
if (messages.length === 0)
|
|
871
|
-
return;
|
|
872
|
-
this.logInfo("processProductSyncMessages: 开始处理", { count: messages.length });
|
|
873
|
-
const deleteIds = [];
|
|
874
|
-
const bodyUpdates = /* @__PURE__ */ new Map();
|
|
875
|
-
const sseRefreshIds = [];
|
|
876
|
-
const priceRefreshIds = [];
|
|
877
|
-
for (const msg of messages) {
|
|
878
|
-
const channelKey = msg._channelKey || msg.module || "product";
|
|
879
|
-
if (channelKey === "product") {
|
|
880
|
-
if (msg.operation === "delete" || msg.action === "delete") {
|
|
881
|
-
if ((_a = msg.ids) == null ? void 0 : _a.length)
|
|
882
|
-
deleteIds.push(...msg.ids);
|
|
883
|
-
else if (msg.id)
|
|
884
|
-
deleteIds.push(msg.id);
|
|
885
|
-
continue;
|
|
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
|
-
}
|
|
891
|
-
if ((_c = msg.change_types) == null ? void 0 : _c.includes("price")) {
|
|
892
|
-
const ids = msg.ids || (msg.id ? [msg.id] : []);
|
|
893
|
-
sseRefreshIds.push(...ids);
|
|
894
|
-
priceRefreshIds.push(...ids);
|
|
895
|
-
continue;
|
|
896
|
-
}
|
|
897
|
-
if (msg.body) {
|
|
898
|
-
const bodyId = msg.body.id || msg.id;
|
|
899
|
-
if (bodyId)
|
|
900
|
-
bodyUpdates.set(bodyId, msg.body);
|
|
901
|
-
continue;
|
|
902
|
-
}
|
|
903
|
-
if ((_d = msg.ids) == null ? void 0 : _d.length) {
|
|
904
|
-
sseRefreshIds.push(...msg.ids);
|
|
905
|
-
} else if (msg.id) {
|
|
906
|
-
sseRefreshIds.push(msg.id);
|
|
907
|
-
}
|
|
908
|
-
} else if (["product_collection", "product_category", "product_quotation"].includes(channelKey)) {
|
|
909
|
-
if ((_e = msg.relation_product_ids) == null ? void 0 : _e.length) {
|
|
910
|
-
sseRefreshIds.push(...msg.relation_product_ids);
|
|
911
|
-
if (channelKey === "product_quotation") {
|
|
912
|
-
this.clearPriceCache();
|
|
913
|
-
priceRefreshIds.push(...msg.relation_product_ids);
|
|
914
|
-
}
|
|
915
|
-
}
|
|
916
|
-
}
|
|
917
|
-
}
|
|
918
|
-
const uniqueDeleteIds = [...new Set(deleteIds)];
|
|
919
|
-
const uniqueSSEIds = [...new Set(sseRefreshIds)];
|
|
920
|
-
const uniquePriceIds = [...new Set(priceRefreshIds)];
|
|
921
|
-
if (uniqueDeleteIds.length > 0) {
|
|
922
|
-
await this.removeProductsByIds(uniqueDeleteIds);
|
|
923
|
-
}
|
|
924
|
-
if (bodyUpdates.size > 0) {
|
|
925
|
-
await this.applyBodyUpdatesToStore(bodyUpdates);
|
|
926
|
-
}
|
|
927
|
-
if (uniqueSSEIds.length > 0) {
|
|
928
|
-
const freshProducts = await this.fetchProductsBySSE(uniqueSSEIds);
|
|
929
|
-
if (freshProducts.length > 0) {
|
|
930
|
-
await this.mergeProductsToStore(freshProducts);
|
|
931
|
-
await this.updatePriceCacheForProducts(freshProducts);
|
|
932
|
-
}
|
|
933
|
-
this.logInfo("processProductSyncMessages: SSE 增量更新完成", {
|
|
934
|
-
requestedCount: uniqueSSEIds.length,
|
|
935
|
-
receivedCount: freshProducts.length
|
|
936
|
-
});
|
|
937
|
-
}
|
|
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: 处理完成", {
|
|
944
|
-
deleteCount: uniqueDeleteIds.length,
|
|
945
|
-
bodyUpdateCount: bodyUpdates.size,
|
|
946
|
-
sseRefreshCount: uniqueSSEIds.length,
|
|
947
|
-
priceRefreshCount: uniquePriceIds.length
|
|
948
|
-
});
|
|
949
|
-
await this.core.effects.emit(import_types.ProductsHooks.onProductsSyncCompleted, null);
|
|
950
|
-
}
|
|
951
|
-
/**
|
|
952
|
-
* 通过 SSE 按 ids 增量拉取商品数据
|
|
953
|
-
* 请求 GET /shop/core/stream?type=product&ids={ids}
|
|
954
|
-
*/
|
|
955
|
-
async fetchProductsBySSE(ids) {
|
|
956
|
-
if (!this.productDataSource) {
|
|
957
|
-
this.logWarning("fetchProductsBySSE: ProductDataSource 不可用");
|
|
958
|
-
return [];
|
|
959
|
-
}
|
|
960
|
-
this.logInfo("fetchProductsBySSE: 开始", { ids, count: ids.length });
|
|
961
|
-
const t0 = performance.now();
|
|
962
|
-
try {
|
|
963
|
-
const productList = await this.productDataSource.run({
|
|
964
|
-
sse: { query: { type: "product", ids } }
|
|
965
|
-
});
|
|
966
|
-
const list = productList || [];
|
|
967
|
-
(0, import_product.perfMark)("fetchProductsBySSE", performance.now() - t0, { count: list.length });
|
|
968
|
-
this.logInfo("fetchProductsBySSE: 成功", {
|
|
969
|
-
requestedCount: ids.length,
|
|
970
|
-
receivedCount: list.length,
|
|
971
|
-
duration: `${Math.round(performance.now() - t0)}ms`
|
|
972
|
-
});
|
|
973
|
-
return list;
|
|
974
|
-
} catch (error) {
|
|
975
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
976
|
-
this.logError("fetchProductsBySSE: 失败", { ids, error: errorMessage });
|
|
977
|
-
return [];
|
|
978
|
-
}
|
|
979
|
-
}
|
|
980
|
-
/**
|
|
981
|
-
* 将 body 完整数据直接覆盖到本地 store(不调用报价单接口)
|
|
982
|
-
* 已存在的 → 直接替换;不存在的 → 追加
|
|
983
|
-
* 同时更新 Map 缓存、IndexDB,清空价格缓存,触发 onProductsChanged
|
|
984
|
-
*/
|
|
985
|
-
async applyBodyUpdatesToStore(bodyUpdates) {
|
|
986
|
-
this.logInfo("applyBodyUpdatesToStore: 开始", { count: bodyUpdates.size });
|
|
987
|
-
let updatedCount = 0;
|
|
988
|
-
let newCount = 0;
|
|
989
|
-
const appliedIds = /* @__PURE__ */ new Set();
|
|
990
|
-
this.store.list = this.store.list.map((p) => {
|
|
991
|
-
if (bodyUpdates.has(p.id)) {
|
|
992
|
-
updatedCount++;
|
|
993
|
-
appliedIds.add(p.id);
|
|
994
|
-
return bodyUpdates.get(p.id);
|
|
995
|
-
}
|
|
996
|
-
return p;
|
|
997
|
-
});
|
|
998
|
-
for (const [id, body] of bodyUpdates) {
|
|
999
|
-
if (!appliedIds.has(id)) {
|
|
1000
|
-
this.store.list.push(body);
|
|
1001
|
-
newCount++;
|
|
1002
|
-
}
|
|
1003
|
-
}
|
|
1004
|
-
this.syncProductsMap();
|
|
1005
|
-
await this.saveProductsToIndexDB(this.store.list);
|
|
1006
|
-
await this.updatePriceCacheForProducts([...bodyUpdates.values()]);
|
|
1007
|
-
this.core.effects.emit(import_types.ProductsHooks.onProductsChanged, this.store.list);
|
|
1008
|
-
this.logInfo("applyBodyUpdatesToStore: 完成", {
|
|
1009
|
-
updatedCount,
|
|
1010
|
-
newCount,
|
|
1011
|
-
totalCount: this.store.list.length
|
|
1012
|
-
});
|
|
1013
|
-
}
|
|
1014
|
-
/**
|
|
1015
|
-
* 将增量拉取的商品合并到 store
|
|
1016
|
-
* 已存在的 → 替换;新的 → 追加
|
|
1017
|
-
* 同时更新 store.map、IndexDB,触发 onProductsChanged
|
|
1018
|
-
*/
|
|
1019
|
-
async mergeProductsToStore(freshProducts) {
|
|
1020
|
-
const freshMap = /* @__PURE__ */ new Map();
|
|
1021
|
-
for (const p of freshProducts) {
|
|
1022
|
-
freshMap.set(p.id, p);
|
|
1023
|
-
}
|
|
1024
|
-
const updatedList = this.store.list.map((p) => {
|
|
1025
|
-
if (freshMap.has(p.id)) {
|
|
1026
|
-
const fresh = freshMap.get(p.id);
|
|
1027
|
-
freshMap.delete(p.id);
|
|
1028
|
-
return fresh;
|
|
1029
|
-
}
|
|
1030
|
-
return p;
|
|
1031
|
-
});
|
|
1032
|
-
const newCount = freshMap.size;
|
|
1033
|
-
for (const p of freshMap.values()) {
|
|
1034
|
-
updatedList.push(p);
|
|
1035
|
-
}
|
|
1036
|
-
const updatedCount = freshProducts.length - newCount;
|
|
1037
|
-
this.store.list = updatedList;
|
|
1038
|
-
this.syncProductsMap();
|
|
1039
|
-
await this.saveProductsToIndexDB(this.store.list);
|
|
1040
|
-
this.logInfo("mergeProductsToStore: 合并完成", {
|
|
1041
|
-
updatedCount,
|
|
1042
|
-
newCount,
|
|
1043
|
-
totalCount: this.store.list.length
|
|
1044
|
-
});
|
|
1045
|
-
this.core.effects.emit(import_types.ProductsHooks.onProductsChanged, this.store.list);
|
|
1046
|
-
}
|
|
1047
|
-
/**
|
|
1048
|
-
* 增量更新价格缓存中变更的商品
|
|
1049
|
-
* 对每个已缓存的日期 key:替换/追加最新商品数据,重新拉取这些 ID 的价格并应用
|
|
1050
|
-
*/
|
|
1051
|
-
async updatePriceCacheForProducts(freshProducts) {
|
|
1052
|
-
if (this.productsPriceCache.size === 0)
|
|
1053
|
-
return;
|
|
1054
|
-
const freshIds = freshProducts.map((p) => p.id);
|
|
1055
|
-
const freshMap = /* @__PURE__ */ new Map();
|
|
1056
|
-
for (const p of freshProducts) {
|
|
1057
|
-
freshMap.set(p.id, p);
|
|
1058
|
-
}
|
|
1059
|
-
this.logInfo("updatePriceCacheForProducts: 开始", {
|
|
1060
|
-
freshIds,
|
|
1061
|
-
cachedDateCount: this.productsPriceCache.size
|
|
1062
|
-
});
|
|
1063
|
-
for (const [dateKey, cachedProducts] of this.productsPriceCache.entries()) {
|
|
1064
|
-
try {
|
|
1065
|
-
const updatedList = cachedProducts.map((p) => {
|
|
1066
|
-
const fresh = freshMap.get(p.id);
|
|
1067
|
-
return fresh ? { ...fresh } : p;
|
|
1068
|
-
});
|
|
1069
|
-
const existingIds = new Set(cachedProducts.map((p) => p.id));
|
|
1070
|
-
for (const p of freshProducts) {
|
|
1071
|
-
if (!existingIds.has(p.id)) {
|
|
1072
|
-
updatedList.push({ ...p });
|
|
1073
|
-
}
|
|
1074
|
-
}
|
|
1075
|
-
const priceData = await this.loadProductsPrice({
|
|
1076
|
-
ids: freshIds,
|
|
1077
|
-
schedule_date: dateKey
|
|
1078
|
-
});
|
|
1079
|
-
const result = priceData && priceData.length > 0 ? (0, import_product.applyPriceDataToProducts)(updatedList, priceData) : updatedList;
|
|
1080
|
-
this.productsPriceCache.set(dateKey, result);
|
|
1081
|
-
this.logInfo("updatePriceCacheForProducts: 日期缓存已更新", {
|
|
1082
|
-
dateKey,
|
|
1083
|
-
updatedIds: freshIds
|
|
1084
|
-
});
|
|
1085
|
-
} catch (error) {
|
|
1086
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
1087
|
-
this.logError("updatePriceCacheForProducts: 失败", { dateKey, error: errorMessage });
|
|
1088
|
-
}
|
|
1089
|
-
}
|
|
1090
|
-
}
|
|
1091
|
-
/**
|
|
1092
|
-
* 全量重新拉取报价单价格并重建价格缓存
|
|
1093
|
-
* 遍历当前已缓存的所有日期 key,对每个日期重新调用 loadProductsPrice
|
|
1094
|
-
*/
|
|
1095
|
-
async refreshAllPriceCache() {
|
|
1096
|
-
const allProducts = this.getProductsRef();
|
|
1097
|
-
if (allProducts.length === 0)
|
|
1098
|
-
return;
|
|
1099
|
-
const ids = allProducts.map((p) => p.id);
|
|
1100
|
-
const dateKeys = Array.from(this.productsPriceCache.keys());
|
|
1101
|
-
this.clearPriceCache();
|
|
1102
|
-
if (dateKeys.length === 0) {
|
|
1103
|
-
this.logInfo("refreshAllPriceCache: 无已缓存日期,跳过");
|
|
1104
|
-
return;
|
|
1105
|
-
}
|
|
1106
|
-
this.logInfo("refreshAllPriceCache: 开始重新拉取", { dateKeys, productCount: ids.length });
|
|
1107
|
-
for (const dateKey of dateKeys) {
|
|
1108
|
-
try {
|
|
1109
|
-
const priceData = await this.loadProductsPrice({ ids, schedule_date: dateKey });
|
|
1110
|
-
if (priceData && priceData.length > 0) {
|
|
1111
|
-
const updatedProducts = (0, import_product.applyPriceDataToProducts)(allProducts, priceData);
|
|
1112
|
-
this.productsPriceCache.set(dateKey, updatedProducts);
|
|
1113
|
-
}
|
|
1114
|
-
this.logInfo("refreshAllPriceCache: 日期缓存已更新", { dateKey });
|
|
1115
|
-
} catch (error) {
|
|
1116
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
1117
|
-
this.logError("refreshAllPriceCache: 失败", { dateKey, error: errorMessage });
|
|
1118
|
-
}
|
|
1119
|
-
}
|
|
1120
|
-
}
|
|
1121
|
-
/**
|
|
1122
|
-
* 静默全量刷新:后台重新拉取全量 SSE 数据并更新本地
|
|
1123
|
-
* 拿到完整数据后一次性替换 store,清除价格缓存,触发 onProductsSyncCompleted
|
|
1124
|
-
* @returns 刷新后的商品列表
|
|
1125
|
-
*/
|
|
1126
|
-
async silentRefresh() {
|
|
1127
|
-
const t0 = performance.now();
|
|
1128
|
-
this.logInfo("silentRefresh 开始");
|
|
1129
|
-
try {
|
|
1130
|
-
const products = await this.loadProductsByServer();
|
|
1131
|
-
if (products && products.length > 0) {
|
|
1132
|
-
this.store.list = products;
|
|
1133
|
-
this.syncProductsMap();
|
|
1134
|
-
this.clearPriceCache();
|
|
1135
|
-
this.core.effects.emit(import_types.ProductsHooks.onProductsChanged, this.store.list);
|
|
1136
|
-
await this.core.effects.emit(import_types.ProductsHooks.onProductsSyncCompleted, null);
|
|
1137
|
-
this.logInfo("silentRefresh 完成", {
|
|
1138
|
-
productCount: products.length,
|
|
1139
|
-
duration: `${Math.round(performance.now() - t0)}ms`
|
|
1140
|
-
});
|
|
1141
|
-
} else {
|
|
1142
|
-
this.logWarning("silentRefresh: 服务器未返回数据");
|
|
1143
|
-
}
|
|
1144
|
-
(0, import_product.perfMark)("silentRefresh", performance.now() - t0, { count: this.store.list.length });
|
|
1145
|
-
return this.store.list;
|
|
1146
|
-
} catch (error) {
|
|
1147
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
1148
|
-
this.logError("silentRefresh 失败", {
|
|
1149
|
-
duration: `${Math.round(performance.now() - t0)}ms`,
|
|
1150
|
-
error: errorMessage
|
|
622
|
+
duration: `${duration}ms`
|
|
1151
623
|
});
|
|
1152
|
-
return this.store.list;
|
|
1153
|
-
}
|
|
1154
|
-
}
|
|
1155
|
-
/**
|
|
1156
|
-
* 销毁同步资源(取消 pubsub 订阅、清除定时器)
|
|
1157
|
-
*/
|
|
1158
|
-
destroyProductSync() {
|
|
1159
|
-
var _a;
|
|
1160
|
-
if (this.syncTimer) {
|
|
1161
|
-
clearTimeout(this.syncTimer);
|
|
1162
|
-
this.syncTimer = void 0;
|
|
1163
|
-
}
|
|
1164
|
-
if ((_a = this.productDataSource) == null ? void 0 : _a.destroy) {
|
|
1165
|
-
this.productDataSource.destroy();
|
|
1166
624
|
}
|
|
1167
|
-
this.pendingSyncMessages = [];
|
|
1168
|
-
this.logInfo("destroyProductSync: 同步资源已销毁");
|
|
1169
625
|
}
|
|
1170
626
|
/**
|
|
1171
627
|
* 获取模块的路由定义
|