customer-chat-sdk 1.0.34 → 1.0.35

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.
@@ -13,7 +13,7 @@ export interface ScreenshotOptions {
13
13
  enableCORS?: boolean;
14
14
  proxyUrl?: string;
15
15
  useProxy?: boolean;
16
- engine?: 'modern-screenshot' | 'snapdom';
16
+ engine?: 'modern-screenshot' | 'snapdom' | 'html2canvas';
17
17
  corsMode?: 'simple' | 'smart' | 'proxy' | 'blob' | 'canvas-proxy' | 'ignore' | 'test-first';
18
18
  silentMode?: boolean;
19
19
  maxRetries?: number;
@@ -125,8 +125,41 @@ export declare class ScreenshotManager {
125
125
  * 注意:snapdom 内部使用 worker 进行截图处理,会在后台线程执行,不会阻塞主线程
126
126
  */
127
127
  private takeScreenshotWithSnapdom;
128
+ /**
129
+ * 使用 html2canvas 截图
130
+ *
131
+ * 优势:
132
+ * - 处理 SVG 和本地资源更快(不需要复杂的 Worker 通信)
133
+ * - 兼容性好,支持更多 CSS 特性
134
+ * - 跨域处理相对简单
135
+ *
136
+ * 劣势:
137
+ * - 在主线程执行,可能阻塞 UI(但处理速度快,影响较小)
138
+ * - 不支持 Worker 模式
139
+ *
140
+ * 适用场景:
141
+ * - 页面包含大量 SVG 图标
142
+ * - 本地资源较多
143
+ * - 需要快速截图
144
+ */
145
+ private takeScreenshotWithHtml2Canvas;
128
146
  /**
129
147
  * 使用 modern-screenshot 截图(启用 Worker)
148
+ *
149
+ * 优势:
150
+ * - 使用 Worker,不阻塞主线程 UI
151
+ * - 支持并发处理
152
+ * - 适合复杂页面
153
+ *
154
+ * 劣势:
155
+ * - 处理 SVG 和本地资源较慢(Worker 通信开销)
156
+ * - 配置相对复杂
157
+ * - 需要处理 Worker URL
158
+ *
159
+ * 适用场景:
160
+ * - 复杂页面,需要不阻塞 UI
161
+ * - 需要高质量截图
162
+ * - 页面资源较少
130
163
  */
131
164
  private takeScreenshotWithModernScreenshot;
132
165
  /**
@@ -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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"}
@@ -2,6 +2,8 @@
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,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';
7
9
  class IconManager {
@@ -6904,6 +6906,9 @@ class ScreenshotManager {
6904
6906
  if (selectedEngine === 'snapdom') {
6905
6907
  dataUrl = await this.takeScreenshotWithSnapdom(this.targetElement);
6906
6908
  }
6909
+ else if (selectedEngine === 'html2canvas') {
6910
+ dataUrl = await this.takeScreenshotWithHtml2Canvas(this.targetElement);
6911
+ }
6907
6912
  else {
6908
6913
  // 默认使用 modern-screenshot
6909
6914
  dataUrl = await this.takeScreenshotWithModernScreenshot(this.targetElement);
@@ -7066,8 +7071,173 @@ class ScreenshotManager {
7066
7071
  throw error;
7067
7072
  }
7068
7073
  }
7074
+ /**
7075
+ * 使用 html2canvas 截图
7076
+ *
7077
+ * 优势:
7078
+ * - 处理 SVG 和本地资源更快(不需要复杂的 Worker 通信)
7079
+ * - 兼容性好,支持更多 CSS 特性
7080
+ * - 跨域处理相对简单
7081
+ *
7082
+ * 劣势:
7083
+ * - 在主线程执行,可能阻塞 UI(但处理速度快,影响较小)
7084
+ * - 不支持 Worker 模式
7085
+ *
7086
+ * 适用场景:
7087
+ * - 页面包含大量 SVG 图标
7088
+ * - 本地资源较多
7089
+ * - 需要快速截图
7090
+ */
7091
+ async takeScreenshotWithHtml2Canvas(element) {
7092
+ if (!this.options.silentMode) {
7093
+ console.log('📸 使用 html2canvas 引擎截图...');
7094
+ }
7095
+ try {
7096
+ // 检查元素是否存在和可见
7097
+ const rect = element.getBoundingClientRect();
7098
+ if (rect.width === 0 || rect.height === 0) {
7099
+ throw new Error('元素尺寸为 0,无法截图');
7100
+ }
7101
+ const isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
7102
+ const isLowEndDevice = navigator.hardwareConcurrency && navigator.hardwareConcurrency <= 4;
7103
+ // 计算压缩后的尺寸
7104
+ let elementWidth = element.scrollWidth || element.clientWidth || element.offsetWidth;
7105
+ let elementHeight = element.scrollHeight || element.clientHeight || element.offsetHeight;
7106
+ if (element === document.body || element === document.documentElement) {
7107
+ elementWidth = Math.max(element.scrollWidth, element.offsetWidth, document.documentElement.scrollWidth, document.documentElement.offsetWidth, window.innerWidth);
7108
+ elementHeight = Math.max(element.scrollHeight, element.offsetHeight, document.documentElement.scrollHeight, document.documentElement.offsetHeight, window.innerHeight);
7109
+ }
7110
+ const { width, height } = this.calculateCompressedSize(elementWidth, elementHeight, this.options.maxWidth, this.options.maxHeight);
7111
+ const finalWidth = width < elementWidth ? width : Math.min(elementWidth, this.options.maxWidth);
7112
+ const finalHeight = height < elementHeight ? height : Math.min(elementHeight, this.options.maxHeight);
7113
+ // html2canvas 质量设置(0-1)
7114
+ const finalQuality = isMobile || isLowEndDevice
7115
+ ? Math.max(this.options.quality * 0.65, 0.2)
7116
+ : this.options.quality;
7117
+ // html2canvas 配置选项
7118
+ const options = {
7119
+ // 基本配置
7120
+ backgroundColor: '#ffffff',
7121
+ scale: this.options.scale !== 1 ? (isMobile ? 0.7 : this.options.scale) : (isMobile ? 0.7 : 1),
7122
+ useCORS: this.options.enableCORS,
7123
+ allowTaint: !this.options.enableCORS, // 如果启用 CORS,不允许 taint
7124
+ logging: !this.options.silentMode,
7125
+ width: finalWidth,
7126
+ height: finalHeight,
7127
+ // 性能优化
7128
+ removeContainer: true, // 截图后移除临时容器
7129
+ imageTimeout: this.options.imageLoadTimeout || 5000,
7130
+ // 忽略某些元素(可选,提升性能)
7131
+ ignoreElements: (element) => {
7132
+ // 忽略隐藏元素
7133
+ const style = window.getComputedStyle(element);
7134
+ if (style.display === 'none' || style.visibility === 'hidden' || style.opacity === '0') {
7135
+ return true;
7136
+ }
7137
+ return false;
7138
+ },
7139
+ };
7140
+ // html2canvas 不支持直接的 proxy 选项,需要通过 onclone 钩子处理图片
7141
+ // 如果配置了代理服务器,在克隆时替换图片 URL
7142
+ if (this.options.useProxy && this.options.proxyUrl && this.options.proxyUrl.trim() !== '') {
7143
+ options.onclone = (clonedDoc) => {
7144
+ // 在克隆的文档中,替换所有跨域图片的 src
7145
+ const images = clonedDoc.querySelectorAll('img');
7146
+ images.forEach((img) => {
7147
+ const originalSrc = img.getAttribute('src');
7148
+ if (!originalSrc)
7149
+ return;
7150
+ // 检查是否是跨域图片
7151
+ try {
7152
+ const imgUrl = new URL(originalSrc, window.location.href);
7153
+ if (imgUrl.origin === window.location.origin) {
7154
+ return; // 同源图片,不需要处理
7155
+ }
7156
+ }
7157
+ catch {
7158
+ // URL 解析失败,可能是相对路径,继续处理
7159
+ }
7160
+ // 检查缓存
7161
+ const cachedDataUrl = this.getCachedImage(originalSrc);
7162
+ if (cachedDataUrl) {
7163
+ img.src = cachedDataUrl;
7164
+ return;
7165
+ }
7166
+ // 对于跨域图片,使用代理 URL
7167
+ // html2canvas 会自动处理,但我们可以预先处理
7168
+ // 注意:html2canvas 会自己处理图片加载,这里主要是为了缓存
7169
+ });
7170
+ };
7171
+ }
7172
+ if (!this.options.silentMode) {
7173
+ console.log(`📸 html2canvas 配置: 尺寸 ${finalWidth}x${finalHeight}, 质量 ${finalQuality.toFixed(2)}, 缩放 ${options.scale}`);
7174
+ }
7175
+ // 执行截图
7176
+ const canvas = await html2canvas(element, options);
7177
+ // 根据输出格式转换
7178
+ let mimeType = 'image/png';
7179
+ let finalQualityForExport = undefined;
7180
+ if (this.options.outputFormat === 'webp' && !isMobile) {
7181
+ try {
7182
+ const testCanvas = document.createElement('canvas');
7183
+ testCanvas.width = 1;
7184
+ testCanvas.height = 1;
7185
+ const testDataUrl = testCanvas.toDataURL('image/webp');
7186
+ if (testDataUrl.indexOf('webp') !== -1) {
7187
+ mimeType = 'image/webp';
7188
+ finalQualityForExport = finalQuality;
7189
+ }
7190
+ }
7191
+ catch {
7192
+ mimeType = 'image/jpeg';
7193
+ finalQualityForExport = finalQuality;
7194
+ }
7195
+ }
7196
+ else if (this.options.outputFormat === 'jpeg') {
7197
+ mimeType = 'image/jpeg';
7198
+ finalQualityForExport = finalQuality;
7199
+ }
7200
+ // 转换为 data URL
7201
+ const dataUrl = mimeType === 'image/png'
7202
+ ? canvas.toDataURL(mimeType)
7203
+ : canvas.toDataURL(mimeType, finalQualityForExport);
7204
+ // 验证结果
7205
+ if (!dataUrl || dataUrl.length < 100) {
7206
+ throw new Error('生成的截图数据无效或过短');
7207
+ }
7208
+ if (!this.options.silentMode) {
7209
+ console.log(`📸 html2canvas 截图成功!格式: ${this.options.outputFormat}, 尺寸: ${canvas.width}x${canvas.height}`);
7210
+ }
7211
+ return dataUrl;
7212
+ }
7213
+ catch (error) {
7214
+ const errorMessage = error instanceof Error ? error.message : String(error);
7215
+ if (!this.options.silentMode) {
7216
+ console.error('📸 html2canvas 截图失败:', errorMessage);
7217
+ if (errorMessage.includes('CORS') || errorMessage.includes('cross-origin')) {
7218
+ console.warn('📸 💡 建议:配置 proxyUrl 选项处理跨域图片');
7219
+ }
7220
+ }
7221
+ throw error;
7222
+ }
7223
+ }
7069
7224
  /**
7070
7225
  * 使用 modern-screenshot 截图(启用 Worker)
7226
+ *
7227
+ * 优势:
7228
+ * - 使用 Worker,不阻塞主线程 UI
7229
+ * - 支持并发处理
7230
+ * - 适合复杂页面
7231
+ *
7232
+ * 劣势:
7233
+ * - 处理 SVG 和本地资源较慢(Worker 通信开销)
7234
+ * - 配置相对复杂
7235
+ * - 需要处理 Worker URL
7236
+ *
7237
+ * 适用场景:
7238
+ * - 复杂页面,需要不阻塞 UI
7239
+ * - 需要高质量截图
7240
+ * - 页面资源较少
7071
7241
  */
7072
7242
  async takeScreenshotWithModernScreenshot(element) {
7073
7243
  if (!this.options.silentMode) {
@@ -1,3 +1,5 @@
1
+ import html2canvas from 'html2canvas';
2
+
1
3
  // 直接使用base64字符串,避免打包后路径问题
2
4
  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==';
3
5
  class IconManager {
@@ -6900,6 +6902,9 @@ class ScreenshotManager {
6900
6902
  if (selectedEngine === 'snapdom') {
6901
6903
  dataUrl = await this.takeScreenshotWithSnapdom(this.targetElement);
6902
6904
  }
6905
+ else if (selectedEngine === 'html2canvas') {
6906
+ dataUrl = await this.takeScreenshotWithHtml2Canvas(this.targetElement);
6907
+ }
6903
6908
  else {
6904
6909
  // 默认使用 modern-screenshot
6905
6910
  dataUrl = await this.takeScreenshotWithModernScreenshot(this.targetElement);
@@ -7062,8 +7067,173 @@ class ScreenshotManager {
7062
7067
  throw error;
7063
7068
  }
7064
7069
  }
7070
+ /**
7071
+ * 使用 html2canvas 截图
7072
+ *
7073
+ * 优势:
7074
+ * - 处理 SVG 和本地资源更快(不需要复杂的 Worker 通信)
7075
+ * - 兼容性好,支持更多 CSS 特性
7076
+ * - 跨域处理相对简单
7077
+ *
7078
+ * 劣势:
7079
+ * - 在主线程执行,可能阻塞 UI(但处理速度快,影响较小)
7080
+ * - 不支持 Worker 模式
7081
+ *
7082
+ * 适用场景:
7083
+ * - 页面包含大量 SVG 图标
7084
+ * - 本地资源较多
7085
+ * - 需要快速截图
7086
+ */
7087
+ async takeScreenshotWithHtml2Canvas(element) {
7088
+ if (!this.options.silentMode) {
7089
+ console.log('📸 使用 html2canvas 引擎截图...');
7090
+ }
7091
+ try {
7092
+ // 检查元素是否存在和可见
7093
+ const rect = element.getBoundingClientRect();
7094
+ if (rect.width === 0 || rect.height === 0) {
7095
+ throw new Error('元素尺寸为 0,无法截图');
7096
+ }
7097
+ const isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
7098
+ const isLowEndDevice = navigator.hardwareConcurrency && navigator.hardwareConcurrency <= 4;
7099
+ // 计算压缩后的尺寸
7100
+ let elementWidth = element.scrollWidth || element.clientWidth || element.offsetWidth;
7101
+ let elementHeight = element.scrollHeight || element.clientHeight || element.offsetHeight;
7102
+ if (element === document.body || element === document.documentElement) {
7103
+ elementWidth = Math.max(element.scrollWidth, element.offsetWidth, document.documentElement.scrollWidth, document.documentElement.offsetWidth, window.innerWidth);
7104
+ elementHeight = Math.max(element.scrollHeight, element.offsetHeight, document.documentElement.scrollHeight, document.documentElement.offsetHeight, window.innerHeight);
7105
+ }
7106
+ const { width, height } = this.calculateCompressedSize(elementWidth, elementHeight, this.options.maxWidth, this.options.maxHeight);
7107
+ const finalWidth = width < elementWidth ? width : Math.min(elementWidth, this.options.maxWidth);
7108
+ const finalHeight = height < elementHeight ? height : Math.min(elementHeight, this.options.maxHeight);
7109
+ // html2canvas 质量设置(0-1)
7110
+ const finalQuality = isMobile || isLowEndDevice
7111
+ ? Math.max(this.options.quality * 0.65, 0.2)
7112
+ : this.options.quality;
7113
+ // html2canvas 配置选项
7114
+ const options = {
7115
+ // 基本配置
7116
+ backgroundColor: '#ffffff',
7117
+ scale: this.options.scale !== 1 ? (isMobile ? 0.7 : this.options.scale) : (isMobile ? 0.7 : 1),
7118
+ useCORS: this.options.enableCORS,
7119
+ allowTaint: !this.options.enableCORS, // 如果启用 CORS,不允许 taint
7120
+ logging: !this.options.silentMode,
7121
+ width: finalWidth,
7122
+ height: finalHeight,
7123
+ // 性能优化
7124
+ removeContainer: true, // 截图后移除临时容器
7125
+ imageTimeout: this.options.imageLoadTimeout || 5000,
7126
+ // 忽略某些元素(可选,提升性能)
7127
+ ignoreElements: (element) => {
7128
+ // 忽略隐藏元素
7129
+ const style = window.getComputedStyle(element);
7130
+ if (style.display === 'none' || style.visibility === 'hidden' || style.opacity === '0') {
7131
+ return true;
7132
+ }
7133
+ return false;
7134
+ },
7135
+ };
7136
+ // html2canvas 不支持直接的 proxy 选项,需要通过 onclone 钩子处理图片
7137
+ // 如果配置了代理服务器,在克隆时替换图片 URL
7138
+ if (this.options.useProxy && this.options.proxyUrl && this.options.proxyUrl.trim() !== '') {
7139
+ options.onclone = (clonedDoc) => {
7140
+ // 在克隆的文档中,替换所有跨域图片的 src
7141
+ const images = clonedDoc.querySelectorAll('img');
7142
+ images.forEach((img) => {
7143
+ const originalSrc = img.getAttribute('src');
7144
+ if (!originalSrc)
7145
+ return;
7146
+ // 检查是否是跨域图片
7147
+ try {
7148
+ const imgUrl = new URL(originalSrc, window.location.href);
7149
+ if (imgUrl.origin === window.location.origin) {
7150
+ return; // 同源图片,不需要处理
7151
+ }
7152
+ }
7153
+ catch {
7154
+ // URL 解析失败,可能是相对路径,继续处理
7155
+ }
7156
+ // 检查缓存
7157
+ const cachedDataUrl = this.getCachedImage(originalSrc);
7158
+ if (cachedDataUrl) {
7159
+ img.src = cachedDataUrl;
7160
+ return;
7161
+ }
7162
+ // 对于跨域图片,使用代理 URL
7163
+ // html2canvas 会自动处理,但我们可以预先处理
7164
+ // 注意:html2canvas 会自己处理图片加载,这里主要是为了缓存
7165
+ });
7166
+ };
7167
+ }
7168
+ if (!this.options.silentMode) {
7169
+ console.log(`📸 html2canvas 配置: 尺寸 ${finalWidth}x${finalHeight}, 质量 ${finalQuality.toFixed(2)}, 缩放 ${options.scale}`);
7170
+ }
7171
+ // 执行截图
7172
+ const canvas = await html2canvas(element, options);
7173
+ // 根据输出格式转换
7174
+ let mimeType = 'image/png';
7175
+ let finalQualityForExport = undefined;
7176
+ if (this.options.outputFormat === 'webp' && !isMobile) {
7177
+ try {
7178
+ const testCanvas = document.createElement('canvas');
7179
+ testCanvas.width = 1;
7180
+ testCanvas.height = 1;
7181
+ const testDataUrl = testCanvas.toDataURL('image/webp');
7182
+ if (testDataUrl.indexOf('webp') !== -1) {
7183
+ mimeType = 'image/webp';
7184
+ finalQualityForExport = finalQuality;
7185
+ }
7186
+ }
7187
+ catch {
7188
+ mimeType = 'image/jpeg';
7189
+ finalQualityForExport = finalQuality;
7190
+ }
7191
+ }
7192
+ else if (this.options.outputFormat === 'jpeg') {
7193
+ mimeType = 'image/jpeg';
7194
+ finalQualityForExport = finalQuality;
7195
+ }
7196
+ // 转换为 data URL
7197
+ const dataUrl = mimeType === 'image/png'
7198
+ ? canvas.toDataURL(mimeType)
7199
+ : canvas.toDataURL(mimeType, finalQualityForExport);
7200
+ // 验证结果
7201
+ if (!dataUrl || dataUrl.length < 100) {
7202
+ throw new Error('生成的截图数据无效或过短');
7203
+ }
7204
+ if (!this.options.silentMode) {
7205
+ console.log(`📸 html2canvas 截图成功!格式: ${this.options.outputFormat}, 尺寸: ${canvas.width}x${canvas.height}`);
7206
+ }
7207
+ return dataUrl;
7208
+ }
7209
+ catch (error) {
7210
+ const errorMessage = error instanceof Error ? error.message : String(error);
7211
+ if (!this.options.silentMode) {
7212
+ console.error('📸 html2canvas 截图失败:', errorMessage);
7213
+ if (errorMessage.includes('CORS') || errorMessage.includes('cross-origin')) {
7214
+ console.warn('📸 💡 建议:配置 proxyUrl 选项处理跨域图片');
7215
+ }
7216
+ }
7217
+ throw error;
7218
+ }
7219
+ }
7065
7220
  /**
7066
7221
  * 使用 modern-screenshot 截图(启用 Worker)
7222
+ *
7223
+ * 优势:
7224
+ * - 使用 Worker,不阻塞主线程 UI
7225
+ * - 支持并发处理
7226
+ * - 适合复杂页面
7227
+ *
7228
+ * 劣势:
7229
+ * - 处理 SVG 和本地资源较慢(Worker 通信开销)
7230
+ * - 配置相对复杂
7231
+ * - 需要处理 Worker URL
7232
+ *
7233
+ * 适用场景:
7234
+ * - 复杂页面,需要不阻塞 UI
7235
+ * - 需要高质量截图
7236
+ * - 页面资源较少
7067
7237
  */
7068
7238
  async takeScreenshotWithModernScreenshot(element) {
7069
7239
  if (!this.options.silentMode) {