@fle-sdk/event-tracking-web 1.2.5 → 1.2.6
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/lib/index.esm.js +1219 -1463
- package/lib/index.esm.min.js +1 -1
- package/lib/index.js +1219 -1463
- package/lib/index.min.js +1 -1
- package/lib/types/batch-sender.d.ts +48 -0
- package/lib/types/device-manager.d.ts +16 -0
- package/lib/types/exposure.d.ts +33 -0
- package/lib/types/index.d.ts +14 -224
- package/lib/types/page-duration.d.ts +23 -0
- package/lib/types/pending-requests.d.ts +45 -0
- package/lib/types/type.d.ts +5 -1
- package/package.json +1 -1
package/lib/index.esm.js
CHANGED
|
@@ -1230,1505 +1230,1471 @@ function () {
|
|
|
1230
1230
|
return WebTrackingTools;
|
|
1231
1231
|
}();
|
|
1232
1232
|
|
|
1233
|
-
var
|
|
1233
|
+
var ExposureTracker =
|
|
1234
1234
|
/** @class */
|
|
1235
|
-
function (
|
|
1236
|
-
|
|
1235
|
+
function () {
|
|
1236
|
+
function ExposureTracker(config, callbacks) {
|
|
1237
|
+
this.observer = null;
|
|
1238
|
+
this.mutationObserver = null;
|
|
1239
|
+
this.elementsMap = new Map();
|
|
1240
|
+
this.config = config;
|
|
1241
|
+
this.callbacks = callbacks;
|
|
1242
|
+
}
|
|
1237
1243
|
|
|
1238
|
-
function
|
|
1239
|
-
|
|
1244
|
+
ExposureTracker.prototype.updateConfig = function (config) {
|
|
1245
|
+
this.config = __assign(__assign({}, this.config), config);
|
|
1246
|
+
};
|
|
1240
1247
|
|
|
1248
|
+
ExposureTracker.prototype.init = function () {
|
|
1249
|
+
var _this = this;
|
|
1241
1250
|
|
|
1242
|
-
|
|
1251
|
+
if (!this.config.autoTrackExposure) {
|
|
1252
|
+
return;
|
|
1253
|
+
}
|
|
1243
1254
|
|
|
1244
|
-
|
|
1255
|
+
if (!("IntersectionObserver" in window)) {
|
|
1256
|
+
if (this.config.showLog) {
|
|
1257
|
+
this.callbacks.printLog("当前浏览器不支持 IntersectionObserver,无法启用曝光埋点");
|
|
1258
|
+
}
|
|
1245
1259
|
|
|
1246
|
-
|
|
1260
|
+
return;
|
|
1261
|
+
}
|
|
1247
1262
|
|
|
1248
|
-
|
|
1263
|
+
this.observer = new IntersectionObserver(function (entries) {
|
|
1264
|
+
entries.forEach(function (entry) {
|
|
1265
|
+
var element = entry.target;
|
|
1249
1266
|
|
|
1250
|
-
|
|
1267
|
+
var elementInfo = _this.elementsMap.get(element);
|
|
1251
1268
|
|
|
1252
|
-
|
|
1269
|
+
if (!elementInfo) {
|
|
1270
|
+
return;
|
|
1271
|
+
}
|
|
1253
1272
|
|
|
1254
|
-
|
|
1273
|
+
var exposureTime = _this.config.exposureTime || 500;
|
|
1255
1274
|
|
|
1256
|
-
|
|
1275
|
+
if (entry.isIntersecting) {
|
|
1276
|
+
elementInfo.isVisible = true;
|
|
1277
|
+
elementInfo.visibleStartTime = _this.callbacks.getTimeStamp();
|
|
1257
1278
|
|
|
1258
|
-
|
|
1279
|
+
if (elementInfo.exposureTimer) {
|
|
1280
|
+
clearTimeout(elementInfo.exposureTimer);
|
|
1281
|
+
}
|
|
1259
1282
|
|
|
1260
|
-
|
|
1283
|
+
elementInfo.exposureTimer = window.setTimeout(function () {
|
|
1284
|
+
if (elementInfo.isVisible) {
|
|
1285
|
+
var exposureScreenIndex = _this.calculateexposureScreenIndex(element);
|
|
1261
1286
|
|
|
1262
|
-
|
|
1287
|
+
_this.callbacks.reportExposure(element, exposureScreenIndex);
|
|
1288
|
+
}
|
|
1289
|
+
}, exposureTime);
|
|
1290
|
+
} else {
|
|
1291
|
+
elementInfo.isVisible = false;
|
|
1263
1292
|
|
|
1264
|
-
|
|
1293
|
+
if (elementInfo.exposureTimer) {
|
|
1294
|
+
clearTimeout(elementInfo.exposureTimer);
|
|
1295
|
+
elementInfo.exposureTimer = null;
|
|
1296
|
+
}
|
|
1297
|
+
}
|
|
1298
|
+
});
|
|
1299
|
+
}, {
|
|
1300
|
+
threshold: this.config.exposureThreshold || 0.5
|
|
1301
|
+
});
|
|
1302
|
+
this.observeExposureElements();
|
|
1303
|
+
this.initMutationObserver();
|
|
1304
|
+
};
|
|
1265
1305
|
|
|
1266
|
-
|
|
1306
|
+
ExposureTracker.prototype.stop = function () {
|
|
1307
|
+
if (this.observer) {
|
|
1308
|
+
this.observer.disconnect();
|
|
1309
|
+
this.observer = null;
|
|
1310
|
+
this.elementsMap.forEach(function (elementInfo) {
|
|
1311
|
+
if (elementInfo.exposureTimer) {
|
|
1312
|
+
clearTimeout(elementInfo.exposureTimer);
|
|
1313
|
+
}
|
|
1314
|
+
});
|
|
1315
|
+
this.elementsMap.clear();
|
|
1316
|
+
}
|
|
1267
1317
|
|
|
1268
|
-
|
|
1318
|
+
if (this.mutationObserver) {
|
|
1319
|
+
this.mutationObserver.disconnect();
|
|
1320
|
+
this.mutationObserver = null;
|
|
1321
|
+
}
|
|
1269
1322
|
|
|
1270
|
-
|
|
1323
|
+
if (this.config.showLog) {
|
|
1324
|
+
this.callbacks.printLog("曝光监听已停止");
|
|
1325
|
+
}
|
|
1326
|
+
};
|
|
1271
1327
|
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
* @param {object} InitParams [初始化参数]
|
|
1282
|
-
*/
|
|
1328
|
+
ExposureTracker.prototype.addExposureElement = function (element) {
|
|
1329
|
+
if (!this.elementsMap.has(element)) {
|
|
1330
|
+
this.elementsMap.set(element, {
|
|
1331
|
+
element: element,
|
|
1332
|
+
visibleStartTime: 0,
|
|
1333
|
+
exposureCount: 0,
|
|
1334
|
+
isVisible: false,
|
|
1335
|
+
exposureTimer: null
|
|
1336
|
+
});
|
|
1283
1337
|
|
|
1284
|
-
|
|
1285
|
-
|
|
1338
|
+
if (this.observer) {
|
|
1339
|
+
this.observer.observe(element);
|
|
1340
|
+
}
|
|
1341
|
+
}
|
|
1342
|
+
};
|
|
1286
1343
|
|
|
1287
|
-
|
|
1288
|
-
|
|
1344
|
+
ExposureTracker.prototype.observeExposureElements = function () {
|
|
1345
|
+
var _this = this;
|
|
1289
1346
|
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
} else {
|
|
1294
|
-
_this.pageKey = pathname.replace(/\//g, "_").substring(1);
|
|
1295
|
-
_this.useCustomPageKey = false;
|
|
1296
|
-
}
|
|
1347
|
+
if (!this.observer) {
|
|
1348
|
+
return;
|
|
1349
|
+
}
|
|
1297
1350
|
|
|
1298
|
-
|
|
1351
|
+
var elements = document.querySelectorAll('[data-exposure="true"]');
|
|
1352
|
+
elements.forEach(function (element) {
|
|
1353
|
+
_this.addExposureElement(element);
|
|
1354
|
+
});
|
|
1299
1355
|
|
|
1300
|
-
|
|
1356
|
+
if (this.config.showLog && elements.length > 0) {
|
|
1357
|
+
this.callbacks.printLog("\u5DF2\u76D1\u542C " + elements.length + " \u4E2A\u66DD\u5149\u5143\u7D20");
|
|
1358
|
+
}
|
|
1359
|
+
};
|
|
1301
1360
|
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
}
|
|
1361
|
+
ExposureTracker.prototype.initMutationObserver = function () {
|
|
1362
|
+
var _this = this;
|
|
1305
1363
|
|
|
1306
|
-
|
|
1364
|
+
if (!("MutationObserver" in window)) {
|
|
1365
|
+
if (this.config.showLog) {
|
|
1366
|
+
this.callbacks.printLog("当前浏览器不支持 MutationObserver,无法监听动态添加的曝光元素");
|
|
1367
|
+
}
|
|
1307
1368
|
|
|
1369
|
+
return;
|
|
1370
|
+
}
|
|
1308
1371
|
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1372
|
+
this.mutationObserver = new MutationObserver(function (mutations) {
|
|
1373
|
+
mutations.forEach(function (mutation) {
|
|
1374
|
+
mutation.addedNodes.forEach(function (node) {
|
|
1375
|
+
if (node.nodeType === Node.ELEMENT_NODE) {
|
|
1376
|
+
var element = node;
|
|
1312
1377
|
|
|
1378
|
+
if (element.hasAttribute("data-exposure") && element.getAttribute("data-exposure") === "true") {
|
|
1379
|
+
_this.addExposureElement(element);
|
|
1380
|
+
} else {
|
|
1381
|
+
var exposureElements = element.querySelectorAll('[data-exposure="true"]');
|
|
1382
|
+
exposureElements.forEach(function (exposureElement) {
|
|
1383
|
+
_this.addExposureElement(exposureElement);
|
|
1384
|
+
});
|
|
1385
|
+
}
|
|
1386
|
+
}
|
|
1387
|
+
});
|
|
1388
|
+
});
|
|
1389
|
+
});
|
|
1390
|
+
this.mutationObserver.observe(document.body, {
|
|
1391
|
+
childList: true,
|
|
1392
|
+
subtree: true
|
|
1393
|
+
});
|
|
1313
1394
|
|
|
1314
|
-
|
|
1395
|
+
if (this.config.showLog) {
|
|
1396
|
+
this.callbacks.printLog("MutationObserver 已启动,监听动态添加的曝光元素");
|
|
1397
|
+
}
|
|
1398
|
+
};
|
|
1315
1399
|
|
|
1400
|
+
ExposureTracker.prototype.calculateexposureScreenIndex = function (element) {
|
|
1401
|
+
var rect = element.getBoundingClientRect();
|
|
1402
|
+
var viewportHeight = window.innerHeight || document.documentElement.clientHeight;
|
|
1403
|
+
var scrollTop = window.scrollY || document.documentElement.scrollTop;
|
|
1404
|
+
var elementPageTop = rect.top + scrollTop;
|
|
1316
1405
|
|
|
1317
|
-
|
|
1406
|
+
if (elementPageTop <= 0) {
|
|
1407
|
+
return 1;
|
|
1408
|
+
}
|
|
1318
1409
|
|
|
1410
|
+
return Math.ceil(elementPageTop / viewportHeight);
|
|
1411
|
+
};
|
|
1319
1412
|
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1413
|
+
ExposureTracker.prototype.getElementInfo = function (element) {
|
|
1414
|
+
return this.elementsMap.get(element);
|
|
1415
|
+
};
|
|
1323
1416
|
|
|
1417
|
+
ExposureTracker.prototype.incrementExposureCount = function (element) {
|
|
1418
|
+
var elementInfo = this.elementsMap.get(element);
|
|
1324
1419
|
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
/**
|
|
1330
|
-
* @description 预置参数
|
|
1331
|
-
* @param {object} PresetParams [预置参数]
|
|
1332
|
-
*/
|
|
1420
|
+
if (elementInfo) {
|
|
1421
|
+
elementInfo.exposureCount++;
|
|
1422
|
+
}
|
|
1423
|
+
};
|
|
1333
1424
|
|
|
1425
|
+
ExposureTracker.prototype.clearExposureTimer = function (element) {
|
|
1426
|
+
var elementInfo = this.elementsMap.get(element);
|
|
1334
1427
|
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
// 恢复自动生成
|
|
1341
|
-
_this.useCustomPageKey = false;
|
|
1342
|
-
var pathname = window.location.pathname;
|
|
1343
|
-
_this.pageKey = pathname.replace(/\//g, "_").substring(1);
|
|
1344
|
-
} else {
|
|
1345
|
-
_this.pageKey = presetParams.pageKey;
|
|
1346
|
-
_this.useCustomPageKey = true;
|
|
1347
|
-
}
|
|
1348
|
-
}
|
|
1428
|
+
if (elementInfo && elementInfo.exposureTimer) {
|
|
1429
|
+
clearTimeout(elementInfo.exposureTimer);
|
|
1430
|
+
elementInfo.exposureTimer = null;
|
|
1431
|
+
}
|
|
1432
|
+
};
|
|
1349
1433
|
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
if (key === 'pageKey') return;
|
|
1434
|
+
return ExposureTracker;
|
|
1435
|
+
}();
|
|
1353
1436
|
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1437
|
+
var PageDurationTracker =
|
|
1438
|
+
/** @class */
|
|
1439
|
+
function () {
|
|
1440
|
+
function PageDurationTracker(config, callbacks) {
|
|
1441
|
+
this.timer = null;
|
|
1442
|
+
this.config = config;
|
|
1443
|
+
this.callbacks = callbacks;
|
|
1444
|
+
}
|
|
1357
1445
|
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
_this.printLog("\u914D\u7F6E\u53C2\u6570\u9A8C\u8BC1\u5931\u8D25: " + String(key) + " = " + val + ", \u539F\u56E0: " + validationResult.message);
|
|
1362
|
-
}
|
|
1363
|
-
}
|
|
1364
|
-
});
|
|
1365
|
-
}
|
|
1446
|
+
PageDurationTracker.prototype.updateConfig = function (config) {
|
|
1447
|
+
this.config = __assign(__assign({}, this.config), config);
|
|
1448
|
+
};
|
|
1366
1449
|
|
|
1367
|
-
|
|
1368
|
-
|
|
1450
|
+
PageDurationTracker.prototype.start = function () {
|
|
1451
|
+
var _this = this;
|
|
1369
1452
|
|
|
1370
|
-
|
|
1371
|
-
|
|
1453
|
+
this.stop();
|
|
1454
|
+
var interval = this.config.pageDurationInterval || 30000;
|
|
1372
1455
|
|
|
1456
|
+
if (interval <= 0) {
|
|
1457
|
+
if (this.config.showLog) {
|
|
1458
|
+
this.callbacks.printLog("定时上报间隔时间无效,已禁用定时上报");
|
|
1459
|
+
}
|
|
1373
1460
|
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
_this.listener();
|
|
1377
|
-
} else {
|
|
1378
|
-
// 取消监听
|
|
1379
|
-
_this.unlistener();
|
|
1380
|
-
} // 处理定时上报配置
|
|
1461
|
+
return;
|
|
1462
|
+
}
|
|
1381
1463
|
|
|
1464
|
+
this.timer = window.setInterval(function () {
|
|
1465
|
+
if (document.visibilityState === "visible") {
|
|
1466
|
+
_this.callbacks.track(interval, {
|
|
1467
|
+
desc: "定时上报页面停留时长"
|
|
1468
|
+
}, true).catch(function (err) {
|
|
1469
|
+
if (_this.config.showLog) {
|
|
1470
|
+
_this.callbacks.printLog("\u5B9A\u65F6\u4E0A\u62A5\u9875\u9762\u505C\u7559\u65F6\u957F\u5931\u8D25: " + err);
|
|
1471
|
+
}
|
|
1472
|
+
});
|
|
1473
|
+
}
|
|
1474
|
+
}, interval);
|
|
1382
1475
|
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
} // 处理曝光监听配置
|
|
1476
|
+
if (this.config.showLog) {
|
|
1477
|
+
this.callbacks.printLog("\u5B9A\u65F6\u4E0A\u62A5\u9875\u9762\u505C\u7559\u65F6\u957F\u5DF2\u542F\u52A8\uFF0C\u95F4\u9694: " + interval + "ms");
|
|
1478
|
+
}
|
|
1479
|
+
};
|
|
1388
1480
|
|
|
1481
|
+
PageDurationTracker.prototype.stop = function () {
|
|
1482
|
+
if (this.timer !== null) {
|
|
1483
|
+
clearInterval(this.timer);
|
|
1484
|
+
this.timer = null;
|
|
1389
1485
|
|
|
1390
|
-
if (
|
|
1391
|
-
|
|
1392
|
-
} else {
|
|
1393
|
-
_this.stopExposureObserver();
|
|
1486
|
+
if (this.config.showLog) {
|
|
1487
|
+
this.callbacks.printLog("定时上报页面停留时长已停止");
|
|
1394
1488
|
}
|
|
1395
|
-
}
|
|
1396
|
-
|
|
1397
|
-
* @description 验证配置参数
|
|
1398
|
-
* @param key 参数名
|
|
1399
|
-
* @param value 参数值
|
|
1400
|
-
* @returns 验证结果
|
|
1401
|
-
*/
|
|
1489
|
+
}
|
|
1490
|
+
};
|
|
1402
1491
|
|
|
1492
|
+
PageDurationTracker.prototype.calculateDuration = function (customDuration) {
|
|
1493
|
+
if (customDuration !== undefined && customDuration !== null) {
|
|
1494
|
+
return Math.max(customDuration, 0);
|
|
1495
|
+
}
|
|
1403
1496
|
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
valid: false,
|
|
1410
|
-
message: 'sampleRate 必须是 0-1 之间的数字'
|
|
1411
|
-
};
|
|
1412
|
-
}
|
|
1497
|
+
var time = this.callbacks.getCookie("retainedStartTime");
|
|
1498
|
+
var retainedStartTime = time ? +time : this.callbacks.getTimeStamp();
|
|
1499
|
+
var currentTime = this.callbacks.getTimeStamp();
|
|
1500
|
+
return Math.max(currentTime - retainedStartTime, 0);
|
|
1501
|
+
};
|
|
1413
1502
|
|
|
1414
|
-
|
|
1503
|
+
return PageDurationTracker;
|
|
1504
|
+
}();
|
|
1415
1505
|
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
return {
|
|
1419
|
-
valid: false,
|
|
1420
|
-
message: 'sendTimeout 必须是大于 0 的数字'
|
|
1421
|
-
};
|
|
1422
|
-
}
|
|
1506
|
+
var BATCH_QUEUE_STORAGE_KEY = "web_tracking_batch_queue";
|
|
1507
|
+
var MAX_STORAGE_SIZE = 4 * 1024 * 1024;
|
|
1423
1508
|
|
|
1424
|
-
|
|
1509
|
+
var BatchSender =
|
|
1510
|
+
/** @class */
|
|
1511
|
+
function () {
|
|
1512
|
+
function BatchSender(config, callbacks) {
|
|
1513
|
+
this.timer = null;
|
|
1514
|
+
this.config = config;
|
|
1515
|
+
this.callbacks = callbacks;
|
|
1516
|
+
}
|
|
1425
1517
|
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
valid: false,
|
|
1430
|
-
message: 'batchInterval 必须是大于 0 的数字'
|
|
1431
|
-
};
|
|
1432
|
-
}
|
|
1518
|
+
BatchSender.prototype.updateConfig = function (config) {
|
|
1519
|
+
this.config = __assign(__assign({}, this.config), config);
|
|
1520
|
+
};
|
|
1433
1521
|
|
|
1434
|
-
|
|
1522
|
+
BatchSender.prototype.addToQueue = function (params) {
|
|
1523
|
+
var _this = this;
|
|
1435
1524
|
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
valid: false,
|
|
1440
|
-
message: 'batchMaxSize 必须是大于 0 的整数'
|
|
1441
|
-
};
|
|
1442
|
-
}
|
|
1525
|
+
if (!this.config.batchSend) {
|
|
1526
|
+
return;
|
|
1527
|
+
}
|
|
1443
1528
|
|
|
1444
|
-
|
|
1529
|
+
if (!this.callbacks.shouldSample()) {
|
|
1530
|
+
if (this.config.showLog) {
|
|
1531
|
+
this.callbacks.printLog("数据已采样跳过(批量模式)");
|
|
1532
|
+
}
|
|
1445
1533
|
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
return {
|
|
1449
|
-
valid: false,
|
|
1450
|
-
message: 'pendingRequestsMaxSize 必须是大于 0 的整数'
|
|
1451
|
-
};
|
|
1452
|
-
}
|
|
1534
|
+
return;
|
|
1535
|
+
}
|
|
1453
1536
|
|
|
1454
|
-
|
|
1537
|
+
var currentQueue = this.getQueueFromStorage();
|
|
1538
|
+
currentQueue.push(params);
|
|
1539
|
+
this.saveQueueToStorage(currentQueue);
|
|
1455
1540
|
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
message: 'pageDurationInterval 必须是大于 0 的数字'
|
|
1461
|
-
};
|
|
1462
|
-
}
|
|
1541
|
+
if (currentQueue.length >= this.config.batchMaxSize) {
|
|
1542
|
+
this.flushQueue();
|
|
1543
|
+
return;
|
|
1544
|
+
}
|
|
1463
1545
|
|
|
1464
|
-
|
|
1546
|
+
if (!this.timer) {
|
|
1547
|
+
this.timer = window.setTimeout(function () {
|
|
1548
|
+
_this.flushQueue();
|
|
1465
1549
|
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
message: 'sendMethod 必须是 auto、xhr 或 beacon'
|
|
1471
|
-
};
|
|
1472
|
-
}
|
|
1550
|
+
_this.timer = null;
|
|
1551
|
+
}, this.config.batchInterval);
|
|
1552
|
+
}
|
|
1553
|
+
};
|
|
1473
1554
|
|
|
1474
|
-
|
|
1555
|
+
BatchSender.prototype.clearTimer = function () {
|
|
1556
|
+
if (this.timer !== null) {
|
|
1557
|
+
clearTimeout(this.timer);
|
|
1558
|
+
this.timer = null;
|
|
1559
|
+
}
|
|
1560
|
+
};
|
|
1475
1561
|
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
return {
|
|
1479
|
-
valid: false,
|
|
1480
|
-
message: 'exposureThreshold 必须是 0-1 之间的数字'
|
|
1481
|
-
};
|
|
1482
|
-
}
|
|
1562
|
+
BatchSender.prototype.clearQueue = function () {
|
|
1563
|
+
this.callbacks.setLocalStorage(BATCH_QUEUE_STORAGE_KEY, "[]");
|
|
1483
1564
|
|
|
1484
|
-
|
|
1565
|
+
if (this.config.showLog) {
|
|
1566
|
+
this.callbacks.printLog("批量队列已清空");
|
|
1567
|
+
}
|
|
1568
|
+
};
|
|
1485
1569
|
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
return {
|
|
1489
|
-
valid: false,
|
|
1490
|
-
message: 'exposureTime 必须是大于 0 的数字'
|
|
1491
|
-
};
|
|
1492
|
-
}
|
|
1570
|
+
BatchSender.prototype.restoreQueue = function () {
|
|
1571
|
+
var queue = this.getQueueFromStorage();
|
|
1493
1572
|
|
|
1494
|
-
|
|
1573
|
+
if (queue.length > 0 && this.config.showLog) {
|
|
1574
|
+
this.callbacks.printLog("\u4ECE LocalStorage \u6062\u590D " + queue.length + " \u6761\u6279\u91CF\u6570\u636E");
|
|
1575
|
+
}
|
|
1576
|
+
};
|
|
1495
1577
|
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
valid: false,
|
|
1500
|
-
message: 'exposureNum 必须是大于 0 的整数或不限制'
|
|
1501
|
-
};
|
|
1502
|
-
}
|
|
1578
|
+
BatchSender.prototype.getQueueFromStorage = function () {
|
|
1579
|
+
try {
|
|
1580
|
+
var storedQueue = this.callbacks.getLocalStorage(BATCH_QUEUE_STORAGE_KEY);
|
|
1503
1581
|
|
|
1504
|
-
|
|
1582
|
+
if (storedQueue) {
|
|
1583
|
+
var parsedQueue = JSON.parse(storedQueue);
|
|
1505
1584
|
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
valid: false,
|
|
1515
|
-
message: key + " \u5FC5\u987B\u662F\u5E03\u5C14\u503C"
|
|
1516
|
-
};
|
|
1517
|
-
}
|
|
1585
|
+
if (Array.isArray(parsedQueue)) {
|
|
1586
|
+
return parsedQueue;
|
|
1587
|
+
}
|
|
1588
|
+
}
|
|
1589
|
+
} catch (e) {
|
|
1590
|
+
this.callbacks.printLog("\u8BFB\u53D6\u6279\u91CF\u961F\u5217\u5931\u8D25: " + e);
|
|
1591
|
+
this.callbacks.setLocalStorage(BATCH_QUEUE_STORAGE_KEY, "[]");
|
|
1592
|
+
}
|
|
1518
1593
|
|
|
1519
|
-
|
|
1594
|
+
return [];
|
|
1595
|
+
};
|
|
1520
1596
|
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
return {
|
|
1525
|
-
valid: false,
|
|
1526
|
-
message: key + " \u5FC5\u987B\u662F\u5BF9\u8C61\u6216 null"
|
|
1527
|
-
};
|
|
1528
|
-
}
|
|
1597
|
+
BatchSender.prototype.saveQueueToStorage = function (queue) {
|
|
1598
|
+
try {
|
|
1599
|
+
var queueString = JSON.stringify(queue);
|
|
1529
1600
|
|
|
1530
|
-
|
|
1601
|
+
if (queueString.length > MAX_STORAGE_SIZE) {
|
|
1602
|
+
var maxItems = Math.floor(queue.length * 0.8);
|
|
1603
|
+
var trimmedQueue = queue.slice(-maxItems);
|
|
1604
|
+
this.callbacks.printLog("\u961F\u5217\u8FC7\u5927\uFF0C\u5DF2\u622A\u65AD\u4FDD\u7559\u6700\u65B0 " + maxItems + " \u6761\u6570\u636E\uFF08\u9650\u5236: " + MAX_STORAGE_SIZE / 1024 / 1024 + "MB\uFF09");
|
|
1605
|
+
this.callbacks.setLocalStorage(BATCH_QUEUE_STORAGE_KEY, JSON.stringify(trimmedQueue));
|
|
1606
|
+
} else {
|
|
1607
|
+
this.callbacks.setLocalStorage(BATCH_QUEUE_STORAGE_KEY, queueString);
|
|
1608
|
+
}
|
|
1609
|
+
} catch (e) {
|
|
1610
|
+
this.callbacks.printLog("\u4FDD\u5B58\u6279\u91CF\u961F\u5217\u5230 LocalStorage \u5931\u8D25: " + e);
|
|
1611
|
+
}
|
|
1612
|
+
};
|
|
1531
1613
|
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1614
|
+
BatchSender.prototype.flushQueue = function () {
|
|
1615
|
+
var batchQueue = this.getQueueFromStorage();
|
|
1616
|
+
if (batchQueue.length === 0) return;
|
|
1617
|
+
var currentTime = this.callbacks.getTimeStamp();
|
|
1618
|
+
var readyToSend = batchQueue.filter(function (item) {
|
|
1619
|
+
if (!item._nextRetryTime) {
|
|
1620
|
+
return true;
|
|
1621
|
+
}
|
|
1539
1622
|
|
|
1540
|
-
|
|
1623
|
+
return item._nextRetryTime <= currentTime;
|
|
1624
|
+
});
|
|
1541
1625
|
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
message: 'platform 必须是字符串'
|
|
1547
|
-
};
|
|
1548
|
-
}
|
|
1626
|
+
if (readyToSend.length === 0) {
|
|
1627
|
+
if (this.config.showLog) {
|
|
1628
|
+
this.callbacks.printLog("\u6279\u91CF\u961F\u5217\u4E2D\u6709 " + batchQueue.length + " \u6761\u6570\u636E\u7B49\u5F85\u91CD\u8BD5");
|
|
1629
|
+
}
|
|
1549
1630
|
|
|
1550
|
-
|
|
1631
|
+
return;
|
|
1632
|
+
}
|
|
1633
|
+
|
|
1634
|
+
var remainingQueue = batchQueue.filter(function (item) {
|
|
1635
|
+
if (!item._nextRetryTime) {
|
|
1636
|
+
return false;
|
|
1551
1637
|
}
|
|
1552
1638
|
|
|
1553
|
-
return
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
* 用户登录
|
|
1559
|
-
*/
|
|
1639
|
+
return item._nextRetryTime > currentTime;
|
|
1640
|
+
});
|
|
1641
|
+
this.saveQueueToStorage(remainingQueue);
|
|
1642
|
+
this.sendBatchData(readyToSend);
|
|
1643
|
+
};
|
|
1560
1644
|
|
|
1645
|
+
BatchSender.prototype.sendBatchData = function (data) {
|
|
1646
|
+
var _this = this;
|
|
1561
1647
|
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1648
|
+
var _a = this.config,
|
|
1649
|
+
serverUrl = _a.serverUrl,
|
|
1650
|
+
contentType = _a.contentType,
|
|
1651
|
+
showLog = _a.showLog,
|
|
1652
|
+
sendMethod = _a.sendMethod,
|
|
1653
|
+
initHeader = _a.header;
|
|
1654
|
+
|
|
1655
|
+
if (showLog) {
|
|
1656
|
+
this.callbacks.printLog("\u6279\u91CF\u53D1\u9001 " + data.length + " \u6761\u6570\u636E");
|
|
1657
|
+
data.forEach(function (item) {
|
|
1658
|
+
return _this.callbacks.printLog(JSON.stringify(item));
|
|
1659
|
+
});
|
|
1660
|
+
}
|
|
1569
1661
|
|
|
1662
|
+
var shouldUseBeacon = this.callbacks.shouldUseBeacon(sendMethod, undefined, initHeader);
|
|
1570
1663
|
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1664
|
+
if (shouldUseBeacon) {
|
|
1665
|
+
try {
|
|
1666
|
+
var blob = new Blob([JSON.stringify(data)], {
|
|
1667
|
+
type: contentType || "application/json"
|
|
1668
|
+
});
|
|
1669
|
+
var sent = navigator.sendBeacon(serverUrl, blob);
|
|
1576
1670
|
|
|
1671
|
+
if (sent) {
|
|
1672
|
+
this.saveQueueToStorage([]);
|
|
1577
1673
|
|
|
1578
|
-
|
|
1674
|
+
if (showLog) {
|
|
1675
|
+
this.callbacks.printLog("\u6279\u91CF\u53D1\u9001\u6210\u529F: " + data.length + " \u6761\u6570\u636E");
|
|
1676
|
+
}
|
|
1677
|
+
} else {
|
|
1678
|
+
this.callbacks.printLog("\u6279\u91CF\u53D1\u9001\u5931\u8D25: sendBeacon \u8FD4\u56DE false\uFF0C\u6570\u636E\u5DF2\u91CD\u65B0\u52A0\u5165\u961F\u5217");
|
|
1679
|
+
this.retryBatchData(data);
|
|
1680
|
+
}
|
|
1681
|
+
} catch (e) {
|
|
1682
|
+
this.callbacks.printLog("\u6279\u91CF\u53D1\u9001\u5931\u8D25: " + e + "\uFF0C\u6570\u636E\u5DF2\u91CD\u65B0\u52A0\u5165\u961F\u5217");
|
|
1683
|
+
this.retryBatchData(data);
|
|
1684
|
+
}
|
|
1685
|
+
} else {
|
|
1686
|
+
this.callbacks.ajax({
|
|
1687
|
+
url: serverUrl,
|
|
1688
|
+
type: "POST",
|
|
1689
|
+
data: JSON.stringify({
|
|
1690
|
+
events: data
|
|
1691
|
+
}),
|
|
1692
|
+
contentType: contentType,
|
|
1693
|
+
credentials: false,
|
|
1694
|
+
timeout: this.config.sendTimeout,
|
|
1695
|
+
cors: true,
|
|
1696
|
+
success: function success() {
|
|
1697
|
+
_this.saveQueueToStorage([]);
|
|
1698
|
+
|
|
1699
|
+
if (_this.config.showLog) {
|
|
1700
|
+
_this.callbacks.printLog("\u6279\u91CF\u53D1\u9001\u6210\u529F: " + data.length + " \u6761\u6570\u636E");
|
|
1701
|
+
}
|
|
1702
|
+
},
|
|
1703
|
+
error: function error(err) {
|
|
1704
|
+
_this.callbacks.printLog("\u6279\u91CF\u53D1\u9001\u5931\u8D25: " + err + "\uFF0C\u6570\u636E\u5DF2\u91CD\u65B0\u52A0\u5165\u961F\u5217");
|
|
1579
1705
|
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1706
|
+
_this.retryBatchData(data);
|
|
1707
|
+
}
|
|
1708
|
+
});
|
|
1709
|
+
}
|
|
1710
|
+
};
|
|
1584
1711
|
|
|
1712
|
+
BatchSender.prototype.retryBatchData = function (data) {
|
|
1713
|
+
var _this = this;
|
|
1585
1714
|
|
|
1586
|
-
|
|
1715
|
+
var currentQueue = this.getQueueFromStorage();
|
|
1587
1716
|
|
|
1717
|
+
var getEventKey = function getEventKey(item) {
|
|
1718
|
+
return item.event + "_" + item.itemKey + "_" + item.requestTime;
|
|
1719
|
+
};
|
|
1588
1720
|
|
|
1589
|
-
|
|
1721
|
+
var existingKeys = new Set(currentQueue.map(getEventKey));
|
|
1722
|
+
var maxRetryCount = 3;
|
|
1723
|
+
var currentTime = this.callbacks.getTimeStamp();
|
|
1724
|
+
var retryData = data.filter(function (item) {
|
|
1725
|
+
var key = getEventKey(item);
|
|
1590
1726
|
|
|
1727
|
+
if (existingKeys.has(key)) {
|
|
1728
|
+
return false;
|
|
1729
|
+
}
|
|
1591
1730
|
|
|
1592
|
-
|
|
1731
|
+
var retryCount = (item._retryCount || 0) + 1;
|
|
1593
1732
|
|
|
1733
|
+
if (retryCount > maxRetryCount) {
|
|
1734
|
+
if (_this.config.showLog) {
|
|
1735
|
+
_this.callbacks.printLog("\u6570\u636E\u5DF2\u8FBE\u5230\u6700\u5927\u91CD\u8BD5\u6B21\u6570\uFF0C\u653E\u5F03\u91CD\u8BD5: " + key);
|
|
1736
|
+
}
|
|
1594
1737
|
|
|
1595
|
-
|
|
1738
|
+
return false;
|
|
1739
|
+
}
|
|
1596
1740
|
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
* 清除存储的设备ID并重新生成
|
|
1603
|
-
* @returns 新的设备ID
|
|
1604
|
-
*/
|
|
1741
|
+
item._retryCount = retryCount;
|
|
1742
|
+
item._nextRetryTime = currentTime + Math.pow(2, retryCount) * 1000;
|
|
1743
|
+
existingKeys.add(key);
|
|
1744
|
+
return true;
|
|
1745
|
+
});
|
|
1605
1746
|
|
|
1747
|
+
var retryQueue = __spreadArray(__spreadArray([], retryData), currentQueue);
|
|
1606
1748
|
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
localStorage.removeItem("device_id"); // 清除内存中的设备ID
|
|
1749
|
+
var maxSize = this.config.batchMaxSize * 2;
|
|
1750
|
+
var trimmedQueue = retryQueue.length > maxSize ? retryQueue.slice(0, maxSize) : retryQueue;
|
|
1751
|
+
this.saveQueueToStorage(trimmedQueue);
|
|
1611
1752
|
|
|
1612
|
-
|
|
1753
|
+
if (this.config.showLog) {
|
|
1754
|
+
this.callbacks.printLog("\u5DF2\u5C06 " + retryData.length + " \u6761\u6570\u636E\u52A0\u5165\u91CD\u8BD5\u961F\u5217");
|
|
1755
|
+
}
|
|
1756
|
+
};
|
|
1613
1757
|
|
|
1614
|
-
|
|
1758
|
+
return BatchSender;
|
|
1759
|
+
}();
|
|
1615
1760
|
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1761
|
+
var DeviceManager =
|
|
1762
|
+
/** @class */
|
|
1763
|
+
function () {
|
|
1764
|
+
function DeviceManager(callbacks) {
|
|
1765
|
+
this.deviceId = "";
|
|
1766
|
+
this.callbacks = callbacks;
|
|
1767
|
+
}
|
|
1623
1768
|
|
|
1769
|
+
DeviceManager.prototype.getDeviceId = function () {
|
|
1770
|
+
if (this.deviceId) {
|
|
1771
|
+
return this.deviceId;
|
|
1772
|
+
}
|
|
1624
1773
|
|
|
1625
|
-
|
|
1626
|
-
var desc = _a.desc,
|
|
1627
|
-
pageKey = _a.pageKey,
|
|
1628
|
-
partkey = _a.partkey,
|
|
1629
|
-
business = _a.business,
|
|
1630
|
-
header = _a.header;
|
|
1774
|
+
var storedDeviceId = this.callbacks.getCookie("device_id") || this.callbacks.getLocalStorage("device_id");
|
|
1631
1775
|
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
privateParamMap: {
|
|
1637
|
-
business: business
|
|
1638
|
-
}
|
|
1639
|
-
});
|
|
1776
|
+
if (storedDeviceId) {
|
|
1777
|
+
this.deviceId = storedDeviceId;
|
|
1778
|
+
return this.deviceId;
|
|
1779
|
+
}
|
|
1640
1780
|
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1781
|
+
var fingerprint = this.callbacks.collectFingerprint();
|
|
1782
|
+
var deviceId = this.callbacks.hashFingerprint(fingerprint);
|
|
1783
|
+
this.callbacks.setCookie("device_id", deviceId, 365 * 2);
|
|
1784
|
+
this.callbacks.setLocalStorage("device_id", deviceId);
|
|
1785
|
+
this.deviceId = deviceId;
|
|
1786
|
+
return this.deviceId;
|
|
1787
|
+
};
|
|
1646
1788
|
|
|
1789
|
+
DeviceManager.prototype.resetDeviceId = function () {
|
|
1790
|
+
document.cookie = "device_id=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;";
|
|
1791
|
+
localStorage.removeItem("device_id");
|
|
1792
|
+
this.deviceId = "";
|
|
1793
|
+
var newDeviceId = this.getDeviceId();
|
|
1794
|
+
return newDeviceId;
|
|
1795
|
+
};
|
|
1647
1796
|
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
_this.unlistener(); // 如果启用了全埋点,监听页面浏览事件
|
|
1797
|
+
return DeviceManager;
|
|
1798
|
+
}();
|
|
1651
1799
|
|
|
1800
|
+
var PENDING_REQUESTS_STORAGE_KEY = "web_tracking_pending_requests";
|
|
1801
|
+
var DEFAULT_PENDING_REQUESTS_MAX_SIZE = 50;
|
|
1652
1802
|
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1803
|
+
var PendingRequestsManager =
|
|
1804
|
+
/** @class */
|
|
1805
|
+
function () {
|
|
1806
|
+
function PendingRequestsManager(config, callbacks) {
|
|
1807
|
+
this.isFlushingPendingData = false;
|
|
1808
|
+
this.isUnloadListenerSetup = false;
|
|
1809
|
+
this.config = config;
|
|
1810
|
+
this.callbacks = callbacks;
|
|
1811
|
+
}
|
|
1656
1812
|
|
|
1657
|
-
|
|
1658
|
-
|
|
1813
|
+
PendingRequestsManager.prototype.updateConfig = function (config) {
|
|
1814
|
+
this.config = __assign(__assign({}, this.config), config);
|
|
1815
|
+
};
|
|
1659
1816
|
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1817
|
+
PendingRequestsManager.prototype.addToQueue = function (params) {
|
|
1818
|
+
var currentRequests = this.getQueueFromStorage();
|
|
1819
|
+
currentRequests.push(params);
|
|
1820
|
+
var maxSize = this.config.pendingRequestsMaxSize || DEFAULT_PENDING_REQUESTS_MAX_SIZE;
|
|
1664
1821
|
|
|
1822
|
+
if (currentRequests.length > maxSize) {
|
|
1823
|
+
var trimmedRequests = currentRequests.slice(-maxSize);
|
|
1665
1824
|
|
|
1666
|
-
if (
|
|
1667
|
-
|
|
1825
|
+
if (this.config.showLog) {
|
|
1826
|
+
this.callbacks.printLog("\u5F85\u53D1\u9001\u8BF7\u6C42\u961F\u5217\u5DF2\u6EE1\uFF0C\u5DF2\u79FB\u9664\u6700\u65E7\u7684\u6570\u636E\uFF08\u6700\u5927\u9650\u5236: " + maxSize + "\uFF09");
|
|
1668
1827
|
}
|
|
1669
|
-
};
|
|
1670
|
-
/**
|
|
1671
|
-
* @description 取消全埋点事件
|
|
1672
|
-
*/
|
|
1673
1828
|
|
|
1829
|
+
this.saveQueueToStorage(trimmedRequests);
|
|
1830
|
+
} else {
|
|
1831
|
+
this.saveQueueToStorage(currentRequests);
|
|
1832
|
+
}
|
|
1833
|
+
};
|
|
1674
1834
|
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
var historyPushState = window.history.pushState;
|
|
1678
|
-
var singlePageEvent = !!historyPushState ? "popstate" : "hashchange";
|
|
1835
|
+
PendingRequestsManager.prototype.restoreQueue = function () {
|
|
1836
|
+
var pendingRequests = this.getQueueFromStorage();
|
|
1679
1837
|
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1838
|
+
if (pendingRequests.length > 0) {
|
|
1839
|
+
if (this.config.showLog) {
|
|
1840
|
+
this.callbacks.printLog("\u4ECE LocalStorage \u6062\u590D " + pendingRequests.length + " \u6761\u5F85\u53D1\u9001\u8BF7\u6C42");
|
|
1683
1841
|
}
|
|
1842
|
+
}
|
|
1843
|
+
};
|
|
1684
1844
|
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
});
|
|
1845
|
+
PendingRequestsManager.prototype.flushQueue = function () {
|
|
1846
|
+
var _this = this;
|
|
1688
1847
|
|
|
1689
|
-
|
|
1848
|
+
var pendingRequests = this.getQueueFromStorage();
|
|
1690
1849
|
|
|
1850
|
+
if (pendingRequests.length === 0) {
|
|
1851
|
+
return;
|
|
1852
|
+
}
|
|
1691
1853
|
|
|
1692
|
-
|
|
1854
|
+
this.saveQueueToStorage([]);
|
|
1855
|
+
var _a = this.config,
|
|
1856
|
+
serverUrl = _a.serverUrl,
|
|
1857
|
+
sendTimeout = _a.sendTimeout,
|
|
1858
|
+
contentType = _a.contentType,
|
|
1859
|
+
showLog = _a.showLog,
|
|
1860
|
+
initHeader = _a.header;
|
|
1861
|
+
pendingRequests.forEach(function (params) {
|
|
1862
|
+
if (!_this.callbacks.shouldSample()) {
|
|
1863
|
+
if (showLog) {
|
|
1864
|
+
_this.callbacks.printLog("待发送请求已采样跳过");
|
|
1865
|
+
}
|
|
1693
1866
|
|
|
1867
|
+
return;
|
|
1868
|
+
}
|
|
1694
1869
|
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1870
|
+
if (showLog) {
|
|
1871
|
+
_this.callbacks.printLog(JSON.stringify(params));
|
|
1872
|
+
}
|
|
1873
|
+
|
|
1874
|
+
_this.callbacks.ajax({
|
|
1875
|
+
url: serverUrl,
|
|
1876
|
+
type: "POST",
|
|
1877
|
+
data: JSON.stringify(params),
|
|
1878
|
+
contentType: contentType,
|
|
1879
|
+
header: initHeader,
|
|
1880
|
+
credentials: false,
|
|
1881
|
+
timeout: sendTimeout,
|
|
1882
|
+
cors: true,
|
|
1883
|
+
success: function success() {
|
|
1884
|
+
if (showLog) {
|
|
1885
|
+
_this.callbacks.printLog("待发送请求发送成功");
|
|
1886
|
+
}
|
|
1887
|
+
},
|
|
1888
|
+
error: function error(err) {
|
|
1889
|
+
if (showLog) {
|
|
1890
|
+
_this.callbacks.printLog("\u5F85\u53D1\u9001\u8BF7\u6C42\u53D1\u9001\u5931\u8D25\uFF08\u4E0D\u518D\u91CD\u8BD5\uFF09: " + err);
|
|
1891
|
+
}
|
|
1892
|
+
}
|
|
1893
|
+
});
|
|
1894
|
+
});
|
|
1895
|
+
};
|
|
1700
1896
|
|
|
1897
|
+
PendingRequestsManager.prototype.flushQueueWithBeacon = function () {
|
|
1898
|
+
var _this = this;
|
|
1701
1899
|
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
_this.batchTimer = null;
|
|
1706
|
-
}
|
|
1707
|
-
};
|
|
1708
|
-
/**
|
|
1709
|
-
* @description 清空批量队列(包括 LocalStorage 中的数据)
|
|
1710
|
-
*/
|
|
1900
|
+
if (this.isFlushingPendingData) {
|
|
1901
|
+
return;
|
|
1902
|
+
}
|
|
1711
1903
|
|
|
1904
|
+
this.isFlushingPendingData = true;
|
|
1905
|
+
var pendingRequests = this.getQueueFromStorage();
|
|
1712
1906
|
|
|
1713
|
-
|
|
1714
|
-
|
|
1907
|
+
if (pendingRequests.length === 0) {
|
|
1908
|
+
this.isFlushingPendingData = false;
|
|
1909
|
+
return;
|
|
1910
|
+
}
|
|
1715
1911
|
|
|
1716
|
-
|
|
1717
|
-
|
|
1912
|
+
var _a = this.config,
|
|
1913
|
+
serverUrl = _a.serverUrl,
|
|
1914
|
+
contentType = _a.contentType,
|
|
1915
|
+
showLog = _a.showLog;
|
|
1916
|
+
var successCount = 0;
|
|
1917
|
+
var failureCount = 0;
|
|
1918
|
+
pendingRequests.forEach(function (params) {
|
|
1919
|
+
if (_this.sendWithBeacon(params, serverUrl, contentType)) {
|
|
1920
|
+
successCount++;
|
|
1921
|
+
} else {
|
|
1922
|
+
failureCount++;
|
|
1718
1923
|
}
|
|
1719
|
-
};
|
|
1720
|
-
/**
|
|
1721
|
-
* @description 从 LocalStorage 获取批量队列
|
|
1722
|
-
* @returns 批量队列数组
|
|
1723
|
-
*/
|
|
1724
|
-
|
|
1924
|
+
});
|
|
1725
1925
|
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1926
|
+
if (showLog) {
|
|
1927
|
+
this.callbacks.printLog("\u9875\u9762\u5378\u8F7D\u65F6\u53D1\u9001\u5F85\u8BF7\u6C42\u6570\u636E: \u6210\u529F " + successCount + " \u6761\uFF0C\u5931\u8D25 " + failureCount + " \u6761");
|
|
1928
|
+
}
|
|
1729
1929
|
|
|
1730
|
-
|
|
1731
|
-
|
|
1930
|
+
this.isFlushingPendingData = false;
|
|
1931
|
+
};
|
|
1732
1932
|
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
}
|
|
1736
|
-
}
|
|
1737
|
-
} catch (e) {
|
|
1738
|
-
_this.printLog("\u8BFB\u53D6\u6279\u91CF\u961F\u5217\u5931\u8D25: " + e); // 如果解析失败,清除损坏的数据
|
|
1933
|
+
PendingRequestsManager.prototype.setupUnloadListener = function () {
|
|
1934
|
+
var _this = this;
|
|
1739
1935
|
|
|
1936
|
+
if (this.isUnloadListenerSetup) {
|
|
1937
|
+
return;
|
|
1938
|
+
}
|
|
1740
1939
|
|
|
1741
|
-
|
|
1940
|
+
this.isUnloadListenerSetup = true;
|
|
1941
|
+
document.addEventListener("visibilitychange", function () {
|
|
1942
|
+
if (_this.isPageUnloading()) {
|
|
1943
|
+
_this.flushQueueWithBeacon();
|
|
1742
1944
|
}
|
|
1945
|
+
});
|
|
1946
|
+
window.addEventListener("beforeunload", function () {
|
|
1947
|
+
_this.flushQueueWithBeacon();
|
|
1948
|
+
});
|
|
1949
|
+
window.addEventListener("pagehide", function () {
|
|
1950
|
+
_this.flushQueueWithBeacon();
|
|
1951
|
+
});
|
|
1952
|
+
};
|
|
1743
1953
|
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
* @description 保存批量队列到 LocalStorage
|
|
1748
|
-
* @param queue 批量队列数组
|
|
1749
|
-
*/
|
|
1954
|
+
PendingRequestsManager.prototype.getQueueFromStorage = function () {
|
|
1955
|
+
try {
|
|
1956
|
+
var storedRequests = this.callbacks.getLocalStorage(PENDING_REQUESTS_STORAGE_KEY);
|
|
1750
1957
|
|
|
1958
|
+
if (storedRequests) {
|
|
1959
|
+
var parsedRequests = JSON.parse(storedRequests);
|
|
1751
1960
|
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1961
|
+
if (Array.isArray(parsedRequests)) {
|
|
1962
|
+
return parsedRequests;
|
|
1963
|
+
}
|
|
1964
|
+
}
|
|
1965
|
+
} catch (e) {
|
|
1966
|
+
this.callbacks.printLog("\u8BFB\u53D6\u5F85\u53D1\u9001\u8BF7\u6C42\u5931\u8D25: " + e);
|
|
1967
|
+
this.callbacks.setLocalStorage(PENDING_REQUESTS_STORAGE_KEY, "[]");
|
|
1968
|
+
}
|
|
1755
1969
|
|
|
1756
|
-
|
|
1757
|
-
|
|
1970
|
+
return [];
|
|
1971
|
+
};
|
|
1758
1972
|
|
|
1759
|
-
|
|
1973
|
+
PendingRequestsManager.prototype.saveQueueToStorage = function (requests) {
|
|
1974
|
+
try {
|
|
1975
|
+
this.callbacks.setLocalStorage(PENDING_REQUESTS_STORAGE_KEY, JSON.stringify(requests));
|
|
1976
|
+
} catch (e) {
|
|
1977
|
+
this.callbacks.printLog("\u4FDD\u5B58\u5F85\u53D1\u9001\u8BF7\u6C42\u5230 LocalStorage \u5931\u8D25: " + e);
|
|
1978
|
+
}
|
|
1979
|
+
};
|
|
1760
1980
|
|
|
1761
|
-
|
|
1981
|
+
PendingRequestsManager.prototype.isPageUnloading = function () {
|
|
1982
|
+
return document.visibilityState === "hidden";
|
|
1983
|
+
};
|
|
1762
1984
|
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
}
|
|
1768
|
-
|
|
1769
|
-
|
|
1985
|
+
PendingRequestsManager.prototype.sendWithBeacon = function (params, serverUrl, contentType) {
|
|
1986
|
+
try {
|
|
1987
|
+
var blob = new Blob([JSON.stringify(params)], {
|
|
1988
|
+
type: contentType || "application/json"
|
|
1989
|
+
});
|
|
1990
|
+
return navigator.sendBeacon(serverUrl, blob);
|
|
1991
|
+
} catch (e) {
|
|
1992
|
+
if (this.config.showLog) {
|
|
1993
|
+
this.callbacks.printLog("sendBeacon \u53D1\u9001\u5931\u8D25: " + e);
|
|
1770
1994
|
}
|
|
1771
|
-
};
|
|
1772
|
-
/**
|
|
1773
|
-
* @description 从 LocalStorage 获取待发送请求队列
|
|
1774
|
-
* @returns 待发送请求队列数组
|
|
1775
|
-
*/
|
|
1776
1995
|
|
|
1996
|
+
return false;
|
|
1997
|
+
}
|
|
1998
|
+
};
|
|
1777
1999
|
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
2000
|
+
return PendingRequestsManager;
|
|
2001
|
+
}();
|
|
2002
|
+
|
|
2003
|
+
var WebTracking =
|
|
2004
|
+
/** @class */
|
|
2005
|
+
function (_super) {
|
|
2006
|
+
__extends(WebTracking, _super);
|
|
1781
2007
|
|
|
1782
|
-
|
|
1783
|
-
|
|
2008
|
+
function WebTracking() {
|
|
2009
|
+
var _this = _super.call(this) || this;
|
|
1784
2010
|
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
2011
|
+
_this.useCustomPageKey = false;
|
|
2012
|
+
_this.userInfo = null;
|
|
2013
|
+
_this.currentUrl = "";
|
|
2014
|
+
_this.pageKey = "";
|
|
2015
|
+
_this.deviceId = "";
|
|
2016
|
+
_this.eventDescMap = {
|
|
2017
|
+
PageView: "Web 浏览页面",
|
|
2018
|
+
WebClick: "Web 元素点击",
|
|
2019
|
+
PageRetained: "Web 页面浏览时长",
|
|
2020
|
+
CustomTrack: "Web 自定义代码上报",
|
|
2021
|
+
WebExposure: "Web 元素曝光"
|
|
2022
|
+
};
|
|
1791
2023
|
|
|
2024
|
+
_this.init = function (initParams) {
|
|
2025
|
+
_this.preset(initParams);
|
|
1792
2026
|
|
|
1793
|
-
|
|
1794
|
-
|
|
2027
|
+
var pathname = window.location.pathname;
|
|
2028
|
+
_this.currentUrl = window.location.href;
|
|
1795
2029
|
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
2030
|
+
if (initParams.pageKey) {
|
|
2031
|
+
_this.pageKey = initParams.pageKey;
|
|
2032
|
+
_this.useCustomPageKey = true;
|
|
2033
|
+
} else {
|
|
2034
|
+
_this.pageKey = pathname.replace(/\//g, "_").substring(1);
|
|
2035
|
+
_this.useCustomPageKey = false;
|
|
2036
|
+
}
|
|
1802
2037
|
|
|
2038
|
+
_this.systemsInfo = _this.getSystemsInfo(initParams.platform);
|
|
2039
|
+
_this.deviceId = _this.deviceManager.getDeviceId();
|
|
1803
2040
|
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
_this.setLocalStorage(_this.PENDING_REQUESTS_STORAGE_KEY, JSON.stringify(requests));
|
|
1807
|
-
} catch (e) {
|
|
1808
|
-
// LocalStorage 可能已满或不可用
|
|
1809
|
-
_this.printLog("\u4FDD\u5B58\u5F85\u53D1\u9001\u8BF7\u6C42\u5230 LocalStorage \u5931\u8D25: " + e);
|
|
2041
|
+
if (initParams.userInfo && _this.isObject(initParams.userInfo)) {
|
|
2042
|
+
_this.userInfo = initParams.userInfo;
|
|
1810
2043
|
}
|
|
1811
|
-
};
|
|
1812
|
-
/**
|
|
1813
|
-
* @description 设置自定义页面唯一标识
|
|
1814
|
-
* @param pageKey 页面唯一标识,如果传入 null 或空字符串,则恢复自动生成
|
|
1815
|
-
* @param autoUpdate 路由变化时是否自动更新(默认:false,使用自定义值后不再自动更新)
|
|
1816
|
-
*/
|
|
1817
2044
|
|
|
2045
|
+
_this.setCookie("retainedStartTime", _this.getTimeStamp());
|
|
1818
2046
|
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
autoUpdate = false;
|
|
2047
|
+
if (_this.initConfig.batchSend) {
|
|
2048
|
+
_this.batchSender.restoreQueue();
|
|
1822
2049
|
}
|
|
1823
2050
|
|
|
1824
|
-
|
|
1825
|
-
// 恢复自动生成
|
|
1826
|
-
_this.useCustomPageKey = false;
|
|
1827
|
-
var pathname = window.location.pathname;
|
|
1828
|
-
_this.pageKey = pathname.replace(/\//g, "_").substring(1);
|
|
2051
|
+
_this.pendingRequestsManager.restoreQueue();
|
|
1829
2052
|
|
|
1830
|
-
|
|
1831
|
-
_this.printLog("\u9875\u9762\u6807\u8BC6\u5DF2\u6062\u590D\u81EA\u52A8\u751F\u6210: " + _this.pageKey);
|
|
1832
|
-
}
|
|
1833
|
-
} else {
|
|
1834
|
-
_this.pageKey = pageKey;
|
|
1835
|
-
_this.useCustomPageKey = !autoUpdate;
|
|
2053
|
+
_this.pendingRequestsManager.setupUnloadListener();
|
|
1836
2054
|
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
}
|
|
2055
|
+
if (_this.initConfig.autoTrackPageDurationInterval) {
|
|
2056
|
+
_this.pageDurationTracker.start();
|
|
1840
2057
|
}
|
|
1841
|
-
};
|
|
1842
|
-
/**
|
|
1843
|
-
* @description 获取当前页面唯一标识
|
|
1844
|
-
* @returns 当前页面唯一标识
|
|
1845
|
-
*/
|
|
1846
2058
|
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
2059
|
+
if (_this.initConfig.autoTrackExposure) {
|
|
2060
|
+
_this.exposureTracker.init();
|
|
2061
|
+
}
|
|
1850
2062
|
};
|
|
1851
2063
|
|
|
1852
|
-
_this.
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
nodeName: nodeName,
|
|
1864
|
-
className: className,
|
|
1865
|
-
position: position
|
|
1866
|
-
};
|
|
1867
|
-
|
|
1868
|
-
var params = _this.getParams({
|
|
1869
|
-
event: "WebClick",
|
|
1870
|
-
desc: _this.eventDescMap["WebClick"],
|
|
1871
|
-
itemKey: _this.getItemKey(target.dataset.partKey),
|
|
1872
|
-
privateParamMap: {
|
|
1873
|
-
targetEle: targetEle,
|
|
1874
|
-
pointerType: e.pointerType,
|
|
1875
|
-
currentUrl: _this.currentUrl,
|
|
1876
|
-
elementSelector: _this.getDomSelector(target) || ""
|
|
2064
|
+
_this.preset = function (presetParams) {
|
|
2065
|
+
if (presetParams instanceof Object) {
|
|
2066
|
+
if (presetParams.pageKey !== undefined) {
|
|
2067
|
+
if (presetParams.pageKey === null || presetParams.pageKey === "") {
|
|
2068
|
+
_this.useCustomPageKey = false;
|
|
2069
|
+
var pathname = window.location.pathname;
|
|
2070
|
+
_this.pageKey = pathname.replace(/\//g, "_").substring(1);
|
|
2071
|
+
} else {
|
|
2072
|
+
_this.pageKey = presetParams.pageKey;
|
|
2073
|
+
_this.useCustomPageKey = true;
|
|
2074
|
+
}
|
|
1877
2075
|
}
|
|
1878
|
-
});
|
|
1879
2076
|
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
/**
|
|
1883
|
-
* @description 路由触发事件
|
|
1884
|
-
*/
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
_this.onPageViewCallback = function (e) {
|
|
1888
|
-
var _a, _b; // 在路由变化前,先发送待发送的数据(避免被取消)
|
|
2077
|
+
_this.each(presetParams, function (val, key) {
|
|
2078
|
+
if (key === "pageKey") return;
|
|
1889
2079
|
|
|
2080
|
+
if (_this.initConfig.hasOwnProperty(key)) {
|
|
2081
|
+
var validationResult = _this.validateConfigParam(String(key), val);
|
|
1890
2082
|
|
|
1891
|
-
|
|
2083
|
+
if (validationResult.valid) {
|
|
2084
|
+
_this.initConfig[key] = val;
|
|
2085
|
+
} else {
|
|
2086
|
+
_this.printLog("\u914D\u7F6E\u53C2\u6570\u9A8C\u8BC1\u5931\u8D25: " + String(key) + " = " + val + ", \u539F\u56E0: " + validationResult.message);
|
|
2087
|
+
}
|
|
2088
|
+
}
|
|
2089
|
+
});
|
|
2090
|
+
}
|
|
1892
2091
|
|
|
1893
|
-
|
|
2092
|
+
if (!/^(((ht|f)tps?):\/\/)?[\w-]+(\.[\w-]+)+([\w.,@?^=%&:/~+#-\(\)]*[\w@?^=%&/~+#-\(\)])?$/.test(_this.initConfig["serverUrl"])) {
|
|
2093
|
+
_this.printLog("当前 server_url 为空或不正确,只在控制台打印日志,network 中不会发数据,请配置正确的 server_url!");
|
|
1894
2094
|
|
|
1895
|
-
|
|
1896
|
-
_this.flushPendingData();
|
|
2095
|
+
_this.initConfig["showLog"] = true;
|
|
1897
2096
|
}
|
|
1898
2097
|
|
|
1899
|
-
|
|
2098
|
+
if (!!_this.initConfig["autoTrack"] || !!_this.initConfig["trackPartKeyClick"]) {
|
|
2099
|
+
_this.listener();
|
|
2100
|
+
} else {
|
|
2101
|
+
_this.unlistener();
|
|
2102
|
+
}
|
|
1900
2103
|
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
2104
|
+
_this.batchSender.updateConfig({
|
|
2105
|
+
batchSend: _this.initConfig.batchSend,
|
|
2106
|
+
batchInterval: _this.initConfig.batchInterval,
|
|
2107
|
+
batchMaxSize: _this.initConfig.batchMaxSize,
|
|
2108
|
+
sendTimeout: _this.initConfig.sendTimeout,
|
|
2109
|
+
serverUrl: _this.initConfig.serverUrl,
|
|
2110
|
+
contentType: _this.initConfig.contentType,
|
|
2111
|
+
showLog: _this.initConfig.showLog,
|
|
2112
|
+
sendMethod: _this.initConfig.sendMethod,
|
|
2113
|
+
header: _this.initConfig.header
|
|
1908
2114
|
});
|
|
1909
2115
|
|
|
1910
|
-
_this.
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
_this.
|
|
1914
|
-
|
|
1915
|
-
|
|
2116
|
+
_this.pendingRequestsManager.updateConfig({
|
|
2117
|
+
pendingRequestsMaxSize: _this.initConfig.pendingRequestsMaxSize,
|
|
2118
|
+
sendTimeout: _this.initConfig.sendTimeout,
|
|
2119
|
+
serverUrl: _this.initConfig.serverUrl,
|
|
2120
|
+
contentType: _this.initConfig.contentType,
|
|
2121
|
+
showLog: _this.initConfig.showLog,
|
|
2122
|
+
header: _this.initConfig.header
|
|
2123
|
+
});
|
|
1916
2124
|
|
|
1917
2125
|
if (_this.initConfig.autoTrackPageDurationInterval) {
|
|
1918
|
-
_this.
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
_this.sendRetained(e.type);
|
|
1924
|
-
|
|
1925
|
-
_this.sendData(params);
|
|
1926
|
-
};
|
|
1927
|
-
|
|
1928
|
-
_this.getParams = function (_a) {
|
|
1929
|
-
var event = _a.event,
|
|
1930
|
-
desc = _a.desc,
|
|
1931
|
-
_b = _a.privateParamMap,
|
|
1932
|
-
privateParamMap = _b === void 0 ? {} : _b,
|
|
1933
|
-
itemKey = _a.itemKey;
|
|
1934
|
-
var business = _this.initConfig.business;
|
|
1935
|
-
var pageWidth = window.innerWidth;
|
|
1936
|
-
var pageHeight = window.innerHeight;
|
|
1937
|
-
var screenWidth = window.screen.width;
|
|
1938
|
-
var screenHeight = window.screen.height; // 过滤敏感数据
|
|
1939
|
-
|
|
1940
|
-
var filteredBusiness = _this.filterSensitiveData(business || {});
|
|
1941
|
-
|
|
1942
|
-
var filteredUserInfo = _this.filterSensitiveData(_this.userInfo || {});
|
|
1943
|
-
|
|
1944
|
-
var filteredPrivateParamMap = _this.filterSensitiveData(privateParamMap || {});
|
|
1945
|
-
|
|
1946
|
-
var filteredUrlParams = _this.filterSensitiveData(_this.getQueryValue() || {}); // 创建私有参数对象
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
var privateParamMapData = {
|
|
1950
|
-
currentUrl: filteredPrivateParamMap.currentUrl || _this.currentUrl,
|
|
1951
|
-
business: Object.assign({}, filteredBusiness, filteredPrivateParamMap.business || {}),
|
|
1952
|
-
pageWidth: pageWidth,
|
|
1953
|
-
pageHeight: pageHeight,
|
|
1954
|
-
screenWidth: screenWidth,
|
|
1955
|
-
screenHeight: screenHeight,
|
|
1956
|
-
sdkVersion: _this.sdkVersion,
|
|
1957
|
-
systemsInfo: _this.systemsInfo,
|
|
1958
|
-
urlParams: filteredUrlParams,
|
|
1959
|
-
userInfo: filteredUserInfo,
|
|
1960
|
-
deviceId: _this.deviceId // 添加设备ID
|
|
1961
|
-
|
|
1962
|
-
}; // 添加其他可能的属性
|
|
1963
|
-
|
|
1964
|
-
if (filteredPrivateParamMap.targetEle) {
|
|
1965
|
-
privateParamMapData.targetEle = filteredPrivateParamMap.targetEle;
|
|
1966
|
-
}
|
|
1967
|
-
|
|
1968
|
-
if (filteredPrivateParamMap.targetUrl) {
|
|
1969
|
-
privateParamMapData.targetUrl = filteredPrivateParamMap.targetUrl;
|
|
1970
|
-
}
|
|
2126
|
+
_this.pageDurationTracker.updateConfig({
|
|
2127
|
+
pageDurationInterval: _this.initConfig.pageDurationInterval,
|
|
2128
|
+
showLog: _this.initConfig.showLog
|
|
2129
|
+
});
|
|
1971
2130
|
|
|
1972
|
-
|
|
1973
|
-
|
|
2131
|
+
_this.pageDurationTracker.start();
|
|
2132
|
+
} else {
|
|
2133
|
+
_this.pageDurationTracker.stop();
|
|
1974
2134
|
}
|
|
1975
2135
|
|
|
1976
|
-
if (
|
|
1977
|
-
|
|
1978
|
-
|
|
2136
|
+
if (_this.initConfig.autoTrackExposure) {
|
|
2137
|
+
_this.exposureTracker.updateConfig({
|
|
2138
|
+
autoTrackExposure: _this.initConfig.autoTrackExposure,
|
|
2139
|
+
exposureThreshold: _this.initConfig.exposureThreshold,
|
|
2140
|
+
exposureTime: _this.initConfig.exposureTime,
|
|
2141
|
+
exposureNum: _this.initConfig.exposureNum,
|
|
2142
|
+
showLog: _this.initConfig.showLog
|
|
2143
|
+
});
|
|
1979
2144
|
|
|
1980
|
-
|
|
1981
|
-
|
|
2145
|
+
_this.exposureTracker.init();
|
|
2146
|
+
} else {
|
|
2147
|
+
_this.exposureTracker.stop();
|
|
1982
2148
|
}
|
|
1983
|
-
|
|
1984
|
-
return {
|
|
1985
|
-
event: event,
|
|
1986
|
-
desc: desc,
|
|
1987
|
-
itemKey: itemKey || _this.getItemKey(),
|
|
1988
|
-
requestTime: _this.getTimeStamp(),
|
|
1989
|
-
privateParamMap: privateParamMapData
|
|
1990
|
-
};
|
|
1991
|
-
};
|
|
1992
|
-
/**
|
|
1993
|
-
* 数据采样判断
|
|
1994
|
-
* @returns 是否应该采样
|
|
1995
|
-
*/
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
_this.shouldSample = function () {
|
|
1999
|
-
var sampleRate = _this.initConfig.sampleRate;
|
|
2000
|
-
if (sampleRate >= 1) return true;
|
|
2001
|
-
if (sampleRate <= 0) return false;
|
|
2002
|
-
return Math.random() < sampleRate;
|
|
2003
|
-
};
|
|
2004
|
-
/**
|
|
2005
|
-
* 批量发送数据
|
|
2006
|
-
*/
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
_this.flushBatchQueue = function () {
|
|
2010
|
-
var batchQueue = _this.getBatchQueueFromStorage();
|
|
2011
|
-
|
|
2012
|
-
if (batchQueue.length === 0) return;
|
|
2013
|
-
|
|
2014
|
-
var currentTime = _this.getTimeStamp(); // 过滤出可以发送的数据(未到重试时间的不发送)
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
var readyToSend = batchQueue.filter(function (item) {
|
|
2018
|
-
if (!item._nextRetryTime) {
|
|
2019
|
-
return true;
|
|
2020
|
-
}
|
|
2021
|
-
|
|
2022
|
-
return item._nextRetryTime <= currentTime;
|
|
2023
|
-
});
|
|
2024
|
-
|
|
2025
|
-
if (readyToSend.length === 0) {
|
|
2026
|
-
if (_this.initConfig.showLog) {
|
|
2027
|
-
_this.printLog("\u6279\u91CF\u961F\u5217\u4E2D\u6709 " + batchQueue.length + " \u6761\u6570\u636E\u7B49\u5F85\u91CD\u8BD5");
|
|
2028
|
-
}
|
|
2029
|
-
|
|
2030
|
-
return;
|
|
2031
|
-
} // 从队列中移除已准备发送的数据
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
var remainingQueue = batchQueue.filter(function (item) {
|
|
2035
|
-
if (!item._nextRetryTime) {
|
|
2036
|
-
return false;
|
|
2037
|
-
}
|
|
2038
|
-
|
|
2039
|
-
return item._nextRetryTime > currentTime;
|
|
2040
|
-
}); // 保存剩余的队列
|
|
2041
|
-
|
|
2042
|
-
_this.saveBatchQueueToStorage(remainingQueue); // 发送批量数据
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
_this.sendBatchData(readyToSend);
|
|
2046
2149
|
};
|
|
2047
|
-
/**
|
|
2048
|
-
* 发送批量数据
|
|
2049
|
-
* @param data 批量数据
|
|
2050
|
-
*/
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
_this.sendBatchData = function (data) {
|
|
2054
|
-
var _a = _this.initConfig,
|
|
2055
|
-
serverUrl = _a.serverUrl,
|
|
2056
|
-
contentType = _a.contentType,
|
|
2057
|
-
showLog = _a.showLog,
|
|
2058
|
-
sendMethod = _a.sendMethod,
|
|
2059
|
-
initHeader = _a.header;
|
|
2060
|
-
|
|
2061
|
-
if (showLog) {
|
|
2062
|
-
_this.printLog("\u6279\u91CF\u53D1\u9001 " + data.length + " \u6761\u6570\u636E");
|
|
2063
|
-
|
|
2064
|
-
data.forEach(function (item) {
|
|
2065
|
-
return _this.printLog(item);
|
|
2066
|
-
});
|
|
2067
|
-
} // 判断是否使用 sendBeacon
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
var shouldUseBeacon = _this.shouldUseBeacon(sendMethod, undefined, initHeader); // 如果使用 sendBeacon
|
|
2071
2150
|
|
|
2151
|
+
_this.validateConfigParam = function (key, value) {
|
|
2152
|
+
switch (key) {
|
|
2153
|
+
case "sampleRate":
|
|
2154
|
+
if (typeof value !== "number" || value < 0 || value > 1) {
|
|
2155
|
+
return {
|
|
2156
|
+
valid: false,
|
|
2157
|
+
message: "sampleRate 必须是 0-1 之间的数字"
|
|
2158
|
+
};
|
|
2159
|
+
}
|
|
2072
2160
|
|
|
2073
|
-
|
|
2074
|
-
try {
|
|
2075
|
-
var blob = new Blob([JSON.stringify(data)], {
|
|
2076
|
-
type: contentType || "application/json"
|
|
2077
|
-
});
|
|
2078
|
-
var sent = navigator.sendBeacon(serverUrl, blob);
|
|
2161
|
+
break;
|
|
2079
2162
|
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2163
|
+
case "sendTimeout":
|
|
2164
|
+
if (typeof value !== "number" || value <= 0) {
|
|
2165
|
+
return {
|
|
2166
|
+
valid: false,
|
|
2167
|
+
message: "sendTimeout 必须是大于 0 的数字"
|
|
2168
|
+
};
|
|
2169
|
+
}
|
|
2083
2170
|
|
|
2084
|
-
|
|
2085
|
-
_this.printLog("\u6279\u91CF\u53D1\u9001\u6210\u529F: " + data.length + " \u6761\u6570\u636E");
|
|
2086
|
-
}
|
|
2087
|
-
} else {
|
|
2088
|
-
// sendBeacon 返回 false,重新加入队列以便重试
|
|
2089
|
-
_this.printLog("\u6279\u91CF\u53D1\u9001\u5931\u8D25: sendBeacon \u8FD4\u56DE false\uFF0C\u6570\u636E\u5DF2\u91CD\u65B0\u52A0\u5165\u961F\u5217");
|
|
2171
|
+
break;
|
|
2090
2172
|
|
|
2091
|
-
|
|
2173
|
+
case "batchInterval":
|
|
2174
|
+
if (typeof value !== "number" || value <= 0) {
|
|
2175
|
+
return {
|
|
2176
|
+
valid: false,
|
|
2177
|
+
message: "batchInterval 必须是大于 0 的数字"
|
|
2178
|
+
};
|
|
2092
2179
|
}
|
|
2093
|
-
} catch (e) {
|
|
2094
|
-
// sendBeacon 失败,重新加入队列以便重试
|
|
2095
|
-
_this.printLog("\u6279\u91CF\u53D1\u9001\u5931\u8D25: " + e + "\uFF0C\u6570\u636E\u5DF2\u91CD\u65B0\u52A0\u5165\u961F\u5217");
|
|
2096
2180
|
|
|
2097
|
-
|
|
2098
|
-
}
|
|
2099
|
-
} else {
|
|
2100
|
-
// 使用 XMLHttpRequest 发送
|
|
2101
|
-
_this.ajax({
|
|
2102
|
-
url: serverUrl,
|
|
2103
|
-
type: "POST",
|
|
2104
|
-
data: JSON.stringify({
|
|
2105
|
-
events: data
|
|
2106
|
-
}),
|
|
2107
|
-
contentType: contentType,
|
|
2108
|
-
credentials: false,
|
|
2109
|
-
timeout: _this.initConfig.sendTimeout,
|
|
2110
|
-
cors: true,
|
|
2111
|
-
success: function success() {
|
|
2112
|
-
// 批量发送成功,确保 LocalStorage 已清空
|
|
2113
|
-
// flushBatchQueue 在发送前已清空 LocalStorage,这里再次确认
|
|
2114
|
-
_this.saveBatchQueueToStorage([]);
|
|
2115
|
-
|
|
2116
|
-
if (_this.initConfig.showLog) {
|
|
2117
|
-
_this.printLog("\u6279\u91CF\u53D1\u9001\u6210\u529F: " + data.length + " \u6761\u6570\u636E");
|
|
2118
|
-
}
|
|
2119
|
-
},
|
|
2120
|
-
error: function error(err) {
|
|
2121
|
-
// 批量发送失败,重新加入队列以便重试
|
|
2122
|
-
_this.printLog("\u6279\u91CF\u53D1\u9001\u5931\u8D25: " + err + "\uFF0C\u6570\u636E\u5DF2\u91CD\u65B0\u52A0\u5165\u961F\u5217");
|
|
2181
|
+
break;
|
|
2123
2182
|
|
|
2124
|
-
|
|
2183
|
+
case "batchMaxSize":
|
|
2184
|
+
if (typeof value !== "number" || value <= 0 || !Number.isInteger(value)) {
|
|
2185
|
+
return {
|
|
2186
|
+
valid: false,
|
|
2187
|
+
message: "batchMaxSize 必须是大于 0 的整数"
|
|
2188
|
+
};
|
|
2125
2189
|
}
|
|
2126
|
-
});
|
|
2127
|
-
}
|
|
2128
|
-
};
|
|
2129
|
-
/**
|
|
2130
|
-
* @description 批量数据重试逻辑
|
|
2131
|
-
* @param data 批量数据
|
|
2132
|
-
*/
|
|
2133
2190
|
|
|
2191
|
+
break;
|
|
2134
2192
|
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2193
|
+
case "pendingRequestsMaxSize":
|
|
2194
|
+
if (typeof value !== "number" || value <= 0 || !Number.isInteger(value)) {
|
|
2195
|
+
return {
|
|
2196
|
+
valid: false,
|
|
2197
|
+
message: "pendingRequestsMaxSize 必须是大于 0 的整数"
|
|
2198
|
+
};
|
|
2199
|
+
}
|
|
2138
2200
|
|
|
2201
|
+
break;
|
|
2139
2202
|
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2203
|
+
case "pageDurationInterval":
|
|
2204
|
+
if (typeof value !== "number" || value <= 0) {
|
|
2205
|
+
return {
|
|
2206
|
+
valid: false,
|
|
2207
|
+
message: "pageDurationInterval 必须是大于 0 的数字"
|
|
2208
|
+
};
|
|
2209
|
+
}
|
|
2143
2210
|
|
|
2144
|
-
|
|
2145
|
-
var maxRetryCount = 3; // 最大重试次数
|
|
2211
|
+
break;
|
|
2146
2212
|
|
|
2147
|
-
|
|
2213
|
+
case "sendMethod":
|
|
2214
|
+
if (typeof value !== "string" || !["auto", "xhr", "beacon"].includes(value)) {
|
|
2215
|
+
return {
|
|
2216
|
+
valid: false,
|
|
2217
|
+
message: "sendMethod 必须是 auto、xhr 或 beacon"
|
|
2218
|
+
};
|
|
2219
|
+
}
|
|
2148
2220
|
|
|
2221
|
+
break;
|
|
2149
2222
|
|
|
2150
|
-
|
|
2151
|
-
|
|
2223
|
+
case "exposureThreshold":
|
|
2224
|
+
if (typeof value !== "number" || value < 0 || value > 1) {
|
|
2225
|
+
return {
|
|
2226
|
+
valid: false,
|
|
2227
|
+
message: "exposureThreshold 必须是 0-1 之间的数字"
|
|
2228
|
+
};
|
|
2229
|
+
}
|
|
2152
2230
|
|
|
2153
|
-
|
|
2154
|
-
return false;
|
|
2155
|
-
} // 检查重试次数
|
|
2231
|
+
break;
|
|
2156
2232
|
|
|
2233
|
+
case "exposureTime":
|
|
2234
|
+
if (typeof value !== "number" || value <= 0) {
|
|
2235
|
+
return {
|
|
2236
|
+
valid: false,
|
|
2237
|
+
message: "exposureTime 必须是大于 0 的数字"
|
|
2238
|
+
};
|
|
2239
|
+
}
|
|
2157
2240
|
|
|
2158
|
-
|
|
2241
|
+
break;
|
|
2159
2242
|
|
|
2160
|
-
|
|
2161
|
-
if (
|
|
2162
|
-
|
|
2243
|
+
case "exposureNum":
|
|
2244
|
+
if (value !== undefined && (typeof value !== "number" || value <= 0 || !Number.isInteger(value))) {
|
|
2245
|
+
return {
|
|
2246
|
+
valid: false,
|
|
2247
|
+
message: "exposureNum 必须是大于 0 的整数或不限制"
|
|
2248
|
+
};
|
|
2163
2249
|
}
|
|
2164
2250
|
|
|
2165
|
-
|
|
2166
|
-
} // 更新重试信息
|
|
2251
|
+
break;
|
|
2167
2252
|
|
|
2253
|
+
case "showLog":
|
|
2254
|
+
case "autoTrack":
|
|
2255
|
+
case "isTrackSinglePage":
|
|
2256
|
+
case "batchSend":
|
|
2257
|
+
case "trackPartKeyClick":
|
|
2258
|
+
case "autoTrackPageDurationInterval":
|
|
2259
|
+
case "autoTrackExposure":
|
|
2260
|
+
if (typeof value !== "boolean") {
|
|
2261
|
+
return {
|
|
2262
|
+
valid: false,
|
|
2263
|
+
message: key + " \u5FC5\u987B\u662F\u5E03\u5C14\u503C"
|
|
2264
|
+
};
|
|
2265
|
+
}
|
|
2168
2266
|
|
|
2169
|
-
|
|
2267
|
+
break;
|
|
2170
2268
|
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2269
|
+
case "business":
|
|
2270
|
+
case "header":
|
|
2271
|
+
if (value !== null && _typeof(value) !== "object") {
|
|
2272
|
+
return {
|
|
2273
|
+
valid: false,
|
|
2274
|
+
message: key + " \u5FC5\u987B\u662F\u5BF9\u8C61\u6216 null"
|
|
2275
|
+
};
|
|
2276
|
+
}
|
|
2175
2277
|
|
|
2176
|
-
|
|
2278
|
+
break;
|
|
2177
2279
|
|
|
2280
|
+
case "contentType":
|
|
2281
|
+
if (value !== "application/json" && value !== "application/x-www-form-urlencoded") {
|
|
2282
|
+
return {
|
|
2283
|
+
valid: false,
|
|
2284
|
+
message: "contentType 必须是 application/json 或 application/x-www-form-urlencoded"
|
|
2285
|
+
};
|
|
2286
|
+
}
|
|
2178
2287
|
|
|
2179
|
-
|
|
2180
|
-
var trimmedQueue = retryQueue.length > maxSize ? retryQueue.slice(0, maxSize) : retryQueue; // 保存失败的数据到 LocalStorage,确保数据不丢失
|
|
2288
|
+
break;
|
|
2181
2289
|
|
|
2182
|
-
|
|
2290
|
+
case "platform":
|
|
2291
|
+
if (typeof value !== "string") {
|
|
2292
|
+
return {
|
|
2293
|
+
valid: false,
|
|
2294
|
+
message: "platform 必须是字符串"
|
|
2295
|
+
};
|
|
2296
|
+
}
|
|
2183
2297
|
|
|
2184
|
-
|
|
2185
|
-
_this.printLog("\u5DF2\u5C06 " + retryData.length + " \u6761\u6570\u636E\u52A0\u5165\u91CD\u8BD5\u961F\u5217");
|
|
2298
|
+
break;
|
|
2186
2299
|
}
|
|
2187
|
-
};
|
|
2188
|
-
/**
|
|
2189
|
-
* 添加到批量队列
|
|
2190
|
-
* @param params 数据参数
|
|
2191
|
-
*/
|
|
2192
|
-
|
|
2193
2300
|
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
if (!_this.shouldSample()) {
|
|
2200
|
-
if (_this.initConfig.showLog) {
|
|
2201
|
-
_this.printLog("数据已采样跳过(批量模式)");
|
|
2202
|
-
}
|
|
2203
|
-
|
|
2204
|
-
return;
|
|
2205
|
-
} // 从 LocalStorage 获取当前队列
|
|
2301
|
+
return {
|
|
2302
|
+
valid: true
|
|
2303
|
+
};
|
|
2304
|
+
};
|
|
2206
2305
|
|
|
2306
|
+
_this.login = function (userInfo) {
|
|
2307
|
+
if (_this.isObject(userInfo)) _this.userInfo = userInfo;
|
|
2308
|
+
};
|
|
2207
2309
|
|
|
2208
|
-
|
|
2310
|
+
_this.getDeviceId = function () {
|
|
2311
|
+
return _this.deviceManager.getDeviceId();
|
|
2312
|
+
};
|
|
2209
2313
|
|
|
2314
|
+
_this.resetDeviceId = function () {
|
|
2315
|
+
return _this.deviceManager.resetDeviceId();
|
|
2316
|
+
};
|
|
2210
2317
|
|
|
2211
|
-
|
|
2318
|
+
_this.track = function (_a) {
|
|
2319
|
+
var desc = _a.desc,
|
|
2320
|
+
pageKey = _a.pageKey,
|
|
2321
|
+
partKey = _a.partKey,
|
|
2322
|
+
business = _a.business,
|
|
2323
|
+
header = _a.header;
|
|
2212
2324
|
|
|
2213
|
-
_this.
|
|
2325
|
+
var params = _this.getParams({
|
|
2326
|
+
desc: desc,
|
|
2327
|
+
event: "CustomTrack",
|
|
2328
|
+
itemKey: _this.getItemKey(partKey, pageKey),
|
|
2329
|
+
privateParamMap: {
|
|
2330
|
+
business: business
|
|
2331
|
+
}
|
|
2332
|
+
});
|
|
2214
2333
|
|
|
2334
|
+
return _this.sendData(params, header);
|
|
2335
|
+
};
|
|
2215
2336
|
|
|
2216
|
-
|
|
2217
|
-
|
|
2337
|
+
_this.listener = function () {
|
|
2338
|
+
_this.unlistener();
|
|
2218
2339
|
|
|
2219
|
-
|
|
2220
|
-
|
|
2340
|
+
if (!!_this.initConfig.autoTrack) {
|
|
2341
|
+
if (!!_this.initConfig.isTrackSinglePage) {
|
|
2342
|
+
_this.rewriteHistory();
|
|
2221
2343
|
|
|
2344
|
+
_this.addSinglePageEvent(_this.onPageViewCallback);
|
|
2345
|
+
}
|
|
2222
2346
|
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2347
|
+
_this.each(["load", "beforeunload"], function (historyType) {
|
|
2348
|
+
_this.addEventListener(window, historyType, _this.onPageViewCallback);
|
|
2349
|
+
});
|
|
2350
|
+
}
|
|
2226
2351
|
|
|
2227
|
-
|
|
2228
|
-
|
|
2352
|
+
if (!!_this.initConfig.autoTrack || !!_this.initConfig.trackPartKeyClick) {
|
|
2353
|
+
_this.addEventListener(window, "click", _this.onClickCallback);
|
|
2229
2354
|
}
|
|
2230
2355
|
};
|
|
2231
|
-
/**
|
|
2232
|
-
* 从 LocalStorage 恢复批量队列
|
|
2233
|
-
*/
|
|
2234
|
-
|
|
2235
2356
|
|
|
2236
|
-
_this.
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
if (_this.initConfig.showLog) {
|
|
2241
|
-
_this.printLog("\u4ECE LocalStorage \u6062\u590D " + batchQueue.length + " \u6761\u5F85\u53D1\u9001\u6570\u636E");
|
|
2242
|
-
} // 恢复后立即尝试发送(如果达到条件)
|
|
2357
|
+
_this.unlistener = function () {
|
|
2358
|
+
if (!!_this.initConfig.isTrackSinglePage) {
|
|
2359
|
+
var historyPushState = window.history.pushState;
|
|
2360
|
+
var singlePageEvent = !!historyPushState ? "popstate" : "hashchange";
|
|
2243
2361
|
|
|
2362
|
+
_this.each(["pushState", "replaceState", singlePageEvent], function (historyName) {
|
|
2363
|
+
_this.removeEventListener(window, historyName, _this.onPageViewCallback);
|
|
2364
|
+
});
|
|
2365
|
+
}
|
|
2244
2366
|
|
|
2245
|
-
|
|
2367
|
+
_this.each(["load", "beforeunload"], function (historyType) {
|
|
2368
|
+
_this.removeEventListener(window, historyType, _this.onPageViewCallback);
|
|
2369
|
+
});
|
|
2246
2370
|
|
|
2247
|
-
|
|
2248
|
-
_this.flushBatchQueue();
|
|
2249
|
-
} else {
|
|
2250
|
-
// 设置定时发送
|
|
2251
|
-
var batchInterval = _this.initConfig.batchInterval;
|
|
2371
|
+
_this.removeEventListener(window, "click", _this.onClickCallback);
|
|
2252
2372
|
|
|
2253
|
-
|
|
2254
|
-
_this.batchTimer = window.setTimeout(function () {
|
|
2255
|
-
_this.flushBatchQueue();
|
|
2373
|
+
_this.batchSender.clearTimer();
|
|
2256
2374
|
|
|
2257
|
-
|
|
2258
|
-
}, batchInterval);
|
|
2259
|
-
}
|
|
2260
|
-
}
|
|
2261
|
-
}
|
|
2375
|
+
_this.pageDurationTracker.stop();
|
|
2262
2376
|
};
|
|
2263
|
-
/**
|
|
2264
|
-
* 添加到待发送请求队列
|
|
2265
|
-
* @param params 数据参数
|
|
2266
|
-
*/
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
_this.addToPendingRequests = function (params) {
|
|
2270
|
-
// 从 LocalStorage 获取当前队列
|
|
2271
|
-
var currentRequests = _this.getPendingRequestsFromStorage(); // 添加新数据
|
|
2272
2377
|
|
|
2378
|
+
_this.clearBatchTimer = function () {
|
|
2379
|
+
_this.batchSender.clearTimer();
|
|
2380
|
+
};
|
|
2273
2381
|
|
|
2274
|
-
|
|
2382
|
+
_this.clearBatchQueue = function () {
|
|
2383
|
+
_this.batchSender.clearQueue();
|
|
2384
|
+
};
|
|
2275
2385
|
|
|
2276
|
-
|
|
2386
|
+
_this.setPageKey = function (pageKey, autoUpdate) {
|
|
2387
|
+
if (autoUpdate === void 0) {
|
|
2388
|
+
autoUpdate = false;
|
|
2389
|
+
}
|
|
2277
2390
|
|
|
2278
|
-
if (
|
|
2279
|
-
|
|
2391
|
+
if (pageKey === null || pageKey === "") {
|
|
2392
|
+
_this.useCustomPageKey = false;
|
|
2393
|
+
var pathname = window.location.pathname;
|
|
2394
|
+
_this.pageKey = pathname.replace(/\//g, "_").substring(1);
|
|
2280
2395
|
|
|
2281
2396
|
if (_this.initConfig.showLog) {
|
|
2282
|
-
_this.printLog("\
|
|
2397
|
+
_this.printLog("\u9875\u9762\u6807\u8BC6\u5DF2\u6062\u590D\u81EA\u52A8\u751F\u6210: " + _this.pageKey);
|
|
2283
2398
|
}
|
|
2284
|
-
|
|
2285
|
-
_this.savePendingRequestsToStorage(trimmedRequests);
|
|
2286
2399
|
} else {
|
|
2287
|
-
_this.
|
|
2288
|
-
|
|
2289
|
-
};
|
|
2290
|
-
/**
|
|
2291
|
-
* 从 LocalStorage 恢复待发送请求
|
|
2292
|
-
*/
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
_this.restorePendingRequestsFromStorage = function () {
|
|
2296
|
-
var pendingRequests = _this.getPendingRequestsFromStorage();
|
|
2400
|
+
_this.pageKey = pageKey;
|
|
2401
|
+
_this.useCustomPageKey = !autoUpdate;
|
|
2297
2402
|
|
|
2298
|
-
if (pendingRequests.length > 0) {
|
|
2299
2403
|
if (_this.initConfig.showLog) {
|
|
2300
|
-
_this.printLog("\
|
|
2301
|
-
}
|
|
2302
|
-
// 数据会留在 LocalStorage 中,等待下次正常发送或页面卸载时发送
|
|
2303
|
-
// 这样可以避免与批量队列冲突
|
|
2304
|
-
|
|
2404
|
+
_this.printLog("\u9875\u9762\u6807\u8BC6\u5DF2\u8BBE\u7F6E\u4E3A: " + pageKey + ", \u81EA\u52A8\u66F4\u65B0: " + autoUpdate);
|
|
2405
|
+
}
|
|
2305
2406
|
}
|
|
2306
2407
|
};
|
|
2307
|
-
/**
|
|
2308
|
-
* 检查页面是否即将卸载
|
|
2309
|
-
* @returns 如果页面即将卸载返回 true,否则返回 false
|
|
2310
|
-
*/
|
|
2311
|
-
|
|
2312
2408
|
|
|
2313
|
-
_this.
|
|
2314
|
-
return
|
|
2409
|
+
_this.getPageKey = function () {
|
|
2410
|
+
return _this.pageKey;
|
|
2315
2411
|
};
|
|
2316
|
-
/**
|
|
2317
|
-
* 使用 sendBeacon 发送数据(页面卸载时的备用方案)
|
|
2318
|
-
* @param params 数据参数
|
|
2319
|
-
* @param serverUrl 服务器地址
|
|
2320
|
-
* @param contentType 内容类型
|
|
2321
|
-
* @returns 是否发送成功
|
|
2322
|
-
*/
|
|
2323
2412
|
|
|
2413
|
+
_this.onClickCallback = function (e) {
|
|
2414
|
+
var _a;
|
|
2324
2415
|
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
return navigator.sendBeacon(serverUrl, blob);
|
|
2331
|
-
} catch (e) {
|
|
2332
|
-
if (_this.initConfig.showLog) {
|
|
2333
|
-
_this.printLog("sendBeacon \u53D1\u9001\u5931\u8D25: " + e);
|
|
2334
|
-
}
|
|
2335
|
-
|
|
2336
|
-
return false;
|
|
2337
|
-
}
|
|
2338
|
-
};
|
|
2339
|
-
/**
|
|
2340
|
-
* 刷新待发送的单个请求(正常情况下的发送)
|
|
2341
|
-
* 注意:这个方法会直接使用 ajax 发送,避免通过 sendData 导致重复
|
|
2342
|
-
*/
|
|
2416
|
+
var target = e.target;
|
|
2417
|
+
if (!((_a = target === null || target === void 0 ? void 0 : target.dataset) === null || _a === void 0 ? void 0 : _a.partKey)) return;
|
|
2418
|
+
var position = [e.pageX, e.pageY];
|
|
2419
|
+
var id = target.id;
|
|
2420
|
+
var className = target.className;
|
|
2343
2421
|
|
|
2422
|
+
var business = _this.extractDataAttributes(target);
|
|
2344
2423
|
|
|
2345
|
-
|
|
2346
|
-
var pendingRequests = _this.getPendingRequestsFromStorage();
|
|
2424
|
+
var desc = target.getAttribute("data-desc") || _this.eventDescMap["WebClick"];
|
|
2347
2425
|
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
} // 清除 LocalStorage 中的待发送请求
|
|
2426
|
+
var partKey = target.getAttribute("data-part-key");
|
|
2427
|
+
var pageKey = target.getAttribute("data-page-key") || undefined;
|
|
2351
2428
|
|
|
2429
|
+
var params = _this.getParams({
|
|
2430
|
+
event: "WebClick",
|
|
2431
|
+
desc: desc,
|
|
2432
|
+
itemKey: _this.getItemKey(partKey, pageKey),
|
|
2433
|
+
privateParamMap: {
|
|
2434
|
+
business: business,
|
|
2435
|
+
targetEle: {
|
|
2436
|
+
nodeName: target.nodeName,
|
|
2437
|
+
id: id,
|
|
2438
|
+
className: className,
|
|
2439
|
+
position: position
|
|
2440
|
+
}
|
|
2441
|
+
}
|
|
2442
|
+
});
|
|
2352
2443
|
|
|
2353
|
-
_this.
|
|
2444
|
+
_this.sendData(params);
|
|
2445
|
+
};
|
|
2354
2446
|
|
|
2447
|
+
_this.onPageViewCallback = function (e) {
|
|
2448
|
+
var _a, _b;
|
|
2355
2449
|
|
|
2356
|
-
var
|
|
2357
|
-
serverUrl = _a.serverUrl,
|
|
2358
|
-
sendTimeout = _a.sendTimeout,
|
|
2359
|
-
contentType = _a.contentType,
|
|
2360
|
-
showLog = _a.showLog,
|
|
2361
|
-
initHeader = _a.header;
|
|
2362
|
-
pendingRequests.forEach(function (params) {
|
|
2363
|
-
// 数据采样判断
|
|
2364
|
-
if (!_this.shouldSample()) {
|
|
2365
|
-
if (showLog) {
|
|
2366
|
-
_this.printLog("待发送请求已采样跳过");
|
|
2367
|
-
}
|
|
2450
|
+
var ORGIN = window.location.origin;
|
|
2368
2451
|
|
|
2369
|
-
|
|
2452
|
+
var params = _this.getParams({
|
|
2453
|
+
event: "PageView",
|
|
2454
|
+
desc: _this.eventDescMap["PageView"],
|
|
2455
|
+
privateParamMap: {
|
|
2456
|
+
currentUrl: _this.currentUrl,
|
|
2457
|
+
targetUrl: ((_a = e.arguments) === null || _a === void 0 ? void 0 : _a[2]) ? ORGIN + ((_b = e.arguments) === null || _b === void 0 ? void 0 : _b[2]) : null
|
|
2370
2458
|
}
|
|
2371
|
-
|
|
2372
|
-
if (showLog) {
|
|
2373
|
-
_this.printLog(params);
|
|
2374
|
-
} // 直接使用 ajax 发送
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
_this.ajax({
|
|
2378
|
-
header: initHeader,
|
|
2379
|
-
url: serverUrl,
|
|
2380
|
-
type: "POST",
|
|
2381
|
-
data: JSON.stringify(params),
|
|
2382
|
-
contentType: contentType,
|
|
2383
|
-
credentials: false,
|
|
2384
|
-
timeout: sendTimeout,
|
|
2385
|
-
cors: true,
|
|
2386
|
-
success: function success() {
|
|
2387
|
-
if (showLog) {
|
|
2388
|
-
_this.printLog("待发送请求发送成功");
|
|
2389
|
-
}
|
|
2390
|
-
},
|
|
2391
|
-
error: function error(err) {
|
|
2392
|
-
if (showLog) {
|
|
2393
|
-
_this.printLog("\u5F85\u53D1\u9001\u8BF7\u6C42\u53D1\u9001\u5931\u8D25\uFF08\u4E0D\u518D\u91CD\u8BD5\uFF09: " + err);
|
|
2394
|
-
}
|
|
2395
|
-
}
|
|
2396
|
-
});
|
|
2397
2459
|
});
|
|
2398
|
-
};
|
|
2399
|
-
/**
|
|
2400
|
-
* 设置页面卸载监听器,确保数据发送
|
|
2401
|
-
*/
|
|
2402
2460
|
|
|
2461
|
+
_this.currentUrl = window.location.href;
|
|
2403
2462
|
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
if (_this.isUnloadListenerSetup) {
|
|
2407
|
-
return;
|
|
2463
|
+
if (!_this.useCustomPageKey) {
|
|
2464
|
+
_this.pageKey = window.location.pathname.replace(/\//g, "_").substring(1);
|
|
2408
2465
|
}
|
|
2409
2466
|
|
|
2410
|
-
_this.
|
|
2467
|
+
if (_this.initConfig.autoTrackPageDurationInterval) {
|
|
2468
|
+
_this.pageDurationTracker.stop();
|
|
2411
2469
|
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
_this.flushPendingData();
|
|
2415
|
-
}
|
|
2416
|
-
}); // 使用 beforeunload 事件作为备用(页面关闭/刷新)
|
|
2470
|
+
_this.pageDurationTracker.start();
|
|
2471
|
+
}
|
|
2417
2472
|
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
|
|
2473
|
+
_this.sendRetained(e.type);
|
|
2474
|
+
|
|
2475
|
+
_this.sendData(params);
|
|
2476
|
+
};
|
|
2421
2477
|
|
|
2422
|
-
|
|
2423
|
-
|
|
2478
|
+
_this.sendRetained = function (type) {
|
|
2479
|
+
var params = _this.getParams({
|
|
2480
|
+
event: "PageRetained",
|
|
2481
|
+
desc: _this.eventDescMap["PageRetained"]
|
|
2424
2482
|
});
|
|
2425
|
-
}; // 标记是否正在刷新待发送数据,避免重复发送
|
|
2426
2483
|
|
|
2484
|
+
if (["beforeunload", "pushState", "replaceState", "hashchange", "popstate"].indexOf(type) >= 0) {
|
|
2485
|
+
var __time = _this.getCookie("retainedStartTime");
|
|
2427
2486
|
|
|
2428
|
-
|
|
2429
|
-
/**
|
|
2430
|
-
* 刷新待发送数据(在页面卸载/跳转时调用)
|
|
2431
|
-
*/
|
|
2487
|
+
var retainedStartTime = __time ? +__time : _this.getTimeStamp();
|
|
2432
2488
|
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2489
|
+
var retainedData = __assign(__assign({}, params), {
|
|
2490
|
+
privateParamMap: __assign(__assign({}, params.privateParamMap), {
|
|
2491
|
+
retainedDuration: Math.max(params.requestTime - retainedStartTime, 0)
|
|
2492
|
+
})
|
|
2493
|
+
});
|
|
2438
2494
|
|
|
2495
|
+
_this.sendData(retainedData);
|
|
2439
2496
|
|
|
2440
|
-
|
|
2497
|
+
_this.setCookie("retainedStartTime", _this.getTimeStamp());
|
|
2498
|
+
}
|
|
2499
|
+
};
|
|
2441
2500
|
|
|
2501
|
+
_this.getParams = function (_a) {
|
|
2502
|
+
var event = _a.event,
|
|
2503
|
+
desc = _a.desc,
|
|
2504
|
+
_b = _a.privateParamMap,
|
|
2505
|
+
privateParamMap = _b === void 0 ? {} : _b,
|
|
2506
|
+
itemKey = _a.itemKey;
|
|
2507
|
+
var business = _this.initConfig.business;
|
|
2508
|
+
var pageWidth = window.innerWidth;
|
|
2509
|
+
var pageHeight = window.innerHeight;
|
|
2510
|
+
var screenWidth = window.screen.width;
|
|
2511
|
+
var screenHeight = window.screen.height;
|
|
2442
2512
|
|
|
2443
|
-
var
|
|
2513
|
+
var filteredBusiness = _this.filterSensitiveData(business || {});
|
|
2444
2514
|
|
|
2445
|
-
var
|
|
2515
|
+
var filteredUserInfo = _this.filterSensitiveData(_this.userInfo || {});
|
|
2446
2516
|
|
|
2447
|
-
|
|
2448
|
-
allPendingData.push.apply(allPendingData, batchQueue);
|
|
2449
|
-
} // 如果有待发送的单个请求,也添加到列表
|
|
2517
|
+
var filteredPrivateParamMap = _this.filterSensitiveData(privateParamMap || {});
|
|
2450
2518
|
|
|
2519
|
+
var filteredUrlParams = _this.filterSensitiveData(_this.getQueryValue() || {});
|
|
2451
2520
|
|
|
2452
|
-
var
|
|
2521
|
+
var privateParamMapData = {
|
|
2522
|
+
currentUrl: filteredPrivateParamMap.currentUrl || _this.currentUrl,
|
|
2523
|
+
business: Object.assign({}, filteredBusiness, filteredPrivateParamMap.business || {}),
|
|
2524
|
+
pageWidth: pageWidth,
|
|
2525
|
+
pageHeight: pageHeight,
|
|
2526
|
+
screenWidth: screenWidth,
|
|
2527
|
+
screenHeight: screenHeight,
|
|
2528
|
+
sdkVersion: _this.sdkVersion,
|
|
2529
|
+
systemsInfo: _this.systemsInfo,
|
|
2530
|
+
urlParams: filteredUrlParams,
|
|
2531
|
+
userInfo: filteredUserInfo,
|
|
2532
|
+
deviceId: _this.deviceId
|
|
2533
|
+
};
|
|
2453
2534
|
|
|
2454
|
-
if (
|
|
2455
|
-
|
|
2535
|
+
if (filteredPrivateParamMap.targetEle) {
|
|
2536
|
+
privateParamMapData.targetEle = filteredPrivateParamMap.targetEle;
|
|
2456
2537
|
}
|
|
2457
2538
|
|
|
2458
|
-
if (
|
|
2459
|
-
|
|
2460
|
-
}
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
_this.isFlushingPendingData = true; // 先保存到 LocalStorage,确保数据不丢失(在发送前保存)
|
|
2539
|
+
if (filteredPrivateParamMap.targetUrl) {
|
|
2540
|
+
privateParamMapData.targetUrl = filteredPrivateParamMap.targetUrl;
|
|
2541
|
+
}
|
|
2464
2542
|
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
} else {
|
|
2469
|
-
_this.setLocalStorage(_this.PENDING_REQUESTS_STORAGE_KEY, JSON.stringify(allPendingData));
|
|
2470
|
-
}
|
|
2471
|
-
} catch (e) {
|
|
2472
|
-
if (_this.initConfig.showLog) {
|
|
2473
|
-
_this.printLog("\u4FDD\u5B58\u5F85\u53D1\u9001\u8BF7\u6C42\u5230 LocalStorage \u5931\u8D25: " + e);
|
|
2474
|
-
}
|
|
2475
|
-
} // 使用 sendBeacon 发送数据(最可靠的方式)
|
|
2543
|
+
if (filteredPrivateParamMap.pointerType) {
|
|
2544
|
+
privateParamMapData.pointerType = filteredPrivateParamMap.pointerType;
|
|
2545
|
+
}
|
|
2476
2546
|
|
|
2547
|
+
if (filteredPrivateParamMap.elementSelector) {
|
|
2548
|
+
privateParamMapData.elementSelector = filteredPrivateParamMap.elementSelector;
|
|
2549
|
+
}
|
|
2477
2550
|
|
|
2478
|
-
if (
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
var dataToSend = allPendingData.length === 1 ? allPendingData[0] : allPendingData;
|
|
2482
|
-
var blob = new Blob([JSON.stringify(dataToSend)], {
|
|
2483
|
-
type: _this.initConfig.contentType || "application/json"
|
|
2484
|
-
});
|
|
2485
|
-
var sent = navigator.sendBeacon(_this.initConfig.serverUrl, blob);
|
|
2551
|
+
if (filteredPrivateParamMap.retainedDuration) {
|
|
2552
|
+
privateParamMapData.retainedDuration = filteredPrivateParamMap.retainedDuration;
|
|
2553
|
+
}
|
|
2486
2554
|
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2555
|
+
if (filteredPrivateParamMap.exposureScreenNo !== undefined) {
|
|
2556
|
+
privateParamMapData.exposureScreenNo = filteredPrivateParamMap.exposureScreenNo;
|
|
2557
|
+
}
|
|
2490
2558
|
|
|
2491
|
-
|
|
2559
|
+
return {
|
|
2560
|
+
event: event,
|
|
2561
|
+
desc: desc,
|
|
2562
|
+
itemKey: itemKey || _this.getItemKey(),
|
|
2563
|
+
requestTime: _this.getTimeStamp(),
|
|
2564
|
+
privateParamMap: privateParamMapData
|
|
2565
|
+
};
|
|
2566
|
+
};
|
|
2492
2567
|
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
_this.printLog("sendBeacon \u8FD4\u56DE false\uFF0C\u6570\u636E\u5DF2\u4FDD\u5B58\u5230 LocalStorage \u7B49\u5F85\u4E0B\u6B21\u6062\u590D");
|
|
2500
|
-
}
|
|
2501
|
-
}
|
|
2502
|
-
} catch (e) {
|
|
2503
|
-
// sendBeacon 失败,数据已在 LocalStorage 中,等待下次恢复
|
|
2504
|
-
if (_this.initConfig.showLog) {
|
|
2505
|
-
_this.printLog("\u9875\u9762\u5378\u8F7D\u65F6\u53D1\u9001\u6570\u636E\u5931\u8D25: " + e + "\uFF0C\u6570\u636E\u5DF2\u4FDD\u5B58\u5230 LocalStorage");
|
|
2506
|
-
}
|
|
2507
|
-
} finally {
|
|
2508
|
-
// 重置标记
|
|
2509
|
-
_this.isFlushingPendingData = false;
|
|
2510
|
-
}
|
|
2511
|
-
} else {
|
|
2512
|
-
// 不支持 sendBeacon,数据已在 LocalStorage 中,等待下次恢复
|
|
2513
|
-
if (_this.initConfig.showLog) {
|
|
2514
|
-
_this.printLog("\u4E0D\u652F\u6301 sendBeacon\uFF0C\u6570\u636E\u5DF2\u4FDD\u5B58\u5230 LocalStorage \u7B49\u5F85\u4E0B\u6B21\u6062\u590D");
|
|
2515
|
-
} // 重置标记
|
|
2568
|
+
_this.shouldSample = function () {
|
|
2569
|
+
var sampleRate = _this.initConfig.sampleRate;
|
|
2570
|
+
if (sampleRate >= 1) return true;
|
|
2571
|
+
if (sampleRate <= 0) return false;
|
|
2572
|
+
return Math.random() < sampleRate;
|
|
2573
|
+
};
|
|
2516
2574
|
|
|
2575
|
+
_this.shouldUseBeacon = function (sendMethod, header, initHeader) {
|
|
2576
|
+
if (sendMethod === "beacon") return true;
|
|
2577
|
+
if (sendMethod === "xhr") return false;
|
|
2517
2578
|
|
|
2518
|
-
|
|
2579
|
+
if (header || initHeader) {
|
|
2580
|
+
return false;
|
|
2519
2581
|
}
|
|
2520
|
-
};
|
|
2521
|
-
/**
|
|
2522
|
-
* 发送数据通用函数
|
|
2523
|
-
*/
|
|
2524
2582
|
|
|
2583
|
+
return typeof navigator.sendBeacon === "function";
|
|
2584
|
+
};
|
|
2525
2585
|
|
|
2526
2586
|
_this.sendData = function (params, header) {
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
|
|
2531
|
-
|
|
2532
|
-
});
|
|
2533
|
-
}
|
|
2587
|
+
return new Promise(function (resolve, reject) {
|
|
2588
|
+
if (!_this.shouldSample()) {
|
|
2589
|
+
if (_this.initConfig.showLog) {
|
|
2590
|
+
_this.printLog("数据已采样跳过");
|
|
2591
|
+
}
|
|
2534
2592
|
|
|
2535
|
-
|
|
2536
|
-
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
|
|
2540
|
-
|
|
2541
|
-
batchSend = _a.batchSend,
|
|
2542
|
-
sendMethod = _a.sendMethod;
|
|
2543
|
-
if (!!showLog) _this.printLog(params); // 如果启用批量发送
|
|
2593
|
+
resolve({
|
|
2594
|
+
success: false,
|
|
2595
|
+
message: "数据已采样跳过"
|
|
2596
|
+
});
|
|
2597
|
+
return;
|
|
2598
|
+
}
|
|
2544
2599
|
|
|
2545
|
-
|
|
2546
|
-
|
|
2600
|
+
if (_this.initConfig.showLog) {
|
|
2601
|
+
_this.printLog(params);
|
|
2602
|
+
}
|
|
2547
2603
|
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
message: "已添加到批量队列"
|
|
2551
|
-
});
|
|
2552
|
-
} // 判断是否使用 sendBeacon
|
|
2604
|
+
if (_this.initConfig.batchSend) {
|
|
2605
|
+
_this.batchSender.addToQueue(params);
|
|
2553
2606
|
|
|
2607
|
+
resolve({
|
|
2608
|
+
success: true,
|
|
2609
|
+
message: "数据已加入批量队列"
|
|
2610
|
+
});
|
|
2611
|
+
return;
|
|
2612
|
+
}
|
|
2554
2613
|
|
|
2555
|
-
|
|
2614
|
+
var _a = _this.initConfig,
|
|
2615
|
+
serverUrl = _a.serverUrl,
|
|
2616
|
+
sendTimeout = _a.sendTimeout,
|
|
2617
|
+
contentType = _a.contentType,
|
|
2618
|
+
showLog = _a.showLog,
|
|
2619
|
+
initHeader = _a.header;
|
|
2556
2620
|
|
|
2621
|
+
var useBeacon = _this.shouldUseBeacon(_this.initConfig.sendMethod, header, initHeader);
|
|
2557
2622
|
|
|
2558
|
-
|
|
2559
|
-
// 检查页面是否即将卸载,如果是,直接使用 sendBeacon 发送,避免被取消
|
|
2560
|
-
if (_this.isPageUnloading()) {
|
|
2623
|
+
if (useBeacon) {
|
|
2561
2624
|
var sent = _this.sendWithBeacon(params, serverUrl, contentType);
|
|
2562
2625
|
|
|
2563
2626
|
if (sent) {
|
|
2564
|
-
|
|
2627
|
+
resolve({
|
|
2565
2628
|
success: true,
|
|
2566
|
-
message: "
|
|
2629
|
+
message: "数据发送成功"
|
|
2567
2630
|
});
|
|
2568
2631
|
} else {
|
|
2569
|
-
|
|
2570
|
-
_this.addToPendingRequests(params);
|
|
2632
|
+
_this.pendingRequestsManager.addToQueue(params);
|
|
2571
2633
|
|
|
2572
|
-
|
|
2573
|
-
success:
|
|
2574
|
-
message: "
|
|
2634
|
+
resolve({
|
|
2635
|
+
success: false,
|
|
2636
|
+
message: "sendBeacon 发送失败,数据已加入待发送队列"
|
|
2575
2637
|
});
|
|
2576
2638
|
}
|
|
2577
|
-
}
|
|
2578
|
-
|
|
2579
|
-
|
|
2580
|
-
return _this.sendBeacon({
|
|
2581
|
-
contentType: contentType,
|
|
2582
|
-
url: serverUrl,
|
|
2583
|
-
data: params
|
|
2584
|
-
}).catch(function (err) {
|
|
2585
|
-
// sendBeacon 失败,添加到待发送队列,避免数据丢失
|
|
2586
|
-
_this.addToPendingRequests(params);
|
|
2587
|
-
|
|
2588
|
-
return Promise.resolve({
|
|
2589
|
-
success: true,
|
|
2590
|
-
message: "sendBeacon 失败,已添加到待发送队列"
|
|
2591
|
-
});
|
|
2592
|
-
});
|
|
2593
|
-
} else {
|
|
2594
|
-
// 使用 XMLHttpRequest 发送
|
|
2595
|
-
return new Promise(function (resolve, reject) {
|
|
2596
|
-
// 如果页面即将卸载且配置为 auto,尝试使用 sendBeacon 作为备用
|
|
2597
|
-
if (_this.isPageUnloading() && sendMethod === 'auto' && _this.isSupportBeaconSend() && !header && !initHeader) {
|
|
2598
|
-
var sent = _this.sendWithBeacon(params, serverUrl, contentType);
|
|
2599
|
-
|
|
2600
|
-
if (sent) {
|
|
2601
|
-
resolve({
|
|
2602
|
-
success: true,
|
|
2603
|
-
message: "页面卸载时使用 sendBeacon 发送成功"
|
|
2604
|
-
});
|
|
2605
|
-
return;
|
|
2606
|
-
} // sendBeacon 失败,继续使用 XMLHttpRequest
|
|
2607
|
-
|
|
2608
|
-
}
|
|
2609
|
-
|
|
2639
|
+
} else {
|
|
2610
2640
|
_this.ajax({
|
|
2611
|
-
header: header || initHeader,
|
|
2612
2641
|
url: serverUrl,
|
|
2613
2642
|
type: "POST",
|
|
2614
2643
|
data: JSON.stringify(params),
|
|
2615
2644
|
contentType: contentType,
|
|
2645
|
+
header: header || initHeader,
|
|
2616
2646
|
credentials: false,
|
|
2617
2647
|
timeout: sendTimeout,
|
|
2618
2648
|
cors: true,
|
|
2619
|
-
success: function success(
|
|
2620
|
-
|
|
2649
|
+
success: function success(data) {
|
|
2650
|
+
if (showLog) {
|
|
2651
|
+
_this.printLog("数据发送成功", data);
|
|
2652
|
+
}
|
|
2653
|
+
|
|
2654
|
+
resolve({
|
|
2621
2655
|
success: true,
|
|
2622
|
-
data:
|
|
2656
|
+
data: data
|
|
2623
2657
|
});
|
|
2624
2658
|
},
|
|
2625
|
-
error: function error(err
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
var sent = _this.sendWithBeacon(params, serverUrl, contentType);
|
|
2629
|
-
|
|
2630
|
-
if (sent) {
|
|
2631
|
-
resolve({
|
|
2632
|
-
success: true,
|
|
2633
|
-
message: "XMLHttpRequest 失败,已使用 sendBeacon 发送"
|
|
2634
|
-
});
|
|
2635
|
-
return;
|
|
2636
|
-
}
|
|
2659
|
+
error: function error(err) {
|
|
2660
|
+
if (showLog) {
|
|
2661
|
+
_this.printLog("数据发送失败", err);
|
|
2637
2662
|
}
|
|
2638
2663
|
|
|
2664
|
+
_this.pendingRequestsManager.addToQueue(params);
|
|
2665
|
+
|
|
2639
2666
|
reject({
|
|
2640
2667
|
success: false,
|
|
2641
|
-
message:
|
|
2642
|
-
|
|
2668
|
+
message: "数据发送失败",
|
|
2669
|
+
error: err
|
|
2643
2670
|
});
|
|
2644
2671
|
}
|
|
2645
2672
|
});
|
|
2646
|
-
}
|
|
2647
|
-
}
|
|
2648
|
-
};
|
|
2649
|
-
/**
|
|
2650
|
-
* @description 判断是否应该使用 sendBeacon
|
|
2651
|
-
* @param sendMethod 配置的发送方式
|
|
2652
|
-
* @param header 自定义 header
|
|
2653
|
-
* @param initHeader 初始化配置的 header
|
|
2654
|
-
* @returns 是否使用 sendBeacon
|
|
2655
|
-
*/
|
|
2656
|
-
|
|
2657
|
-
|
|
2658
|
-
_this.shouldUseBeacon = function (sendMethod, header, initHeader) {
|
|
2659
|
-
// 如果配置为 xhr,不使用 beacon
|
|
2660
|
-
if (sendMethod === 'xhr') {
|
|
2661
|
-
return false;
|
|
2662
|
-
} // 如果配置为 beacon,检查是否支持
|
|
2663
|
-
|
|
2664
|
-
|
|
2665
|
-
if (sendMethod === 'beacon') {
|
|
2666
|
-
return _this.isSupportBeaconSend() === true;
|
|
2667
|
-
} // 如果配置为 auto(默认),使用原有逻辑
|
|
2668
|
-
// 只有在支持 sendBeacon 且没有自定义 header 时才使用
|
|
2669
|
-
|
|
2670
|
-
|
|
2671
|
-
return _this.isSupportBeaconSend() === true && !header && !initHeader;
|
|
2672
|
-
};
|
|
2673
|
-
/**
|
|
2674
|
-
* @description 留存时长上报
|
|
2675
|
-
* @param type
|
|
2676
|
-
*/
|
|
2677
|
-
|
|
2678
|
-
|
|
2679
|
-
_this.sendRetained = function (type) {
|
|
2680
|
-
var params = _this.getParams({
|
|
2681
|
-
event: "PageRetained",
|
|
2682
|
-
desc: _this.eventDescMap["PageRetained"]
|
|
2673
|
+
}
|
|
2683
2674
|
});
|
|
2675
|
+
};
|
|
2684
2676
|
|
|
2685
|
-
|
|
2686
|
-
|
|
2687
|
-
|
|
2688
|
-
|
|
2689
|
-
|
|
2690
|
-
var retainedData = __assign(__assign({}, params), {
|
|
2691
|
-
privateParamMap: __assign(__assign({}, params.privateParamMap), {
|
|
2692
|
-
retainedDuration: Math.max(params.requestTime - retainedStartTime, 0)
|
|
2693
|
-
})
|
|
2677
|
+
_this.sendWithBeacon = function (params, serverUrl, contentType) {
|
|
2678
|
+
try {
|
|
2679
|
+
var blob = new Blob([JSON.stringify(params)], {
|
|
2680
|
+
type: contentType || "application/json"
|
|
2694
2681
|
});
|
|
2682
|
+
return navigator.sendBeacon(serverUrl, blob);
|
|
2683
|
+
} catch (e) {
|
|
2684
|
+
if (_this.initConfig.showLog) {
|
|
2685
|
+
_this.printLog("sendBeacon \u53D1\u9001\u5931\u8D25: " + e);
|
|
2686
|
+
}
|
|
2695
2687
|
|
|
2696
|
-
|
|
2697
|
-
|
|
2698
|
-
_this.setCookie("retainedStartTime", _this.getTimeStamp());
|
|
2688
|
+
return false;
|
|
2699
2689
|
}
|
|
2700
2690
|
};
|
|
2701
|
-
/**
|
|
2702
|
-
* @description 用户主动上报页面停留时长
|
|
2703
|
-
* @param duration 自定义停留时长(毫秒),如果不传则自动计算从页面加载(或上次调用)到当前的时长
|
|
2704
|
-
* @param options 可选参数,包括自定义描述、业务参数等
|
|
2705
|
-
* @param resetStartTime 是否重置起始时间,默认 true(手动上报后重置,定时上报不重置)
|
|
2706
|
-
* @returns Promise<TrackingResponse> 上报结果
|
|
2707
|
-
*/
|
|
2708
|
-
|
|
2709
2691
|
|
|
2710
2692
|
_this.trackPageDuration = function (duration, options, resetStartTime) {
|
|
2711
2693
|
if (resetStartTime === void 0) {
|
|
2712
2694
|
resetStartTime = true;
|
|
2713
|
-
}
|
|
2714
|
-
|
|
2715
|
-
|
|
2716
|
-
var retainedDuration;
|
|
2717
|
-
|
|
2718
|
-
if (duration !== undefined && duration !== null) {
|
|
2719
|
-
// 使用自定义时长
|
|
2720
|
-
retainedDuration = Math.max(duration, 0);
|
|
2721
|
-
} else {
|
|
2722
|
-
// 自动计算时长
|
|
2723
|
-
var __time = _this.getCookie("retainedStartTime");
|
|
2724
|
-
|
|
2725
|
-
var retainedStartTime = __time ? +__time : _this.getTimeStamp();
|
|
2726
|
-
|
|
2727
|
-
var currentTime = _this.getTimeStamp();
|
|
2728
|
-
|
|
2729
|
-
retainedDuration = Math.max(currentTime - retainedStartTime, 0);
|
|
2730
|
-
} // 构建参数
|
|
2695
|
+
}
|
|
2731
2696
|
|
|
2697
|
+
var retainedDuration = _this.pageDurationTracker.calculateDuration(duration);
|
|
2732
2698
|
|
|
2733
2699
|
var desc = (options === null || options === void 0 ? void 0 : options.desc) || _this.eventDescMap["PageRetained"];
|
|
2734
2700
|
var pageKey = (options === null || options === void 0 ? void 0 : options.pageKey) || _this.pageKey;
|
|
@@ -2743,12 +2709,9 @@ function (_super) {
|
|
|
2743
2709
|
business: business,
|
|
2744
2710
|
retainedDuration: retainedDuration
|
|
2745
2711
|
}
|
|
2746
|
-
});
|
|
2747
|
-
|
|
2748
|
-
|
|
2749
|
-
var result = _this.sendData(params, header); // 根据 resetStartTime 参数决定是否重置起始时间
|
|
2750
|
-
// 手动上报后重置起始时间,定时上报不重置(累积计算)
|
|
2712
|
+
});
|
|
2751
2713
|
|
|
2714
|
+
var result = _this.sendData(params, header);
|
|
2752
2715
|
|
|
2753
2716
|
if (resetStartTime) {
|
|
2754
2717
|
_this.setCookie("retainedStartTime", _this.getTimeStamp());
|
|
@@ -2756,230 +2719,41 @@ function (_super) {
|
|
|
2756
2719
|
|
|
2757
2720
|
return result;
|
|
2758
2721
|
};
|
|
2759
|
-
/**
|
|
2760
|
-
* @description 启动定时上报页面停留时长的定时器
|
|
2761
|
-
*/
|
|
2762
|
-
|
|
2763
|
-
|
|
2764
|
-
_this.startPageDurationTimer = function () {
|
|
2765
|
-
// 先停止现有的定时器(避免重复启动)
|
|
2766
|
-
_this.stopPageDurationTimer();
|
|
2767
|
-
|
|
2768
|
-
var interval = _this.initConfig.pageDurationInterval || 30000; // 检查间隔时间是否有效
|
|
2769
|
-
|
|
2770
|
-
if (interval <= 0) {
|
|
2771
|
-
if (_this.initConfig.showLog) {
|
|
2772
|
-
_this.printLog("定时上报间隔时间无效,已禁用定时上报");
|
|
2773
|
-
}
|
|
2774
|
-
|
|
2775
|
-
return;
|
|
2776
|
-
} // 启动定时器
|
|
2777
|
-
|
|
2778
|
-
|
|
2779
|
-
_this.pageDurationTimer = window.setInterval(function () {
|
|
2780
|
-
// 只在页面可见时上报(避免后台上报)
|
|
2781
|
-
if (document.visibilityState === "visible") {
|
|
2782
|
-
// 定时上报:retainedDuration 直接使用上报间隔时间,数据工程师会清洗数据
|
|
2783
|
-
_this.trackPageDuration(interval, {
|
|
2784
|
-
desc: "定时上报页面停留时长",
|
|
2785
|
-
business: {
|
|
2786
|
-
reportType: "interval",
|
|
2787
|
-
interval: interval
|
|
2788
|
-
}
|
|
2789
|
-
}, true).catch(function (err) {
|
|
2790
|
-
if (_this.initConfig.showLog) {
|
|
2791
|
-
_this.printLog("\u5B9A\u65F6\u4E0A\u62A5\u9875\u9762\u505C\u7559\u65F6\u957F\u5931\u8D25: " + err);
|
|
2792
|
-
}
|
|
2793
|
-
});
|
|
2794
|
-
}
|
|
2795
|
-
}, interval);
|
|
2796
|
-
|
|
2797
|
-
if (_this.initConfig.showLog) {
|
|
2798
|
-
_this.printLog("\u5B9A\u65F6\u4E0A\u62A5\u9875\u9762\u505C\u7559\u65F6\u957F\u5DF2\u542F\u52A8\uFF0C\u95F4\u9694: " + interval + "ms");
|
|
2799
|
-
}
|
|
2800
|
-
};
|
|
2801
|
-
/**
|
|
2802
|
-
* @description 停止定时上报页面停留时长的定时器
|
|
2803
|
-
*/
|
|
2804
2722
|
|
|
2723
|
+
_this.getItemKey = function (partKey, pageKey) {
|
|
2724
|
+
var _pageKey = pageKey !== undefined ? pageKey : _this.pageKey;
|
|
2805
2725
|
|
|
2806
|
-
|
|
2807
|
-
if (_this.pageDurationTimer !== null) {
|
|
2808
|
-
clearInterval(_this.pageDurationTimer);
|
|
2809
|
-
_this.pageDurationTimer = null;
|
|
2726
|
+
var _partKey = partKey !== undefined ? partKey : "";
|
|
2810
2727
|
|
|
2811
|
-
|
|
2812
|
-
|
|
2813
|
-
}
|
|
2728
|
+
if (_partKey) {
|
|
2729
|
+
return _this.initConfig.appKey + "." + _pageKey + "." + _partKey;
|
|
2814
2730
|
}
|
|
2815
|
-
};
|
|
2816
|
-
/**
|
|
2817
|
-
* @description 获取 itemKey
|
|
2818
|
-
* @param {[string]} partkey [控件/自定义事件的唯一标识]
|
|
2819
|
-
* @return {[string]}
|
|
2820
|
-
*/
|
|
2821
|
-
|
|
2822
2731
|
|
|
2823
|
-
|
|
2824
|
-
var appKey = _this.initConfig.appKey;
|
|
2825
|
-
var keys = [appKey, (pageKey || _this.pageKey).toString(), partkey ? partkey.toString() : undefined].filter(function (key) {
|
|
2826
|
-
return !!key;
|
|
2827
|
-
});
|
|
2828
|
-
return keys.reduce(function (str, key) {
|
|
2829
|
-
return str + ("" + (str.length ? "." : "")) + key;
|
|
2830
|
-
}, "");
|
|
2732
|
+
return _this.initConfig.appKey + "." + _pageKey;
|
|
2831
2733
|
};
|
|
2832
|
-
/**
|
|
2833
|
-
* @description 从元素或其祖先节点提取 data-* 属性
|
|
2834
|
-
* @param element 目标元素
|
|
2835
|
-
* @returns 提取的业务参数对象
|
|
2836
|
-
*/
|
|
2837
|
-
|
|
2838
2734
|
|
|
2839
2735
|
_this.extractDataAttributes = function (element) {
|
|
2840
2736
|
var business = {};
|
|
2841
|
-
var currentElement = element;
|
|
2842
|
-
|
|
2843
|
-
while (currentElement) {
|
|
2844
|
-
var attributes = currentElement.attributes;
|
|
2845
|
-
|
|
2846
|
-
for (var i = 0; i < attributes.length; i++) {
|
|
2847
|
-
var attr = attributes[i];
|
|
2848
|
-
var name_1 = attr.name;
|
|
2849
2737
|
|
|
2850
|
-
|
|
2851
|
-
|
|
2738
|
+
for (var i = 0; i < element.attributes.length; i++) {
|
|
2739
|
+
var name_1 = element.attributes[i].name;
|
|
2852
2740
|
|
|
2853
|
-
|
|
2854
|
-
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
|
|
2858
|
-
}
|
|
2859
|
-
}
|
|
2860
|
-
}
|
|
2861
|
-
|
|
2862
|
-
currentElement = currentElement.parentElement;
|
|
2863
|
-
|
|
2864
|
-
if (currentElement && currentElement.tagName === 'BODY') {
|
|
2865
|
-
break;
|
|
2741
|
+
if (name_1.startsWith("data-") && name_1 !== "data-exposure" && name_1 !== "data-part-key" && name_1 !== "data-desc" && name_1 !== "data-page-key") {
|
|
2742
|
+
var key = name_1.replace("data-", "").replace(/-([a-z])/g, function (_, letter) {
|
|
2743
|
+
return letter.toUpperCase();
|
|
2744
|
+
});
|
|
2745
|
+
business[key] = element.getAttribute(name_1);
|
|
2866
2746
|
}
|
|
2867
2747
|
}
|
|
2868
2748
|
|
|
2869
2749
|
return business;
|
|
2870
2750
|
};
|
|
2871
|
-
/**
|
|
2872
|
-
* @description 初始化曝光监听
|
|
2873
|
-
*/
|
|
2874
|
-
|
|
2875
|
-
|
|
2876
|
-
_this.initExposureObserver = function () {
|
|
2877
|
-
if (!_this.initConfig.autoTrackExposure) {
|
|
2878
|
-
return;
|
|
2879
|
-
}
|
|
2880
|
-
|
|
2881
|
-
if (!('IntersectionObserver' in window)) {
|
|
2882
|
-
if (_this.initConfig.showLog) {
|
|
2883
|
-
_this.printLog('当前浏览器不支持 IntersectionObserver,无法启用曝光埋点');
|
|
2884
|
-
}
|
|
2885
|
-
|
|
2886
|
-
return;
|
|
2887
|
-
}
|
|
2888
|
-
|
|
2889
|
-
var threshold = _this.initConfig.exposureThreshold || 0.5;
|
|
2890
|
-
_this.exposureObserver = new IntersectionObserver(function (entries) {
|
|
2891
|
-
entries.forEach(function (entry) {
|
|
2892
|
-
var element = entry.target;
|
|
2893
|
-
|
|
2894
|
-
var elementInfo = _this.exposureElementsMap.get(element);
|
|
2895
|
-
|
|
2896
|
-
if (!elementInfo) {
|
|
2897
|
-
return;
|
|
2898
|
-
}
|
|
2899
|
-
|
|
2900
|
-
var exposureTime = _this.initConfig.exposureTime || 500;
|
|
2901
|
-
|
|
2902
|
-
if (entry.isIntersecting) {
|
|
2903
|
-
elementInfo.isVisible = true;
|
|
2904
|
-
elementInfo.visibleStartTime = _this.getTimeStamp();
|
|
2905
|
-
|
|
2906
|
-
if (elementInfo.exposureTimer) {
|
|
2907
|
-
clearTimeout(elementInfo.exposureTimer);
|
|
2908
|
-
}
|
|
2909
|
-
|
|
2910
|
-
elementInfo.exposureTimer = window.setTimeout(function () {
|
|
2911
|
-
if (elementInfo.isVisible) {
|
|
2912
|
-
_this.reportExposure(element);
|
|
2913
|
-
}
|
|
2914
|
-
}, exposureTime);
|
|
2915
|
-
} else {
|
|
2916
|
-
elementInfo.isVisible = false;
|
|
2917
|
-
|
|
2918
|
-
if (elementInfo.exposureTimer) {
|
|
2919
|
-
clearTimeout(elementInfo.exposureTimer);
|
|
2920
|
-
elementInfo.exposureTimer = null;
|
|
2921
|
-
}
|
|
2922
|
-
}
|
|
2923
|
-
});
|
|
2924
|
-
}, {
|
|
2925
|
-
threshold: threshold
|
|
2926
|
-
});
|
|
2927
|
-
|
|
2928
|
-
_this.observeExposureElements();
|
|
2929
|
-
|
|
2930
|
-
_this.initMutationObserver();
|
|
2931
|
-
};
|
|
2932
|
-
/**
|
|
2933
|
-
* @description 添加单个曝光元素到监听
|
|
2934
|
-
* @param element 曝光元素
|
|
2935
|
-
*/
|
|
2936
|
-
|
|
2937
|
-
|
|
2938
|
-
_this.addExposureElement = function (element) {
|
|
2939
|
-
if (!_this.exposureElementsMap.has(element)) {
|
|
2940
|
-
_this.exposureElementsMap.set(element, {
|
|
2941
|
-
element: element,
|
|
2942
|
-
visibleStartTime: 0,
|
|
2943
|
-
exposureCount: 0,
|
|
2944
|
-
isVisible: false,
|
|
2945
|
-
exposureTimer: null
|
|
2946
|
-
});
|
|
2947
|
-
|
|
2948
|
-
if (_this.exposureObserver) {
|
|
2949
|
-
_this.exposureObserver.observe(element);
|
|
2950
|
-
}
|
|
2951
|
-
}
|
|
2952
|
-
};
|
|
2953
|
-
/**
|
|
2954
|
-
* @description 监听页面上的曝光元素
|
|
2955
|
-
*/
|
|
2956
|
-
|
|
2957
|
-
|
|
2958
|
-
_this.observeExposureElements = function () {
|
|
2959
|
-
if (!_this.exposureObserver) {
|
|
2960
|
-
return;
|
|
2961
|
-
}
|
|
2962
|
-
|
|
2963
|
-
var elements = document.querySelectorAll('[data-exposure="true"]');
|
|
2964
|
-
elements.forEach(function (element) {
|
|
2965
|
-
_this.addExposureElement(element);
|
|
2966
|
-
});
|
|
2967
|
-
|
|
2968
|
-
if (_this.initConfig.showLog && elements.length > 0) {
|
|
2969
|
-
_this.printLog("\u5DF2\u76D1\u542C " + elements.length + " \u4E2A\u66DD\u5149\u5143\u7D20");
|
|
2970
|
-
}
|
|
2971
|
-
};
|
|
2972
|
-
/**
|
|
2973
|
-
* @description 上报曝光事件
|
|
2974
|
-
* @param element 曝光元素
|
|
2975
|
-
*/
|
|
2976
2751
|
|
|
2977
|
-
|
|
2978
|
-
|
|
2979
|
-
var elementInfo = _this.exposureElementsMap.get(element);
|
|
2752
|
+
_this.handleExposureReport = function (element, exposureScreenIndex) {
|
|
2753
|
+
var elementInfo = _this.exposureTracker.getElementInfo(element);
|
|
2980
2754
|
|
|
2981
2755
|
if (!elementInfo) {
|
|
2982
|
-
return;
|
|
2756
|
+
return Promise.resolve();
|
|
2983
2757
|
}
|
|
2984
2758
|
|
|
2985
2759
|
var exposureNum = _this.initConfig.exposureNum;
|
|
@@ -2989,34 +2763,33 @@ function (_super) {
|
|
|
2989
2763
|
_this.printLog("\u5143\u7D20\u5DF2\u8FBE\u5230\u6700\u5927\u66DD\u5149\u6B21\u6570\u9650\u5236: " + exposureNum);
|
|
2990
2764
|
}
|
|
2991
2765
|
|
|
2992
|
-
return;
|
|
2766
|
+
return Promise.resolve();
|
|
2993
2767
|
}
|
|
2994
2768
|
|
|
2995
2769
|
var business = _this.extractDataAttributes(element);
|
|
2996
2770
|
|
|
2997
|
-
var desc = element.getAttribute(
|
|
2771
|
+
var desc = element.getAttribute("data-desc") || _this.eventDescMap["WebExposure"];
|
|
2998
2772
|
|
|
2999
|
-
var
|
|
2773
|
+
var partKey = element.getAttribute("data-part-key") || "exposure";
|
|
2774
|
+
var pageKey = element.getAttribute("data-page-key") || undefined;
|
|
3000
2775
|
|
|
3001
2776
|
var params = _this.getParams({
|
|
3002
|
-
event:
|
|
2777
|
+
event: "WebExposure",
|
|
3003
2778
|
desc: desc,
|
|
3004
|
-
itemKey: _this.getItemKey(
|
|
2779
|
+
itemKey: _this.getItemKey(partKey, pageKey),
|
|
3005
2780
|
privateParamMap: {
|
|
3006
|
-
business: business
|
|
2781
|
+
business: business,
|
|
2782
|
+
exposureScreenNo: exposureScreenIndex
|
|
3007
2783
|
}
|
|
3008
2784
|
});
|
|
3009
2785
|
|
|
3010
|
-
_this.sendData(params).then(function () {
|
|
3011
|
-
|
|
2786
|
+
return _this.sendData(params).then(function () {
|
|
2787
|
+
_this.exposureTracker.incrementExposureCount(element);
|
|
3012
2788
|
|
|
3013
|
-
|
|
3014
|
-
clearTimeout(elementInfo.exposureTimer);
|
|
3015
|
-
elementInfo.exposureTimer = null;
|
|
3016
|
-
}
|
|
2789
|
+
_this.exposureTracker.clearExposureTimer(element);
|
|
3017
2790
|
|
|
3018
2791
|
if (_this.initConfig.showLog) {
|
|
3019
|
-
_this.printLog("\u66DD\u5149\u4E0A\u62A5\u6210\u529F\uFF0C\u5F53\u524D\u66DD\u5149\u6B21\u6570: " + elementInfo.exposureCount);
|
|
2792
|
+
_this.printLog("\u66DD\u5149\u4E0A\u62A5\u6210\u529F\uFF0C\u5F53\u524D\u66DD\u5149\u6B21\u6570: " + (elementInfo.exposureCount + 1));
|
|
3020
2793
|
}
|
|
3021
2794
|
}).catch(function (err) {
|
|
3022
2795
|
if (_this.initConfig.showLog) {
|
|
@@ -3024,81 +2797,8 @@ function (_super) {
|
|
|
3024
2797
|
}
|
|
3025
2798
|
});
|
|
3026
2799
|
};
|
|
3027
|
-
/**
|
|
3028
|
-
* @description 初始化 MutationObserver 监听动态添加的元素
|
|
3029
|
-
*/
|
|
3030
|
-
|
|
3031
|
-
|
|
3032
|
-
_this.initMutationObserver = function () {
|
|
3033
|
-
if (!('MutationObserver' in window)) {
|
|
3034
|
-
if (_this.initConfig.showLog) {
|
|
3035
|
-
_this.printLog('当前浏览器不支持 MutationObserver,无法监听动态添加的曝光元素');
|
|
3036
|
-
}
|
|
3037
|
-
|
|
3038
|
-
return;
|
|
3039
|
-
}
|
|
3040
|
-
|
|
3041
|
-
_this.mutationObserver = new MutationObserver(function (mutations) {
|
|
3042
|
-
mutations.forEach(function (mutation) {
|
|
3043
|
-
mutation.addedNodes.forEach(function (node) {
|
|
3044
|
-
if (node.nodeType === Node.ELEMENT_NODE) {
|
|
3045
|
-
var element = node;
|
|
3046
|
-
|
|
3047
|
-
if (element.hasAttribute('data-exposure') && element.getAttribute('data-exposure') === 'true') {
|
|
3048
|
-
_this.addExposureElement(element);
|
|
3049
|
-
} else {
|
|
3050
|
-
var exposureElements = element.querySelectorAll('[data-exposure="true"]');
|
|
3051
|
-
exposureElements.forEach(function (exposureElement) {
|
|
3052
|
-
_this.addExposureElement(exposureElement);
|
|
3053
|
-
});
|
|
3054
|
-
}
|
|
3055
|
-
}
|
|
3056
|
-
});
|
|
3057
|
-
});
|
|
3058
|
-
});
|
|
3059
|
-
|
|
3060
|
-
_this.mutationObserver.observe(document.body, {
|
|
3061
|
-
childList: true,
|
|
3062
|
-
subtree: true
|
|
3063
|
-
});
|
|
3064
|
-
|
|
3065
|
-
if (_this.initConfig.showLog) {
|
|
3066
|
-
_this.printLog('MutationObserver 已启动,监听动态添加的曝光元素');
|
|
3067
|
-
}
|
|
3068
|
-
};
|
|
3069
|
-
/**
|
|
3070
|
-
* @description 停止曝光监听
|
|
3071
|
-
*/
|
|
3072
|
-
|
|
3073
|
-
|
|
3074
|
-
_this.stopExposureObserver = function () {
|
|
3075
|
-
if (_this.exposureObserver) {
|
|
3076
|
-
_this.exposureObserver.disconnect();
|
|
3077
|
-
|
|
3078
|
-
_this.exposureObserver = null;
|
|
3079
|
-
|
|
3080
|
-
_this.exposureElementsMap.forEach(function (elementInfo) {
|
|
3081
|
-
if (elementInfo.exposureTimer) {
|
|
3082
|
-
clearTimeout(elementInfo.exposureTimer);
|
|
3083
|
-
}
|
|
3084
|
-
});
|
|
3085
|
-
|
|
3086
|
-
_this.exposureElementsMap.clear();
|
|
3087
|
-
}
|
|
3088
|
-
|
|
3089
|
-
if (_this.mutationObserver) {
|
|
3090
|
-
_this.mutationObserver.disconnect();
|
|
3091
|
-
|
|
3092
|
-
_this.mutationObserver = null;
|
|
3093
|
-
}
|
|
3094
|
-
|
|
3095
|
-
if (_this.initConfig.showLog) {
|
|
3096
|
-
_this.printLog('曝光监听已停止');
|
|
3097
|
-
}
|
|
3098
|
-
};
|
|
3099
|
-
|
|
3100
|
-
_this.sdkVersion = "1.2.4"; // sdk版本
|
|
3101
2800
|
|
|
2801
|
+
_this.sdkVersion = "1.2.4";
|
|
3102
2802
|
_this.initConfig = {
|
|
3103
2803
|
appKey: "",
|
|
3104
2804
|
platform: undefined,
|
|
@@ -3122,18 +2822,74 @@ function (_super) {
|
|
|
3122
2822
|
autoTrackExposure: false,
|
|
3123
2823
|
exposureThreshold: 0.5,
|
|
3124
2824
|
exposureTime: 500,
|
|
3125
|
-
exposureNum: undefined
|
|
3126
|
-
|
|
3127
|
-
}; // 系统信息
|
|
3128
|
-
|
|
2825
|
+
exposureNum: undefined
|
|
2826
|
+
};
|
|
3129
2827
|
_this.systemsInfo = {};
|
|
2828
|
+
_this.deviceManager = new DeviceManager({
|
|
2829
|
+
getCookie: _this.getCookie.bind(_this),
|
|
2830
|
+
setCookie: _this.setCookie.bind(_this),
|
|
2831
|
+
getLocalStorage: _this.getLocalStorage.bind(_this),
|
|
2832
|
+
setLocalStorage: _this.setLocalStorage.bind(_this),
|
|
2833
|
+
collectFingerprint: _this.collectFingerprint.bind(_this),
|
|
2834
|
+
hashFingerprint: _this.hashFingerprint.bind(_this)
|
|
2835
|
+
});
|
|
2836
|
+
_this.batchSender = new BatchSender({
|
|
2837
|
+
batchSend: false,
|
|
2838
|
+
batchInterval: 5000,
|
|
2839
|
+
batchMaxSize: 10,
|
|
2840
|
+
sendTimeout: 3000,
|
|
2841
|
+
serverUrl: "",
|
|
2842
|
+
contentType: "application/json",
|
|
2843
|
+
showLog: false,
|
|
2844
|
+
sendMethod: "auto",
|
|
2845
|
+
header: undefined
|
|
2846
|
+
}, {
|
|
2847
|
+
getLocalStorage: _this.getLocalStorage.bind(_this),
|
|
2848
|
+
setLocalStorage: _this.setLocalStorage.bind(_this),
|
|
2849
|
+
getTimeStamp: _this.getTimeStamp.bind(_this),
|
|
2850
|
+
ajax: _this.ajax.bind(_this),
|
|
2851
|
+
shouldSample: _this.shouldSample.bind(_this),
|
|
2852
|
+
shouldUseBeacon: _this.shouldUseBeacon.bind(_this),
|
|
2853
|
+
printLog: _this.printLog.bind(_this)
|
|
2854
|
+
});
|
|
2855
|
+
_this.pendingRequestsManager = new PendingRequestsManager({
|
|
2856
|
+
pendingRequestsMaxSize: 50,
|
|
2857
|
+
sendTimeout: 3000,
|
|
2858
|
+
serverUrl: "",
|
|
2859
|
+
contentType: "application/json",
|
|
2860
|
+
showLog: false,
|
|
2861
|
+
header: undefined
|
|
2862
|
+
}, {
|
|
2863
|
+
getLocalStorage: _this.getLocalStorage.bind(_this),
|
|
2864
|
+
setLocalStorage: _this.setLocalStorage.bind(_this),
|
|
2865
|
+
shouldSample: _this.shouldSample.bind(_this),
|
|
2866
|
+
ajax: _this.ajax.bind(_this),
|
|
2867
|
+
printLog: _this.printLog.bind(_this)
|
|
2868
|
+
});
|
|
2869
|
+
_this.pageDurationTracker = new PageDurationTracker({
|
|
2870
|
+
pageDurationInterval: 30000,
|
|
2871
|
+
showLog: false
|
|
2872
|
+
}, {
|
|
2873
|
+
getCookie: _this.getCookie.bind(_this),
|
|
2874
|
+
setCookie: _this.setCookie.bind(_this),
|
|
2875
|
+
getTimeStamp: _this.getTimeStamp.bind(_this),
|
|
2876
|
+
track: _this.trackPageDuration.bind(_this),
|
|
2877
|
+
printLog: _this.printLog.bind(_this)
|
|
2878
|
+
});
|
|
2879
|
+
_this.exposureTracker = new ExposureTracker({
|
|
2880
|
+
autoTrackExposure: false,
|
|
2881
|
+
exposureThreshold: 0.5,
|
|
2882
|
+
exposureTime: 500,
|
|
2883
|
+
exposureNum: undefined,
|
|
2884
|
+
showLog: false
|
|
2885
|
+
}, {
|
|
2886
|
+
reportExposure: _this.handleExposureReport.bind(_this),
|
|
2887
|
+
printLog: _this.printLog.bind(_this),
|
|
2888
|
+
getTimeStamp: _this.getTimeStamp.bind(_this),
|
|
2889
|
+
extractDataAttributes: _this.extractDataAttributes.bind(_this)
|
|
2890
|
+
});
|
|
3130
2891
|
return _this;
|
|
3131
2892
|
}
|
|
3132
|
-
/**
|
|
3133
|
-
* @description 添加单页面监听事件
|
|
3134
|
-
* @param callback
|
|
3135
|
-
*/
|
|
3136
|
-
|
|
3137
2893
|
|
|
3138
2894
|
WebTracking.prototype.addSinglePageEvent = function (callback) {
|
|
3139
2895
|
var _this = this;
|