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