customer-chat-sdk 1.1.1 → 1.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/core/CustomerSDK.d.ts +1 -0
- package/dist/core/CustomerSDK.d.ts.map +1 -1
- package/dist/core/IconManager.d.ts +6 -1
- package/dist/core/IconManager.d.ts.map +1 -1
- package/dist/core/IframeManager.d.ts +1 -0
- package/dist/core/IframeManager.d.ts.map +1 -1
- package/dist/core/ScreenshotManager.d.ts +1 -1
- package/dist/core/ScreenshotManager.d.ts.map +1 -1
- package/dist/customer-sdk.cjs.js +253 -146
- package/dist/customer-sdk.esm.js +253 -146
- package/dist/customer-sdk.min.js +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/types/index.d.ts +2 -1
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/customer-sdk.esm.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// 直接使用base64字符串,避免打包后路径问题
|
|
2
2
|
const iconImage = 'data:image/png;base64,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';
|
|
3
3
|
class IconManager {
|
|
4
|
-
constructor(position, debug = false) {
|
|
4
|
+
constructor(position, debug = false, target) {
|
|
5
5
|
this.iconElement = null;
|
|
6
6
|
this.badgeElement = null;
|
|
7
7
|
this.onClickCallback = null;
|
|
@@ -19,8 +19,11 @@ class IconManager {
|
|
|
19
19
|
this.iconPosition = null; // 图标位置配置
|
|
20
20
|
this.debug = false; // debug 模式标志
|
|
21
21
|
this.isClickEnabled = true; // 是否允许点击(iframe 打开时禁用)
|
|
22
|
+
this.target = null; // 图标传送目标元素(可以是 HTMLElement 或选择器字符串)
|
|
22
23
|
this.iconPosition = position || null;
|
|
23
24
|
this.debug = debug;
|
|
25
|
+
// 保存 target(可以是 HTMLElement 或字符串选择器)
|
|
26
|
+
this.target = target || null;
|
|
24
27
|
}
|
|
25
28
|
/**
|
|
26
29
|
* 显示悬浮图标
|
|
@@ -119,8 +122,18 @@ class IconManager {
|
|
|
119
122
|
this.iconElement.appendChild(imgContainer);
|
|
120
123
|
// 添加拖动和点击事件
|
|
121
124
|
this.setupDragEvents();
|
|
122
|
-
//
|
|
123
|
-
|
|
125
|
+
// 添加到目标元素(如果 target 是字符串,需要重新查找,因为可能在初始化时元素还不存在)
|
|
126
|
+
const targetElement = this.getTargetElement();
|
|
127
|
+
if (targetElement) {
|
|
128
|
+
targetElement.appendChild(this.iconElement);
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
// 如果目标元素不存在,回退到 document.body
|
|
132
|
+
document.body.appendChild(this.iconElement);
|
|
133
|
+
if (this.debug) {
|
|
134
|
+
console.warn('Target element not found, icon added to document.body');
|
|
135
|
+
}
|
|
136
|
+
}
|
|
124
137
|
if (this.debug) {
|
|
125
138
|
console.log('CustomerSDK icon displayed');
|
|
126
139
|
}
|
|
@@ -493,6 +506,44 @@ class IconManager {
|
|
|
493
506
|
this.iconElement.style.cursor = 'pointer';
|
|
494
507
|
}
|
|
495
508
|
}
|
|
509
|
+
/**
|
|
510
|
+
* 获取目标元素(支持动态查找)
|
|
511
|
+
*/
|
|
512
|
+
getTargetElement() {
|
|
513
|
+
if (!this.target) {
|
|
514
|
+
return document.body;
|
|
515
|
+
}
|
|
516
|
+
// 如果 target 是字符串选择器,每次都需要重新查找(支持动态元素)
|
|
517
|
+
if (typeof this.target === 'string') {
|
|
518
|
+
const element = document.querySelector(this.target);
|
|
519
|
+
if (element) {
|
|
520
|
+
return element;
|
|
521
|
+
}
|
|
522
|
+
else {
|
|
523
|
+
// 如果元素不存在,回退到 document.body
|
|
524
|
+
if (this.debug) {
|
|
525
|
+
console.warn(`Target element not found: ${this.target}, falling back to document.body`);
|
|
526
|
+
}
|
|
527
|
+
return document.body;
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
// 如果 target 是 HTMLElement
|
|
531
|
+
if (this.target instanceof HTMLElement) {
|
|
532
|
+
// 检查元素是否还在 DOM 中
|
|
533
|
+
if (document.body.contains(this.target)) {
|
|
534
|
+
return this.target;
|
|
535
|
+
}
|
|
536
|
+
else {
|
|
537
|
+
// 如果元素不在 DOM 中,回退到 document.body
|
|
538
|
+
if (this.debug) {
|
|
539
|
+
console.warn('Target element no longer in DOM, falling back to document.body');
|
|
540
|
+
}
|
|
541
|
+
return document.body;
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
// 默认回退到 document.body
|
|
545
|
+
return document.body;
|
|
546
|
+
}
|
|
496
547
|
/**
|
|
497
548
|
* 创建消息徽章(简化版)
|
|
498
549
|
*/
|
|
@@ -572,7 +623,15 @@ class IframeManager {
|
|
|
572
623
|
*/
|
|
573
624
|
async init() {
|
|
574
625
|
try {
|
|
626
|
+
// PC模式:预创建遮罩层(隐藏状态),避免后续移动DOM导致iframe重新加载
|
|
627
|
+
const actualMode = this.getActualMode();
|
|
628
|
+
const isPC = actualMode === 'popup';
|
|
629
|
+
if (isPC) {
|
|
630
|
+
// 创建遮罩层但不立即显示(showImmediately = false)
|
|
631
|
+
this.createOverlay(false);
|
|
632
|
+
}
|
|
575
633
|
// 创建隐藏的iframe(预连接到SSE)
|
|
634
|
+
// 注意:createIframe 会将容器添加到遮罩层(PC模式)或 body(移动端)
|
|
576
635
|
this.createIframe();
|
|
577
636
|
this.isCreated = true;
|
|
578
637
|
if (this.debug) {
|
|
@@ -600,10 +659,30 @@ class IframeManager {
|
|
|
600
659
|
const isPC = actualMode === 'popup';
|
|
601
660
|
// PC模式:创建或显示遮罩层
|
|
602
661
|
if (isPC) {
|
|
603
|
-
|
|
662
|
+
// 如果遮罩层不存在,创建并显示;如果已存在,直接显示
|
|
663
|
+
this.createOverlay(true); // showImmediately = true,立即显示
|
|
604
664
|
}
|
|
605
665
|
// 显示已创建的容器
|
|
666
|
+
// 关键优化:容器在 init() 时已经添加到正确位置,这里只改变样式,不移动 DOM
|
|
667
|
+
// 这样可以避免 iframe 重新加载
|
|
606
668
|
if (this.containerElement) {
|
|
669
|
+
// 确保容器在 DOM 中(理论上已经在 init() 时添加,但为了安全)
|
|
670
|
+
if (!this.containerElement.parentNode) {
|
|
671
|
+
// 如果容器不在 DOM 中(异常情况),根据模式添加到正确位置
|
|
672
|
+
if (isPC && this.overlayElement) {
|
|
673
|
+
// PC模式:确保遮罩层在 DOM 中,然后将容器添加到遮罩层
|
|
674
|
+
if (!this.overlayElement.parentNode) {
|
|
675
|
+
document.body.appendChild(this.overlayElement);
|
|
676
|
+
}
|
|
677
|
+
this.overlayElement.appendChild(this.containerElement);
|
|
678
|
+
}
|
|
679
|
+
else {
|
|
680
|
+
// 移动端模式:直接添加到 body
|
|
681
|
+
document.body.appendChild(this.containerElement);
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
// 注意:不再检查容器是否在遮罩层内,因为 init() 时已经正确放置
|
|
685
|
+
// 如果移动容器会导致 iframe 重新加载,所以不移动
|
|
607
686
|
if (isPC) {
|
|
608
687
|
// PC模式:配置为居中弹窗样式
|
|
609
688
|
Object.assign(this.containerElement.style, {
|
|
@@ -615,17 +694,18 @@ class IframeManager {
|
|
|
615
694
|
opacity: '1',
|
|
616
695
|
display: 'block'
|
|
617
696
|
});
|
|
618
|
-
//
|
|
619
|
-
// 只有当容器不在遮罩层内时才移动,且确保遮罩层在 DOM 中
|
|
697
|
+
// 显示遮罩层(确保在 DOM 中)
|
|
620
698
|
if (this.overlayElement) {
|
|
621
|
-
//
|
|
699
|
+
// 确保遮罩层在 DOM 中
|
|
622
700
|
if (!this.overlayElement.parentNode) {
|
|
623
701
|
document.body.appendChild(this.overlayElement);
|
|
624
702
|
}
|
|
625
|
-
//
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
703
|
+
// 显示遮罩层(只改变样式,不移动)
|
|
704
|
+
Object.assign(this.overlayElement.style, {
|
|
705
|
+
visibility: 'visible',
|
|
706
|
+
opacity: '1',
|
|
707
|
+
display: 'flex'
|
|
708
|
+
});
|
|
629
709
|
}
|
|
630
710
|
}
|
|
631
711
|
else {
|
|
@@ -706,11 +786,16 @@ class IframeManager {
|
|
|
706
786
|
*/
|
|
707
787
|
destroy() {
|
|
708
788
|
this.hide();
|
|
789
|
+
// 移除容器和遮罩层
|
|
709
790
|
if (this.containerElement) {
|
|
710
791
|
this.containerElement.remove();
|
|
711
792
|
this.containerElement = null;
|
|
712
793
|
this.iframeElement = null;
|
|
713
794
|
}
|
|
795
|
+
if (this.overlayElement) {
|
|
796
|
+
this.overlayElement.remove();
|
|
797
|
+
this.overlayElement = null;
|
|
798
|
+
}
|
|
714
799
|
this.isCreated = false;
|
|
715
800
|
if (this.debug) {
|
|
716
801
|
console.log('CustomerSDK container destroyed');
|
|
@@ -732,25 +817,23 @@ class IframeManager {
|
|
|
732
817
|
}
|
|
733
818
|
/**
|
|
734
819
|
* 创建遮罩层(PC模式使用)
|
|
820
|
+
* @param showImmediately 是否立即显示,默认 false(用于 init() 时创建但不显示)
|
|
735
821
|
*/
|
|
736
|
-
createOverlay() {
|
|
737
|
-
//
|
|
738
|
-
if (this.overlayElement
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
opacity: '1',
|
|
752
|
-
display: 'flex'
|
|
753
|
-
});
|
|
822
|
+
createOverlay(showImmediately = false) {
|
|
823
|
+
// 如果遮罩层已存在
|
|
824
|
+
if (this.overlayElement) {
|
|
825
|
+
// 如果不在 DOM 中,添加到 DOM
|
|
826
|
+
if (!this.overlayElement.parentNode) {
|
|
827
|
+
document.body.appendChild(this.overlayElement);
|
|
828
|
+
}
|
|
829
|
+
// 根据参数决定是否显示
|
|
830
|
+
if (showImmediately) {
|
|
831
|
+
Object.assign(this.overlayElement.style, {
|
|
832
|
+
visibility: 'visible',
|
|
833
|
+
opacity: '1',
|
|
834
|
+
display: 'flex'
|
|
835
|
+
});
|
|
836
|
+
}
|
|
754
837
|
return;
|
|
755
838
|
}
|
|
756
839
|
// 创建新的遮罩层
|
|
@@ -764,10 +847,12 @@ class IframeManager {
|
|
|
764
847
|
height: '100%',
|
|
765
848
|
backgroundColor: 'rgba(0, 0, 0, 0.5)',
|
|
766
849
|
zIndex: '999998',
|
|
767
|
-
display: 'flex',
|
|
850
|
+
display: showImmediately ? 'flex' : 'none', // 根据参数决定初始显示状态
|
|
768
851
|
alignItems: 'center',
|
|
769
852
|
justifyContent: 'center',
|
|
770
|
-
cursor: this.config.allowClose ? 'pointer' : 'default'
|
|
853
|
+
cursor: this.config.allowClose ? 'pointer' : 'default',
|
|
854
|
+
visibility: showImmediately ? 'visible' : 'hidden',
|
|
855
|
+
opacity: showImmediately ? '1' : '0'
|
|
771
856
|
});
|
|
772
857
|
// 点击遮罩层关闭(只添加一次事件监听器)
|
|
773
858
|
if (this.config.allowClose) {
|
|
@@ -897,8 +982,16 @@ class IframeManager {
|
|
|
897
982
|
this.injectMobileStyles();
|
|
898
983
|
}
|
|
899
984
|
});
|
|
900
|
-
//
|
|
901
|
-
|
|
985
|
+
// 关键优化:PC模式将容器添加到遮罩层(如果遮罩层已创建),避免后续移动DOM导致iframe重新加载
|
|
986
|
+
// 移动端直接添加到body
|
|
987
|
+
if (isPC && this.overlayElement) {
|
|
988
|
+
// PC模式:添加到遮罩层(遮罩层已在 init() 中创建)
|
|
989
|
+
this.overlayElement.appendChild(this.containerElement);
|
|
990
|
+
}
|
|
991
|
+
else {
|
|
992
|
+
// 移动端模式:直接添加到body
|
|
993
|
+
document.body.appendChild(this.containerElement);
|
|
994
|
+
}
|
|
902
995
|
if (this.debug) {
|
|
903
996
|
console.log('CustomerSDK container created (hidden, ready for SSE)');
|
|
904
997
|
}
|
|
@@ -14540,7 +14633,7 @@ class ScreenshotManager {
|
|
|
14540
14633
|
useProxy: options.useProxy ?? true, // 默认启用代理(如果配置了proxyUrl)
|
|
14541
14634
|
engine: options.engine ?? 'modern-screenshot',
|
|
14542
14635
|
corsMode: options.corsMode ?? 'canvas-proxy',
|
|
14543
|
-
|
|
14636
|
+
debug: options.debug !== undefined ? options.debug : false, // 默认 false,不输出日志
|
|
14544
14637
|
maxRetries: options.maxRetries ?? 2,
|
|
14545
14638
|
preloadImages: options.preloadImages ?? false, // 默认不预加载,按需加载
|
|
14546
14639
|
maxConcurrentDownloads: options.maxConcurrentDownloads ?? 10, // 增加并发数
|
|
@@ -14560,9 +14653,9 @@ class ScreenshotManager {
|
|
|
14560
14653
|
this.setupMessageListener();
|
|
14561
14654
|
this.setupVisibilityChangeListener();
|
|
14562
14655
|
// 打印初始化信息
|
|
14563
|
-
if (
|
|
14656
|
+
if (this.options.debug) {
|
|
14564
14657
|
console.log('📸 ScreenshotManager 初始化完成');
|
|
14565
|
-
console.log(`📸 配置: interval=${this.options.interval}ms, engine=${this.options.engine},
|
|
14658
|
+
console.log(`📸 配置: interval=${this.options.interval}ms, engine=${this.options.engine}, debug=${this.options.debug}`);
|
|
14566
14659
|
console.log('📸 等待 iframe 发送 checkScreenshot 消息...');
|
|
14567
14660
|
}
|
|
14568
14661
|
// 启动缓存清理定时器
|
|
@@ -14585,7 +14678,7 @@ class ScreenshotManager {
|
|
|
14585
14678
|
if (this.screenshotContext) {
|
|
14586
14679
|
try {
|
|
14587
14680
|
destroyContext(this.screenshotContext);
|
|
14588
|
-
if (
|
|
14681
|
+
if (this.options.debug) {
|
|
14589
14682
|
console.log('📸 目标元素变化,清理 context');
|
|
14590
14683
|
}
|
|
14591
14684
|
}
|
|
@@ -14608,7 +14701,7 @@ class ScreenshotManager {
|
|
|
14608
14701
|
this.handleIframeMessage(event);
|
|
14609
14702
|
};
|
|
14610
14703
|
window.addEventListener('message', this.messageHandler);
|
|
14611
|
-
if (
|
|
14704
|
+
if (this.options.debug) {
|
|
14612
14705
|
console.log('📸 消息监听器已设置,正在监听 iframe 消息...');
|
|
14613
14706
|
}
|
|
14614
14707
|
}
|
|
@@ -14618,12 +14711,12 @@ class ScreenshotManager {
|
|
|
14618
14711
|
setupVisibilityChangeListener() {
|
|
14619
14712
|
document.addEventListener('visibilitychange', () => {
|
|
14620
14713
|
if (document.hidden) {
|
|
14621
|
-
if (
|
|
14714
|
+
if (this.options.debug) {
|
|
14622
14715
|
console.log('📸 页面隐藏,截图轮询已暂停');
|
|
14623
14716
|
}
|
|
14624
14717
|
}
|
|
14625
14718
|
else {
|
|
14626
|
-
if (
|
|
14719
|
+
if (this.options.debug) {
|
|
14627
14720
|
console.log('📸 页面显示,截图轮询已恢复');
|
|
14628
14721
|
}
|
|
14629
14722
|
}
|
|
@@ -14640,7 +14733,7 @@ class ScreenshotManager {
|
|
|
14640
14733
|
}
|
|
14641
14734
|
// 如果提供了发送消息的回调,保存它(用于后续发送二进制数据)
|
|
14642
14735
|
// 注意:消息来源验证在 setupMessageListener 中处理
|
|
14643
|
-
if (
|
|
14736
|
+
if (this.options.debug) {
|
|
14644
14737
|
console.log('📸 [iframe] 收到消息:', event.data);
|
|
14645
14738
|
}
|
|
14646
14739
|
// 尝试解析为二进制配置(新格式)
|
|
@@ -14654,7 +14747,7 @@ class ScreenshotManager {
|
|
|
14654
14747
|
if (isValid) {
|
|
14655
14748
|
// 启用截图功能
|
|
14656
14749
|
if (!this.isEnabled) {
|
|
14657
|
-
if (
|
|
14750
|
+
if (this.options.debug) {
|
|
14658
14751
|
console.log('📸 [iframe] 启用截图功能(二进制模式)');
|
|
14659
14752
|
}
|
|
14660
14753
|
this.isEnabled = true;
|
|
@@ -14664,7 +14757,7 @@ class ScreenshotManager {
|
|
|
14664
14757
|
// 计算剩余有效时间(毫秒)
|
|
14665
14758
|
const remainingTime = binaryConfig.ttl - currentTime;
|
|
14666
14759
|
// 启动或更新截图轮询
|
|
14667
|
-
if (
|
|
14760
|
+
if (this.options.debug) {
|
|
14668
14761
|
const remainingMinutes = Math.ceil(remainingTime / 60000);
|
|
14669
14762
|
console.log(`📸 [iframe] 设置轮询间隔: ${this.dynamicInterval}ms,剩余有效时间: ${remainingMinutes}分钟`);
|
|
14670
14763
|
}
|
|
@@ -14676,7 +14769,7 @@ class ScreenshotManager {
|
|
|
14676
14769
|
this.expirationTimer = null;
|
|
14677
14770
|
}
|
|
14678
14771
|
this.expirationTimer = setTimeout(() => {
|
|
14679
|
-
if (
|
|
14772
|
+
if (this.options.debug) {
|
|
14680
14773
|
console.log('📸 [iframe] 二进制配置已过期,停止截图');
|
|
14681
14774
|
}
|
|
14682
14775
|
this.stopScreenshot();
|
|
@@ -14687,7 +14780,7 @@ class ScreenshotManager {
|
|
|
14687
14780
|
}
|
|
14688
14781
|
else {
|
|
14689
14782
|
// 禁用截图功能(ttl == 0 或已过期)
|
|
14690
|
-
if (
|
|
14783
|
+
if (this.options.debug) {
|
|
14691
14784
|
if (binaryConfig.ttl === 0) {
|
|
14692
14785
|
console.log('📸 [iframe] ttl == 0,禁用截图功能');
|
|
14693
14786
|
}
|
|
@@ -14706,11 +14799,15 @@ class ScreenshotManager {
|
|
|
14706
14799
|
return;
|
|
14707
14800
|
}
|
|
14708
14801
|
// 如果不是二进制配置格式,记录错误
|
|
14709
|
-
|
|
14802
|
+
if (this.options.debug) {
|
|
14803
|
+
console.error('📸 [iframe] 解析配置失败:未识别的配置格式');
|
|
14804
|
+
}
|
|
14710
14805
|
this.uploadError = '解析配置失败:仅支持二进制配置格式';
|
|
14711
14806
|
}
|
|
14712
14807
|
catch (error) {
|
|
14713
|
-
|
|
14808
|
+
if (this.options.debug) {
|
|
14809
|
+
console.error('📸 [iframe] 处理消息失败:', error);
|
|
14810
|
+
}
|
|
14714
14811
|
this.uploadError = error instanceof Error ? error.message : String(error);
|
|
14715
14812
|
}
|
|
14716
14813
|
}
|
|
@@ -14749,17 +14846,19 @@ class ScreenshotManager {
|
|
|
14749
14846
|
*/
|
|
14750
14847
|
startScreenshot(customInterval) {
|
|
14751
14848
|
if (!this.isEnabled) {
|
|
14752
|
-
|
|
14849
|
+
if (this.options.debug) {
|
|
14850
|
+
console.warn('📸 截图功能已禁用,无法启动');
|
|
14851
|
+
}
|
|
14753
14852
|
return;
|
|
14754
14853
|
}
|
|
14755
14854
|
const currentInterval = customInterval || this.dynamicInterval || this.options.interval;
|
|
14756
14855
|
if (this.isRunning) {
|
|
14757
|
-
if (
|
|
14856
|
+
if (this.options.debug) {
|
|
14758
14857
|
console.log(`📸 更新轮询间隔: ${currentInterval}ms`);
|
|
14759
14858
|
}
|
|
14760
14859
|
this.stopScreenshot();
|
|
14761
14860
|
}
|
|
14762
|
-
if (
|
|
14861
|
+
if (this.options.debug) {
|
|
14763
14862
|
console.log(`📸 开始轮询截图,间隔: ${currentInterval}ms`);
|
|
14764
14863
|
}
|
|
14765
14864
|
this.isRunning = true;
|
|
@@ -14772,7 +14871,7 @@ class ScreenshotManager {
|
|
|
14772
14871
|
const scheduleNext = async () => {
|
|
14773
14872
|
// 如果上次任务还没完成,等待完成
|
|
14774
14873
|
if (!this.isCurrentTaskCompleted) {
|
|
14775
|
-
if (
|
|
14874
|
+
if (this.options.debug) {
|
|
14776
14875
|
console.log('📸 [定时] 等待上次任务完成...');
|
|
14777
14876
|
}
|
|
14778
14877
|
// 每100ms检查一次任务是否完成
|
|
@@ -14792,7 +14891,7 @@ class ScreenshotManager {
|
|
|
14792
14891
|
this.isCurrentTaskCompleted = false;
|
|
14793
14892
|
// 记录定时开始时间
|
|
14794
14893
|
const scheduleStartTime = performance.now();
|
|
14795
|
-
if (
|
|
14894
|
+
if (this.options.debug) {
|
|
14796
14895
|
console.log(`📸 [定时开始] 开始新一轮截图任务`);
|
|
14797
14896
|
}
|
|
14798
14897
|
try {
|
|
@@ -14824,7 +14923,7 @@ class ScreenshotManager {
|
|
|
14824
14923
|
const combinedBufferSize = combinedBuffer.byteLength;
|
|
14825
14924
|
const combineTime = performance.now() - combineStartTime;
|
|
14826
14925
|
// 打印大小信息
|
|
14827
|
-
if (
|
|
14926
|
+
if (this.options.debug) {
|
|
14828
14927
|
console.log('📸 [轮询-大小统计]');
|
|
14829
14928
|
console.log(` Base64 大小: ${base64Size} 字符`);
|
|
14830
14929
|
console.log(` 图片字节大小: ${(imageBufferSize / 1024).toFixed(2)} KB (${imageBufferSize} 字节)`);
|
|
@@ -14845,7 +14944,7 @@ class ScreenshotManager {
|
|
|
14845
14944
|
const sendCallbackTime = performance.now() - sendCallbackStartTime;
|
|
14846
14945
|
const totalSendTime = performance.now() - sendStartTime;
|
|
14847
14946
|
const totalTime = performance.now() - scheduleStartTime;
|
|
14848
|
-
if (
|
|
14947
|
+
if (this.options.debug) {
|
|
14849
14948
|
console.log('📸 [轮询] ✅ 二进制数据已发送到 iframe');
|
|
14850
14949
|
console.log(` ⏱️ 发送回调耗时: ${sendCallbackTime.toFixed(2)}ms`);
|
|
14851
14950
|
console.log(` ⏱️ 发送阶段总耗时: ${totalSendTime.toFixed(2)}ms`);
|
|
@@ -14854,7 +14953,9 @@ class ScreenshotManager {
|
|
|
14854
14953
|
}
|
|
14855
14954
|
}
|
|
14856
14955
|
catch (error) {
|
|
14857
|
-
|
|
14956
|
+
if (this.options.debug) {
|
|
14957
|
+
console.error('📸 [轮询] ❌ 处理二进制数据失败:', error);
|
|
14958
|
+
}
|
|
14858
14959
|
}
|
|
14859
14960
|
}
|
|
14860
14961
|
// 任务完成(无压缩模式)
|
|
@@ -14863,7 +14964,7 @@ class ScreenshotManager {
|
|
|
14863
14964
|
else if (this.currentBinaryConfig && this.options.compress) {
|
|
14864
14965
|
// 启用了压缩,等待 Worker 压缩完成后在 onmessage 中发送
|
|
14865
14966
|
// 任务完成标志会在压缩完成的回调中设置
|
|
14866
|
-
if (
|
|
14967
|
+
if (this.options.debug) {
|
|
14867
14968
|
console.log('📸 [轮询] 等待 Worker 压缩完成后发送到 iframe...');
|
|
14868
14969
|
}
|
|
14869
14970
|
}
|
|
@@ -14873,7 +14974,7 @@ class ScreenshotManager {
|
|
|
14873
14974
|
}
|
|
14874
14975
|
}
|
|
14875
14976
|
catch (error) {
|
|
14876
|
-
if (
|
|
14977
|
+
if (this.options.debug) {
|
|
14877
14978
|
console.error('📸 [轮询] 截图失败:', error);
|
|
14878
14979
|
}
|
|
14879
14980
|
// 任务失败,标记为完成
|
|
@@ -14898,7 +14999,7 @@ class ScreenshotManager {
|
|
|
14898
14999
|
if (!this.isRunning) {
|
|
14899
15000
|
return;
|
|
14900
15001
|
}
|
|
14901
|
-
if (
|
|
15002
|
+
if (this.options.debug) {
|
|
14902
15003
|
console.log('📸 停止轮询截图');
|
|
14903
15004
|
}
|
|
14904
15005
|
this.isRunning = false;
|
|
@@ -14915,7 +15016,9 @@ class ScreenshotManager {
|
|
|
14915
15016
|
*/
|
|
14916
15017
|
async captureOnce(force = false) {
|
|
14917
15018
|
if (!this.isEnabled && !force) {
|
|
14918
|
-
|
|
15019
|
+
if (this.options.debug) {
|
|
15020
|
+
console.warn('📸 截图功能已禁用,无法执行截图。如需测试,请先调用 enable(true) 启用截图功能');
|
|
15021
|
+
}
|
|
14919
15022
|
return false;
|
|
14920
15023
|
}
|
|
14921
15024
|
return await this.takeScreenshot();
|
|
@@ -14925,14 +15028,16 @@ class ScreenshotManager {
|
|
|
14925
15028
|
*/
|
|
14926
15029
|
async takeScreenshot(scheduleStartTime) {
|
|
14927
15030
|
if (!this.targetElement) {
|
|
14928
|
-
|
|
15031
|
+
if (this.options.debug) {
|
|
15032
|
+
console.warn('📸 目标元素不存在');
|
|
15033
|
+
}
|
|
14929
15034
|
return false;
|
|
14930
15035
|
}
|
|
14931
15036
|
// 记录截图开始时间
|
|
14932
15037
|
const screenshotStartTime = performance.now();
|
|
14933
15038
|
this.setupGlobalErrorHandlers();
|
|
14934
15039
|
try {
|
|
14935
|
-
if (
|
|
15040
|
+
if (this.options.debug) {
|
|
14936
15041
|
console.log(`📸 开始截图 #${this.screenshotCount + 1}...`);
|
|
14937
15042
|
if (scheduleStartTime) {
|
|
14938
15043
|
const waitTime = screenshotStartTime - scheduleStartTime;
|
|
@@ -14946,7 +15051,7 @@ class ScreenshotManager {
|
|
|
14946
15051
|
this.waitForFonts()
|
|
14947
15052
|
]);
|
|
14948
15053
|
const waitStylesTime = performance.now() - waitStylesStartTime;
|
|
14949
|
-
if (
|
|
15054
|
+
if (this.options.debug) {
|
|
14950
15055
|
console.log(` ⏱️ 等待样式和字体加载耗时: ${waitStylesTime.toFixed(2)}ms`);
|
|
14951
15056
|
}
|
|
14952
15057
|
// 等待元素完全渲染(特别是对于 modern-screenshot)
|
|
@@ -14955,12 +15060,12 @@ class ScreenshotManager {
|
|
|
14955
15060
|
requestAnimationFrame(() => resolve());
|
|
14956
15061
|
}));
|
|
14957
15062
|
const waitRenderTime = performance.now() - waitRenderStartTime;
|
|
14958
|
-
if (
|
|
15063
|
+
if (this.options.debug) {
|
|
14959
15064
|
console.log(` ⏱️ 等待渲染完成耗时: ${waitRenderTime.toFixed(2)}ms`);
|
|
14960
15065
|
}
|
|
14961
15066
|
// 选择截图引擎
|
|
14962
15067
|
const selectedEngine = this.options.engine || 'modern-screenshot';
|
|
14963
|
-
if (
|
|
15068
|
+
if (this.options.debug) {
|
|
14964
15069
|
console.log(`📸 使用截图引擎: ${selectedEngine}`);
|
|
14965
15070
|
}
|
|
14966
15071
|
// 优化:如果启用预加载,才预处理图片;否则让引擎按需加载
|
|
@@ -15000,7 +15105,7 @@ class ScreenshotManager {
|
|
|
15000
15105
|
dataUrl = await this.takeScreenshotWithModernScreenshot(this.targetElement);
|
|
15001
15106
|
}
|
|
15002
15107
|
const engineTime = performance.now() - engineStartTime;
|
|
15003
|
-
if (
|
|
15108
|
+
if (this.options.debug) {
|
|
15004
15109
|
console.log(` ⏱️ 截图引擎执行耗时: ${engineTime.toFixed(2)}ms`);
|
|
15005
15110
|
}
|
|
15006
15111
|
const timestamp = Date.now();
|
|
@@ -15014,7 +15119,7 @@ class ScreenshotManager {
|
|
|
15014
15119
|
const removed = this.screenshotHistory.shift();
|
|
15015
15120
|
// 强制 GC(如果可能)
|
|
15016
15121
|
if (removed && removed.length > 1000000) { // 大于1MB的字符串
|
|
15017
|
-
if (
|
|
15122
|
+
if (this.options.debug) {
|
|
15018
15123
|
console.log(`📸 清理旧截图,释放内存: ${Math.round(removed.length * 0.75 / 1024)} KB`);
|
|
15019
15124
|
}
|
|
15020
15125
|
}
|
|
@@ -15028,7 +15133,7 @@ class ScreenshotManager {
|
|
|
15028
15133
|
if (removed) {
|
|
15029
15134
|
const removedSize = removed.length;
|
|
15030
15135
|
totalSize -= removedSize;
|
|
15031
|
-
if (
|
|
15136
|
+
if (this.options.debug) {
|
|
15032
15137
|
console.warn(`📸 ⚠️ 历史记录总大小超过限制,清理最旧截图: ${Math.round(removedSize * 0.75 / 1024)} KB`);
|
|
15033
15138
|
}
|
|
15034
15139
|
}
|
|
@@ -15040,7 +15145,7 @@ class ScreenshotManager {
|
|
|
15040
15145
|
const screenshotTotalTime = performance.now() - screenshotStartTime;
|
|
15041
15146
|
// 打印基本信息
|
|
15042
15147
|
const base64Data = dataUrl.split(',')[1] || '';
|
|
15043
|
-
if (
|
|
15148
|
+
if (this.options.debug) {
|
|
15044
15149
|
console.log('📸 截图完成:');
|
|
15045
15150
|
console.log(`📸 编号: #${this.screenshotCount}`);
|
|
15046
15151
|
console.log(`📸 时间: ${new Date(timestamp).toLocaleTimeString()}`);
|
|
@@ -15059,7 +15164,7 @@ class ScreenshotManager {
|
|
|
15059
15164
|
// 确保 Worker 已创建
|
|
15060
15165
|
if (!this.worker) {
|
|
15061
15166
|
this.worker = this.createWorker();
|
|
15062
|
-
if (
|
|
15167
|
+
if (this.options.debug) {
|
|
15063
15168
|
if (this.worker) {
|
|
15064
15169
|
console.log('📸 Worker 已创建,准备压缩');
|
|
15065
15170
|
}
|
|
@@ -15071,7 +15176,7 @@ class ScreenshotManager {
|
|
|
15071
15176
|
if (this.worker) {
|
|
15072
15177
|
// 记录压缩开始时间
|
|
15073
15178
|
const compressStartTime = performance.now();
|
|
15074
|
-
if (
|
|
15179
|
+
if (this.options.debug) {
|
|
15075
15180
|
console.log('📸 发送到 WebWorker 进行压缩...');
|
|
15076
15181
|
}
|
|
15077
15182
|
// 保存原始 dataUrl 用于后续对比(在 Worker 压缩完成后)
|
|
@@ -15094,7 +15199,7 @@ class ScreenshotManager {
|
|
|
15094
15199
|
}
|
|
15095
15200
|
else {
|
|
15096
15201
|
// Worker 不可用,如果配置了二进制模式,直接发送原始截图
|
|
15097
|
-
if (
|
|
15202
|
+
if (this.options.debug) {
|
|
15098
15203
|
console.warn('📸 ⚠️ Worker 不可用,跳过压缩(使用原始截图)');
|
|
15099
15204
|
}
|
|
15100
15205
|
// Worker 不可用时,如果配置了二进制模式,立即发送原始截图
|
|
@@ -15110,7 +15215,7 @@ class ScreenshotManager {
|
|
|
15110
15215
|
data: combinedBuffer
|
|
15111
15216
|
};
|
|
15112
15217
|
this.sendToIframeCallback(message);
|
|
15113
|
-
if (
|
|
15218
|
+
if (this.options.debug) {
|
|
15114
15219
|
console.log('📸 [Worker 不可用] ✅ 原始截图已发送到 iframe');
|
|
15115
15220
|
}
|
|
15116
15221
|
}
|
|
@@ -15135,7 +15240,7 @@ class ScreenshotManager {
|
|
|
15135
15240
|
console.error('📸 截图失败:', err);
|
|
15136
15241
|
this.error = errorMessage;
|
|
15137
15242
|
}
|
|
15138
|
-
else if (
|
|
15243
|
+
else if (this.options.debug) {
|
|
15139
15244
|
console.warn('📸 截图遇到跨域问题(已忽略)');
|
|
15140
15245
|
}
|
|
15141
15246
|
return false;
|
|
@@ -15152,7 +15257,7 @@ class ScreenshotManager {
|
|
|
15152
15257
|
* 注意:snapdom 内部使用 worker 进行截图处理,会在后台线程执行,不会阻塞主线程
|
|
15153
15258
|
*/
|
|
15154
15259
|
async takeScreenshotWithSnapdom(element) {
|
|
15155
|
-
if (
|
|
15260
|
+
if (this.options.debug) {
|
|
15156
15261
|
console.log('📸 使用 snapdom 引擎截图...');
|
|
15157
15262
|
}
|
|
15158
15263
|
// 限制只截图可见区域(viewport),避免截图不可见区域
|
|
@@ -15192,7 +15297,7 @@ class ScreenshotManager {
|
|
|
15192
15297
|
// 简化方案:直接使用 body,但添加尺寸限制选项(如果 snapdom 支持)
|
|
15193
15298
|
// 如果不支持,则只能截图整个 body
|
|
15194
15299
|
targetElement = element;
|
|
15195
|
-
if (
|
|
15300
|
+
if (this.options.debug) {
|
|
15196
15301
|
console.log(`📸 注意:snapdom 将截图整个 body,建议使用 html2canvas 或 modern-screenshot 来限制可见区域`);
|
|
15197
15302
|
console.log(`📸 可见区域尺寸: ${window.innerWidth}x${window.innerHeight}`);
|
|
15198
15303
|
}
|
|
@@ -15209,7 +15314,7 @@ class ScreenshotManager {
|
|
|
15209
15314
|
elementRect.left >= 0 &&
|
|
15210
15315
|
elementRect.bottom <= window.innerHeight &&
|
|
15211
15316
|
elementRect.right <= window.innerWidth;
|
|
15212
|
-
if (!isFullyVisible &&
|
|
15317
|
+
if (!isFullyVisible && this.options.debug) {
|
|
15213
15318
|
console.warn(`📸 ⚠️ 元素部分不可见,snapdom 可能会截图整个元素(包括不可见部分)`);
|
|
15214
15319
|
console.warn(`📸 建议:使用 html2canvas 或 modern-screenshot 来限制可见区域`);
|
|
15215
15320
|
}
|
|
@@ -15227,12 +15332,12 @@ class ScreenshotManager {
|
|
|
15227
15332
|
proxyUrl = proxyUrl.endsWith('?') ? proxyUrl + 'url=' : proxyUrl + '?url=';
|
|
15228
15333
|
}
|
|
15229
15334
|
options.useProxy = proxyUrl;
|
|
15230
|
-
if (
|
|
15335
|
+
if (this.options.debug) {
|
|
15231
15336
|
console.log(`📸 使用代理服务器处理跨域图片: ${proxyUrl}`);
|
|
15232
15337
|
}
|
|
15233
15338
|
}
|
|
15234
15339
|
else {
|
|
15235
|
-
if (
|
|
15340
|
+
if (this.options.debug) {
|
|
15236
15341
|
if (!this.options.useProxy) {
|
|
15237
15342
|
console.log('📸 代理功能已禁用(useProxy: false)');
|
|
15238
15343
|
}
|
|
@@ -15274,7 +15379,7 @@ class ScreenshotManager {
|
|
|
15274
15379
|
parent.removeChild(container);
|
|
15275
15380
|
}
|
|
15276
15381
|
}
|
|
15277
|
-
if (
|
|
15382
|
+
if (this.options.debug) {
|
|
15278
15383
|
console.log(`📸 snapdom 截图成功!格式: ${outputFormat}, 尺寸: ${img.width}x${img.height}`);
|
|
15279
15384
|
}
|
|
15280
15385
|
return dataUrl;
|
|
@@ -15292,14 +15397,14 @@ class ScreenshotManager {
|
|
|
15292
15397
|
const errorName = error instanceof Error ? error.name : 'Unknown';
|
|
15293
15398
|
// 针对不同类型的错误给出具体提示
|
|
15294
15399
|
if (errorName === 'EncodingError' || errorMessage.includes('cannot be decoded')) {
|
|
15295
|
-
if (
|
|
15400
|
+
if (this.options.debug) {
|
|
15296
15401
|
console.warn('📸 ⚠️ 图片解码失败 - 这通常是因为跨域图片无法访问');
|
|
15297
15402
|
console.warn('📸 💡 解决方案:配置 proxyUrl 选项');
|
|
15298
15403
|
console.warn('📸 📖 参考: https://snapdom.dev/#cors');
|
|
15299
15404
|
}
|
|
15300
15405
|
}
|
|
15301
15406
|
else if (errorMessage.includes('CORS') || errorMessage.includes('cross-origin')) {
|
|
15302
|
-
if (
|
|
15407
|
+
if (this.options.debug) {
|
|
15303
15408
|
console.warn('📸 ⚠️ 检测到 CORS 错误,建议配置 proxyUrl 选项');
|
|
15304
15409
|
}
|
|
15305
15410
|
}
|
|
@@ -15324,7 +15429,7 @@ class ScreenshotManager {
|
|
|
15324
15429
|
* - 需要快速截图
|
|
15325
15430
|
*/
|
|
15326
15431
|
async takeScreenshotWithHtml2Canvas(element) {
|
|
15327
|
-
if (
|
|
15432
|
+
if (this.options.debug) {
|
|
15328
15433
|
console.log('📸 使用 html2canvas 引擎截图...');
|
|
15329
15434
|
}
|
|
15330
15435
|
try {
|
|
@@ -15378,7 +15483,7 @@ class ScreenshotManager {
|
|
|
15378
15483
|
: (isMobile ? 0.5 : 0.6), // 用户未配置,使用默认值
|
|
15379
15484
|
useCORS: this.options.enableCORS,
|
|
15380
15485
|
allowTaint: !this.options.enableCORS, // 如果启用 CORS,不允许 taint
|
|
15381
|
-
logging:
|
|
15486
|
+
logging: this.options.debug, // 使用配置的静默模式
|
|
15382
15487
|
// foreignObjectRendering: true, // ❌ 移除:可能导致跨域图片不显示
|
|
15383
15488
|
// removeContainer: true, // ❌ 移除:移到后面,避免重复定义
|
|
15384
15489
|
// 不设置 width 和 height,让 html2canvas 自动计算
|
|
@@ -15516,12 +15621,12 @@ class ScreenshotManager {
|
|
|
15516
15621
|
}
|
|
15517
15622
|
catch (e) {
|
|
15518
15623
|
// 忽略内联化错误
|
|
15519
|
-
if (
|
|
15624
|
+
if (this.options.debug) {
|
|
15520
15625
|
console.warn('📸 iOS 样式内联化失败:', e);
|
|
15521
15626
|
}
|
|
15522
15627
|
}
|
|
15523
15628
|
}
|
|
15524
|
-
if (
|
|
15629
|
+
if (this.options.debug) {
|
|
15525
15630
|
const styleLinks = clonedDoc.querySelectorAll('link[rel="stylesheet"]').length;
|
|
15526
15631
|
const styleTags = clonedDoc.querySelectorAll('style').length;
|
|
15527
15632
|
console.log(`📸 onclone: 已复制 ${styleLinks} 个样式表链接和 ${styleTags} 个内联样式标签${isIOS ? ' (iOS 模式:已内联化计算样式)' : ''}`);
|
|
@@ -15570,7 +15675,7 @@ class ScreenshotManager {
|
|
|
15570
15675
|
const cachedDataUrl = this.getCachedImage(originalSrc);
|
|
15571
15676
|
if (cachedDataUrl) {
|
|
15572
15677
|
img.src = cachedDataUrl;
|
|
15573
|
-
if (
|
|
15678
|
+
if (this.options.debug) {
|
|
15574
15679
|
console.log(`📸 使用缓存的图片: ${originalSrc.substring(0, 50)}...`);
|
|
15575
15680
|
}
|
|
15576
15681
|
return;
|
|
@@ -15579,7 +15684,7 @@ class ScreenshotManager {
|
|
|
15579
15684
|
// 构建代理 URL
|
|
15580
15685
|
try {
|
|
15581
15686
|
if (!this.options.proxyUrl) {
|
|
15582
|
-
if (
|
|
15687
|
+
if (this.options.debug) {
|
|
15583
15688
|
console.warn(`📸 ⚠️ 未配置代理 URL,跨域图片可能无法显示: ${originalSrc}`);
|
|
15584
15689
|
}
|
|
15585
15690
|
return;
|
|
@@ -15592,19 +15697,19 @@ class ScreenshotManager {
|
|
|
15592
15697
|
baseUrl = baseUrl.replace(/[?&]$/, '');
|
|
15593
15698
|
const proxyUrl = `${baseUrl}?${params.toString()}`;
|
|
15594
15699
|
img.src = proxyUrl;
|
|
15595
|
-
if (
|
|
15700
|
+
if (this.options.debug) {
|
|
15596
15701
|
console.log(`📸 使用代理 URL 替换跨域图片: ${originalSrc.substring(0, 50)}... -> ${proxyUrl.substring(0, 50)}...`);
|
|
15597
15702
|
}
|
|
15598
15703
|
}
|
|
15599
15704
|
catch (error) {
|
|
15600
|
-
if (
|
|
15705
|
+
if (this.options.debug) {
|
|
15601
15706
|
console.warn(`📸 ⚠️ 处理图片 URL 失败: ${originalSrc}`, error);
|
|
15602
15707
|
}
|
|
15603
15708
|
}
|
|
15604
15709
|
});
|
|
15605
15710
|
};
|
|
15606
15711
|
}
|
|
15607
|
-
if (
|
|
15712
|
+
if (this.options.debug) {
|
|
15608
15713
|
console.log(`📸 html2canvas 配置: 元素尺寸 ${elementWidth}x${elementHeight}, 质量 ${finalQuality.toFixed(2)}, 缩放 ${options.scale}`);
|
|
15609
15714
|
console.log(`📸 html2canvas 将自动计算截图尺寸(不限制 width/height)`);
|
|
15610
15715
|
console.log(`📸 用户配置质量: ${this.options.quality}, 实际使用质量: ${finalQuality.toFixed(2)}`);
|
|
@@ -15649,7 +15754,7 @@ class ScreenshotManager {
|
|
|
15649
15754
|
if (!dataUrl || dataUrl.length < 100) {
|
|
15650
15755
|
throw new Error('生成的截图数据无效或过短');
|
|
15651
15756
|
}
|
|
15652
|
-
if (
|
|
15757
|
+
if (this.options.debug) {
|
|
15653
15758
|
console.log(`📸 html2canvas 截图成功!格式: ${mimeType}, 尺寸: ${canvas.width}x${canvas.height}, 质量: ${finalQualityForExport?.toFixed(2) || 'N/A (PNG)'}`);
|
|
15654
15759
|
console.log(`📸 输出格式: ${mimeType}, 用户配置质量: ${this.options.quality}, 实际使用质量: ${finalQualityForExport?.toFixed(2) || 'N/A (PNG)'}`);
|
|
15655
15760
|
}
|
|
@@ -15657,7 +15762,7 @@ class ScreenshotManager {
|
|
|
15657
15762
|
}
|
|
15658
15763
|
catch (error) {
|
|
15659
15764
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
15660
|
-
if (
|
|
15765
|
+
if (this.options.debug) {
|
|
15661
15766
|
console.error('📸 html2canvas 截图失败:', errorMessage);
|
|
15662
15767
|
if (errorMessage.includes('CORS') || errorMessage.includes('cross-origin')) {
|
|
15663
15768
|
console.warn('📸 💡 建议:配置 proxyUrl 选项处理跨域图片');
|
|
@@ -15690,7 +15795,7 @@ class ScreenshotManager {
|
|
|
15690
15795
|
if (this.isScreenshotInProgress) {
|
|
15691
15796
|
// 队列最多保留 1 个请求,避免积压
|
|
15692
15797
|
if (this.screenshotQueue.length >= 1) {
|
|
15693
|
-
if (
|
|
15798
|
+
if (this.options.debug) {
|
|
15694
15799
|
console.log('📸 截图队列已满,跳过当前请求(等待队列处理)');
|
|
15695
15800
|
}
|
|
15696
15801
|
// 等待队列中的请求完成
|
|
@@ -15719,7 +15824,7 @@ class ScreenshotManager {
|
|
|
15719
15824
|
});
|
|
15720
15825
|
}
|
|
15721
15826
|
this.isScreenshotInProgress = true;
|
|
15722
|
-
if (
|
|
15827
|
+
if (this.options.debug) {
|
|
15723
15828
|
console.log('📸 使用 modern-screenshot 引擎截图(Worker 模式)...');
|
|
15724
15829
|
}
|
|
15725
15830
|
try {
|
|
@@ -15739,7 +15844,7 @@ class ScreenshotManager {
|
|
|
15739
15844
|
elementWidth = element.clientWidth || element.offsetWidth || element.scrollWidth;
|
|
15740
15845
|
elementHeight = element.clientHeight || element.offsetHeight || element.scrollHeight;
|
|
15741
15846
|
}
|
|
15742
|
-
if (
|
|
15847
|
+
if (this.options.debug) {
|
|
15743
15848
|
console.log(`📸 目标元素: ${element.tagName}${element.id ? '#' + element.id : ''}${element.className ? '.' + element.className.split(' ').join('.') : ''}`);
|
|
15744
15849
|
console.log(`📸 元素尺寸: ${elementWidth}x${elementHeight}`);
|
|
15745
15850
|
console.log(`📸 scrollWidth: ${element.scrollWidth}, scrollHeight: ${element.scrollHeight}`);
|
|
@@ -15773,7 +15878,7 @@ class ScreenshotManager {
|
|
|
15773
15878
|
// 检查内存缓存(优先使用缓存,带过期时间检查)
|
|
15774
15879
|
const cachedDataUrl = this.getCachedImage(url);
|
|
15775
15880
|
if (cachedDataUrl) {
|
|
15776
|
-
if (
|
|
15881
|
+
if (this.options.debug) {
|
|
15777
15882
|
console.log(`📸 ✅ 使用内存缓存图片: ${url.substring(0, 50)}...`);
|
|
15778
15883
|
}
|
|
15779
15884
|
return cachedDataUrl;
|
|
@@ -15825,7 +15930,7 @@ class ScreenshotManager {
|
|
|
15825
15930
|
}
|
|
15826
15931
|
}
|
|
15827
15932
|
catch (error) {
|
|
15828
|
-
if (
|
|
15933
|
+
if (this.options.debug) {
|
|
15829
15934
|
console.warn(`📸 代理处理图片失败: ${url.substring(0, 100)}...`, error);
|
|
15830
15935
|
}
|
|
15831
15936
|
// 失败时返回原 URL,让 modern-screenshot 自己处理
|
|
@@ -15874,7 +15979,7 @@ class ScreenshotManager {
|
|
|
15874
15979
|
// 按照 demo 的方式:只在 context 不存在时创建,之后一直复用
|
|
15875
15980
|
// 不进行复杂的检测和重新创建逻辑
|
|
15876
15981
|
if (!this.screenshotContext) {
|
|
15877
|
-
if (
|
|
15982
|
+
if (this.options.debug) {
|
|
15878
15983
|
console.log(`📸 创建截图 Worker 上下文...`);
|
|
15879
15984
|
console.log(`📸 Worker 模式: ${workerNumber} 个 Worker`);
|
|
15880
15985
|
}
|
|
@@ -15895,23 +16000,23 @@ class ScreenshotManager {
|
|
|
15895
16000
|
// 如果用户指定了 workerUrl,使用指定的 URL
|
|
15896
16001
|
if (this.options.workerUrl) {
|
|
15897
16002
|
simpleContextOptions.workerUrl = this.options.workerUrl;
|
|
15898
|
-
if (
|
|
16003
|
+
if (this.options.debug) {
|
|
15899
16004
|
console.log(`📸 使用指定的 Worker URL: ${this.options.workerUrl}`);
|
|
15900
16005
|
}
|
|
15901
16006
|
}
|
|
15902
16007
|
else {
|
|
15903
|
-
if (
|
|
16008
|
+
if (this.options.debug) {
|
|
15904
16009
|
console.log('📸 Worker URL 未指定,modern-screenshot 将自动处理');
|
|
15905
16010
|
}
|
|
15906
16011
|
}
|
|
15907
16012
|
try {
|
|
15908
16013
|
this.screenshotContext = await createContext$1(element, simpleContextOptions);
|
|
15909
|
-
if (
|
|
16014
|
+
if (this.options.debug) {
|
|
15910
16015
|
console.log('📸 Worker 上下文创建成功');
|
|
15911
16016
|
}
|
|
15912
16017
|
}
|
|
15913
16018
|
catch (error) {
|
|
15914
|
-
if (
|
|
16019
|
+
if (this.options.debug) {
|
|
15915
16020
|
console.error('📸 创建 Worker 上下文失败:', error);
|
|
15916
16021
|
}
|
|
15917
16022
|
throw error;
|
|
@@ -15921,7 +16026,7 @@ class ScreenshotManager {
|
|
|
15921
16026
|
// 按照 demo 的方式:使用 domToWebp 时传递配置参数
|
|
15922
16027
|
let dataUrl;
|
|
15923
16028
|
const outputFormat = this.options.outputFormat || 'webp';
|
|
15924
|
-
if (
|
|
16029
|
+
if (this.options.debug) {
|
|
15925
16030
|
console.log(`📸 使用 ${outputFormat.toUpperCase()} 格式截图(直接输出,无需转换)...`);
|
|
15926
16031
|
}
|
|
15927
16032
|
// 构建 domToWebp/domToJpeg/domToPng 的配置参数(和 demo 一致)
|
|
@@ -15956,14 +16061,14 @@ class ScreenshotManager {
|
|
|
15956
16061
|
if (!dataUrl || dataUrl.length < 100) {
|
|
15957
16062
|
throw new Error('生成的截图数据无效或过短');
|
|
15958
16063
|
}
|
|
15959
|
-
if (
|
|
16064
|
+
if (this.options.debug) {
|
|
15960
16065
|
console.log(`📸 ✅ modern-screenshot 截图成功(Worker 模式,${outputFormat.toUpperCase()} 格式)`);
|
|
15961
16066
|
}
|
|
15962
16067
|
return dataUrl;
|
|
15963
16068
|
}
|
|
15964
16069
|
catch (workerError) {
|
|
15965
16070
|
// Worker 模式失败,回退到普通模式(和 demo 一致)
|
|
15966
|
-
if (
|
|
16071
|
+
if (this.options.debug) {
|
|
15967
16072
|
console.warn('📸 Worker 模式失败,回退到普通模式:', workerError);
|
|
15968
16073
|
}
|
|
15969
16074
|
// 销毁失败的 context
|
|
@@ -16006,7 +16111,7 @@ class ScreenshotManager {
|
|
|
16006
16111
|
if (!dataUrl || dataUrl.length < 100) {
|
|
16007
16112
|
throw new Error('生成的截图数据无效或过短');
|
|
16008
16113
|
}
|
|
16009
|
-
if (
|
|
16114
|
+
if (this.options.debug) {
|
|
16010
16115
|
console.log(`📸 ✅ modern-screenshot 截图成功(普通模式,${outputFormat.toUpperCase()} 格式)`);
|
|
16011
16116
|
}
|
|
16012
16117
|
return dataUrl;
|
|
@@ -16014,7 +16119,7 @@ class ScreenshotManager {
|
|
|
16014
16119
|
}
|
|
16015
16120
|
catch (error) {
|
|
16016
16121
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
16017
|
-
if (
|
|
16122
|
+
if (this.options.debug) {
|
|
16018
16123
|
console.error('📸 modern-screenshot 截图失败:', errorMessage);
|
|
16019
16124
|
console.error('📸 元素信息:', {
|
|
16020
16125
|
width: rect.width,
|
|
@@ -16038,7 +16143,7 @@ class ScreenshotManager {
|
|
|
16038
16143
|
catch (error) {
|
|
16039
16144
|
// 外层错误处理:确保即使发生错误也释放锁
|
|
16040
16145
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
16041
|
-
if (
|
|
16146
|
+
if (this.options.debug) {
|
|
16042
16147
|
console.error('📸 modern-screenshot 截图异常:', errorMessage);
|
|
16043
16148
|
}
|
|
16044
16149
|
throw error;
|
|
@@ -16092,7 +16197,7 @@ class ScreenshotManager {
|
|
|
16092
16197
|
link.crossOrigin = 'anonymous';
|
|
16093
16198
|
document.head.appendChild(link);
|
|
16094
16199
|
this.preconnected = true;
|
|
16095
|
-
if (
|
|
16200
|
+
if (this.options.debug) {
|
|
16096
16201
|
console.log(`📸 ✅ 已预连接代理服务器: ${proxyOrigin}`);
|
|
16097
16202
|
}
|
|
16098
16203
|
}
|
|
@@ -16217,7 +16322,7 @@ class ScreenshotManager {
|
|
|
16217
16322
|
if (networkImages.length === 0) {
|
|
16218
16323
|
return;
|
|
16219
16324
|
}
|
|
16220
|
-
if (
|
|
16325
|
+
if (this.options.debug) {
|
|
16221
16326
|
const totalImages = images.length;
|
|
16222
16327
|
console.log(`📸 发现 ${networkImages.length}/${totalImages} 个可视区域内的跨域图片,开始并行预加载...`);
|
|
16223
16328
|
}
|
|
@@ -16225,7 +16330,7 @@ class ScreenshotManager {
|
|
|
16225
16330
|
// 只有当 useProxy 为 true 且 proxyUrl 存在时才使用代理
|
|
16226
16331
|
const shouldUseProxy = this.options.useProxy && this.options.proxyUrl && this.options.proxyUrl.trim() !== '';
|
|
16227
16332
|
if (shouldUseProxy) {
|
|
16228
|
-
if (
|
|
16333
|
+
if (this.options.debug) {
|
|
16229
16334
|
console.log(`📸 使用代理服务器处理跨域图片: ${this.options.proxyUrl}`);
|
|
16230
16335
|
}
|
|
16231
16336
|
// 优化:增加并发数,使用更大的批次
|
|
@@ -16253,13 +16358,13 @@ class ScreenshotManager {
|
|
|
16253
16358
|
}
|
|
16254
16359
|
catch (error) {
|
|
16255
16360
|
// 静默失败,不影响其他图片
|
|
16256
|
-
if (
|
|
16361
|
+
if (this.options.debug) {
|
|
16257
16362
|
console.warn(`📸 ❌ 代理预加载失败: ${originalSrc.substring(0, 50)}...`);
|
|
16258
16363
|
}
|
|
16259
16364
|
}
|
|
16260
16365
|
}));
|
|
16261
16366
|
}));
|
|
16262
|
-
if (
|
|
16367
|
+
if (this.options.debug) {
|
|
16263
16368
|
console.log(`📸 ✅ 预处理完成,缓存了 ${this.imageProxyCache.size} 个代理图片`);
|
|
16264
16369
|
}
|
|
16265
16370
|
}
|
|
@@ -16284,7 +16389,7 @@ class ScreenshotManager {
|
|
|
16284
16389
|
// 移除末尾的 ? 或 &(如果有)
|
|
16285
16390
|
baseUrl = baseUrl.replace(/[?&]$/, '');
|
|
16286
16391
|
const requestUrl = `${baseUrl}?${params.toString()}`;
|
|
16287
|
-
if (
|
|
16392
|
+
if (this.options.debug) {
|
|
16288
16393
|
console.log(`📸 🔄 代理请求 URL: ${requestUrl.substring(0, 200)}...`);
|
|
16289
16394
|
}
|
|
16290
16395
|
// 请求代理服务器
|
|
@@ -16303,7 +16408,7 @@ class ScreenshotManager {
|
|
|
16303
16408
|
const blob = await response.blob();
|
|
16304
16409
|
// 将 blob 转换为 data URL(用于 modern-screenshot 兼容性)
|
|
16305
16410
|
const dataUrl = await this.blobToDataUrl(blob);
|
|
16306
|
-
if (
|
|
16411
|
+
if (this.options.debug) {
|
|
16307
16412
|
console.log(`📸 ✅ 代理模式成功(已转换为 data URL): ${imageUrl.substring(0, 100)}...`);
|
|
16308
16413
|
}
|
|
16309
16414
|
return dataUrl;
|
|
@@ -16334,7 +16439,7 @@ class ScreenshotManager {
|
|
|
16334
16439
|
if (sizeMB > maxSizeMB) {
|
|
16335
16440
|
if (this.options.skipLargeImages) {
|
|
16336
16441
|
// 跳过过大的图片,返回占位符
|
|
16337
|
-
if (
|
|
16442
|
+
if (this.options.debug) {
|
|
16338
16443
|
console.warn(`📸 ⚠️ 跳过过大图片(${sizeMB.toFixed(2)}MB > ${maxSizeMB}MB): ${url.substring(0, 100)}...`);
|
|
16339
16444
|
}
|
|
16340
16445
|
// 返回一个 1x1 的透明占位符,避免截图失败
|
|
@@ -16342,7 +16447,7 @@ class ScreenshotManager {
|
|
|
16342
16447
|
}
|
|
16343
16448
|
else {
|
|
16344
16449
|
// 不跳过,但添加警告
|
|
16345
|
-
if (
|
|
16450
|
+
if (this.options.debug) {
|
|
16346
16451
|
console.warn(`📸 ⚠️ 图片较大(${sizeMB.toFixed(2)}MB),可能导致内存问题: ${url.substring(0, 100)}...`);
|
|
16347
16452
|
}
|
|
16348
16453
|
}
|
|
@@ -16356,14 +16461,14 @@ class ScreenshotManager {
|
|
|
16356
16461
|
if (blobSizeMB > maxSizeMB) {
|
|
16357
16462
|
if (this.options.skipLargeImages) {
|
|
16358
16463
|
// 跳过过大的图片,返回占位符
|
|
16359
|
-
if (
|
|
16464
|
+
if (this.options.debug) {
|
|
16360
16465
|
console.warn(`📸 ⚠️ 跳过过大图片(实际大小 ${blobSizeMB.toFixed(2)}MB > ${maxSizeMB}MB): ${url.substring(0, 100)}...`);
|
|
16361
16466
|
}
|
|
16362
16467
|
return 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==';
|
|
16363
16468
|
}
|
|
16364
16469
|
else {
|
|
16365
16470
|
// 不跳过,但添加警告
|
|
16366
|
-
if (
|
|
16471
|
+
if (this.options.debug) {
|
|
16367
16472
|
console.warn(`📸 ⚠️ 图片较大(实际大小 ${blobSizeMB.toFixed(2)}MB),可能导致内存问题: ${url.substring(0, 100)}...`);
|
|
16368
16473
|
}
|
|
16369
16474
|
}
|
|
@@ -16379,7 +16484,7 @@ class ScreenshotManager {
|
|
|
16379
16484
|
}
|
|
16380
16485
|
catch (error) {
|
|
16381
16486
|
// 下载失败,返回原 URL,让 modern-screenshot 自己处理
|
|
16382
|
-
if (
|
|
16487
|
+
if (this.options.debug) {
|
|
16383
16488
|
console.warn(`📸 ⚠️ 下载图片失败: ${url.substring(0, 100)}...`, error);
|
|
16384
16489
|
}
|
|
16385
16490
|
return url;
|
|
@@ -16810,7 +16915,7 @@ class ScreenshotManager {
|
|
|
16810
16915
|
// 更新历史记录为压缩后的数据
|
|
16811
16916
|
this.screenshotHistory[this.screenshotHistory.length - 1] = compressed.dataUrl;
|
|
16812
16917
|
// 打印压缩统计信息和 base64 对比
|
|
16813
|
-
if (
|
|
16918
|
+
if (this.options.debug) {
|
|
16814
16919
|
if (compressed.error) {
|
|
16815
16920
|
// 压缩失败,使用原始数据
|
|
16816
16921
|
console.warn('📸 [Worker 压缩] ⚠️ 压缩失败,使用原始截图');
|
|
@@ -16864,7 +16969,7 @@ class ScreenshotManager {
|
|
|
16864
16969
|
};
|
|
16865
16970
|
newWorker.onerror = (e) => {
|
|
16866
16971
|
console.error('📸 WebWorker 错误:', e);
|
|
16867
|
-
if (
|
|
16972
|
+
if (this.options.debug) {
|
|
16868
16973
|
console.warn('📸 Worker 压缩失败,使用原始截图');
|
|
16869
16974
|
}
|
|
16870
16975
|
// Worker 发生错误时,如果配置了二进制模式,发送原始截图
|
|
@@ -16880,7 +16985,7 @@ class ScreenshotManager {
|
|
|
16880
16985
|
data: combinedBuffer
|
|
16881
16986
|
};
|
|
16882
16987
|
this.sendToIframeCallback(message);
|
|
16883
|
-
if (
|
|
16988
|
+
if (this.options.debug) {
|
|
16884
16989
|
console.log('📸 [Worker 错误] ✅ 原始截图已发送到 iframe');
|
|
16885
16990
|
}
|
|
16886
16991
|
}
|
|
@@ -17045,7 +17150,7 @@ class ScreenshotManager {
|
|
|
17045
17150
|
async takeScreenshotAndSendBinary(config) {
|
|
17046
17151
|
// 如果已经在运行,先停止再重新开始
|
|
17047
17152
|
if (this.isRunning) {
|
|
17048
|
-
if (
|
|
17153
|
+
if (this.options.debug) {
|
|
17049
17154
|
console.log(`📸 更新轮询间隔: ${this.dynamicInterval || this.options.interval}ms`);
|
|
17050
17155
|
}
|
|
17051
17156
|
this.stopScreenshot();
|
|
@@ -17076,7 +17181,7 @@ class ScreenshotManager {
|
|
|
17076
17181
|
// 验证:base64Data(从 latestScreenshot 提取)和 imageBufferBase64(从 imageBuffer 转换)应该一致
|
|
17077
17182
|
const isBase64Same = base64Data === imageBufferBase64;
|
|
17078
17183
|
// 打印 imageBuffer 的 base64 编码(用于和接收端对比)
|
|
17079
|
-
if (
|
|
17184
|
+
if (this.options.debug) {
|
|
17080
17185
|
console.log('📸 [发送前] 数据流程分析:');
|
|
17081
17186
|
console.log(` latestScreenshot: ${latestScreenshot.substring(0, 50)}... (原始 data URL)`);
|
|
17082
17187
|
console.log(` base64Data (从 latestScreenshot 提取): 长度 ${base64Data.length} 字符`);
|
|
@@ -17102,7 +17207,7 @@ class ScreenshotManager {
|
|
|
17102
17207
|
const combinedBuffer = this.combineBinaryData(configBuffer, imageBuffer);
|
|
17103
17208
|
const combinedBufferSize = combinedBuffer.byteLength;
|
|
17104
17209
|
// 打印大小信息
|
|
17105
|
-
if (
|
|
17210
|
+
if (this.options.debug) {
|
|
17106
17211
|
console.log('📸 [大小统计]');
|
|
17107
17212
|
console.log(` Base64 大小: ${base64Size} 字符`);
|
|
17108
17213
|
console.log(` 图片字节大小: ${(imageBufferSize / 1024).toFixed(2)} KB (${imageBufferSize} 字节)`);
|
|
@@ -17116,7 +17221,7 @@ class ScreenshotManager {
|
|
|
17116
17221
|
data: combinedBuffer
|
|
17117
17222
|
};
|
|
17118
17223
|
this.sendToIframeCallback(message);
|
|
17119
|
-
if (
|
|
17224
|
+
if (this.options.debug) {
|
|
17120
17225
|
console.log('📸 [iframe] ✅ 二进制数据已发送到 iframe');
|
|
17121
17226
|
}
|
|
17122
17227
|
}
|
|
@@ -17130,14 +17235,14 @@ class ScreenshotManager {
|
|
|
17130
17235
|
}
|
|
17131
17236
|
}
|
|
17132
17237
|
else {
|
|
17133
|
-
if (
|
|
17238
|
+
if (this.options.debug) {
|
|
17134
17239
|
console.warn('📸 [iframe] 截图完成但未找到截图数据');
|
|
17135
17240
|
}
|
|
17136
17241
|
}
|
|
17137
17242
|
}
|
|
17138
17243
|
else {
|
|
17139
17244
|
// 启用了压缩,等待 Worker 压缩完成后在 onmessage 中自动发送
|
|
17140
|
-
if (
|
|
17245
|
+
if (this.options.debug) {
|
|
17141
17246
|
console.log('📸 [iframe] 等待 Worker 压缩完成后发送到 iframe...');
|
|
17142
17247
|
}
|
|
17143
17248
|
}
|
|
@@ -17167,7 +17272,7 @@ class ScreenshotManager {
|
|
|
17167
17272
|
const base64Data = dataUrl.split(',')[1] || '';
|
|
17168
17273
|
const base64Size = base64Data.length;
|
|
17169
17274
|
// 完整打印发送前的 base64 信息(用于调试)
|
|
17170
|
-
if (
|
|
17275
|
+
if (this.options.debug) {
|
|
17171
17276
|
console.log('📸 [发送前] Base64 信息:');
|
|
17172
17277
|
console.log(` Base64 长度: ${base64Size} 字符`);
|
|
17173
17278
|
console.log(` 📸 [发送前] 完整 Base64:`);
|
|
@@ -17191,7 +17296,7 @@ class ScreenshotManager {
|
|
|
17191
17296
|
const combinedBufferSize = combinedBuffer.byteLength;
|
|
17192
17297
|
const combineTime = performance.now() - combineStartTime;
|
|
17193
17298
|
// 打印大小信息
|
|
17194
|
-
if (
|
|
17299
|
+
if (this.options.debug) {
|
|
17195
17300
|
console.log('📸 [压缩后-大小统计]');
|
|
17196
17301
|
console.log(` Base64 大小: ${base64Size} 字符`);
|
|
17197
17302
|
console.log(` 图片字节大小: ${(imageBufferSize / 1024).toFixed(2)} KB (${imageBufferSize} 字节)`);
|
|
@@ -17214,7 +17319,7 @@ class ScreenshotManager {
|
|
|
17214
17319
|
if (scheduleStartTime) {
|
|
17215
17320
|
totalTime = performance.now() - scheduleStartTime;
|
|
17216
17321
|
}
|
|
17217
|
-
if (
|
|
17322
|
+
if (this.options.debug) {
|
|
17218
17323
|
console.log('📸 [压缩后] ✅ 二进制数据已发送到 iframe');
|
|
17219
17324
|
console.log(` ⏱️ 发送回调耗时: ${sendCallbackTime.toFixed(2)}ms`);
|
|
17220
17325
|
console.log(` ⏱️ 发送阶段总耗时: ${totalSendTime.toFixed(2)}ms`);
|
|
@@ -17317,8 +17422,8 @@ class ScreenshotManager {
|
|
|
17317
17422
|
if (newOptions.compress !== undefined) {
|
|
17318
17423
|
this.options.compress = newOptions.compress;
|
|
17319
17424
|
}
|
|
17320
|
-
if (newOptions.
|
|
17321
|
-
this.options.
|
|
17425
|
+
if (newOptions.debug !== undefined) {
|
|
17426
|
+
this.options.debug = newOptions.debug;
|
|
17322
17427
|
}
|
|
17323
17428
|
if (newOptions.proxyUrl !== undefined) {
|
|
17324
17429
|
this.options.proxyUrl = newOptions.proxyUrl;
|
|
@@ -17331,7 +17436,7 @@ class ScreenshotManager {
|
|
|
17331
17436
|
if (this.screenshotContext) {
|
|
17332
17437
|
try {
|
|
17333
17438
|
destroyContext(this.screenshotContext);
|
|
17334
|
-
if (
|
|
17439
|
+
if (this.options.debug) {
|
|
17335
17440
|
console.log(`📸 引擎已从 ${oldEngine} 切换到 ${newEngine},已清理旧 context`);
|
|
17336
17441
|
}
|
|
17337
17442
|
}
|
|
@@ -17340,12 +17445,12 @@ class ScreenshotManager {
|
|
|
17340
17445
|
}
|
|
17341
17446
|
this.screenshotContext = null;
|
|
17342
17447
|
}
|
|
17343
|
-
if (
|
|
17448
|
+
if (this.options.debug) {
|
|
17344
17449
|
console.log(`📸 截图引擎已更新: ${oldEngine} → ${newEngine}`);
|
|
17345
17450
|
console.log(`📸 下次截图时将使用新引擎: ${newEngine}`);
|
|
17346
17451
|
}
|
|
17347
17452
|
}
|
|
17348
|
-
else if (
|
|
17453
|
+
else if (this.options.debug) {
|
|
17349
17454
|
console.log('📸 截图配置已更新');
|
|
17350
17455
|
}
|
|
17351
17456
|
}
|
|
@@ -17445,7 +17550,7 @@ class ScreenshotManager {
|
|
|
17445
17550
|
const itemSizeMB = value.dataUrl.length * 0.75 / (1024 * 1024);
|
|
17446
17551
|
this.imageProxyCache.delete(key);
|
|
17447
17552
|
currentSizeMB -= itemSizeMB;
|
|
17448
|
-
if (
|
|
17553
|
+
if (this.options.debug) {
|
|
17449
17554
|
console.log(`📸 清理内存缓存(超过限制): ${key.substring(0, 50)}...`);
|
|
17450
17555
|
}
|
|
17451
17556
|
}
|
|
@@ -17470,7 +17575,7 @@ class ScreenshotManager {
|
|
|
17470
17575
|
expiredUrls.forEach(url => {
|
|
17471
17576
|
this.imageProxyCache.delete(url);
|
|
17472
17577
|
});
|
|
17473
|
-
if (expiredUrls.length > 0 &&
|
|
17578
|
+
if (expiredUrls.length > 0 && this.options.debug) {
|
|
17474
17579
|
console.log(`📸 清理了 ${expiredUrls.length} 个过期缓存`);
|
|
17475
17580
|
}
|
|
17476
17581
|
}
|
|
@@ -17482,7 +17587,7 @@ class ScreenshotManager {
|
|
|
17482
17587
|
// 每2分钟清理一次过期缓存(从5分钟改为2分钟,更频繁)
|
|
17483
17588
|
setInterval(() => {
|
|
17484
17589
|
this.cleanExpiredCache();
|
|
17485
|
-
if (
|
|
17590
|
+
if (this.options.debug) {
|
|
17486
17591
|
const memoryCacheSize = this.imageProxyCache.size;
|
|
17487
17592
|
const memoryCacheSizeMB = Array.from(this.imageProxyCache.values())
|
|
17488
17593
|
.reduce((sum, cached) => sum + cached.dataUrl.length * 0.75 / (1024 * 1024), 0);
|
|
@@ -20822,9 +20927,10 @@ class CustomerServiceSDK {
|
|
|
20822
20927
|
agent: config.agent,
|
|
20823
20928
|
timestamp: Date.now()
|
|
20824
20929
|
};
|
|
20825
|
-
//
|
|
20930
|
+
// 创建悬浮图标管理器(支持自定义位置和传送目标)
|
|
20826
20931
|
const iconPosition = options?.iconPosition || undefined;
|
|
20827
|
-
|
|
20932
|
+
const iconTarget = options?.target || undefined;
|
|
20933
|
+
this.iconManager = new IconManager(iconPosition, this.debug, iconTarget);
|
|
20828
20934
|
await this.iconManager.show();
|
|
20829
20935
|
// 创建iframe管理器(自动检测设备类型)
|
|
20830
20936
|
this.iframeManager = new IframeManager({
|
|
@@ -20864,10 +20970,10 @@ class CustomerServiceSDK {
|
|
|
20864
20970
|
// 默认截图目标为 document.body,可以通过配置自定义
|
|
20865
20971
|
const targetElement = document.body;
|
|
20866
20972
|
// 传入发送消息到 iframe 的回调函数
|
|
20867
|
-
// 将 debug
|
|
20973
|
+
// 将 debug 配置传递给截图管理器
|
|
20868
20974
|
const screenshotOptions = {
|
|
20869
20975
|
...config.screenshot,
|
|
20870
|
-
|
|
20976
|
+
debug: this.debug // 直接传递 debug 标志
|
|
20871
20977
|
};
|
|
20872
20978
|
this.screenshotManager = new ScreenshotManager(targetElement, screenshotOptions, (data) => {
|
|
20873
20979
|
// 通过 IframeManager 发送消息到 iframe
|
|
@@ -21082,8 +21188,9 @@ class CustomerServiceSDK {
|
|
|
21082
21188
|
return result.visitorId;
|
|
21083
21189
|
}
|
|
21084
21190
|
catch (error) {
|
|
21085
|
-
|
|
21086
|
-
|
|
21191
|
+
if (this.debug) {
|
|
21192
|
+
console.warn('❌ Failed to get device fingerprint, using fallback:', error);
|
|
21193
|
+
}
|
|
21087
21194
|
const fallbackId = 'device_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9);
|
|
21088
21195
|
if (this.debug) {
|
|
21089
21196
|
console.log('🆔 Fallback Device ID:', fallbackId);
|