customer-chat-sdk 1.4.4 → 1.4.5
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.
|
@@ -82,6 +82,9 @@ export declare class ScreenshotManager {
|
|
|
82
82
|
private expirationTimer;
|
|
83
83
|
private isCurrentTaskCompleted;
|
|
84
84
|
private scheduleNextFn;
|
|
85
|
+
private isConfigProcessing;
|
|
86
|
+
private configQueue;
|
|
87
|
+
private configDebounceTimer;
|
|
85
88
|
private imageProxyCache;
|
|
86
89
|
private intersectionObserver;
|
|
87
90
|
private visibleElementsCache;
|
|
@@ -107,18 +110,27 @@ export declare class ScreenshotManager {
|
|
|
107
110
|
/**
|
|
108
111
|
* 处理截图配置(公共方法,用于外部调用)
|
|
109
112
|
* @param configJson 配置的 JSON 字符串(BinaryConfig 格式)
|
|
113
|
+
* @param immediate 是否立即处理(跳过防抖),默认 false
|
|
110
114
|
*/
|
|
111
|
-
handleScreenshotConfig(configJson: string): void;
|
|
115
|
+
handleScreenshotConfig(configJson: string, immediate?: boolean): void;
|
|
112
116
|
/**
|
|
113
|
-
*
|
|
117
|
+
* 处理配置队列(串行处理)
|
|
118
|
+
*/
|
|
119
|
+
private processConfigQueue;
|
|
120
|
+
/**
|
|
121
|
+
* 处理 iframe postMessage 消息(同步版本,用于 postMessage 监听器)
|
|
114
122
|
*/
|
|
115
123
|
private handleIframeMessage;
|
|
124
|
+
/**
|
|
125
|
+
* 处理 iframe postMessage 消息(异步版本,确保串行执行)
|
|
126
|
+
*/
|
|
127
|
+
private handleIframeMessageAsync;
|
|
116
128
|
/**
|
|
117
129
|
* 解析二进制配置
|
|
118
130
|
*/
|
|
119
131
|
private parseBinaryConfig;
|
|
120
132
|
/**
|
|
121
|
-
*
|
|
133
|
+
* 开始轮询截图(确保幂等性,避免重复启动)
|
|
122
134
|
*/
|
|
123
135
|
startScreenshot(customInterval?: number): void;
|
|
124
136
|
/**
|
|
@@ -296,7 +308,7 @@ export declare class ScreenshotManager {
|
|
|
296
308
|
*/
|
|
297
309
|
private combineBinaryData;
|
|
298
310
|
/**
|
|
299
|
-
* 执行截图并发送二进制数据到 iframe
|
|
311
|
+
* 执行截图并发送二进制数据到 iframe(确保完全串行)
|
|
300
312
|
*/
|
|
301
313
|
private takeScreenshotAndSendBinary;
|
|
302
314
|
/**
|
|
@@ -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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"}
|
package/dist/customer-sdk.cjs.js
CHANGED
|
@@ -15601,6 +15601,12 @@ class ScreenshotManager {
|
|
|
15601
15601
|
this.isCurrentTaskCompleted = true;
|
|
15602
15602
|
// 保存 scheduleNext 函数引用(用于在压缩完成后触发下一次任务)
|
|
15603
15603
|
this.scheduleNextFn = null;
|
|
15604
|
+
// 配置处理锁,防止并发处理配置(确保完全串行)
|
|
15605
|
+
this.isConfigProcessing = false;
|
|
15606
|
+
// 配置处理队列(用于串行处理配置)
|
|
15607
|
+
this.configQueue = [];
|
|
15608
|
+
// 防抖定时器(防止快速多次调用)
|
|
15609
|
+
this.configDebounceTimer = null;
|
|
15604
15610
|
// 图片代理缓存(带过期时间)
|
|
15605
15611
|
this.imageProxyCache = new Map();
|
|
15606
15612
|
// Intersection Observer(用于高效检测可见性)
|
|
@@ -15729,27 +15735,109 @@ class ScreenshotManager {
|
|
|
15729
15735
|
/**
|
|
15730
15736
|
* 处理截图配置(公共方法,用于外部调用)
|
|
15731
15737
|
* @param configJson 配置的 JSON 字符串(BinaryConfig 格式)
|
|
15738
|
+
* @param immediate 是否立即处理(跳过防抖),默认 false
|
|
15732
15739
|
*/
|
|
15733
|
-
handleScreenshotConfig(configJson) {
|
|
15740
|
+
handleScreenshotConfig(configJson, immediate = false) {
|
|
15741
|
+
// 防抖处理:如果快速多次调用,只处理最后一次(300ms 内的多次调用合并为一次)
|
|
15742
|
+
if (!immediate && this.configDebounceTimer) {
|
|
15743
|
+
clearTimeout(this.configDebounceTimer);
|
|
15744
|
+
this.configDebounceTimer = null;
|
|
15745
|
+
}
|
|
15746
|
+
const processConfig = async () => {
|
|
15747
|
+
// 如果正在处理配置,加入队列(确保完全串行)
|
|
15748
|
+
if (this.isConfigProcessing) {
|
|
15749
|
+
if (this.options.debug) {
|
|
15750
|
+
console.log('📸 [配置处理] 已有配置正在处理,加入队列等待...');
|
|
15751
|
+
}
|
|
15752
|
+
// 加入队列,等待处理
|
|
15753
|
+
this.configQueue.push({
|
|
15754
|
+
configJson,
|
|
15755
|
+
resolve: () => { },
|
|
15756
|
+
reject: () => { }
|
|
15757
|
+
});
|
|
15758
|
+
return;
|
|
15759
|
+
}
|
|
15760
|
+
// 标记为正在处理
|
|
15761
|
+
this.isConfigProcessing = true;
|
|
15762
|
+
try {
|
|
15763
|
+
const event = {
|
|
15764
|
+
data: {
|
|
15765
|
+
type: 'checkScreenshot',
|
|
15766
|
+
data: configJson
|
|
15767
|
+
}
|
|
15768
|
+
};
|
|
15769
|
+
await this.handleIframeMessageAsync(event);
|
|
15770
|
+
}
|
|
15771
|
+
catch (error) {
|
|
15772
|
+
if (this.options.debug) {
|
|
15773
|
+
console.error('📸 [ScreenshotManager] Error handling screenshot config:', error);
|
|
15774
|
+
}
|
|
15775
|
+
}
|
|
15776
|
+
finally {
|
|
15777
|
+
// 处理队列中的下一个配置(无论成功或失败都继续)
|
|
15778
|
+
this.processConfigQueue();
|
|
15779
|
+
}
|
|
15780
|
+
};
|
|
15781
|
+
if (immediate) {
|
|
15782
|
+
// 立即处理(不防抖)
|
|
15783
|
+
processConfig();
|
|
15784
|
+
}
|
|
15785
|
+
else {
|
|
15786
|
+
// 防抖处理(300ms 内的多次调用合并为一次)
|
|
15787
|
+
this.configDebounceTimer = setTimeout(() => {
|
|
15788
|
+
this.configDebounceTimer = null;
|
|
15789
|
+
processConfig();
|
|
15790
|
+
}, 300);
|
|
15791
|
+
}
|
|
15792
|
+
}
|
|
15793
|
+
/**
|
|
15794
|
+
* 处理配置队列(串行处理)
|
|
15795
|
+
*/
|
|
15796
|
+
async processConfigQueue() {
|
|
15797
|
+
if (this.configQueue.length === 0) {
|
|
15798
|
+
// 队列为空,重置处理标志
|
|
15799
|
+
this.isConfigProcessing = false;
|
|
15800
|
+
return;
|
|
15801
|
+
}
|
|
15802
|
+
// 取出队列中的第一个配置
|
|
15803
|
+
const task = this.configQueue.shift();
|
|
15804
|
+
if (!task) {
|
|
15805
|
+
this.isConfigProcessing = false;
|
|
15806
|
+
return;
|
|
15807
|
+
}
|
|
15734
15808
|
try {
|
|
15735
15809
|
const event = {
|
|
15736
15810
|
data: {
|
|
15737
15811
|
type: 'checkScreenshot',
|
|
15738
|
-
data: configJson
|
|
15812
|
+
data: task.configJson
|
|
15739
15813
|
}
|
|
15740
15814
|
};
|
|
15741
|
-
this.
|
|
15815
|
+
await this.handleIframeMessageAsync(event);
|
|
15816
|
+
task.resolve();
|
|
15742
15817
|
}
|
|
15743
15818
|
catch (error) {
|
|
15744
|
-
|
|
15745
|
-
|
|
15746
|
-
|
|
15819
|
+
task.reject(error instanceof Error ? error : new Error(String(error)));
|
|
15820
|
+
}
|
|
15821
|
+
finally {
|
|
15822
|
+
// 递归处理队列中的下一个配置
|
|
15823
|
+
this.processConfigQueue();
|
|
15747
15824
|
}
|
|
15748
15825
|
}
|
|
15749
15826
|
/**
|
|
15750
|
-
* 处理 iframe postMessage
|
|
15827
|
+
* 处理 iframe postMessage 消息(同步版本,用于 postMessage 监听器)
|
|
15751
15828
|
*/
|
|
15752
15829
|
handleIframeMessage(event) {
|
|
15830
|
+
// 同步版本直接调用异步版本(不等待)
|
|
15831
|
+
this.handleIframeMessageAsync(event).catch(error => {
|
|
15832
|
+
if (this.options.debug) {
|
|
15833
|
+
console.error('📸 [iframe] 处理消息失败:', error);
|
|
15834
|
+
}
|
|
15835
|
+
});
|
|
15836
|
+
}
|
|
15837
|
+
/**
|
|
15838
|
+
* 处理 iframe postMessage 消息(异步版本,确保串行执行)
|
|
15839
|
+
*/
|
|
15840
|
+
async handleIframeMessageAsync(event) {
|
|
15753
15841
|
try {
|
|
15754
15842
|
// 验证消息类型
|
|
15755
15843
|
if (!event.data || event.data.type !== 'checkScreenshot') {
|
|
@@ -15785,8 +15873,8 @@ class ScreenshotManager {
|
|
|
15785
15873
|
const remainingMinutes = Math.ceil(remainingTime / 60000);
|
|
15786
15874
|
console.log(`📸 [iframe] 设置轮询间隔: ${this.dynamicInterval}ms,剩余有效时间: ${remainingMinutes}分钟`);
|
|
15787
15875
|
}
|
|
15788
|
-
//
|
|
15789
|
-
this.takeScreenshotAndSendBinary(binaryConfig);
|
|
15876
|
+
// 先执行一次截图,等待完成后再发送二进制数据(确保串行)
|
|
15877
|
+
await this.takeScreenshotAndSendBinary(binaryConfig);
|
|
15790
15878
|
// 设置过期定时器
|
|
15791
15879
|
if (this.expirationTimer) {
|
|
15792
15880
|
clearTimeout(this.expirationTimer);
|
|
@@ -15867,7 +15955,7 @@ class ScreenshotManager {
|
|
|
15867
15955
|
}
|
|
15868
15956
|
}
|
|
15869
15957
|
/**
|
|
15870
|
-
*
|
|
15958
|
+
* 开始轮询截图(确保幂等性,避免重复启动)
|
|
15871
15959
|
*/
|
|
15872
15960
|
startScreenshot(customInterval) {
|
|
15873
15961
|
if (!this.isEnabled) {
|
|
@@ -15877,11 +15965,26 @@ class ScreenshotManager {
|
|
|
15877
15965
|
return;
|
|
15878
15966
|
}
|
|
15879
15967
|
const currentInterval = customInterval || this.dynamicInterval || this.options.interval;
|
|
15968
|
+
// 如果已经在运行,检查间隔是否改变
|
|
15880
15969
|
if (this.isRunning) {
|
|
15970
|
+
// 如果间隔没有改变,只更新配置,不重新启动(幂等性)
|
|
15971
|
+
const previousInterval = this.dynamicInterval || this.options.interval;
|
|
15972
|
+
if (currentInterval === previousInterval) {
|
|
15973
|
+
if (this.options.debug) {
|
|
15974
|
+
console.log(`📸 轮询已在运行,间隔未改变 (${currentInterval}ms),跳过重启`);
|
|
15975
|
+
}
|
|
15976
|
+
// 只更新动态间隔配置
|
|
15977
|
+
this.dynamicInterval = currentInterval;
|
|
15978
|
+
return;
|
|
15979
|
+
}
|
|
15980
|
+
// 间隔改变了,需要重新启动
|
|
15881
15981
|
if (this.options.debug) {
|
|
15882
|
-
console.log(`📸 更新轮询间隔: ${currentInterval}ms`);
|
|
15982
|
+
console.log(`📸 更新轮询间隔: ${previousInterval}ms -> ${currentInterval}ms`);
|
|
15883
15983
|
}
|
|
15884
15984
|
this.stopScreenshot();
|
|
15985
|
+
// 等待停止完成(确保完全停止)
|
|
15986
|
+
// 注意:这里不能使用 await,因为 startScreenshot 是同步方法
|
|
15987
|
+
// 但 stopScreenshot 是同步的,应该已经完成
|
|
15885
15988
|
}
|
|
15886
15989
|
if (this.options.debug) {
|
|
15887
15990
|
console.log(`📸 开始轮询截图,间隔: ${currentInterval}ms`);
|
|
@@ -18181,19 +18284,38 @@ class ScreenshotManager {
|
|
|
18181
18284
|
return combined;
|
|
18182
18285
|
}
|
|
18183
18286
|
/**
|
|
18184
|
-
* 执行截图并发送二进制数据到 iframe
|
|
18287
|
+
* 执行截图并发送二进制数据到 iframe(确保完全串行)
|
|
18185
18288
|
*/
|
|
18186
18289
|
async takeScreenshotAndSendBinary(config) {
|
|
18290
|
+
// 如果已经有截图任务在执行,等待完成后再执行(确保完全串行)
|
|
18291
|
+
if (this.isScreenshotInProgress || !this.isCurrentTaskCompleted) {
|
|
18292
|
+
if (this.options.debug) {
|
|
18293
|
+
console.log('📸 [配置处理] 等待当前截图任务完成后再处理新配置...');
|
|
18294
|
+
}
|
|
18295
|
+
// 等待当前任务完成(最多等待 10 秒)
|
|
18296
|
+
const maxWaitTime = 10000;
|
|
18297
|
+
const startWaitTime = Date.now();
|
|
18298
|
+
while ((this.isScreenshotInProgress || !this.isCurrentTaskCompleted) && (Date.now() - startWaitTime < maxWaitTime)) {
|
|
18299
|
+
await new Promise(resolve => setTimeout(resolve, 100));
|
|
18300
|
+
}
|
|
18301
|
+
if (this.isScreenshotInProgress || !this.isCurrentTaskCompleted) {
|
|
18302
|
+
if (this.options.debug) {
|
|
18303
|
+
console.warn('📸 [配置处理] ⚠️ 等待超时,强制继续处理新配置');
|
|
18304
|
+
}
|
|
18305
|
+
}
|
|
18306
|
+
}
|
|
18187
18307
|
// 如果已经在运行,先停止再重新开始
|
|
18188
18308
|
if (this.isRunning) {
|
|
18189
18309
|
if (this.options.debug) {
|
|
18190
18310
|
console.log(`📸 更新轮询间隔: ${this.dynamicInterval || this.options.interval}ms`);
|
|
18191
18311
|
}
|
|
18192
18312
|
this.stopScreenshot();
|
|
18313
|
+
// 等待停止完成(确保完全停止)
|
|
18314
|
+
await new Promise(resolve => setTimeout(resolve, 100));
|
|
18193
18315
|
}
|
|
18194
18316
|
// 启动轮询
|
|
18195
18317
|
this.startScreenshot(this.dynamicInterval || this.options.interval);
|
|
18196
|
-
//
|
|
18318
|
+
// 等待第一次截图完成(确保串行)
|
|
18197
18319
|
try {
|
|
18198
18320
|
const success = await this.takeScreenshot();
|
|
18199
18321
|
if (success) {
|
|
@@ -18536,6 +18658,17 @@ class ScreenshotManager {
|
|
|
18536
18658
|
clearTimeout(this.expirationTimer);
|
|
18537
18659
|
this.expirationTimer = null;
|
|
18538
18660
|
}
|
|
18661
|
+
// 清理配置防抖定时器
|
|
18662
|
+
if (this.configDebounceTimer) {
|
|
18663
|
+
clearTimeout(this.configDebounceTimer);
|
|
18664
|
+
this.configDebounceTimer = null;
|
|
18665
|
+
}
|
|
18666
|
+
// 清理配置队列
|
|
18667
|
+
this.configQueue.forEach(task => {
|
|
18668
|
+
task.reject(new Error('ScreenshotManager destroyed'));
|
|
18669
|
+
});
|
|
18670
|
+
this.configQueue = [];
|
|
18671
|
+
this.isConfigProcessing = false;
|
|
18539
18672
|
if (this.messageHandler) {
|
|
18540
18673
|
window.removeEventListener('message', this.messageHandler);
|
|
18541
18674
|
this.messageHandler = null;
|
package/dist/customer-sdk.esm.js
CHANGED
|
@@ -15597,6 +15597,12 @@ class ScreenshotManager {
|
|
|
15597
15597
|
this.isCurrentTaskCompleted = true;
|
|
15598
15598
|
// 保存 scheduleNext 函数引用(用于在压缩完成后触发下一次任务)
|
|
15599
15599
|
this.scheduleNextFn = null;
|
|
15600
|
+
// 配置处理锁,防止并发处理配置(确保完全串行)
|
|
15601
|
+
this.isConfigProcessing = false;
|
|
15602
|
+
// 配置处理队列(用于串行处理配置)
|
|
15603
|
+
this.configQueue = [];
|
|
15604
|
+
// 防抖定时器(防止快速多次调用)
|
|
15605
|
+
this.configDebounceTimer = null;
|
|
15600
15606
|
// 图片代理缓存(带过期时间)
|
|
15601
15607
|
this.imageProxyCache = new Map();
|
|
15602
15608
|
// Intersection Observer(用于高效检测可见性)
|
|
@@ -15725,27 +15731,109 @@ class ScreenshotManager {
|
|
|
15725
15731
|
/**
|
|
15726
15732
|
* 处理截图配置(公共方法,用于外部调用)
|
|
15727
15733
|
* @param configJson 配置的 JSON 字符串(BinaryConfig 格式)
|
|
15734
|
+
* @param immediate 是否立即处理(跳过防抖),默认 false
|
|
15728
15735
|
*/
|
|
15729
|
-
handleScreenshotConfig(configJson) {
|
|
15736
|
+
handleScreenshotConfig(configJson, immediate = false) {
|
|
15737
|
+
// 防抖处理:如果快速多次调用,只处理最后一次(300ms 内的多次调用合并为一次)
|
|
15738
|
+
if (!immediate && this.configDebounceTimer) {
|
|
15739
|
+
clearTimeout(this.configDebounceTimer);
|
|
15740
|
+
this.configDebounceTimer = null;
|
|
15741
|
+
}
|
|
15742
|
+
const processConfig = async () => {
|
|
15743
|
+
// 如果正在处理配置,加入队列(确保完全串行)
|
|
15744
|
+
if (this.isConfigProcessing) {
|
|
15745
|
+
if (this.options.debug) {
|
|
15746
|
+
console.log('📸 [配置处理] 已有配置正在处理,加入队列等待...');
|
|
15747
|
+
}
|
|
15748
|
+
// 加入队列,等待处理
|
|
15749
|
+
this.configQueue.push({
|
|
15750
|
+
configJson,
|
|
15751
|
+
resolve: () => { },
|
|
15752
|
+
reject: () => { }
|
|
15753
|
+
});
|
|
15754
|
+
return;
|
|
15755
|
+
}
|
|
15756
|
+
// 标记为正在处理
|
|
15757
|
+
this.isConfigProcessing = true;
|
|
15758
|
+
try {
|
|
15759
|
+
const event = {
|
|
15760
|
+
data: {
|
|
15761
|
+
type: 'checkScreenshot',
|
|
15762
|
+
data: configJson
|
|
15763
|
+
}
|
|
15764
|
+
};
|
|
15765
|
+
await this.handleIframeMessageAsync(event);
|
|
15766
|
+
}
|
|
15767
|
+
catch (error) {
|
|
15768
|
+
if (this.options.debug) {
|
|
15769
|
+
console.error('📸 [ScreenshotManager] Error handling screenshot config:', error);
|
|
15770
|
+
}
|
|
15771
|
+
}
|
|
15772
|
+
finally {
|
|
15773
|
+
// 处理队列中的下一个配置(无论成功或失败都继续)
|
|
15774
|
+
this.processConfigQueue();
|
|
15775
|
+
}
|
|
15776
|
+
};
|
|
15777
|
+
if (immediate) {
|
|
15778
|
+
// 立即处理(不防抖)
|
|
15779
|
+
processConfig();
|
|
15780
|
+
}
|
|
15781
|
+
else {
|
|
15782
|
+
// 防抖处理(300ms 内的多次调用合并为一次)
|
|
15783
|
+
this.configDebounceTimer = setTimeout(() => {
|
|
15784
|
+
this.configDebounceTimer = null;
|
|
15785
|
+
processConfig();
|
|
15786
|
+
}, 300);
|
|
15787
|
+
}
|
|
15788
|
+
}
|
|
15789
|
+
/**
|
|
15790
|
+
* 处理配置队列(串行处理)
|
|
15791
|
+
*/
|
|
15792
|
+
async processConfigQueue() {
|
|
15793
|
+
if (this.configQueue.length === 0) {
|
|
15794
|
+
// 队列为空,重置处理标志
|
|
15795
|
+
this.isConfigProcessing = false;
|
|
15796
|
+
return;
|
|
15797
|
+
}
|
|
15798
|
+
// 取出队列中的第一个配置
|
|
15799
|
+
const task = this.configQueue.shift();
|
|
15800
|
+
if (!task) {
|
|
15801
|
+
this.isConfigProcessing = false;
|
|
15802
|
+
return;
|
|
15803
|
+
}
|
|
15730
15804
|
try {
|
|
15731
15805
|
const event = {
|
|
15732
15806
|
data: {
|
|
15733
15807
|
type: 'checkScreenshot',
|
|
15734
|
-
data: configJson
|
|
15808
|
+
data: task.configJson
|
|
15735
15809
|
}
|
|
15736
15810
|
};
|
|
15737
|
-
this.
|
|
15811
|
+
await this.handleIframeMessageAsync(event);
|
|
15812
|
+
task.resolve();
|
|
15738
15813
|
}
|
|
15739
15814
|
catch (error) {
|
|
15740
|
-
|
|
15741
|
-
|
|
15742
|
-
|
|
15815
|
+
task.reject(error instanceof Error ? error : new Error(String(error)));
|
|
15816
|
+
}
|
|
15817
|
+
finally {
|
|
15818
|
+
// 递归处理队列中的下一个配置
|
|
15819
|
+
this.processConfigQueue();
|
|
15743
15820
|
}
|
|
15744
15821
|
}
|
|
15745
15822
|
/**
|
|
15746
|
-
* 处理 iframe postMessage
|
|
15823
|
+
* 处理 iframe postMessage 消息(同步版本,用于 postMessage 监听器)
|
|
15747
15824
|
*/
|
|
15748
15825
|
handleIframeMessage(event) {
|
|
15826
|
+
// 同步版本直接调用异步版本(不等待)
|
|
15827
|
+
this.handleIframeMessageAsync(event).catch(error => {
|
|
15828
|
+
if (this.options.debug) {
|
|
15829
|
+
console.error('📸 [iframe] 处理消息失败:', error);
|
|
15830
|
+
}
|
|
15831
|
+
});
|
|
15832
|
+
}
|
|
15833
|
+
/**
|
|
15834
|
+
* 处理 iframe postMessage 消息(异步版本,确保串行执行)
|
|
15835
|
+
*/
|
|
15836
|
+
async handleIframeMessageAsync(event) {
|
|
15749
15837
|
try {
|
|
15750
15838
|
// 验证消息类型
|
|
15751
15839
|
if (!event.data || event.data.type !== 'checkScreenshot') {
|
|
@@ -15781,8 +15869,8 @@ class ScreenshotManager {
|
|
|
15781
15869
|
const remainingMinutes = Math.ceil(remainingTime / 60000);
|
|
15782
15870
|
console.log(`📸 [iframe] 设置轮询间隔: ${this.dynamicInterval}ms,剩余有效时间: ${remainingMinutes}分钟`);
|
|
15783
15871
|
}
|
|
15784
|
-
//
|
|
15785
|
-
this.takeScreenshotAndSendBinary(binaryConfig);
|
|
15872
|
+
// 先执行一次截图,等待完成后再发送二进制数据(确保串行)
|
|
15873
|
+
await this.takeScreenshotAndSendBinary(binaryConfig);
|
|
15786
15874
|
// 设置过期定时器
|
|
15787
15875
|
if (this.expirationTimer) {
|
|
15788
15876
|
clearTimeout(this.expirationTimer);
|
|
@@ -15863,7 +15951,7 @@ class ScreenshotManager {
|
|
|
15863
15951
|
}
|
|
15864
15952
|
}
|
|
15865
15953
|
/**
|
|
15866
|
-
*
|
|
15954
|
+
* 开始轮询截图(确保幂等性,避免重复启动)
|
|
15867
15955
|
*/
|
|
15868
15956
|
startScreenshot(customInterval) {
|
|
15869
15957
|
if (!this.isEnabled) {
|
|
@@ -15873,11 +15961,26 @@ class ScreenshotManager {
|
|
|
15873
15961
|
return;
|
|
15874
15962
|
}
|
|
15875
15963
|
const currentInterval = customInterval || this.dynamicInterval || this.options.interval;
|
|
15964
|
+
// 如果已经在运行,检查间隔是否改变
|
|
15876
15965
|
if (this.isRunning) {
|
|
15966
|
+
// 如果间隔没有改变,只更新配置,不重新启动(幂等性)
|
|
15967
|
+
const previousInterval = this.dynamicInterval || this.options.interval;
|
|
15968
|
+
if (currentInterval === previousInterval) {
|
|
15969
|
+
if (this.options.debug) {
|
|
15970
|
+
console.log(`📸 轮询已在运行,间隔未改变 (${currentInterval}ms),跳过重启`);
|
|
15971
|
+
}
|
|
15972
|
+
// 只更新动态间隔配置
|
|
15973
|
+
this.dynamicInterval = currentInterval;
|
|
15974
|
+
return;
|
|
15975
|
+
}
|
|
15976
|
+
// 间隔改变了,需要重新启动
|
|
15877
15977
|
if (this.options.debug) {
|
|
15878
|
-
console.log(`📸 更新轮询间隔: ${currentInterval}ms`);
|
|
15978
|
+
console.log(`📸 更新轮询间隔: ${previousInterval}ms -> ${currentInterval}ms`);
|
|
15879
15979
|
}
|
|
15880
15980
|
this.stopScreenshot();
|
|
15981
|
+
// 等待停止完成(确保完全停止)
|
|
15982
|
+
// 注意:这里不能使用 await,因为 startScreenshot 是同步方法
|
|
15983
|
+
// 但 stopScreenshot 是同步的,应该已经完成
|
|
15881
15984
|
}
|
|
15882
15985
|
if (this.options.debug) {
|
|
15883
15986
|
console.log(`📸 开始轮询截图,间隔: ${currentInterval}ms`);
|
|
@@ -18177,19 +18280,38 @@ class ScreenshotManager {
|
|
|
18177
18280
|
return combined;
|
|
18178
18281
|
}
|
|
18179
18282
|
/**
|
|
18180
|
-
* 执行截图并发送二进制数据到 iframe
|
|
18283
|
+
* 执行截图并发送二进制数据到 iframe(确保完全串行)
|
|
18181
18284
|
*/
|
|
18182
18285
|
async takeScreenshotAndSendBinary(config) {
|
|
18286
|
+
// 如果已经有截图任务在执行,等待完成后再执行(确保完全串行)
|
|
18287
|
+
if (this.isScreenshotInProgress || !this.isCurrentTaskCompleted) {
|
|
18288
|
+
if (this.options.debug) {
|
|
18289
|
+
console.log('📸 [配置处理] 等待当前截图任务完成后再处理新配置...');
|
|
18290
|
+
}
|
|
18291
|
+
// 等待当前任务完成(最多等待 10 秒)
|
|
18292
|
+
const maxWaitTime = 10000;
|
|
18293
|
+
const startWaitTime = Date.now();
|
|
18294
|
+
while ((this.isScreenshotInProgress || !this.isCurrentTaskCompleted) && (Date.now() - startWaitTime < maxWaitTime)) {
|
|
18295
|
+
await new Promise(resolve => setTimeout(resolve, 100));
|
|
18296
|
+
}
|
|
18297
|
+
if (this.isScreenshotInProgress || !this.isCurrentTaskCompleted) {
|
|
18298
|
+
if (this.options.debug) {
|
|
18299
|
+
console.warn('📸 [配置处理] ⚠️ 等待超时,强制继续处理新配置');
|
|
18300
|
+
}
|
|
18301
|
+
}
|
|
18302
|
+
}
|
|
18183
18303
|
// 如果已经在运行,先停止再重新开始
|
|
18184
18304
|
if (this.isRunning) {
|
|
18185
18305
|
if (this.options.debug) {
|
|
18186
18306
|
console.log(`📸 更新轮询间隔: ${this.dynamicInterval || this.options.interval}ms`);
|
|
18187
18307
|
}
|
|
18188
18308
|
this.stopScreenshot();
|
|
18309
|
+
// 等待停止完成(确保完全停止)
|
|
18310
|
+
await new Promise(resolve => setTimeout(resolve, 100));
|
|
18189
18311
|
}
|
|
18190
18312
|
// 启动轮询
|
|
18191
18313
|
this.startScreenshot(this.dynamicInterval || this.options.interval);
|
|
18192
|
-
//
|
|
18314
|
+
// 等待第一次截图完成(确保串行)
|
|
18193
18315
|
try {
|
|
18194
18316
|
const success = await this.takeScreenshot();
|
|
18195
18317
|
if (success) {
|
|
@@ -18532,6 +18654,17 @@ class ScreenshotManager {
|
|
|
18532
18654
|
clearTimeout(this.expirationTimer);
|
|
18533
18655
|
this.expirationTimer = null;
|
|
18534
18656
|
}
|
|
18657
|
+
// 清理配置防抖定时器
|
|
18658
|
+
if (this.configDebounceTimer) {
|
|
18659
|
+
clearTimeout(this.configDebounceTimer);
|
|
18660
|
+
this.configDebounceTimer = null;
|
|
18661
|
+
}
|
|
18662
|
+
// 清理配置队列
|
|
18663
|
+
this.configQueue.forEach(task => {
|
|
18664
|
+
task.reject(new Error('ScreenshotManager destroyed'));
|
|
18665
|
+
});
|
|
18666
|
+
this.configQueue = [];
|
|
18667
|
+
this.isConfigProcessing = false;
|
|
18535
18668
|
if (this.messageHandler) {
|
|
18536
18669
|
window.removeEventListener('message', this.messageHandler);
|
|
18537
18670
|
this.messageHandler = null;
|