# 2026-04-22 Desktop UI Regression Handoff

## 背景

当前桌面端存在三类已被本地代码事实确认的回归：

1. 幕布/启动遮罩被改坏：
   - logo 过大
   - 背景视觉失控
2. 主界面被改坏：
   - 左侧工作区样式异常
   - 右侧工作区白屏/内容消失
3. 窗口控件异常：
   - 关闭/最大化/最小化按钮跑到左上角

本交接文档的目标，是把“哪里坏了、为什么坏了、应该怎么修、修的时候要防什么回归、怎么验收”一次性写清楚，供另一个 AI 直接执行。

## 已确认的代码事实

### 1. 幕布/logo 变大的直接原因

`6dec17b feat(客户端): 增加专家模型配置与品牌化打包支持` 在 `apps/ui/src/App.tsx` 新增了两组品牌图片节点：

- 侧栏 logo：
  - `sidebar-logo-mark-shell`
  - `sidebar-logo-mark`
- 启动幕布 logo：
  - `startup-overlay-mark-shell`
  - `startup-overlay-logo`

对应位置：

- `apps/ui/src/App.tsx` 侧栏 logo 区域
- `apps/ui/src/App.tsx` 启动遮罩品牌区

但在以下样式文件中，没有找到这些类名的样式定义：

- `apps/ui/src/styles.css`
- `apps/ui/src/tailwind.css`

同时，`apps/ui/src/assets/brand-icon.png` 的实际尺寸是 `512x512`。在没有宽高约束的前提下，图片按原始尺寸渲染，足以解释“logo 很大”。

结论：

- 这是明确的样式缺失，不是素材本身问题。

### 2. 幕布背景失控的直接原因

启动幕布的基础背景样式定义在 `apps/ui/src/styles.css` 的 `.startup-overlay`、`.startup-overlay-panel`、`.startup-overlay-copy h1` 等规则中。

同一个 `6dec17b` 提交把幕布头部结构从“纯文字标题”改成了“图片 logo + 文案”的新结构，但没有同步补齐：

- `startup-overlay-brand-line`
- `startup-overlay-brand-copy`
- `startup-overlay-mark-shell`
- `startup-overlay-logo`

结论：

- 幕布不是单纯“颜色不对”，而是 DOM 结构变了、对应样式没补齐，导致既有幕布布局失衡。

### 3. 主界面左侧/右侧被改坏的主要来源

`91f42aa feat(ui): refresh chat and settings interactions` 对主界面结构做了较大改动，重点包括：

- 侧栏容器改成带大量强制类的新版结构
- 会话区结构改成新的 `sidebar-session-actions` / `sidebar-session-menu`
- 主内容区改成新的 `conversation-panel-head-layout`
- 新增 `page-drag-strip`、`conversation-drag-strip`
- 对 `conversation-panel`、`conversation-panel-body`、`composer-shell` 大量追加 `!` 强制覆盖类

对应文件：

- `apps/ui/src/App.tsx`

但样式层没有补齐同等粒度的定义。已确认缺失或未在样式文件中落地的类名包括：

- `sidebar-session-actions`
- `page-drag-strip`
- `conversation-drag-strip`
- `settings-input-label`
- `sidebar-logo-mark`
- `startup-overlay-logo`

结论：

- 这一步不是“小修小补”，而是把主界面结构先改了，但样式体系没有完整跟上。
- 右侧“白屏/消失”优先按“布局容器回归”处理，不要先假设是数据流或 IPC 问题。

### 4. Tailwind 样式管线放大了回归

`5e19ad5 feat(ui): add tailwind style pipeline` 新增：

- `apps/ui/src/tailwind.css`
- `apps/ui/src/main.tsx` 中在 `styles.css` 后继续引入 `tailwind.css`

事实：

- `tailwind.css` 在 `styles.css` 之后加载
- `App.tsx` 中又引入了大量 `!` 优先级类
- 新旧两套样式同时作用于同一批 DOM

结论：

- 当前回归不只是“某几个 class 写错了”，而是旧样式、Tailwind 组件层、内联强制类三套机制叠加，放大了布局失衡。

### 5. 窗口按钮跑到左上角的直接原因

当前磁盘上的 `apps/desktop/src/main/create-window.ts` 包含以下设置：

- `Menu.setApplicationMenu(null)`
- `titleBarStyle: "hidden"`
- `titleBarOverlay: false`
- `frame: false`

这意味着：

- 原生标题栏被去掉
- 窗口拖拽区和窗口控制按钮完全依赖前端自绘

同时，前端 `App.tsx` 中存在自定义窗口控件：

- `window-controls`
- `window-control-button`

