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