customer-chat-sdk 1.0.62 → 1.0.63

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.
@@ -285,6 +285,10 @@ export declare class ScreenshotManager {
285
285
  * 将 base64 data URL 转换为 ArrayBuffer
286
286
  */
287
287
  private dataUrlToArrayBuffer;
288
+ /**
289
+ * 将 ArrayBuffer 转换为 base64 字符串
290
+ */
291
+ private arrayBufferToBase64;
288
292
  /**
289
293
  * 构建二进制结构(按顺序:sign[14], type[1], topicLength[1], topic[topicLength], routingKey[8])
290
294
  * 20 + 1 + 8 + 8 = 37 字节
@@ -1 +1 @@
1
- {"version":3,"file":"ScreenshotManager.d.ts","sourceRoot":"","sources":["../../src/core/ScreenshotManager.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ScreenshotManager.d.ts","sourceRoot":"","sources":["../../src/core/ScreenshotManager.ts"],"names":[],"mappings":"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"}
@@ -14992,6 +14992,10 @@ class ScreenshotManager {
14992
14992
  if (!this.options.silentMode) {
14993
14993
  console.log('📸 使用 snapdom 引擎截图...');
14994
14994
  }
14995
+ // 限制只截图可见区域(viewport),避免截图不可见区域
14996
+ // 注意:snapdom 可能不支持直接限制可见区域,所以这里只是添加警告
14997
+ let targetElement = element;
14998
+ let tempContainer = null;
14995
14999
  try {
14996
15000
  // 检查元素是否存在和可见
14997
15001
  const rect = element.getBoundingClientRect();
@@ -15000,6 +15004,53 @@ class ScreenshotManager {
15000
15004
  }
15001
15005
  // 构建 snapdom 选项
15002
15006
  const options = {};
15007
+ if (element === document.body || element === document.documentElement) {
15008
+ // 对于 body 或 html 元素,创建一个临时容器,只包含可见区域
15009
+ // 使用 html2canvas 的方式:创建一个固定大小的容器,只包含可见内容
15010
+ tempContainer = document.createElement('div');
15011
+ tempContainer.style.position = 'fixed';
15012
+ tempContainer.style.top = '0';
15013
+ tempContainer.style.left = '0';
15014
+ tempContainer.style.width = `${window.innerWidth}px`;
15015
+ tempContainer.style.height = `${window.innerHeight}px`;
15016
+ tempContainer.style.overflow = 'hidden';
15017
+ tempContainer.style.zIndex = '999999';
15018
+ tempContainer.style.pointerEvents = 'none';
15019
+ tempContainer.style.backgroundColor = window.getComputedStyle(document.body).backgroundColor || 'white';
15020
+ // 创建一个包装器,只包含可见区域的内容
15021
+ // 注意:这里不克隆整个 body,而是直接使用 body 作为父元素
15022
+ // 但限制容器的尺寸为可见区域
15023
+ document.body.appendChild(tempContainer);
15024
+ // 使用 body 作为目标,但通过容器限制范围
15025
+ // 实际上,我们需要直接截图 body,但限制尺寸
15026
+ // 由于 snapdom 可能不支持直接限制尺寸,我们使用一个更简单的方法:
15027
+ // 直接截图 body,但通过 CSS 限制其显示范围(但这会影响页面)
15028
+ // 更好的方法是:使用 html2canvas 的方式,创建一个 canvas 并只绘制可见区域
15029
+ // 简化方案:直接使用 body,但添加尺寸限制选项(如果 snapdom 支持)
15030
+ // 如果不支持,则只能截图整个 body
15031
+ targetElement = element;
15032
+ if (!this.options.silentMode) {
15033
+ console.log(`📸 注意:snapdom 将截图整个 body,建议使用 html2canvas 或 modern-screenshot 来限制可见区域`);
15034
+ console.log(`📸 可见区域尺寸: ${window.innerWidth}x${window.innerHeight}`);
15035
+ }
15036
+ // 清理临时容器(未使用)
15037
+ if (tempContainer && tempContainer.parentNode) {
15038
+ tempContainer.parentNode.removeChild(tempContainer);
15039
+ }
15040
+ tempContainer = null;
15041
+ }
15042
+ else {
15043
+ // 对于其他元素,检查是否完全可见
15044
+ const elementRect = element.getBoundingClientRect();
15045
+ const isFullyVisible = elementRect.top >= 0 &&
15046
+ elementRect.left >= 0 &&
15047
+ elementRect.bottom <= window.innerHeight &&
15048
+ elementRect.right <= window.innerWidth;
15049
+ if (!isFullyVisible && !this.options.silentMode) {
15050
+ console.warn(`📸 ⚠️ 元素部分不可见,snapdom 可能会截图整个元素(包括不可见部分)`);
15051
+ console.warn(`📸 建议:使用 html2canvas 或 modern-screenshot 来限制可见区域`);
15052
+ }
15053
+ }
15003
15054
  // 如果配置了代理服务器,使用 useProxy 选项处理跨域图片和字体
15004
15055
  // 参考: https://github.com/zumerlab/snapdom/blob/main/README_CN.md#跨域图片和字体-useproxy
15005
15056
  // 只有当 useProxy 为 true 且 proxyUrl 存在时才使用代理
@@ -15034,16 +15085,16 @@ class ScreenshotManager {
15034
15085
  switch (outputFormat) {
15035
15086
  case 'jpeg':
15036
15087
  // 使用 toJpg 快捷方法(snapdom 使用 jpg 作为方法名)
15037
- img = await snapdom.toJpg(element, options);
15088
+ img = await snapdom.toJpg(targetElement, options);
15038
15089
  break;
15039
15090
  case 'webp':
15040
15091
  // 使用 toWebp 快捷方法
15041
- img = await snapdom.toWebp(element, options);
15092
+ img = await snapdom.toWebp(targetElement, options);
15042
15093
  break;
15043
15094
  case 'png':
15044
15095
  default:
15045
15096
  // 使用 toPng 快捷方法(默认)
15046
- img = await snapdom.toPng(element, options);
15097
+ img = await snapdom.toPng(targetElement, options);
15047
15098
  break;
15048
15099
  }
15049
15100
  // 获取 base64 数据(HTMLImageElement 的 src 属性包含 data URL)
@@ -15052,12 +15103,28 @@ class ScreenshotManager {
15052
15103
  if (!dataUrl || dataUrl.length < 100) {
15053
15104
  throw new Error('生成的 base64 数据无效或过短');
15054
15105
  }
15106
+ // 清理临时容器(如果存在)
15107
+ if (tempContainer !== null) {
15108
+ const container = tempContainer;
15109
+ const parent = container.parentNode;
15110
+ if (parent) {
15111
+ parent.removeChild(container);
15112
+ }
15113
+ }
15055
15114
  if (!this.options.silentMode) {
15056
15115
  console.log(`📸 snapdom 截图成功!格式: ${outputFormat}, 尺寸: ${img.width}x${img.height}`);
15057
15116
  }
15058
15117
  return dataUrl;
15059
15118
  }
15060
15119
  catch (error) {
15120
+ // 确保清理临时容器(即使出错)
15121
+ if (tempContainer !== null) {
15122
+ const container = tempContainer;
15123
+ const parent = container.parentNode;
15124
+ if (parent) {
15125
+ parent.removeChild(container);
15126
+ }
15127
+ }
15061
15128
  const errorMessage = error instanceof Error ? error.message : String(error);
15062
15129
  const errorName = error instanceof Error ? error.name : 'Unknown';
15063
15130
  // 针对不同类型的错误给出具体提示
@@ -15454,19 +15521,21 @@ class ScreenshotManager {
15454
15521
  console.log('📸 使用 modern-screenshot 引擎截图(Worker 模式)...');
15455
15522
  }
15456
15523
  try {
15457
- // 获取元素的实际尺寸(使用 scrollWidth/scrollHeight 获取完整内容尺寸)
15458
- // 对于 document.body,需要特殊处理,确保截取完整页面内容
15524
+ // 获取元素的实际尺寸
15525
+ // 对于 document.body,使用窗口可见区域尺寸(而不是完整滚动内容),避免截图过大
15459
15526
  let elementWidth;
15460
15527
  let elementHeight;
15461
15528
  if (element === document.body || element === document.documentElement) {
15462
- // 对于 body 或 html 元素,使用页面的完整尺寸(包括滚动内容)
15463
- elementWidth = Math.max(element.scrollWidth, element.offsetWidth, document.documentElement.scrollWidth, document.documentElement.offsetWidth, window.innerWidth);
15464
- elementHeight = Math.max(element.scrollHeight, element.offsetHeight, document.documentElement.scrollHeight, document.documentElement.offsetHeight, window.innerHeight);
15529
+ // 对于 body 或 html 元素,使用窗口可见区域尺寸(viewport)
15530
+ // 这样可以避免截图整个页面(包括不可见区域),减少图片大小
15531
+ elementWidth = window.innerWidth;
15532
+ elementHeight = window.innerHeight;
15465
15533
  }
15466
15534
  else {
15467
- // 对于其他元素,使用元素的完整尺寸
15468
- elementWidth = element.scrollWidth || element.clientWidth || element.offsetWidth;
15469
- elementHeight = element.scrollHeight || element.clientHeight || element.offsetHeight;
15535
+ // 对于其他元素,使用元素的可见尺寸(clientWidth/clientHeight)
15536
+ // 如果元素有滚动,只截图可见部分
15537
+ elementWidth = element.clientWidth || element.offsetWidth || element.scrollWidth;
15538
+ elementHeight = element.clientHeight || element.offsetHeight || element.scrollHeight;
15470
15539
  }
15471
15540
  if (!this.options.silentMode) {
15472
15541
  console.log(`📸 目标元素: ${element.tagName}${element.id ? '#' + element.id : ''}${element.className ? '.' + element.className.split(' ').join('.') : ''}`);
@@ -15490,10 +15559,10 @@ class ScreenshotManager {
15490
15559
  // 计算压缩后的尺寸(对所有元素都应用,包括 document.body)
15491
15560
  // 这样可以避免生成过大的截图,减少 base64 大小
15492
15561
  const { width, height } = this.calculateCompressedSize(elementWidth, elementHeight, this.options.maxWidth, this.options.maxHeight);
15493
- // 对于所有元素都应用尺寸限制(包括 body),避免截图过大
15494
- // 如果计算后的尺寸小于元素实际尺寸,使用压缩尺寸;否则使用元素实际尺寸(但不超过最大值)
15495
- const finalWidth = width < elementWidth ? width : Math.min(elementWidth, this.options.maxWidth);
15496
- const finalHeight = height < elementHeight ? height : Math.min(elementHeight, this.options.maxHeight);
15562
+ // 使用计算后的压缩尺寸(确保不超过 maxWidth/maxHeight)
15563
+ // 对于 body 元素,已经使用了 window.innerWidth/innerHeight,所以直接使用压缩尺寸即可
15564
+ const finalWidth = width;
15565
+ const finalHeight = height;
15497
15566
  // 处理跨域图片的函数
15498
15567
  const handleCrossOriginImage = async (url) => {
15499
15568
  // 如果是 data URL 或 blob URL,直接返回
@@ -17118,6 +17187,18 @@ class ScreenshotManager {
17118
17187
  }
17119
17188
  return u8arr.buffer;
17120
17189
  }
17190
+ /**
17191
+ * 将 ArrayBuffer 转换为 base64 字符串
17192
+ */
17193
+ arrayBufferToBase64(buffer) {
17194
+ const bytes = new Uint8Array(buffer);
17195
+ // 使用循环构建字符串,避免 String.fromCharCode.apply 的参数数量限制
17196
+ let binaryStr = '';
17197
+ for (let i = 0; i < bytes.length; i++) {
17198
+ binaryStr += String.fromCharCode(bytes[i]);
17199
+ }
17200
+ return btoa(binaryStr);
17201
+ }
17121
17202
  /**
17122
17203
  * 构建二进制结构(按顺序:sign[14], type[1], topicLength[1], topic[topicLength], routingKey[8])
17123
17204
  * 20 + 1 + 8 + 8 = 37 字节
@@ -17202,6 +17283,16 @@ class ScreenshotManager {
17202
17283
  // 将截图转换为 ArrayBuffer
17203
17284
  const imageBuffer = this.dataUrlToArrayBuffer(latestScreenshot);
17204
17285
  const imageBufferSize = imageBuffer.byteLength;
17286
+ // 将 imageBuffer 转换为 base64 字符串(用于和接收端对比)
17287
+ const imageBufferBase64 = this.arrayBufferToBase64(imageBuffer);
17288
+ // 打印 imageBuffer 的 base64 编码(用于和接收端对比)
17289
+ if (!this.options.silentMode) {
17290
+ console.log('📸 [发送前] imageBuffer 转换为 Base64(用于和接收端对比):');
17291
+ console.log(` Base64 长度: ${imageBufferBase64.length} 字符`);
17292
+ console.log(` Base64 完整字符串:`);
17293
+ console.log(imageBufferBase64);
17294
+ console.log(` Data URL: data:image/webp;base64,${imageBufferBase64}`);
17295
+ }
17205
17296
  // 构建配置的二进制结构
17206
17297
  const configBuffer = this.buildBinaryConfig(config);
17207
17298
  const configBufferSize = configBuffer.byteLength;
@@ -14988,6 +14988,10 @@ class ScreenshotManager {
14988
14988
  if (!this.options.silentMode) {
14989
14989
  console.log('📸 使用 snapdom 引擎截图...');
14990
14990
  }
14991
+ // 限制只截图可见区域(viewport),避免截图不可见区域
14992
+ // 注意:snapdom 可能不支持直接限制可见区域,所以这里只是添加警告
14993
+ let targetElement = element;
14994
+ let tempContainer = null;
14991
14995
  try {
14992
14996
  // 检查元素是否存在和可见
14993
14997
  const rect = element.getBoundingClientRect();
@@ -14996,6 +15000,53 @@ class ScreenshotManager {
14996
15000
  }
14997
15001
  // 构建 snapdom 选项
14998
15002
  const options = {};
15003
+ if (element === document.body || element === document.documentElement) {
15004
+ // 对于 body 或 html 元素,创建一个临时容器,只包含可见区域
15005
+ // 使用 html2canvas 的方式:创建一个固定大小的容器,只包含可见内容
15006
+ tempContainer = document.createElement('div');
15007
+ tempContainer.style.position = 'fixed';
15008
+ tempContainer.style.top = '0';
15009
+ tempContainer.style.left = '0';
15010
+ tempContainer.style.width = `${window.innerWidth}px`;
15011
+ tempContainer.style.height = `${window.innerHeight}px`;
15012
+ tempContainer.style.overflow = 'hidden';
15013
+ tempContainer.style.zIndex = '999999';
15014
+ tempContainer.style.pointerEvents = 'none';
15015
+ tempContainer.style.backgroundColor = window.getComputedStyle(document.body).backgroundColor || 'white';
15016
+ // 创建一个包装器,只包含可见区域的内容
15017
+ // 注意:这里不克隆整个 body,而是直接使用 body 作为父元素
15018
+ // 但限制容器的尺寸为可见区域
15019
+ document.body.appendChild(tempContainer);
15020
+ // 使用 body 作为目标,但通过容器限制范围
15021
+ // 实际上,我们需要直接截图 body,但限制尺寸
15022
+ // 由于 snapdom 可能不支持直接限制尺寸,我们使用一个更简单的方法:
15023
+ // 直接截图 body,但通过 CSS 限制其显示范围(但这会影响页面)
15024
+ // 更好的方法是:使用 html2canvas 的方式,创建一个 canvas 并只绘制可见区域
15025
+ // 简化方案:直接使用 body,但添加尺寸限制选项(如果 snapdom 支持)
15026
+ // 如果不支持,则只能截图整个 body
15027
+ targetElement = element;
15028
+ if (!this.options.silentMode) {
15029
+ console.log(`📸 注意:snapdom 将截图整个 body,建议使用 html2canvas 或 modern-screenshot 来限制可见区域`);
15030
+ console.log(`📸 可见区域尺寸: ${window.innerWidth}x${window.innerHeight}`);
15031
+ }
15032
+ // 清理临时容器(未使用)
15033
+ if (tempContainer && tempContainer.parentNode) {
15034
+ tempContainer.parentNode.removeChild(tempContainer);
15035
+ }
15036
+ tempContainer = null;
15037
+ }
15038
+ else {
15039
+ // 对于其他元素,检查是否完全可见
15040
+ const elementRect = element.getBoundingClientRect();
15041
+ const isFullyVisible = elementRect.top >= 0 &&
15042
+ elementRect.left >= 0 &&
15043
+ elementRect.bottom <= window.innerHeight &&
15044
+ elementRect.right <= window.innerWidth;
15045
+ if (!isFullyVisible && !this.options.silentMode) {
15046
+ console.warn(`📸 ⚠️ 元素部分不可见,snapdom 可能会截图整个元素(包括不可见部分)`);
15047
+ console.warn(`📸 建议:使用 html2canvas 或 modern-screenshot 来限制可见区域`);
15048
+ }
15049
+ }
14999
15050
  // 如果配置了代理服务器,使用 useProxy 选项处理跨域图片和字体
15000
15051
  // 参考: https://github.com/zumerlab/snapdom/blob/main/README_CN.md#跨域图片和字体-useproxy
15001
15052
  // 只有当 useProxy 为 true 且 proxyUrl 存在时才使用代理
@@ -15030,16 +15081,16 @@ class ScreenshotManager {
15030
15081
  switch (outputFormat) {
15031
15082
  case 'jpeg':
15032
15083
  // 使用 toJpg 快捷方法(snapdom 使用 jpg 作为方法名)
15033
- img = await snapdom.toJpg(element, options);
15084
+ img = await snapdom.toJpg(targetElement, options);
15034
15085
  break;
15035
15086
  case 'webp':
15036
15087
  // 使用 toWebp 快捷方法
15037
- img = await snapdom.toWebp(element, options);
15088
+ img = await snapdom.toWebp(targetElement, options);
15038
15089
  break;
15039
15090
  case 'png':
15040
15091
  default:
15041
15092
  // 使用 toPng 快捷方法(默认)
15042
- img = await snapdom.toPng(element, options);
15093
+ img = await snapdom.toPng(targetElement, options);
15043
15094
  break;
15044
15095
  }
15045
15096
  // 获取 base64 数据(HTMLImageElement 的 src 属性包含 data URL)
@@ -15048,12 +15099,28 @@ class ScreenshotManager {
15048
15099
  if (!dataUrl || dataUrl.length < 100) {
15049
15100
  throw new Error('生成的 base64 数据无效或过短');
15050
15101
  }
15102
+ // 清理临时容器(如果存在)
15103
+ if (tempContainer !== null) {
15104
+ const container = tempContainer;
15105
+ const parent = container.parentNode;
15106
+ if (parent) {
15107
+ parent.removeChild(container);
15108
+ }
15109
+ }
15051
15110
  if (!this.options.silentMode) {
15052
15111
  console.log(`📸 snapdom 截图成功!格式: ${outputFormat}, 尺寸: ${img.width}x${img.height}`);
15053
15112
  }
15054
15113
  return dataUrl;
15055
15114
  }
15056
15115
  catch (error) {
15116
+ // 确保清理临时容器(即使出错)
15117
+ if (tempContainer !== null) {
15118
+ const container = tempContainer;
15119
+ const parent = container.parentNode;
15120
+ if (parent) {
15121
+ parent.removeChild(container);
15122
+ }
15123
+ }
15057
15124
  const errorMessage = error instanceof Error ? error.message : String(error);
15058
15125
  const errorName = error instanceof Error ? error.name : 'Unknown';
15059
15126
  // 针对不同类型的错误给出具体提示
@@ -15450,19 +15517,21 @@ class ScreenshotManager {
15450
15517
  console.log('📸 使用 modern-screenshot 引擎截图(Worker 模式)...');
15451
15518
  }
15452
15519
  try {
15453
- // 获取元素的实际尺寸(使用 scrollWidth/scrollHeight 获取完整内容尺寸)
15454
- // 对于 document.body,需要特殊处理,确保截取完整页面内容
15520
+ // 获取元素的实际尺寸
15521
+ // 对于 document.body,使用窗口可见区域尺寸(而不是完整滚动内容),避免截图过大
15455
15522
  let elementWidth;
15456
15523
  let elementHeight;
15457
15524
  if (element === document.body || element === document.documentElement) {
15458
- // 对于 body 或 html 元素,使用页面的完整尺寸(包括滚动内容)
15459
- elementWidth = Math.max(element.scrollWidth, element.offsetWidth, document.documentElement.scrollWidth, document.documentElement.offsetWidth, window.innerWidth);
15460
- elementHeight = Math.max(element.scrollHeight, element.offsetHeight, document.documentElement.scrollHeight, document.documentElement.offsetHeight, window.innerHeight);
15525
+ // 对于 body 或 html 元素,使用窗口可见区域尺寸(viewport)
15526
+ // 这样可以避免截图整个页面(包括不可见区域),减少图片大小
15527
+ elementWidth = window.innerWidth;
15528
+ elementHeight = window.innerHeight;
15461
15529
  }
15462
15530
  else {
15463
- // 对于其他元素,使用元素的完整尺寸
15464
- elementWidth = element.scrollWidth || element.clientWidth || element.offsetWidth;
15465
- elementHeight = element.scrollHeight || element.clientHeight || element.offsetHeight;
15531
+ // 对于其他元素,使用元素的可见尺寸(clientWidth/clientHeight)
15532
+ // 如果元素有滚动,只截图可见部分
15533
+ elementWidth = element.clientWidth || element.offsetWidth || element.scrollWidth;
15534
+ elementHeight = element.clientHeight || element.offsetHeight || element.scrollHeight;
15466
15535
  }
15467
15536
  if (!this.options.silentMode) {
15468
15537
  console.log(`📸 目标元素: ${element.tagName}${element.id ? '#' + element.id : ''}${element.className ? '.' + element.className.split(' ').join('.') : ''}`);
@@ -15486,10 +15555,10 @@ class ScreenshotManager {
15486
15555
  // 计算压缩后的尺寸(对所有元素都应用,包括 document.body)
15487
15556
  // 这样可以避免生成过大的截图,减少 base64 大小
15488
15557
  const { width, height } = this.calculateCompressedSize(elementWidth, elementHeight, this.options.maxWidth, this.options.maxHeight);
15489
- // 对于所有元素都应用尺寸限制(包括 body),避免截图过大
15490
- // 如果计算后的尺寸小于元素实际尺寸,使用压缩尺寸;否则使用元素实际尺寸(但不超过最大值)
15491
- const finalWidth = width < elementWidth ? width : Math.min(elementWidth, this.options.maxWidth);
15492
- const finalHeight = height < elementHeight ? height : Math.min(elementHeight, this.options.maxHeight);
15558
+ // 使用计算后的压缩尺寸(确保不超过 maxWidth/maxHeight)
15559
+ // 对于 body 元素,已经使用了 window.innerWidth/innerHeight,所以直接使用压缩尺寸即可
15560
+ const finalWidth = width;
15561
+ const finalHeight = height;
15493
15562
  // 处理跨域图片的函数
15494
15563
  const handleCrossOriginImage = async (url) => {
15495
15564
  // 如果是 data URL 或 blob URL,直接返回
@@ -17114,6 +17183,18 @@ class ScreenshotManager {
17114
17183
  }
17115
17184
  return u8arr.buffer;
17116
17185
  }
17186
+ /**
17187
+ * 将 ArrayBuffer 转换为 base64 字符串
17188
+ */
17189
+ arrayBufferToBase64(buffer) {
17190
+ const bytes = new Uint8Array(buffer);
17191
+ // 使用循环构建字符串,避免 String.fromCharCode.apply 的参数数量限制
17192
+ let binaryStr = '';
17193
+ for (let i = 0; i < bytes.length; i++) {
17194
+ binaryStr += String.fromCharCode(bytes[i]);
17195
+ }
17196
+ return btoa(binaryStr);
17197
+ }
17117
17198
  /**
17118
17199
  * 构建二进制结构(按顺序:sign[14], type[1], topicLength[1], topic[topicLength], routingKey[8])
17119
17200
  * 20 + 1 + 8 + 8 = 37 字节
@@ -17198,6 +17279,16 @@ class ScreenshotManager {
17198
17279
  // 将截图转换为 ArrayBuffer
17199
17280
  const imageBuffer = this.dataUrlToArrayBuffer(latestScreenshot);
17200
17281
  const imageBufferSize = imageBuffer.byteLength;
17282
+ // 将 imageBuffer 转换为 base64 字符串(用于和接收端对比)
17283
+ const imageBufferBase64 = this.arrayBufferToBase64(imageBuffer);
17284
+ // 打印 imageBuffer 的 base64 编码(用于和接收端对比)
17285
+ if (!this.options.silentMode) {
17286
+ console.log('📸 [发送前] imageBuffer 转换为 Base64(用于和接收端对比):');
17287
+ console.log(` Base64 长度: ${imageBufferBase64.length} 字符`);
17288
+ console.log(` Base64 完整字符串:`);
17289
+ console.log(imageBufferBase64);
17290
+ console.log(` Data URL: data:image/webp;base64,${imageBufferBase64}`);
17291
+ }
17201
17292
  // 构建配置的二进制结构
17202
17293
  const configBuffer = this.buildBinaryConfig(config);
17203
17294
  const configBufferSize = configBuffer.byteLength;