但在样式文件中没有找到对应样式定义。

结论：

- “按钮跑到左上角”不是 Electron 自己乱了，而是无边框窗口已开启，但前端窗口控件样式未落地，最终按普通块元素渲染。

### 6. 一个额外风险事实

本地排查时观察到：

- `git rev-parse HEAD:apps/desktop/src/main/create-window.ts` 指向的版本，不包含上面的无边框窗口设置
- 但磁盘上的 `apps/desktop/src/main/create-window.ts` 包含这些设置
- `git status` 没有把这个文件标成已修改

这说明当前工作区存在一个异常点：

- 磁盘文件状态和 Git 记录不一致

在正式修改前，执行方必须先再次核实：

- 实际运行的是哪个文件内容
- 本地是否存在未正常反映到 `git status` 的工作树状态

这里不能拍脑袋直接回退。

## 修复目标

本轮只修复 UI 回归，不扩散到无关功能：

1. 幕布恢复正常：
   - logo 尺寸受控
   - 品牌区布局稳定
   - 背景和文案不冲突
2. 主界面恢复正常：
   - 左侧工作区宽度、卡片、滚动区恢复
   - 右侧会话区恢复可见和可滚动
   - 不再出现大面积空白
3. 窗口控件恢复正常：
   - 按钮位置回到右上角
   - 拖拽区域和点击区域边界明确
4. 修复方式可回归验证，不引入新的结构性风险。

## 建议修复方案

### 方案总原则

不要在当前基础上继续“补更多 Tailwind 强制类”。优先做减法：

1. 先收敛结构
2. 再补缺失样式
3. 最后决定是否保留 frameless 窗口

### A. 先修幕布和 logo

目标文件：

- `apps/ui/src/App.tsx`
- `apps/ui/src/styles.css`

动作：

1. 给以下类补齐明确样式，而不是继续依赖默认图片尺寸：
   - `sidebar-logo-mark-shell`
   - `sidebar-logo-mark`
   - `startup-overlay-brand-line`
   - `startup-overlay-brand-copy`
   - `startup-overlay-mark-shell`
   - `startup-overlay-logo`
2. 明确约束：
   - 侧栏 logo 用固定容器，图片宽高固定，`object-fit: contain`
   - 幕布 logo 也用固定容器，不允许原图裸渲染
3. 幕布品牌区改为稳定的横向或竖向布局，不要让图片直接参与标题文本的现有排版逻辑。

建议优先值：

- 侧栏 logo 容器：`72px` 到 `96px`
- 幕布 logo 容器：`96px` 到 `128px`

### B. 收敛主界面结构，先恢复稳定布局

目标文件：

- `apps/ui/src/App.tsx`
- `apps/ui/src/styles.css`
- `apps/ui/src/tailwind.css`

动作：

1. 以 `6dec17b` 之前的主界面稳定骨架为参考，核对以下区域：
   - `shell`
   - `sidebar`
   - `main-shell`
   - `content-area`
   - `conversation-panel`
   - `conversation-panel-body`
2. 对 `91f42aa` 引入的大量 `!` 强制类做收敛：
   - 只保留确实必要的交互视觉类
   - 去掉会改变主布局边界、宽高、overflow 的强制类
3. 如果某个新类没有对应样式定义，二选一：
   - 要么补样式
   - 要么删掉该 class 和相关结构
   - 不允许继续保留“有 DOM 无样式”的中间状态
4. 优先恢复右侧主内容区的高度链路：
   - `shell`
   - `main-shell`
   - `content-area`
   - `conversation-panel`
   - `conversation-panel-body`
   - `message-list`

重点检查：

- `min-height: 0`
- `overflow: hidden/auto`
- `flex: 1`
- `grid` / `flex` 嵌套层级

### C. 窗口控件修复策略

目标文件：

- `apps/desktop/src/main/create-window.ts`
- `apps/ui/src/App.tsx`
- `apps/ui/src/styles.css`
- `apps/ui/src/tailwind.css`

分两步处理，先选低风险方案。

#### 低风险优先方案

先恢复原生标题栏，不再依赖前端自绘窗口控件。

做法：

1. 去掉或回退：
   - `frame: false`
   - `titleBarStyle: "hidden"`
   - `titleBarOverlay: false`
2. 删除或禁用前端自绘：
   - `window-controls`
   - `window-control-button`
   - `app-drag-region`
   - `app-no-drag`
   - `page-drag-strip`
   - `conversation-drag-strip`

适用条件：

- 如果项目当前没有明确要求必须保留自定义无边框窗口

这是本轮推荐默认方案，因为风险最低。

#### 次选方案

如果必须保留 frameless 窗口，再补完整自绘方案。

