- standard/开发规范.md: 新增 §3.1 UI组件铁律: 所有UI组件必须使用MUI,列表枚举12类禁止自写 移除 §4 中「简单UI组件」自写例外 更新 §附录: MUI明确为强制组件库,Tailwind仅辅助 - docs/UI UX设计集成方案: 组件树前增加MUI强制使用说明 - docs/架构与交互设计: Renderer进程说明补充MUI,Hero技术栈加入MUI
741 lines
54 KiB
HTML
741 lines
54 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>MetonaAI Desktop — UI/UX 设计集成方案 | v1.0</title>
|
||
<style>
|
||
:root {
|
||
--bg:#0f1117; --bg-card:#1a1d27; --bg-code:#12141c; --bg-nav:#141620;
|
||
--text:#e1e4ed; --text-dim:#8b8fa7; --accent:#6366f1; --accent2:#818cf8;
|
||
--green:#34d399; --orange:#fb923c; --red:#f87171; --amber:#fbbf24;
|
||
--cyan:#22d3ee; --purple:#a855f7; --pink:#f472b6; --border:#2a2d3a;
|
||
}
|
||
*{margin:0;padding:0;box-sizing:border-box}
|
||
body{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI','PingFang SC','Microsoft YaHei',sans-serif;background:var(--bg);color:var(--text);line-height:1.7;display:flex;scroll-behavior:smooth}
|
||
.sidebar{position:fixed;top:0;left:0;width:300px;height:100vh;background:var(--bg-nav);border-right:1px solid var(--border);overflow-y:auto;z-index:100;padding:24px 0}
|
||
.sidebar-logo{padding:0 20px 20px;border-bottom:1px solid var(--border);margin-bottom:16px}
|
||
.sidebar-logo h2{font-size:19px;background:linear-gradient(135deg,var(--accent),var(--accent2),var(--purple));-webkit-background-clip:text;-webkit-text-fill-color:transparent}
|
||
.sidebar-section{padding:8px 20px;font-size:10.5px;text-transform:uppercase;letter-spacing:1.2px;color:var(--text-dim);font-weight:600}
|
||
.sidebar a{display:flex;align-items:center;gap:10px;padding:7px 20px;color:var(--text-dim);text-decoration:none;font-size:13px;transition:all .15s}
|
||
.sidebar a:hover,.sidebar a.active{color:var(--text);background:rgba(99,102,241,.06)}
|
||
.sidebar a.active{border-right:2px solid var(--accent)}
|
||
.main{margin-left:300px;flex:1;min-height:100vh}
|
||
.hero{background:linear-gradient(135deg,rgba(99,102,241,.07),rgba(244,114,182,.05));border-bottom:1px solid var(--border);padding:56px 60px 48px}
|
||
.hero h1{font-size:30px;font-weight:800;background:linear-gradient(135deg,var(--accent),var(--purple),var(--pink));-webkit-background-clip:text;-webkit-text-fill-color:transparent;margin-bottom:10px}
|
||
.hero p{color:var(--text-dim);font-size:15px;max-width:740px}
|
||
.hero-meta{display:flex;gap:24px;margin-top:18px;flex-wrap:wrap}
|
||
.hero-meta span{font-size:13px;color:var(--text-dim);display:flex;align-items:center;gap:6px}
|
||
.content{padding:40px 60px 100px;max-width:1080px}
|
||
.api-section{margin-bottom:60px;scroll-margin-top:20px}
|
||
.api-section h2{font-size:22px;font-weight:700;margin-bottom:16px;display:flex;align-items:center;gap:10px}
|
||
.api-section h3{font-size:16px;font-weight:600;margin:32px 0 12px;color:var(--accent2)}
|
||
.api-section .desc{color:var(--text-dim);font-size:14.5px;margin-bottom:16px}
|
||
.api-section .desc code{color:var(--cyan);background:var(--bg-code);padding:2px 6px;border-radius:4px;font-size:13px}
|
||
table.spec{width:100%;border-collapse:collapse;margin-bottom:24px;font-size:13.5px}
|
||
table.spec th{text-align:left;padding:10px 14px;background:var(--bg-card);border-bottom:1px solid var(--border);color:var(--text-dim);font-weight:600;font-size:11px;text-transform:uppercase;letter-spacing:.8px}
|
||
table.spec td{padding:10px 14px;border-bottom:1px solid rgba(42,45,58,.5);vertical-align:top;transition:background .15s}
|
||
table.spec tr:hover td{background:rgba(99,102,241,.03)}
|
||
table.spec tr:last-child td{border-bottom:none}
|
||
.f1{font-family:'SF Mono',monospace;color:var(--cyan);font-weight:600;font-size:13px}
|
||
.f2{font-family:'SF Mono',monospace;color:var(--accent2);font-size:11.5px}
|
||
.f3{color:var(--red);font-size:11px;font-weight:600}
|
||
.code-block{background:var(--bg-code);border:1px solid var(--border);border-radius:10px;padding:20px;overflow-x:auto;margin-bottom:24px;transition:border-color .2s}
|
||
.code-block:hover{border-color:rgba(99,102,241,.3)}
|
||
.code-block pre{margin:0;font-family:'SF Mono','Fira Code',monospace;font-size:13px;line-height:1.6;color:var(--text)}
|
||
.hl-kw{color:var(--purple)}.hl-str{color:var(--green)}.hl-num{color:var(--orange)}
|
||
.hl-cm{color:var(--text-dim);font-style:italic}.hl-fn{color:var(--accent)}.hl-prop{color:var(--cyan)}
|
||
.note-box{background:rgba(99,102,241,.05);border-left:3px solid var(--accent);border-radius:0 8px 8px 0;padding:14px 18px;margin-bottom:24px;font-size:13.5px;color:var(--text-dim);transition:border-color .2s}
|
||
.note-box:hover{border-left-color:var(--accent2)}
|
||
.note-box strong{color:var(--accent)}
|
||
.note-box code{color:var(--cyan);background:var(--bg-code);padding:1px 5px;border-radius:3px;font-size:12.5px}
|
||
.warn-box{background:rgba(251,191,36,.05);border-left:3px solid var(--amber);border-radius:0 8px 8px 0;padding:14px 18px;margin-bottom:24px;font-size:13.5px;color:var(--text-dim);transition:border-color .2s}
|
||
.warn-box:hover{border-left-color:var(--orange)}
|
||
.arch-diagram{background:var(--bg-card);border:1px solid var(--border);border-radius:10px;padding:24px;margin:20px 0 30px;overflow-x:auto;transition:border-color .2s}
|
||
.arch-diagram:hover{border-color:rgba(99,102,241,.3)}
|
||
.arch-diagram pre{font-family:'SF Mono',monospace;font-size:12px;line-height:1.55;color:var(--text);margin:0}
|
||
.node{display:inline-block;padding:6px 14px;border-radius:8px;margin:3px;font-size:12px;font-family:'SF Mono',monospace}
|
||
.node-core{background:rgba(99,102,241,.15);border:1px solid rgba(99,102,241,.3);color:var(--accent2)}
|
||
.node-data{background:rgba(34,211,238,.1);border:1px solid rgba(34,211,238,.2);color:var(--cyan)}
|
||
.node-ui{background:rgba(168,85,247,.12);border:1px solid rgba(168,85,247,.25);color:var(--purple)}
|
||
.node-tool{background:rgba(244,114,182,.1);border:1px solid rgba(244,114,182,.2);color:var(--pink)}
|
||
.section-divider{border:none;height:1px;background:var(--border);margin:56px 0}
|
||
::-webkit-scrollbar{width:6px;height:6px}
|
||
::-webkit-scrollbar-track{background:transparent}
|
||
::-webkit-scrollbar-thumb{background:var(--border);border-radius:3px}
|
||
@media(max-width:900px){.sidebar{display:none}.main{margin-left:0}.hero,.content{padding:30px 24px}}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
|
||
<nav class="sidebar">
|
||
<div class="sidebar-logo"><h2>🎨 MetonaAI Desktop UI/UX</h2></div>
|
||
<div class="sidebar-section">研究综述</div>
|
||
<a href="#trends">📊 2026 UI/UX 趋势</a>
|
||
<a href="#patterns">🧩 Agent 设计模式</a>
|
||
<a href="#references">🔗 参考项目</a>
|
||
<div class="sidebar-section">MetonaToast</div>
|
||
<a href="#metona-toast">📢 项目分析</a>
|
||
<a href="#toast-integration">⚙️ 集成方案</a>
|
||
<div class="sidebar-section">UI 设计</div>
|
||
<a href="#layout">🏗️ 整体布局</a>
|
||
<a href="#chat-panel">💬 聊天面板</a>
|
||
<a href="#trace-viewer">🔍 Trace Viewer</a>
|
||
<a href="#tool-call">🔧 工具调用 UI</a>
|
||
<a href="#settings">⚙️ 设置面板</a>
|
||
<div class="sidebar-section">组件系统</div>
|
||
<a href="#component-tree">🌲 组件树</a>
|
||
<a href="#theme-system">🎨 主题系统</a>
|
||
<a href="#animation">✨ 动效规范</a>
|
||
</nav>
|
||
|
||
<div class="main">
|
||
|
||
<div class="hero">
|
||
<h1>MetonaAI Desktop — UI/UX 设计集成方案</h1>
|
||
<p>综合 2026 年 AI Agent 交互设计前沿趋势 + MetonaToast 组件库研究成果,产出 MetonaAI Desktop 完整的用户界面设计方案,确保"可见思维、可控行动、可信结果"。</p>
|
||
<div class="hero-meta">
|
||
<span>📊 研究来源: <strong>Fuselab Creative / Ant Design X / A2UI / Hermes Agent</strong></span>
|
||
<span>📦 集成组件: <strong>MetonaToast v2.0.0</strong></span>
|
||
</div>
|
||
<div class="note-box" style="margin-top:16px">
|
||
<strong>📋 文档层级:</strong>本文档是 <strong>用户界面与交互设计的权威定义</strong>,与《构建指南》第九章(React 前端)对应。冲突时以本文档为准。
|
||
</div>
|
||
</div>
|
||
|
||
<div class="content">
|
||
|
||
<!-- ===== 行业趋势 ===== -->
|
||
<section class="api-section" id="trends">
|
||
<h2>📊 2026 AI Agent UI/UX 趋势综述</h2>
|
||
<p class="desc">通过分析 Fuselab Creative、UX Tigers、Ant Design X、Google A2UI、The Skins Factory 等权威来源,提炼出 6 大核心趋势:</p>
|
||
|
||
<table class="spec">
|
||
<tr><th>#</th><th>趋势</th><th>核心要求</th><th>Metona 对应</th></tr>
|
||
<tr>
|
||
<td class="f1">1</td>
|
||
<td><strong>可解释 AI(Explainable AI)</strong></td>
|
||
<td>用户必须看到 Agent 在<strong>想什么</strong>、<strong>做什么</strong>、<strong>为什么</strong></td>
|
||
<td class="f2">TraceViewer 实时展示 Thought → ToolCall → Observation 全链路</td>
|
||
</tr>
|
||
<tr>
|
||
<td class="f1">2</td>
|
||
<td><strong>Agentic UX / RICH 范式</strong></td>
|
||
<td>角色(Role) + 意图(Intention) + 会话(Conversation) + 混合界面(Hybrid UI)</td>
|
||
<td class="f2">SOUL.md 定义角色 + Chat 对话 + Tool Panel 混合 UI</td>
|
||
</tr>
|
||
<tr>
|
||
<td class="f1">3</td>
|
||
<td><strong>透明与可控</strong></td>
|
||
<td>每步提供 override 控制、用户可随时中断/修正</td>
|
||
<td class="f2">Abort 按钮、工具调用前确认弹窗、参数可编辑</td>
|
||
</tr>
|
||
<tr>
|
||
<td class="f1">4</td>
|
||
<td><strong>A2UI — AI 说出 UI</strong></td>
|
||
<td>Agent 以声明式 JSON 描述 UI 意图,客户端原生渲染</td>
|
||
<td class="f2">预留 A2UI 接口,Agent 可动态生成卡片/表格/图表</td>
|
||
</tr>
|
||
<tr>
|
||
<td class="f1">5</td>
|
||
<td><strong>多模态混合界面</strong></td>
|
||
<td>文本 + 代码 + 图表 + 图片 + 3D 混合呈现</td>
|
||
<td class="f2">MessageItem 支持 Markdown + 代码高亮 + 图片 + Mermaid 图表</td>
|
||
</tr>
|
||
<tr>
|
||
<td class="f1">6</td>
|
||
<td><strong>优雅错误恢复</strong></td>
|
||
<td>错误不是终点,是引导用户修正的入口</td>
|
||
<td class="f2">MetonaToast error/warning 通知 + 错误上下文面板</td>
|
||
</tr>
|
||
</table>
|
||
|
||
<div class="note-box">
|
||
<strong>💡 Fuselab Creative 核心论断:</strong>"Agent UX 与传统 UI 的根本区别在于 — Agent 界面必须传达系统正在做什么、解释其推理逻辑、在每一步提供覆盖控制、并从错误中优雅恢复。设计挑战是在保持用户信任的同时允许系统自主操作。"
|
||
</div>
|
||
</section>
|
||
|
||
<hr class="section-divider">
|
||
|
||
<!-- ===== 设计模式 ===== -->
|
||
<section class="api-section" id="patterns">
|
||
<h2>🧩 Agent 交互设计模式</h2>
|
||
|
||
<h3>Ant Design X — RICH 范式</h3>
|
||
<table class="spec">
|
||
<tr><th>维度</th><th>含义</th><th>Metona 实现</th></tr>
|
||
<tr><td class="f1">Role(角色)</td><td>Agent 的身份、性格、能力边界</td><td class="f2">SOUL.md → System Prompt RoleDefinition</td></tr>
|
||
<tr><td class="f1">Intention(意图)</td><td>理解用户目标,主动规划</td><td class="f2">ReAct Loop → Thought 思考过程实时展示</td></tr>
|
||
<tr><td class="f1">Conversation(会话)</td><td>多轮对话 + 历史上下文</td><td class="f2">ChatPanel + Session 管理 + Memory 检索</td></tr>
|
||
<tr><td class="f1">Hybrid UI(混合界面)</td><td>对话 + 传统 UI 混合</td><td class="f2">Chat + Tool Panel + TraceViewer + Settings 同屏</td></tr>
|
||
</table>
|
||
|
||
<h3>Agent UI 五大核心面板</h3>
|
||
<div class="arch-diagram">
|
||
<pre>
|
||
<span class="node node-core">1. 对话面板</span> → <span class="node node-data">2. 思维面板</span> → <span class="node node-tool">3. 工具面板</span> → <span class="node node-ui">4. 工作区面板</span> → <span class="node node-core">5. 状态栏</span>
|
||
|
||
核心交互链路: 用户输入 → Agent思考 → 工具执行 → 结果展示 → 反馈通知
|
||
│ │ │ │
|
||
实时流式 折叠/展开 参数+耗时 Markdown渲染
|
||
│ │ │ │
|
||
MetonaToast TraceViewer ToolCallCard MessageItem</pre>
|
||
</div>
|
||
</section>
|
||
|
||
<hr class="section-divider">
|
||
|
||
<!-- ===== MetonaToast 分析 ===== -->
|
||
<section class="api-section" id="metona-toast">
|
||
<h2>📢 MetonaToast 项目分析</h2>
|
||
<p class="desc">
|
||
<code>metona-toast</code> v2.0.0 — 你的自研通知组件库,已发布到 npm。
|
||
纯 JavaScript,零依赖,gzip <10KB,设计精致。
|
||
</p>
|
||
|
||
<table class="spec">
|
||
<tr><th>特性</th><th>详情</th><th>Metona Desktop 用途</th></tr>
|
||
<tr><td class="f1">80+ 图标</td><td class="f2">success/error/warning/info/loading 及扩展</td><td>工具结果通知、LLM 错误提示、操作确认</td></tr>
|
||
<tr><td class="f1">11 种动画</td><td class="f2">slide/fade/scale/bounce/flip/rotate/zoom/slideUp/Down/Left/Right</td><td>用 <strong>bounce</strong> 表示重要通知,<strong>fade</strong> 表示信息</td></tr>
|
||
<tr><td class="f1">主题系统</td><td class="f2">light/dark/auto/warm + registerTheme()</td><td>与 Electron 暗色模式无缝同步,auto 跟随系统</td></tr>
|
||
<tr><td class="f1">国际化</td><td class="f2">zh-CN / en-US + addTranslations()</td><td>根据用户系统语言自动切换</td></tr>
|
||
<tr><td class="f1">插件系统</td><td class="f2">keyboard(ESC关闭)/persistence(localStorage)/accessibility</td><td>keyboard 插件让用户 ESC 关闭所有通知</td></tr>
|
||
<tr><td class="f1">可拖拽关闭</td><td class="f2">Pointer Events 拖拽,旋转+透明反馈</td><td>自然手势关闭,符合现代交互习惯</td></tr>
|
||
<tr><td class="f1">毛玻璃效果</td><td class="f2">backdrop-filter: blur(14px) saturate(180%)</td><td>与 Electron 窗口背景融合,有层次感</td></tr>
|
||
<tr><td class="f1">链式调用</td><td class="f2">loading()→success() / loading()→error()</td><td>工具执行中显示 loading,完成后转为 success/error</td></tr>
|
||
<tr><td class="f1">confirm/prompt</td><td class="f2">对话框式确认和输入</td><td>高风险工具调用前的用户确认</td></tr>
|
||
<tr><td class="f1">progress/countdown</td><td class="f2">进度条和倒计时</td><td>长时间操作(模型下载、文件处理)</td></tr>
|
||
</table>
|
||
</section>
|
||
|
||
<section class="api-section" id="toast-integration">
|
||
<h2>⚙️ MetonaToast 集成方案</h2>
|
||
|
||
<h3>安装与配置</h3>
|
||
<div class="code-block">
|
||
<pre><span class="hl-cm">// electron/main.ts — 主进程不直接使用(Node 环境无 DOM)</span>
|
||
<span class="hl-cm">// src/main.tsx — React 渲染进程入口</span>
|
||
<span class="hl-kw">import</span> MeToast <span class="hl-kw">from</span> <span class="hl-str">'metona-toast'</span>;
|
||
|
||
<span class="hl-cm">// 全局配置(应用启动时执行一次)</span>
|
||
MeToast.<span class="hl-fn">configure</span>({
|
||
<span class="hl-prop">position</span>: <span class="hl-str">'top-right'</span>,
|
||
<span class="hl-prop">duration</span>: <span class="hl-num">4000</span>,
|
||
<span class="hl-prop">max</span>: <span class="hl-num">6</span>,
|
||
<span class="hl-prop">theme</span>: <span class="hl-str">'auto'</span>, <span class="hl-cm">// 跟随系统暗色模式</span>
|
||
<span class="hl-prop">animation</span>: <span class="hl-str">'slide'</span>,
|
||
<span class="hl-prop">pauseOnHover</span>: <span class="hl-kw">true</span>,
|
||
<span class="hl-prop">closeOnClick</span>: <span class="hl-kw">true</span>,
|
||
<span class="hl-prop">showProgress</span>: <span class="hl-kw">true</span>,
|
||
<span class="hl-prop">draggable</span>: <span class="hl-kw">true</span>,
|
||
<span class="hl-prop">locale</span>: <span class="hl-str">'zh-CN'</span>,
|
||
});
|
||
|
||
<span class="hl-cm">// 安装插件</span>
|
||
MeToast.<span class="hl-fn">use</span>(<span class="hl-str">'keyboard'</span>); <span class="hl-cm">// ESC 关闭所有</span>
|
||
MeToast.<span class="hl-fn">use</span>(<span class="hl-str">'persistence'</span>); <span class="hl-cm">// 配置持久化</span>
|
||
MeToast.<span class="hl-fn">use</span>(<span class="hl-str">'accessibility'</span>); <span class="hl-cm">// 屏幕阅读器</span></pre>
|
||
</div>
|
||
|
||
<h3>场景映射表</h3>
|
||
<table class="spec">
|
||
<tr><th>Metona 场景</th><th>Toast 调用</th><th>动画</th></tr>
|
||
<tr><td>工具执行成功</td><td class="f1"><code>MeToast.success('文件读取完成')</code></td><td class="f2">slide</td></tr>
|
||
<tr><td>工具执行失败</td><td class="f1"><code>MeToast.error('网络请求超时')</code></td><td class="f2">bounce</td></tr>
|
||
<tr><td>权限校验被拒</td><td class="f1"><code>MeToast.warning('需要权限确认')</code></td><td class="f2">scale</td></tr>
|
||
<tr><td>LLM 开始推理</td><td class="f1"><code>MeToast.info('正在思考...', {duration:0})</code></td><td class="f2">fade</td></tr>
|
||
<tr><td>Session 保存</td><td class="f1"><code>MeToast.success('会话已保存')</code></td><td class="f2">slide</td></tr>
|
||
<tr><td>MCP Server 连接</td><td class="f1"><code>MeToast.success('MCP 已连接', {title:'filesystem'})</code></td><td class="f2">slideUp</td></tr>
|
||
<tr><td>上下文压缩</td><td class="f1"><code>MeToast.info('上下文已压缩', {duration:2000})</code></td><td class="f2">fade</td></tr>
|
||
<tr><td>模型下载进度</td><td class="f1"><code>MeToast.progress('下载中...').setProgress(60)</code></td><td class="f2">slide</td></tr>
|
||
<tr><td>高风险操作确认</td><td class="f1"><code>MeToast.confirm('确定删除文件?')</code></td><td class="f2">scale</td></tr>
|
||
</table>
|
||
|
||
<div class="note-box">
|
||
<strong>💡 主进程通知桥接:</strong>Electron 主进程(Node.js 环境)无法直接调用 DOM Toast。通过 IPC 发送
|
||
<code>mainWindow.webContents.send('toast:show', { type:'success', message:'...' })</code>,
|
||
渲染进程监听并调用 <code>MeToast[event.type](event.message)</code>。
|
||
</div>
|
||
</section>
|
||
|
||
<hr class="section-divider">
|
||
|
||
<!-- ===== 整体布局 ===== -->
|
||
<section class="api-section" id="layout">
|
||
<h2>🏗️ 整体布局设计</h2>
|
||
<p class="desc">参考 Claude Code / Cursor / Hermes Agent 桌面版的布局设计,采用经典的 IDE 式三栏布局。</p>
|
||
|
||
<div class="arch-diagram">
|
||
<pre>
|
||
<span class="hl-cm">┌──────────────────────────────────────────────────────────────┐</span>
|
||
<span class="hl-cm">│ Header Bar [🔮 MetonaAI Desktop] [会话] [设置] [— □ ✕] │</span>
|
||
<span class="hl-cm">├──────────┬────────────────────────────────┬──────────────────┤</span>
|
||
<span class="hl-cm">│ │ │ │</span>
|
||
<span class="hl-cm">│ Sidebar │ Main Chat Area │ Detail Panel │</span>
|
||
<span class="hl-cm">│ │ │ (可折叠) │</span>
|
||
<span class="hl-cm">│ ┌──────┐ │ ┌──────────────────────────┐ │ ┌──────────────┐│</span>
|
||
<span class="hl-cm">│ │ 会话 │ │ │ [Agent] 💭 思考过程... │ │ │ Trace Viewer ││</span>
|
||
<span class="hl-cm">│ │ 列表 │ │ │ [Agent] 🔧 read_file │ │ │ ││</span>
|
||
<span class="hl-cm">│ │ │ │ │ [Agent] 📄 文件内容 │ │ │ #1 THINKING ││</span>
|
||
<span class="hl-cm">│ │ + 新建│ │ │ [Agent] 结论: ... │ │ │ #2 PARSING ││</span>
|
||
<span class="hl-cm">│ │ │ │ │ │ │ │ #3 EXECUTING ││</span>
|
||
<span class="hl-cm">│ │ ──── │ │ │ │ │ │ #4 OBSERVING ││</span>
|
||
<span class="hl-cm">│ │ 工具 │ │ │ │ │ │ #5 REFLECTING ││</span>
|
||
<span class="hl-cm">│ │ 管理 │ │ │ │ │ │ #6 COMPRESSING ││</span>
|
||
<span class="hl-cm">│ │ 工具 │ │ ├──────────────────────────┤ │ ├──────────────┤│</span>
|
||
<span class="hl-cm">│ │ 管理 │ │ │ [输入框..............] [发送] │ │ │ Token 用量 ││</span>
|
||
<span class="hl-cm">│ │ │ │ │ [📎文件] [🔧工具] [⚙️] │ │ │ 输入: 1240 ││</span>
|
||
<span class="hl-cm">│ │ ──── │ │ └──────────────────────────┘ │ │ 输出: 350 ││</span>
|
||
<span class="hl-cm">│ │ 记忆 │ │ │ └──────────────┘│</span>
|
||
<span class="hl-cm">│ │ 搜索 │ │ │ │</span>
|
||
<span class="hl-cm">│ └──────┘ │ │ │</span>
|
||
<span class="hl-cm">├──────────┴────────────────────────────────┴──────────────────┤</span>
|
||
<span class="hl-cm">│ Status Bar 🟢 Agent Ready | deepseek-v4-pro | Tokens: 1.2K │</span>
|
||
<span class="hl-cm">└──────────────────────────────────────────────────────────────┘</span>
|
||
</pre>
|
||
</div>
|
||
|
||
<table class="spec">
|
||
<tr><th>区域</th><th>宽度</th><th>内容</th></tr>
|
||
<tr><td class="f1">Header Bar</td><td class="f2">全宽</td><td>Logo + 窗口控制 + 快捷操作</td></tr>
|
||
<tr><td class="f1">Sidebar (可折叠)</td><td class="f2">260px</td><td>会话列表、工具管理、记忆搜索、MCP 管理</td></tr>
|
||
<tr><td class="f1">Main Chat Area</td><td class="f2">弹性</td><td>消息流 + 输入框 + 流式渲染</td></tr>
|
||
<tr><td class="f1">Detail Panel (可折叠)</td><td class="f2">320px</td><td>TraceViewer + Token 用量 + 工具状态</td></tr>
|
||
<tr><td class="f1">Status Bar</td><td class="f2">全宽</td><td>Agent 状态、Provider 信息、Token 统计</td></tr>
|
||
</table>
|
||
|
||
<h3>布局模式</h3>
|
||
<p class="desc">为适应不同场景和屏幕尺寸,提供三种布局模式:</p>
|
||
<table class="spec">
|
||
<tr><th>模式</th><th>Sidebar</th><th>DetailPanel</th><th>Chat 区域</th><th>触发方式</th></tr>
|
||
<tr><td class="f1">默认模式</td><td class="f2">展开 260px</td><td class="f2">展开 320px</td><td class="f2">弹性(约 1340px @1920)</td><td class="f2">默认状态</td></tr>
|
||
<tr><td class="f1">紧凑模式</td><td class="f2">折叠 56px 图标条</td><td class="f2">折叠 48px 图标条</td><td class="f2">弹性(约 1816px @1920)</td><td class="f2"><code>Cmd/Ctrl+B</code> + <code>Cmd/Ctrl+J</code></td></tr>
|
||
<tr><td class="f1">专注模式</td><td class="f2">隐藏</td><td class="f2">隐藏</td><td class="f2">全宽(约 1920px)</td><td class="f2"><code>Cmd/Ctrl+Shift+F</code></td></tr>
|
||
</table>
|
||
<div class="note-box">
|
||
<strong>💡 布局设计原则:</strong>Sidebar 和 DetailPanel 均为<strong>可折叠抽屉式</strong>,默认展开完整面板,折叠后只保留图标条(悬停可预览,点击展开为浮层)。Chat 区域在两侧折叠时获得最大宽度,适合宽屏代码展示和 Markdown 渲染。
|
||
</div>
|
||
|
||
<h3>消息布局:全宽卡片流</h3>
|
||
<p class="desc">放弃传统聊天应用的左右分栏气泡布局,采用<strong>全宽卡片流</strong>布局(参考 Claude / ChatGPT)。Agent 的核心交互是任务执行而非聊天,工具调用结果、代码块、表格都需要全宽展示。</p>
|
||
<table class="spec">
|
||
<tr><th>消息类型</th><th>布局</th><th>对齐</th><th>宽度</th></tr>
|
||
<tr><td class="f1">User Message</td><td class="f2">浅色背景卡片 + 用户头像</td><td class="f2">左对齐</td><td class="f2">全宽(max-width: 768px 居中)</td></tr>
|
||
<tr><td class="f1">Agent Thought</td><td class="f2">缩进灰色虚线框</td><td class="f2">左对齐</td><td class="f2">全宽(可折叠)</td></tr>
|
||
<tr><td class="f1">Agent ToolCall</td><td class="f2">缩进彩色卡片 + 状态图标</td><td class="f2">左对齐</td><td class="f2">全宽</td></tr>
|
||
<tr><td class="f1">Agent Answer</td><td class="f2">无背景或极浅背景 + Agent 头像</td><td class="f2">左对齐</td><td class="f2">全宽 Markdown 渲染</td></tr>
|
||
</table>
|
||
<div class="note-box">
|
||
<strong>💡 为什么不用气泡布局:</strong>传统左右分栏气泡将用户消息右对齐,导致 Agent 的长回复(含代码块、表格、图表)被压缩到一半宽度。全宽卡片流让所有内容都能利用完整宽度,阅读体验显著提升。用户消息虽然全宽,但通过 <code>max-width: 768px</code> 居中限制可读性。
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ===== 聊天面板 ===== -->
|
||
<section class="api-section" id="chat-panel">
|
||
<h2>💬 聊天面板设计</h2>
|
||
|
||
<h3>消息类型矩阵</h3>
|
||
<table class="spec">
|
||
<tr><th>消息角色</th><th>视觉样式</th><th>内容渲染</th><th>交互</th></tr>
|
||
<tr>
|
||
<td class="f1">User Message</td>
|
||
<td class="f2">全宽 / 浅色背景卡片 / 用户头像 / 左对齐</td>
|
||
<td>纯文本 + 附件缩略图</td>
|
||
<td>双击编辑 / 右键菜单</td>
|
||
</tr>
|
||
<tr>
|
||
<td class="f1">Agent Thought</td>
|
||
<td class="f2">左对齐 / 虚线边框 / 💭 图标 / 可折叠</td>
|
||
<td>纯文本(等宽字体)</td>
|
||
<td>默认折叠,点击展开</td>
|
||
</tr>
|
||
<tr>
|
||
<td class="f1">Agent Tool Call</td>
|
||
<td class="f2">左对齐 / 紫色边框 / 🔧 图标</td>
|
||
<td>工具名 + JSON 参数 + 状态图标</td>
|
||
<td>悬停显示参数详情、点击跳转 Trace</td>
|
||
</tr>
|
||
<tr>
|
||
<td class="f1">Agent Tool Result</td>
|
||
<td class="f2">左对齐 / 青色边框 / 📄 图标</td>
|
||
<td>结果摘要 + 文件路径/行数/耗时</td>
|
||
<td>点击打开完整结果</td>
|
||
</tr>
|
||
<tr>
|
||
<td class="f1">Agent Answer</td>
|
||
<td class="f2">左对齐 / 无背景 / Agent 头像</td>
|
||
<td>Markdown + 代码高亮 + 图表</td>
|
||
<td>代码块一键复制、链接可点击</td>
|
||
</tr>
|
||
<tr>
|
||
<td class="f1">System Notification</td>
|
||
<td class="f2">居中 / 灰色 / 小字</td>
|
||
<td>时间戳 / 状态变化</td>
|
||
<td>不可交互</td>
|
||
</tr>
|
||
</table>
|
||
|
||
<h3>流式渲染策略</h3>
|
||
<p class="desc">
|
||
使用 <code>requestAnimationFrame</code> + 节流(每 16ms 一次)平滑更新 DOM。
|
||
Thought 内容进入时显示 <code>💭 思考中...</code> 加载动画,收到 <code>thinking_end</code> 后折叠。
|
||
工具调用使用 <code>ToolCallCard</code> 骨架屏先行占位,结果到达时填充。
|
||
</p>
|
||
</section>
|
||
|
||
<!-- ===== Trace Viewer ===== -->
|
||
<section class="api-section" id="trace-viewer">
|
||
<h2>🔍 Trace Viewer 设计</h2>
|
||
<p class="desc">置于右侧 Detail Panel,以时间轴方式展示每次 ReAct 迭代的完整过程。用户可展开每一步查看细节。</p>
|
||
|
||
<div class="arch-diagram">
|
||
<pre>
|
||
<span class="hl-cm">┌─ Trace Viewer ──────────────────────────────────┐</span>
|
||
<span class="hl-cm">│ Session: 数据分析任务 迭代: 2/20 │</span>
|
||
<span class="hl-cm">│─────────────────────────────────────────────────│</span>
|
||
<span class="hl-cm">│ │</span>
|
||
<span class="hl-cm">│ ▼ #1 THINKING 1.2s 120 tok │</span>
|
||
<span class="hl-cm">│ 💭 "需要先读取目标文件..." │</span>
|
||
<span class="hl-cm">│ │</span>
|
||
<span class="hl-cm">│ ▶ #2 PARSING 0.1s │</span>
|
||
<span class="hl-cm">│ │</span>
|
||
<span class="hl-cm">│ ▼ #3 EXECUTING 0.3s │</span>
|
||
<span class="hl-cm">│ 🔧 read_file: /data.csv ✓ 5ms │</span>
|
||
<span class="hl-cm">│ 📄 1000 rows, 3 cols │</span>
|
||
<span class="hl-cm">│ │</span>
|
||
<span class="hl-cm">│ ▶ #4 OBSERVING 0.1s │</span>
|
||
<span class="hl-cm">│ │</span>
|
||
<span class="hl-cm">│ ▶ #5 REFLECTING 0.2s │</span>
|
||
<span class="hl-cm">│ 💭 "数据结构清晰,可以进行下一步分析..." │</span>
|
||
<span class="hl-cm">│ │</span>
|
||
<span class="hl-cm">│ ▶ #6 COMPRESSING 0.1s │</span>
|
||
<span class="hl-cm">│ 📦 上下文已压缩 (3.2K → 1.8K) │</span>
|
||
<span class="hl-cm">│ │</span>
|
||
<span class="hl-cm">│ ○ #7 THINKING (当前) │</span>
|
||
<span class="hl-cm">│ ⏳ 正在调用 LLM... │</span>
|
||
<span class="hl-cm">│ │</span>
|
||
<span class="hl-cm">│─────────────────────────────────────────────────│</span>
|
||
<span class="hl-cm">│ Token: 入 1.2K | 出 0.4K | 总计 1.6K │</span>
|
||
<span class="hl-cm">│ 耗时: 2.3s | Provider: DeepSeek v4-pro │</span>
|
||
<span class="hl-cm">└─────────────────────────────────────────────────┘</span>
|
||
</pre>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ===== 工具调用 UI ===== -->
|
||
<section class="api-section" id="tool-call">
|
||
<h2>🔧 工具调用 UI</h2>
|
||
|
||
<h3>ToolCallCard 状态机</h3>
|
||
<table class="spec">
|
||
<tr><th>状态</th><th>图标</th><th>颜色</th><th>行为</th></tr>
|
||
<tr><td class="f1">pending</td><td class="f2">⏳ 旋转</td><td class="f2" style="color:var(--amber)">#fbbf24</td><td>骨架屏占位,等待工具执行</td></tr>
|
||
<tr><td class="f1">executing</td><td class="f2">🔧 脉冲</td><td class="f2" style="color:var(--purple)">#a855f7</td><td>显示参数摘要</td></tr>
|
||
<tr><td class="f1">success</td><td class="f2">✅</td><td class="f2" style="color:var(--green)">#34d399</td><td>显示结果摘要 + 执行耗时</td></tr>
|
||
<tr><td class="f1">error</td><td class="f2">❌</td><td class="f2" style="color:var(--red)">#f87171</td><td>显示错误信息 + 重试按钮</td></tr>
|
||
<tr><td class="f1">blocked</td><td class="f2">🚫</td><td class="f2" style="color:var(--orange)">#fb923c</td><td>显示拒绝原因 + 手动授权按钮</td></tr>
|
||
</table>
|
||
|
||
<h3>高风险操作确认流程</h3>
|
||
<div class="code-block">
|
||
<pre><span class="hl-cm"># 用户在聊天面板看到:</span>
|
||
┌─────────────────────────────────────────┐
|
||
│ 🔧 write_file │
|
||
│ 目标: /home/user/config.yaml │
|
||
│ 风险: ⚠️ MEDIUM — 将覆盖已有文件 │
|
||
│ │
|
||
│ [查看差异] [✅ 确认执行] [❌ 取消] │
|
||
└─────────────────────────────────────────┘
|
||
|
||
<span class="hl-cm"># 用户点击「确认执行」后:</span>
|
||
MeToast.<span class="hl-fn">success</span>({ <span class="hl-prop">title</span>: <span class="hl-str">'已授权'</span>, <span class="hl-prop">message</span>: <span class="hl-str">'write_file 正在执行...'</span> });
|
||
|
||
<span class="hl-cm"># 用户点击「取消」后:</span>
|
||
MeToast.<span class="hl-fn">warning</span>(<span class="hl-str">'操作已取消'</span>);</pre>
|
||
</div>
|
||
|
||
<h3>确认流程优化:信任会话</h3>
|
||
<p class="desc">为避免密集操作场景(如批量重构代码)下逐次确认打断流程,引入<strong>信任会话</strong>机制:</p>
|
||
<table class="spec">
|
||
<tr><th>模式</th><th>行为</th><th>触发方式</th></tr>
|
||
<tr><td class="f1">默认模式</td><td class="f2">MEDIUM+ 操作逐次确认</td><td class="f2">默认</td></tr>
|
||
<tr><td class="f1">信任会话</td><td class="f2">MEDIUM 操作不逐次确认,会话结束时生成操作摘要供审查</td><td class="f2">设置中开启</td></tr>
|
||
<tr><td class="f1">同类免确认</td><td class="f2">同一会话内同类操作(如 write_file)首次确认后不再确认</td><td class="f2">确认弹窗勾选「本次会话不再确认同类操作」</td></tr>
|
||
<tr><td class="f1">批量确认</td><td class="f2">连续多个同类操作合并为一个确认弹窗</td><td class="f2">Agent 连续发起 ≥3 个同类操作时自动触发</td></tr>
|
||
</table>
|
||
<div class="warn-box">
|
||
<strong>⚠ HIGH 级别操作始终需要确认</strong>,不受信任会话影响。CRITICAL 级别需要双人复核(未来计划)。
|
||
</div>
|
||
<div class="note-box">
|
||
<strong>💡 确认弹窗增强:</strong>增加「查看命令」展开区域,显示完整的工具调用参数(JSON 格式),让用户做出知情决策。
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ===== 设置面板 ===== -->
|
||
<section class="api-section" id="settings">
|
||
<h2>⚙️ 设置面板</h2>
|
||
<p class="desc">分 Tab 展示,配置变更即时持久化到 SQLite 数据库。</p>
|
||
|
||
<table class="spec">
|
||
<tr><th>Tab</th><th>内容</th></tr>
|
||
<tr><td class="f1">LLM 配置</td><td class="f2">Provider 选择、API Key、模型名称、参数滑块(temperature/maxTokens/contextWindow)</td></tr>
|
||
<tr><td class="f1">Agent 配置</td><td class="f2">最大迭代次数、超时、Thinking 开关、反思模式、压缩阈值</td></tr>
|
||
<tr><td class="f1">工具管理</td><td class="f2">9 个基础工具开关、风险级别配置、路径白名单、命令黑名单</td></tr>
|
||
<tr><td class="f1">MCP 服务</td><td class="f2">Server 列表、添加/删除/启停、连接状态指示灯</td></tr>
|
||
<tr><td class="f1">外观</td><td class="f2">主题(light/dark/auto)、字体大小、消息密度、动画开关</td></tr>
|
||
<tr><td class="f1">日志与数据</td><td class="f2">日志级别、数据库位置、数据导出/清理、使用统计</td></tr>
|
||
</table>
|
||
</section>
|
||
|
||
<hr class="section-divider">
|
||
|
||
<!-- ===== 组件树 ===== -->
|
||
<section class="api-section" id="component-tree">
|
||
<h2>🌲 组件树</h2>
|
||
|
||
<div class="note-box">
|
||
<strong>🎨 UI 组件库:</strong>所有 UI 交互组件强制使用 <strong>Material UI (MUI)</strong>(<code>@mui/material</code>)。按钮、输入框、弹窗、选择器、表单控件、标签页、提示、布局、进度条、卡片等均使用 MUI 组件。除非 MUI 确认不存在对应组件,否则<strong>禁止自写 UI 组件</strong>。Tailwind CSS 仅作为 MUI 的辅助样式补充(间距、颜色变量),不可替代 MUI 组件。
|
||
</div>
|
||
|
||
<div class="arch-diagram">
|
||
<pre>
|
||
<span class="hl-cm">AppLayout</span>
|
||
├── <span class="hl-box">Header</span> (Logo + SessionSelector + SettingsButton)
|
||
├── <span class="hl-box">Sidebar</span>
|
||
│ ├── SessionList (会话列表 + 新建/搜索/分组/置顶)
|
||
│ ├── ToolManager (工具状态 + MCP 管理)
|
||
│ └── MemorySearch (记忆检索面板)
|
||
├── <span class="hl-box">ChatPanel</span>
|
||
│ ├── MessageList (虚拟滚动 · 全宽卡片流)
|
||
│ │ ├── MessageItem (User/Assistant/Tool/System)
|
||
│ │ ├── ThoughtBlock (可折叠思考内容)
|
||
│ │ ├── ToolCallCard (工具调用卡片)
|
||
│ │ └── ToolResultBlock (工具结果块)
|
||
│ ├── StreamingIndicator (流式加载)
|
||
│ └── ChatInput (输入框 + 附件 + 工具选择 + 上下文指示器)
|
||
├── <span class="hl-box">DetailPanel</span> (右侧,可折叠为图标条)
|
||
│ ├── TraceViewer (ReAct 迭代追踪)
|
||
│ ├── TokenUsage (Token 统计图表)
|
||
│ └── AgentMonitor (Agent 状态指示)
|
||
├── <span class="hl-box">StatusBar</span> (状态栏)
|
||
├── <span class="hl-box">ToastContainer</span> (MetonaToast 通知层)
|
||
├── <span class="hl-box">OnboardingWizard</span> (首次使用引导)
|
||
└── <span class="hl-box">CommandPalette</span> (Cmd+K 快速搜索)
|
||
</pre>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ===== 首次使用引导 ===== -->
|
||
<section class="api-section" id="onboarding">
|
||
<h2>👋 首次使用引导(Onboarding)</h2>
|
||
<p class="desc">首次启动应用时自动展示引导向导,帮助用户完成初始配置。向导完成后不再显示(可通过设置重新触发)。</p>
|
||
|
||
<h3>引导流程</h3>
|
||
<div class="flow-step" style="display:flex;gap:14px;margin-bottom:14px;align-items:flex-start"><span style="min-width:28px;height:28px;background:var(--accent);color:#000;border-radius:50%;display:flex;align-items:center;justify-content:center;font-weight:700;font-size:13px;flex-shrink:0">1</span><span style="font-size:14px"><strong>欢迎页</strong>:Metona 是什么、能做什么(3 句话 + 动图展示)</span></div>
|
||
<div class="flow-step" style="display:flex;gap:14px;margin-bottom:14px;align-items:flex-start"><span style="min-width:28px;height:28px;background:var(--accent);color:#000;border-radius:50%;display:flex;align-items:center;justify-content:center;font-weight:700;font-size:13px;flex-shrink:0">2</span><span style="font-size:14px"><strong>配置 LLM</strong>:选择 Provider(DeepSeek/Agnes/Ollama)→ 输入 API Key 或 Ollama 地址 → 测试连接</span></div>
|
||
<div class="flow-step" style="display:flex;gap:14px;margin-bottom:14px;align-items:flex-start"><span style="min-width:28px;height:28px;background:var(--accent);color:#000;border-radius:50%;display:flex;align-items:center;justify-content:center;font-weight:700;font-size:13px;flex-shrink:0">3</span><span style="font-size:14px"><strong>自定义 Agent</strong>:选择预设角色或自定义 SOUL.md → 填写 USERS.md(技术栈、偏好)</span></div>
|
||
<div class="flow-step" style="display:flex;gap:14px;margin-bottom:14px;align-items:flex-start"><span style="min-width:28px;height:28px;background:var(--accent);color:#000;border-radius:50%;display:flex;align-items:center;justify-content:center;font-weight:700;font-size:13px;flex-shrink:0">4</span><span style="font-size:14px"><strong>工作空间</strong>:确认默认路径 <code>~/MetonaWorkspaces/default/</code> 或选择自定义路径</span></div>
|
||
<div class="flow-step" style="display:flex;gap:14px;margin-bottom:14px;align-items:flex-start"><span style="min-width:28px;height:28px;background:var(--accent);color:#000;border-radius:50%;display:flex;align-items:center;justify-content:center;font-weight:700;font-size:13px;flex-shrink:0">5</span><span style="font-size:14px"><strong>开始使用</strong>:展示一个示例对话,让用户感受 Agent 能力</span></div>
|
||
|
||
<div class="note-box">
|
||
<strong>💡 设计要点:</strong>每一步都可以「跳过」,不强制完成。跳过配置 LLM 的用户会在首次发送消息时提示配置。向导状态记录在 <code>app_config</code> 表中(<code>onboarding.completed = true/false</code>)。
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ===== 快捷键 ===== -->
|
||
<section class="api-section" id="shortcuts">
|
||
<h2>⌨️ 快捷键体系</h2>
|
||
<p class="desc">快捷键是桌面 Agent 应用的核心生产力工具。所有快捷键支持 macOS(Cmd)和 Windows/Linux(Ctrl)。</p>
|
||
|
||
<table class="spec">
|
||
<tr><th>快捷键</th><th>功能</th><th>分类</th></tr>
|
||
<tr><td class="f1"><code>Cmd/Ctrl + N</code></td><td>新建会话</td><td class="f2">会话</td></tr>
|
||
<tr><td class="f1"><code>Cmd/Ctrl + K</code></td><td>快速搜索(会话/记忆/文件)</td><td class="f2">全局</td></tr>
|
||
<tr><td class="f1"><code>Cmd/Ctrl + Enter</code></td><td>发送消息</td><td class="f2">输入</td></tr>
|
||
<tr><td class="f1"><code>Cmd/Ctrl + Shift + Enter</code></td><td>换行(多行输入)</td><td class="f2">输入</td></tr>
|
||
<tr><td class="f1"><code>Cmd/Ctrl + .</code></td><td>中断 Agent 执行</td><td class="f2">Agent</td></tr>
|
||
<tr><td class="f1"><code>Cmd/Ctrl + Shift + F</code></td><td>专注模式(隐藏 Sidebar + DetailPanel)</td><td class="f2">布局</td></tr>
|
||
<tr><td class="f1"><code>Cmd/Ctrl + B</code></td><td>折叠/展开 Sidebar</td><td class="f2">布局</td></tr>
|
||
<tr><td class="f1"><code>Cmd/Ctrl + J</code></td><td>折叠/展开 DetailPanel</td><td class="f2">布局</td></tr>
|
||
<tr><td class="f1"><code>Cmd/Ctrl + ,</code></td><td>打开设置</td><td class="f2">全局</td></tr>
|
||
<tr><td class="f1"><code>Cmd/Ctrl + [ / ]</code></td><td>历史会话切换(上一个/下一个)</td><td class="f2">会话</td></tr>
|
||
<tr><td class="f1"><code>Esc</code></td><td>关闭弹窗/取消焦点</td><td class="f2">全局</td></tr>
|
||
<tr><td class="f1"><code>Cmd/Ctrl + L</code></td><td>聚焦输入框</td><td class="f2">输入</td></tr>
|
||
<tr><td class="f1"><code>Cmd/Ctrl + Shift + C</code></td><td>复制最后一条 Agent 回复</td><td class="f2">编辑</td></tr>
|
||
<tr><td class="f1"><code>Cmd/Ctrl + D</code></td><td>切换暗色/亮色主题</td><td class="f2">外观</td></tr>
|
||
</table>
|
||
|
||
<div class="note-box">
|
||
<strong>💡 输入框智能特性:</strong>
|
||
<br>• <strong>多行自适应</strong>:输入框默认单行,输入多行时自动扩展(最大 6 行后滚动)
|
||
<br>• <strong>文件拖拽</strong>:拖拽文件到输入框自动添加为附件,显示文件名 + 大小
|
||
<br>• <strong>图片粘贴</strong>:粘贴剪贴板图片自动转为 base64 附件
|
||
<br>• <strong><code>/</code> 命令</strong>:输入 <code>/</code> 弹出命令菜单(<code>/tool</code> 选择工具、<code>/memory</code> 搜索记忆、<code>/clear</code> 清空会话、<code>/export</code> 导出会话)
|
||
<br>• <strong><code>@</code> 提及</strong>:输入 <code>@</code> 弹出文件/会话提及菜单,快速引用上下文
|
||
<br>• <strong>上下文指示器</strong>:输入框下方显示当前上下文使用率(如 "Context: 12K / 128K (9%)"),接近上限时变色警告
|
||
<br>• <strong>草稿自动保存</strong>:未发送的输入内容自动保存,切换会话后恢复
|
||
</div>
|
||
|
||
<h3>右键菜单设计</h3>
|
||
<table class="spec">
|
||
<tr><th>对象</th><th>菜单项</th></tr>
|
||
<tr><td class="f1">消息</td><td class="f2">复制 · 引用回复 · 编辑(仅用户消息) · 删除 · 重新生成(仅 Agent 消息)</td></tr>
|
||
<tr><td class="f1">工具调用卡片</td><td class="f2">查看参数 · 查看完整结果 · 复制结果 · 重新执行</td></tr>
|
||
<tr><td class="f1">会话项</td><td class="f2">重命名 · 置顶 · 归档 · 删除 · 导出</td></tr>
|
||
<tr><td class="f1">代码块</td><td class="f2">复制代码 · 在编辑器中打开</td></tr>
|
||
<tr><td class="f1">Trace 步骤</td><td class="f2">复制 Thought · 复制工具参数 · 导出步骤详情</td></tr>
|
||
</table>
|
||
</section>
|
||
|
||
<!-- ===== 主题系统 ===== -->
|
||
<section class="api-section" id="theme-system">
|
||
<h2>🎨 主题系统</h2>
|
||
<p class="desc">双主题引擎:CSS Variables(应用级)+ MetonaToast Theme API(通知级),统一 token 体系。</p>
|
||
|
||
<h3>CSS 变量 Token 体系</h3>
|
||
<div class="code-block">
|
||
<pre><span class="hl-cm">/* 亮色主题 */</span>
|
||
:root[data-theme=<span class="hl-str">"light"</span>] {
|
||
--bg-primary: <span class="hl-str">#ffffff</span>;
|
||
--bg-secondary: <span class="hl-str">#f8fafc</span>;
|
||
--bg-tertiary: <span class="hl-str">#f1f5f9</span>;
|
||
--text-primary: <span class="hl-str">#0f172a</span>;
|
||
--text-secondary: <span class="hl-str">#334155</span>; <span class="hl-cm">/* 对比度 ~8:1,满足 WCAG AA */</span>
|
||
--border-color: <span class="hl-str">#e2e8f0</span>;
|
||
--accent: <span class="hl-str">#6366f1</span>;
|
||
}
|
||
|
||
<span class="hl-cm">/* 暗色主题 */</span>
|
||
:root[data-theme=<span class="hl-str">"dark"</span>] {
|
||
--bg-primary: <span class="hl-str">#0f1117</span>;
|
||
--bg-secondary: <span class="hl-str">#1a1d27</span>;
|
||
--bg-tertiary: <span class="hl-str">#252836</span>;
|
||
--text-primary: <span class="hl-str">#e1e4ed</span>;
|
||
--text-secondary: <span class="hl-str">#64748b</span>; <span class="hl-cm">/* 对比度 ~4.6:1,满足 WCAG AA */</span>
|
||
--border-color: <span class="hl-str">#2a2d3a</span>;
|
||
--accent: <span class="hl-str">#818cf8</span>;
|
||
}</pre>
|
||
</div>
|
||
|
||
<div class="note-box">
|
||
<strong>💡 主题同步:</strong>Electron 的 <code>nativeTheme.themeSource</code> 控制 Chromium 的 <code>prefers-color-scheme</code>。
|
||
MetonaToast 的 <code>theme:'auto'</code> 自动跟随。应用级 CSS 通过 <code>matchMedia('(prefers-color-scheme: dark)')</code> 监听切换。
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ===== 动效 ===== -->
|
||
<section class="api-section" id="animation">
|
||
<h2>✨ 动效规范</h2>
|
||
|
||
<table class="spec">
|
||
<tr><th>场景</th><th>动效</th><th>时长</th><th>缓动</th></tr>
|
||
<tr><td class="f1">消息进入</td><td class="f2">从下方淡入 + 上移 10px</td><td>300ms</td><td class="f2">ease-out</td></tr>
|
||
<tr><td class="f1">流式文本</td><td class="f2">逐字出现(CSS typing 模拟)</td><td>—</td><td class="f2">—</td></tr>
|
||
<tr><td class="f1">Thought 展开</td><td class="f2">max-height 过渡 + 淡入</td><td>250ms</td><td class="f2">ease</td></tr>
|
||
<tr><td class="f1">Tool 状态切换</td><td class="f2">图标旋转/脉冲 + 边框颜色渐变</td><td>400ms</td><td class="f2">ease-in-out</td></tr>
|
||
<tr><td class="f1">Sidebar 折叠</td><td class="f2">width 过渡</td><td>300ms</td><td class="f2">cubic-bezier(0.4,0,0.2,1)</td></tr>
|
||
<tr><td class="f1">Toast 通知</td><td class="f2">11 种(MetonaToast)</td><td>400-650ms</td><td class="f2">cubic-bezier (库内)</td></tr>
|
||
<tr><td class="f1">加载骨架屏</td><td class="f2">shimmer 光泽扫过</td><td>1.5s loop</td><td class="f2">linear infinite</td></tr>
|
||
<tr><td class="f1">悬停反馈</td><td class="f2">scale(1.02) + shadow 提升</td><td>150ms</td><td class="f2">ease-out</td></tr>
|
||
</table>
|
||
|
||
<h3>性能保护机制</h3>
|
||
<p class="desc">动效在低性能设备和用户偏好下自动降级:</p>
|
||
<table class="spec">
|
||
<tr><th>条件</th><th>降级策略</th></tr>
|
||
<tr><td class="f1"><code>prefers-reduced-motion: reduce</code></td><td class="f2">所有动效即时切换(duration: 0ms),流式文本改为闪烁光标</td></tr>
|
||
<tr><td class="f1">FPS < 30(检测到掉帧)</td><td class="f2">骨架屏 shimmer 改为静态灰色背景,悬停 scale 改为仅 shadow</td></tr>
|
||
<tr><td class="f1">设置中关闭「动画效果」</td><td class="f2">等同于 <code>prefers-reduced-motion</code>,所有动效禁用</td></tr>
|
||
</table>
|
||
<div class="note-box">
|
||
<strong>💡 流式文本优化:</strong>放弃逐字 DOM 更新方案(性能差),改为 <code>caret-color</code> 闪烁光标 + CSS <code>animation</code> 实现打字机效果。文本内容通过 <code>requestAnimationFrame</code> 批量插入(每帧一次),避免高频 DOM 操作。
|
||
</div>
|
||
<div class="note-box">
|
||
<strong>💡 设置面板增加「动画效果」开关:</strong>三档选项——<code>开启</code>(全动效)/ <code>关闭</code>(禁用所有动效)/ <code>自动跟随系统</code>(默认,读取 <code>prefers-reduced-motion</code>)。配置存储在 <code>app_config</code> 表中(<code>ui.animationMode = 'auto' | 'on' | 'off'</code>)。
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ===== 错误恢复 ===== -->
|
||
<section class="api-section" id="error-recovery">
|
||
<h2>🚧 错误恢复体验</h2>
|
||
<p class="desc">错误不是终点,是引导用户修正的入口。不同错误类型采用不同的交互策略:</p>
|
||
|
||
<table class="spec">
|
||
<tr><th>错误类型</th><th>UI 展示</th><th>恢复策略</th><th>用户操作</th></tr>
|
||
<tr><td class="f1">工具执行错误<br>(如文件不存在)</td><td class="f2">内联在聊天流中<br>红色边框卡片</td><td class="f2">Agent 自动分析错误 → 决定重试或换策略</td><td class="f2">通常无需操作;如需用户输入,Agent 在聊天中内联提问</td></tr>
|
||
<tr><td class="f1">LLM 调用错误<br>(如 API 超时)</td><td class="f2">错误卡片 + 操作按钮</td><td class="f2">等待用户决策</td><td class="f2"><code>[重试]</code> / <code>[切换 Provider]</code> / <code>[查看详情]</code></td></tr>
|
||
<tr><td class="f1">解析错误<br>(LLM 输出不符合格式)</td><td class="f2">用户无感知<br>(静默重试)</td><td class="f2">静默重试(最多 3 次),超出后显示提示</td><td class="f2">超出重试后显示「模型输出异常」+ <code>[重试]</code></td></tr>
|
||
<tr><td class="f1">权限拒绝<br>(用户取消操作)</td><td class="f2">灰色卡片</td><td class="f2">Agent 收到取消信号,调整策略</td><td class="f2"><code>[修改权限设置]</code> 链接</td></tr>
|
||
<tr><td class="f1">网络连接错误</td><td class="f2">StatusBar 红色指示灯 + Toast</td><td class="f2">自动检测网络恢复后提示用户</td><td class="f2"><code>[重试]</code> / <code>[离线模式]</code>(仅 Ollama 可用)</td></tr>
|
||
</table>
|
||
<div class="note-box">
|
||
<strong>💡 所有错误在 TraceViewer 中留痕:</strong>每个错误作为一个独立 Trace 步骤,记录完整的错误信息、堆栈、重试历史。用户可以事后展开查看,不影响正常对话流。
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ===== 会话管理 ===== -->
|
||
<section class="api-section" id="session-management">
|
||
<h2>📁 会话管理</h2>
|
||
<p class="desc">Sidebar 会话列表支持搜索、分组、置顶、归档,适应长期使用场景。</p>
|
||
|
||
<h3>会话列表功能</h3>
|
||
<table class="spec">
|
||
<tr><th>功能</th><th>交互方式</th><th>说明</th></tr>
|
||
<tr><td class="f1">搜索</td><td class="f2">会话列表顶部搜索框</td><td class="f2">按标题和消息内容模糊搜索(<code>fuse.js</code>)</td></tr>
|
||
<tr><td class="f1">置顶</td><td class="f2">右键菜单 → 置顶</td><td class="f2">置顶会话固定在列表顶部,显示 📌 图标</td></tr>
|
||
<tr><td class="f1">分组</td><td class="f2">自动按工作空间分组</td><td class="f2">每个工作空间一个折叠组,可展开/收起</td></tr>
|
||
<tr><td class="f1">归档</td><td class="f2">右键菜单 → 归档</td><td class="f2">归档的会话移入「归档」折叠区,不占主列表空间,可恢复</td></tr>
|
||
<tr><td class="f1">重命名</td><td class="f2">双击会话标题 / 右键菜单</td><td class="f2">内联编辑,回车保存</td></tr>
|
||
<tr><td class="f1">导出</td><td class="f2">右键菜单 → 导出</td><td class="f2">导出为 Markdown / JSON</td></tr>
|
||
<tr><td class="f1">删除</td><td class="f2">右键菜单 → 删除</td><td class="f2">移入回收站(可恢复 30 天)</td></tr>
|
||
</table>
|
||
<div class="note-box">
|
||
<strong>💡 会话项信息:</strong>每个会话项显示——会话标题(自动生成或用户重命名)、最后活跃时间(如「3 分钟前」)、消息数、Agent 状态指示灯(进行中显示绿色脉冲)。
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ===== 窗口管理 ===== -->
|
||
<section class="api-section" id="window-management">
|
||
<h2>🖥️ 窗口管理</h2>
|
||
<p class="desc">Electron 桌面应用的窗口管理习惯设计:</p>
|
||
|
||
<table class="spec">
|
||
<tr><th>功能</th><th>行为</th><th>配置项</th></tr>
|
||
<tr><td class="f1">关闭窗口</td><td class="f2">最小化到系统托盘(默认),不退出应用</td><td class="f2"><code>app.closeToTray = true</code>(可关闭)</td></tr>
|
||
<tr><td class="f1">托盘图标</td><td class="f2">显示 Agent 状态:空闲(白色)/ 思考中(蓝色脉冲)/ 执行中(绿色旋转)</td><td class="f2">—</td></tr>
|
||
<tr><td class="f1">托盘菜单</td><td class="f2">新建会话 · 显示窗口 · 退出</td><td class="f2">—</td></tr>
|
||
<tr><td class="f1">多窗口</td><td class="f2">每个工作空间可独立开窗口,窗口标题显示工作空间名称</td><td class="f2"><code>app.multiWindow = true</code></td></tr>
|
||
<tr><td class="f1">全局快捷键</td><td class="f2"><code>Cmd/Ctrl+Shift+M</code> 从任意应用切换到 Metona 窗口</td><td class="f2">可自定义快捷键</td></tr>
|
||
<tr><td class="f1">系统通知</td><td class="f2">Agent 完成长时间任务时发送系统通知(点击跳转到对应会话)</td><td class="f2"><code>app.notifications = true</code></td></tr>
|
||
<tr><td class="f1">开机自启</td><td class="f2">系统启动时自动启动 Metona(最小化到托盘)</td><td class="f2"><code>app.autoStart = false</code></td></tr>
|
||
</table>
|
||
<div class="note-box">
|
||
<strong>💡 托盘图标实现:</strong>使用 <code>electron Tray</code> API,动态切换图标以反映 Agent 状态。托盘图标右键菜单通过 <code>Menu.buildFromTemplate()</code> 构建。全局快捷键使用 <code>globalShortcut.register()</code>。
|
||
</div>
|
||
</section>
|
||
|
||
<!-- FOOTER -->
|
||
<div style="text-align:center;padding:40px 0 20px;color:var(--text-dim);font-size:13px;border-top:1px solid var(--border)">
|
||
<p>🎨 MetonaAI Desktop UI/UX 设计集成方案</p>
|
||
<p>研究来源: <strong style="color:var(--accent)">Fuselab Creative · Ant Design X · Google A2UI · Hermes Agent · Siyu's Newsletter</strong></p>
|
||
<p style="margin-top:6px">集成组件: <strong style="color:var(--purple)">MetonaToast v2.0.0</strong> · 版本 <strong style="color:var(--accent2)">v1.0.0</strong> · 2026-06-26</p>
|
||
</div>
|
||
|
||
<!-- Back to Top Button -->
|
||
<button id="backToTop" onclick="window.scrollTo({top:0,behavior:'smooth'})" style="
|
||
position:fixed;bottom:30px;right:30px;width:44px;height:44px;border-radius:50%;
|
||
background:var(--accent);color:#fff;border:none;cursor:pointer;font-size:20px;
|
||
display:none;align-items:center;justify-content:center;
|
||
box-shadow:0 4px 12px rgba(99,102,241,.3);transition:transform .2s,opacity .2s;z-index:1000
|
||
">↑</button>
|
||
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
document.querySelectorAll('.sidebar a[href^="#"]').forEach(a=>{a.addEventListener('click',e=>{e.preventDefault();const t=document.querySelector(a.getAttribute('href'));t&&t.scrollIntoView({behavior:'smooth',block:'start'})})});
|
||
const S=document.querySelectorAll('.api-section'),L=document.querySelectorAll('.sidebar a[href^="#"]'),B=document.getElementById('backToTop');
|
||
window.addEventListener('scroll',()=>{let c='';S.forEach(s=>{if(window.scrollY>=s.offsetTop-100)c=s.id});L.forEach(a=>{a.classList.toggle('active',a.getAttribute('href')==='#'+c)});if(B)B.style.display=window.scrollY>300?'flex':'none'});
|
||
</script>
|
||
</body>
|
||
</html> |