# 用户端聊天页重构记录

## 一、变更背景

依据 2026 年 7 月 11 日确认的最新设计图，重构“大本营答疑助手”登录后的手机端聊天页面。本次只调整现有聊天功能的视觉层级和交互体验，不新增官网、首页、课程、个人中心、收藏、通知或其他门户能力。

## 二、现状确认

- 前端技术栈：Vue 3、TypeScript、Vite。
- 图标组件：复用项目已安装的 `@lucide/vue`，不使用 Emoji、字符图标或手绘 SVG。
- Markdown：复用 `markdown-it` 渲染 AI 回复。
- 登录态与用户信息：复用现有 `userApi.profile()` 和本地令牌逻辑。
- 当前会话额度：来自用户资料接口的 `todayUsed` 与 `dailyLimit` 字段，页面展示为“已使用/每日上限”。
- 会话列表：复用 `GET /chat/session/list`，字段包含标题、消息数量和更新时间。
- 会话消息：复用 `GET /chat/history`。
- 会话新建、改名、删除：分别复用现有 `POST /chat/session`、`PUT /chat/session/title`、`DELETE /chat/session/:id`。
- 消息发送：复用现有流式接口 `POST /chat/completions`，不修改后端协议。
- 退出登录：复用现有退出接口和清理登录态逻辑。

## 三、改造范围

1. 将聊天页拆分为顶部栏、额度栏、消息列表、输入区和历史会话抽屉等职责清晰的组件。
2. 顶部显示历史会话入口、助手名称、连接状态、昵称、用户名和退出按钮。
3. 用户消息右对齐，AI 回复使用适合长文本阅读的白色卡片并正确渲染 Markdown。
4. 空会话只显示简洁提示，不增加推荐问题或其他入口。
5. 输入框支持 1 至 3 行自动增高，失败时保留输入内容，成功后再清空。
6. 历史会话从左侧抽屉打开，支持新建、切换、改名和删除。
7. 会话改名使用输入弹窗，删除和退出使用二次确认弹窗，不使用浏览器原生 `alert` 或 `confirm`。
8. 补全初始化、加载、发送、生成、空列表、网络异常和登录失效等反馈。
9. 适配 375px、390px、414px 手机宽度、微信浏览器、刘海屏、底部安全区和软键盘场景。

## 四、关键交互决策

### 4.1 新聊天

点击“新聊天”时优先复用已有的零消息空会话，避免连续点击产生多个空会话；没有空会话时才调用创建接口。

### 4.2 会话切换

点击当前会话不重复请求；切换其他会话时加载完整历史消息、关闭抽屉、刷新额度并滚动到最新消息。

### 4.3 消息滚动

- 用户发送问题后滚动到新问题位置。
- 用户位于底部附近时，流式回答自动跟随。
- 用户主动向上阅读后暂停强制跟随，避免被持续拉回底部。
- 会话切换后主动滚动到最新消息。

### 4.4 消息发送

- 空内容和请求中禁止重复发送。
- 发送成功并完成流式响应后清空输入框。
- 发送失败时保留输入内容，便于用户修改或重试。
- AI 回复中的模型内部 `<think>` 内容不展示。

### 4.5 会话删除

删除前必须二次确认。删除当前会话后，优先进入最近会话；如果没有其他会话，则创建新的空会话。

### 4.6 移动端布局

顶部栏和底部输入区固定在应用容器内，中间聊天区独立滚动；抽屉打开时锁定底层滚动，并使用独立列表滚动区域。

## 五、计划修改文件

- `apps/user-client/src/App.vue`
- `apps/user-client/src/styles.css`
- `apps/user-client/src/components/ChatHeader.vue`（新增）
- `apps/user-client/src/components/SessionQuota.vue`（新增）
- `apps/user-client/src/components/MessageList.vue`（新增）
- `apps/user-client/src/components/ChatMessage.vue`
- `apps/user-client/src/components/ChatComposer.vue`
- `apps/user-client/src/components/SessionDrawer.vue`
- 必要时新增日期格式化等轻量工具文件，不调整无关页面。

## 六、明确不做

- 不修改后端接口协议。
- 不增加用户头像、通知、收藏、点赞、点踩、复制操作栏、个人中心、课程、资料、老师、统计、会话搜索、分组、置顶或推荐问题。
- 不展示模型内部思考过程。
- 不使用模拟会话、模拟消息、写死用户名或写死额度。

## 七、验收方式

1. 执行前端构建和类型检查。
2. 使用真实本地服务验证登录后的聊天主流程。
3. 检查 375px、390px、414px 宽度下的空会话、长回答、抽屉、改名、删除和输入区。
4. 检查无横向滚动、无控制台报错、无内容遮挡。
5. 将设计图与实现截图进行并排对照，并在项目根目录保存 `design-qa.md`。

## 八、实施结果

- 已完成 `ChatHeader`、`SessionQuota`、`MessageList` 三个职责组件的新增。
- 已重构 `ChatMessage`、`ChatComposer`、`SessionDrawer` 和聊天主页面。
- 已补全退出、会话改名和会话删除的应用内确认弹窗。
- 已实现零消息会话复用、同会话防重复加载、删除当前会话后的自动承接。
- 已实现流式回答响应式更新、用户上滑后暂停自动跟随、发送失败保留输入。
- 已隐藏模型内部思考过程，并兼容模型产生嵌套 `<think>` 标签的情况。
- 已修正消息接口 UTC 无时区字符串在本地显示少 8 小时的问题。
- 已移除 Vite 热更新端口硬编码，使本机直连和域名网关按当前访问地址建立连接。
- 已使用真实账号和真实接口完成空会话、消息发送、长回答、额度刷新、历史抽屉、改名弹窗和删除确认验证。
- 已完成 375px、390px、414px 三档浏览器尺寸检查，无横向滚动或核心区域遮挡。
- `npm run build` 和 Vue TypeScript 类型检查通过，最终浏览器控制台无错误或警告。

## 九、环境记录

重建本地容器时发现数据库已存在 `sys_chat_session.summary` 字段，但 Alembic 版本仍停留在 `0004_daily_chat_reset_date`，导致同事新增的 `0005_chat_session_summary` 重复加列而启动失败。本地已核实字段存在后将版本标记到 `0005_chat_session_summary`，随后正常执行 `0006_expand_ai_request_log_text`。本次未修改后端代码或迁移文件。
