| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188 |
- import { Component, OnInit, OnDestroy, ViewChild, ElementRef, AfterViewChecked, Input } from '@angular/core';
- import { CommonModule } from '@angular/common';
- import { MatCardModule } from '@angular/material/card';
- import { MatButtonModule } from '@angular/material/button';
- import { MatIconModule } from '@angular/material/icon';
- import { MatSelectModule } from '@angular/material/select';
- import { MatFormFieldModule } from '@angular/material/form-field';
- import { MatCheckboxModule } from '@angular/material/checkbox';
- import { MatTooltipModule } from '@angular/material/tooltip';
- import { FormsModule } from '@angular/forms';
- import { Subscription } from 'rxjs';
- import { LogService } from '../services/log.service';
- import { SessionService } from '../services/session.service';
- import { AuthService } from '../services/auth.service';
-
- import { LogEntry } from '../models/log.model';
- import { Session } from '../models/session.model';
-
- @Component({
- selector: 'app-log-display',
- standalone: true,
- imports: [
- CommonModule,
- MatCardModule,
- MatButtonModule,
- MatIconModule,
- MatSelectModule,
- MatFormFieldModule,
- MatCheckboxModule,
- MatTooltipModule,
- FormsModule
- ],
- templateUrl: './log-display.component.html',
- styleUrl: './log-display.component.scss'
- })
- export class LogDisplayComponent implements OnInit, OnDestroy, AfterViewChecked {
- @Input() instanceId?: string; // 实例ID参数,用于过滤该实例的会话日志
-
- @ViewChild('logContent') private logContent!: ElementRef;
-
- allLogs: LogEntry[] = [];
- filteredLogs: LogEntry[] = [];
- availableSessions: Session[] = [];
-
- selectedLevel = 'all';
- selectedSessionId = 'all';
- autoScroll = true;
- isPaused = false;
-
- private subscriptions: Subscription = new Subscription();
- private shouldScroll = false;
-
- constructor(
- private logService: LogService,
- private sessionService: SessionService,
- private authService: AuthService
- ) {}
-
- ngOnInit() {
- // 订阅日志流
- this.subscriptions.add(
- this.logService.logStream$.subscribe(log => {
- if (!this.isPaused) {
- this.allLogs.push(log);
- this.applyFilters();
- this.shouldScroll = this.autoScroll;
- }
- })
- );
-
- // 订阅会话列表(用于过滤)- 使用BehaviorSubject避免重复请求
- this.subscriptions.add(
- this.sessionService.sessions$.subscribe(sessions => {
- this.availableSessions = sessions;
- // 如果有instanceId,过滤属于该实例的会话(移除实例过滤,直接使用所有会话)
- // 注意:instanceService已移除,不再支持实例过滤
- })
- );
-
- // 初始化一些示例日志
- this.addSampleLogs();
- }
-
- ngAfterViewChecked() {
- if (this.shouldScroll) {
- this.scrollToBottom();
- this.shouldScroll = false;
- }
- }
-
- ngOnDestroy() {
- this.subscriptions.unsubscribe();
- }
-
- private addSampleLogs() {
- // 添加一些示例日志
- const sampleLogs: LogEntry[] = [
- {
- id: '1',
- timestamp: new Date(),
- level: 'info',
- message: '日志系统已初始化',
- source: 'log-service'
- },
- {
- id: '2',
- timestamp: new Date(Date.now() - 60000),
- level: 'info',
- message: '连接到 opencode 服务',
- source: 'opencode-client'
- },
- {
- id: '3',
- timestamp: new Date(Date.now() - 30000),
- level: 'debug',
- message: '用户登录成功',
- sessionID: 'session-123',
- source: 'auth-service'
- }
- ];
-
- this.allLogs = [...sampleLogs, ...this.allLogs];
- this.applyFilters();
- }
-
- applyFilters() {
- this.filteredLogs = this.allLogs.filter(log => {
- // 级别过滤
- if (this.selectedLevel !== 'all' && log.level !== this.selectedLevel) {
- return false;
- }
-
- // 会话过滤
- if (this.selectedSessionId !== 'all') {
- if (!log.sessionID) return false;
- if (log.sessionID !== this.selectedSessionId) return false;
- }
-
- // 实例过滤(如果设置了instanceId)
-
-
- return true;
- });
-
- // 按时间排序(最新的在前面)
- this.filteredLogs.sort((a, b) => b.timestamp.getTime() - a.timestamp.getTime());
- }
-
- getLevelLabel(level: string): string {
- const labels: { [key: string]: string } = {
- 'info': '信息',
- 'warn': '警告',
- 'error': '错误',
- 'debug': '调试'
- };
- return labels[level] || level;
- }
-
- getSessionTitle(sessionId: string): string {
- const session = this.availableSessions.find(s => s.id === sessionId);
- return session ? session.title : sessionId;
- }
-
- toggleAutoScroll() {
- this.autoScroll = !this.autoScroll;
- if (this.autoScroll) {
- this.shouldScroll = true;
- }
- }
-
- togglePause() {
- this.isPaused = !this.isPaused;
- }
-
- clearLogs() {
- this.allLogs = [];
- this.filteredLogs = [];
- }
-
- private scrollToBottom() {
- try {
- this.logContent.nativeElement.scrollTop =
- this.logContent.nativeElement.scrollHeight;
- } catch (err) {
- console.error('滚动失败:', err);
- }
- }
- }
|