# S6: 聊天界面 — 气泡 + 输入框 + 流式渲染 ## 目标 在 `aichat.html` 的主区域(#chatArea)实现完整的聊天界面: - 用户消息气泡(右侧蓝色) - AI 消息气泡(左侧灰色) - 底部输入框 + 发送按钮 - 流式渲染:SSE 实时推送 AI 回复,逐词显示 - Enter 发送 / Shift+Enter 换行 - Loading 指示器(AI 思考中) - 自动滚动到底部 - 切换到不同会话时加载历史消息 ## 涉及文件 - `templates/aichat.html` — 唯一修改文件 ## 依赖(已验证) - `local_db.py`: conversations/messages 表 ✓, conv_list/msg_list/msg_add 等函数 ✓ - `app.py`: - /api/conversations ✓ - /api/conversations//messages GET ✓ - /api/conversations//messages POST ✓ - /api/conversations//stream SSE ✓ - /chat → aichat.html ✓ ## 数据流 ``` 用户输入 → POST /api/conversations//messages → 保存 user msg → call_hermes() → 保存 assistant msg → 返回 JSON 或者:用户输入 → GET /api/conversations//stream?message=xxx → SSE text/event-stream → 前端逐 chunk 渲染 → [DONE] 后追加到消息列表 ``` 两者都可用。POST 模式适合简单场景,SSE 适合流式。同时支持。 ## 步骤 1. **CSS**: 添加消息气泡样式(user/assistant)、输入区域样式、loading 动画 2. **HTML**: 替换 #chatArea 的 .empty-state 为 .messages-container + .input-area 3. **JS**: 实现 `selectConversation(id)` 加载历史消息 4. **JS**: 实现 `sendMessage()` — SSE 流式发送 + 渲染 5. **JS**: 实现流式 chunk 渲染、完成标记、自动滚动 6. **JS**: Enter 发送 / Shift+Enter 换行 ## 验证命令 ```bash # 1. 页面能打开 curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1:5000/chat # 2. 关键 JS 函数存在 curl -s http://127.0.0.1:5000/chat | grep "function sendMessage" curl -s http://127.0.0.1:5000/chat | grep "function selectConversation" # 3. JS 无转义错误 curl -s http://127.0.0.1:5000/chat | python3 -c " import sys; html=sys.stdin.read() assert \"style=\\\\\\\\'\" not in html, 'STYLE BACKSLASH BUG' assert \"\\\\\\\\\\\\\\\\\\\\\\\"'\" not in html, 'TRIPLE ESCAPE BUG' print('JS CLEAN') " # 4. 关键 DOM 元素存在 curl -s http://127.0.0.1:5000/chat | grep 'id="msgList"' curl -s http://127.0.0.1:5000/chat | grep 'id="msgInput"' curl -s http://127.0.0.1:5000/chat | grep 'id="sendBtn"' # 5. 无 onclick 转义陷阱 curl -s http://127.0.0.1:5000/chat | python3 -c " import sys; html=sys.stdin.read() assert 'toggleContent(' not in html, 'ONCLICK ESCAPE BUG' assert '\\\\\\'' not in html, 'BACKSLASH SINGLE QUOTE' print('ONCLICK CLEAN') " # 6. smoketest cd ~/wechat-viewer && python3 test_smoke.py ``` ## 风险 - SSE 实现需注意连接断开后的清理 - 消息气泡中 Markdown/代码块渲染(基础实现即可,不做复杂格式化) - 自动滚动需在流式刷新时保持体验 - 不要用 `\\'` 转义 onclick(直接使用 data 属性 + addEventListener 或避免引号嵌套)