嵌入式绘图组件介绍
在 MJ-Studio 的对话功能中,AI 可以通过 Markdown 代码块直接生成插图,让文字内容与视觉效果无缝结合。这个功能特别适合生成小说配图、教程插图、场景可视化等场景。
功能概述
- 对话中生图: AI 在回复中插入特殊格式的代码块,自动触发图片生成
- 幂等设计: 相同的唯一标识不会重复生成,刷新页面保持状态
- 状态同步: 基于全局事件系统,图片生成进度实时更新
- 任务复用: 与绘图工作台共享任务系统,统一管理
- 模糊控制: 遵循全局模糊设置,保护隐私内容
使用方式
AI 输出格式
AI 在回复中使用 mj-drawing 代码块定义绘图参数:
markdown
```mj-drawing
uniqueId: 第一章-主角初遇场景
prompt: A young swordsman drawing his sword under moonlight, silver blade reflecting the moon
model: flux-schnell
negative: blurry, low quality
autostart: false
```参数说明
| 参数 | 必需 | 默认值 | 说明 |
|---|---|---|---|
uniqueId | ✅ | - | 全局唯一标识,用于缓存和去重 |
prompt | ✅ | - | 绘图提示词 |
model | ❌ | 默认配置 | 模型名称,匹配用户启用的模型配置 |
negative | ❌ | - | 负面提示词 |
autostart | ❌ | false | 是否自动开始生成 |
uniqueId 设计
- 用途: 防止相同场景重复生图,支持刷新页面后状态恢复
- 格式建议: 章节-场景-序号,如
第一章-林雨拔剑-001 - 全局唯一: 同一用户下,相同 uniqueId 只会生成一次任务
autostart 参数
false(默认): 显示"生成插图"按钮,用户点击后才开始生成true: 组件挂载后自动开始生成任务
典型场景
场景 1: 小说配图
AI 在生成小说内容时,在关键场景自动插入绘图组件:
markdown
林雨缓缓拔出长剑,月光在剑身上流转,映照出他坚毅的面容。
```mj-drawing
uniqueId: 第一章-林雨拔剑-001
prompt: A young swordsman drawing his sword under moonlight, silver blade reflecting the moon, determined expression, ancient Chinese martial arts style, dramatic lighting, cinematic composition
model: flux-schnell
negative: blurry, low quality, modern clothing
```
对面的蒙面杀手也不甘示弱,黑色斗篷在夜风中猎猎作响。场景 2: 教程插图
技术教程中插入架构图或流程图:
markdown
用户登录流程如下:
```mj-drawing
uniqueId: 用户登录流程图
prompt: Clean flowchart diagram showing user login process, boxes and arrows, professional style, white background
model: dalle-3
negative: messy, cluttered
```
首先验证用户名和密码...场景 3: 场景可视化
游戏设计文档中可视化场景:
markdown
这个关卡的地图布局如下:
```mj-drawing
uniqueId: 第三关-地图布局
prompt: Top-down view of a dungeon level, stone corridors, treasure chests, monster spawn points, grid-based layout, pixel art style
model: midjourney-v6
```
玩家从左上角入口进入...组件界面
状态显示
嵌入式绘图组件会根据任务状态显示不同的界面:
idle 状态 (等待生成):
┌─────────────────────────────────────┐
│ ┌─────────────────────────────┐ │
│ │ ✨ 图标 │ │
│ │ 等待提交 │ │
│ │ [生成插图] 按钮 │ │
│ │ │ │
│ │ ───────────────────── │ │
│ │ uniqueId: xxx │ │
│ │ prompt: xxx │ │
│ └─────────────────────────────┘ │
│ [模型标签] │
└─────────────────────────────────────┘processing 状态 (生成中):
┌─────────────────────────────────────┐
│ ┌─────────────────────────────┐ │
│ │ [竖线加载动画] │ │
│ │ 正在创作中... │ │
│ │ │ │
│ │ ───────────────────── │ │
│ │ uniqueId: xxx │ │
│ │ prompt: xxx │ │
│ └─────────────────────────────┘ │
│ [模型标签] │
│ ════════════════════════════════ │ ← 彩色进度条
└─────────────────────────────────────┘success 状态 (已完成):
┌─────────────────────────────────────┐
│ [生成的图片] │
│ (点击切换模糊/清晰) │
│ │
│ [操作按钮组] ← 默认隐藏 │
│ [模型标签] │
└─────────────────────────────────────┘failed 状态 (失败):
┌─────────────────────────────────────┐
│ ┌─────────────────────────────┐ │
│ │ ⚠️ 图标 │ │
│ │ 生成失败 │ │
│ │ 错误信息: xxx │ │
│ │ [重试] 按钮 │ │
│ │ ───────────────────── │ │
│ │ uniqueId: xxx │ │
│ │ prompt: xxx │ │
│ └─────────────────────────────┘ │
│ [模型标签] │
└─────────────────────────────────────┘操作按钮
按钮显示规则 (仅成功状态):
- 默认隐藏: 所有按钮默认不显示
- PC 端: 鼠标悬浮图片时显示按钮
- 移动端: 点击图片切换按钮显示/隐藏
按钮布局 (左上角半透明按钮组):
┌─────────────────────────────────────┐
│ [⬇][🔍][🔄][ℹ️] ← 半透明圆形按钮 │
│ │
│ [生成的图片] │
│ │
│ [模型标签] │
└─────────────────────────────────────┘按钮功能:
- 下载按钮 (⬇): 下载图片到本地
- 放大查看 (🔍): 在模态框中查看大图
- 重新生成 (🔄): 删除旧任务重新生成
- 查看详情 (ℹ️): 显示 uniqueId、提示词、模型等信息
详情弹窗
点击信息按钮显示绘图参数:
┌─────────────────────────────────┐
│ 绘图详情 [×] │
├─────────────────────────────────┤
│ │
│ 标识 (uniqueId) │
│ 第一章-林雨拔剑-001 │
│ │
│ 提示词 (prompt) │
│ A young swordsman drawing... │
│ │
│ 模型 (model) │
│ flux-schnell │
│ │
│ 负面提示词 (negative) │
│ blurry, low quality │
│ │
│ [关闭] │
└─────────────────────────────────┘技术实现
前端流程
1. AI 输出 mj-drawing 代码块
↓
2. useMarkdown 识别并解析参数
↓
3. MarkdownContent 渲染 MjDrawingBlock 组件
↓
4. 组件挂载时调用 POST /api/illustrations
- 已存在任务 → 显示当前状态
- 不存在 + autostart=false → 显示"生成"按钮
- 不存在 + autostart=true → 创建并开始任务
↓
5. 订阅全局事件,实时更新任务状态
↓
6. 任务完成后显示图片流式输出处理
AI 流式输出时,代码块可能未闭合:
AI 正在输出 → ```mj-drawing
uniqueId: xxx
prompt: A young... (未闭合)解决方案:
- 检测未闭合的代码块,显示占位符 "正在生成插图参数..."
- 等待代码块闭合后再解析参数
- 清理 AI 输出中的零宽字符,避免解析错误
数据库设计
复用 tasks 表,新增两个字段:
| 字段 | 类型 | 说明 |
|---|---|---|
uniqueId | TEXT | 全局唯一标识 (唯一索引) |
sourceType | TEXT | 来源类型 (workbench / chat) |
来源标记:
workbench: 绘图工作台创建chat: 对话中的嵌入式绘图组件创建
筛选分离:
- 绘图工作台默认只显示
sourceType = workbench的任务 - 需要筛选才会显示
sourceType = chat的任务
API 接口
POST /api/illustrations
查询或创建插图任务 (幂等接口)
请求体:
json
{
"uniqueId": "第一章-林雨拔剑-001",
"prompt": "A young swordsman...",
"model": "flux-schnell",
"negative": "blurry, low quality",
"autostart": false
}响应:
json
{
"taskId": 123,
"status": "success",
"progress": null,
"resourceUrl": "/api/images/xxx.jpg",
"error": null,
"isBlurred": true
}逻辑:
- 根据
uniqueId查询任务 - 已存在 → 返回当前状态
- 不存在 +
autostart=false→ 返回{ status: 'idle', taskId: null } - 不存在 +
autostart=true→ 创建任务并提交,返回pending状态
核心组件
| 组件 | 文件路径 | 功能 |
|---|---|---|
useMarkdown | app/composables/useMarkdown.ts | 识别 mj-drawing 代码块,生成占位符 HTML |
MarkdownContent | app/components/chat/MarkdownContent.vue | 解析占位符,渲染 MjDrawingBlock 组件 |
MjDrawingBlock | app/components/chat/MjDrawingBlock.vue | 嵌入式绘图组件,管理任务状态和 UI |
与绘图工作台的关系
共享部分
- 任务系统: 共享
tasks表和任务服务 - 模型配置: 使用相同的上游和模型配置
- 全局事件: 共享任务状态更新事件
- 模糊控制: 遵循全局模糊设置
独立部分
- 来源标记:
sourceType = chat,与工作台任务分开筛选 - 唯一标识:
uniqueId字段,工作台任务为 null - 参数来源: 通过代码块定义,而非表单输入
- 自动触发: 支持
autostart自动生成
配置 AI 助手
要让 AI 在对话中使用嵌入式绘图功能,可以在助手的 System Prompt 中添加指引:
## 插图功能
在输出小说内容时,请在以下场景插入绘图组件生成插图:
- 重要场景切换
- 关键人物登场
- 高潮情节
- 环境氛围描写
### 插图组件格式
```mj-drawing
uniqueId: 唯一标识 (描述性名称,如"第一章-主角初遇场景")
prompt: 详细的画面描述 (英文效果更佳)
model: flux-schnell
negative: blurry, low quality, distorted
```
### 插图要求
1. uniqueId 必须全局唯一,建议格式: 章节-场景-序号
2. prompt 要详细描述:
- 人物外貌、服装、动作
- 场景环境、光线、氛围
- 画面构图、视角
- 艺术风格 (如: digital art, anime style, realistic)
3. 每个章节建议 2-4 张插图
4. 插图位置应在相关描写段落之后
### 插图示例
林雨缓缓拔出长剑,月光在剑身上流转,映照出他坚毅的面容。
```mj-drawing
uniqueId: 第一章-林雨拔剑-001
prompt: A young swordsman drawing his sword under moonlight, silver blade reflecting the moon, determined expression, ancient Chinese martial arts style, dramatic lighting, cinematic composition
model: flux-schnell
negative: blurry, low quality, modern clothing
```
对面的蒙面杀手也不甘示弱,黑色斗篷在夜风中猎猎作响。使用技巧
优化提示词
- 详细描述: 包含人物、场景、光线、氛围、风格等要素
- 英文优先: 大部分模型对英文提示词效果更好
- 指定风格: 添加
digital art、anime style、realistic等风格关键词 - 负面提示词: 使用
blurry、low quality、distorted等避免常见问题
uniqueId 命名规范
- 描述性: 清晰描述场景,如
第一章-林雨拔剑-001 - 层级结构: 章节-场景-序号
- 唯一性: 确保全局唯一,避免重复生成
模型选择
- 快速生成:
flux-schnell(速度快,效果好) - 高质量:
midjourney-v6、dalle-3(质量高,速度慢) - 中文提示词:
z-image-turbo(支持中文提示词)
注意事项
限制和约束
- uniqueId 唯一性: 相同 uniqueId 只会生成一次,修改参数不会重新生成
- 模型可用性: 指定的 model 必须在用户的上游配置中存在
- 流式输出: 代码块未闭合时不会触发生成,等待完整输出
- 事件订阅: 需要用户登录并建立全局 SSE 连接
性能优化
- 懒加载: 组件挂载时才查询任务状态
- 事件驱动: 状态更新通过全局事件推送,不轮询
- 模糊加载: 图片默认模糊,点击后加载原图
- 缓存复用: 相同 uniqueId 复用已有任务
下一步计划
短期增强
- 批量操作: 支持一键重新生成所有失败的插图
- 参数编辑: 允许用户修改 uniqueId 后的绘图参数
- 预览优化: 支持图片放大查看、全屏模式
中期扩展
- 视频支持: 支持
mj-video代码块生成视频 - 音频支持: 支持
mj-audio代码块生成配乐 - 图库导入: 支持从图库选择已有图片作为插图
长期规划
- 智能插图: AI 自动判断何时需要插图,自动生成
- 风格一致性: 同一对话中的插图保持风格一致
- 角色记忆: 记住角色外貌,保持插图中的角色一致性
