CatPtain commited on
Commit
d1278b8
·
verified ·
1 Parent(s): 21da54e

Upload screenshotService.js

Browse files
backend/src/services/screenshotService.js CHANGED
@@ -35,7 +35,10 @@ class ScreenshotService {
35
  '--disable-domain-reliability',
36
  '--disable-component-extensions-with-background-pages',
37
  '--force-device-scale-factor=1',
38
- '--enable-precise-memory-info'
 
 
 
39
  ]
40
  });
41
  console.log('Puppeteer浏览器初始化完成');
@@ -51,20 +54,55 @@ class ScreenshotService {
51
  }
52
  }
53
 
54
- async modifyHtmlForScreenshot(htmlContent, targetWidth, targetHeight) {
55
- console.log(`开始修改HTML for截图, 目标尺寸: ${targetWidth}x${targetHeight}`);
56
-
57
- // 创建完全针对截图优化的HTML版本
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
58
  const optimizedHtml = htmlContent.replace(
59
- /<head>/i,
60
- `<head>
61
- <meta charset="UTF-8">
62
- <meta name="viewport" content="width=${targetWidth}, height=${targetHeight}, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no, viewport-fit=cover">
63
- <!-- 截图模式标识 -->
64
  <meta name="screenshot-mode" content="true">
65
- <!-- 强制精确尺寸控制 -->
66
- <style id="screenshot-optimization">
67
- /* 全局重置 - 完全消除边距 */
68
  *, *::before, *::after {
69
  margin: 0 !important;
70
  padding: 0 !important;
@@ -73,7 +111,6 @@ class ScreenshotService {
73
  outline: none !important;
74
  }
75
 
76
- /* 根元素强制设置 */
77
  html {
78
  width: ${targetWidth}px !important;
79
  height: ${targetHeight}px !important;
@@ -87,13 +124,10 @@ class ScreenshotService {
87
  left: 0 !important;
88
  margin: 0 !important;
89
  padding: 0 !important;
90
- border: none !important;
91
- outline: none !important;
92
  transform: none !important;
93
  transform-origin: top left !important;
94
  }
95
 
96
- /* Body元素强制设置 */
97
  body {
98
  width: ${targetWidth}px !important;
99
  height: ${targetHeight}px !important;
@@ -107,13 +141,10 @@ class ScreenshotService {
107
  left: 0 !important;
108
  margin: 0 !important;
109
  padding: 0 !important;
110
- border: none !important;
111
- outline: none !important;
112
  transform: none !important;
113
  transform-origin: top left !important;
114
  }
115
 
116
- /* 幻灯片容器强制设置 */
117
  .slide-container {
118
  width: ${targetWidth}px !important;
119
  height: ${targetHeight}px !important;
@@ -129,8 +160,6 @@ class ScreenshotService {
129
  transform-origin: top left !important;
130
  margin: 0 !important;
131
  padding: 0 !important;
132
- border: none !important;
133
- outline: none !important;
134
  box-shadow: none !important;
135
  z-index: 1 !important;
136
  }
@@ -144,7 +173,6 @@ class ScreenshotService {
144
  height: 0 !important;
145
  }
146
 
147
- /* Firefox */
148
  html {
149
  scrollbar-width: none !important;
150
  }
@@ -163,82 +191,93 @@ class ScreenshotService {
163
  pointer-events: none !important;
164
  }
165
 
166
- /* 移除响应式样式 */
167
- .browse-mode * {
168
- display: none !important;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
169
  }
170
  </style>`
171
  );
172
 
173
- // 注入截图专用JavaScript
174
  const finalHtml = optimizedHtml.replace(
175
- /<\/body>/i,
176
  `
177
- <script id="screenshot-finalizer">
178
- // 截图模式最终设置
179
  window.SCREENSHOT_EXACT_MODE = true;
180
  window.PPT_TARGET_WIDTH = ${targetWidth};
181
  window.PPT_TARGET_HEIGHT = ${targetHeight};
182
 
183
- // 立即执行尺寸强制设置
184
  (function() {
185
- const exactWidth = ${targetWidth};
186
- const exactHeight = ${targetHeight};
187
 
188
- console.log('截图模式强制设置:', exactWidth + 'x' + exactHeight);
189
 
190
- // 强制设置根元素
191
  const html = document.documentElement;
192
  const body = document.body;
193
 
194
- html.style.cssText = \`
195
- width: \${exactWidth}px !important;
196
- height: \${exactHeight}px !important;
197
- min-width: \${exactWidth}px !important;
198
- min-height: \${exactHeight}px !important;
199
- max-width: \${exactWidth}px !important;
200
- max-height: \${exactHeight}px !important;
201
- overflow: hidden !important;
202
- margin: 0 !important;
203
- padding: 0 !important;
204
- position: fixed !important;
205
- top: 0 !important;
206
- left: 0 !important;
207
- border: none !important;
208
- outline: none !important;
209
- transform: none !important;
210
- transform-origin: top left !important;
211
- \`;
 
 
 
 
 
 
 
 
 
 
212
 
213
- body.style.cssText = \`
214
- width: \${exactWidth}px !important;
215
- height: \${exactHeight}px !important;
216
- min-width: \${exactWidth}px !important;
217
- min-height: \${exactHeight}px !important;
218
- max-width: \${exactWidth}px !important;
219
- max-height: \${exactHeight}px !important;
220
- overflow: hidden !important;
221
- margin: 0 !important;
222
- padding: 0 !important;
223
- position: fixed !important;
224
- top: 0 !important;
225
- left: 0 !important;
226
- border: none !important;
227
- outline: none !important;
228
- transform: none !important;
229
- transform-origin: top left !important;
230
- \`;
231
 
232
  // 设置容器
233
  const container = document.querySelector('.slide-container');
234
  if (container) {
235
  container.style.cssText = \`
236
- width: \${exactWidth}px !important;
237
- height: \${exactHeight}px !important;
238
- min-width: \${exactWidth}px !important;
239
- min-height: \${exactHeight}px !important;
240
- max-width: \${exactWidth}px !important;
241
- max-height: \${exactHeight}px !important;
242
  position: fixed !important;
243
  top: 0 !important;
244
  left: 0 !important;
@@ -253,23 +292,17 @@ class ScreenshotService {
253
  \`;
254
  }
255
 
256
- // 移除响应式类
257
- html.classList.remove('browse-mode');
258
- body.classList.remove('browse-mode');
259
-
260
- console.log('截图模式设置完成');
261
  })();
262
 
263
  // DOM加载完成后再次确认
264
  document.addEventListener('DOMContentLoaded', function() {
265
- console.log('DOM加载完成,最终确认尺寸设置');
266
-
267
- // 再次强制设置,确保完全生效
268
  const html = document.documentElement;
269
  const body = document.body;
270
  const container = document.querySelector('.slide-container');
271
 
272
- [html, body, container].forEach(element => {
 
273
  if (element) {
274
  element.style.width = '${targetWidth}px';
275
  element.style.height = '${targetHeight}px';
@@ -282,41 +315,54 @@ class ScreenshotService {
282
  element.style.border = 'none';
283
  element.style.outline = 'none';
284
  element.style.overflow = 'hidden';
285
-
286
- if (element !== container) {
287
- element.style.position = 'fixed';
288
- element.style.top = '0';
289
- element.style.left = '0';
290
- }
291
  }
292
  });
293
 
294
- // 最终验证
295
- setTimeout(() => {
296
- console.log('最终尺寸验证:', {
297
- html: html.offsetWidth + 'x' + html.offsetHeight,
298
- body: body.offsetWidth + 'x' + body.offsetHeight,
299
- container: container ? container.offsetWidth + 'x' + container.offsetHeight : 'none',
300
- target: '${targetWidth}x${targetHeight}'
301
- });
302
- }, 100);
 
 
 
 
 
 
 
 
 
 
 
303
  });
304
  </script>
305
- </body>`
306
  );
307
 
308
- console.log('HTML修改完成,已注入截图优化代码');
309
  return finalHtml;
310
  }
