137 lines
3.9 KiB
Markdown
137 lines
3.9 KiB
Markdown
# 首页图片选择功能设计
|
||
|
||
## 1. 需求概述
|
||
|
||
在首页聊天界面的加号按钮弹出的底部面板中,实现拍照和相册选择图片功能:
|
||
- 最多选择 3 张图片
|
||
- 图片预览显示在输入框上方
|
||
- 图片可被取消移除
|
||
- 点击发送后图片随文本一起发送到后端
|
||
|
||
## 2. 技术方案
|
||
|
||
### 2.1 依赖
|
||
|
||
添加 `image_picker: ^1.0.7` 到 `pubspec.yaml`
|
||
|
||
### 2.2 状态管理
|
||
|
||
在 `HomeScreen` 中添加图片状态:
|
||
```dart
|
||
List<XFile> _selectedImages = []; // 最多3张
|
||
```
|
||
|
||
### 2.3 图片选择逻辑
|
||
|
||
修改 `home_sheet.dart`:
|
||
- `image_picker` 选择图片(最多3张)
|
||
- 返回选中的 `List<XFile>` 到 `HomeScreen`
|
||
|
||
### 2.4 AG-UI 消息格式
|
||
|
||
修改 `ag_ui_service.dart` 的 `_buildRunInput` 方法,支持多模态消息:
|
||
|
||
```dart
|
||
Map<String, dynamic> _buildRunInput({
|
||
required String content,
|
||
List<XFile>? images,
|
||
}) {
|
||
final threadId = _threadId ?? _newUuid();
|
||
final runId = _nextId(_runIdPrefix);
|
||
|
||
// 构建多模态内容块
|
||
final contentBlocks = <Map<String, dynamic>>[];
|
||
|
||
// 添加文本
|
||
if (content.isNotEmpty) {
|
||
contentBlocks.add({'type': 'text', 'text': content});
|
||
}
|
||
|
||
// 添加图片(Base64 编码)
|
||
for (final image in images ?? []) {
|
||
final bytes = await image.readAsBytes();
|
||
final base64 = base64Encode(bytes);
|
||
contentBlocks.add({
|
||
'type': 'image',
|
||
'source': {
|
||
'type': 'base64',
|
||
'media_type': 'image/jpeg',
|
||
'data': base64,
|
||
},
|
||
});
|
||
}
|
||
|
||
return {
|
||
'threadId': threadId,
|
||
'runId': runId,
|
||
'state': <String, dynamic>{},
|
||
'messages': [
|
||
{
|
||
'id': _nextId('user_'),
|
||
'role': 'user',
|
||
'content': contentBlocks.length == 1
|
||
? (contentBlocks[0]['type'] == 'text'
|
||
? contentBlocks[0]['text']
|
||
: contentBlocks)
|
||
: contentBlocks,
|
||
},
|
||
],
|
||
// ...
|
||
};
|
||
}
|
||
```
|
||
|
||
## 3. UI 设计
|
||
|
||
### 3.1 图片预览区
|
||
|
||
位置:输入框上方,聊天消息区域下方
|
||
|
||
```
|
||
┌─────────────────────────────────────┐
|
||
│ 聊天消息区域 │
|
||
│ │
|
||
├─────────────────────────────────────┤
|
||
│ ┌─────────┐ ┌─────────┐ ┌────────┐│
|
||
│ │ ✕ │ │ ✕ │ │ ✕ ││ ← 预览区
|
||
│ │ [图片] │ │ [图片] │ │ [图片] ││
|
||
│ └─────────┘ └─────────┘ └────────┘│
|
||
├─────────────────────────────────────┤
|
||
│ [+] [ 输入消息... ] [发送]│
|
||
└─────────────────────────────────────┘
|
||
```
|
||
|
||
### 3.2 样式规格
|
||
|
||
| 元素 | 值 |
|
||
|------|-----|
|
||
| 预览卡片尺寸 | 80x80 dp |
|
||
| 圆角 | `AppRadius.md` (12dp) |
|
||
| 间距 | `AppSpacing.sm` (8dp) |
|
||
| 取消按钮 | 24x24 圆形,红色背景,白色 X 图标 |
|
||
| 边框 | 1dp `AppColors.slate200` |
|
||
|
||
### 3.3 交互
|
||
|
||
- 点击加号 → 底部弹出选择面板
|
||
- 选择图片 → 预览区显示缩略图
|
||
- 点击 X → 移除对应图片
|
||
- 输入文本 + 有图片 → 点击发送发送组合消息
|
||
|
||
## 4. 文件改动
|
||
|
||
| 文件 | 改动 |
|
||
|------|------|
|
||
| `pubspec.yaml` | 添加 image_picker 依赖 |
|
||
| `home_sheet.dart` | 实现拍照/相册选择 |
|
||
| `home_screen.dart` | 添加图片状态、预览区 UI |
|
||
| `ag_ui_service.dart` | 修改 _buildRunInput 支持多模态 |
|
||
|
||
## 5. 测试要点
|
||
|
||
- [ ] 选择 1-3 张图片正常显示
|
||
- [ ] 选择超过 3 张时提示或限制
|
||
- [ ] 图片可以成功移除
|
||
- [ ] 发送消息时图片 Base64 正确编码
|
||
- [ ] AG-UI 消息格式符合规范
|