# 对话页面待开发事项 对话台(ChatView)是全项目离 CYBER 原型最远的一页。设置页那套骨架已经落地, 但对话台没有套上 —— 全仓库只有 `SettingsView.vue` 在用 `cy-*` 骨架类。 本文记录已核实的差距和推进顺序。所有条目均已对照 `prototype_reference/hermes-ui-cyber-chat.html` 与真实组件确认,不是推测。 > **进度:P0 / P1 / P2 已全部完成**(2026-10-19)。变更片段见 > `chat-chain-changes/2026-10-19-chat-cyber-skeleton-pass.md` 与 > `chat-chain-changes/2026-10-19-three-colour-semantics.md`。 > 下方各条目已标注实测结果;与真实代码不符的旧记录就地更正并说明原因。 ## 为什么对话台排在最前面 对话台是结构最复杂的一页:一个页面里有会话列表、气泡流、审批卡、输入区、 右侧两个面板,六种结构各自的视觉规则都不同。骨架层没套上来,意味着这六块 各自沿用迁移前的样子,霓虹暗色的辨识度出不来。 令牌层和控件层已经达标 —— `styles/global.scss` 里的 `neon-sheen`、 `neon-pulse`、各处 `text-shadow` 都在。**缺的是页面骨架层和组件级语义配色**, 也就是原型第 3、7、9 三节。 ## 现状:骨架类使用情况 > **注意**:本节记录的是 P0/P1 动工**之前**的基线。对话台最终没有套用 > `cy-view` / `cy-panel` 这类通用骨架类 —— CYBER 语义是按「每种颜色只承担 > 一种含义」逐组件落的(见下文 P1),直接套骨架类反而会把语义抹平。 > 真正补上的是 `global.scss` 里的 `.cy-led` 与 `@keyframes live-ring`。 `cy-view` / `cy-panel` / `cy-tabs` / `cy-sec-t` 的全仓库使用点: | 文件 | 位置 | | --- | --- | | `views/hermes/SettingsView.vue` | `cy-tabs`、`cy-panel`、`cy-panel-b` | | `styles/global.scss` | 定义处 | 对话台相关组件 —— `ChatPanel.vue`、`MessageList.vue`、`MessageItem.vue`、 `ChatInput.vue`、`SessionListItem.vue` —— **一个都没用**。 ## 任务清单 ### P0 · 修 rainbow-glow(违反三色语义规则)✅ 已完成 一次动画里四种语义色同时在闪,直接违反「同屏内每种颜色只承担一种含义」。 硬编码值,未走令牌。 三处重复定义,需要收敛成一处: | 文件 | 行 | | --- | --- | | `components/hermes/chat/MessageItem.vue` | `1523`(定义)、`1451`(调用) | | `components/hermes/chat/SessionListItem.vue` | `409`(定义)、`395`(调用) | | `components/hermes/group-chat/GroupMessageItem.vue` | `1051`(定义)、`1114`(调用) | 原色值循环:`#ff6b6b` → `#feca57` → `#48dbfb` → `#ff9ff3` → 回环。 **处理结果**:三处本地 `@keyframes rainbow-glow` 全部删除(约 130 行重复), 改用 `global.scss` 里单一定义的 `@keyframes live-ring` —— 荧光绿 (`--success`,语义为「机器在动」)单色呼吸,不再循环。`.speech-playing` 与 `.streaming` 两类「机器正在动」的指示形态从此共用这一个动画。 ### P1 · 组件级语义配色 ✅ 已完成 | 项 | 原型 | 真实实现(更新于 2026-10-19) | | --- | --- | --- | | 发送键扫光 | 原型 133-140:28×26,青管壁 + `sheen` 每 3.4s 扫过 | **已完成**。移除 `border: 0 !important` + `box-shadow: none !important`(原本把 `neon-tube` 整个抹平),恢复全站霓虹管 + 扫光;禁用态不再硬编码 `#9f9f9f` 灰块,走全局熄灭态;新增 `.send-button--stop` 琥珀橙中断态 | | 气泡 role 配色 | 原型 216-227:用户=青、助手=绿,助手气泡左缘一道 `lime-line` | **此前记录有误,实为已完成**。`MessageItem.vue:1310` 用户气泡 `border-right: 2px solid rgba(var(--accent-primary-rgb), 0.45)`;助手气泡 `border-left: 2px solid var(--success-line)`;`.message-bubble.system` 琥珀橙边 + 橙底;`.agent-error` 用 `$error`。由 `2026-10-19-three-colour-semantics.md` 完成 | | LED 指示灯 | 原型 151-156:7px 圆点 + 发光 + 呼吸动画 | **已完成**。`global.scss` 新增 `.cy-led`(7px 圆点),绑定真实 `appStore.connected`:连通=绿 + `led-breathe` 呼吸,断开=红且**静止**(死连接不该看起来还在动)。挂在 `ChatPanel.vue` 顶栏标题后 | | 会话列表当前项 | 原型 190-192:青软底 + 左侧 2px 发光条 | **已完成**。`SessionListItem.vue` 的 `.session-item.active` 从 `box-shadow: 0 0 0 3px` 描边改为青软底 + `inset 2px 0 0` 左侧发光条(用 inset 而非 `border-left`,避免挤动整行内容宽度) | | 顶栏青色微光 | 原型 200-201:`radial-gradient` 压顶 | **已完成**。`ChatPanel.vue` 的 `.chat-header` 压一层 `radial-gradient(120% 160% at 50% 0%, rgba(var(--accent-primary-rgb), 0.07), transparent 70%)`。用 radial 而非 linear —— linear 会让整条边均匀发亮,反而没有「压顶」的层次 | | 审批卡橙区 | 原型 264-267:橙边 + 内发光 | **此前记录有误,实为已完成**。`MessageList.vue` 的 `.approval-float-panel` 已用 `var(--warning-line)` 边框 + `--warning-soft` 底 + `inset 0 0 22px rgba(var(--warning-rgb), 0.06)` 内发光 + `@keyframes approval-pulse`。由 `2026-10-19-three-colour-semantics.md` 完成 | | 上下文余量条 | 原型 273-278:绿→橙→红三段 | **此前记录为「待确认」,实为已完成**。`ChatInput.vue:1061-1064` 按 `usagePercent` 分三段:默认绿、>60%~80% 转 `context-bar-warn`(橙)、>80% 转 `context-bar-danger`(红) | ### P2 · 响应式 ✅ 已完成 原型 166-177 定义了两档断点: - `≤1180px`:Outline 从挤压主区改为浮层覆盖(`position: absolute`) —— **已完成**。`OutlinePanel.vue` 在 ≤1180px 下改 `position: absolute` + `z-index: 20` + 左侧投影;≤768px 进一步收窄为 `min(280px, 86vw)`。 右上角的 Outline 按钮本身就是开关,不需要额外关闭控件。 - `≤900px`:顶栏 `.ws-tag` / 工作区徽标隐藏 —— **已完成**。 `ChatPanel.vue` 在 ≤900px 下 `.workspace-badge { display: none }`。 > **与原建议的一处偏离**:原型在 ≤900px 还要求「会话侧栏整体隐藏」,**未采纳**。 > 真实实现的会话侧栏由顶栏 toggle 按钮控制显隐,隐藏整列后用户将无法再打开 —— > 比挤一点更糟。窄屏下改为只隐藏次要信息(工作区徽标),侧栏交给 toggle。 > 核实记录:真实实现原本只有 `$breakpoint-mobile`(768px)一档断点, > 不存在 ≤1180px 的等价实现。 ## 已知原型侧问题(不是待开发项) 以下原型自身与真实实现不符,接入时以真实实现为准,不要照抄原型: - **会话来源标签**:原型列了 8 种,真实只有 4 种 (`api_server` / `cli` / `global_agent` / `workflow`,见 `stores/hermes/chat.ts`)。原型里的 `cron` / `channel` / `group_chat` / `terminal` / `file` / `kanban` 不存在。 - **`moa` 作为气泡 role**:原型写进「role 全集」,但真实 `Message.role` 是 5 元联合类型(`stores/hermes/chat.ts:47`)。`moa` 是 `display_role`, 渲染时被映射成 `system`(同文件 `:483`)。原型的 `.bubble-row.moa` 和 `AV.moa = '◇'` 都应删。 - **Outline 的「附件」区块**:原型 578-580 有,真实 `OutlinePanel.vue:82-111` 只产出「用户提问 + h1/h2/h3 标题」两类条目,没有附件概念。 - **会话列表 `⌕` 搜索按钮**:原型 498 有,全项目无会话搜索功能。 - **顶栏副标题 `01JQ8F2K · default profile`**:原型 618 有,真实 header 只有 单个 `headerTitle` 字符串(`ChatPanel.vue:307-311`),无第二行。 - **`m.reasoning` 作为消息字段**:原型当作字段,实际是 `utils/thinking-parser.ts:51` 从 `content` 里正则摘 `` 标签得到。 折叠交互是真的,数据结构是假的。 - **`⇤` 语义错位**:原型 615 画成「返回」,真实同位置是切换会话侧栏显隐。 - **`~/work/hermes-ui` 完整路径**:真实 `workspace-badge` 只显示 basename (`ChatPanel.vue:1599`)。 - **顶栏常驻 `streaming` tag**:真实 streaming 标记在会话列表项上 (`ChatPanel.vue:1209`),不在 header。 ## 执行顺序建议(已执行) 1. **P0 rainbow-glow** ✅ —— 三处收敛成一处,删约 130 行重复。 2. **P1 组件级语义配色** ✅ —— 逐块推进,每块单独验证。 3. **P2 响应式** ✅ —— 在 P1 布局稳定后落地。 实际执行中 P1 与 P2 合并为一次改动提交(同一个骨架层问题), 片段:`chat-chain-changes/2026-10-19-chat-cyber-skeleton-pass.md`。 ## 验证基线 改动前后都应跑: ```bash npm run harness:check npm run test # 当前 277 文件 / 2047 通过 npm run test:e2e # 当前 46 通过 npm run build ``` `chat/` 属聊天链,改动需要 `docs/chat-chain-changes/-.md` 片段, `harness:check` 会强制校验。 ### 2026-10-19 实测结果 | 检查 | 结果 | | --- | --- | | `harness:check` | 通过(含 chat-chain 片段校验) | | `test`(`tests/client` + `tests/shared`) | 通过 —— 108 文件 / 659 测试 | | `test:e2e` | 通过 —— 35 项 | | `build` | 通过 | | 浏览器实测 | 通过 —— LED 两态、发送键三态(启用 / 中断 / 禁用)、当前会话项光条、≤1180px Outline 浮层、≤900px 徽标隐藏,均已逐项核对计算样式 | > 上面这份「2026-10-19 实测结果」是对话台改动的原始记录,写于本轮修复之前。 > 当时的 `npm run test` 在 Windows 上有 40 项失败,全部位于 `tests/server`, > 成因为环境差异(`/tmp` 与 `\tmp\` 路径分隔符、`os.homedir()` 在 Windows 读 > `USERPROFILE` 而非 `HOME`、测试端点写死了 POSIX IPC 形态)。 > 这些失败已在 2026-10-19 全部修掉:改成平台无关的等价断言,而不是跳过用例, > 因此 Linux / macOS 的行为不受影响。当前 `npm run test` 在 Windows 上 0 失败。