311
 
312
- async captureScreenshot(htmlContent, width, height, options = {}) {
313
  try {
314
  await this.initBrowser();
315
 
316
- console.log(`开始截图, 目标尺寸: ${width}x${height}`);
 
 
 
 
317
 
318
- // 修改HTML内容以适应截图
319
- const optimizedHtml = await this.modifyHtmlForScreenshot(htmlContent, width, height);
320
 
321
  // 创建新页面
322
  const page = await this.browser.newPage();
@@ -324,8 +370,8 @@ class ScreenshotService {
324
  try {
325
  // 设置精确的viewport尺寸
326
  await page.setViewport({
327
- width: width,
328
- height: height,
329
  deviceScaleFactor: options.deviceScaleFactor || 2, // 高清截图
330
  });
331
 
@@ -338,76 +384,84 @@ class ScreenshotService {
338
  // 等待页面完全渲染
339
  await page.waitForTimeout(2000);
340
 
341
- // 执行最终的尺寸验证和调整
342
  await page.evaluate((targetWidth, targetHeight) => {
343
  const html = document.documentElement;
344
  const body = document.body;
345
  const container = document.querySelector('.slide-container');
346
 
347
- // 最终强制设置
348
- [html, body].forEach(element => {
349
- if (element) {
350
- element.style.width = targetWidth + 'px';
351
- element.style.height = targetHeight + 'px';
352
- element.style.minWidth = targetWidth + 'px';
353
- element.style.minHeight = targetHeight + 'px';
354
- element.style.maxWidth = targetWidth + 'px';
355
- element.style.maxHeight = targetHeight + 'px';
356
- element.style.margin = '0';
357
- element.style.padding = '0';
358
- element.style.border = 'none';
359
- element.style.outline = 'none';
360
- element.style.overflow = 'hidden';
 
 
 
 
361
  element.style.position = 'fixed';
362
  element.style.top = '0';
363
  element.style.left = '0';
364
  }
365
- });
 
 
 
366
 
367
  if (container) {
368
- container.style.width = targetWidth + 'px';
369
- container.style.height = targetHeight + 'px';
370
- container.style.minWidth = targetWidth + 'px';
371
- container.style.minHeight = targetHeight + 'px';
372
- container.style.maxWidth = targetWidth + 'px';
373
- container.style.maxHeight = targetHeight + 'px';
374
  container.style.position = 'fixed';
375
  container.style.top = '0';
376
  container.style.left = '0';
377
- container.style.margin = '0';
378
- container.style.padding = '0';
379
- container.style.border = 'none';
380
- container.style.outline = 'none';
381
- container.style.overflow = 'hidden';
382
- container.style.transform = 'none';
383
  container.style.boxShadow = 'none';
 
384
  }
385
 
386
- console.log('最终页面尺寸确认:', {
 
387
  html: html.offsetWidth + 'x' + html.offsetHeight,
388
  body: body.offsetWidth + 'x' + body.offsetHeight,
389
- container: container ? container.offsetWidth + 'x' + container.offsetHeight : 'none'
390
- });
391
- }, width, height);
 
 
 
 
 
 
 
 
 
 
392
 
393
  // 再次等待以确保所有更改生效
394
  await page.waitForTimeout(1000);
395
 
396
  // 执行截图,使用精确的剪裁区域
397
  const screenshot = await page.screenshot({
398
- type: options.format || 'png',
399
- quality: options.quality || 100,
400
  clip: {
401
  x: 0,
402
  y: 0,
403
- width: width,
404
- height: height
405
  },
406
  omitBackground: false, // 包含背景
407
  captureBeyondViewport: false, // 不截取视口外内容
408
  });
409
 
410
- console.log(`截图完成, 生成了 ${screenshot.length} 字节的图片数据`);
411
  return screenshot;
412
 
413
  } finally {
@@ -415,10 +469,16 @@ class ScreenshotService {
415
  }
416
 
417
  } catch (error) {
418
- console.error('截图失败:', error);
419
- throw new Error(`截图失败: ${error.message}`);
420
  }
421
  }
 
 
 
 
 
 
422
  }
423
 
424
  export default new ScreenshotService();
 
35
  '--disable-domain-reliability',
36
  '--disable-component-extensions-with-background-pages',
37
  '--force-device-scale-factor=1',
38
+ '--enable-precise-memory-info',
39
+ '--disable-features=VizDisplayCompositor',
40
+ '--run-all-compositor-stages-before-draw',
41
+ '--disable-new-content-rendering-timeout'
42
  ]
43
  });
