From 41ced37e9191943ce8411d1fbd749adc72e26574 Mon Sep 17 00:00:00 2001 From: EMRG Evolution Date: Thu, 6 Aug 2026 07:03:18 +0800 Subject: [PATCH] =?UTF-8?q?emrg:=20GUI=20=E9=87=8D=E8=AE=BE=E8=AE=A1=20P1?= =?UTF-8?q?=20=E2=80=94=20=E5=8F=8C=E4=B8=BB=E9=A2=98=E8=AE=BE=E8=AE=A1?= =?UTF-8?q?=E4=BB=A4=E7=89=8C=20+=20=E6=96=B0=E5=B8=83=E5=B1=80=E9=AA=A8?= =?UTF-8?q?=E6=9E=B6=20(#415)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 按 docs/design/gui-redesign.md(宿主已确认)实施 P1: - css/tokens.css:双主题令牌(浅色 #fafafa / 深色 #17181c,品牌绿 #16a06c/#2fbf83) - css/base.css:reset + 全局排版(正文 15px/1.7)+ markdown 基础样式 - css/layout.css:侧边栏 260px(品牌区/新对话/会话列表/底部设置+连接圆点)、 聊天区居中 760px、卡片式输入区(圆形 ↑ 发送按钮) - css/components.css:旧 app.css 组件样式迁移改用 tokens(消息/工具卡/对话框/会话项) - index.html:新骨架(去掉技术状态栏,技术信息收纳隐藏但保留 DOM id 兼容 app.js) - 删除 app.css 功能不丢:app.js 27 个 DOM id 全部保留;npm test 29 全绿;472 Python tests 通过 --- docs/design/gui-redesign.md | 524 +++++++++++++++++++++++++++ emrg/gui/renderer/app.css | 316 ---------------- emrg/gui/renderer/css/base.css | 85 +++++ emrg/gui/renderer/css/components.css | 175 +++++++++ emrg/gui/renderer/css/layout.css | 207 +++++++++++ emrg/gui/renderer/css/tokens.css | 99 +++++ emrg/gui/renderer/index.html | 117 +++--- 7 files changed, 1162 insertions(+), 361 deletions(-) create mode 100644 docs/design/gui-redesign.md delete mode 100644 emrg/gui/renderer/app.css create mode 100644 emrg/gui/renderer/css/base.css create mode 100644 emrg/gui/renderer/css/components.css create mode 100644 emrg/gui/renderer/css/layout.css create mode 100644 emrg/gui/renderer/css/tokens.css diff --git a/docs/design/gui-redesign.md b/docs/design/gui-redesign.md new file mode 100644 index 00000000..77ea2230 --- /dev/null +++ b/docs/design/gui-redesign.md @@ -0,0 +1,524 @@ +# EMRG GUI 完全重设计(面向非开发者) + +> 状态:**草案 — 待宿主 review** +> 定位:GUI 是 EMRG 面向**非开发者**的主要入口(80% 日常使用场景) +> 关键词:**简洁 · 友好 · 漂亮** +> 范围:renderer 层完全重写(index.html / app.css / app.js / markdown.js) +> 不变:main.js / preload.js / daemon_client.js / IPC 协议 / CSP 策略 + +--- + +## 1. 目标用户与设计哲学 + +### 1.1 目标用户 + +**非开发者**:不关心 daemon / session ID / 工具调用细节,只想和一个聪明友好的 AI 助手对话,让它帮忙做事。对他们来说: + +- "daemon" 是黑话 → 只显示"已连接 / 连接中" +- "session s_260805_1430" 是乱码 → 只显示对话标题 +- "tool_call bash 2.3s" 是噪音 → 显示"正在帮你执行命令… ✓ 完成" +- "演化 42 次" 是术语 → 显示"EMRG 一直在成长"(或藏进"关于") + +### 1.2 设计哲学 + +| 原则 | 说明 | +|------|------| +| **一眼会用** | 打开就知道该做什么。不需要说明书,不需要快捷键也能完成所有操作 | +| **友好有温度** | 圆润、柔和、留白充足。用鼓励性文案,不用技术术语和错误黑话 | +| **漂亮精致** | 现代消费级审美:细腻阴影、柔和圆角、优雅动效。第一眼有好感 | +| **渐进披露** | 默认极简,细节按需展开(工具过程可折叠、高级设置收纳) | +| **信任感** | AI 在后台做事时给用户温和的反馈(正在做什么、做完了),而不是沉默或刷屏 | + +### 1.3 参考坐标 + +- **ChatGPT / Claude.ai**:大众熟悉的 AI 对话范式(零学习成本) +- **Apple 系应用**:留白、字重层次、柔和阴影、精致动效 +- **Raycast / Arc**:现代感、漂亮的输入框与命令感 +- **避免**:终端风、信息过载、开发者黑话、密集布局 + +### 1.4 与 TUI 的分工 + +| | TUI | GUI | +|---|---|---| +| 用户 | 开发者 | **非开发者(主入口)** | +| 审美 | 终端美学、信息密度 | **简洁友好漂亮** | +| 操作 | 键盘极致 | 鼠标优先,键盘辅助 | + +两者共享同一 daemon,但**视觉语言各自独立**——GUI 不强行对齐 TUI 的暗色终端风。 + +--- + +## 2. 视觉设计系统 + +### 2.1 主题 + +**跟随系统**:默认支持浅色 + 深色两套,`prefers-color-scheme` 自动切换,设置里可手动覆盖(浅色 / 深色 / 跟随系统)。 + +> 非开发者多用浅色系统;浅色更显友好干净。深色保证夜间舒适。 + +### 2.2 色彩 + +品牌色:**生机绿**(EMRG = emergence / 生长,绿色契合"自我进化、持续成长"的品牌叙事)。 + +```css +:root { + /* ── 浅色主题 ── */ + --bg: #fafafa; /* 页面背景:近白的暖灰 */ + --bg-panel: #ffffff; /* 面板/卡片:纯白 */ + --bg-soft: #f2f3f5; /* 柔和底:输入框、hover */ + --text-1: #1a1d21; /* 主文字 */ + --text-2: #5f6672; /* 次文字 */ + --text-3: #9aa1ad; /* 弱文字(时间、占位) */ + --border: #e8eaed; /* 边框 */ + --accent: #16a06c; /* 品牌绿 */ + --accent-soft: #e6f5ee; /* 品牌绿浅底(用户气泡、选中) */ + --accent-hover: #128a5c; + --blue: #3b82f6; /* 链接 */ + --red: #e5484d; /* 错误/删除 */ + --amber: #f5a623; /* 进行中 */ + --shadow-sm: 0 1px 2px rgba(16,24,40,.05); + --shadow-md: 0 4px 16px rgba(16,24,40,.08); + --shadow-lg: 0 12px 40px rgba(16,24,40,.14); + + /* ── 深色主题 ── */ + [data-theme="dark"] { + --bg: #17181c; + --bg-panel: #1f2127; + --bg-soft: #26282f; + --text-1: #eceef2; + --text-2: #a4a9b4; + --text-3: #6b7078; + --border: #2e3138; + --accent: #2fbf83; + --accent-soft: #1d3a2f; + --accent-hover: #37d192; + --shadow-sm: 0 1px 2px rgba(0,0,0,.3); + --shadow-md: 0 4px 16px rgba(0,0,0,.35); + --shadow-lg: 0 12px 40px rgba(0,0,0,.5); + } +} +``` + +**要点**: +- 浅色为主打(干净友好),深色同品质 +- 品牌绿点缀不滥用:发送按钮、选中态、连接状态、EMRG 标识 +- 柔和阴影建立层次(浅色主题),深色主题弱化阴影靠底色分层 + +### 2.3 字体与排版 + +```css +--font: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", + "Noto Sans CJK SC", "Microsoft YaHei", sans-serif; +--font-mono: "SF Mono", Menlo, Consolas, monospace; /* 仅代码块 */ + +正文 15px / 行高 1.7 ← 比现在的 14px 更大更舒展,阅读友好 +次级 13px / 行高 1.5 +辅助 12px(时间戳、提示) +标题 17-20px / 600 weight +``` + +- 正文比现在**加大到 15px、行高 1.7**——非开发者重视可读性 +- 段落间距充足,中文渲染优先(PingFang / 微软雅黑) + +### 2.4 圆角 / 间距 / 阴影 + +``` +圆角:气泡 18px · 输入框/按钮 12px · 卡片 14px · 对话框 20px +间距:8px 基准网格,留白慷慨(聊天区左右留白 ≥ 24px) +阴影:三档柔和阴影(sm/md/lg),仅浅色主题明显 +``` + +圆润但不卡通:圆角 12-20px 区间,统一不混用。 + +### 2.5 动效 + +``` +快 150ms(hover / focus) +中 250ms cubic-bezier(.2,.8,.3,1)(消息出现 / 面板展开) +慢 350ms(对话框 / 主题切换) +``` + +- 消息出现:轻微上浮 + 淡入(`translateY(8px)→0 + opacity`) +- 工具进行中:温和的呼吸/进度动画,不刺眼 +- 打字回复:流式文字自然增长 + 末尾柔和光标脉动 +- **克制**:无弹跳、无夸张缩放、无干扰注意力的循环动画 + +--- + +## 3. 布局 + +### 3.1 整体结构 + +``` +┌──────────────────────────────────────────────────────────────┐ +│ ┌────────────┐ ┌───────────────────────────────────────────┐ │ +│ │ ✦ EMRG │ │ │ │ +│ │ │ │ (对话标题,居中,简洁) │ │ +│ │ + 新对话 │ ├───────────────────────────────────────────┤ │ +│ │ │ │ │ │ +│ │ 今天 │ │ 聊天区(居中,最大宽度 760px) │ │ +│ │ 帮我写周报 │ │ │ │ +│ │ 整理照片 │ │ │ │ +│ │ 昨天 │ │ │ │ +│ │ 旅行规划 │ │ │ │ +│ │ │ ├───────────────────────────────────────────┤ │ +│ │ ⚙︎ ⚑ │ │ ┌──────────────────────────────┐ ↑ │ │ +│ └────────────┘ │ │ 输入消息… │ 发送 │ │ +│ │ └──────────────────────────────┘ │ │ +│ └───────────────────────────────────────────┘ │ +└──────────────────────────────────────────────────────────────┘ +``` + +- **侧边栏**:品牌区 + 新对话按钮 + 按时间分组的对话列表 + 底部设置 +- **聊天区**:居中单栏,**最大宽度 760px**(最佳阅读宽度),宽屏两侧留白 +- **输入区**:悬浮卡片式输入框,醒目 +- **去掉**:底部技术状态栏(daemon dot / instance id / 演化计数 → 收纳,见 §5.3) + +### 3.2 侧边栏 + +``` +┌────────────────────┐ +│ ✦ EMRG │ 品牌标识(✦ 符号 + 字标,品牌绿) +│ │ +│ ┌────────────────┐ │ +│ │ + 新对话 │ │ 醒目主按钮(品牌绿描边或浅底) +│ └────────────────┘ │ +│ │ +│ 今天 │ 时间分组标题(text-3,12px) +│ 帮我写周报 │ 对话项:单行标题,hover 柔和底 +│ 整理照片思路 │ 当前对话:accent-soft 底 + 品牌绿文字 +│ 昨天 │ +│ 旅行规划 │ +│ 更早 │ +│ 卸载问题排查 │ +│ │ +│ ⚙︎ 设置 ● │ 底部:设置 + 连接状态小圆点 +└────────────────────┘ +``` + +- 对话列表**只显示标题**,不显示 session ID / 消息数(噪音) +- 按时间分组(今天 / 昨天 / 更早),符合非开发者心智 +- 右键菜单:重命名 / 删除(删除有友好确认) +- 可折叠(工具栏按钮),窄屏自动收起 +- 底部连接状态:仅一个小圆点(绿=正常),不写技术细节 + +### 3.3 聊天区 + +**对话范式采用大众熟悉的 AI 助手样式**(ChatGPT/Claude 式),零学习成本: + +``` +┌────────────────────────────────────────────┐ +│ │ +│ 帮我写一份周报 [我] │ ← 用户:右对齐柔和气泡 +│ │ +│ ✦ 好的,这是周报草稿: │ ← EMRG:全宽,✦ 标识开头 +│ │ +│ ## 本周工作 │ ← Markdown 舒适排版 +│ 1. 完成了…… │ +│ ```代码块(圆角、浅色底、复制按钮)``` │ +│ │ +│ ┌ 🔍 正在查找相关文件… ✓ 完成 ─┐ │ ← 工具过程:折叠行 +│ │ +│ [我] 再精简一点 │ +│ │ +│ ✦ 已为你精简:…… │ +│ │ +└────────────────────────────────────────────┘ +``` + +- **用户消息**:右对齐柔和气泡(`accent-soft` 底,大圆角),亲切 familiar +- **EMRG 消息**:全宽无气泡(长文/代码可读性最佳),行首 `✦` 品牌标识 +- **工具过程**:默认折叠为一行友好状态(见 §4.2),不打断阅读 +- 消息间距充足(24px),时间戳弱化(hover 才显示或置于分组处) + +### 3.4 输入区 + +``` +┌────────────────────────────────────────────────────┐ +│ ┌──────────────────────────────────────────────┐ │ +│ │ 输入消息,按 Enter 发送… │ │ +│ │ │ │ +│ │ ┌────┐ │ │ +│ │ │ ↑ │ │ │ +│ │ └────┘ │ │ +│ └──────────────────────────────────────────────┘ │ +│ EMRG 可能会犯错,请核对重要信息 │ ← 友好免责提示(text-3) +└────────────────────────────────────────────────────┘ +``` + +- 卡片式输入框:白底 + 柔和阴影 + 大圆角,视觉焦点 +- 圆形品牌绿发送按钮(`↑` 图标)在框内右下,醒目 +- 回复中:发送按钮变停止(`■`),红色系 +- 自动增高(最多 ~6 行) +- Enter 发送 / Shift+Enter 换行(占位符里提示) + +### 3.5 空状态与首启 + +**空对话**(新建后)——友好欢迎屏,降低"对着空白发呆"的门槛: + +``` + ✦ + 你好,我是 EMRG + 我可以帮你写作、整理、查资料、处理文件… + + ┌ 试试问我 ─────────────────────┐ + │ 📝 帮我写一份周报 │ ← 可点击的示例卡片 + │ 🗂 整理这个文件夹 │ 点击直接填入输入框 + │ ✈️ 规划一次旅行 │ + └──────────────────────────────┘ +``` + +**首启引导**:全屏友好向导(品牌欢迎语 → 填 API Key → 完成),一步一屏、文案口语化、可跳过目录选择。 + +--- + +## 4. 组件规格 + +### 4.1 消息 + +| | 用户 | EMRG | 系统提示 | +|---|---|---|---| +| 样式 | 右对齐气泡 `accent-soft` | 全宽,`✦` 标识 | 居中弱化小字 | +| 渲染 | 纯文本 | Markdown(marked+hljs+DOMPurify) | 纯文本 | +| 圆角 | 18px(右下 6px) | — | — | + +### 4.2 工具过程(友好化重设计 · 重点) + +非开发者不需要看原始工具卡片。改为**折叠式友好状态行**: + +``` +进行中: ◌ 正在读取文件… (琥珀色,温和转动动画) +完成: ✓ 已读取 3 个文件 展开 ⌄ (绿色,默认折叠) +失败: ⚠ 这一步没成功,我换个方法 (红色系,措辞友好) +``` + +- 用**动词短语**描述("正在读取文件…" / "正在运行命令…" / "正在搜索…"),按 tool_name 映射友好文案 +- 默认折叠,点"展开"才看原始输出(保留透明可查,满足高级用户) +- 原始输出区:等宽字体、圆角浅底、2000 字符截断 + 展开全文(性能约束保留) + +### 4.3 对话项 / 按钮 / 菜单 + +- **对话项**:单行标题,hover 柔和底,当前项 accent-soft 底;右键 → 重命名/删除 +- **按钮**:主按钮品牌绿、次按钮浅底、危险按钮红;圆角 12px,点击区 ≥ 36px +- **确认对话框**:友好文案("删除这段对话?删除后无法恢复")+ [取消][删除],替代 `confirm()` +- **右键菜单**:白底卡片 + 阴影 + 大圆角 + +### 4.4 设置对话框 + +分组清晰、口语化标签。**模型支持多个配置 + 对话中随时切换**: + +``` +设置 +───────────────────────────────────────── +模型服务 + API Key [••••••••••••] + 接口地址 [https://api.deepseek.com] + + 可用模型 + 添加模型 + ┌───────────────────────────────────────────┐ + │ ● deepseek-chat 默认模型 [编辑][−]│ ← 列表:名称 + 默认标记 + │ gpt-4o 支持图片 [编辑][−]│ + │ deepseek-reasoner [编辑][−]│ + └───────────────────────────────────────────┘ + +工作目录 + EMRG 在哪里帮你干活 [~/Documents 选择…] + +外观 + 主题 ( ) 浅色 ( ) 深色 (•) 跟随系统 +───────────────────────────────────────── + [取消] [保存] +``` + +**模型管理交互**: +- 列表展示所有已配置模型(对应 config.toml 的 `[llm].model` 默认项 + `[[llm.models]]` 全部条目) +- `+ 添加模型` / `[编辑]` → 行内展开小表单: + ``` + 名称 [gpt-4o ] ← 显示名(必填) + 模型 ID [gpt-4o ] ← API 实际模型名(选填,默认同名称) + 支持图片 [✓] ← vision 开关(友好措辞,不写"vision") + ``` +- `[−]` 删除(默认模型不可删,只能先换默认) +- `设为默认`:点击模型行的单选圆点 → 写入 `[llm].model` +- 保存后写入 config.toml `[[llm.models]]`(name/model/vision 字段,context_window 可选高级项) + +### 4.5 对话中的模型切换器 + +**位置**:输入区上方(或顶栏),常驻可见,一键切换: + +``` +┌────────────────────────────────────────────────────┐ +│ 当前模型:deepseek-chat ⌄ │ ← 点击弹出列表 +│ │ +│ ┌────────────────────────────┐ │ +│ │ ✓ deepseek-chat │ │ +│ │ gpt-4o 🖼 │ ← 🖼 = 支持图片 │ +│ │ deepseek-reasoner │ │ +│ └────────────────────────────┘ │ +│ │ +│ ┌──────────────────────────────────────────────┐ │ +│ │ 输入消息… [ ↑ ] │ │ +│ └──────────────────────────────────────────────┘ │ +└────────────────────────────────────────────────────┘ +``` + +- 点击 → 下拉列表展示全部已配置模型,`✓` 标记当前 +- 选择后调用 `emrg.setModel({model})` → daemon `set_model` → 广播 `model_set` +- 切换即时生效(下一条消息即用新模型),切换成功时切换器短暂高亮确认 +- 支持图片的模型显示小图标(友好表达 vision 能力) +- 只有一个模型时切换器仍显示(不可点或点了提示"去设置添加更多模型") + +--- + +## 5. 文案与情感化设计(非开发者的关键) + +### 5.1 文案规范 + +| 场景 | 技术黑话 ❌ | 友好文案 ✅ | +|------|-----------|-----------| +| 连接断开 | "daemon 连接断开" | "连接中断了,正在重新连接…" | +| 重连成功 | "✓ 已重新连接" | "回来了,我们继续 ✦" | +| 会话忙 | "session busy" | "我还在处理上一条,稍等一下哦" | +| 发送失败 | "发送失败: {error}" | "没发送成功,你的话我还留着,再试一次?"(保留输入) | +| 工具失败 | "tool failed" | "这一步没成功,我换个方法试试" | +| 删除确认 | "确定删除会话 s_xxx?" | "删除这段对话?删除后无法恢复" | + +原则:**口语化、鼓励性、不责怪用户、给出下一步**。 + +### 5.2 品牌存在感 + +- `✦` 作为 EMRG 的温和标识(助手消息行首、空状态、品牌区) +- 品牌绿贯穿:发送、连接正常、选中、成长标识 +- 语气:一个安静可靠、一直在成长的助手 + +### 5.3 EMRG 特色(演化)的友好表达 + +"自我演化"是 EMRG 的灵魂,但对非开发者要**翻译成温度**: + +- 不在主界面刷"演化 42 次" +- 设置 → 关于 里友好展示:"EMRG 已自我成长 42 次,感谢你的每一次反馈" +- 可选:演化发生时,侧边栏 ✦ 标识有一次温和的闪烁(存在感而非打扰) + +--- + +## 6. 交互 + +### 6.1 鼠标优先,键盘辅助 + +非开发者靠鼠标完成一切;快捷键作为锦上添花(不强制): + +| 快捷键 | 动作 | +|--------|------| +| Enter / Shift+Enter | 发送 / 换行 | +| ⌘N | 新对话 | +| ⌘B | 折叠侧边栏 | +| ⌘, | 设置 | +| ESC | 停止回复 / 关闭弹窗 | + +### 6.2 流式与自动滚动 + +- delta → 追加文本(不解析 Markdown),末尾柔和光标脉动 +- done → requestIdleCallback 全量 Markdown 渲染 +- 自动滚动仅在用户停留在底部时;上滑阅读时**不打扰**,出现"回到底部"悬浮按钮 + +### 6.3 断连体验 + +- 侧边栏底部圆点变灰/红 + 顶部温和横幅"连接中断,正在重连…" +- 输入框保持可用,发送时友好提示 +- 重连成功横幅消失,无刺眼弹窗 + +--- + +## 7. 技术约束(不可违反) + +### 7.1 IPC / CSP / vendor + +- preload.js 暴露的 API 面**基本零改动**,仅一处扩展(见下) +- daemon_client.js **零改动** +- CSP 不变:无外部 CDN、无 web font(系统字体栈)、本地资源 +- vendor 不变:marked + DOMPurify + highlight.js(hljs 主题需适配新配色) +- main→renderer 事件类型不变(message_delta/done/tool_started/…) + +**唯一 IPC 扩展(多模型保存)**: +- 现状:`emrg:saveSettings` 只处理 `{apiKey, baseUrl, model, projectDir}` 四个字段,无法保存多模型列表 +- 需要:`saveSettings` 接收 `models` 数组(每项 `{name, model?, vision?}`),main.js 写入 config.toml `[[llm.models]]` +- `emrg:getSettings` 同步返回完整模型对象(现在只返回 name 字符串数组),供设置页编辑 +- 顺手简化现有 `validateConfig`:去掉"白名单/纵深防御"那套,改为直接接收所需字段 + 一行基本类型检查(防写坏 config.toml)。这是健壮性,不是安全设计 +- **main.js 仅此一处改动**(saveSettings/getSettings 两个 handler),其余不动 + +### 7.2 性能约束 + +- 流式 delta 只动 textContent,不触发整块重排 +- Markdown 全量渲染走 requestIdleCallback(2s timeout) +- 工具输出 2000 字符截断 + 展开 +- 聊天区动画只用 transform/opacity(GPU 友好),不阻塞输入 + +### 7.3 跨平台一致 + +macOS / Windows / Linux 渲染一致;系统字体栈覆盖中文(PingFang / 微软雅黑 / Noto CJK)。 + +--- + +## 8. 文件结构(重写后) + +``` +emrg/gui/renderer/ +├── index.html # 新骨架 +├── css/ +│ ├── tokens.css # 设计令牌(双主题色彩/字体/圆角/阴影/动效) +│ ├── base.css # reset + 全局 +│ ├── layout.css # 侧边栏/聊天区/输入区 +│ ├── components.css # 气泡/工具行/按钮/对话框/菜单 +│ └── animations.css # 过渡动画 +├── js/ +│ ├── app.js # boot / 事件分发 +│ ├── chat.js # 消息渲染 / 流式 / 工具友好化 +│ ├── sidebar.js # 对话列表 / 时间分组 / 右键菜单 +│ ├── dialogs.js # 设置 / 首启 / 确认 +│ ├── markdown.js # marked + DOMPurify + hljs +│ ├── copywriting.js # 友好文案映射(工具动词、错误话术) +│ └── utils.js +``` + +不用框架、不用 bundler(多 `