@pisell/pisellos 2.2.191 → 2.2.192
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/server/modules/order/index.d.ts +1 -68
- package/dist/server/modules/order/index.js +334 -761
- package/dist/server/modules/products/index.d.ts +0 -57
- package/dist/server/modules/products/index.js +347 -706
- package/lib/server/modules/order/index.d.ts +1 -68
- package/lib/server/modules/order/index.js +6 -376
- package/lib/server/modules/products/index.d.ts +0 -57
- package/lib/server/modules/products/index.js +0 -333
- package/package.json +1 -1
|
@@ -3,36 +3,6 @@ import { BaseModule } from '../../../modules/BaseModule';
|
|
|
3
3
|
import { ProductData } from '../../../modules/Product/types';
|
|
4
4
|
import type { RouteDefinition } from '../../types';
|
|
5
5
|
import { ProductIdScope, ProductFormatter, ProductFormatterContext } from './types';
|
|
6
|
-
/** 商品模块流程调试日志条目 */
|
|
7
|
-
interface ProductFlowLogEntry {
|
|
8
|
-
ts: string;
|
|
9
|
-
step: string;
|
|
10
|
-
metadata?: Record<string, unknown>;
|
|
11
|
-
}
|
|
12
|
-
/** 单个商品 IndexDB 写入记录 */
|
|
13
|
-
interface ProductWriteStatEntry {
|
|
14
|
-
ts: string;
|
|
15
|
-
writeSeq: number;
|
|
16
|
-
source: string;
|
|
17
|
-
writeMethod: string;
|
|
18
|
-
productId: number;
|
|
19
|
-
mergeAction?: 'insert' | 'update' | 'snapshot' | 'delete';
|
|
20
|
-
}
|
|
21
|
-
declare global {
|
|
22
|
-
interface Window {
|
|
23
|
-
__productModuleFlowLogs?: ProductFlowLogEntry[];
|
|
24
|
-
__productModuleWriteStats?: Record<string, ProductWriteStatEntry[]>;
|
|
25
|
-
clearProductModuleFlowLogs?: () => void;
|
|
26
|
-
exportProductModuleFlowLogs?: () => string;
|
|
27
|
-
exportProductModuleWriteStats?: () => string;
|
|
28
|
-
summarizeProductModuleWrites?: (topN?: number) => Array<{
|
|
29
|
-
productId: number;
|
|
30
|
-
writeCount: number;
|
|
31
|
-
sources: string[];
|
|
32
|
-
lastWriteAt: string;
|
|
33
|
-
}>;
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
6
|
/**
|
|
37
7
|
* Products 模块 - 用于获取和管理完整的商品详细数据
|
|
38
8
|
* 相比 ProductList 模块,Products 会获取所有详细信息并缓存
|
|
@@ -57,8 +27,6 @@ export declare class ProductsModule extends BaseModule implements Module {
|
|
|
57
27
|
private productDataSource;
|
|
58
28
|
private pendingSyncMessages;
|
|
59
29
|
private syncTimer?;
|
|
60
|
-
/** IndexDB 写入序号,便于日志关联 */
|
|
61
|
-
private productFlowWriteSeq;
|
|
62
30
|
/** 最近一次 SSE 全量拉取完成时间 */
|
|
63
31
|
private lastServerFullFetchAtMs;
|
|
64
32
|
/** 最近一次 preload 完成时间(含 IndexDB 命中) */
|
|
@@ -85,30 +53,6 @@ export declare class ProductsModule extends BaseModule implements Module {
|
|
|
85
53
|
* @param metadata 日志元数据
|
|
86
54
|
*/
|
|
87
55
|
private logError;
|
|
88
|
-
/**
|
|
89
|
-
* 初始化 window 上的商品流程调试日志。
|
|
90
|
-
*
|
|
91
|
-
* @example
|
|
92
|
-
* window.clearProductModuleFlowLogs()
|
|
93
|
-
* copy(window.exportProductModuleFlowLogs?.() || '[]')
|
|
94
|
-
*/
|
|
95
|
-
private initProductFlowLogs;
|
|
96
|
-
/**
|
|
97
|
-
* 写入 window 商品流程调试日志。
|
|
98
|
-
*
|
|
99
|
-
* @example
|
|
100
|
-
* this.pushProductFlowLog('mergeProductsToStore.start', { count: 3 })
|
|
101
|
-
*/
|
|
102
|
-
private pushProductFlowLog;
|
|
103
|
-
/** 当前内存 store 快照,供流程日志使用 */
|
|
104
|
-
private getProductStoreSnapshot;
|
|
105
|
-
/**
|
|
106
|
-
* 记录 IndexDB 写入统计(按 productId 聚合)。
|
|
107
|
-
*
|
|
108
|
-
* @example
|
|
109
|
-
* this.trackProductWrite('pubsub.mergeProductsToStore', 'clear+bulkUpdate', products, { 1: 'update' })
|
|
110
|
-
*/
|
|
111
|
-
private trackProductWrite;
|
|
112
56
|
/**
|
|
113
57
|
* 加载商品价格(原始方法,不带缓存)
|
|
114
58
|
* @private
|
|
@@ -371,4 +315,3 @@ export declare class ProductsModule extends BaseModule implements Module {
|
|
|
371
315
|
*/
|
|
372
316
|
getRoutes(): RouteDefinition[];
|
|
373
317
|
}
|
|
374
|
-
export {};
|
|
@@ -27,9 +27,6 @@ var import_Quotation = require("../../../modules/Quotation");
|
|
|
27
27
|
var import_types = require("./types");
|
|
28
28
|
var import_product = require("../../utils/product");
|
|
29
29
|
var INDEXDB_STORE_NAME = "products";
|
|
30
|
-
var PRODUCT_FLOW_LOG_WINDOW_KEY = "__productModuleFlowLogs";
|
|
31
|
-
var PRODUCT_WRITE_STATS_WINDOW_KEY = "__productModuleWriteStats";
|
|
32
|
-
var PRODUCT_FLOW_LOG_MAX_LENGTH = 1e3;
|
|
33
30
|
var PRODUCT_SYNC_DEBOUNCE_MS = 1e4;
|
|
34
31
|
var PRODUCT_SILENT_REFRESH_MIN_INTERVAL_MS = 3e4;
|
|
35
32
|
var ProductsModule = class extends import_BaseModule.BaseModule {
|
|
@@ -50,8 +47,6 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
|
|
|
50
47
|
this.isPriceFormatterRegistered = false;
|
|
51
48
|
this.quotationBridgeLoadedKey = "";
|
|
52
49
|
this.pendingSyncMessages = [];
|
|
53
|
-
/** IndexDB 写入序号,便于日志关联 */
|
|
54
|
-
this.productFlowWriteSeq = 0;
|
|
55
50
|
/** 最近一次 SSE 全量拉取完成时间 */
|
|
56
51
|
this.lastServerFullFetchAtMs = 0;
|
|
57
52
|
/** 最近一次 preload 完成时间(含 IndexDB 命中) */
|
|
@@ -87,12 +82,6 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
|
|
|
87
82
|
this.registerBuiltinPriceFormatter();
|
|
88
83
|
this.initProductDataSource();
|
|
89
84
|
this.setupProductSync();
|
|
90
|
-
this.initProductFlowLogs();
|
|
91
|
-
this.pushProductFlowLog("initialize.complete", {
|
|
92
|
-
hasDbManager: !!this.dbManager,
|
|
93
|
-
hasLogger: !!this.logger,
|
|
94
|
-
initialProductCount: this.store.list.length
|
|
95
|
-
});
|
|
96
85
|
this.logInfo("模块初始化完成", {
|
|
97
86
|
hasDbManager: !!this.dbManager,
|
|
98
87
|
hasLogger: !!this.logger,
|
|
@@ -149,138 +138,6 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
|
|
|
149
138
|
}
|
|
150
139
|
} catch {
|
|
151
140
|
}
|
|
152
|
-
this.pushProductFlowLog(`error.${title}`, metadata);
|
|
153
|
-
}
|
|
154
|
-
/**
|
|
155
|
-
* 初始化 window 上的商品流程调试日志。
|
|
156
|
-
*
|
|
157
|
-
* @example
|
|
158
|
-
* window.clearProductModuleFlowLogs()
|
|
159
|
-
* copy(window.exportProductModuleFlowLogs?.() || '[]')
|
|
160
|
-
*/
|
|
161
|
-
initProductFlowLogs() {
|
|
162
|
-
try {
|
|
163
|
-
const win = typeof globalThis !== "undefined" ? globalThis.window : void 0;
|
|
164
|
-
if (!win)
|
|
165
|
-
return;
|
|
166
|
-
win[PRODUCT_FLOW_LOG_WINDOW_KEY] = [];
|
|
167
|
-
win[PRODUCT_WRITE_STATS_WINDOW_KEY] = {};
|
|
168
|
-
win.clearProductModuleFlowLogs = () => {
|
|
169
|
-
win[PRODUCT_FLOW_LOG_WINDOW_KEY] = [];
|
|
170
|
-
win[PRODUCT_WRITE_STATS_WINDOW_KEY] = {};
|
|
171
|
-
this.productFlowWriteSeq = 0;
|
|
172
|
-
this.pushProductFlowLog("debug.clear", {});
|
|
173
|
-
};
|
|
174
|
-
win.exportProductModuleFlowLogs = () => {
|
|
175
|
-
const logs = win[PRODUCT_FLOW_LOG_WINDOW_KEY] || [];
|
|
176
|
-
return JSON.stringify(logs, null, 2);
|
|
177
|
-
};
|
|
178
|
-
win.exportProductModuleWriteStats = () => {
|
|
179
|
-
const stats = win[PRODUCT_WRITE_STATS_WINDOW_KEY] || {};
|
|
180
|
-
return JSON.stringify(stats, null, 2);
|
|
181
|
-
};
|
|
182
|
-
win.summarizeProductModuleWrites = (topN = 20) => {
|
|
183
|
-
const stats = win[PRODUCT_WRITE_STATS_WINDOW_KEY] || {};
|
|
184
|
-
return Object.entries(stats).map(([productId, entries]) => {
|
|
185
|
-
const list = entries || [];
|
|
186
|
-
const sources = [...new Set(list.map((item) => item.source))];
|
|
187
|
-
const last = list[list.length - 1];
|
|
188
|
-
return {
|
|
189
|
-
productId: Number(productId),
|
|
190
|
-
writeCount: list.length,
|
|
191
|
-
sources,
|
|
192
|
-
lastWriteAt: (last == null ? void 0 : last.ts) || ""
|
|
193
|
-
};
|
|
194
|
-
}).sort((a, b) => b.writeCount - a.writeCount).slice(0, topN);
|
|
195
|
-
};
|
|
196
|
-
this.pushProductFlowLog("debug.init", {
|
|
197
|
-
logKey: PRODUCT_FLOW_LOG_WINDOW_KEY,
|
|
198
|
-
writeStatsKey: PRODUCT_WRITE_STATS_WINDOW_KEY,
|
|
199
|
-
indexDbStrategy: "全量 replaceProductsSnapshotInIndexDB + 增量 patchProductsInIndexDB",
|
|
200
|
-
helpers: [
|
|
201
|
-
"clearProductModuleFlowLogs",
|
|
202
|
-
"exportProductModuleFlowLogs",
|
|
203
|
-
"exportProductModuleWriteStats",
|
|
204
|
-
"summarizeProductModuleWrites"
|
|
205
|
-
]
|
|
206
|
-
});
|
|
207
|
-
} catch {
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
/**
|
|
211
|
-
* 写入 window 商品流程调试日志。
|
|
212
|
-
*
|
|
213
|
-
* @example
|
|
214
|
-
* this.pushProductFlowLog('mergeProductsToStore.start', { count: 3 })
|
|
215
|
-
*/
|
|
216
|
-
pushProductFlowLog(step, metadata) {
|
|
217
|
-
try {
|
|
218
|
-
const win = typeof globalThis !== "undefined" ? globalThis.window : void 0;
|
|
219
|
-
if (!win)
|
|
220
|
-
return;
|
|
221
|
-
if (!Array.isArray(win[PRODUCT_FLOW_LOG_WINDOW_KEY])) {
|
|
222
|
-
win[PRODUCT_FLOW_LOG_WINDOW_KEY] = [];
|
|
223
|
-
}
|
|
224
|
-
const entry = {
|
|
225
|
-
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
226
|
-
step,
|
|
227
|
-
metadata: metadata || {}
|
|
228
|
-
};
|
|
229
|
-
win[PRODUCT_FLOW_LOG_WINDOW_KEY].push(entry);
|
|
230
|
-
const logs = win[PRODUCT_FLOW_LOG_WINDOW_KEY];
|
|
231
|
-
if (logs.length > PRODUCT_FLOW_LOG_MAX_LENGTH) {
|
|
232
|
-
logs.splice(0, logs.length - PRODUCT_FLOW_LOG_MAX_LENGTH);
|
|
233
|
-
}
|
|
234
|
-
console.log(`[ProductFlow] ${step}`, metadata || {});
|
|
235
|
-
} catch {
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
/** 当前内存 store 快照,供流程日志使用 */
|
|
239
|
-
getProductStoreSnapshot() {
|
|
240
|
-
return {
|
|
241
|
-
storeListCount: this.store.list.length,
|
|
242
|
-
storeMapCount: this.store.map.size,
|
|
243
|
-
pendingSyncCount: this.pendingSyncMessages.length
|
|
244
|
-
};
|
|
245
|
-
}
|
|
246
|
-
/**
|
|
247
|
-
* 记录 IndexDB 写入统计(按 productId 聚合)。
|
|
248
|
-
*
|
|
249
|
-
* @example
|
|
250
|
-
* this.trackProductWrite('pubsub.mergeProductsToStore', 'clear+bulkUpdate', products, { 1: 'update' })
|
|
251
|
-
*/
|
|
252
|
-
trackProductWrite(source, writeMethod, products, mergeActions = {}, defaultMergeAction = "update") {
|
|
253
|
-
this.productFlowWriteSeq += 1;
|
|
254
|
-
const writeSeq = this.productFlowWriteSeq;
|
|
255
|
-
try {
|
|
256
|
-
const win = typeof globalThis !== "undefined" ? globalThis.window : void 0;
|
|
257
|
-
if (!win)
|
|
258
|
-
return writeSeq;
|
|
259
|
-
if (!win[PRODUCT_WRITE_STATS_WINDOW_KEY]) {
|
|
260
|
-
win[PRODUCT_WRITE_STATS_WINDOW_KEY] = {};
|
|
261
|
-
}
|
|
262
|
-
const stats = win[PRODUCT_WRITE_STATS_WINDOW_KEY];
|
|
263
|
-
for (const product of products) {
|
|
264
|
-
const productId = product == null ? void 0 : product.id;
|
|
265
|
-
if (productId === void 0 || productId === null)
|
|
266
|
-
continue;
|
|
267
|
-
const mergeAction = mergeActions[productId] || defaultMergeAction;
|
|
268
|
-
const entry = {
|
|
269
|
-
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
270
|
-
writeSeq,
|
|
271
|
-
source,
|
|
272
|
-
writeMethod,
|
|
273
|
-
productId,
|
|
274
|
-
mergeAction
|
|
275
|
-
};
|
|
276
|
-
const key = String(productId);
|
|
277
|
-
if (!stats[key])
|
|
278
|
-
stats[key] = [];
|
|
279
|
-
stats[key].push(entry);
|
|
280
|
-
}
|
|
281
|
-
} catch {
|
|
282
|
-
}
|
|
283
|
-
return writeSeq;
|
|
284
141
|
}
|
|
285
142
|
/**
|
|
286
143
|
* 加载商品价格(原始方法,不带缓存)
|
|
@@ -853,7 +710,6 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
|
|
|
853
710
|
this.logWarning("loadProductsByServer: ProductDataSource 不可用");
|
|
854
711
|
return [];
|
|
855
712
|
}
|
|
856
|
-
this.pushProductFlowLog("loadProductsByServer.start", this.getProductStoreSnapshot());
|
|
857
713
|
this.logInfo("开始通过 DataSource SSE 加载商品列表");
|
|
858
714
|
const t0 = performance.now();
|
|
859
715
|
try {
|
|
@@ -861,7 +717,6 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
|
|
|
861
717
|
const productList = await this.productDataSource.run({ sse: {} });
|
|
862
718
|
const list = productList || [];
|
|
863
719
|
(0, import_product.perfMark)("loadProductsByServer.SSE", performance.now() - tSSE, { count: list.length });
|
|
864
|
-
this.pushProductFlowLog("loadProductsByServer.sseSuccess", { count: list.length });
|
|
865
720
|
this.logInfo("通过 DataSource SSE 加载商品列表成功", {
|
|
866
721
|
productCount: list.length,
|
|
867
722
|
duration: `${Math.round(performance.now() - t0)}ms`
|
|
@@ -869,16 +724,9 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
|
|
|
869
724
|
await this.replaceProductsSnapshotInIndexDB(list, "loadProductsByServer");
|
|
870
725
|
this.lastServerFullFetchAtMs = Date.now();
|
|
871
726
|
await this.core.effects.emit(import_types.ProductsHooks.onProductsLoaded, list);
|
|
872
|
-
this.pushProductFlowLog("loadProductsByServer.done", {
|
|
873
|
-
count: list.length,
|
|
874
|
-
...this.getProductStoreSnapshot()
|
|
875
|
-
});
|
|
876
727
|
(0, import_product.perfMark)("loadProductsByServer", performance.now() - t0, { count: list.length });
|
|
877
728
|
return list;
|
|
878
729
|
} catch (error) {
|
|
879
|
-
this.pushProductFlowLog("loadProductsByServer.failed", {
|
|
880
|
-
error: error instanceof Error ? error.message : String(error)
|
|
881
|
-
});
|
|
882
730
|
const duration = Math.round(performance.now() - t0);
|
|
883
731
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
884
732
|
console.error("[Products] 加载商品数据失败:", error);
|
|
@@ -971,20 +819,12 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
|
|
|
971
819
|
* @param params 查询参数
|
|
972
820
|
*/
|
|
973
821
|
async loadProductsByServerHttp(params) {
|
|
974
|
-
this.pushProductFlowLog("loadProductsByServerHttp.start", {
|
|
975
|
-
params: params || {},
|
|
976
|
-
...this.getProductStoreSnapshot()
|
|
977
|
-
});
|
|
978
822
|
const productList = await this.fetchProductsByHttp(params);
|
|
979
823
|
if (productList.length > 0) {
|
|
980
824
|
await this.replaceProductsSnapshotInIndexDB(productList, "loadProductsByServerHttp");
|
|
981
825
|
this.lastServerFullFetchAtMs = Date.now();
|
|
982
826
|
await this.core.effects.emit(import_types.ProductsHooks.onProductsLoaded, productList);
|
|
983
827
|
}
|
|
984
|
-
this.pushProductFlowLog("loadProductsByServerHttp.done", {
|
|
985
|
-
count: productList.length,
|
|
986
|
-
...this.getProductStoreSnapshot()
|
|
987
|
-
});
|
|
988
828
|
return productList;
|
|
989
829
|
}
|
|
990
830
|
/**
|
|
@@ -1029,12 +869,6 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
|
|
|
1029
869
|
*/
|
|
1030
870
|
async removeProductsByIds(ids) {
|
|
1031
871
|
const idSet = new Set(ids);
|
|
1032
|
-
this.pushProductFlowLog("removeProductsByIds.start", {
|
|
1033
|
-
ids,
|
|
1034
|
-
count: ids.length,
|
|
1035
|
-
writeStrategy: "delete-by-id",
|
|
1036
|
-
...this.getProductStoreSnapshot()
|
|
1037
|
-
});
|
|
1038
872
|
this.logInfo("removeProductsByIds", { ids, count: ids.length });
|
|
1039
873
|
this.store.list = this.store.list.filter((p) => !idSet.has(p.id));
|
|
1040
874
|
for (const id of ids) {
|
|
@@ -1045,13 +879,6 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
|
|
|
1045
879
|
for (const id of ids) {
|
|
1046
880
|
await this.dbManager.delete(INDEXDB_STORE_NAME, id);
|
|
1047
881
|
}
|
|
1048
|
-
this.trackProductWrite(
|
|
1049
|
-
"pubsub.removeProductsByIds",
|
|
1050
|
-
"delete",
|
|
1051
|
-
ids.map((id) => ({ id })),
|
|
1052
|
-
Object.fromEntries(ids.map((id) => [id, "delete"])),
|
|
1053
|
-
"delete"
|
|
1054
|
-
);
|
|
1055
882
|
} catch (error) {
|
|
1056
883
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
1057
884
|
this.logError("removeProductsByIds: IndexDB 删除失败", { ids, error: errorMessage });
|
|
@@ -1064,10 +891,6 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
|
|
|
1064
891
|
);
|
|
1065
892
|
}
|
|
1066
893
|
this.core.effects.emit(import_types.ProductsHooks.onProductsChanged, this.store.list);
|
|
1067
|
-
this.pushProductFlowLog("removeProductsByIds.done", {
|
|
1068
|
-
ids,
|
|
1069
|
-
...this.getProductStoreSnapshot()
|
|
1070
|
-
});
|
|
1071
894
|
this.logInfo("removeProductsByIds 完成", { remaining: this.store.list.length });
|
|
1072
895
|
}
|
|
1073
896
|
/**
|
|
@@ -1076,7 +899,6 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
|
|
|
1076
899
|
*/
|
|
1077
900
|
async refreshProducts() {
|
|
1078
901
|
const tTotal = performance.now();
|
|
1079
|
-
this.pushProductFlowLog("refreshProducts.start", this.getProductStoreSnapshot());
|
|
1080
902
|
this.logInfo("refreshProducts 开始");
|
|
1081
903
|
const products = await this.loadProductsByServer();
|
|
1082
904
|
if (products && products.length > 0) {
|
|
@@ -1088,11 +910,6 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
|
|
|
1088
910
|
this.logWarning("refreshProducts: 服务器未返回数据");
|
|
1089
911
|
}
|
|
1090
912
|
(0, import_product.perfMark)("refreshProducts", performance.now() - tTotal, { count: this.store.list.length });
|
|
1091
|
-
this.pushProductFlowLog("refreshProducts.done", {
|
|
1092
|
-
count: this.store.list.length,
|
|
1093
|
-
durationMs: Math.round(performance.now() - tTotal),
|
|
1094
|
-
...this.getProductStoreSnapshot()
|
|
1095
|
-
});
|
|
1096
913
|
return this.store.list;
|
|
1097
914
|
}
|
|
1098
915
|
/**
|
|
@@ -1164,54 +981,22 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
|
|
|
1164
981
|
*/
|
|
1165
982
|
async replaceProductsSnapshotInIndexDB(products, source) {
|
|
1166
983
|
if (!this.dbManager) {
|
|
1167
|
-
this.pushProductFlowLog("replaceProductsSnapshotInIndexDB.skip", {
|
|
1168
|
-
source,
|
|
1169
|
-
reason: "no_dbManager",
|
|
1170
|
-
inputCount: products.length
|
|
1171
|
-
});
|
|
1172
984
|
this.logWarning("replaceProductsSnapshotInIndexDB: dbManager 不可用");
|
|
1173
985
|
return;
|
|
1174
986
|
}
|
|
1175
987
|
try {
|
|
1176
988
|
await this.runInProductIndexDBSaveQueue(async () => {
|
|
1177
|
-
this.pushProductFlowLog("replaceProductsSnapshotInIndexDB.start", {
|
|
1178
|
-
source,
|
|
1179
|
-
writeStrategy: "clear+bulkUpdate",
|
|
1180
|
-
inputCount: products.length,
|
|
1181
|
-
storeListCount: this.store.list.length
|
|
1182
|
-
});
|
|
1183
989
|
this.logInfo("replaceProductsSnapshotInIndexDB 开始", { source, productCount: products.length });
|
|
1184
990
|
const t0 = performance.now();
|
|
1185
991
|
await this.dbManager.clear(INDEXDB_STORE_NAME);
|
|
1186
|
-
this.pushProductFlowLog("replaceProductsSnapshotInIndexDB.cleared", {
|
|
1187
|
-
source,
|
|
1188
|
-
inputCount: products.length
|
|
1189
|
-
});
|
|
1190
992
|
if (products.length > 0) {
|
|
1191
993
|
await this.dbManager.bulkUpdate(INDEXDB_STORE_NAME, products);
|
|
1192
994
|
}
|
|
1193
|
-
const writeSeq = this.trackProductWrite(
|
|
1194
|
-
source,
|
|
1195
|
-
"clear+bulkUpdate",
|
|
1196
|
-
products,
|
|
1197
|
-
{},
|
|
1198
|
-
"snapshot"
|
|
1199
|
-
);
|
|
1200
995
|
(0, import_product.perfMark)("replaceProductsSnapshotInIndexDB", performance.now() - t0, { count: products.length });
|
|
1201
|
-
this.pushProductFlowLog("replaceProductsSnapshotInIndexDB.done", {
|
|
1202
|
-
source,
|
|
1203
|
-
writeSeq,
|
|
1204
|
-
count: products.length
|
|
1205
|
-
});
|
|
1206
996
|
this.logInfo("replaceProductsSnapshotInIndexDB 完成", { source, productCount: products.length });
|
|
1207
997
|
});
|
|
1208
998
|
} catch (error) {
|
|
1209
999
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
1210
|
-
this.pushProductFlowLog("replaceProductsSnapshotInIndexDB.error", {
|
|
1211
|
-
source,
|
|
1212
|
-
productCount: products.length,
|
|
1213
|
-
error: errorMessage
|
|
1214
|
-
});
|
|
1215
1000
|
this.logError("全量保存商品到 IndexDB 失败", {
|
|
1216
1001
|
source,
|
|
1217
1002
|
productCount: products.length,
|
|
@@ -1227,56 +1012,28 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
|
|
|
1227
1012
|
*/
|
|
1228
1013
|
async patchProductsInIndexDB(products, source, mergeActions = {}) {
|
|
1229
1014
|
if (!this.dbManager || products.length === 0) {
|
|
1230
|
-
this.pushProductFlowLog("patchProductsInIndexDB.skip", {
|
|
1231
|
-
source,
|
|
1232
|
-
hasDbManager: !!this.dbManager,
|
|
1233
|
-
inputCount: products.length
|
|
1234
|
-
});
|
|
1235
1015
|
return;
|
|
1236
1016
|
}
|
|
1237
1017
|
const validProducts = products.filter((p) => (p == null ? void 0 : p.id) !== void 0 && (p == null ? void 0 : p.id) !== null);
|
|
1238
1018
|
if (validProducts.length === 0) {
|
|
1239
|
-
this.pushProductFlowLog("patchProductsInIndexDB.skipNoId", { source, inputCount: products.length });
|
|
1240
1019
|
return;
|
|
1241
1020
|
}
|
|
1242
1021
|
try {
|
|
1243
1022
|
await this.runInProductIndexDBSaveQueue(async () => {
|
|
1244
|
-
let writeMethod = "none";
|
|
1245
|
-
this.pushProductFlowLog("patchProductsInIndexDB.start", {
|
|
1246
|
-
source,
|
|
1247
|
-
writeStrategy: "bulkUpdate-patch",
|
|
1248
|
-
count: validProducts.length,
|
|
1249
|
-
productIds: validProducts.map((p) => p.id),
|
|
1250
|
-
storeListCount: this.store.list.length
|
|
1251
|
-
});
|
|
1252
1023
|
this.logInfo("patchProductsInIndexDB 开始", { source, count: validProducts.length });
|
|
1253
1024
|
const t0 = performance.now();
|
|
1254
1025
|
if (typeof this.dbManager.bulkUpdate === "function") {
|
|
1255
|
-
writeMethod = "bulkUpdate";
|
|
1256
1026
|
await this.dbManager.bulkUpdate(INDEXDB_STORE_NAME, validProducts);
|
|
1257
1027
|
} else if (typeof this.dbManager.update === "function") {
|
|
1258
|
-
writeMethod = "update";
|
|
1259
1028
|
for (const product of validProducts) {
|
|
1260
1029
|
await this.dbManager.update(INDEXDB_STORE_NAME, product);
|
|
1261
1030
|
}
|
|
1262
1031
|
}
|
|
1263
|
-
const writeSeq = this.trackProductWrite(source, writeMethod, validProducts, mergeActions);
|
|
1264
1032
|
(0, import_product.perfMark)("patchProductsInIndexDB", performance.now() - t0, { count: validProducts.length });
|
|
1265
|
-
this.pushProductFlowLog("patchProductsInIndexDB.done", {
|
|
1266
|
-
source,
|
|
1267
|
-
writeSeq,
|
|
1268
|
-
writeMethod,
|
|
1269
|
-
count: validProducts.length
|
|
1270
|
-
});
|
|
1271
1033
|
this.logInfo("patchProductsInIndexDB 完成", { source, count: validProducts.length });
|
|
1272
1034
|
});
|
|
1273
1035
|
} catch (error) {
|
|
1274
1036
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
1275
|
-
this.pushProductFlowLog("patchProductsInIndexDB.error", {
|
|
1276
|
-
source,
|
|
1277
|
-
error: errorMessage,
|
|
1278
|
-
productCount: validProducts.length
|
|
1279
|
-
});
|
|
1280
1037
|
this.logError("增量保存商品到 IndexDB 失败", {
|
|
1281
1038
|
source,
|
|
1282
1039
|
error: errorMessage,
|
|
@@ -1304,7 +1061,6 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
|
|
|
1304
1061
|
async preload() {
|
|
1305
1062
|
console.log("[Products] 开始预加载数据...");
|
|
1306
1063
|
const tTotal = performance.now();
|
|
1307
|
-
this.pushProductFlowLog("preload.start", this.getProductStoreSnapshot());
|
|
1308
1064
|
this.logInfo("开始预加载数据");
|
|
1309
1065
|
try {
|
|
1310
1066
|
const tIndexDB = performance.now();
|
|
@@ -1329,11 +1085,6 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
|
|
|
1329
1085
|
duration: `${Math.round(performance.now() - tTotal)}ms`,
|
|
1330
1086
|
source: "IndexDB"
|
|
1331
1087
|
});
|
|
1332
|
-
this.pushProductFlowLog("preload.done", {
|
|
1333
|
-
source: "IndexDB",
|
|
1334
|
-
loadedCount: cachedData.length,
|
|
1335
|
-
...this.getProductStoreSnapshot()
|
|
1336
|
-
});
|
|
1337
1088
|
this.lastPreloadCompletedAtMs = Date.now();
|
|
1338
1089
|
return;
|
|
1339
1090
|
}
|
|
@@ -1362,14 +1113,8 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
|
|
|
1362
1113
|
duration: `${Math.round(performance.now() - tTotal)}ms`,
|
|
1363
1114
|
source: "Server"
|
|
1364
1115
|
});
|
|
1365
|
-
this.pushProductFlowLog("preload.done", {
|
|
1366
|
-
source: "Server",
|
|
1367
|
-
loadedCount: products.length,
|
|
1368
|
-
...this.getProductStoreSnapshot()
|
|
1369
|
-
});
|
|
1370
1116
|
this.lastPreloadCompletedAtMs = Date.now();
|
|
1371
1117
|
} else {
|
|
1372
|
-
this.pushProductFlowLog("preload.empty", this.getProductStoreSnapshot());
|
|
1373
1118
|
(0, import_product.perfMark)("preload(empty)", performance.now() - tTotal, { source: "empty" });
|
|
1374
1119
|
this.logWarning("预加载完成但未获取到数据", {
|
|
1375
1120
|
duration: `${Math.round(performance.now() - tTotal)}ms`
|
|
@@ -1415,17 +1160,6 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
|
|
|
1415
1160
|
action_filed: data.action_filed
|
|
1416
1161
|
});
|
|
1417
1162
|
this.pendingSyncMessages.push({ ...data, _channelKey: channelKey });
|
|
1418
|
-
this.pushProductFlowLog("pubsub.messageEnqueued", {
|
|
1419
|
-
channelKey,
|
|
1420
|
-
action: data.action,
|
|
1421
|
-
operation: data.operation,
|
|
1422
|
-
id: data.id,
|
|
1423
|
-
ids: data.ids,
|
|
1424
|
-
hasBody: !!data.body,
|
|
1425
|
-
changeTypes: data.change_types,
|
|
1426
|
-
pendingSyncCount: this.pendingSyncMessages.length,
|
|
1427
|
-
debounceMs: PRODUCT_SYNC_DEBOUNCE_MS
|
|
1428
|
-
});
|
|
1429
1163
|
if (this.syncTimer) {
|
|
1430
1164
|
clearTimeout(this.syncTimer);
|
|
1431
1165
|
}
|
|
@@ -1478,10 +1212,6 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
|
|
|
1478
1212
|
this.pendingSyncMessages = [];
|
|
1479
1213
|
if (messages.length === 0)
|
|
1480
1214
|
return;
|
|
1481
|
-
this.pushProductFlowLog("processProductSyncMessages.start", {
|
|
1482
|
-
messageCount: messages.length,
|
|
1483
|
-
...this.getProductStoreSnapshot()
|
|
1484
|
-
});
|
|
1485
1215
|
this.logInfo("processProductSyncMessages: 开始处理", { count: messages.length });
|
|
1486
1216
|
const deleteIds = [];
|
|
1487
1217
|
const bodyUpdates = /* @__PURE__ */ new Map();
|
|
@@ -1536,13 +1266,6 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
|
|
|
1536
1266
|
const uniqueDeleteIds = [...new Set(deleteIds)];
|
|
1537
1267
|
const uniqueSSEIds = [...new Set(sseRefreshIds)];
|
|
1538
1268
|
const uniquePriceIds = [...new Set(priceRefreshIds)];
|
|
1539
|
-
this.pushProductFlowLog("processProductSyncMessages.parsed", {
|
|
1540
|
-
deleteIds: uniqueDeleteIds,
|
|
1541
|
-
bodyUpdateIds: [...bodyUpdates.keys()],
|
|
1542
|
-
sseRefreshIds: uniqueSSEIds,
|
|
1543
|
-
priceRefreshIds: uniquePriceIds,
|
|
1544
|
-
shouldClearPriceCache
|
|
1545
|
-
});
|
|
1546
1269
|
if (uniqueDeleteIds.length > 0) {
|
|
1547
1270
|
await this.removeProductsByIds(uniqueDeleteIds);
|
|
1548
1271
|
}
|
|
@@ -1586,10 +1309,6 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
|
|
|
1586
1309
|
"pubsub.processProductSyncMessages",
|
|
1587
1310
|
patchMergeActions
|
|
1588
1311
|
);
|
|
1589
|
-
this.pushProductFlowLog("processProductSyncMessages.patchDone", {
|
|
1590
|
-
patchCount: patchProducts.length,
|
|
1591
|
-
patchProductIds: patchProducts.map((p) => p.id)
|
|
1592
|
-
});
|
|
1593
1312
|
}
|
|
1594
1313
|
if (storeMutated) {
|
|
1595
1314
|
this.core.effects.emit(import_types.ProductsHooks.onProductsChanged, this.store.list);
|
|
@@ -1609,7 +1328,6 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
|
|
|
1609
1328
|
});
|
|
1610
1329
|
const hasChanges = uniqueDeleteIds.length > 0 || allChangedIds.length > 0 || shouldClearPriceCache;
|
|
1611
1330
|
if (!hasChanges) {
|
|
1612
|
-
this.pushProductFlowLog("processProductSyncMessages.noChanges", {});
|
|
1613
1331
|
this.logInfo("processProductSyncMessages: 没有变更,不触发 onProductsSyncCompleted");
|
|
1614
1332
|
return;
|
|
1615
1333
|
}
|
|
@@ -1625,14 +1343,6 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
|
|
|
1625
1343
|
await this.core.effects.emit(import_types.ProductsHooks.onProductsSyncCompleted, {
|
|
1626
1344
|
changedIds: allChangedIds
|
|
1627
1345
|
});
|
|
1628
|
-
this.pushProductFlowLog("processProductSyncMessages.done", {
|
|
1629
|
-
deleteCount: uniqueDeleteIds.length,
|
|
1630
|
-
bodyUpdateCount: bodyUpdates.size,
|
|
1631
|
-
sseRefreshCount: uniqueSSEIds.length,
|
|
1632
|
-
allChangedIds,
|
|
1633
|
-
shouldClearPriceCache,
|
|
1634
|
-
...this.getProductStoreSnapshot()
|
|
1635
|
-
});
|
|
1636
1346
|
}
|
|
1637
1347
|
/**
|
|
1638
1348
|
* 通过 SSE 按 ids 增量拉取商品数据
|
|
@@ -1672,12 +1382,6 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
|
|
|
1672
1382
|
*/
|
|
1673
1383
|
async applyBodyUpdatesToStore(bodyUpdates, options) {
|
|
1674
1384
|
const changedProductIds = [...bodyUpdates.keys()];
|
|
1675
|
-
this.pushProductFlowLog("applyBodyUpdatesToStore.start", {
|
|
1676
|
-
changedProductIds,
|
|
1677
|
-
count: bodyUpdates.size,
|
|
1678
|
-
skipIndexDB: !!(options == null ? void 0 : options.skipIndexDB),
|
|
1679
|
-
...this.getProductStoreSnapshot()
|
|
1680
|
-
});
|
|
1681
1385
|
this.logInfo("applyBodyUpdatesToStore: 开始", { count: bodyUpdates.size });
|
|
1682
1386
|
let updatedCount = 0;
|
|
1683
1387
|
let newCount = 0;
|
|
@@ -1710,13 +1414,6 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
|
|
|
1710
1414
|
if (!(options == null ? void 0 : options.skipEmit)) {
|
|
1711
1415
|
this.core.effects.emit(import_types.ProductsHooks.onProductsChanged, this.store.list);
|
|
1712
1416
|
}
|
|
1713
|
-
this.pushProductFlowLog("applyBodyUpdatesToStore.done", {
|
|
1714
|
-
changedProductIds,
|
|
1715
|
-
updatedCount,
|
|
1716
|
-
newCount,
|
|
1717
|
-
totalCount: this.store.list.length,
|
|
1718
|
-
indexDbPatchCount: (options == null ? void 0 : options.skipIndexDB) ? 0 : changedProducts.length
|
|
1719
|
-
});
|
|
1720
1417
|
this.logInfo("applyBodyUpdatesToStore: 完成", {
|
|
1721
1418
|
updatedCount,
|
|
1722
1419
|
newCount,
|
|
@@ -1756,12 +1453,6 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
|
|
|
1756
1453
|
}
|
|
1757
1454
|
const updatedCount = freshProducts.length - newCount;
|
|
1758
1455
|
const changedProductIds = freshProducts.map((p) => p.id);
|
|
1759
|
-
this.pushProductFlowLog("mergeProductsToStore.start", {
|
|
1760
|
-
changedProductIds,
|
|
1761
|
-
incomingCount: freshProducts.length,
|
|
1762
|
-
skipIndexDB: !!(options == null ? void 0 : options.skipIndexDB),
|
|
1763
|
-
...this.getProductStoreSnapshot()
|
|
1764
|
-
});
|
|
1765
1456
|
this.store.list = updatedList;
|
|
1766
1457
|
this.syncProductsMap();
|
|
1767
1458
|
if (!(options == null ? void 0 : options.skipIndexDB)) {
|
|
@@ -1770,13 +1461,6 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
|
|
|
1770
1461
|
if (!(options == null ? void 0 : options.skipEmit)) {
|
|
1771
1462
|
this.core.effects.emit(import_types.ProductsHooks.onProductsChanged, this.store.list);
|
|
1772
1463
|
}
|
|
1773
|
-
this.pushProductFlowLog("mergeProductsToStore.done", {
|
|
1774
|
-
changedProductIds,
|
|
1775
|
-
updatedCount,
|
|
1776
|
-
newCount,
|
|
1777
|
-
totalCount: this.store.list.length,
|
|
1778
|
-
indexDbPatchCount: (options == null ? void 0 : options.skipIndexDB) ? 0 : changedProducts.length
|
|
1779
|
-
});
|
|
1780
1464
|
this.logInfo("mergeProductsToStore: 合并完成", {
|
|
1781
1465
|
updatedCount,
|
|
1782
1466
|
newCount,
|
|
@@ -1795,18 +1479,8 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
|
|
|
1795
1479
|
const elapsedSincePreload = now - this.lastPreloadCompletedAtMs;
|
|
1796
1480
|
const elapsedSinceFullFetch = now - this.lastServerFullFetchAtMs;
|
|
1797
1481
|
if (this.lastPreloadCompletedAtMs > 0 && elapsedSincePreload < PRODUCT_SILENT_REFRESH_MIN_INTERVAL_MS || this.lastServerFullFetchAtMs > 0 && elapsedSinceFullFetch < PRODUCT_SILENT_REFRESH_MIN_INTERVAL_MS) {
|
|
1798
|
-
this.pushProductFlowLog("silentRefresh.skipped", {
|
|
1799
|
-
elapsedSincePreloadMs: this.lastPreloadCompletedAtMs > 0 ? elapsedSincePreload : null,
|
|
1800
|
-
elapsedSinceFullFetchMs: this.lastServerFullFetchAtMs > 0 ? elapsedSinceFullFetch : null,
|
|
1801
|
-
minIntervalMs: PRODUCT_SILENT_REFRESH_MIN_INTERVAL_MS,
|
|
1802
|
-
...this.getProductStoreSnapshot()
|
|
1803
|
-
});
|
|
1804
1482
|
return this.store.list;
|
|
1805
1483
|
}
|
|
1806
|
-
this.pushProductFlowLog("silentRefresh.start", {
|
|
1807
|
-
note: "会调用 loadProductsByServer → replaceProductsSnapshotInIndexDB",
|
|
1808
|
-
...this.getProductStoreSnapshot()
|
|
1809
|
-
});
|
|
1810
1484
|
this.logInfo("silentRefresh 开始");
|
|
1811
1485
|
try {
|
|
1812
1486
|
const products = await this.loadProductsByServer();
|
|
@@ -1816,24 +1490,17 @@ var ProductsModule = class extends import_BaseModule.BaseModule {
|
|
|
1816
1490
|
this.clearPriceCache();
|
|
1817
1491
|
this.core.effects.emit(import_types.ProductsHooks.onProductsChanged, this.store.list);
|
|
1818
1492
|
await this.core.effects.emit(import_types.ProductsHooks.onProductsSyncCompleted, null);
|
|
1819
|
-
this.pushProductFlowLog("silentRefresh.done", {
|
|
1820
|
-
productCount: products.length,
|
|
1821
|
-
durationMs: Math.round(performance.now() - t0),
|
|
1822
|
-
...this.getProductStoreSnapshot()
|
|
1823
|
-
});
|
|
1824
1493
|
this.logInfo("silentRefresh 完成", {
|
|
1825
1494
|
productCount: products.length,
|
|
1826
1495
|
duration: `${Math.round(performance.now() - t0)}ms`
|
|
1827
1496
|
});
|
|
1828
1497
|
} else {
|
|
1829
|
-
this.pushProductFlowLog("silentRefresh.empty", {});
|
|
1830
1498
|
this.logWarning("silentRefresh: 服务器未返回数据");
|
|
1831
1499
|
}
|
|
1832
1500
|
(0, import_product.perfMark)("silentRefresh", performance.now() - t0, { count: this.store.list.length });
|
|
1833
1501
|
return this.store.list;
|
|
1834
1502
|
} catch (error) {
|
|
1835
1503
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
1836
|
-
this.pushProductFlowLog("silentRefresh.failed", { error: errorMessage });
|
|
1837
1504
|
this.logError("silentRefresh 失败", {
|
|
1838
1505
|
duration: `${Math.round(performance.now() - t0)}ms`,
|
|
1839
1506
|
error: errorMessage
|