Upload screenshotService.js
Browse files
backend/src/services/screenshotService.js
CHANGED
@@ -92,7 +92,6 @@ class ScreenshotService {
|
|
92 |
|
93 |
// 内存和性能优化
|
94 |
'--disable-dev-shm-usage',
|
95 |
-
'--disable-gpu',
|
96 |
'--disable-extensions',
|
97 |
'--disable-background-timer-throttling',
|
98 |
'--disable-backgrounding-occluded-windows',
|
@@ -100,17 +99,25 @@ class ScreenshotService {
|
|
100 |
'--no-first-run',
|
101 |
'--no-default-browser-check',
|
102 |
'--disable-default-apps',
|
103 |
-
'--disable-features=TranslateUI
|
104 |
'--disable-ipc-flooding-protection',
|
105 |
|
106 |
// 容器环境优化 - 禁用D-Bus和系统服务
|
107 |
'--disable-dbus',
|
108 |
-
'--disable-software-rasterizer',
|
109 |
'--disable-field-trial-config',
|
110 |
'--disable-translate',
|
111 |
'--disable-web-security',
|
112 |
'--allow-running-insecure-content',
|
113 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
114 |
// 内存限制优化
|
115 |
'--js-flags=--max-old-space-size=512', // 降低JS内存使用
|
116 |
'--memory-pressure-off',
|
@@ -120,9 +127,6 @@ class ScreenshotService {
|
|
120 |
'--disable-background-networking',
|
121 |
'--disable-background-mode',
|
122 |
|
123 |
-
// 字体渲染优化
|
124 |
-
'--font-render-hinting=none',
|
125 |
-
|
126 |
// 禁用不必要的功能
|
127 |
'--disable-breakpad',
|
128 |
'--disable-component-update',
|
@@ -242,17 +246,48 @@ class ScreenshotService {
|
|
242 |
// 构建Google字体URL
|
243 |
const googleFontsUrl = `https://fonts.googleapis.com/css2?family=${this.googleFonts.join('&family=')}&display=swap`;
|
244 |
|
245 |
-
// 注入字体CSS
|
246 |
await page.evaluateOnNewDocument((fontsUrl) => {
|
247 |
// 创建link元素加载Google字体
|
248 |
const link = document.createElement('link');
|
249 |
link.rel = 'stylesheet';
|
250 |
link.href = fontsUrl;
|
|
|
251 |
|
252 |
-
//
|
253 |
-
|
254 |
-
document.head
|
255 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
256 |
}, googleFontsUrl);
|
257 |
} catch (error) {
|
258 |
console.warn('⚠️ Failed to inject Google Fonts:', error.message);
|
@@ -698,7 +733,7 @@ class ScreenshotService {
|
|
698 |
return document.fonts ? document.fonts.ready : Promise.resolve();
|
699 |
});
|
700 |
|
701 |
-
// 等待SVG
|
702 |
await page.evaluate(() => {
|
703 |
return new Promise(resolve => {
|
704 |
const svgs = document.querySelectorAll('svg');
|
@@ -707,26 +742,47 @@ class ScreenshotService {
|
|
707 |
return;
|
708 |
}
|
709 |
|
710 |
-
|
711 |
-
|
712 |
-
|
713 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
714 |
};
|
715 |
|
716 |
-
|
717 |
-
|
718 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
719 |
} else {
|
720 |
-
|
721 |
-
|
722 |
}
|
723 |
-
}
|
724 |
|
725 |
-
//
|
726 |
-
|
727 |
|
728 |
-
//
|
729 |
-
setTimeout(
|
|
|
|
|
|
|
730 |
});
|
731 |
});
|
732 |
|
|
|
92 |
|
93 |
// 内存和性能优化
|
94 |
'--disable-dev-shm-usage',
|
|
|
95 |
'--disable-extensions',
|
96 |
'--disable-background-timer-throttling',
|
97 |
'--disable-backgrounding-occluded-windows',
|
|
|
99 |
'--no-first-run',
|
100 |
'--no-default-browser-check',
|
101 |
'--disable-default-apps',
|
102 |
+
'--disable-features=TranslateUI',
|
103 |
'--disable-ipc-flooding-protection',
|
104 |
|
105 |
// 容器环境优化 - 禁用D-Bus和系统服务
|
106 |
'--disable-dbus',
|
|
|
107 |
'--disable-field-trial-config',
|
108 |
'--disable-translate',
|
109 |
'--disable-web-security',
|
110 |
'--allow-running-insecure-content',
|
111 |
|
112 |
+
// SVG和字体渲染优化
|
113 |
+
'--font-render-hinting=none', // 修复字体渲染不一致问题
|
114 |
+
'--enable-font-antialiasing', // 启用字体抗锯齿
|
115 |
+
'--force-color-profile=srgb', // 强制使用sRGB颜色配置
|
116 |
+
'--disable-software-rasterizer', // 禁用软件光栅化,使用硬件加速
|
117 |
+
'--enable-gpu-rasterization', // 启用GPU光栅化以改善SVG渲染
|
118 |
+
'--enable-oop-rasterization', // 启用进程外光栅化
|
119 |
+
'--disable-features=VizDisplayCompositor', // 禁用可能影响渲染的功能
|
120 |
+
|
121 |
// 内存限制优化
|
122 |
'--js-flags=--max-old-space-size=512', // 降低JS内存使用
|
123 |
'--memory-pressure-off',
|
|
|
127 |
'--disable-background-networking',
|
128 |
'--disable-background-mode',
|
129 |
|
|
|
|
|
|
|
130 |
// 禁用不必要的功能
|
131 |
'--disable-breakpad',
|
132 |
'--disable-component-update',
|
|
|
246 |
// 构建Google字体URL
|
247 |
const googleFontsUrl = `https://fonts.googleapis.com/css2?family=${this.googleFonts.join('&family=')}&display=swap`;
|
248 |
|
249 |
+
// 注入字体CSS(改进版)
|
250 |
await page.evaluateOnNewDocument((fontsUrl) => {
|
251 |
// 创建link元素加载Google字体
|
252 |
const link = document.createElement('link');
|
253 |
link.rel = 'stylesheet';
|
254 |
link.href = fontsUrl;
|
255 |
+
link.crossOrigin = 'anonymous'; // 添加跨域支持
|
256 |
|
257 |
+
// 立即添加到head,不等待DOMContentLoaded
|
258 |
+
const addFontLink = () => {
|
259 |
+
if (document.head) {
|
260 |
+
document.head.appendChild(link);
|
261 |
+
console.log('Google Fonts injected successfully');
|
262 |
+
} else {
|
263 |
+
// 如果head还不存在,等待一下再试
|
264 |
+
setTimeout(addFontLink, 10);
|
265 |
+
}
|
266 |
+
};
|
267 |
+
|
268 |
+
// 立即尝试添加
|
269 |
+
addFontLink();
|
270 |
+
|
271 |
+
// 同时添加备用字体CSS
|
272 |
+
const style = document.createElement('style');
|
273 |
+
style.textContent = `
|
274 |
+
* {
|
275 |
+
font-family: 'Noto Sans SC', 'Microsoft YaHei', 'SimHei', sans-serif !important;
|
276 |
+
}
|
277 |
+
svg text {
|
278 |
+
font-family: 'Noto Sans SC', 'Microsoft YaHei', 'SimHei', sans-serif !important;
|
279 |
+
}
|
280 |
+
`;
|
281 |
+
|
282 |
+
const addBackupStyle = () => {
|
283 |
+
if (document.head) {
|
284 |
+
document.head.appendChild(style);
|
285 |
+
} else {
|
286 |
+
setTimeout(addBackupStyle, 10);
|
287 |
+
}
|
288 |
+
};
|
289 |
+
|
290 |
+
addBackupStyle();
|
291 |
}, googleFontsUrl);
|
292 |
} catch (error) {
|
293 |
console.warn('⚠️ Failed to inject Google Fonts:', error.message);
|
|
|
733 |
return document.fonts ? document.fonts.ready : Promise.resolve();
|
734 |
});
|
735 |
|
736 |
+
// 等待SVG元素完全加载和渲染(改进版)
|
737 |
await page.evaluate(() => {
|
738 |
return new Promise(resolve => {
|
739 |
const svgs = document.querySelectorAll('svg');
|
|
|
742 |
return;
|
743 |
}
|
744 |
|
745 |
+
console.log(`Found ${svgs.length} SVG elements, waiting for rendering...`);
|
746 |
+
|
747 |
+
// 检查SVG是否已渲染的函数
|
748 |
+
const checkSVGRendered = (svg) => {
|
749 |
+
try {
|
750 |
+
// 检查SVG的bounding box是否有效
|
751 |
+
const bbox = svg.getBBox();
|
752 |
+
return bbox && bbox.width > 0 && bbox.height > 0;
|
753 |
+
} catch (e) {
|
754 |
+
// 如果getBBox失败,检查SVG是否有子元素
|
755 |
+
return svg.children.length > 0;
|
756 |
+
}
|
757 |
};
|
758 |
|
759 |
+
// 等待所有SVG渲染完成
|
760 |
+
const waitForSVGs = () => {
|
761 |
+
let allRendered = true;
|
762 |
+
|
763 |
+
svgs.forEach(svg => {
|
764 |
+
if (!checkSVGRendered(svg)) {
|
765 |
+
allRendered = false;
|
766 |
+
}
|
767 |
+
});
|
768 |
+
|
769 |
+
if (allRendered) {
|
770 |
+
console.log('All SVG elements rendered successfully');
|
771 |
+
resolve();
|
772 |
} else {
|
773 |
+
// 继续等待
|
774 |
+
setTimeout(waitForSVGs, 100);
|
775 |
}
|
776 |
+
};
|
777 |
|
778 |
+
// 开始检查
|
779 |
+
waitForSVGs();
|
780 |
|
781 |
+
// 超时保护,最多等待5秒
|
782 |
+
setTimeout(() => {
|
783 |
+
console.log('SVG rendering timeout, proceeding anyway');
|
784 |
+
resolve();
|
785 |
+
}, 5000);
|
786 |
});
|
787 |
});
|
788 |
|