Skip to content

左侧菜单配置

左侧菜单(NavigationRail)是场景 UI 的核心导航区域,用户通过点击图标切换不同的功能面板。

工作原理

sidebarItems 配置 → NavigationRail 渲染图标 → 用户点击 → 侧边栏显示对应面板
  1. 场景激活时,客户端读取 ui.sidebarItems 渲染左侧菜单图标
  2. 用户点击图标,客户端设置 activeSidePanel 为该菜单项的 id
  3. 侧边栏根据 id 查找面板组件并渲染

声明式场景菜单

scenario.jsonui.sidebarItems 中配置,仅支持内置面板:

json
{
  "ui": {
    "layout": "chat-centric",
    "sidebarItems": [
      {
        "id": "explorer",
        "icon": "Files",
        "label": "Workspace",
        "labelZh": "工作区",
        "component": "ExplorerView",
        "position": 0
      },
      {
        "id": "knowledge",
        "icon": "BookOpen",
        "label": "Knowledge",
        "labelZh": "知识库",
        "component": "KnowledgeView",
        "position": 1
      },
      {
        "id": "history",
        "icon": "History",
        "label": "History",
        "labelZh": "历史",
        "component": "HistoryView",
        "position": 2
      },
      {
        "id": "tasks",
        "icon": "CheckSquare",
        "label": "Tasks",
        "labelZh": "任务",
        "component": "TasksView",
        "position": 3
      }
    ]
  }
}

宽屏模式 (wideMode)

wideModeSidebarItem 的可选字段,当设为 true 时,该菜单项对应的面板将占据主内容区域(而非侧边栏),同时侧边栏自动收起。

使用场景

  • 设置面板:场景专属设置需要一个宽大的操作区域,不适合在狭窄侧边栏中展示
  • 知识库:需要全屏展示的复杂面板
  • 仪表盘:数据密集的统计面板

配置示例:场景专属设置

第一步:声明菜单项 + wideMode

typescript
getPlugin() {
  return {
    ui: {
      sidebarItems: [
        // ... 其他侧边栏项
        {
          id: 'settings',
          icon: 'Settings',
          label: 'Settings',
          labelZh: '场景设置',
          component: 'MySettingsView',
          position: 8,
          wideMode: true,  // 宽屏模式
        },
      ],
    },
  }
}

第二步:创建设置视图组件

tsx
// components/settings/MySettingsView.tsx
import { useCallback } from 'react'
import { useStore } from '@store'
import { MySettingsDialog } from './MySettingsDialog'

export default function MySettingsView() {
  const closePanel = useCallback(() => {
    // 关闭设置时回到文件管理器
    useStore.getState().setActiveSidePanel('explorer')
  }, [])

  return <MySettingsDialog embedded onClose={closePanel} />
}

第三步:创建设置对话框组件

tsx
// components/settings/MySettingsDialog.tsx
export function MySettingsDialog({
  embedded = false,
  onClose,
}: {
  embedded?: boolean
  onClose?: () => void
}) {
  const content = (
    <div className={`flex h-full ${embedded ? '' : 'max-h-[800px]'}`}>
      {/* 左侧导航 */}
      <div className="w-56 bg-surface/30 backdrop-blur-xl pt-8 pb-6">
        {/* 标签页导航 */}
      </div>
      {/* 右侧内容 */}
      <div className="flex-1 overflow-auto">
        {/* 设置表单 */}
      </div>
    </div>
  )

  if (embedded) {
    return content  // wideMode 下直接渲染,无弹窗遮罩
  }

  return (
    <OverlayDialog onClose={onClose}>
      {content}
    </OverlayDialog>
  )
}

关键点embedded 模式下移除弹窗遮罩,onClose 回调切换侧边栏面板回到 explorer。

工作原理

用户点击 wideMode 菜单项
  → 侧边栏收起 (sidebar hidden)
  → 面板组件渲染到 FullPageSlot(主内容区)
  → 用户点击关闭按钮 → setActiveSidePanel('explorer')
  → 侧边栏恢复,面板回到 explorer

内置面板组件

component 值说明
ExplorerView文件浏览器
SearchView全局搜索
GitViewGit 源码管理
ProblemsView问题诊断
OutlineView符号大纲
HistoryView历史记录
ShellViewShell 终端
KnowledgeView知识库
NotesView笔记
TasksView任务管理
BookmarksView书签
PromptsView提示词库

编程式场景菜单

编程式场景支持自定义面板组件,分两步:

第一步:声明菜单项

getPlugin()ui.sidebarItems 中声明:

typescript
getPlugin() {
  return {
    ui: {
      sidebarItems: [
        // 自定义面板:component 对应 getComponents() 返回的 key
        {
          id: 'tasks',
          icon: 'CheckSquare',
          label: 'Tasks',
          labelZh: '任务',
          component: 'TaskListPanel',
          position: 0,
        },
        {
          id: 'stats',
          icon: 'BarChart3',
          label: 'Stats',
          labelZh: '统计',
          component: 'StatsPanel',
          position: 1,
        },
        // 内置面板:直接引用内置组件名
        {
          id: 'explorer',
          icon: 'Files',
          label: 'Workspace',
          labelZh: '工作区',
          component: 'ExplorerView',
          position: 2,
        },
        {
          id: 'knowledge',
          icon: 'BookOpen',
          label: 'Knowledge',
          labelZh: '知识库',
          component: 'KnowledgeView',
          position: 3,
        },
      ],
      defaultSidePanel: 'tasks',
    },
  }
}

第二步:注册自定义组件

getComponents() 中注册:

typescript
import { TaskListPanel } from './components/TaskListPanel.js'
import { StatsPanel } from './components/StatsPanel.js'

getComponents() {
  return {
    TaskListPanel,
    StatsPanel,
  }
}

关键:sidebarItems 中的 component 值必须与 getComponents() 返回的 key 一致。

字段说明

字段类型必填说明
idstring菜单项唯一标识,同时作为面板 ID
iconstring图标名称,使用 lucide-react 图标名
labelstring英文标签
labelZhstring中文标签
componentstring面板组件名
positionnumber排序位置,从小到大
wideModeboolean宽屏模式下是否作为主面板显示

常用图标参考

图标名适用场景
Files文件/工作区
Search搜索
GitBranchGit 管理
BookOpen知识库
History历史记录
Terminal终端
CheckSquare任务
BarChart3统计/图表
Database数据源
Settings设置
Map地图/行程
Wallet预算/财务
Stethoscope诊断
BrainAI/深度思考
Zap快速操作
FolderTree目录树
ListTree大纲
AlertCircle问题/告警

完整图标列表参考 lucide.dev

布局与菜单的关系

不同 layout 值对左侧菜单的显示策略不同:

布局菜单显示说明
chat-centric有 sidebarItems 时显示无菜单项时隐藏侧边栏
editor-centric始终显示左侧菜单 + 中间编辑器 + 右侧聊天
dashboard-centric始终显示左侧菜单 + 中间仪表盘 + 右侧聊天
analytics-centric始终显示左侧菜单 + 中间分析面板 + 右侧聊天
canvas-centric始终显示左侧菜单 + 中间画布 + 右侧聊天
minimal不显示仅聊天界面
focus-centric不显示编辑器 + 聊天
research-centric有 sidebarItems 时显示编辑器 + 聊天 + 可选菜单

AweeClaw AI 应用构建平台