要求：

1. `window-controls` 和 `window-control-button` 必须补全样式
2. 顶部 drag 区必须是稳定、连续、可见但克制的热区
3. 所有交互控件明确 `no-drag`
4. 聊天页、专家页、设置页都要统一验证

若选择此方案，测试量明显更大。

### D. Tailwind 管线收敛

目标文件：

- `apps/ui/src/tailwind.css`
- `apps/ui/src/main.tsx`

动作：

1. 先确认 `tailwind.css` 中哪些规则是真正必需的
2. 对仅用于本次改坏布局的规则做减法，尤其是：
   - 全局字体和背景覆盖
   - 与旧样式重复定义的布局类
   - 只定义了一半的组件类
3. 如果某一类组件主要靠 `styles.css` 驱动，就不要再在 `tailwind.css` 中半覆盖同一结构

## 修改范围

本轮允许修改：

- `apps/ui/src/App.tsx`
- `apps/ui/src/styles.css`
- `apps/ui/src/tailwind.css`
- `apps/ui/src/main.tsx`
- `apps/desktop/src/main/create-window.ts`

本轮原则上不动：

- IPC
- runtime
- gateway
- shared-types
- 配置存储逻辑
- 专家路由逻辑

除非在修复中确认右侧白屏不是布局问题，而是页面根本没渲染成功。只有出现明确证据时，才扩大范围。

## 风险点

### 1. 工作树状态异常风险

`create-window.ts` 存在“磁盘内容和 HEAD 内容不一致，但 `git status` 不报修改”的现象。

风险：

- 执行方可能以为自己修了源文件，实际运行的却不是这份内容

要求：

- 修复前先做一次内容核对
- 修复后再核对一次实际运行文件和构建产物

### 2. 旧样式和 Tailwind 冲突风险

当前同时存在：

- `styles.css`
- `tailwind.css`
- `App.tsx` 里的大量强制类

风险：

- 只修一层会被另一层覆盖

要求：

- 每改一块布局，都要同时看 DOM、旧样式、Tailwind 样式、强制类四件事

### 3. 无边框窗口交互风险

如果继续保留 `frame: false`，风险包括：

- 拖拽区域误吞点击
- 按钮点击变拖拽
- 页面局部可拖、局部不可拖

要求：

- 没有强需求时，优先回原生标题栏

### 4. 误把白屏归因到数据层的风险

当前没有直接证据证明右侧白屏来自 IPC、workspace summary 或消息加载失败。

风险：

- 执行方误入数据流排查，修一圈还没解决布局

要求：

- 先把布局骨架恢复，再决定是否需要继续查数据层

## 测试计划

### 1. 静态检查

执行：

```powershell
corepack pnpm typecheck
```

目标：

- 确保 UI 改动没有引入类型错误

### 2. 桌面主界面人工回归

验证项：

1. 启动后幕布 logo 尺寸正常，不再按原图 512x512 裸显示
2. 幕布品牌区、文案、进度条不重叠
3. 进入主界面后左侧侧栏宽度正常
4. 左侧 logo 卡片尺寸正常
5. 左侧会话区可以正常显示和滚动
6. 右侧会话区可见，不是整块白屏
7. 消息区和输入区都能正常显示

### 3. 窗口控件回归

验证项：

1. 关闭/最大化/最小化按钮出现在预期位置
2. 点击三个按钮行为正确
3. 窗口拖拽行为正确
4. 不会出现“按钮在左上角裸排”的情况

### 4. 多页面回归

至少验证：

1. 聊天页
2. 专家页
3. 设置页

原因：

- 这些页面都被 `91f42aa` 的结构改动波及

### 5. CSS 冲突回归

验证项：

1. 删除或收敛某批 `!` 强制类后，页面没有因为 Tailwind 覆盖再次错位
2. `styles.css` 与 `tailwind.css` 中对同一块布局的控制关系明确

## 建议执行顺序

1. 先核对 `create-window.ts` 的真实工作树状态
2. 先修 logo 与启动幕布缺样式问题
3. 再修主界面布局骨架
4. 再决定窗口控件走“回原生标题栏”还是“补完整自绘”
5. 最后跑 `typecheck` 并做桌面人工回归

## 一句话结论

当前回归不是单点 bug，而是三步叠加造成的：

- `6dec17b` 引入品牌图片和窗口控件结构，但没补齐样式
- `5e19ad5` 引入 Tailwind 样式管线，放大覆盖冲突
- `91f42aa` 重排主界面结构，又继续增加了大量未完全落地的新类和强制样式

修复时要先做减法，优先恢复稳定布局和原生窗口行为，再决定是否保留自定义视觉方案。
