Skip to content

交互逻辑和UI说明

UI结构概述

LLM Agent采用三列布局结构:

  1. 左侧导航栏 - 固定宽度,包含主要功能导航按钮
  2. 中间内容列表 - 根据当前功能显示对应的列表内容
  3. 右侧主内容区 - 显示主要交互内容

整个UI设计采用嵌套SplitContainer实现分区显示,确保内容区域大小可灵活调整。

主要控件层次结构

LlmAgentMainForm
├── mainSplitContainer
│   ├── Panel1 (导航栏)
│   │   └── navPanel
│   │       ├── avatarButton
│   │       ├── chatNavButton
│   │       ├── channelNavButton
│   │       ├── websiteNavButton
│   │       ├── promptsNavButton
│   │       └── settingsNavButton
│   │
│   └── Panel2 (内容区)
│       ├── chatPagePanel
│       │   └── chatPageSplitContainer
│       │       ├── Panel1 (聊天列表)
│       │       │   └── chatListContainer
│       │       │       ├── Panel1 (搜索和新建)
│       │       │       │   ├── searchBox
│       │       │       │   └── newChatButton
│       │       │       └── Panel2 (聊天列表)
│       │       │           └── chatListPanel
│       │       │
│       │       └── Panel2 (聊天内容)
│       │           └── inputPanel
│       │
│       ├── channelPanel
│       │   └── channelPageSplitContainer
│       │       ├── Panel1 (渠道列表)
│       │       │   └── channelListPanel
│       │       │       └── channelListBox
│       │       └── Panel2 (渠道详情)
│       │           └── channelDetailsPanel
│       │
│       ├── aiWebsitePanel
│       │   └── aiWebsitePageSplitContainer
│       │       ├── Panel1 (网站列表)
│       │       │   └── aiWebsiteMenuPanel
│       │       │       └── websiteListContainer
│       │       │           ├── Panel1 (搜索和新建)
│       │       │           │   ├── websiteSearchBox
│       │       │           │   └── newWebsiteButton
│       │       │           └── Panel2 (网站列表)
│       │       │               └── websiteListPanel
│       │       └── Panel2 (网站内容)
│       │           └── aiWebsiteContentPanel
│       │
│       ├── userProfilePanel
│       │   └── userProfilePageSplitContainer
│       │       ├── Panel1 (用户列表)
│       │       │   └── userProfileMenuPanel
│       │       │       └── userListContainer
│       │       │           ├── Panel1 (搜索和新建)
│       │       │           │   ├── userSearchBox
│       │       │           │   └── newUserButton
│       │       │           └── Panel2 (用户列表)
│       │       │               └── userListPanel
│       │       └── Panel2 (用户详情)
│       │           └── userProfileContentPanel
│       │
│       ├── promptsPanel
│       │   └── promptsPageSplitContainer
│       │       ├── Panel1 (提示词列表)
│       │       │   └── promptsListContainer
│       │       │       ├── Panel1 (搜索和新建)
│       │       │       │   ├── promptSearchBox
│       │       │       │   └── newPromptButton
│       │       │       └── Panel2 (提示词列表)
│       │       │           └── promptsListPanel
│       │       └── Panel2 (提示词内容)
│       │           └── promptsContentPanel
│       │
│       └── settingsPanel
│           └── settingsPageSplitContainer
│               ├── Panel1 (设置菜单)
│               │   └── settingsMenuPanel
│               └── Panel2 (设置内容)
│                   └── settingsContentContainer
│                       └── settingsContentPanel

导航流程

  1. 应用启动 - 默认显示chatPagePanel,激活chatNavButton
  2. 导航切换 - 点击左侧导航按钮,调用SwitchToPanel方法:
    • 隐藏所有内容面板
    • 显示对应目标面板
    • 重置所有导航按钮样式
    • 高亮当前活动按钮
    • 执行特定面板的初始化操作

