customer-chat-sdk 1.0.40 → 1.0.41
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.
- package/dist/core/ScreenshotManager.d.ts +10 -0
- package/dist/core/ScreenshotManager.d.ts.map +1 -1
- package/dist/customer-sdk.cjs.js +242 -104
- package/dist/customer-sdk.esm.js +242 -104
- package/dist/customer-sdk.min.js +2 -2
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/customer-sdk.esm.js
CHANGED
|
@@ -14319,8 +14319,13 @@ class ScreenshotManager {
|
|
|
14319
14319
|
this.screenshotTimer = null;
|
|
14320
14320
|
// modern-screenshot Worker 上下文(用于复用,避免频繁创建和销毁)
|
|
14321
14321
|
this.screenshotContext = null;
|
|
14322
|
+
this.contextElement = null; // 当前 context 对应的元素
|
|
14323
|
+
this.contextOptionsHash = ''; // context 配置的哈希值,用于判断是否需要重新创建
|
|
14322
14324
|
// 截图锁,防止并发截图
|
|
14323
14325
|
this.isScreenshotInProgress = false;
|
|
14326
|
+
// 截图队列(用于处理频繁的截图请求)
|
|
14327
|
+
this.screenshotQueue = [];
|
|
14328
|
+
this.isProcessingQueue = false;
|
|
14324
14329
|
// PostMessage 监听器
|
|
14325
14330
|
this.messageHandler = null;
|
|
14326
14331
|
// 动态轮询间隔(由 iframe 消息控制)
|
|
@@ -14373,7 +14378,8 @@ class ScreenshotManager {
|
|
|
14373
14378
|
maxCacheSize: options.maxCacheSize ?? 50, // 默认最大50MB
|
|
14374
14379
|
maxCacheAge: options.maxCacheAge ?? 86400000, // 默认24小时(86400000ms)
|
|
14375
14380
|
maxImageSize: options.maxImageSize ?? 5, // 不使用代理时,单个图片最大尺寸(MB),默认5MB
|
|
14376
|
-
skipLargeImages: options.skipLargeImages ?? true // 不使用代理时,是否跳过过大的图片,默认true(跳过)
|
|
14381
|
+
skipLargeImages: options.skipLargeImages ?? true, // 不使用代理时,是否跳过过大的图片,默认true(跳过)
|
|
14382
|
+
workerNumber: options.workerNumber ?? undefined // modern-screenshot Worker 数量,默认自动计算(undefined 表示自动)
|
|
14377
14383
|
};
|
|
14378
14384
|
this.setupMessageListener();
|
|
14379
14385
|
this.setupVisibilityChangeListener();
|
|
@@ -14401,15 +14407,22 @@ class ScreenshotManager {
|
|
|
14401
14407
|
* 设置目标元素
|
|
14402
14408
|
*/
|
|
14403
14409
|
setTargetElement(element) {
|
|
14404
|
-
//
|
|
14405
|
-
if (this.targetElement !== element
|
|
14406
|
-
|
|
14407
|
-
|
|
14408
|
-
|
|
14409
|
-
|
|
14410
|
-
|
|
14410
|
+
// 如果元素变化,需要清理 context(下次截图时会重新创建)
|
|
14411
|
+
if (this.targetElement !== element) {
|
|
14412
|
+
if (this.screenshotContext) {
|
|
14413
|
+
try {
|
|
14414
|
+
destroyContext(this.screenshotContext);
|
|
14415
|
+
if (!this.options.silentMode) {
|
|
14416
|
+
console.log('📸 目标元素变化,清理 context');
|
|
14417
|
+
}
|
|
14418
|
+
}
|
|
14419
|
+
catch (e) {
|
|
14420
|
+
// 忽略清理错误
|
|
14421
|
+
}
|
|
14422
|
+
this.screenshotContext = null;
|
|
14423
|
+
this.contextElement = null;
|
|
14424
|
+
this.contextOptionsHash = '';
|
|
14411
14425
|
}
|
|
14412
|
-
this.screenshotContext = null;
|
|
14413
14426
|
}
|
|
14414
14427
|
this.targetElement = element;
|
|
14415
14428
|
}
|
|
@@ -14637,22 +14650,36 @@ class ScreenshotManager {
|
|
|
14637
14650
|
if (!this.worker && this.options.compress) {
|
|
14638
14651
|
this.worker = this.createWorker();
|
|
14639
14652
|
}
|
|
14640
|
-
//
|
|
14641
|
-
|
|
14653
|
+
// 设置定时器(使用递归 setTimeout,确保等待前一个完成)
|
|
14654
|
+
// 这样可以避免 setInterval 不等待异步完成的问题
|
|
14655
|
+
const scheduleNext = async () => {
|
|
14642
14656
|
if (this.isRunning && this.isEnabled && !document.hidden) {
|
|
14643
|
-
|
|
14644
|
-
|
|
14645
|
-
|
|
14646
|
-
|
|
14647
|
-
|
|
14648
|
-
|
|
14649
|
-
.
|
|
14650
|
-
|
|
14651
|
-
|
|
14657
|
+
try {
|
|
14658
|
+
await this.takeScreenshot();
|
|
14659
|
+
// 如果配置了上传,且当前有上传配置,自动上传
|
|
14660
|
+
if (this.currentUploadConfig) {
|
|
14661
|
+
const latestScreenshot = this.getLatestScreenshot();
|
|
14662
|
+
if (latestScreenshot && !this.isUploading) {
|
|
14663
|
+
this.uploadScreenshot(latestScreenshot, this.currentUploadConfig)
|
|
14664
|
+
.catch((error) => {
|
|
14665
|
+
console.error('📸 [轮询] 自动上传失败:', error);
|
|
14666
|
+
});
|
|
14667
|
+
}
|
|
14668
|
+
}
|
|
14669
|
+
}
|
|
14670
|
+
catch (error) {
|
|
14671
|
+
if (!this.options.silentMode) {
|
|
14672
|
+
console.error('📸 [轮询] 截图失败:', error);
|
|
14652
14673
|
}
|
|
14653
14674
|
}
|
|
14654
14675
|
}
|
|
14655
|
-
|
|
14676
|
+
// 如果还在运行,安排下一次截图
|
|
14677
|
+
if (this.isRunning) {
|
|
14678
|
+
this.screenshotTimer = setTimeout(scheduleNext, currentInterval);
|
|
14679
|
+
}
|
|
14680
|
+
};
|
|
14681
|
+
// 立即开始第一次
|
|
14682
|
+
scheduleNext();
|
|
14656
14683
|
// 注意:不再立即执行一次,因为已经在 takeScreenshotAndUpload 中执行了
|
|
14657
14684
|
}
|
|
14658
14685
|
/**
|
|
@@ -15272,8 +15299,37 @@ class ScreenshotManager {
|
|
|
15272
15299
|
*/
|
|
15273
15300
|
async takeScreenshotWithModernScreenshot(element) {
|
|
15274
15301
|
// 检查是否有截图正在进行(防止并发冲突)
|
|
15302
|
+
// 如果正在进行,将请求加入队列,而不是直接拒绝
|
|
15275
15303
|
if (this.isScreenshotInProgress) {
|
|
15276
|
-
|
|
15304
|
+
// 队列最多保留 1 个请求,避免积压
|
|
15305
|
+
if (this.screenshotQueue.length >= 1) {
|
|
15306
|
+
if (!this.options.silentMode) {
|
|
15307
|
+
console.log('📸 截图队列已满,跳过当前请求(等待队列处理)');
|
|
15308
|
+
}
|
|
15309
|
+
// 等待队列中的请求完成
|
|
15310
|
+
return new Promise((resolve, reject) => {
|
|
15311
|
+
const checkQueue = () => {
|
|
15312
|
+
if (!this.isScreenshotInProgress && this.screenshotQueue.length === 0) {
|
|
15313
|
+
// 队列已清空,重新尝试
|
|
15314
|
+
this.takeScreenshotWithModernScreenshot(element).then(resolve).catch(reject);
|
|
15315
|
+
}
|
|
15316
|
+
else {
|
|
15317
|
+
setTimeout(checkQueue, 100); // 100ms 后再次检查
|
|
15318
|
+
}
|
|
15319
|
+
};
|
|
15320
|
+
checkQueue();
|
|
15321
|
+
});
|
|
15322
|
+
}
|
|
15323
|
+
// 将请求加入队列
|
|
15324
|
+
return new Promise((resolve, reject) => {
|
|
15325
|
+
this.screenshotQueue.push({ resolve: () => {
|
|
15326
|
+
this.takeScreenshotWithModernScreenshot(element).then(resolve).catch(reject);
|
|
15327
|
+
}, reject });
|
|
15328
|
+
// 启动队列处理(如果还没启动)
|
|
15329
|
+
if (!this.isProcessingQueue) {
|
|
15330
|
+
this.processScreenshotQueue();
|
|
15331
|
+
}
|
|
15332
|
+
});
|
|
15277
15333
|
}
|
|
15278
15334
|
this.isScreenshotInProgress = true;
|
|
15279
15335
|
if (!this.options.silentMode) {
|
|
@@ -15485,20 +15541,38 @@ class ScreenshotManager {
|
|
|
15485
15541
|
if (rect.width === 0 || rect.height === 0) {
|
|
15486
15542
|
throw new Error('元素尺寸为 0,无法截图');
|
|
15487
15543
|
}
|
|
15488
|
-
//
|
|
15489
|
-
//
|
|
15490
|
-
|
|
15491
|
-
|
|
15492
|
-
|
|
15544
|
+
// Worker 数量配置:智能计算或使用用户配置
|
|
15545
|
+
// workerNumber > 0 会启用 Worker 模式,截图处理在后台线程执行,不会阻塞主线程 UI
|
|
15546
|
+
// 如果用户指定了 workerNumber,直接使用;否则根据设备性能自动计算
|
|
15547
|
+
let workerNumber;
|
|
15548
|
+
if (this.options.workerNumber !== undefined && this.options.workerNumber > 0) {
|
|
15549
|
+
// 用户明确指定了 workerNumber
|
|
15550
|
+
workerNumber = this.options.workerNumber;
|
|
15551
|
+
}
|
|
15552
|
+
else {
|
|
15553
|
+
// 自动计算 workerNumber
|
|
15554
|
+
const cpuCores = navigator.hardwareConcurrency || 4; // 默认假设 4 核
|
|
15555
|
+
if (isMobile || isLowEndDevice) {
|
|
15556
|
+
// 移动设备/低端设备:使用 1 个 Worker(避免内存压力)
|
|
15557
|
+
workerNumber = 1;
|
|
15493
15558
|
}
|
|
15494
|
-
|
|
15495
|
-
//
|
|
15559
|
+
else if (cpuCores >= 8) {
|
|
15560
|
+
// 高性能设备(8核及以上):使用 3-4 个 Worker(充分利用多核)
|
|
15561
|
+
// 但根据截图间隔调整:频繁截图(间隔 < 2秒)时使用更多 Worker
|
|
15562
|
+
const isFrequentScreenshot = this.options.interval < 2000;
|
|
15563
|
+
workerNumber = isFrequentScreenshot ? Math.min(4, Math.floor(cpuCores / 2)) : 3;
|
|
15564
|
+
}
|
|
15565
|
+
else if (cpuCores >= 4) {
|
|
15566
|
+
// 中等性能设备(4-7核):使用 2 个 Worker
|
|
15567
|
+
workerNumber = 2;
|
|
15568
|
+
}
|
|
15569
|
+
else {
|
|
15570
|
+
// 低性能设备(< 4核):使用 1 个 Worker
|
|
15571
|
+
workerNumber = 1;
|
|
15496
15572
|
}
|
|
15497
|
-
this.screenshotContext = null;
|
|
15498
15573
|
}
|
|
15499
|
-
//
|
|
15500
|
-
|
|
15501
|
-
const workerNumber = isMobile || isLowEndDevice ? 1 : 2;
|
|
15574
|
+
// 限制 workerNumber 范围:1-8(避免过多 Worker 导致资源竞争)
|
|
15575
|
+
workerNumber = Math.max(1, Math.min(8, workerNumber));
|
|
15502
15576
|
// 构建 createContext 配置
|
|
15503
15577
|
// 参考: https://github.com/qq15725/modern-screenshot/blob/main/src/options.ts
|
|
15504
15578
|
const contextOptions = {
|
|
@@ -15515,7 +15589,28 @@ class ScreenshotManager {
|
|
|
15515
15589
|
// 参考: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/canvas#maximum_canvas_size
|
|
15516
15590
|
// 大多数浏览器限制为 16,777,216 像素(4096x4096),这里设置为更保守的值
|
|
15517
15591
|
maximumCanvasSize: 16777216, // 16M 像素(约 4096x4096)
|
|
15592
|
+
// 使用 modern-screenshot 内置的 timeout(更可靠)
|
|
15593
|
+
timeout: Math.max(this.options.interval * 6, 5000),
|
|
15518
15594
|
};
|
|
15595
|
+
// 限制 timeout 最多 15 秒
|
|
15596
|
+
contextOptions.timeout = Math.min(contextOptions.timeout, 15000);
|
|
15597
|
+
// 如果用户指定了 workerUrl,使用指定的 URL
|
|
15598
|
+
// 否则让 modern-screenshot 自动处理(它会尝试从 node_modules 或 CDN 加载)
|
|
15599
|
+
// 注意:在某些构建工具(如 Rollup)中,可能需要手动指定 workerUrl
|
|
15600
|
+
if (this.options.workerUrl) {
|
|
15601
|
+
contextOptions.workerUrl = this.options.workerUrl;
|
|
15602
|
+
if (!this.options.silentMode) {
|
|
15603
|
+
console.log(`📸 使用指定的 Worker URL: ${this.options.workerUrl}`);
|
|
15604
|
+
}
|
|
15605
|
+
}
|
|
15606
|
+
else {
|
|
15607
|
+
// 未指定 workerUrl 时,modern-screenshot 会自动处理
|
|
15608
|
+
// 但在某些构建环境中可能需要手动指定,可以使用 CDN 作为后备
|
|
15609
|
+
// 这里不设置 workerUrl,让 modern-screenshot 自己处理
|
|
15610
|
+
if (!this.options.silentMode) {
|
|
15611
|
+
console.log('📸 Worker URL 未指定,modern-screenshot 将自动处理');
|
|
15612
|
+
}
|
|
15613
|
+
}
|
|
15519
15614
|
// 对所有元素都设置尺寸限制(包括 document.body),避免截图过大
|
|
15520
15615
|
// 这样可以减少 base64 大小,提高性能
|
|
15521
15616
|
if (finalWidth && finalHeight) {
|
|
@@ -15544,69 +15639,99 @@ class ScreenshotManager {
|
|
|
15544
15639
|
// 如果未指定 scale,移动设备默认使用 0.7
|
|
15545
15640
|
contextOptions.scale = 0.7;
|
|
15546
15641
|
}
|
|
15547
|
-
//
|
|
15548
|
-
//
|
|
15549
|
-
|
|
15550
|
-
|
|
15551
|
-
|
|
15552
|
-
|
|
15553
|
-
|
|
15554
|
-
|
|
15555
|
-
|
|
15556
|
-
|
|
15557
|
-
|
|
15558
|
-
|
|
15559
|
-
|
|
15560
|
-
|
|
15561
|
-
|
|
15642
|
+
// 优化:复用 context,避免频繁创建和销毁(性能提升 20%+)
|
|
15643
|
+
// 只在元素变化或配置变化时重新创建 context
|
|
15644
|
+
const contextOptionsHash = JSON.stringify({
|
|
15645
|
+
workerNumber,
|
|
15646
|
+
quality: finalQuality,
|
|
15647
|
+
scale: contextOptions.scale,
|
|
15648
|
+
width: contextOptions.width,
|
|
15649
|
+
height: contextOptions.height,
|
|
15650
|
+
maximumCanvasSize: contextOptions.maximumCanvasSize,
|
|
15651
|
+
timeout: contextOptions.timeout
|
|
15652
|
+
});
|
|
15653
|
+
const needsRecreateContext = !this.screenshotContext ||
|
|
15654
|
+
this.contextElement !== element ||
|
|
15655
|
+
this.contextOptionsHash !== contextOptionsHash;
|
|
15656
|
+
if (needsRecreateContext) {
|
|
15657
|
+
if (!this.options.silentMode) {
|
|
15658
|
+
if (this.screenshotContext) {
|
|
15659
|
+
console.log('📸 检测到元素或配置变化,重新创建 context...');
|
|
15660
|
+
}
|
|
15661
|
+
else {
|
|
15662
|
+
console.log(`📸 Worker 模式: ${workerNumber} 个 Worker,质量: ${finalQuality.toFixed(2)},缩放: ${contextOptions.scale || 1}`);
|
|
15663
|
+
}
|
|
15562
15664
|
}
|
|
15563
|
-
|
|
15564
|
-
|
|
15565
|
-
|
|
15665
|
+
// 销毁旧 context
|
|
15666
|
+
if (this.screenshotContext) {
|
|
15667
|
+
try {
|
|
15668
|
+
destroyContext(this.screenshotContext);
|
|
15566
15669
|
}
|
|
15567
|
-
|
|
15568
|
-
|
|
15569
|
-
|
|
15570
|
-
|
|
15670
|
+
catch (e) {
|
|
15671
|
+
// 忽略清理错误
|
|
15672
|
+
}
|
|
15673
|
+
this.screenshotContext = null;
|
|
15674
|
+
}
|
|
15675
|
+
// 添加 progress 回调(可选,用于显示进度)
|
|
15676
|
+
if (!this.options.silentMode) {
|
|
15677
|
+
contextOptions.progress = (current, total) => {
|
|
15678
|
+
if (total > 0) {
|
|
15679
|
+
const percent = Math.round((current / total) * 100);
|
|
15680
|
+
if (percent % 25 === 0 || current === total) { // 每 25% 或完成时打印
|
|
15681
|
+
console.log(`📸 截图进度: ${current}/${total} (${percent}%)`);
|
|
15682
|
+
}
|
|
15683
|
+
}
|
|
15684
|
+
};
|
|
15685
|
+
}
|
|
15686
|
+
// 添加重试机制创建新 context
|
|
15687
|
+
let retries = 0;
|
|
15688
|
+
const maxRetries = this.options.maxRetries || 2;
|
|
15689
|
+
while (retries <= maxRetries) {
|
|
15690
|
+
try {
|
|
15691
|
+
this.screenshotContext = await createContext$1(element, contextOptions);
|
|
15692
|
+
this.contextElement = element;
|
|
15693
|
+
this.contextOptionsHash = contextOptionsHash;
|
|
15694
|
+
break;
|
|
15695
|
+
}
|
|
15696
|
+
catch (error) {
|
|
15697
|
+
if (retries === maxRetries) {
|
|
15698
|
+
throw new Error(`创建截图上下文失败(已重试 ${maxRetries} 次): ${error instanceof Error ? error.message : String(error)}`);
|
|
15699
|
+
}
|
|
15700
|
+
retries++;
|
|
15701
|
+
const delay = 1000 * retries; // 递增延迟:1秒、2秒...
|
|
15702
|
+
if (!this.options.silentMode) {
|
|
15703
|
+
console.warn(`📸 ⚠️ 创建截图上下文失败,${delay}ms 后重试 (${retries}/${maxRetries})...`);
|
|
15704
|
+
}
|
|
15705
|
+
await new Promise(resolve => setTimeout(resolve, delay));
|
|
15571
15706
|
}
|
|
15572
|
-
|
|
15707
|
+
}
|
|
15708
|
+
}
|
|
15709
|
+
else {
|
|
15710
|
+
if (!this.options.silentMode) {
|
|
15711
|
+
console.log('📸 复用现有 context(性能优化)');
|
|
15573
15712
|
}
|
|
15574
15713
|
}
|
|
15575
15714
|
try {
|
|
15576
15715
|
// 根据输出格式选择对应的 API,避免格式转换(性能优化)
|
|
15577
|
-
//
|
|
15578
|
-
const timeoutMs = 30000; // 30秒超时
|
|
15579
|
-
const timeoutPromise = new Promise((_, reject) => {
|
|
15580
|
-
setTimeout(() => {
|
|
15581
|
-
reject(new Error(`截图超时(${timeoutMs}ms),可能页面过大或 Worker 处理时间过长`));
|
|
15582
|
-
}, timeoutMs);
|
|
15583
|
-
});
|
|
15716
|
+
// 注意:timeout 已经在 createContext 时设置,modern-screenshot 内部会处理超时
|
|
15584
15717
|
let dataUrl;
|
|
15585
15718
|
const outputFormat = this.options.outputFormat || 'webp';
|
|
15586
15719
|
if (!this.options.silentMode) {
|
|
15587
15720
|
console.log(`📸 使用 ${outputFormat.toUpperCase()} 格式截图(直接输出,无需转换)...`);
|
|
15588
15721
|
}
|
|
15589
15722
|
// 根据输出格式选择对应的 API
|
|
15723
|
+
// modern-screenshot 内部已经处理了超时,不需要额外的 Promise.race
|
|
15590
15724
|
if (outputFormat === 'webp') {
|
|
15591
15725
|
// 使用 domToWebp,直接输出 WebP 格式,无需转换
|
|
15592
|
-
dataUrl = await
|
|
15593
|
-
domToWebp(this.screenshotContext),
|
|
15594
|
-
timeoutPromise
|
|
15595
|
-
]);
|
|
15726
|
+
dataUrl = await domToWebp(this.screenshotContext);
|
|
15596
15727
|
}
|
|
15597
15728
|
else if (outputFormat === 'jpeg') {
|
|
15598
15729
|
// 使用 domToJpeg,直接输出 JPEG 格式,无需转换
|
|
15599
|
-
dataUrl = await
|
|
15600
|
-
domToJpeg(this.screenshotContext),
|
|
15601
|
-
timeoutPromise
|
|
15602
|
-
]);
|
|
15730
|
+
dataUrl = await domToJpeg(this.screenshotContext);
|
|
15603
15731
|
}
|
|
15604
15732
|
else {
|
|
15605
15733
|
// 默认使用 domToPng
|
|
15606
|
-
dataUrl = await
|
|
15607
|
-
domToPng(this.screenshotContext),
|
|
15608
|
-
timeoutPromise
|
|
15609
|
-
]);
|
|
15734
|
+
dataUrl = await domToPng(this.screenshotContext);
|
|
15610
15735
|
}
|
|
15611
15736
|
// 验证截图结果
|
|
15612
15737
|
if (!dataUrl || dataUrl.length < 100) {
|
|
@@ -15633,37 +15758,11 @@ class ScreenshotManager {
|
|
|
15633
15758
|
throw error;
|
|
15634
15759
|
}
|
|
15635
15760
|
finally {
|
|
15636
|
-
//
|
|
15637
|
-
//
|
|
15638
|
-
|
|
15639
|
-
try {
|
|
15640
|
-
destroyContext(this.screenshotContext);
|
|
15641
|
-
if (!this.options.silentMode) {
|
|
15642
|
-
console.log('📸 ✅ modern-screenshot context 已清理');
|
|
15643
|
-
}
|
|
15644
|
-
}
|
|
15645
|
-
catch (e) {
|
|
15646
|
-
if (!this.options.silentMode) {
|
|
15647
|
-
console.warn('📸 ⚠️ 清理 context 失败:', e);
|
|
15648
|
-
}
|
|
15649
|
-
}
|
|
15650
|
-
finally {
|
|
15651
|
-
// 确保 context 引用被清除
|
|
15652
|
-
this.screenshotContext = null;
|
|
15653
|
-
}
|
|
15654
|
-
}
|
|
15761
|
+
// 优化:不复用 context 时才清理(性能优化)
|
|
15762
|
+
// 如果元素或配置没有变化,保留 context 以便下次复用
|
|
15763
|
+
// 这样可以避免频繁创建和销毁 Worker,提升性能 20%+
|
|
15655
15764
|
// 释放截图锁
|
|
15656
15765
|
this.isScreenshotInProgress = false;
|
|
15657
|
-
// 强制触发垃圾回收(如果可能)
|
|
15658
|
-
// 注意:这需要浏览器支持,不是所有浏览器都有效
|
|
15659
|
-
if (typeof window !== 'undefined' && window.gc && typeof window.gc === 'function') {
|
|
15660
|
-
try {
|
|
15661
|
-
window.gc();
|
|
15662
|
-
}
|
|
15663
|
-
catch {
|
|
15664
|
-
// 忽略 GC 错误
|
|
15665
|
-
}
|
|
15666
|
-
}
|
|
15667
15766
|
}
|
|
15668
15767
|
}
|
|
15669
15768
|
catch (error) {
|
|
@@ -15679,7 +15778,34 @@ class ScreenshotManager {
|
|
|
15679
15778
|
if (this.isScreenshotInProgress) {
|
|
15680
15779
|
this.isScreenshotInProgress = false;
|
|
15681
15780
|
}
|
|
15781
|
+
// 处理队列中的下一个请求
|
|
15782
|
+
this.processScreenshotQueue();
|
|
15783
|
+
}
|
|
15784
|
+
}
|
|
15785
|
+
/**
|
|
15786
|
+
* 处理截图队列
|
|
15787
|
+
*/
|
|
15788
|
+
async processScreenshotQueue() {
|
|
15789
|
+
if (this.isProcessingQueue || this.screenshotQueue.length === 0) {
|
|
15790
|
+
return;
|
|
15791
|
+
}
|
|
15792
|
+
this.isProcessingQueue = true;
|
|
15793
|
+
while (this.screenshotQueue.length > 0 && !this.isScreenshotInProgress) {
|
|
15794
|
+
const task = this.screenshotQueue.shift();
|
|
15795
|
+
if (task) {
|
|
15796
|
+
try {
|
|
15797
|
+
task.resolve();
|
|
15798
|
+
// 等待当前截图完成
|
|
15799
|
+
while (this.isScreenshotInProgress) {
|
|
15800
|
+
await new Promise(resolve => setTimeout(resolve, 50));
|
|
15801
|
+
}
|
|
15802
|
+
}
|
|
15803
|
+
catch (error) {
|
|
15804
|
+
task.reject(error instanceof Error ? error : new Error(String(error)));
|
|
15805
|
+
}
|
|
15806
|
+
}
|
|
15682
15807
|
}
|
|
15808
|
+
this.isProcessingQueue = false;
|
|
15683
15809
|
}
|
|
15684
15810
|
/**
|
|
15685
15811
|
* 预连接代理服务器(优化网络性能)
|
|
@@ -16553,6 +16679,18 @@ class ScreenshotManager {
|
|
|
16553
16679
|
* 清理资源
|
|
16554
16680
|
*/
|
|
16555
16681
|
destroy() {
|
|
16682
|
+
// 清理 modern-screenshot context
|
|
16683
|
+
if (this.screenshotContext) {
|
|
16684
|
+
try {
|
|
16685
|
+
destroyContext(this.screenshotContext);
|
|
16686
|
+
}
|
|
16687
|
+
catch (e) {
|
|
16688
|
+
// 忽略清理错误
|
|
16689
|
+
}
|
|
16690
|
+
this.screenshotContext = null;
|
|
16691
|
+
this.contextElement = null;
|
|
16692
|
+
this.contextOptionsHash = '';
|
|
16693
|
+
}
|
|
16556
16694
|
this.stopScreenshot();
|
|
16557
16695
|
if (this.worker) {
|
|
16558
16696
|
this.worker.terminate();
|