@page "/" @implements IDisposable @inject XiaoZhi_AgentService XiaoZhiAgent @inject IJSRuntime JS
@if (currentPage == "chat") {
小智AI助手
连接状态:@(XiaoZhiAgent.IsConnected ? "已连接" : "未连接") @XiaoZhiAgent.Agent.ConnectState.ToString()
@switch (XiaoZhiAgent.Emotion.ToLower()) { case "happy": case "excited": break; case "sad": break; case "surprised": case "surprise": break; case "angry": break; case "laughing": break; case "pleased": break; case "loading": break; case "typing": break; case "voice": break; default: break; }
@if (XiaoZhiAgent.ChatHistory.Count == 0) {

欢迎使用小智AI助手!

  • • 输入文字或点击🎤语音对话
  • • 支持实时语音识别和AI回复
} @foreach (var message in XiaoZhiAgent.ChatHistory) {
@message.Timestamp.ToString("HH:mm")
@message.Content
} @if (!string.IsNullOrEmpty(XiaoZhiAgent.QuestionMessae) && (XiaoZhiAgent.ChatHistory.Count == 0 || !XiaoZhiAgent.ChatHistory.Any(m => m.IsUser && m.Content == XiaoZhiAgent.QuestionMessae))) {
@DateTime.Now.ToString("HH:mm")
@XiaoZhiAgent.QuestionMessae
} @if (!string.IsNullOrEmpty(XiaoZhiAgent.AnswerMessae) && (XiaoZhiAgent.ChatHistory.Count == 0 || !XiaoZhiAgent.ChatHistory.Any(m => !m.IsUser && m.Content == XiaoZhiAgent.AnswerMessae))) {
@DateTime.Now.ToString("HH:mm")
@XiaoZhiAgent.AnswerMessae
}
@(XiaoZhiAgent.IsRecording ? "录音中" : "待机")
VAD: @XiaoZhiAgent.VadCounter
音量
情绪: @XiaoZhiAgent.Emotion
@if (XiaoZhiAgent.IsRecording) { } else { }
} else if (currentPage == "settings") { }
@code { private string currentPage = "chat"; // 当前页面:chat 或 settings private string txtValue = string.Empty; private System.Timers.Timer _timer = new System.Timers.Timer(100) { Enabled = true }; // 更频繁的更新以显示音频强度 private ElementReference messagesContainer; protected override async Task OnInitializedAsync() { _timer.Elapsed += Timer_Elapsed; } private void SwitchPage(string page) { currentPage = page; StateHasChanged(); } private void SwitchToChat() { currentPage = "chat"; StateHasChanged(); } private void SwitchToSettings() { currentPage = "settings"; StateHasChanged(); } private async void Timer_Elapsed(object sender, EventArgs args) { await Task.Factory.StartNew(() => { InvokeAsync(() => { StateHasChanged(); return Task.CompletedTask; }); }); } // 跟踪上一次消息数量,用于判断是否有新消息 private int previousMessageCount = 0; private bool userIsScrolling = false; private DateTime lastScrollTime = DateTime.MinValue; protected override async Task OnAfterRenderAsync(bool firstRender) { // 自动滚动到底部的条件: // 1. 首次渲染 // 2. 有新消息且用户没有主动滚动(或最后滚动时间已超过3秒) if (currentPage == "chat" && ( firstRender || (XiaoZhiAgent.ChatHistory.Count > previousMessageCount && (!userIsScrolling || (DateTime.Now - lastScrollTime).TotalSeconds > 3)) )) { await ScrollToBottom(); previousMessageCount = XiaoZhiAgent.ChatHistory.Count; } } private async Task ScrollToBottom() { try { await Task.Delay(100); // 等待DOM更新 // 使用JS互操作滚动到底部 await JS.InvokeVoidAsync("scrollToBottom", messagesContainer); } catch { // 忽略错误 } } // 强制滚动到底部(用于发送新消息时) private async Task ForceScrollToBottom() { try { await Task.Delay(100); // 等待DOM更新 // 直接滚动到底部,不检查条件 await JS.InvokeVoidAsync("forceScrollToBottom", messagesContainer); } catch { // 忽略错误 } } private async Task HandleKeyPress(KeyboardEventArgs e) { if (e.Key == "Enter" && !string.IsNullOrWhiteSpace(txtValue)) { await SendText(); } } private async Task SendText() { if (!string.IsNullOrWhiteSpace(txtValue)) { var message = txtValue.Trim(); txtValue = string.Empty; // 清空输入框 await XiaoZhiAgent.Agent.ChatMessage(message); // 用户发送消息后,强制滚动到底部 userIsScrolling = false; await ForceScrollToBottom(); } } private async Task StartRecording() { try { await XiaoZhiAgent.Agent.StartRecording("auto"); // 开始录音时,强制滚动到底部 userIsScrolling = false; await ForceScrollToBottom(); } catch (Exception ex) { // 处理录音启动错误 Console.WriteLine($"启动录音时出错: {ex.Message}"); } } private async Task StopRecording() { try { await XiaoZhiAgent.Agent.StopRecording(); } catch (Exception ex) { // 处理录音停止错误 Console.WriteLine($"停止录音时出错: {ex.Message}"); } } private async Task StopChat() { try { await XiaoZhiAgent.Agent.ChatAbort(); } catch (Exception ex) { // 处理打断对话错误 Console.WriteLine($"打断对话时出错: {ex.Message}"); } } private void ClearChat() { XiaoZhiAgent.ClearChatHistory(); StateHasChanged(); } // 处理滚动事件 private void HandleScroll(EventArgs args) { userIsScrolling = true; lastScrollTime = DateTime.Now; // 3秒后重置滚动状态 _ = Task.Run(async () => { await Task.Delay(3000); userIsScrolling = false; }); } private string GetVadStatusClass() { if (XiaoZhiAgent.VadCounter > 0 && XiaoZhiAgent.VadCounter < 10) { return "active"; } return string.Empty; } void IDisposable.Dispose() { _timer?.Close(); _timer?.Dispose(); } }