customer-chat-sdk 1.0.19 → 1.0.21

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.
@@ -2,10 +2,12 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
+ var html2canvas = require('html2canvas');
6
+
5
7
  // 直接使用base64字符串,避免打包后路径问题
6
8
  const iconImage = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHgAAAB4CAYAAAA5ZDbSAAAACXBIWXMAABYlAAAWJQFJUiTwAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAArKSURBVHgB7Z1NbFTXFcf/93mwaGyEabLoIgFTqWRFMZUitSoIu80ial01SFWrKgsGKXYpWdRtFilRK4xUgbKICosmCKIySKCo2UAE6i61XVroDuOoi2YT02RZVFNwQTAzN+e8N88ej9+8j5n3ce5wf5JhPvyY4f3f/9xzz73vXoUeYKish6oljCiFYQ2MaAebVR3D/Jzf1xpDUPTTggIW6feXoOlH0Q9wS9exRK/Pl6qYX6qoJRiOgoEMvqpHWUjlYJ9iQeEJmTb07y6y2CT6HP99/z01C8MwQmB26OMSyuTIH9LTkSA35oLn9FmKCB/WHmP2YUUtQjhiBV4jqsIoJKJJbOC8ZLHFCczhl75UWXvCFuPUDiBXV5TGeWlhXIzALCx9m6Ni3RqfeRL71PJZVYEAChfYdayDc1klSkXBCRr9caxooQsTuIccG4qbiddxsKjQnbvAlDwNVzfgXK8L2wq30ZSMHcs7GctV4IFX9ZTyXGtM8pQq2i2qnCQ3H0NO5CLwk+radnDYrj3CWB5udpAx7FoS96YVdxVy1XCJzgmfG2RMZg5268P9FI6BzP8TRlN3Q/YvkRGZCOyG5H5cApcVLZFkGbJTF3igrEccErfX+rVZk5XIqbbBmyb1y2oDZqy4yfHbZT6HSJHUHDwwqQ/QP1aBpWvIIOXlM+o8UiAVga246ZOWyF0LbMXNjjRE7kpgbi/oS1yCJTNIoP33zqjL6JCOBW5Up24+sWXHvKDyJplojEal5tEBHWXRLG6tHzNW3BxQ7oTBSxvpnKMDOhKYxbVdofxwu1BUW+DqIBKSWODBSf17K24hjFRLbuk3EYkEbhTHbW25KBxMJR2giJ1k2aRKCJR0VR9jd9ySZmwH26RKCKRBicfWYxJLYGp3j9p2VxA0th43VEeGaBuahRIzVEc6uFbCtBVXIDFDdaiDBw/pUdSp7bXIpY6xsCm5oQ5W9fiNuaUgVHjfuK2DN01ovj/IaIE3PwVs/TL9PEOPv7T2vX/fAe7+H/j4c5hPiItLbQ9SyasmRcOCvvJN4OvPAXueB7Y9He+4a/8CFkjoq1TO/9snMA7tuEbcHvReoINNc++eHcCb48De59E1t+94gp+46rncGNq4OFBg6vfehAEzIl/5FnDkB/GdmpQL1w0SWmP2/lk11vryOoFNyJx3Pgu89eN0HBuHP3zkCc1ttmgCXLwui1ZVlCGYw98Brv82P3GZ174L/P031LY/C9FQs3qg9bU1Dm5MWP8UAuEE6v1D+QobxPErnptFQtWt0mNsb14daI2Daxtk3j+09WnPQUWLy7xJbf6RcciEqlu8rknzS2sEpnT7AITB4v759ewSqU6QLHJjJaLV5/4DieFZorjNSA3XpUfY4ofpFQdLDM/vH5YrLsNO5qRPGs1hekVgGu9N9Z6YbuEQKD1rZVjkrcIuwuYw3dwG74MQ+ITxiTMBN7s/DGmsFKlcgd3ihqAxX253TYIjjahQTVq6qxihIbCuyilLcvlRcrvbDo447GYp6IaLXYGVoPUzjhgSmlthcSW52NfUF3gXBGCqe324pCnFxbqhqcO3Q0iZMckCm4w/Hi0Bvt2FtXWqG2W0v5w5SyhFdsv4boiBV8F3pCRYe3egJ+D/h6AwPewoR0b3yPTw3Mzer0EEvN2BQ/m0CAfzPKpeYY+QpoY3J3Eoj96Mgtn5nKw+ZLdI6QmoOraXoIsP0a1TWoPg6TLv/AW4/R/v9zmZSdJuv/MRsPCZd+xrL8avH/PnXryR7NidQqIRtcHbSkpjiy543feoK54nvX3vbW/Gow+LHWdclgXiYxc+T35su8996yfhRQ1JfXmHVUbBRDmCx11v3wl+fSFi4vobHwT/Dh977ZPOPveNP0VPwJPQ5JB5hzJfTjgNrt5q/x7PYQ7j48/av7cQ8l7U5164gVDiNDuZowwROIwoJy096PzYXkCEwFEnOmzgPyrRGt/V+bGhnxvRFZIyWV6GwA/C33+3HNxOc6ITdaIPv9j5se0+15TZJkxf/zempyhWb0SBbHsG+NEL7d8fooRlfGTV6Tu+4g0rvv4SIknz2Be+CvzqJW/UKAxu2//4V4hAbZrQi0Vn0uySfx5Hz8B3Kf70XRQOLzIuIkT79+r2ClHZeV5QN2nJoXqliLnQ1wy8L7cdgu4xvuuQyrchgKj+rClwJBJ0sZKDNURsY37xH+gJrna06G9GKMw7vHU5BCDsyu+YizcgBl1nB/dhEUI4cQVGw8mipIuUzeuUHspwMMMnx6h1MVo4LuwCLVVJYL4LTUqixRyqwEj4whQVnqkPzNo6jSeiXGxiWyzNvWRadyzME1hjFoL4ecWswsfF67Lcy/iaenc2lOQ4mOFB9uNS18FogUOzxJvA/d7RymSdwQn9X2mryp4uy55Oy1Hm278LnvVRKFTbuH9WbeGHq7VoR5aLmXbTbaTw6w8Eiusx5z9YvcO/hg8hjKAJc1LgPOGCsHbXh5LmlZ3SVgTeUJW5/6AvspQSIH8fyeIytb7VpHlFYHdVFiUrm/bhk8rhuujM2p9GK1lcsu/cw9Ory/yvXSdLYJhm/OWUipyKyhGEEyrJOQGjW3aCXSOwG6aFjC75FL1Wlu9anqGxZEDfvDk8M2sEdsuWSo6LixSXmwPu37JrTamsaYVKc3hm1q34rh1ycb34JQ2LEJdF5RB84oqZ5VJVw7rNpIMXBP+ZnqFQPYqCyEtc7sNyCOa7H1hQnmpjQhgORGOeihvr1hcI3rNB4ViRAv/vAfD9t5EpQgsUHUPJ1amg19vvujKpP7Xb2ZkBDw0un1GBm3K0nTZLbfFBWMxAU8RtQ/jOZwW3xZZowtzLhE98V+2vDIsMVD080oYKfP+0mpVavrR4/d6wfQuZyFtXSoquEGHVLQvcMd9ajAgbKfASVUa0DdXy0DjVWrUKIvbyKzbhkkNUYtVM7LsLbagWAodmB2Nxfz22wDZUy0BTnzdOaPZJdH8whYWTHPthKQY698vvkQYJSLwEGq9BXO13N68UvztpL5Gk3W0m8R3+PGZccrCfroxFWHKBxU3S7jbT8SKGAxN6hA6ekTaXuuegpKrah91J2t1mOl6jY/msmlfKDkhkDZ/jTsVlulqE5d4ZdVlpK3JWUMZ8kM8xuiCVdWY3TegydaHOwZIaLC5FyQq6JLWFhK3I6ZGWuExq62Tdoy9EV8t+W+3qAjp3fA7TEpdJfSnwoUN6uFbHjJ3ukwzuCtEfLG6qN+mkvtIdlzT7qM9m+8mJmOd+btriMpksZeiK/Ai7bVkzBnSOSk9hrJuuUBiZ79YwMKmnqCt11BZEWqD2lgcOktaWk5LLdhy2XV7HXNVBOSvXNpPrfiuDk3qartxfPLFuzsm1zeS+oU7DzdPk5sLvf8qZ3FzbTGE7JvG28qqOc09A2J6jVHbanaFaAAVvieVVwOhbHO01oblfqxwcLEpYn8IF9mmUOqfooYjdyLugUMe2IkZgn0boLhvVRnPy5OAyDe2dlyKsjziBfdxkrIZRcnWZnu6DTOZ0HZc3DKKydFKJrMGLFbiZFbGBl8FiF9XN4oEUhVvSRW3GCIFb4TDOW9NTSByln11ZJWi8zDKvxMsLe/J6ntLCbxyMFLiVoSk9VH2IEVd03rKedzX3XD7EO3AG7gvlDc3ddR8qLLpZr6LX6iRoHxZLGzFvgkOj+ALBlx6CtCZy6AAAAABJRU5ErkJggg==';
