# 新 AI 助手:页面设计 > 状态:设计初稿,2026-10-24。新助手以**独立的大页面**展示(菜单路由),不放在顶栏右上角。需求见 [requirements.md](requirements.md),前后端结构见 [technical-design.md](technical-design.md)。对话组件来自 `@agent-server/chat-ui`(AgentServer `packages/chat-ui`)。 ## 1. 路由与菜单 在 `src/router/record.ts` 增加一级菜单: ```ts { path: 'ai-assistant', name: 'aiAssistant', icon: 'i-ph:sparkle', // 与旧助手的 i-ph:chat-circle-dots 区分 label: 'AI 助手', meta: { componentName: 'AiAssistant', showTab: true, }, component: 'ai-assistant/index', }, ``` - 单标签页(不设 `enableMultiTab`):一个页面同时只打开一个会话,避免多个标签各自维持 SSE 连接。 - 当前会话写在查询参数 `?session=ses_xxx`(切换会话时 `router.replace`):刷新页面、从浏览器历史返回都能回到同一个会话;链接发给别人时,对方打开会因归属校验失败而回到新会话。 - 页面组件名为 `AiAssistant`,进入标签页的 KeepAlive:切换到其他标签时组件不销毁,进行中的回答继续接收;关闭标签时 `dispose` 订阅(运行本身不中断,下次打开从断点继续显示)。 - 菜单可见性按现有菜单权限机制配置为 FR-03 允许的角色;`AGENT_ENABLED=false` 时不注册该菜单。 - 旧助手顶栏按钮保持不变,两者并存。 ## 2. 布局 宽屏(≥ 1280px)三栏,中间为对话主区: ``` ┌───────────────┬──────────────────────────────────────────────┬─────────────────┐ │ + 新对话 │ 站点 XXXX 告警排查 ✎ [Sonnet 5.5 ▾] ⋯ │ 本会话文件 ⇥ │ │ 🔍 搜索会话 ├──────────────────────────────────────────────┤ ─────────────── │ │ │ │ 上传 │ │ 今天 │ (对话时间线,最大宽度 880px 居中) │ 📄 sales.xlsx │ │ ● 站点XXXX告警 │ 用户:…… │ 🖼 截图1.png │ │ SIM 用量统计 │ 助手:…… │ 产出 │ │ 昨天 │ ▸ 已调用 查询站点概况(0.8s) │ 📊 report.docx │ │ TOU 模版对比 │ ▸ 已调用 查询站点告警/事件记录(1.2s) │ 📈 trend.png │ │ 最近 7 天 │ ┌ 审批:保存 TOU 模版(测试服)… ┐ │ │ │ … │ └ [允许一次][本会话允许][拒绝] ┘ │ ┌─────────────┐ │ │ │ 📊 report.docx 2.1 MB [下载] │ │ 文件预览 │ │ │ │ │ │ (图片/PDF/ │ │ │ ├──────────────────────────────────────────────┤ │ Markdown/ │ │ │ ⇤ 收起 │ [📎] 输入问题,Enter 发送,Shift+Enter 换行 ▶ │ │ CSV 前 200 行)│ │ │ │ 本轮 12.3k / 1.8k tokens · 排队中(第 2 位) │ └─────────────┘ │ └───────────────┴──────────────────────────────────────────────┴─────────────────┘ 240px 自适应 320px ``` | 区域 | 内容 | 实现 | | --- | --- | --- | | 左栏:会话 | 新对话按钮;按标题搜索;按“今天 / 昨天 / 最近 7 天 / 更早”分组;悬停显示改名、删除;当前会话高亮;可收起 | NaiveUI(`NInput`、`NScrollbar`、`NDropdown`、`NPopconfirm`),数据来自 `/agent/sessions` | | 顶部栏 | 会话标题(点击改名);模型选择(Profile 允许的模型);更多菜单:删除会话、复制会话链接 | NaiveUI;模型切换调用 `PATCH /agent/v1/sessions/:id { model }` | | 中间:对话 | 时间线、工具卡片、审批与提问卡片、文件卡片、输入框(附件、拖拽、粘贴截图)、中断、断线续传 | ``;`#toolbar` 插槽放用量与排队信息,`#empty` 插槽放欢迎页(第 3 节) | | 右栏:文件 | 本会话的上传与产出文件(按来源分组,最新在前);点击在下方预览;下载 | `client.sessions.files(id)`,收到 `file.changed` 事件时刷新;预览用 chat-ui 的 `useFileObjectUrl`、`MarkdownView` | 对话主区的时间线限制最大宽度(880px)居中,宽屏下不至于一行过长;表格类回复允许横向滚动。 ### 2.1 窄屏 | 宽度 | 布局 | | --- | --- | | 1024~1279px | 右栏默认收起,顶部栏出现“文件”按钮,以右侧 `NDrawer` 打开 | | < 1024px | 左栏也收起为顶部栏的“会话”按钮,以左侧 `NDrawer` 打开 | 左右栏的展开/收起状态记在 `localStorage`(读写包在 try/catch 中,失败时用默认值)。 ## 3. 欢迎页(空会话) 新对话或空会话时,主区显示: - 一句说明:“可以查询站点、告警、停机、功率流、日志、录波、TOU 模版、SIM 卡数据,解答产品问题,分析上传的文件并生成报告。” - 示例问题卡片(2 × 3),点击即发送(`session.send(text)`): - 查一下站点 XXXX 最近 7 天的告警和事件 - 统计昨天停机站点按国家分布 - 分析站点 XXXX 本月的功率流,生成趋势图 - 告警码 XXXX 是什么意思,通常怎么处理 - 对比生产服和测试服的 TOU 模版 XXXX - 帮我把上传的 Excel 整理成一份 Word 报告 示例中的 SN、告警码等用占位符,点击后填入输入框而不直接发送,让用户补全(带占位符的卡片显示“填写后发送”)。 - 底部提示:“数据来自 FWH 平台,结果仅供参考;涉及修改数据的操作会先请你确认。” ## 4. 交互细节 | 场景 | 行为 | | --- | --- | | 首次进入(无 `?session=`) | 打开最近活跃的会话;没有会话时显示欢迎页,发送第一条消息时才创建会话(避免产生空会话) | | 新对话 | 主区回到欢迎页,地址去掉 `?session=`;左栏不出现新条目,直到发送第一条消息 | | 发送第一条消息 | `POST /agent/sessions` → 发送消息 → 用前 30 字改名 → 左栏插入并高亮 | | 切换会话 | 当前会话 `dispose`,打开目标会话(拉取历史事件 + 订阅),右栏刷新文件列表 | | 会话不存在 / 不属于本人 | 提示“会话不存在或无权访问”,回到欢迎页 | | 运行中切换会话或离开页面 | 不中断运行;左栏该会话显示“进行中”小圆点(依据最近一次打开时的运行状态,回到该会话时以实际状态为准) | | 运行中再次发送 | 输入框保持可编辑,发送按钮置灰并提示“上一轮尚未结束,可先中断” | | 删除当前会话 | 二次确认 → 删除 → 回到欢迎页 | | 审批 / 提问卡片待处理 | 页面标签显示提醒标记;离开页面期间到达的审批,回到页面时卡片仍在(来自 `GET /v1/interactions`) | | AgentServer 或 fwh-agent-mcp 不可用 | 顶部栏下方显示横幅“AI 服务暂不可用”,输入框禁用;工具级别的不可用由工具卡片显示错误,不影响对话 | ## 5. 主题与样式 - 引入 `@agent-server/chat-ui/style.css`;组件的原子类已在包内编译隔离,ToolBox 的 UnoCSS 不需要扫描 SDK。 - 明暗模式:ToolBox 切换主题时同步设置 `data-theme`(组件读取 `` 上的属性,需验证不影响 NaiveUI 的主题)。 - 配色:在页面根元素上覆盖 `--app-*` 变量,使按钮、链接、选中色与 ToolBox 主色一致;完整变量见 `@agent-server/ui-tokens` 的 `variables.css`。 - 左栏、顶部栏、右栏使用 NaiveUI 组件,与 ToolBox 其他页面一致;中间对话区保持 chat-ui 自身风格。 ## 6. 代码结构 ``` src/views/ai-assistant/ index.vue 页面:三栏布局、路由参数、窄屏抽屉 components/ SessionSidebar.vue 左栏:会话列表、搜索、分组、改名、删除 ChatHeader.vue 顶部栏:标题、模型选择、更多菜单 WelcomePanel.vue 欢迎页与示例问题 FilePanel.vue 右栏:文件列表与预览 composables/ useAgentClient.ts AgentClient 单例(baseUrl = /agent,令牌 = ToolBox 登录令牌) useAgentSessions.ts 会话列表、创建、改名、删除、当前会话与路由同步 useSessionFiles.ts 文件列表与 file.changed 刷新 src/service/agent/index.ts /agent/sessions/* 接口 ``` 不修改 `src/layout/header/Actions/AiChat/`、`src/service/aiChat/`。