diff --git a/src/app/elements/connect/connect-dialog/advanced-option/advanced-option.component.ts b/src/app/elements/connect/connect-dialog/advanced-option/advanced-option.component.ts index 483050fa1..4cbdcfdd7 100644 --- a/src/app/elements/connect/connect-dialog/advanced-option/advanced-option.component.ts +++ b/src/app/elements/connect/connect-dialog/advanced-option/advanced-option.component.ts @@ -212,9 +212,6 @@ export class ElementAdvancedOptionComponent implements OnChanges, OnInit { this.advancedOptions = this.allOptions.filter(i => !i.hidden()); this.isShowAdvancedOption = this.advancedOptions.length > 0; - - console.log('advancedOptions', this.advancedOptions); - console.log('isShowAdvancedOption', this.isShowAdvancedOption); } onChange() { diff --git a/src/app/elements/left-bar/left-bar.component.ts b/src/app/elements/left-bar/left-bar.component.ts index a7eedbe13..8e295b894 100644 --- a/src/app/elements/left-bar/left-bar.component.ts +++ b/src/app/elements/left-bar/left-bar.component.ts @@ -82,7 +82,6 @@ export class ElementLeftBarComponent implements OnInit, AfterViewInit, OnDestroy this.resizeObserver = new ResizeObserver(entries => { for (const entry of entries) { const width = entry.contentRect.width; - console.log('Sidebar width changed:', width); // 这里你可以触发你需要的逻辑 } }); diff --git a/src/app/elements/replay/guacamole/guacamole.component.html b/src/app/elements/replay/guacamole/guacamole.component.html index bf3e1a3a5..317b0e42d 100644 --- a/src/app/elements/replay/guacamole/guacamole.component.html +++ b/src/app/elements/replay/guacamole/guacamole.component.html @@ -1,8 +1,17 @@ + +
+ +
+
+ +
+
+
- +

{{ 'Redirecting' | translate }}...

@@ -43,12 +52,12 @@
-
+
- -
@@ -60,6 +69,7 @@ id="position-slider" [(ngModel)]="percent" [max]="max" + [disabled]="isLoading || isSeeking" (mouseup)="runFrom()" class="progress-slider">
diff --git a/src/app/elements/replay/guacamole/guacamole.component.ts b/src/app/elements/replay/guacamole/guacamole.component.ts index cde18f31d..095d66927 100644 --- a/src/app/elements/replay/guacamole/guacamole.component.ts +++ b/src/app/elements/replay/guacamole/guacamole.component.ts @@ -25,11 +25,13 @@ import { debounceTime, distinctUntilChanged } from 'rxjs/operators'; export class ElementReplayGuacamoleComponent implements OnInit, OnChanges, AfterViewInit { isPlaying = false; isSeeking = false; + isLoading = false; recording: any; playerRef: any; displayRef: any; screenRef: any; recordingDisplay: any; + resizeObserver: any; max = 100; percent = 0; duration = '00:00'; @@ -122,6 +124,18 @@ export class ElementReplayGuacamoleComponent implements OnInit, OnChanges, After } }); + // 监听容器尺寸变化,避免侧栏展开/收起或布局变化时未触发 window.resize 的情况 + if ('ResizeObserver' in window && this.screenRef) { + this.resizeObserver = new (window as any).ResizeObserver(() => { + this.applyScaleWithRetry(100); + }); + try { + this.resizeObserver.observe(this.screenRef); + } catch (e) { + // 忽略观察器异常 + } + } + if (this.isMobile()) { this.initTouchEvents(); } @@ -131,13 +145,13 @@ export class ElementReplayGuacamoleComponent implements OnInit, OnChanges, After } initRecording() { - // 先注册事件,避免在 connect 之后事件被瞬间触发而丢失 this.recording.onload = () => { this.applyScaleWithRetry(200); }; this.recording.onplay = () => { this.isPlaying = true; + this.isLoading = false; this.applyScaleWithRetry(100); }; @@ -182,32 +196,36 @@ export class ElementReplayGuacamoleComponent implements OnInit, OnChanges, After } }, 1000); - // 连接录制流 this.recording.connect(''); - - // 立即尝试播放,不等待 onload,增强大文件/慢速网络下的起播速度 this.safeAutoplayWithRetry(); } private safeAutoplayWithRetry(maxRetry: number = 5, delayMs: number = 500) { let attempts = 0; + this.isLoading = true; + const tryPlay = () => { - if (!this.recording) { - return; - } + if (!this.recording) return; + try { if (!this.recording.isPlaying()) { this.recording.play(); } } catch (e) { - console.error(e) + console.error(e); } if (this.recording && !this.recording.isPlaying() && attempts < maxRetry) { attempts++; setTimeout(tryPlay, delayMs); + } else if (this.recording && this.recording.isPlaying()) { + this.isLoading = false; + } else if (attempts >= maxRetry) { + // 超过最大重试次数后,允许用户交互 + this.isLoading = false; } }; + tryPlay(); } @@ -265,11 +283,19 @@ export class ElementReplayGuacamoleComponent implements OnInit, OnChanges, After } this.interval = null; + if (this.resizeObserver) { + try { + this.resizeObserver.disconnect(); + } catch (e) {} + this.resizeObserver = null; + } + this.playerRef = null; this.displayRef = null; this.screenRef = null; this.isPlaying = false; this.isSeeking = false; + this.isLoading = false; this.max = 100; this.percent = 0; this.duration = '00:00'; @@ -305,7 +331,8 @@ export class ElementReplayGuacamoleComponent implements OnInit, OnChanges, After const widthScale = availableWidth / width; const heightScale = availableHeight / height; - scale = Math.min(widthScale, heightScale, 1); + // 允许放大以自适应容器 + scale = Math.min(widthScale, heightScale); } return scale; } @@ -421,6 +448,7 @@ export class ElementReplayGuacamoleComponent implements OnInit, OnChanges, After private initTouchEvents() { const screen = document.getElementById('screen'); + if (!screen) { return; } @@ -473,5 +501,7 @@ export class ElementReplayGuacamoleComponent implements OnInit, OnChanges, After toggleCommands() { this.commandsCollapsed = !this.commandsCollapsed; + // 面板展开/收起后强制尝试缩放 + this.applyScaleWithRetry(100); } } diff --git a/src/app/elements/replay/parts/parts.component.ts b/src/app/elements/replay/parts/parts.component.ts index 1aa589a2f..e2619f738 100644 --- a/src/app/elements/replay/parts/parts.component.ts +++ b/src/app/elements/replay/parts/parts.component.ts @@ -1,6 +1,5 @@ import { Replay } from '@app/model'; import { ActivatedRoute } from '@angular/router'; -import { TranslateService } from '@ngx-translate/core'; import { HttpService, I18nService, LogService } from '@app/services'; import { ChangeDetectorRef, Component, Input, OnInit, HostListener } from '@angular/core'; @@ -50,7 +49,6 @@ export class ElementsPartsComponent implements OnInit { private _http: HttpService, private _logger: LogService, private route: ActivatedRoute, - private _translate: TranslateService, private cdRef: ChangeDetectorRef ) {} @@ -199,16 +197,6 @@ export class ElementsPartsComponent implements OnInit { let isFirstPush = true; for (const item of file) { - // 先拿第一个保证有东西可以播出来 - isFirstPush = await this.fetchSection(file[0], sessionId, isFirstPush); - - // 其他的放到异步任务中 - Promise.resolve().then(async() => { - for(const item of file.slice(1)) { - await this.fetchSection(item, sessionId, isFirstPush); - } - }) - isFirstPush = await this.fetchSection(item, sessionId, isFirstPush); } }