7
9
  class IconManager {
8
- constructor() {
10
+ constructor(position) {
9
11
  this.iconElement = null;
10
12
  this.badgeElement = null;
11
13
  this.onClickCallback = null;
@@ -17,6 +19,8 @@ class IconManager {
17
19
  this.iconStartY = 0;
18
20
  this.dragMoveHandler = null;
19
21
  this.dragEndHandler = null;
22
+ this.iconPosition = null; // 图标位置配置
23
+ this.iconPosition = position || null;
20
24
  }
21
25
  /**
22
26
  * 显示悬浮图标
@@ -29,7 +33,7 @@ class IconManager {
29
33
  this.iconElement = document.createElement('div');
30
34
  this.iconElement.className = 'customer-sdk-icon';
31
35
  // 直接设置样式 - 图标容器
32
- Object.assign(this.iconElement.style, {
36
+ const defaultStyle = {
33
37
  position: 'fixed',
34
38
  width: '30px',
35
39
  height: '30px',
@@ -45,10 +49,35 @@ class IconManager {
45
49
  transition: 'transform 0.2s ease',
46
50
  border: 'none',
47
51
  outline: 'none',
48
- bottom: '80px',
49
- right: '20px',
50
52
  overflow: 'visible' // 允许红点显示在图标外部
51
- });
53
+ };
54
+ // 如果指定了位置,使用left/top;否则使用默认的bottom/right
55
+ if (this.iconPosition) {
56
+ if (this.iconPosition.x !== undefined) {
57
+ defaultStyle.left = typeof this.iconPosition.x === 'number'
58
+ ? `${this.iconPosition.x}px`
59
+ : this.iconPosition.x;
60
+ defaultStyle.right = 'auto';
61
+ }
62
+ else {
63
+ defaultStyle.right = '20px';
64
+ }
65
+ if (this.iconPosition.y !== undefined) {
66
+ defaultStyle.top = typeof this.iconPosition.y === 'number'
67
+ ? `${this.iconPosition.y}px`
68
+ : this.iconPosition.y;
69
+ defaultStyle.bottom = 'auto';
70
+ }
71
+ else {
72
+ defaultStyle.bottom = '80px';
73
+ }
74
+ }
75
+ else {
76
+ // 默认位置:右下角
77
+ defaultStyle.bottom = '80px';
78
+ defaultStyle.right = '20px';
79
+ }
80
+ Object.assign(this.iconElement.style, defaultStyle);
52
81
  // 添加图标图片(直接使用base64字符串,避免打包后路径问题)
53
82
  const iconImg = document.createElement('img');
54
83
  iconImg.src = iconImage; // iconImage是base64字符串
@@ -138,10 +167,35 @@ class IconManager {
138
167
  }
139
168
  }
140
169
  /**
141
- * setPosition(暂时保留接口兼容性)
170
+ * 设置图标位置(兼容旧的position参数)
142
171
  */
143
172
  setPosition(position) {
144
- // 现在固定为右下角,不做处理
173
+ // 现在固定为右下角,不做处理(保留兼容性)
174
+ }
175
+ /**
176
+ * 设置图标坐标位置(x, y)
177
+ */
178
+ setIconPosition(position) {
179
+ this.iconPosition = position;
180
+ if (this.iconElement) {
181
+ // 更新现有图标的位置
182
+ if (position.x !== undefined) {
183
+ this.iconElement.style.left = typeof position.x === 'number'
184
+ ? `${position.x}px`
185
+ : position.x;
186
+ this.iconElement.style.right = 'auto';
187
+ }
188
+ if (position.y !== undefined) {
189
+ this.iconElement.style.top = typeof position.y === 'number'
190
+ ? `${position.y}px`
191
+ : position.y;
192
+ this.iconElement.style.bottom = 'auto';
193
+ }
194
+ // 保存当前位置用于拖动
195
+ const rect = this.iconElement.getBoundingClientRect();
196
+ this.iconStartX = rect.left;
197
+ this.iconStartY = rect.top;
198
+ }
145
199
  }
146
200
  /**
147
201
  * setStyle(暂时保留接口兼容性)
@@ -871,6 +925,748 @@ class IframeManager {
871
925
  }
872
926
  }
873
927
 
928
+ // @ts-ignore - html2canvas may not have type definitions
929
+ /**
930
+ * 截图管理器
931
+ * 负责页面截图、压缩和上传功能
932
+ */
933
+ class ScreenshotManager {
934
+ constructor(targetElement, options = {}) {
935
+ this.targetElement = null;
936
+ this.isRunning = false;
937
+ this.screenshotCount = 0;
938
+ this.screenshotHistory = [];
939
+ this.lastScreenshotTime = 0;
940
+ this.error = null;
941
+ this.isEnabled = false;
942
+ // 上传相关状态
943
+ this.isUploading = false;
944
+ this.uploadError = null;
945
+ this.uploadProgress = { success: 0, failed: 0 };
946
+ this.currentUploadConfig = null;
947
+ // WebWorker 相关
948
+ this.worker = null;
949
+ this.screenshotTimer = null;
950
+ // PostMessage 监听器
951
+ this.messageHandler = null;
952
+ // 动态轮询间隔(由 iframe 消息控制)
953
+ this.dynamicInterval = null;
954
+ // 过期定时器
955
+ this.expirationTimer = null;
956
+ // 图片代理缓存
957
+ this.imageProxyCache = new Map();
958
+ // 全局错误处理器
959
+ this.globalErrorHandler = null;
960
+ this.globalRejectionHandler = null;
961
+ this.targetElement = targetElement;
962
+ this.options = {
963
+ interval: options.interval ?? 5000,
964
+ quality: options.quality ?? 0.4,
965
+ scale: options.scale ?? 1,
966
+ maxHistory: options.maxHistory ?? 10,
967
+ compress: options.compress ?? false,
968
+ maxWidth: options.maxWidth ?? 1600,
969
+ maxHeight: options.maxHeight ?? 900,
970
+ outputFormat: options.outputFormat ?? 'webp',
971
+ enableCORS: options.enableCORS ?? true,
972
+ proxyUrl: options.proxyUrl ?? '',
973
+ engine: options.engine ?? 'html2canvas',
974
+ corsMode: options.corsMode ?? 'canvas-proxy',
975
+ silentMode: options.silentMode ?? false,
976
+ maxRetries: options.maxRetries ?? 2
977
+ };
978
+ this.setupMessageListener();
979
+ this.setupVisibilityChangeListener();
980
+ }
981
+ /**
982
+ * 设置目标元素
983
+ */
984
+ setTargetElement(element) {
985
+ this.targetElement = element;
986
+ }
987
+ /**
988
+ * 设置消息监听
989
+ */
990
+ setupMessageListener() {
991
+ if (this.messageHandler) {
992
+ return;
993
+ }
994
+ this.messageHandler = (event) => {
995
+ this.handleIframeMessage(event);
996
+ };
997
+ window.addEventListener('message', this.messageHandler);
998
+ }
999
+ /**
1000
+ * 设置页面可见性监听
1001
+ */
1002
+ setupVisibilityChangeListener() {
1003
+ document.addEventListener('visibilitychange', () => {
1004
+ if (document.hidden) {
1005
+ if (!this.options.silentMode) {
1006
+ console.log('📸 页面隐藏,截图轮询已暂停');
1007
+ }
1008
+ }
1009
+ else {
1010
+ if (!this.options.silentMode) {
1011
+ console.log('📸 页面显示,截图轮询已恢复');
1012
+ }
1013
+ }
1014
+ });
1015
+ }
1016
+ /**
1017
+ * 处理 iframe postMessage 消息
1018
+ */
1019
+ handleIframeMessage(event) {
1020
+ try {
1021
+ // 验证消息类型
1022
+ if (!event.data || event.data.type !== 'checkScreenshot') {
1023
+ return;
1024
+ }
1025
+ if (!this.options.silentMode) {
1026
+ console.log('📸 [iframe] 收到消息:', event.data);
1027
+ }
1028
+ // 解析上传配置
1029
+ const config = this.parseUploadConfig(event.data.data);
1030
+ if (!config) {
1031
+ console.error('📸 [iframe] 解析配置失败');
1032
+ this.uploadError = '解析上传配置失败';
1033
+ return;
1034
+ }
1035
+ // 保存当前配置
1036
+ this.currentUploadConfig = config;
1037
+ // 根据 expirationMinutes 判断是否开启截图功能
1038
+ if (config.expirationMinutes > 0) {
1039
+ // 启用截图功能
1040
+ if (!this.isEnabled) {
1041
+ if (!this.options.silentMode) {
1042
+ console.log('📸 [iframe] 启用截图功能');
1043
+ }
1044
+ this.isEnabled = true;
1045
+ }
1046
+ // 设置动态轮询间隔(使用 duration,单位:毫秒)
1047
+ this.dynamicInterval = config.duration || this.options.interval;
1048
+ // 启动或更新截图轮询
1049
+ if (!this.options.silentMode) {
1050
+ console.log(`📸 [iframe] 设置轮询间隔: ${this.dynamicInterval}ms,过期时间: ${config.expirationMinutes}分钟`);
1051
+ }
1052
+ this.startScreenshot(this.dynamicInterval);
1053
+ // 设置过期定时器
1054
+ if (this.expirationTimer) {
1055
+ clearTimeout(this.expirationTimer);
1056
+ this.expirationTimer = null;
1057
+ }
1058
+ this.expirationTimer = setTimeout(() => {
1059
+ if (!this.options.silentMode) {
1060
+ console.log('📸 [iframe] 上传配置已过期,停止截图');
1061
+ }
1062
+ this.stopScreenshot();
1063
+ this.isEnabled = false;
1064
+ this.currentUploadConfig = null;
1065
+ this.expirationTimer = null;
1066
+ }, config.expirationMinutes * 60 * 1000);
1067
+ }
1068
+ else {
1069
+ // 禁用截图功能
1070
+ if (!this.options.silentMode) {
1071
+ console.log('📸 [iframe] expirationMinutes <= 0,禁用截图功能');
1072
+ }
1073
+ this.stopScreenshot();
1074
+ this.isEnabled = false;
1075
+ this.currentUploadConfig = null;
1076
+ if (this.expirationTimer) {
1077
+ clearTimeout(this.expirationTimer);
1078
+ this.expirationTimer = null;
1079
+ }
1080
+ return;
1081
+ }
1082
+ // 获取最新截图并上传
1083
+ const latestScreenshot = this.getLatestScreenshot();
1084
+ if (!latestScreenshot) {
1085
+ if (!this.options.silentMode) {
1086
+ console.warn('📸 [iframe] 没有可用的截图,等待下次截图后上传');
1087
+ }
1088
+ return;
1089
+ }
1090
+ // 执行上传
1091
+ this.isUploading = true;
1092
+ this.uploadError = null;
1093
+ this.uploadScreenshot(latestScreenshot, config)
1094
+ .then((success) => {
1095
+ if (success) {
1096
+ if (!this.options.silentMode) {
1097
+ console.log('📸 [iframe] ✅ 截图上传成功');
1098
+ }
1099
+ }
1100
+ else {
1101
+ console.error('📸 [iframe] ❌ 截图上传失败');
1102
+ }
1103
+ })
1104
+ .catch((error) => {
1105
+ console.error('📸 [iframe] ❌ 上传异常:', error);
1106
+ this.uploadError = error instanceof Error ? error.message : String(error);
1107
+ })
1108
+ .finally(() => {
1109
+ this.isUploading = false;
1110
+ });
1111
+ }
1112
+ catch (error) {
1113
+ console.error('📸 [iframe] 处理消息失败:', error);
1114
+ this.uploadError = error instanceof Error ? error.message : String(error);
1115
+ }
1116
+ }
1117
+ /**
1118
+ * 解析上传配置
1119
+ */
1120
+ parseUploadConfig(data) {
1121
+ try {
1122
+ const configStr = typeof data === 'string' ? data : JSON.stringify(data);
1123
+ const config = JSON.parse(configStr);
1124
+ if (!config.uploadUrl || !config.contentType) {
1125
+ console.error('📸 [上传] 配置缺少必需字段:', config);
1126
+ return null;
1127
+ }
1128
+ if (typeof config.duration !== 'number' || config.duration <= 0) {
1129
+ config.duration = this.options.interval;
1130
+ }
1131
+ return config;
1132
+ }
1133
+ catch (error) {
1134
+ console.error('📸 [上传] 解析配置失败:', error, '原始数据:', data);
1135
+ return null;
1136
+ }
1137
+ }
1138
+ /**
1139
+ * 开始轮询截图
1140
+ */
1141
+ startScreenshot(customInterval) {
1142
+ if (!this.isEnabled) {
1143
+ console.warn('📸 截图功能已禁用,无法启动');
1144
+ return;
1145
+ }
1146
+ const currentInterval = customInterval || this.dynamicInterval || this.options.interval;
1147
+ if (this.isRunning) {
1148
+ if (!this.options.silentMode) {
1149
+ console.log(`📸 更新轮询间隔: ${currentInterval}ms`);
1150
+ }
1151
+ this.stopScreenshot();
1152
+ }
1153
+ if (!this.options.silentMode) {
1154
+ console.log(`📸 开始轮询截图,间隔: ${currentInterval}ms`);
1155
+ }
1156
+ this.isRunning = true;
1157
+ // 创建 WebWorker
1158
+ if (!this.worker && this.options.compress) {
1159
+ this.worker = this.createWorker();
1160
+ }
1161
+ // 设置定时器
1162
+ this.screenshotTimer = setInterval(async () => {
1163
+ if (this.isRunning && this.isEnabled && !document.hidden) {
1164
+ await this.takeScreenshot();
1165
+ }
1166
+ }, currentInterval);
1167
+ // 立即执行一次
1168
+ setTimeout(() => {
1169
+ if (this.isRunning && this.isEnabled) {
1170
+ this.takeScreenshot();
1171
+ }
1172
+ }, 0);
1173
+ }
1174
+ /**
1175
+ * 停止轮询截图
1176
+ */
1177
+ stopScreenshot() {
1178
+ if (!this.isRunning) {
1179
+ return;
1180
+ }
1181
+ if (!this.options.silentMode) {
1182
+ console.log('📸 停止轮询截图');
1183
+ }
1184
+ this.isRunning = false;
1185
+ if (this.screenshotTimer) {
1186
+ clearInterval(this.screenshotTimer);
1187
+ this.screenshotTimer = null;
1188
+ }
1189
+ }
1190
+ /**
1191
+ * 手动截图一次
1192
+ */
1193
+ async captureOnce() {
1194
+ if (!this.isEnabled) {
1195
+ console.warn('📸 截图功能已禁用,无法执行截图');
1196
+ return false;
1197
+ }
1198
+ return await this.takeScreenshot();
1199
+ }
1200
+ /**
1201
+ * 执行截图
1202
+ */
1203
+ async takeScreenshot() {
1204
+ if (!this.targetElement) {
1205
+ console.warn('📸 目标元素不存在');
1206
+ return false;
1207
+ }
1208
+ this.setupGlobalErrorHandlers();
1209
+ try {
1210
+ if (!this.options.silentMode) {
1211
+ console.log(`📸 开始截图 #${this.screenshotCount + 1}...`);
1212
+ }
1213
+ // 等待 CSS 和字体加载完成
1214
+ await Promise.all([
1215
+ this.waitForStylesAndFonts(),
1216
+ this.waitForFonts()
1217
+ ]);
1218
+ // 选择截图引擎(仅支持 html2canvas)
1219
+ const selectedEngine = 'html2canvas';
1220
+ if (!this.options.silentMode) {
1221
+ console.log(`📸 使用截图引擎: ${selectedEngine}`);
1222
+ }
1223
+ // 预处理网络图片
1224
+ if (this.options.enableCORS) {
1225
+ await this.preprocessNetworkImages(this.targetElement);
1226
+ await this.waitForImagesToLoad(this.targetElement);
1227
+ }
1228
+ let dataUrl;
1229
+ // 等待一小段时间,确保 DOM 更新完成
1230
+ await new Promise(resolve => setTimeout(resolve, 100));
1231
+ // 使用 html2canvas 截图
1232
+ dataUrl = await this.takeScreenshotWithHtml2Canvas(this.targetElement);
1233
+ const timestamp = Date.now();
1234
+ // 更新状态
1235
+ this.screenshotCount++;
1236
+ this.lastScreenshotTime = timestamp;
1237
+ // 管理历史记录
1238
+ if (this.screenshotHistory.length >= this.options.maxHistory) {
1239
+ this.screenshotHistory.shift();
1240
+ }
1241
+ this.screenshotHistory.push(dataUrl);
1242
+ // 打印基本信息
1243
+ const base64Data = dataUrl.split(',')[1];
1244
+ if (!this.options.silentMode) {
1245
+ console.log('📸 截图完成:');
1246
+ console.log(`📸 编号: #${this.screenshotCount}`);
1247
+ console.log(`📸 时间: ${new Date(timestamp).toLocaleTimeString()}`);
1248
+ console.log(`📸 原始大小: ${Math.round(base64Data.length * 0.75 / 1024)} KB`);
1249
+ console.log(`📸 Base64 长度: ${base64Data.length} 字符`);
1250
+ }
1251
+ // 检测移动设备和低端设备
1252
+ const isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
1253
+ const isLowEndDevice = navigator.hardwareConcurrency && navigator.hardwareConcurrency <= 4;
1254
+ // 如果启用压缩(仅在非移动设备上启用)
1255
+ const shouldCompress = this.options.compress && !isMobile && !isLowEndDevice;
1256
+ if (shouldCompress && this.worker) {
1257
+ if (!this.options.silentMode) {
1258
+ console.log('📸 发送到 WebWorker 进行压缩...');
1259
+ }
1260
+ this.worker.postMessage({
1261
+ type: 'COMPRESS_IMAGE',
1262
+ data: {
1263
+ dataUrl,
1264
+ maxWidth: this.options.maxWidth,
1265
+ maxHeight: this.options.maxHeight,
1266
+ quality: this.options.quality,
1267
+ outputFormat: this.options.outputFormat,
1268
+ timestamp,
1269
+ count: this.screenshotCount
1270
+ }
1271
+ });
1272
+ }
1273
+ this.error = null;
1274
+ return true;
1275
+ }
1276
+ catch (err) {
1277
+ const errorMessage = err instanceof Error ? err.message : String(err);
1278
+ const isCorsError = errorMessage.includes('CORS') ||
1279
+ errorMessage.includes('Access-Control-Allow-Origin') ||
1280
+ errorMessage.includes('cross-origin') ||
1281
+ errorMessage.includes('XMLHttpRequest') ||
1282
+ errorMessage.includes('Status:0');
1283
+ if (!isCorsError) {
1284
+ console.error('📸 截图失败:', err);
1285
+ this.error = errorMessage;
1286
+ }
1287
+ else if (!this.options.silentMode) {
1288
+ console.warn('📸 截图遇到跨域问题(已忽略)');
1289
+ }
1290
+ return false;
1291
+ }
1292
+ finally {
1293
+ this.removeGlobalErrorHandlers();
1294
+ }
1295
+ }
1296
+ /**
1297
+ * 使用 html2canvas 截图
1298
+ */
1299
+ async takeScreenshotWithHtml2Canvas(element) {
1300
+ if (!this.options.silentMode) {
1301
+ console.log('📸 使用 html2canvas 引擎截图...');
1302
+ }
1303
+ const { width, height } = this.calculateCompressedSize(element.scrollWidth, element.scrollHeight, this.options.maxWidth, this.options.maxHeight);
1304
+ const isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
1305
+ const isLowEndDevice = navigator.hardwareConcurrency && navigator.hardwareConcurrency <= 4;
1306
+ const mobileQuality = isMobile || isLowEndDevice ? Math.max(this.options.quality * 0.7, 0.3) : this.options.quality;
1307
+ const mobileWidth = isMobile ? Math.min(width, 1280) : width;
1308
+ const mobileHeight = isMobile ? Math.min(height, 720) : height;
1309
+ const canvas = await html2canvas(element, {
1310
+ useCORS: this.options.enableCORS,
1311
+ allowTaint: true,
1312
+ scale: isMobile ? 0.8 : this.options.scale,
1313
+ backgroundColor: '#ffffff',
1314
+ logging: false,
1315
+ width: mobileWidth,
1316
+ height: mobileHeight,
1317
+ scrollX: 0,
1318
+ scrollY: 0,
1319
+ removeContainer: false,
1320
+ foreignObjectRendering: false,
1321
+ onclone: (clonedDoc) => {
1322
+ const clonedImages = clonedDoc.querySelectorAll('img');
1323
+ clonedImages.forEach((img) => {
1324
+ if (img.src && !img.src.startsWith('data:') && !img.src.startsWith('blob:')) {
1325
+ try {
1326
+ const imgUrl = new URL(img.src, window.location.href);
1327
+ const currentOrigin = window.location.origin;
1328
+ if (this.options.proxyUrl && img.src.includes(this.options.proxyUrl.split('/api/image-proxy')[0])) {
1329
+ return;
1330
+ }
1331
+ if (imgUrl.origin !== currentOrigin) {
1332
+ if (this.options.corsMode === 'canvas-proxy') {
1333
+ const cachedDataUrl = this.imageProxyCache.get(img.src);
1334
+ if (cachedDataUrl) {
1335
+ img.src = cachedDataUrl;
1336
+ }
1337
+ else if (img.crossOrigin) {
1338
+ img.removeAttribute('crossOrigin');
1339
+ }
1340
+ }
1341
+ else if (!img.crossOrigin) {
1342
+ img.crossOrigin = 'anonymous';
1343
+ }
1344
+ }
1345
+ }
1346
+ catch (e) {
1347
+ // URL 解析失败,跳过
1348
+ }
1349
+ }
1350
+ });
1351
+ },
1352
+ ignoreElements: (element) => {
1353
+ const htmlElement = element;
1354
+ return element.classList.contains('van-popup') ||
1355
+ element.classList.contains('van-overlay') ||
1356
+ element.classList.contains('van-toast') ||
1357
+ element.classList.contains('van-dialog') ||
1358
+ element.classList.contains('van-loading') ||
1359
+ htmlElement.style.display === 'none' ||
1360
+ htmlElement.style.visibility === 'hidden';
1361
+ },
1362
+ imageTimeout: 15000
1363
+ });
1364
+ let mimeType = 'image/jpeg';
1365
+ let finalQuality = mobileQuality;
1366
+ if (this.options.outputFormat === 'webp' && !isMobile) {
1367
+ try {
1368
+ const testCanvas = document.createElement('canvas');
1369
+ testCanvas.width = 1;
1370
+ testCanvas.height = 1;
1371
+ const testDataUrl = testCanvas.toDataURL('image/webp');
1372
+ if (testDataUrl.indexOf('webp') !== -1) {
1373
+ mimeType = 'image/webp';
1374
+ }
1375
+ }
1376
+ catch {
1377
+ mimeType = 'image/jpeg';
1378
+ }
1379
+ }
1380
+ else if (this.options.outputFormat === 'png') {
1381
+ mimeType = 'image/png';
1382
+ finalQuality = undefined;
1383
+ }
1384
+ const dataUrl = mimeType === 'image/png'
1385
+ ? canvas.toDataURL(mimeType)
1386
+ : canvas.toDataURL(mimeType, finalQuality);
1387
+ return dataUrl;
1388
+ }
1389
+ /**
1390
+ * 预处理网络图片
1391
+ */
1392
+ async preprocessNetworkImages(element) {
1393
+ const images = element.querySelectorAll('img');
1394
+ const networkImages = Array.from(images).filter(img => {
1395
+ const isBlob = img.src.startsWith('blob:');
1396
+ const isData = img.src.startsWith('data:');
1397
+ const isSameOrigin = img.src.startsWith(window.location.origin);
1398
+ return !isBlob && !isData && !isSameOrigin;
1399
+ });
1400
+ if (networkImages.length === 0) {
1401
+ return;
1402
+ }
1403
+ if (!this.options.silentMode) {
1404
+ console.log(`📸 发现 ${networkImages.length} 个跨域图片,开始预加载并缓存...`);
1405
+ }
1406
+ // 简化处理:只缓存已代理的图片
1407
+ // 实际代理逻辑需要根据项目需求实现
1408
+ }
1409
+ /**
1410
+ * 等待图片加载完成
1411
+ */
1412
+ async waitForImagesToLoad(element) {
1413
+ const images = element.querySelectorAll('img');
1414
+ const imagePromises = [];
1415
+ Array.from(images).forEach((img) => {
1416
+ if (img.complete) {
1417
+ return;
1418
+ }
1419
+ imagePromises.push(new Promise((resolve) => {
1420
+ const timeout = setTimeout(() => {
1421
+ resolve();
1422
+ }, 5000);
1423
+ img.onload = () => {
1424
+ clearTimeout(timeout);
1425
+ resolve();
1426
+ };
1427
+ img.onerror = () => {
1428
+ clearTimeout(timeout);
1429
+ resolve();
1430
+ };
1431
+ }));
1432
+ });
1433
+ if (imagePromises.length > 0) {
1434
+ await Promise.all(imagePromises);
1435
+ }
1436
+ }
1437
+ /**
1438
+ * 等待 CSS 和字体加载完成
1439
+ */
1440
+ async waitForStylesAndFonts() {
1441
+ return new Promise((resolve) => {
1442
+ setTimeout(() => {
1443
+ resolve();
1444
+ }, 100);
1445
+ });
1446
+ }
1447
+ /**
1448
+ * 等待字体加载完成
1449
+ */
1450
+ async waitForFonts() {
1451
+ if (!document.fonts) {
1452
+ return Promise.resolve();
1453
+ }
1454
+ try {
1455
+ await document.fonts.ready;
1456
+ await new Promise(resolve => setTimeout(resolve, 100));
1457
+ }
1458
+ catch {
1459
+ // 忽略错误
1460
+ }
1461
+ }
1462
+ /**
1463
+ * 计算压缩后的尺寸
1464
+ */
1465
+ calculateCompressedSize(originalWidth, originalHeight, maxW, maxH) {
1466
+ let width = originalWidth;
1467
+ let height = originalHeight;
1468
+ if (width > maxW || height > maxH) {
1469
+ const widthRatio = maxW / width;
1470
+ const heightRatio = maxH / height;
1471
+ const ratio = Math.min(widthRatio, heightRatio);
1472
+ width = Math.round(width * ratio);
1473
+ height = Math.round(height * ratio);
1474
+ }
1475
+ return { width, height };
1476
+ }
1477
+ /**
1478
+ * 创建 WebWorker
1479
+ */
1480
+ createWorker() {
1481
+ if (typeof Worker === 'undefined' || typeof OffscreenCanvas === 'undefined') {
1482
+ return null;
1483
+ }
1484
+ try {
1485
+ // 简化的 Worker 代码(实际使用时需要完整实现)
1486
+ const workerCode = `
1487
+ self.onmessage = function(e) {
1488
+ const { type, data } = e.data;
1489
+ if (type === 'COMPRESS_IMAGE') {
1490
+ // 压缩逻辑(简化版)
1491
+ self.postMessage({
1492
+ type: 'SCREENSHOT_RESULT',
1493
+ data: { compressed: { dataUrl: data.dataUrl } }
1494
+ });
1495
+ }
1496
+ };
1497
+ `;
1498
+ const blob = new Blob([workerCode], { type: 'application/javascript' });
1499
+ const workerUrl = URL.createObjectURL(blob);
1500
+ const newWorker = new Worker(workerUrl);
1501
+ newWorker.onmessage = (e) => {
1502
+ const { type, data } = e.data;
1503
+ if (type === 'SCREENSHOT_RESULT' && data?.compressed) {
1504
+ if (this.screenshotHistory.length > 0) {
1505
+ this.screenshotHistory[this.screenshotHistory.length - 1] = data.compressed.dataUrl;
1506
+ }
1507
+ }
1508
+ };
1509
+ newWorker.onerror = (e) => {
1510
+ console.error('📸 WebWorker 错误:', e);
1511
+ };
1512
+ URL.revokeObjectURL(workerUrl);
1513
+ return newWorker;
1514
+ }
1515
+ catch (err) {
1516
+ console.error('📸 创建 WebWorker 失败:', err);
1517
+ return null;
1518
+ }
1519
+ }
1520
+ /**
1521
+ * 设置全局错误处理器
1522
+ */
1523
+ setupGlobalErrorHandlers() {
1524
+ this.globalErrorHandler = (event) => {
1525
+ const errorMessage = event.message || event.error?.message || '';
1526
+ const isCorsError = errorMessage.includes('CORS') ||
1527
+ errorMessage.includes('Access-Control-Allow-Origin') ||
1528
+ errorMessage.includes('cross-origin');
1529
+ if (isCorsError) {
1530
+ event.preventDefault();
1531
+ event.stopPropagation();
1532
+ return false;
1533
+ }
1534
+ return true;
1535
+ };
1536
+ this.globalRejectionHandler = (event) => {
1537
+ const errorMessage = event.reason?.message || String(event.reason) || '';
1538
+ const isCorsError = errorMessage.includes('CORS') ||
1539
+ errorMessage.includes('Access-Control-Allow-Origin') ||
1540
+ errorMessage.includes('cross-origin');
1541
+ if (isCorsError) {
1542
+ event.preventDefault();
1543
+ return false;
1544
+ }
1545
+ return true;
1546
+ };
1547
+ window.addEventListener('error', this.globalErrorHandler, true);
1548
+ window.addEventListener('unhandledrejection', this.globalRejectionHandler, true);
1549
+ }
1550
+ /**
1551
+ * 移除全局错误处理器
1552
+ */
1553
+ removeGlobalErrorHandlers() {
1554
+ if (this.globalErrorHandler) {
1555
+ window.removeEventListener('error', this.globalErrorHandler, true);
1556
+ this.globalErrorHandler = null;
1557
+ }
1558
+ if (this.globalRejectionHandler) {
1559
+ window.removeEventListener('unhandledrejection', this.globalRejectionHandler, true);
1560
+ this.globalRejectionHandler = null;
1561
+ }
1562
+ }
1563
+ /**
1564
+ * 上传截图到 S3
1565
+ */
1566
+ async uploadScreenshot(dataUrl, config) {
1567
+ try {
1568
+ if (!this.options.silentMode) {
1569
+ console.log('📸 [上传] 开始上传截图...');
1570
+ }
1571
+ const blob = this.dataUrlToBlob(dataUrl, config.contentType);
1572
+ const response = await fetch(config.uploadUrl, {
1573
+ method: 'PUT',
1574
+ body: blob,
1575
+ headers: {
1576
+ 'Content-Type': config.contentType
1577
+ }
1578
+ });
1579
+ if (response.status === 200) {
1580
+ if (!this.options.silentMode) {
1581
+ console.log('📸 [上传] ✅ 上传成功');
1582
+ }
1583
+ this.uploadProgress.success++;
1584
+ return true;
1585
+ }
1586
+ else {
1587
+ const errorText = await response.text().catch(() => '');
1588
+ const errorMsg = `上传失败: HTTP ${response.status} ${response.statusText}${errorText ? ` - ${errorText.substring(0, 200)}` : ''}`;
1589
+ console.error('📸 [上传] ❌', errorMsg);
1590
+ this.uploadError = errorMsg;
1591
+ this.uploadProgress.failed++;
1592
+ return false;
1593
+ }
1594
+ }
1595
+ catch (error) {
1596
+ const errorMsg = error instanceof Error ? error.message : String(error);
1597
+ console.error('📸 [上传] ❌ 上传异常:', errorMsg);
1598
+ this.uploadError = `上传异常: ${errorMsg}`;
1599
+ this.uploadProgress.failed++;
1600
+ return false;
1601
+ }
1602
+ }
1603
+ /**
1604
+ * 将 base64 data URL 转换为 Blob
1605
+ */
1606
+ dataUrlToBlob(dataUrl, contentType) {
1607
+ const arr = dataUrl.split(',');
1608
+ const mimeMatch = arr[0].match(/:(.*?);/);
1609
+ const mime = mimeMatch ? mimeMatch[1] : contentType;
1610
+ const bstr = atob(arr[1]);
1611
+ let n = bstr.length;
1612
+ const u8arr = new Uint8Array(n);
1613
+ while (n--) {
1614
+ u8arr[n] = bstr.charCodeAt(n);
1615
+ }
1616
+ return new Blob([u8arr], { type: mime });
1617
+ }
1618
+ /**
1619
+ * 获取最新截图
1620
+ */
1621
+ getLatestScreenshot() {
1622
+ return this.screenshotHistory[this.screenshotHistory.length - 1] || null;
1623
+ }
1624
+ /**
1625
+ * 启用/禁用截图功能
1626
+ */
1627
+ enable(enabled) {
1628
+ this.isEnabled = enabled;
1629
+ if (!enabled && this.isRunning) {
1630
+ this.stopScreenshot();
1631
+ }
1632
+ }
1633
+ /**
1634
+ * 清理资源
1635
+ */
1636
+ destroy() {
1637
+ this.stopScreenshot();
1638
+ if (this.worker) {
1639
+ this.worker.terminate();
1640
+ this.worker = null;
1641
+ }
1642
+ if (this.expirationTimer) {
1643
+ clearTimeout(this.expirationTimer);
1644
+ this.expirationTimer = null;
1645
+ }
1646
+ if (this.messageHandler) {
1647
+ window.removeEventListener('message', this.messageHandler);
1648
+ this.messageHandler = null;
1649
+ }
1650
+ this.removeGlobalErrorHandlers();
1651
+ }
1652
+ /**
1653
+ * 获取状态
1654
+ */
1655
+ getState() {
1656
+ return {
1657
+ isRunning: this.isRunning,
1658
+ screenshotCount: this.screenshotCount,
1659
+ lastScreenshotTime: this.lastScreenshotTime,
1660
+ error: this.error,
1661
+ isEnabled: this.isEnabled,
1662
+ isUploading: this.isUploading,
1663
+ uploadError: this.uploadError,
1664
+ uploadProgress: { ...this.uploadProgress },
1665
+ currentUploadConfig: this.currentUploadConfig
1666
+ };
1667
+ }
1668
+ }
1669
+
874
1670
  /******************************************************************************
875
1671
  Copyright (c) Microsoft Corporation.
876
1672
 
@@ -4145,6 +4941,7 @@ class CustomerServiceSDK {
4145
4941
  constructor() {
4146
4942
  this.iconManager = null;
4147
4943
  this.iframeManager = null;
4944
+ this.screenshotManager = null;
4148
4945
  this.config = null;
4149
4946
  this.isInitialized = false;
4150
4947
  }
@@ -4165,8 +4962,9 @@ class CustomerServiceSDK {
4165
4962
  console.log('Device ID:', deviceId);
4166
4963
  // 构建iframe URL(带参数)
4167
4964
  const iframeUrl = this.buildIframeUrl(config, deviceId);
4168
- // 创建悬浮图标管理器(IconManager现在是写死的)
4169
- this.iconManager = new IconManager();
4965
+ // 创建悬浮图标管理器(支持自定义位置)
4966
+ const iconPosition = options?.iconPosition || undefined;
4967
+ this.iconManager = new IconManager(iconPosition);
4170
4968
  await this.iconManager.show();
4171
4969
  // 创建iframe管理器(自动检测设备类型)
4172
4970
  this.iframeManager = new IframeManager({
@@ -4175,12 +4973,13 @@ class CustomerServiceSDK {
4175
4973
  width: 400,
4176
4974
  height: 600,
4177
4975
  allowClose: true,
4178
- onMessage: (messageType, data) => {
4976
+ onMessage: (messageType, _data) => {
4179
4977
  // 处理来自iframe的消息
4180
4978
  if (messageType === 'new-message') {
4181
4979
  // 显示红点通知(只显示红点,不显示数字)
4182
4980
  this.showNotification(0, { pulse: true });
4183
4981
  }
4982
+ // checkScreenshot 消息由 ScreenshotManager 处理,不需要在这里处理
4184
4983
  },
4185
4984
  onClose: () => {
4186
4985
  // iframe关闭时,清理图标拖动事件监听器
@@ -4196,6 +4995,13 @@ class CustomerServiceSDK {
4196
4995
  this.clearNotification();
4197
4996
  this.iframeManager?.show();
4198
4997
  });
4998
+ // 初始化截图管理器(如果启用了截图功能)
4999
+ if (config.screenshot) {
5000
+ // 默认截图目标为 document.body,可以通过配置自定义
5001
+ const targetElement = document.body;
5002
+ this.screenshotManager = new ScreenshotManager(targetElement, config.screenshot);
5003
+ console.log('CustomerSDK screenshot manager initialized');
5004
+ }
4199
5005
  this.isInitialized = true;
4200
5006
  console.log('CustomerSDK initialized successfully (iframe pre-connected to SSE)');
4201
5007
  }
@@ -4219,6 +5025,12 @@ class CustomerServiceSDK {
4219
5025
  setIconPosition(position) {
4220
5026
  this.iconManager?.setPosition(position);
4221
5027
  }
5028
+ /**
5029
+ * 设置图标坐标位置(x, y)
5030
+ */
5031
+ setIconCoordinates(position) {
5032
+ this.iconManager?.setIconPosition(position);
5033
+ }
4222
5034
  /**
4223
5035
  * 更新图标样式
4224
5036
  */
@@ -4283,14 +5095,38 @@ class CustomerServiceSDK {
4283
5095
  clearNotification() {
4284
5096
  this.iconManager?.clearNotification();
4285
5097
  }
5098
+ /**
5099
+ * 设置截图目标元素
5100
+ */
5101
+ setScreenshotTarget(element) {
5102
+ this.screenshotManager?.setTargetElement(element);
5103
+ }
5104
+ /**
5105
+ * 手动触发截图
5106
+ */
5107
+ async captureScreenshot() {
5108
+ if (!this.screenshotManager) {
5109
+ console.warn('截图功能未启用');
5110
+ return false;
5111
+ }
5112
+ return await this.screenshotManager.captureOnce();
5113
+ }
5114
+ /**
5115
+ * 获取截图状态
5116
+ */
5117
+ getScreenshotState() {
5118
+ return this.screenshotManager?.getState() || null;
5119
+ }
4286
5120
  /**
4287
5121
  * 销毁 SDK
4288
5122
  */
4289
5123
  destroy() {
4290
5124
  this.iconManager?.hide();
4291
5125
  this.iframeManager?.close();
5126
+ this.screenshotManager?.destroy();
4292
5127
  this.iconManager = null;
4293
5128
  this.iframeManager = null;
5129
+ this.screenshotManager = null;
4294
5130
  this.config = null;
4295
5131
  this.isInitialized = false;
4296
5132
  console.log('CustomerSDK destroyed');
@@ -4370,6 +5206,10 @@ const setIconPosition = (position) => {
4370
5206
  const sdk = getInstance();
4371
5207
  sdk.setIconPosition(position);
4372
5208
  };
5209
+ const setIconCoordinates = (position) => {
5210
+ const sdk = getInstance();
5211
+ sdk.setIconCoordinates(position);
5212
+ };
4373
5213
  const setIconStyle = (style) => {
4374
5214
  const sdk = getInstance();
4375
5215
  sdk.setIconStyle(style);
@@ -4419,6 +5259,21 @@ const destroy = () => {
4419
5259
  sdk.destroy();
4420
5260
  globalSDKInstance = null;
4421
5261
  };
5262
+ /**
5263
+ * 截图相关API
5264
+ */
5265
+ const setScreenshotTarget = (element) => {
5266
+ const sdk = getInstance();
5267
+ sdk.setScreenshotTarget(element);
5268
+ };
5269
+ const captureScreenshot = async () => {
5270
+ const sdk = getInstance();
5271
+ return await sdk.captureScreenshot();
5272
+ };
5273
+ const getScreenshotState = () => {
5274
+ const sdk = getInstance();
5275
+ return sdk.getScreenshotState();
5276
+ };
4422
5277
  // 默认导出
4423
5278
  var index = {
4424
5279
  init,
@@ -4426,6 +5281,7 @@ var index = {
4426
5281
  showIcon,
4427
5282
  hideIcon,
4428
5283
  setIconPosition,
5284
+ setIconCoordinates,
4429
5285
  setIconStyle,
4430
5286
  openChat,
4431
5287
  closeChat,
@@ -4434,22 +5290,29 @@ var index = {
4434
5290
  getConnectionStatus,
4435
5291
  showNotification,
4436
5292
  clearNotification,
5293
+ setScreenshotTarget,
5294
+ captureScreenshot,
5295
+ getScreenshotState,
4437
5296
  destroy
4438
5297
  };
4439
5298
 
4440
5299
  exports.CustomerServiceSDK = CustomerServiceSDK;
5300
+ exports.captureScreenshot = captureScreenshot;
4441
5301
  exports.clearNotification = clearNotification;
4442
5302
  exports.closeChat = closeChat;
4443
5303
  exports.default = index;
4444
5304
  exports.destroy = destroy;
4445
5305
  exports.getConnectionStatus = getConnectionStatus;
4446
5306
  exports.getInstance = getInstance;
5307
+ exports.getScreenshotState = getScreenshotState;
4447
5308
  exports.hideIcon = hideIcon;
4448
5309
  exports.init = init;
4449
5310
  exports.isChatOpen = isChatOpen;
4450
5311
  exports.openChat = openChat;
4451
5312
  exports.sendToIframe = sendToIframe;
5313
+ exports.setIconCoordinates = setIconCoordinates;
4452
5314
  exports.setIconPosition = setIconPosition;
4453
5315
  exports.setIconStyle = setIconStyle;
5316
+ exports.setScreenshotTarget = setScreenshotTarget;
4454
5317
  exports.showIcon = showIcon;
4455
5318
  exports.showNotification = showNotification;