44
  console.log('Puppeteer浏览器初始化完成');
 
54
  }
55
  }
56
 
57
+ // 从HTML中提取PPT尺寸信息
58
+ extractPPTDimensions(htmlContent) {
59
+ try {
60
+ // 从JavaScript中提取PPT_DIMENSIONS
61
+ const dimensionMatch = htmlContent.match(/window\.PPT_DIMENSIONS\s*=\s*{\s*width:\s*(\d+),\s*height:\s*(\d+)\s*}/);
62
+ if (dimensionMatch) {
63
+ return {
64
+ width: parseInt(dimensionMatch[1]),
65
+ height: parseInt(dimensionMatch[2])
66
+ };
67
+ }
68
+
69
+ // 从viewport meta标签中提取
70
+ const viewportMatch = htmlContent.match(/width=(\d+),\s*height=(\d+)/);
71
+ if (viewportMatch) {
72
+ return {
73
+ width: parseInt(viewportMatch[1]),
74
+ height: parseInt(viewportMatch[2])
75
+ };
76
+ }
77
+
78
+ // 从CSS中提取
79
+ const cssMatch = htmlContent.match(/width:\s*(\d+)px.*height:\s*(\d+)px/);
80
+ if (cssMatch) {
81
+ return {
82
+ width: parseInt(cssMatch[1]),
83
+ height: parseInt(cssMatch[2])
84
+ };
85
+ }
86
+
87
+ // 默认尺寸
88
+ return { width: 960, height: 720 };
89
+ } catch (error) {
90
+ console.warn('提取PPT尺寸失败,使用默认尺寸:', error.message);
91
+ return { width: 960, height: 720 };
92
+ }
93
+ }
94
+
95
+ // 优化HTML内容以确保精确截图
96
+ optimizeHtmlForScreenshot(htmlContent, targetWidth, targetHeight) {
97
+ console.log(`优化HTML for精确截图, 目标尺寸: ${targetWidth}x${targetHeight}`);
98
+
99
+ // 在<head>标签后立即插入截图优化代码
100
  const optimizedHtml = htmlContent.replace(
101
+ /(<head[^>]*>)/i,
102
+ `$1
 
 
 
103
  <meta name="screenshot-mode" content="true">
104
+ <style id="screenshot-precise-control">
105
+ /* 截图模式:绝对精确的尺寸控制 */
 
106
  *, *::before, *::after {
107
  margin: 0 !important;
108
  padding: 0 !important;
 
111
  outline: none !important;
112
  }
113
 
 
114
  html {
115
  width: ${targetWidth}px !important;
116
  height: ${targetHeight}px !important;
 
124
  left: 0 !important;
125
  margin: 0 !important;
126
  padding: 0 !important;
 
 
127
  transform: none !important;
128
  transform-origin: top left !important;
129
  }
130
 
 
131
  body {
132
  width: ${targetWidth}px !important;
133
  height: ${targetHeight}px !important;
 
141
  left: 0 !important;
142
  margin: 0 !important;
143
  padding: 0 !important;
 
 
144
  transform: none !important;
145
  transform-origin: top left !important;
146
  }
147
 
 
148
  .slide-container {
149
  width: ${targetWidth}px !important;
150
  height: ${targetHeight}px !important;
 
160
  transform-origin: top left !important;
161
  margin: 0 !important;
162
  padding: 0 !important;
 
 
163
  box-shadow: none !important;
164
  z-index: 1 !important;
165
  }
 
173
  height: 0 !important;
174
  }
175
 
 
176
  html {
177
  scrollbar-width: none !important;
178
  }
 
191
  pointer-events: none !important;
192
  }
193
 
194
+ /* 强制移除响应式样式 */
195
+ .browse-mode,
196
+ .browse-mode html,
197
+ .browse-mode body,
198
+ .browse-mode .slide-container {
199
+ display: block !important;
200
+ position: fixed !important;
201
+ width: ${targetWidth}px !important;
202
+ height: ${targetHeight}px !important;
203
+ min-width: ${targetWidth}px !important;
204
+ min-height: ${targetHeight}px !important;
205
+ max-width: ${targetWidth}px !important;
206
+ max-height: ${targetHeight}px !important;
207
+ transform: none !important;
208
+ background-color: transparent !important;
209
+ top: 0 !important;
210
+ left: 0 !important;
211
+ margin: 0 !important;
212
+ padding: 0 !important;
213
+ box-shadow: none !important;
214
  }
215
  </style>`
216
  );
217
 
218
+ // 在</body>前插入截图专用JavaScript
219
  const finalHtml = optimizedHtml.replace(
220
+ /(<\/body>)/i,
221
  `
222
+ <script id="screenshot-precision-script">
223
+ // 截图模式强制设置
224
  window.SCREENSHOT_EXACT_MODE = true;
225
  window.PPT_TARGET_WIDTH = ${targetWidth};
226
  window.PPT_TARGET_HEIGHT = ${targetHeight};
227
 
228
+ // 立即执行强制设置,确保尺寸精确
229
  (function() {
230
+ const targetW = ${targetWidth};
231
+ const targetH = ${targetHeight};
232
 
233
+ console.log('截图模式精确设置开始:', targetW + 'x' + targetH);
234
 
 
235
  const html = document.documentElement;
236
  const body = document.body;
237
 
238
+ // 强制设置根元素
239
+ const setElementSize = (element, width, height) => {
240
+ if (!element) return;
241
+
242
+ element.style.cssText = \`
243
+ width: \${width}px !important;
244
+ height: \${height}px !important;
245
+ min-width: \${width}px !important;
246
+ min-height: \${height}px !important;
247
+ max-width: \${width}px !important;
248
+ max-height: \${height}px !important;
249
+ overflow: hidden !important;
250
+ margin: 0 !important;
251
+ padding: 0 !important;
252
+ position: fixed !important;
253
+ top: 0 !important;
254
+ left: 0 !important;
255
+ border: none !important;
256
+ outline: none !important;
257
+ transform: none !important;
258
+ transform-origin: top left !important;
259
+ box-sizing: border-box !important;
260
+ \`;
261
+ };
262
+
263
+ // 设置HTML和Body
264
+ setElementSize(html, targetW, targetH);
265
+ setElementSize(body, targetW, targetH);
266
 
267
+ // 移除可能的���应式类
268
+ html.classList.remove('browse-mode');
269
+ body.classList.remove('browse-mode');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
270
 
271
  // 设置容器
272
  const container = document.querySelector('.slide-container');
273
  if (container) {
274
  container.style.cssText = \`
275
+ width: \${targetW}px !important;
276
+ height: \${targetH}px !important;
277
+ min-width: \${targetW}px !important;
278
+ min-height: \${targetH}px !important;
279
+ max-width: \${targetW}px !important;
280
+ max-height: \${targetH}px !important;
281
  position: fixed !important;
282
  top: 0 !important;
283
  left: 0 !important;
 
292
  \`;
293
  }
294
 
295
+ console.log('截图模式精确设置完成');
 
 
 
 
296
  })();
297
 
298
  // DOM加载完成后再次确认
299
  document.addEventListener('DOMContentLoaded', function() {
 
 
 
300
  const html = document.documentElement;
301
  const body = document.body;
302
  const container = document.querySelector('.slide-container');
303
 
304
+ // 最终强制设置,确保完全生效
305
+ [html, body].forEach(element => {
306
  if (element) {
307
  element.style.width = '${targetWidth}px';
308
  element.style.height = '${targetHeight}px';
 
315
  element.style.border = 'none';
316
  element.style.outline = 'none';
317
  element.style.overflow = 'hidden';
318
+ element.style.position = 'fixed';
319
+ element.style.top = '0';
320
+ element.style.left = '0';
321
+ element.style.transform = 'none';
 
 
322
  }
323
  });
324
 
325
+ if (container) {
326
+ container.style.width = '${targetWidth}px';
327
+ container.style.height = '${targetHeight}px';
328
+ container.style.minWidth = '${targetWidth}px';
329
+ container.style.minHeight = '${targetHeight}px';
330
+ container.style.maxWidth = '${targetWidth}px';
331
+ container.style.maxHeight = '${targetHeight}px';
332
+ container.style.position = 'fixed';
333
+ container.style.top = '0';
334
+ container.style.left = '0';
335
+ container.style.margin = '0';
336
+ container.style.padding = '0';
337
+ container.style.border = 'none';
338
+ container.style.outline = 'none';
339
+ container.style.overflow = 'hidden';
340
+ container.style.transform = 'none';
341
+ container.style.boxShadow = 'none';
342
+ }
343
+
344
+ console.log('DOM加载后的最终尺寸确认完成');
345
  });
346
  </script>
347
+ $1`
348
  );
349
 
350
+ console.log('HTML优化完成,已注入精确尺寸控制代码');
351
  return finalHtml;
352
  }
