任务多图支持设计
状态:暂不实现 - 复杂度较高,收益有限,详见文末"复杂度评估"章节
概述
支持单个绘图任务生成多张图片。用户对生成结果不满意时,可点击"重新生成"按钮追加新图片,同时保留历史图片供切换查看。
使用场景
- 嵌入式绘图组件:AI 生成的插图不满意,点击重新生成
- 绘图工作台:对任务结果不满意,追加生成新图片
- 图片浏览:在多张图片间切换,选择最满意的一张
数据模型变更
方案:新增 task_images 表
sql
CREATE TABLE task_images (
id INTEGER PRIMARY KEY AUTOINCREMENT,
task_id INTEGER NOT NULL REFERENCES tasks(id),
image_url TEXT NOT NULL, -- 图片 URL
created_at TEXT NOT NULL, -- 生成时间
status TEXT NOT NULL DEFAULT 'pending', -- pending/processing/success/failed
error TEXT, -- 失败原因
progress TEXT -- 生成进度
);
CREATE INDEX task_images_task_id ON task_images(task_id);tasks 表变更
sql
ALTER TABLE tasks ADD COLUMN selected_image_id INTEGER REFERENCES task_images(id);| 字段 | 说明 |
|---|---|
selected_image_id | 当前选中的图片 ID,用于记录用户偏好 |
字段迁移
现有 tasks 表的图片相关字段保持不变(兼容性),新生成的图片写入 task_images 表:
| 原字段 | 处理方式 |
|---|---|
imageUrl | 保留,作为第一张图片的冗余存储 |
progress | 保留,表示当前正在生成的图片进度 |
error | 保留,表示当前生成的错误 |
任务状态设计
任务级状态 (tasks.status)
| 状态 | 含义 |
|---|---|
pending | 任务创建,等待提交 |
submitting | 正在提交到上游 |
processing | 有图片正在生成中 |
success | 至少有一张图片生成成功,且当前无进行中的生成 |
failed | 最近一次生成失败,且当前无进行中的生成 |
图片级状态 (task_images.status)
| 状态 | 含义 |
|---|---|
pending | 等待生成 |
processing | 生成中 |
success | 生成成功 |
failed | 生成失败 |
状态流转
任务创建 → pending
↓
首次提交 → submitting → processing → success/failed
↓
点击重新生成 → processing → success/failed
↓
再次重新生成 → ...API 设计
POST /api/tasks/:id/regenerate
触发重新生成(追加新图片)
请求:无需 body
响应:
json
{
"taskId": 123,
"imageId": 456,
"status": "processing"
}逻辑:
- 检查任务是否存在且属于当前用户
- 创建新的
task_images记录(状态为pending) - 更新
tasks.status为processing - 提交生成任务
并发生成:允许同时生成多张图片,用户可连续点击多次
PUT /api/tasks/:id/select-image
切换选中的图片
请求:
json
{
"imageId": 456
}响应:
json
{
"success": true
}GET /api/tasks/:id(现有接口扩展)
响应新增字段:
json
{
"id": 123,
"status": "success",
"images": [
{
"id": 1,
"imageUrl": "/api/images/xxx.jpg",
"status": "success",
"createdAt": "2025-12-24T10:00:00Z"
},
{
"id": 2,
"imageUrl": "/api/images/yyy.jpg",
"status": "success",
"createdAt": "2025-12-24T10:05:00Z"
}
],
"selectedImageId": 2,
"currentImageUrl": "/api/images/yyy.jpg"
}POST /api/illustrations(现有接口扩展)
响应新增字段:
json
{
"taskId": 123,
"status": "success",
"images": [...],
"selectedImageId": 2,
"currentImageUrl": "/api/images/yyy.jpg"
}前端组件设计
MjDrawingBlock.vue 变更
┌─────────────────────────────────────┐
│ [图片区域] │
│ ┌─────────────────────────────┐ │
│ │ │ │
│ │ [当前图片] │ │
│ │ │ │
│ │ [◀] [▶] │ │ ← 多图时显示切换按钮
│ └─────────────────────────────┘ │
│ │
│ [下载] [放大] [重新生成] │ ← 成功时显示重新生成按钮
│ [模型标签] [2/3] [信息按钮] │ ← 显示当前图片索引
│ ════════════════════════════════ │
└─────────────────────────────────────┘新增功能:
- 左右切换按钮(多图时显示)
- 图片索引指示器(如 2/3)
- 重新生成按钮(成功状态时显示)
TaskCard.vue 变更(绘图工作台)
与 MjDrawingBlock 类似:
- 添加图片切换功能
- 添加重新生成按钮
- 显示图片数量指示器
实现文件清单
数据库
server/database/schema.ts- 添加taskImages表,tasks添加selectedImageIdserver/database/migrations/- 生成迁移文件
后端
server/services/task.ts- 添加regenerate()、selectImage()方法server/api/tasks/[id]/regenerate.post.ts- 重新生成接口server/api/tasks/[id]/select-image.put.ts- 切换图片接口server/api/tasks/[id].get.ts- 扩展返回 images 数组
前端
app/components/chat/MjDrawingBlock.vue- 添加多图切换和重新生成app/components/drawing/TaskCard.vue- 添加多图切换和重新生成app/composables/useTasks.ts- 添加regenerate()、selectImage()方法
兼容性考虑
- 现有任务:通过迁移脚本将
tasks.imageUrl导入task_images表 - API 响应:统一从
task_images表读取,保持接口一致性 - tasks.imageUrl 字段:保留但不再写入,仅用于迁移过渡期的兼容
数据迁移脚本
迁移时执行:
sql
-- 将现有成功任务的图片导入 task_images
INSERT INTO task_images (task_id, image_url, status, created_at)
SELECT id, image_url, 'success', created_at
FROM tasks
WHERE image_url IS NOT NULL AND status = 'success';
-- 更新 selected_image_id 指向迁移的图片
UPDATE tasks
SET selected_image_id = (
SELECT id FROM task_images WHERE task_images.task_id = tasks.id LIMIT 1
)
WHERE image_url IS NOT NULL AND status = 'success';边界情况
- 并发重新生成:允许同时生成多张,前端显示多个进度条或合并显示
- 生成中切换图片:允许,不影响正在进行的生成
- 删除任务:级联删除所有
task_images记录
复杂度评估
新增复杂度
| 方面 | 变更 | 复杂度增量 |
|---|---|---|
| 数据库 | 新增 task_images 表 + 迁移脚本 | 中 |
| 后端服务 | TaskService 需管理两张表的状态同步 | 高 |
| 并发控制 | 多个图片同时生成,状态聚合逻辑复杂 | 高 |
| 轮询逻辑 | 需轮询多个图片状态,判断整体完成 | 中 |
| 前端组件 | 图片切换、多进度显示、索引同步 | 中 |
| API | 3 个新接口 + 现有接口扩展 | 中 |
风险点
状态同步:
tasks.status需根据所有task_images状态聚合计算- 任一图片 processing → 任务 processing
- 全部完成且至少一张成功 → 任务 success
- 全部完成且全部失败 → 任务 failed
并发生成的 UI 表达:多张图片同时生成时如何展示?
- 方案 A:显示多个进度条(复杂)
- 方案 B:只显示"N 张生成中"文字(简单)
轮询效率:每次轮询需查询
task_images表,数据量大时可能有性能问题
建议
不建议现阶段实现此功能,理由:
- 投入产出比低:当前单图模式已能满足基本需求,重新生成可通过"删除 + 新建"实现
- 复杂度显著增加:状态管理从单一变为聚合,容易出 bug
- 并发生成场景少:用户通常看到结果后才决定是否重新生成,很少连续点击
如果确实需要,建议简化方案:
- 禁止并发生成:同一任务同时只能有一个生成进行中,降低状态管理复杂度
- 延迟实现切换记忆:
selectedImageId可以先不做服务端持久化,仅前端记忆 - 分阶段交付:
- 第一阶段:仅支持重新生成 + 图片切换(无并发、无持久化选择)
- 第二阶段:按需添加并发和持久化
