fix(chat): repair Arco migration fallout in the chat page

The Phase 006 walkthrough surfaced four issues the automated checks could
not see. Dead naive-ui class names left behind by the migration stopped
matching, tooltips that carried their label as trailing default-slot text
leaked that text into the flex row, the workspace panel squeezed the chat
column until the input toolbar wrapped, and the Escape fallback still
looked for naive-ui's modal mask.

Tooltips now pass their label through the content prop, the tool panel
reserves a minimum width for the chat column, and Escape finds the visible
Arco modal and clicks its close button.
This commit is contained in:
2026-10-18 03:11:35 +08:00
parent effc29085c
commit c3eeea4187
10 changed files with 181 additions and 85 deletions
+11
View File
@@ -82,3 +82,14 @@ Phase 005 起,新代码与迁移代码一律使用 Arco Design Vue。本文表
排查手法:`el.__vueParentComponent.props` 看目标组件到底认不认这个 prop,
再看 `el.outerHTML` 确认渲染出来的骨架。回归由
`tests/e2e/chat-input-dropdown.spec.ts` 卡住。
- **迁移时最容易漏的是 CSS 里的 naive 类名**,因为 `grep naive-ui` 匹配不到
`:deep(.n-button__content)` 这种写法。聊天页原本有 35 处这类死样式,在 Arco 下
全部不生效,必须逐条改写成 Arco 类名。注意三处结构差异:
- `a-button` **没有** content 包裹层(naive 有 `.n-button__content`),
`gap` / `min-width` 要直接写在 button 上
- `a-modal` 没有 `body-wrapper` 分层,用 `.arco-modal` / `.arco-modal-body`
- `a-drawer` 同理,没有 `content` / `body-content-wrapper` 分层
- `useKeyboard.ts` 里查 `.n-modal-mask` 的 Esc 兜底属于跨组件的全局约定,迁移
组件时最容易漏掉。改弹窗库时必须同步 grep `.n-modal|.n-drawer|.n-base-` 这类
**字符串字面量**里的类名,而不只是组件 import。回归由
`tests/client/session-search.test.ts` 的 Esc 用例卡住。
@@ -0,0 +1,86 @@
---
date: 2026-10-17
pr: pending
feature: Phase 006 follow-up - Arco class-name cleanup, tooltip content props, tool panel width clamp, Escape dialog fallback
impact: Cosmetic styling fix plus one behavior fix. Dead naive-ui CSS class names in the chat components are rewritten to Arco equivalents so the toolbar, model label, drawer body scrolling, and mobile breakpoints receive their intended styles again; Arco tooltips that carried their label as trailing default-slot text now pass it through the content prop so the text stops being rendered into the layout flow; the workspace/terminal panel no longer squeezes the chat column narrow enough to wrap the input toolbar; and Escape again closes Arco chat dialogs because the fallback no longer looks for naive-ui's .n-modal-mask. No chat store logic, no /chat-run payload, and no message rendering path is touched.
---
# Phase 006 follow-up: Arco style cleanup and Esc dialog fallback
Branch: `phase/006-chat-arco`
Touched feature: chat toolbar styling, chat dialogs, session context menu
layout, Esc-to-close fallback
## Why
Phase 006 migrated the chat page to Arco, but the manual checklist walkthrough
surfaced four problems that the automated checks could not see:
1. Opening the workspace/terminal panel squeezed the chat column so far that the
input toolbar wrapped "Add attachment" into a vertical stack and truncated the
model label.
2. 35 `:deep(.n-*)` rules in the chat components were left behind by the
migration. They silently stopped matching because Arco uses different class
names, and `grep naive-ui` never sees them because they are class names in a
style block rather than an import.
3. `useKeyboard.ts` still looked for `.n-modal-mask` to close dialogs on Escape.
Every chat dialog had moved to Arco, so Escape no longer closed the model
picker or session search.
4. Four Arco tooltips carried their label as trailing default-slot text
(`<a-tooltip><a-button/></a-tooltip>{{ t(...) }}`). naive-ui rendered the
tooltip slot as an overlay so the text was harmless; Arco renders the default
slot inline, so those text nodes sat in the flex row as zero-width items and
contributed to the toolbar squeeze above.
## What changed
- `ChatPanel.vue` — `toolPanelMaxWidth()` now reserves `CHAT_MAIN_MIN_WIDTH`
(620px) for the chat column instead of a flat 120px, so the toolbar always has
room. `showToolPanel` already re-clamps on open, so persisted widths from older
builds are corrected on the next toggle. Dead naive classes rewritten:
`.n-button` → `.arco-btn`, and the new-chat drawer's `-content` /
`-body-content-wrapper` layers collapsed onto `.arco-drawer` / `.arco-drawer-body`
because Arco has no such nesting.
- `ChatInput.vue` — dropped the `.n-button__content` / `.n-button__border` /
`.n-button__ripple` / `.n-base-wave` rules; Arco's `a-button` is already
`display: flex` and carries a transparent border, so `gap` and
`border-color` now go on the button itself. `.n-switch` → `.arco-switch`,
`.n-button__icon` → `.arco-btn-icon`. The context-length, attach, and model
tooltips now pass their label via `:content`. `.input-toolbar` is pinned to
`flex-wrap: nowrap`.
- `TerminalPanel.vue` — the new-session tooltip passes its label via `:content`.
- `MessageList.vue`, `MessageItem.vue`, `SessionSearchModal.vue` — same
class-name rewrite; `.n-drawer-body-content-wrapper` → `.arco-drawer-body`,
`.n-modal-body-wrapper` → `.arco-modal`, `.n-input` → `.arco-input`.
- `useKeyboard.ts` — the Escape fallback now finds the visible `.arco-modal` and
clicks its `.arco-modal-close-btn`.
## Verification
The toolbar was measured with the workspace panel open across viewport widths
1600 / 1280 / 1100 / 1024 / 900 / 820. `.input-toolbar` stays a single 32px row
at every width and `.input-model-label` is no longer clipped (`scrollWidth ===
clientWidth`). Before the fix the same measurement showed a 90px-tall two-row
toolbar and a truncated model label.
## Behavior impact
Cosmetic only, plus one fix. Toolbar, model label, drawer body scrolling and
mobile breakpoints now actually receive their intended styles. Tooltip labels
stop being emitted into the layout. Escape now closes Arco chat dialogs again. No
chat store logic, no `/chat-run` payload, and no message rendering path was
touched.
## Regression coverage
- `tests/client/session-search.test.ts` — asserts Escape clicks an open Arco
modal's close button and ignores leftover naive-ui markup.
- `tests/e2e/chat-input-dropdown.spec.ts`, `tests/e2e/chat-rendering-smoke.spec.ts`
— unchanged, still green (35 e2e tests).
```bash
npm run test # 274 files / 2027 tests
npm run test:e2e # 35 tests
npm run harness:check
npm run build
```