聊天功能交互流程

  1. 新建对话

    • 点击"新建聊天"按钮 → 调用CreateNewChat方法
    • 创建新会话,清空消息区域
    • 添加系统欢迎消息
    • 重新初始化聊天主题列表
    • 切换到聊天界面,设置输入框焦点
  2. 发送消息

    • 输入消息 → 按Ctrl+Enter或点击发送按钮
    • 调用SendMessage方法
    • 添加用户消息到当前会话
    • 调用API获取AI响应(支持流式响应)
    • 更新UI显示结果
    • 更新聊天历史列表
  3. 切换历史对话

    • 点击左侧会话列表中的历史项目
    • 调用会话管理器切换到对应会话
    • 更新UI显示选中的会话内容

设置面板交互流程

  1. 模型设置

    • 选择提供商 → 触发ProviderChanged事件
    • 更新模型列表
    • 保存设置并更新窗体标题
  2. API设置

    • 填写API密钥和主机地址
    • 点击更新按钮 → 调用UpdateApiSettings方法
    • 保存配置
  3. 通用设置

    • 勾选流式响应 → 更新_useStreamResponse变量
    • 修改系统提示词 → 保存到Properties.Settings

控件访问关系

由于采用嵌套结构,控件的访问需要考虑层次关系:

csharp
// 示例:获取txtOutput控件
RichTextBox txtOutput = chatOutputPanel.Controls["txtOutput"] as RichTextBox;

// 示例:获取深层嵌套的控件
CheckBox chkStreamResponse = settingsContentPanel.Controls.Find("chkStreamResponse", true).FirstOrDefault() as CheckBox;

界面切换机制

界面使用Panel的Visible属性进行切换,确保同一时刻只有一个主要内容面板可见:

csharp
// 隐藏所有内容面板
foreach (Control control in mainSplitContainer.Panel2.Controls)
{
    control.Visible = false;
}

// 显示目标面板
targetPanel.Visible = true;

事件处理模式

应用采用事件驱动的交互模式,主要事件处理包括:

  1. 导航事件

    csharp
    private void chatNavButton_Click(object sender, EventArgs e)
    {
        SwitchToPanel(chatPagePanel, chatNavButton);
    }
  2. 聊天事件

    csharp
    private void btnSend_Click(object sender, EventArgs e)
    {
        SendMessage();
    }
    
    private void txtInput_KeyDown(object sender, KeyEventArgs e)
    {
        if (e.Control && e.KeyCode == Keys.Enter)
        {
            SendMessage();
            e.Handled = true;
        }
    }
  3. 设置变更事件

    csharp
    private void cboProvider_SelectedIndexChanged(object sender, EventArgs e)
    {
        if (_isUpdatingUI) return;
        
        UpdateModelList();
        SaveSettings();
    }

异步操作处理

聊天消息发送和接收使用异步模式,确保UI响应性:

csharp
private async Task SendMessageAsync()
{
    // 显示发送中状态
    SetSendingState(true);
    
    try
    {
        // 异步调用API
        var response = await _channelService.SendMessageAsync(message, currentChannel);
        
        // 更新UI显示
        UpdateChatDisplay(response);
    }
    catch (Exception ex)
    {
        HandleError(ex);
    }
    finally
    {
        // 恢复UI状态
        SetSendingState(false);
    }
}

防止事件循环

应用使用标志变量防止UI更新触发事件导致的循环:

csharp
// 用于防止界面更新时触发事件处理
private bool _isUpdatingUI = false;

private void UpdateChannelDetails(Channel channel)
{
    _isUpdatingUI = true;
    
    try
    {
        // 更新UI控件
        txtChannelName.Text = channel.Name;
        chkEnabled.Checked = channel.IsEnabled;
        // ...其他UI更新
    }
    finally
    {
        _isUpdatingUI = false;
    }
}

注意事项与最佳实践

  1. 控件访问一致性

    • 所有控件访问应统一考虑层次结构,避免直接访问
    • 使用Controls.Find方法查找深层嵌套控件
  2. 错误处理

    • 在访问控件前增加null检查,提高应用稳定性
    • 使用try-catch块处理可能的异常
  3. UI线程同步

    • 从工作线程更新UI时使用Invoke/BeginInvoke
    • 确保UI操作在UI线程执行
  4. 资源释放

    • 实现IDisposable接口,确保资源正确释放
    • 使用using语句自动释放资源
  5. 性能优化

    • 使用SuspendLayout/ResumeLayout减少重绘
    • 批量更新UI,避免频繁触发布局计算

基于 MIT 许可发布