353
 
354
+ async generateScreenshot(htmlContent, options = {}) {
355
  try {
356
  await this.initBrowser();
357
 
358
+ console.log('开始生成截图...');
359
+
360
+ // 从HTML中提取PPT的精确尺寸
361
+ const dimensions = this.extractPPTDimensions(htmlContent);
362
+ console.log(`检测到PPT尺寸: ${dimensions.width}x${dimensions.height}`);
363
 
364
+ // 优化HTML内容以确保精确截图
365
+ const optimizedHtml = this.optimizeHtmlForScreenshot(htmlContent, dimensions.width, dimensions.height);
366
 
367
  // 创建新页面
368
  const page = await this.browser.newPage();
 
370
  try {
371
  // 设置精确的viewport尺寸
372
  await page.setViewport({
373
+ width: dimensions.width,
374
+ height: dimensions.height,
375
  deviceScaleFactor: options.deviceScaleFactor || 2, // 高清截图
376
  });
377
 
 
384
  // 等待页面完全渲染
385
  await page.waitForTimeout(2000);
386
 
387
+ // 执行最终的尺寸验证和强制设置
388
  await page.evaluate((targetWidth, targetHeight) => {
389
  const html = document.documentElement;
390
  const body = document.body;
391
  const container = document.querySelector('.slide-container');
392
 
393
+ // 最终强制设置,确保精确尺寸
394
+ const forceSize = (element, width, height) => {
395
+ if (!element) return;
396
+
397
+ element.style.width = width + 'px';
398
+ element.style.height = height + 'px';
399
+ element.style.minWidth = width + 'px';
400
+ element.style.minHeight = height + 'px';
401
+ element.style.maxWidth = width + 'px';
402
+ element.style.maxHeight = height + 'px';
403
+ element.style.margin = '0';
404
+ element.style.padding = '0';
405
+ element.style.border = 'none';
406
+ element.style.outline = 'none';
407
+ element.style.overflow = 'hidden';
408
+ element.style.transform = 'none';
409
+
410
+ if (element !== container) {
411
  element.style.position = 'fixed';
412
  element.style.top = '0';
413
  element.style.left = '0';
414
  }
415
+ };
416
+
417
+ forceSize(html, targetWidth, targetHeight);
418
+ forceSize(body, targetWidth, targetHeight);
419
 
420
  if (container) {
421
+ forceSize(container, targetWidth, targetHeight);
 
 
 
 
 
422
  container.style.position = 'fixed';
423
  container.style.top = '0';
424
  container.style.left = '0';
 
 
 
 
 
 
425
  container.style.boxShadow = 'none';
426
+ container.style.zIndex = '1';
427
  }
428
 
429
+ // 验证尺寸设置结果
430
+ const verification = {
431
  html: html.offsetWidth + 'x' + html.offsetHeight,
432
  body: body.offsetWidth + 'x' + body.offsetHeight,
433
+ container: container ? container.offsetWidth + 'x' + container.offsetHeight : 'none',
434
+ target: targetWidth + 'x' + targetHeight
435
+ };
436
+
437
+ console.log('最终尺寸验证:', verification);
438
+
439
+ // 如果尺寸不匹配,记录警告
440
+ if (html.offsetWidth !== targetWidth || html.offsetHeight !== targetHeight) {
441
+ console.warn('HTML尺寸不匹配目标尺寸!');
442
+ }
443
+
444
+ return verification;
445
+ }, dimensions.width, dimensions.height);
446
 
447
  // 再次等待以确保所有更改生效
448
  await page.waitForTimeout(1000);
449
 
450
  // 执行截图,使用精确的剪裁区域
451
  const screenshot = await page.screenshot({
452
+ type: options.format || 'jpeg',
453
+ quality: options.quality || 95,
454
  clip: {
455
  x: 0,
456
  y: 0,
457
+ width: dimensions.width,
458
+ height: dimensions.height
459
  },
460
  omitBackground: false, // 包含背景
461
  captureBeyondViewport: false, // 不截取视口外内容
462
  });
463
 
464
+ console.log(`截图成功生成,尺寸: ${dimensions.width}x${dimensions.height}, 数据大小: ${screenshot.length} 字节`);
465
  return screenshot;
466
 
467
  } finally {
 
469
  }
470
 
471
  } catch (error) {
472
+ console.error('截图生成失败:', error);
473
+ throw new Error(`截图生成失败: ${error.message}`);
474
  }
475
  }
476
+
477
+ // 兼容旧方法名
478
+ async captureScreenshot(htmlContent, width, height, options = {}) {
479
+ console.log('使用兼容方法captureScreenshot,建议使用generateScreenshot');
480
+ return this.generateScreenshot(htmlContent, options);
481
+ }
482
  }
483
 
484
  export default new ScreenshotService();