customer-chat-sdk 1.1.5 → 1.1.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/dist/customer-sdk.esm.js
CHANGED
|
@@ -182,7 +182,7 @@ class IconManager {
|
|
|
182
182
|
if (this.iconElement) {
|
|
183
183
|
this.iconElement.remove();
|
|
184
184
|
this.iconElement = null;
|
|
185
|
-
|
|
185
|
+
// 注意:不清空 onClickCallback,以便再次显示时能继续使用
|
|
186
186
|
this.dragMoveHandler = null;
|
|
187
187
|
this.dragEndHandler = null;
|
|
188
188
|
if (this.debug) {
|
|
@@ -601,7 +601,6 @@ class IconManager {
|
|
|
601
601
|
class IframeManager {
|
|
602
602
|
constructor(config = {}) {
|
|
603
603
|
this.iframeElement = null;
|
|
604
|
-
this.overlayElement = null;
|
|
605
604
|
this.containerElement = null; // 包装容器,包含iframe和关闭按钮
|
|
606
605
|
this.isOpen = false;
|
|
607
606
|
this.isCreated = false;
|
|
@@ -623,18 +622,11 @@ class IframeManager {
|
|
|
623
622
|
*/
|
|
624
623
|
async init() {
|
|
625
624
|
try {
|
|
626
|
-
//
|
|
625
|
+
// 关键修复:在初始化前,先清理页面上所有旧的容器元素
|
|
627
626
|
// 防止切换模式或多次初始化时产生重复的元素
|
|
628
627
|
this.cleanupOrphanedElements();
|
|
629
|
-
// PC模式:预创建遮罩层(隐藏状态),避免后续移动DOM导致iframe重新加载
|
|
630
|
-
const actualMode = this.getActualMode();
|
|
631
|
-
const isPC = actualMode === 'popup';
|
|
632
|
-
if (isPC) {
|
|
633
|
-
// 创建遮罩层但不立即显示(showImmediately = false)
|
|
634
|
-
this.createOverlay(false);
|
|
635
|
-
}
|
|
636
628
|
// 创建隐藏的iframe(预连接到SSE)
|
|
637
|
-
// 注意:createIframe
|
|
629
|
+
// 注意:createIframe 会将容器添加到 body
|
|
638
630
|
this.createIframe();
|
|
639
631
|
this.isCreated = true;
|
|
640
632
|
if (this.debug) {
|
|
@@ -658,70 +650,24 @@ class IframeManager {
|
|
|
658
650
|
throw new Error('Iframe not initialized. Call init() first.');
|
|
659
651
|
}
|
|
660
652
|
try {
|
|
661
|
-
const actualMode = this.getActualMode();
|
|
662
|
-
const isPC = actualMode === 'popup';
|
|
663
|
-
// PC模式:创建或显示遮罩层
|
|
664
|
-
if (isPC) {
|
|
665
|
-
// 如果遮罩层不存在,创建并显示;如果已存在,直接显示
|
|
666
|
-
this.createOverlay(true); // showImmediately = true,立即显示
|
|
667
|
-
}
|
|
668
653
|
// 显示已创建的容器
|
|
669
654
|
// 关键优化:容器在 init() 时已经添加到正确位置,这里只改变样式,不移动 DOM
|
|
670
655
|
// 这样可以避免 iframe 重新加载
|
|
671
656
|
if (this.containerElement) {
|
|
672
657
|
// 确保容器在 DOM 中(理论上已经在 init() 时添加,但为了安全)
|
|
673
658
|
if (!this.containerElement.parentNode) {
|
|
674
|
-
// 如果容器不在 DOM
|
|
675
|
-
|
|
676
|
-
// PC模式:确保遮罩层在 DOM 中,然后将容器添加到遮罩层
|
|
677
|
-
if (!this.overlayElement.parentNode) {
|
|
678
|
-
document.body.appendChild(this.overlayElement);
|
|
679
|
-
}
|
|
680
|
-
this.overlayElement.appendChild(this.containerElement);
|
|
681
|
-
}
|
|
682
|
-
else {
|
|
683
|
-
// 移动端模式:直接添加到 body
|
|
684
|
-
document.body.appendChild(this.containerElement);
|
|
685
|
-
}
|
|
686
|
-
}
|
|
687
|
-
// 注意:不再检查容器是否在遮罩层内,因为 init() 时已经正确放置
|
|
688
|
-
// 如果移动容器会导致 iframe 重新加载,所以不移动
|
|
689
|
-
if (isPC) {
|
|
690
|
-
// PC模式:配置为居中弹窗样式
|
|
691
|
-
Object.assign(this.containerElement.style, {
|
|
692
|
-
position: 'fixed',
|
|
693
|
-
top: '50%',
|
|
694
|
-
left: '50%',
|
|
695
|
-
transform: 'translate(-50%, -50%)',
|
|
696
|
-
visibility: 'visible',
|
|
697
|
-
opacity: '1',
|
|
698
|
-
display: 'block'
|
|
699
|
-
});
|
|
700
|
-
// 显示遮罩层(确保在 DOM 中)
|
|
701
|
-
if (this.overlayElement) {
|
|
702
|
-
// 确保遮罩层在 DOM 中
|
|
703
|
-
if (!this.overlayElement.parentNode) {
|
|
704
|
-
document.body.appendChild(this.overlayElement);
|
|
705
|
-
}
|
|
706
|
-
// 显示遮罩层(只改变样式,不移动)
|
|
707
|
-
Object.assign(this.overlayElement.style, {
|
|
708
|
-
visibility: 'visible',
|
|
709
|
-
opacity: '1',
|
|
710
|
-
display: 'flex'
|
|
711
|
-
});
|
|
712
|
-
}
|
|
713
|
-
}
|
|
714
|
-
else {
|
|
715
|
-
// 移动端模式:直接全屏显示,不需要遮罩层
|
|
716
|
-
Object.assign(this.containerElement.style, {
|
|
717
|
-
position: 'fixed',
|
|
718
|
-
visibility: 'visible',
|
|
719
|
-
opacity: '1',
|
|
720
|
-
display: 'block'
|
|
721
|
-
});
|
|
722
|
-
// 禁用body滚动,防止出现滚动条
|
|
723
|
-
this.preventBodyScroll(true);
|
|
659
|
+
// 如果容器不在 DOM 中(异常情况),直接添加到 body
|
|
660
|
+
document.body.appendChild(this.containerElement);
|
|
724
661
|
}
|
|
662
|
+
// PC和移动端都使用全屏模式
|
|
663
|
+
Object.assign(this.containerElement.style, {
|
|
664
|
+
position: 'fixed',
|
|
665
|
+
visibility: 'visible',
|
|
666
|
+
opacity: '1',
|
|
667
|
+
display: 'block'
|
|
668
|
+
});
|
|
669
|
+
// 禁用body滚动,防止出现滚动条
|
|
670
|
+
this.preventBodyScroll(true);
|
|
725
671
|
}
|
|
726
672
|
this.isOpen = true;
|
|
727
673
|
if (this.debug) {
|
|
@@ -753,22 +699,10 @@ class IframeManager {
|
|
|
753
699
|
opacity: '0',
|
|
754
700
|
display: 'none'
|
|
755
701
|
});
|
|
756
|
-
//
|
|
757
|
-
}
|
|
758
|
-
// 隐藏遮罩层但不移除(仅PC模式,避免重新创建导致 iframe 重新加载)
|
|
759
|
-
if (this.overlayElement) {
|
|
760
|
-
Object.assign(this.overlayElement.style, {
|
|
761
|
-
visibility: 'hidden',
|
|
762
|
-
opacity: '0',
|
|
763
|
-
display: 'none'
|
|
764
|
-
});
|
|
765
|
-
// 不移除遮罩层,下次显示时直接显示即可
|
|
766
|
-
}
|
|
767
|
-
// 恢复body滚动(移动端模式)
|
|
768
|
-
const actualModeForScroll = this.getActualMode();
|
|
769
|
-
if (actualModeForScroll === 'fullscreen') {
|
|
770
|
-
this.preventBodyScroll(false);
|
|
702
|
+
// 注意:不移动容器,保持容器在当前位置(body),避免 iframe 重新加载
|
|
771
703
|
}
|
|
704
|
+
// 恢复body滚动
|
|
705
|
+
this.preventBodyScroll(false);
|
|
772
706
|
this.isOpen = false;
|
|
773
707
|
if (this.debug) {
|
|
774
708
|
console.log('CustomerSDK iframe hidden (SSE still connected)');
|
|
@@ -789,16 +723,12 @@ class IframeManager {
|
|
|
789
723
|
*/
|
|
790
724
|
destroy() {
|
|
791
725
|
this.hide();
|
|
792
|
-
//
|
|
726
|
+
// 移除容器
|
|
793
727
|
if (this.containerElement) {
|
|
794
728
|
this.containerElement.remove();
|
|
795
729
|
this.containerElement = null;
|
|
796
730
|
this.iframeElement = null;
|
|
797
731
|
}
|
|
798
|
-
if (this.overlayElement) {
|
|
799
|
-
this.overlayElement.remove();
|
|
800
|
-
this.overlayElement = null;
|
|
801
|
-
}
|
|
802
732
|
this.isCreated = false;
|
|
803
733
|
if (this.debug) {
|
|
804
734
|
console.log('CustomerSDK container destroyed');
|
|
@@ -819,19 +749,9 @@ class IframeManager {
|
|
|
819
749
|
}
|
|
820
750
|
}
|
|
821
751
|
/**
|
|
822
|
-
*
|
|
752
|
+
* 清理页面上孤立的容器元素(防止重复创建)
|
|
823
753
|
*/
|
|
824
754
|
cleanupOrphanedElements() {
|
|
825
|
-
// 清理所有旧的遮罩层元素(不属于当前实例的)
|
|
826
|
-
const existingOverlays = document.querySelectorAll('.customer-sdk-overlay');
|
|
827
|
-
existingOverlays.forEach((overlay) => {
|
|
828
|
-
if (overlay !== this.overlayElement) {
|
|
829
|
-
overlay.remove();
|
|
830
|
-
if (this.debug) {
|
|
831
|
-
console.log('清理旧的遮罩层元素');
|
|
832
|
-
}
|
|
833
|
-
}
|
|
834
|
-
});
|
|
835
755
|
// 清理所有旧的容器元素(不属于当前实例的)
|
|
836
756
|
const existingContainers = document.querySelectorAll('.customer-sdk-container');
|
|
837
757
|
existingContainers.forEach((container) => {
|
|
@@ -843,55 +763,6 @@ class IframeManager {
|
|
|
843
763
|
}
|
|
844
764
|
});
|
|
845
765
|
}
|
|
846
|
-
/**
|
|
847
|
-
* 创建遮罩层(PC模式使用)
|
|
848
|
-
* @param showImmediately 是否立即显示,默认 false(用于 init() 时创建但不显示)
|
|
849
|
-
*/
|
|
850
|
-
createOverlay(showImmediately = false) {
|
|
851
|
-
// 如果遮罩层已存在
|
|
852
|
-
if (this.overlayElement) {
|
|
853
|
-
// 如果不在 DOM 中,添加到 DOM
|
|
854
|
-
if (!this.overlayElement.parentNode) {
|
|
855
|
-
document.body.appendChild(this.overlayElement);
|
|
856
|
-
}
|
|
857
|
-
// 根据参数决定是否显示
|
|
858
|
-
if (showImmediately) {
|
|
859
|
-
Object.assign(this.overlayElement.style, {
|
|
860
|
-
visibility: 'visible',
|
|
861
|
-
opacity: '1',
|
|
862
|
-
display: 'flex'
|
|
863
|
-
});
|
|
864
|
-
}
|
|
865
|
-
return;
|
|
866
|
-
}
|
|
867
|
-
// 创建新的遮罩层
|
|
868
|
-
this.overlayElement = document.createElement('div');
|
|
869
|
-
this.overlayElement.className = 'customer-sdk-overlay';
|
|
870
|
-
Object.assign(this.overlayElement.style, {
|
|
871
|
-
position: 'fixed',
|
|
872
|
-
top: '0',
|
|
873
|
-
left: '0',
|
|
874
|
-
width: '100%',
|
|
875
|
-
height: '100%',
|
|
876
|
-
backgroundColor: 'rgba(0, 0, 0, 0.5)',
|
|
877
|
-
zIndex: '999998',
|
|
878
|
-
display: showImmediately ? 'flex' : 'none', // 根据参数决定初始显示状态
|
|
879
|
-
alignItems: 'center',
|
|
880
|
-
justifyContent: 'center',
|
|
881
|
-
cursor: this.config.allowClose ? 'pointer' : 'default',
|
|
882
|
-
visibility: showImmediately ? 'visible' : 'hidden',
|
|
883
|
-
opacity: showImmediately ? '1' : '0'
|
|
884
|
-
});
|
|
885
|
-
// 点击遮罩层关闭(只添加一次事件监听器)
|
|
886
|
-
if (this.config.allowClose) {
|
|
887
|
-
this.overlayElement.addEventListener('click', (e) => {
|
|
888
|
-
if (e.target === this.overlayElement) {
|
|
889
|
-
this.close();
|
|
890
|
-
}
|
|
891
|
-
});
|
|
892
|
-
}
|
|
893
|
-
document.body.appendChild(this.overlayElement);
|
|
894
|
-
}
|
|
895
766
|
/**
|
|
896
767
|
* 创建iframe(默认隐藏状态,用于SSE连接)
|
|
897
768
|
*/
|
|
@@ -937,25 +808,26 @@ class IframeManager {
|
|
|
937
808
|
// 根据设备类型设置模式
|
|
938
809
|
const actualMode = this.getActualMode();
|
|
939
810
|
const isPC = actualMode === 'popup';
|
|
940
|
-
this.iframeElement.scrolling =
|
|
941
|
-
// PC
|
|
942
|
-
// 移动端:使用全屏
|
|
811
|
+
this.iframeElement.scrolling = 'auto'; // PC和移动端都显示滚动条
|
|
812
|
+
// PC模式:使用配置的宽度,高度100%;移动端:100%宽度和高度
|
|
943
813
|
const containerStyles = isPC ? {
|
|
944
|
-
// PC
|
|
814
|
+
// PC模式:配置的宽度,高度100%
|
|
945
815
|
width: `${this.config.width || 450}px`,
|
|
946
|
-
height:
|
|
816
|
+
height: '100%',
|
|
947
817
|
maxWidth: '90vw',
|
|
948
|
-
maxHeight: '
|
|
818
|
+
maxHeight: '100%',
|
|
949
819
|
backgroundColor: '#ffffff',
|
|
950
|
-
borderRadius: '
|
|
951
|
-
boxShadow: '
|
|
820
|
+
borderRadius: '0',
|
|
821
|
+
boxShadow: 'none',
|
|
952
822
|
border: 'none',
|
|
953
823
|
position: 'fixed',
|
|
954
824
|
zIndex: '999999',
|
|
955
|
-
// PC
|
|
956
|
-
top: '
|
|
825
|
+
// PC模式:水平居中,垂直占满
|
|
826
|
+
top: '0',
|
|
957
827
|
left: '50%',
|
|
958
|
-
|
|
828
|
+
bottom: '0',
|
|
829
|
+
right: 'auto',
|
|
830
|
+
transform: 'translateX(-50%)',
|
|
959
831
|
overflow: 'hidden',
|
|
960
832
|
// 初始隐藏的关键样式
|
|
961
833
|
visibility: 'hidden',
|
|
@@ -991,35 +863,20 @@ class IframeManager {
|
|
|
991
863
|
width: '100%',
|
|
992
864
|
height: '100%',
|
|
993
865
|
border: 'none',
|
|
994
|
-
borderRadius: 'inherit'
|
|
995
|
-
...(isPC ? {} : {
|
|
996
|
-
// 移动端:彻底禁用滚动条
|
|
997
|
-
overflow: 'hidden',
|
|
998
|
-
scrollbarWidth: 'none', // Firefox
|
|
999
|
-
msOverflowStyle: 'none', // IE/Edge
|
|
1000
|
-
WebkitScrollbar: 'none' // WebKit (Chrome/Safari)
|
|
1001
|
-
})
|
|
866
|
+
borderRadius: 'inherit'
|
|
1002
867
|
};
|
|
1003
868
|
Object.assign(this.iframeElement.style, iframeStyles);
|
|
1004
869
|
// 将iframe放入容器
|
|
1005
870
|
this.containerElement.appendChild(this.iframeElement);
|
|
1006
871
|
// 添加iframe加载事件监听(移动端样式优化)
|
|
1007
872
|
this.iframeElement.addEventListener('load', () => {
|
|
1008
|
-
//
|
|
873
|
+
// 移动端注入自定义样式
|
|
1009
874
|
if (!isPC) {
|
|
1010
875
|
this.injectMobileStyles();
|
|
1011
876
|
}
|
|
1012
877
|
});
|
|
1013
|
-
//
|
|
1014
|
-
|
|
1015
|
-
if (isPC && this.overlayElement) {
|
|
1016
|
-
// PC模式:添加到遮罩层(遮罩层已在 init() 中创建)
|
|
1017
|
-
this.overlayElement.appendChild(this.containerElement);
|
|
1018
|
-
}
|
|
1019
|
-
else {
|
|
1020
|
-
// 移动端模式:直接添加到body
|
|
1021
|
-
document.body.appendChild(this.containerElement);
|
|
1022
|
-
}
|
|
878
|
+
// 关键优化:容器直接添加到body,避免后续移动DOM导致iframe重新加载
|
|
879
|
+
document.body.appendChild(this.containerElement);
|
|
1023
880
|
if (this.debug) {
|
|
1024
881
|
console.log('CustomerSDK container created (hidden, ready for SSE)');
|
|
1025
882
|
}
|
|
@@ -20989,9 +20846,9 @@ class CustomerServiceSDK {
|
|
|
20989
20846
|
// checkScreenshot 消息由 ScreenshotManager 处理,不需要在这里处理
|
|
20990
20847
|
},
|
|
20991
20848
|
onClose: () => {
|
|
20992
|
-
// iframe
|
|
20849
|
+
// iframe关闭时,清理图标拖动事件监听器,并重新显示图标
|
|
20993
20850
|
this.iconManager?.forceCleanupDragEvents();
|
|
20994
|
-
this.iconManager?.
|
|
20851
|
+
this.iconManager?.show();
|
|
20995
20852
|
},
|
|
20996
20853
|
...options
|
|
20997
20854
|
});
|
|
@@ -21001,9 +20858,9 @@ class CustomerServiceSDK {
|
|
|
21001
20858
|
this.iconManager.onClick(() => {
|
|
21002
20859
|
// 打开iframe时清除红点通知
|
|
21003
20860
|
this.clearNotification();
|
|
20861
|
+
// 点击图标后隐藏图标
|
|
20862
|
+
this.iconManager?.hide();
|
|
21004
20863
|
this.iframeManager?.show();
|
|
21005
|
-
// iframe 打开后,禁用图标点击(防止重复打开)
|
|
21006
|
-
this.iconManager?.disableClick();
|
|
21007
20864
|
});
|
|
21008
20865
|
// 初始化截图管理器(如果启用了截图功能)
|
|
21009
20866
|
if (config.screenshot) {
|