Files
TrueGrowth/specs/003-chat-drawer/research.md

188 lines
5.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Research: 对话抽屉 (Chat Drawer)
**Date**: 2025-12-03
**Feature**: 001-chat-drawer
## 技术决策
### 1. 抽屉组件实现方案
**Decision**: 使用 CSS Transform + Transition 实现抽屉动画
**Rationale**:
- CSS Transform 利用 GPU 加速,性能最优
- 现有项目已有类似动画模式unified-toolbar 的响应式切换)
- 简单直接,易于维护
**Alternatives Considered**:
- Framer Motion功能强大但增加依赖体积
- React Spring学习曲线较高
- TDesign Drawer与画板布局集成复杂
### 2. 流式响应实现方案
**Decision**: 使用 Fetch API + ReadableStream 处理 SSE (Server-Sent Events)
**Rationale**:
- 原生支持,无需额外依赖
- 与现有 Gemini API 集成模式一致
- 可以逐字符/逐词渲染,提供最佳用户体验
**Alternatives Considered**:
- WebSocket需要服务端支持过于复杂
- 轮询:用户体验差,延迟高
- 第三方库(如 openai-streams增加依赖
### 3. 对话存储方案
**Decision**: IndexedDB via localforage独立 store
**Rationale**:
- 项目已使用 localforagetask-queue 模块)
- IndexedDB 支持大容量存储50MB+
- 异步 API 不阻塞主线程
- 支持复杂查询和索引
**Alternatives Considered**:
- localStorage5MB 限制,同步 API
- 纯 IndexedDBAPI 复杂localforage 封装更友好
- 云端存储:需要后端支持,超出当前范围
### 4. 会话状态管理方案
**Decision**: React Context + useReducer + RxJS Subject
**Rationale**:
- 与现有 DrawnixContext 模式一致
- RxJS 用于跨组件事件通信(参考 task-queue-service
- useReducer 管理复杂状态转换
**Alternatives Considered**:
- Redux/Zustand增加依赖当前规模不需要
- 纯 Context复杂状态难以管理
- Jotai/Recoil团队不熟悉
### 5. 附件处理方案
**Decision**: FileReader + Base64 编码存储小文件,大文件使用 Blob URL
**Rationale**:
- 小文件(<5MBBase64 存储便于 IndexedDB 持久化
- 大文件 Blob URL 避免内存问题
- 与现有 media-cache-service 模式一致
**Alternatives Considered**:
- 全部 Base64大文件性能差
- 全部 Blob刷新后丢失
- 云存储:需要后端
### 6. 响应式布局方案
**Decision**: CSS Media Query + ResizeObserver + isMobile 状态
**Rationale**:
- 与现有 unified-toolbar 响应式模式一致
- 结合 CSS 和 JS 实现精确控制
- 复用现有 isMobile 检测逻辑
**Alternatives Considered**:
- 纯 CSS复杂状态难以处理
- 纯 JS性能开销大
### 7. AI API 集成方案
**Decision**: 复用现有 gemini-api 工具,扩展支持聊天接口
**Rationale**:
- API Key 管理已在 settings-manager 中实现
- 减少重复代码
- 统一的错误处理和重试逻辑
**Alternatives Considered**:
- 新建独立 API 模块:重复工作
- 使用第三方 SDK增加依赖
## 最佳实践
### React 组件结构
```typescript
// 组件拆分策略 - 确保每个文件 <500 行
// ChatDrawer.tsx: 主容器,状态管理 (~200行)
// MessageList.tsx: 消息列表渲染 (~150行)
// MessageItem.tsx: 单条消息 (~100行)
// MessageInput.tsx: 输入框 (~150行)
// SessionList.tsx: 会话列表 (~100行)
// SessionItem.tsx: 单个会话 (~80行)
// AttachmentPreview.tsx: 附件预览 (~100行)
// StreamingText.tsx: 流式文本 (~80行)
```
### 性能优化
```typescript
// 1. 消息列表虚拟化(长列表场景)
// 使用 react-window 或自定义实现
// 2. 消息组件记忆化
const MessageItem = React.memo(({ message }) => {...});
// 3. 存储操作防抖
const debouncedSave = useMemo(
() => debounce(saveToStorage, 500),
[]
);
// 4. 流式渲染优化
// 使用 requestAnimationFrame 批量更新
```
### 错误处理
```typescript
// 统一错误边界
class ChatErrorBoundary extends React.Component {
static getDerivedStateFromError(error) {
return { hasError: true, error };
}
render() {
if (this.state.hasError) {
return <ChatErrorFallback error={this.state.error} />;
}
return this.props.children;
}
}
// API 错误处理
try {
await sendMessage(content);
} catch (error) {
if (error.name === 'AbortError') {
// 用户取消
} else if (error.status === 429) {
// 限流
} else {
// 通用错误
}
}
```
## 技术风险
| Risk | Impact | Mitigation |
|------|--------|------------|
| AI API 响应慢 | 用户体验差 | 流式显示 + 加载状态 + 超时处理 |
| IndexedDB 存储满 | 数据丢失 | 存储限额监控 + 自动清理旧数据 |
| 长对话性能 | 卡顿 | 虚拟滚动 + 消息分页 |
| 移动端键盘遮挡 | 输入困难 | 监听 visualViewport + 自动滚动 |
| 网络断开 | 消息发送失败 | 离线检测 + 队列重试 |
## 参考实现
- **现有 Dialog 系统**: `packages/drawnix/src/components/dialog/dialog.tsx`
- **Task Queue UI**: `packages/drawnix/src/components/task-queue/`
- **存储服务**: `packages/drawnix/src/services/storage-service.ts`
- **Settings Manager**: `packages/drawnix/src/utils/settings-manager.ts`
- **Gemini API**: `packages/drawnix/src/utils/gemini-api/`