import { Component, Inject, OnInit, OnDestroy } from '@angular/core';
import { I18NService } from '@core';
import { ALAIN_I18N_TOKEN, SettingsService, User } from '@delon/theme';
import { LayoutDefaultOptions } from '@delon/theme/layout-default';
import { environment } from '@env/environment';
import { Observable, Subject, of } from 'rxjs';
import { delay, tap, finalize, catchError, takeUntil } from 'rxjs/operators';
import { CONSTANTS } from '../../shared/constants';
import { AiBotService, ChatMessage } from '../../shared/services/ai-bot.service';
@Component({
selector: 'layout-basic',
template: `
{{ 'menu.advanced.labels' | i18n }}
Apache HertzBeat (incubating) {{ version }}
Copyright © {{ currentYear }}
Apache HertzBeat
Licensed under the Apache License, Version 2.0
{{ message.content }}
{{ message.timestamp | date : 'HH:mm' }}
{{ currentBotMessage.content }}
{{ currentBotMessage.timestamp | date : 'HH:mm' }}
`,
styleUrls: ['./basic.component.less']
})
export class LayoutBasicComponent implements OnInit, OnDestroy {
options: LayoutDefaultOptions = {
logoExpanded: `./assets/brand_white.svg`,
logoCollapsed: `./assets/logo.svg`
};
avatar: string = `./assets/img/avatar.svg`;
searchToggleStatus = false;
showSettingDrawer = !environment.production;
version = CONSTANTS.VERSION;
currentYear = new Date().getFullYear();
get user(): User {
return this.settings.user;
}
get role(): string {
let userTmp = this.settings.user;
if (userTmp == undefined || userTmp.role == undefined) {
return this.i18nSvc.fanyi('app.role.admin');
} else {
let roles: string[] = JSON.parse(userTmp.role);
return roles.length > 0 ? roles[0] : '';
}
}
// AI Chatbot related properties
isChatbotOpen = false;
isChatbotMaximized = false;
chatMessages: ChatMessage[] = [];
currentMessage = '';
isLoading = false;
currentBotMessage: ChatMessage | null = null;
// For subscription cleanup
private destroy$ = new Subject();
constructor(
private settings: SettingsService,
@Inject(ALAIN_I18N_TOKEN) private i18nSvc: I18NService,
private aiBotService: AiBotService
) {}
ngOnInit(): void {
// Initialize welcome message
this.chatMessages.push({
content: this.i18nSvc.fanyi('ai.bot.greeting'),
isUser: false,
timestamp: new Date()
});
console.log('AI Chatbot initialization completed');
}
ngOnDestroy(): void {
// Cancel all subscriptions when component is destroyed
this.destroy$.next();
this.destroy$.complete();
}
toggleChatbot(): void {
this.isChatbotOpen = !this.isChatbotOpen;
if (!this.isChatbotOpen) {
setTimeout(() => {
this.isChatbotMaximized = false;
}, 300);
} else {
// Scroll to bottom when window opens
setTimeout(() => this.scrollToBottom(), 100);
}
console.log('Toggle chatbot status:', this.isChatbotOpen ? 'open' : 'closed');
}
toggleMaximize(): void {
setTimeout(() => {
this.isChatbotMaximized = !this.isChatbotMaximized;
console.log('Chat window maximize status:', this.isChatbotMaximized ? 'maximized' : 'normal');
}, 10);
}
sendMessage(): void {
if (!this.currentMessage.trim() || this.isLoading) return;
// Add user message
this.chatMessages.push({
content: this.currentMessage,
isUser: true,
timestamp: new Date()
});
const userMessage = this.currentMessage;
this.currentMessage = '';
this.isLoading = true;
this.currentBotMessage = null;
// Ensure scrolling to bottom after message display
setTimeout(() => this.scrollToBottom(), 100);
// Call AI service to get response
this.aiBotService
.sendMessage(userMessage)
.pipe(
takeUntil(this.destroy$),
finalize(() => {
this.isLoading = false;
// If there is a current message, add it to chat history
if (this.currentBotMessage) {
this.chatMessages.push({ ...this.currentBotMessage });
this.currentBotMessage = null;
}
// Ensure scrolling to bottom after message display
setTimeout(() => this.scrollToBottom(), 100);
})
)
.subscribe({
next: response => {
console.log('Received AI response update:', response);
// Update currently receiving message
this.currentBotMessage = response;
// Scroll to bottom in real-time
this.scrollToBottom();
},
error: error => {
console.error('AI response error:', error);
// Add error message
this.chatMessages.push({
content: this.i18nSvc.fanyi('ai.bot.connect-fail'),
isUser: false,
timestamp: new Date()
});
}
});
}
// Scroll to bottom of messages
private scrollToBottom(): void {
try {
const chatMessages = document.querySelector('.chatbot-messages');
if (chatMessages) {
chatMessages.scrollTop = chatMessages.scrollHeight;
}
} catch (err) {
console.error('Failed to scroll to bottom:', err);
}
}
}