Initial TrueGrowth source import

This commit is contained in:
2026-07-07 09:36:36 +08:00
commit 3b6781d695
2283 changed files with 691996 additions and 0 deletions

View File

@@ -0,0 +1,177 @@
# Data Model: 对话抽屉 (Chat Drawer)
**Date**: 2025-12-03
**Feature**: 001-chat-drawer
## Entities
### ChatSession (对话会话)
| Field | Type | Description | Constraints |
|-------|------|-------------|-------------|
| id | string | 会话唯一标识 | UUID v4, 主键 |
| title | string | 会话标题 | 从首条消息截取max 30字符 |
| createdAt | number | 创建时间戳 | Unix milliseconds |
| updatedAt | number | 最后更新时间戳 | Unix milliseconds |
| messageCount | number | 消息数量 | ≥ 0 |
**Lifecycle States**: Active → Archived (future)
**Indexes**:
- Primary: `id`
- Secondary: `updatedAt` (用于排序)
### ChatMessage (对话消息)
| Field | Type | Description | Constraints |
|-------|------|-------------|-------------|
| id | string | 消息唯一标识 | UUID v4, 主键 |
| sessionId | string | 所属会话ID | 外键 → ChatSession.id |
| role | 'user' \| 'assistant' | 消息角色 | 枚举值 |
| content | string | 消息内容 | Markdown格式 |
| timestamp | number | 发送时间戳 | Unix milliseconds |
| status | MessageStatus | 消息状态 | 枚举值 |
| attachments | Attachment[] | 附件列表 | 可选,数组 |
| error | string \| null | 错误信息 | 可选 |
**MessageStatus 枚举**:
- `sending`: 发送中
- `streaming`: AI正在生成
- `success`: 发送成功
- `failed`: 发送失败
**Indexes**:
- Primary: `id`
- Compound: `[sessionId, timestamp]` (用于按会话查询消息)
### Attachment (附件)
| Field | Type | Description | Constraints |
|-------|------|-------------|-------------|
| id | string | 附件唯一标识 | UUID v4 |
| name | string | 文件名 | max 255字符 |
| type | string | MIME类型 | e.g., 'image/png' |
| size | number | 文件大小 | bytes |
| data | string | 文件数据 | Base64 或 Blob URL |
| isBlob | boolean | 是否为Blob URL | 用于清理 |
**支持的文件类型**:
- 图片: image/png, image/jpeg, image/gif, image/webp
- 文档: application/pdf, text/plain, text/markdown
- 其他: application/json, text/csv
**大小限制**:
- 单个文件: 10MB
- 单条消息总附件: 20MB
### DrawerState (抽屉状态)
| Field | Type | Description | Constraints |
|-------|------|-------------|-------------|
| isOpen | boolean | 是否展开 | 默认 false |
| width | number | 当前宽度 | 320-500px默认视口30% |
| activeSessionId | string \| null | 当前活跃会话ID | 可选 |
**Note**: DrawerState 存储在 localStorage不使用 IndexedDB需要同步访问
## Relationships
```
┌─────────────────┐ ┌─────────────────┐
│ ChatSession │ 1:N │ ChatMessage │
│─────────────────│───────│─────────────────│
│ id (PK) │ │ id (PK) │
│ title │ │ sessionId (FK) │
│ createdAt │ │ role │
│ updatedAt │ │ content │
│ messageCount │ │ timestamp │
└─────────────────┘ │ status │
│ attachments[] │
└─────────────────┘
│ 1:N (embedded)
┌─────────────────┐
│ Attachment │
│─────────────────│
│ id │
│ name │
│ type │
│ size │
│ data │
└─────────────────┘
```
## Storage Schema
### IndexedDB Configuration
```javascript
// Database: 'aitu-chat'
// Version: 1
const stores = {
sessions: {
keyPath: 'id',
indexes: [
{ name: 'updatedAt', keyPath: 'updatedAt', unique: false }
]
},
messages: {
keyPath: 'id',
indexes: [
{ name: 'sessionId', keyPath: 'sessionId', unique: false },
{ name: 'sessionTimestamp', keyPath: ['sessionId', 'timestamp'], unique: false }
]
}
};
```
### localStorage Keys
```typescript
const CHAT_STORAGE_KEYS = {
DRAWER_STATE: 'aitu:chat:drawer-state',
ACTIVE_SESSION: 'aitu:chat:active-session',
};
```
## Validation Rules
### ChatSession
- `id`: 必须是有效的 UUID v4
- `title`: 非空最大30字符自动从首条消息截取
- `createdAt/updatedAt`: 有效的 Unix 时间戳
### ChatMessage
- `id`: 必须是有效的 UUID v4
- `sessionId`: 必须引用存在的 ChatSession
- `role`: 必须是 'user' 或 'assistant'
- `content`: 用户消息最大10000字符AI消息无限制
- `attachments`: 单条消息最多5个附件
### Attachment
- `type`: 必须在支持的 MIME 类型列表中
- `size`: 单个文件最大10MB
- `data`: Base64 字符串或有效的 Blob URL
## Data Cleanup Policies
### 自动清理
- 会话数量超过50时删除最早的会话保留最近50个
- 单会话消息超过100条时删除最早的消息
- Blob URL 在页面卸载时自动释放
### 手动清理
- 用户可删除单个会话及其所有消息
- 用户可清空所有对话历史
## Migration Strategy
### Version 1 (Initial)
- 创建 sessions 和 messages stores
- 无需迁移
### Future Versions
- 使用 localforage 的版本管理
- 迁移脚本模式参考 `history-migration.ts`