# 无限画布功能集成开发方案 ## 项目背景 本方案旨在参考 [lobe-chat-pro](https://github.com/vual/lobe-chat-pro) 项目的无限画布功能,将其核心能力集成到我们的 AI Chatbot 项目中。 --- ## 一、lobe-chat-pro 无限画布功能分析 ### 1.1 核心功能特性 | 功能模块 | 描述 | 支持的模型 | |---------|------|-----------| | **连续对话画布** | 在对话中设计、修改图片,用图片生成视频 | Google、OpenAI、Midjourney、Kling、Doubao | | **画图生成** | 文本转图片、参考图生成 | Google、OpenAI、Midjourney、Kling、Doubao | | **视频生成** | 文本转视频、图片转视频 | Google、OpenAI、Kling、Luma、Runway | | **图片修改** | 高清放大、移除背景、提取图层、局部修改、图片扩展 | 各类图像处理 API | | **联网搜索** | 根据需求搜索网络上的最新内容 | 搜索引擎 API | ### 1.2 技术栈对比 | 技术点 | lobe-chat-pro | 我们的项目 | 兼容性 | |--------|---------------|-----------|--------| | 框架 | Next.js 15.3.6 | Next.js 16 | ✅ 高度兼容 | | React | 19.2.1 | 19.0.0-rc | ✅ 兼容 | | 状态管理 | Zustand 5.0.4 | React Hooks + SWR | ⚠️ 需评估 | | UI 库 | Tailwind + antd-style | Tailwind + Radix UI | ✅ 可共存 | | 虚拟列表 | react-virtuoso | 无 | 🆕 需引入 | | 布局 | react-layout-kit | 无 | 🆕 需引入 | | 数据库 | PostgreSQL | PostgreSQL + Drizzle | ✅ 兼容 | ### 1.3 关键依赖库 ```json { "@lobehub/editor": "^1.20.2", "@tanstack/react-query": "^5.90.2", "react-virtuoso": "^4.14.1", "react-layout-kit": "^2.0.0", "react-rnd": "^10.5.2", "framer-motion": "^12.23.24", "zustand": "^5.0.4" } ``` --- ## 二、集成方案设计 ### 2.1 方案选择 #### 方案 A:完整移植 + 深度集成(推荐度:⭐⭐⭐⭐⭐) **描述:** 完整移植 lobe-chat-pro 的无限画布模块,然后修改代码深度集成我们的功能 **优点:** - 功能完整,体验一致 - 快速获得成熟稳定的功能 - 减少从零开发的风险和工作量 - 移植后可逐步优化和定制 - 可复用已验证的代码逻辑 **缺点:** - 需要引入相关依赖 - 需要花时间适配现有架构 - 需要理解原项目代码结构 #### 方案 B:参考实现,自主开发(推荐度:⭐⭐⭐) **描述:** 参考 lobe-chat-pro 的设计思路,基于现有架构自主开发 **优点:** - 与现有架构深度融合 - 可控性高 **缺点:** - 开发工作量大 - 需要从零实现所有功能 - 开发周期长 #### 方案 C:仅移植核心组件(推荐度:⭐⭐) **描述:** 只移植部分核心组件,其余自主开发 **优点:** - 灵活性高 **缺点:** - 可能导致功能不完整 - 集成难度大 ### 2.2 推荐方案:方案 A - 完整移植 + 深度集成 基于以下考虑: 1. lobe-chat-pro 的画布功能已经过验证,稳定可靠 2. 完整移植可以快速获得全部功能 3. 移植后再深度集成我们现有的图片编辑功能(抠图、增强、场景裂变等) 4. 可以复用我们现有的 AI 模型配置和存储服务 5. 渐进式适配降低风险 --- ## 三、完整移植方案 ### 3.1 需要移植的文件清单 #### 3.1.1 核心状态管理(必须移植) ``` src/store/painting/ ├── action.ts # 核心操作逻辑(623行)- 包含 Midjourney 等 API 调用 ├── index.ts # 导出入口 ├── initialState.ts # 初始状态定义 ├── selectors.ts # 状态选择器 ├── store.ts # Zustand store 创建 └── utils.ts # 工具函数 src/store/image/ ├── index.ts # 图片状态 store ├── slices/ │ ├── createImage/ # 图片创建状态 │ ├── generationConfig/ # 生成配置状态 │ ├── generationBatch/ # 批次管理 │ └── generationTopic/ # 主题管理 └── selectors.ts # 选择器 ``` #### 3.1.2 服务层(必须移植) ``` src/services/painting/ ├── client.ts # 客户端服务实现 ├── index.ts # 服务导出 ├── server.ts # 服务端实现 └── type.ts # 服务接口定义 src/services/textToImage.ts # 文本生图服务 src/services/image.ts # 图片服务 ``` #### 3.1.3 类型定义(必须移植) ``` src/types/ ├── painting/ │ └── index.ts # Painting 类型定义 ├── image/ │ └── index.ts # 图片相关类型 └── tool/ └── index.ts # 工具类型 ``` #### 3.1.4 页面和组件(必须移植) ``` src/app/[variants]/(main)/ ├── painting/ # 独立绘图面板 │ ├── page.tsx │ ├── layout.tsx │ └── features/ │ ├── ImagesContainer/ # 图片容器 │ ├── PalettePanel/ # 调色板面板 │ └── PromptInput/ # 提示词输入 │ ├── image/ # 图片生成工作区 │ ├── page.tsx │ ├── layout.tsx │ └── features/ │ ├── ImageWorkspace/ # 图片工作区 │ ├── GenerationFeed/ # 生成结果展示 │ └── PromptInput/ # 提示词输入 src/features/Conversation/ ├── Messages/ # 消息渲染 │ ├── Assistant/ │ │ ├── MessageContent.tsx │ │ ├── Tool/ # 工具调用渲染 │ │ └── Extra/ │ └── User/ └── components/ └── VirtualizedList/ # 虚拟化列表 ``` #### 3.1.5 API 路由(必须移植) ``` src/app/(backend)/webapi/ ├── text-to-image/ │ └── [provider]/ │ └── route.ts # 图片生成 API ├── text-to-video/ │ └── [provider]/ │ └── route.ts # 视频生成 API └── painting/ └── route.ts # 绘图管理 API ``` #### 3.1.6 数据库模型(需适配) ``` src/database/ ├── models/ │ └── painting.ts # 绘图数据模型 └── schemas/ └── painting.ts # 绘图表结构 ``` ### 3.2 需要安装的依赖 ```bash # 必须安装的依赖 pnpm add zustand@5.0.4 immer@^10.1.3 # 画布交互相关 pnpm add react-rnd@^10.5.2 react-virtuoso@^4.14.1 react-layout-kit@^2.0.0 # 动画效果 pnpm add framer-motion@^12.23.24 # 数据获取(可选,我们已有 SWR) pnpm add @tanstack/react-query@^5.90.2 # 编辑器组件(可选) pnpm add @lobehub/editor@^1.20.2 # UI 组件(可选,用于过渡期) pnpm add antd@^5.27.4 antd-style@^3.7.1 ``` ### 3.3 移植步骤 #### 步骤 1:准备工作 ```bash # 1. 克隆 lobe-chat-pro 仓库到本地参考 git clone https://github.com/vual/lobe-chat-pro.git ~/lobe-chat-pro-ref # 2. 安装必要依赖 cd ~/Desktop/ai-chatbot-main pnpm add zustand@5.0.4 immer@^10.1.3 react-rnd@^10.5.2 \ react-virtuoso@^4.14.1 react-layout-kit@^2.0.0 framer-motion@^12.23.24 ``` #### 步骤 2:创建目录结构 ```bash # 在我们项目中创建对应目录 mkdir -p components/canvas mkdir -p components/canvas/nodes mkdir -p components/canvas/tools mkdir -p components/canvas/hooks mkdir -p store/painting mkdir -p store/image mkdir -p services/painting mkdir -p types/painting mkdir -p app/canvas mkdir -p app/canvas/[id] mkdir -p app/api/canvas mkdir -p app/api/canvas/generate ``` #### 步骤 3:移植核心文件 按以下顺序移植(依赖关系从低到高): | 顺序 | 文件/目录 | 来源路径 | 目标路径 | 说明 | |-----|----------|---------|---------|------| | 1 | 类型定义 | `src/types/painting/` | `types/painting/` | 基础类型 | | 2 | 服务接口 | `src/services/painting/type.ts` | `services/painting/type.ts` | 接口定义 | | 3 | 初始状态 | `src/store/painting/initialState.ts` | `store/painting/initialState.ts` | 状态定义 | | 4 | 选择器 | `src/store/painting/selectors.ts` | `store/painting/selectors.ts` | 状态选择 | | 5 | 工具函数 | `src/store/painting/utils.ts` | `store/painting/utils.ts` | 辅助函数 | | 6 | Store | `src/store/painting/store.ts` | `store/painting/store.ts` | 状态管理 | | 7 | Actions | `src/store/painting/action.ts` | `store/painting/action.ts` | 核心逻辑 | | 8 | 服务实现 | `src/services/painting/client.ts` | `services/painting/client.ts` | 客户端服务 | | 9 | 页面组件 | `src/app/[variants]/(main)/painting/` | `app/canvas/` | 画布页面 | --- ## 四、深度集成方案 移植完成后,需要深度集成我们现有的功能。 ### 4.1 整体架构设计 ``` ┌─────────────────────────────────────────────────────────────────────────┐ │ 无限画布工作区 │ ├─────────────────────────────────────────────────────────────────────────┤ │ ┌─────────────┐ ┌───────────────────────┐ ┌─────────────────────┐ │ │ │ 工具栏 │ │ 画布区域 │ │ 属性面板 │ │ │ │ - 选择 │ │ - 消息节点 │ │ - 节点配置 │ │ │ │ - 画笔 │ │ - 图片节点 │ │ - 生成参数 │ │ │ │ - 文本 │ │ - 视频节点 │ │ - 历史记录 │ │ │ │ - 形状 │ │ - 连接线 │ │ │ │ │ │ │ │ │ │ 【深度集成功能】 │ │ │ │ 【集成】 │ │ 【集成我们的功能】 │ │ - 抠图 │ │ │ │ - 抠图 │ │ - 场景裂变结果 │ │ - 图片增强 │ │ │ │ - 增强 │ │ - 角度编辑结果 │ │ - 图片扩展 │ │ │ │ - 扩展 │ │ - 抠图结果 │ │ - 角度编辑 │ │ │ │ - 角度 │ │ │ │ - 场景裂变 │ │ │ └─────────────┘ └───────────────────────┘ └─────────────────────┘ │ ├─────────────────────────────────────────────────────────────────────────┤ │ ┌─────────────────────────────────────────────────────────────────┐ │ │ │ 输入区域 │ │ │ │ - 文本输入 / 图片上传 / 语音输入 / 【复用 multimodal-input】 │ │ │ └─────────────────────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────────────────────┘ ``` ### 4.2 需要适配的部分 #### 4.2.1 数据库适配(Drizzle ORM) 将 lobe-chat-pro 的数据库模型适配到我们的 Drizzle Schema: ```typescript // lib/db/schema.ts (新增) import { pgTable, uuid, text, jsonb, timestamp, integer } from 'drizzle-orm/pg-core'; // 画布项目表 export const canvasProject = pgTable('canvas_project', { id: uuid('id').primaryKey().defaultRandom(), userId: uuid('user_id').notNull().references(() => user.id, { onDelete: 'cascade' }), title: text('title').notNull().default('未命名画布'), description: text('description'), thumbnail: text('thumbnail'), canvasData: jsonb('canvas_data'), // 存储完整画布状态 createdAt: timestamp('created_at').notNull().defaultNow(), updatedAt: timestamp('updated_at').notNull().defaultNow(), }); // 绘图记录表(对应 lobe-chat-pro 的 Painting) export const painting = pgTable('painting', { id: uuid('id').primaryKey().defaultRandom(), userId: uuid('user_id').notNull().references(() => user.id, { onDelete: 'cascade' }), projectId: uuid('project_id').references(() => canvasProject.id, { onDelete: 'set null' }), // 平台和动作 platform: text('platform').notNull(), // 'Midjourney' | 'Google' | 'OpenAI' | 'Kling' | 'Doubao' | 'Alibaba' action: text('action').notNull(), // 'IMAGINE' | 'BLEND' | 'DESCRIBE' | 'UPSCALE' | 'VARIATION' 等 // 任务状态 taskId: text('task_id'), status: text('status').notNull().default('SUBMITTED'), // 'SUBMITTED' | 'IN_PROGRESS' | 'SUCCESS' | 'FAILURE' progress: integer('progress').default(0), failReason: text('fail_reason'), // 内容 prompt: text('prompt'), negativePrompt: text('negative_prompt'), images: jsonb('images').$type>(), // 配置 config: jsonb('config'), extra: jsonb('extra'), createdAt: timestamp('created_at').notNull().defaultNow(), updatedAt: timestamp('updated_at').notNull().defaultNow(), }); ``` #### 4.2.2 认证适配(NextAuth) ```typescript // services/painting/server.ts (适配) import { auth } from '@/app/(auth)/auth'; export class ServerPaintingService { async queryPainting(params?: { current?: number; pageSize?: number }) { const session = await auth(); if (!session?.user?.id) { throw new Error('Unauthorized'); } // 使用我们的 Drizzle 查询 const paintings = await db.query.painting.findMany({ where: eq(painting.userId, session.user.id), limit: params?.pageSize || 20, offset: ((params?.current || 1) - 1) * (params?.pageSize || 20), orderBy: desc(painting.createdAt), }); return paintings; } // ... 其他方法 } ``` #### 4.2.3 AI 提供商适配 将 lobe-chat-pro 的 AI 调用适配到我们的动态提供商系统: ```typescript // lib/ai/canvas-providers.ts import { getActiveAIProvider } from '@/lib/db/queries'; export async function getCanvasImageProvider(providerType: string) { // 从数据库获取配置的提供商 const provider = await getActiveAIProvider(providerType); switch (providerType) { case 'alibaba': return createAlibabaImageProvider(provider); case 'gemini': return createGeminiImageProvider(provider); case 'openai': return createOpenAIImageProvider(provider); // ... 其他提供商 } } ``` #### 4.2.4 存储服务适配 ```typescript // services/painting/storage.ts import { uploadToStorage } from '@/lib/storage/service'; export async function savePaintingImage(imageUrl: string, userId: string) { // 下载图片 const response = await fetch(imageUrl); const blob = await response.blob(); // 上传到我们的存储桶 const file = new File([blob], `painting-${Date.now()}.png`, { type: 'image/png' }); const storedUrl = await uploadToStorage(file, userId, 'painting'); return storedUrl; } ``` ### 4.3 深度集成我们的现有功能 #### 4.3.1 集成图片编辑功能 在画布的图片节点中集成我们现有的图片编辑能力: ```typescript // components/canvas/nodes/ImageNode.tsx import { ImageAnnotator } from '@/components/image-annotator'; import { AngleEditDialog } from '@/components/angle-edit-dialog'; export function ImageNode({ data }: { data: ImageNodeData }) { const [editMode, setEditMode] = useState<'view' | 'annotate' | 'angle' | null>('view'); // 图片操作菜单 - 集成我们现有的所有功能 const imageActions = [ // 图片处理 { label: '抠图', action: 'rmbg', api: '/api/rmbg', icon: Scissors }, { label: '变清晰', action: 'enhance', api: '/api/enhance', icon: Sparkles }, { label: '图片扩展', action: 'extend', api: '/api/extend', icon: Expand }, { label: '尺寸调整', action: 'resize', api: '/api/resize', icon: Maximize2 }, { label: '角度编辑', action: 'angle', component: AngleEditDialog, icon: Move3D }, { label: '场景裂变', action: 'scene-fusion', component: SceneFusionView, icon: Layers }, { label: '物体检测', action: 'detect', api: '/api/detect-object', icon: Search }, // 标注工具 { label: '画笔标注', action: 'pen', tool: 'pen', icon: Pencil }, { label: '箭头标注', action: 'arrow', tool: 'arrow', icon: ArrowRight }, { label: '圆圈标注', action: 'circle', tool: 'circle', icon: Circle }, { label: '文字标注', action: 'text', tool: 'text', icon: Type }, // 其他 { label: '下载图片', action: 'download', icon: Download }, { label: '上传到相册', action: 'upload-gallery', api: '/api/gallery', icon: Upload }, ]; const handleAction = async (action: string) => { // 调用对应的 API 或打开编辑组件 }; return (
{data.prompt} {editMode === 'annotate' && ( )} {editMode === 'angle' && ( )}
); } ``` #### 4.3.2 集成 AI 模型选择 使用我们数据库中配置的 AI 模型: ```typescript // components/canvas/panels/ModelSelector.tsx import useSWR from 'swr'; export function ModelSelector({ type }: { type: 'image' | 'video' }) { // 从数据库获取可用的模型 const { data: models } = useSWR(`/api/admin/ai-models?type=${type}`); return ( ); } ``` #### 4.3.3 集成场景裂变功能 将场景裂变作为画布的一个特殊节点类型: ```typescript // components/canvas/nodes/SceneFusionNode.tsx export function SceneFusionNode({ data }: { data: SceneFusionNodeData }) { const [results, setResults] = useState([]); const [isGenerating, setIsGenerating] = useState(false); const handleGenerate = async () => { setIsGenerating(true); const response = await fetch('/api/scene-fusion', { method: 'POST', body: JSON.stringify({ productImage: data.productImage, backgroundImages: data.backgroundImages, productName: data.productName, }), }); const result = await response.json(); setResults(result.images); setIsGenerating(false); }; return (
{results.map((url, index) => ( {`结果 ))}
); } ``` ### 4.4 UI 适配策略 #### 方式一:保留 antd 组件(快速上线) 初期可以保留 lobe-chat-pro 使用的 antd 组件,后续再逐步替换: ```bash pnpm add antd@^5.27.4 antd-style@^3.7.1 ``` #### 方式二:替换为 Radix UI(推荐长期) 将 antd 组件逐步替换为我们的 Radix UI 组件: | antd 组件 | 替换为 | 说明 | |----------|--------|------| | `Button` | `@/components/ui/button` | 直接替换 | | `Input` | `@/components/ui/input` | 直接替换 | | `Select` | `@/components/ui/select` | 直接替换 | | `Modal` | `@/components/ui/dialog` | 直接替换 | | `Dropdown` | `@/components/ui/dropdown-menu` | 直接替换 | | `Tabs` | `@/components/ui/tabs` | 直接替换 | | `Slider` | `@/components/ui/slider` | 直接替换 | | `Tooltip` | `@/components/ui/tooltip` | 直接替换 | --- ## 五、开发计划(移植 + 集成) ### 5.1 阶段划分 #### 第一阶段:环境准备与依赖安装 **任务清单:** - [ ] 克隆 lobe-chat-pro 仓库到本地作为参考 - [ ] 安装所有必要依赖 - [ ] 创建目录结构 - [ ] 配置 TypeScript 和 ESLint **命令:** ```bash # 克隆参考仓库 git clone https://github.com/vual/lobe-chat-pro.git ~/lobe-chat-pro-ref # 安装依赖 pnpm add zustand@5.0.4 immer@^10.1.3 react-rnd@^10.5.2 \ react-virtuoso@^4.14.1 react-layout-kit@^2.0.0 \ framer-motion@^12.23.24 antd@^5.27.4 antd-style@^3.7.1 ``` #### 第二阶段:核心模块移植 **任务清单:** - [ ] 移植类型定义 (`types/painting/`) - [ ] 移植状态管理 (`store/painting/`) - [ ] 移植服务层 (`services/painting/`) - [ ] 移植 API 路由 - [ ] 适配数据库 Schema **交付物:** - 可运行的状态管理系统 - 数据库表结构 - 基础 API 接口 #### 第三阶段:页面组件移植 **任务清单:** - [ ] 移植画布页面组件 - [ ] 移植绘图面板组件 - [ ] 移植图片工作区组件 - [ ] 配置路由 **交付物:** - 可访问的画布页面 `/canvas` - 基础绘图功能 #### 第四阶段:深度集成我们的功能 **任务清单:** - [ ] 集成图片抠图功能 - [ ] 集成图片增强功能 - [ ] 集成图片扩展功能 - [ ] 集成角度编辑功能 - [ ] 集成场景裂变功能 - [ ] 集成我们的 AI 模型配置 **交付物:** - 在画布中可使用我们所有的图片编辑功能 - 支持从数据库选择 AI 模型 #### 第五阶段:UI 适配与优化 **任务清单:** - [ ] 将 antd 组件替换为 Radix UI(可选) - [ ] 统一样式风格 - [ ] 性能优化 - [ ] 测试和修复 Bug **交付物:** - 风格统一的 UI - 稳定可用的无限画布功能 ### 5.2 详细任务清单 | 序号 | 任务 | 优先级 | 状态 | |-----|------|--------|------| | 1 | 安装 Zustand 和相关依赖 | P0 | ⬜ | | 2 | 创建 `store/painting/` 目录结构 | P0 | ⬜ | | 3 | 移植 `painting` 类型定义 | P0 | ⬜ | | 4 | 移植 `paintingStore` 状态管理 | P0 | ⬜ | | 5 | 创建 `painting` 数据库表 | P0 | ⬜ | | 6 | 移植 `PaintingService` 服务层 | P0 | ⬜ | | 7 | 适配认证系统(NextAuth) | P0 | ⬜ | | 8 | 移植画布主页面组件 | P1 | ⬜ | | 9 | 移植绘图面板组件 | P1 | ⬜ | | 10 | 配置画布路由 `/canvas` | P1 | ⬜ | | 11 | 适配存储服务 | P1 | ⬜ | | 12 | 集成抠图功能 | P2 | ⬜ | | 13 | 集成图片增强功能 | P2 | ⬜ | | 14 | 集成场景裂变功能 | P2 | ⬜ | | 15 | 集成角度编辑功能 | P2 | ⬜ | | 16 | 集成 AI 模型选择 | P2 | ⬜ | | 17 | UI 风格统一 | P3 | ⬜ | | 18 | 性能优化 | P3 | ⬜ | --- ## 六、技术参考 ### 6.1 核心模块设计 #### 模块 1:画布引擎(Canvas Engine) **文件结构:** ``` components/canvas/ ├── index.tsx # 主组件入口 ├── Canvas.tsx # 画布容器 ├── CanvasViewport.tsx # 视口控制(缩放、平移) ├── CanvasNode.tsx # 节点基类 ├── nodes/ │ ├── MessageNode.tsx # 消息节点 │ ├── ImageNode.tsx # 图片节点 │ ├── VideoNode.tsx # 视频节点 │ └── ConnectionLine.tsx # 连接线 ├── tools/ │ ├── SelectTool.tsx # 选择工具 │ ├── PanTool.tsx # 平移工具 │ └── ZoomControl.tsx # 缩放控制 ├── hooks/ │ ├── useCanvasState.ts # 画布状态管理 │ ├── useNodeDrag.ts # 节点拖拽 │ ├── useViewport.ts # 视口控制 │ └── useCanvasHistory.ts # 撤销/重做 └── types.ts # 类型定义 ``` **核心接口定义:** ```typescript // types.ts export interface CanvasNode { id: string; type: 'message' | 'image' | 'video' | 'text'; position: { x: number; y: number }; size: { width: number; height: number }; data: MessageNodeData | ImageNodeData | VideoNodeData; connections: string[]; // 连接的节点 ID createdAt: Date; updatedAt: Date; } export interface MessageNodeData { role: 'user' | 'assistant'; content: string; attachments?: Attachment[]; } export interface ImageNodeData { src: string; prompt?: string; model?: string; status: 'pending' | 'generating' | 'completed' | 'failed'; metadata?: Record; } export interface VideoNodeData { src: string; thumbnail?: string; prompt?: string; model?: string; status: 'pending' | 'generating' | 'completed' | 'failed'; duration?: number; } export interface CanvasState { nodes: CanvasNode[]; selectedNodeIds: string[]; viewport: { x: number; y: number; zoom: number; }; tool: 'select' | 'pan' | 'draw'; } ``` #### 模块 2:状态管理(Canvas Store) **推荐引入 Zustand 进行状态管理:** ```typescript // store/canvas.ts import { create } from 'zustand'; import { immer } from 'zustand/middleware/immer'; interface CanvasStore { // 状态 nodes: CanvasNode[]; selectedNodeIds: string[]; viewport: Viewport; tool: ToolType; history: CanvasState[]; historyIndex: number; // 节点操作 addNode: (node: CanvasNode) => void; updateNode: (id: string, updates: Partial) => void; deleteNode: (id: string) => void; selectNode: (id: string, multi?: boolean) => void; // 视口操作 setViewport: (viewport: Partial) => void; zoomIn: () => void; zoomOut: () => void; fitToScreen: () => void; // 历史操作 undo: () => void; redo: () => void; pushHistory: () => void; // 工具 setTool: (tool: ToolType) => void; } export const useCanvasStore = create()( immer((set, get) => ({ // ... 实现 })) ); ``` #### 模块 3:AI 生成集成 **扩展现有 AI 服务:** ```typescript // lib/ai/canvas-ai.ts export interface CanvasAIService { // 图片生成 generateImage(params: { prompt: string; model: string; referenceImage?: string; size?: string; style?: string; }): Promise; // 视频生成 generateVideo(params: { prompt: string; model: string; referenceImage?: string; duration?: number; }): Promise; // 图片编辑 editImage(params: { image: string; action: 'upscale' | 'remove-bg' | 'extend' | 'inpaint'; options?: Record; }): Promise; // 对话生成 chat(params: { messages: Message[]; model: string; attachments?: Attachment[]; }): AsyncIterable; } ``` #### 模块 4:持久化存储 **数据库 Schema 扩展:** ```typescript // lib/db/schema.ts (新增) export const canvasProject = pgTable('canvas_project', { id: uuid('id').primaryKey().defaultRandom(), userId: uuid('user_id').notNull().references(() => user.id), title: text('title').notNull(), description: text('description'), thumbnail: text('thumbnail'), canvasData: jsonb('canvas_data').$type(), createdAt: timestamp('created_at').notNull().defaultNow(), updatedAt: timestamp('updated_at').notNull().defaultNow(), }); export const canvasNode = pgTable('canvas_node', { id: uuid('id').primaryKey().defaultRandom(), projectId: uuid('project_id').notNull().references(() => canvasProject.id), type: text('type').notNull(), position: jsonb('position').$type(), size: jsonb('size').$type(), data: jsonb('data'), connections: jsonb('connections').$type(), createdAt: timestamp('created_at').notNull().defaultNow(), updatedAt: timestamp('updated_at').notNull().defaultNow(), }); ``` ### 6.2 功能入口位置 #### 现有页面结构 ``` app/ ├── (chat)/ # 聊天模块(带侧边栏和顶部导航) │ ├── layout.tsx # 包含 TopNavbar + AppSidebar │ ├── page.tsx # 首页 │ ├── chat/[id]/page.tsx # 聊天详情页 │ ├── gallery/page.tsx # 图片相册页 │ └── featured/page.tsx # 精选作品页 ├── (admin)/ # 管理后台模块 │ └── settings/page.tsx # 系统设置页 └── (auth)/ # 认证模块 ├── login/page.tsx └── register/page.tsx ``` #### 入口位置方案 **方案 1:放在 (chat) 路由组内(推荐)** ``` app/(chat)/ ├── canvas/ # 画布列表页 │ └── page.tsx ├── canvas/[id]/ # 画布编辑页 │ └── page.tsx └── painting/ # 独立绘图面板(可选) └── page.tsx ``` **优点:** - 复用现有的 `TopNavbar` 和 `AppSidebar` - 与现有页面(gallery、featured)风格一致 - 用户可以在侧边栏快速切换 **方案 2:独立路由组** ``` app/(canvas)/ ├── layout.tsx # 独立布局(可能需要全屏画布) ├── page.tsx # 画布列表 └── [id]/ └── page.tsx # 画布编辑 ``` **优点:** - 画布编辑页可以使用全屏布局 - 布局更灵活 **方案 3:混合方案(推荐)** ``` app/ ├── (chat)/ │ └── canvas/ # 画布列表页(带侧边栏) │ └── page.tsx └── canvas/ # 画布编辑页(独立全屏布局) └── [id]/ ├── layout.tsx # 全屏画布布局 └── page.tsx ``` **优点:** - 列表页保持与其他页面一致的布局 - 编辑页使用全屏布局,最大化画布空间 #### 入口位置:顶部导航栏 当前顶部导航栏已有按钮: - 工具箱(自定义链接) - AI精选 - 精选榜 - **图片编辑** ← 现有功能 - 我的图册 - 系统设置(管理员) **添加"无限画布"入口,放在"图片编辑"旁边:** ``` 工具箱 | AI精选 | 精选榜 | 图片编辑 | 【无限画布】 | 我的图册 | ⚙️ ``` #### 需要修改的文件 ```typescript // components/top-navbar.tsx // 1. 添加图标导入 import { LayoutGrid } from "lucide-react"; // 2. 在"图片编辑"按钮后面添加"无限画布"按钮(约第255行后) {/* 无限画布 */} ``` #### 完整的导航栏按钮顺序 | 顺序 | 按钮 | 图标 | 颜色 | 路由 | |-----|------|------|------|------| | 1 | 工具箱 | `Briefcase` | 默认 | 下拉菜单 | | 2 | AI精选 | `Sparkles` | 黄色 | `/featured` | | 3 | 精选榜 | `Trophy` | 橙色 | 下拉菜单 | | 4 | 图片编辑 | `Edit` | 默认 | 弹窗 | | 5 | **无限画布** | `LayoutGrid` | **紫色** | `/canvas` | | 6 | 我的图册 | `Images` | 默认 | `/gallery` | | 7 | 系统设置 | `Settings` | 默认 | `/settings` | ### 6.3 页面路由设计 ``` app/ ├── (chat)/ │ ├── canvas/ │ │ └── page.tsx # 画布列表页(带侧边栏) │ └── ... ├── canvas/ │ └── [id]/ │ ├── layout.tsx # 全屏画布布局 │ └── page.tsx # 画布编辑页 └── api/ └── canvas/ ├── route.ts # 画布 CRUD ├── [id]/ │ ├── route.ts # 单个画布操作 │ └── nodes/ │ └── route.ts # 节点操作 └── generate/ ├── image/ │ └── route.ts # 图片生成 └── video/ └── route.ts # 视频生成 ``` ### 6.3 UI 组件示例 **基于现有 Radix UI 组件扩展:** ```tsx // components/canvas/ui/CanvasToolbar.tsx export function CanvasToolbar() { return (
} tool="select" /> } tool="pan" /> } tool="draw" /> {/* 集成我们的图片编辑功能 - 完整列表 */} {/* 图片处理功能 */} {/* 标注工具 */}
); } ``` --- ## 七、技术风险与应对 | 风险 | 影响 | 应对措施 | |------|------|---------| | 移植代码兼容性问题 | 高 | 分模块移植,逐步测试验证 | | antd 与 Radix UI 冲突 | 中 | 初期保留 antd,后期逐步替换 | | 大量节点性能问题 | 高 | 使用虚拟化渲染、节点懒加载 | | 状态同步复杂 | 中 | 使用 Zustand + immer 简化状态管理 | | AI 生成超时 | 中 | 实现任务队列、状态轮询 | | 数据库 Schema 差异 | 中 | 提前设计好适配层 | --- ## 八、技术选型建议 ### 8.1 必须引入的依赖 ```json { "zustand": "^5.0.4", // 状态管理(lobe-chat-pro 使用) "immer": "^10.0.0", // 不可变数据 "react-rnd": "^10.5.2", // 拖拽调整大小 "framer-motion": "^12.0.0", // 动画效果 "antd": "^5.27.4", // UI 组件(过渡期使用) "antd-style": "^3.7.1" // 样式系统(过渡期使用) } ``` ### 8.2 可选依赖 ```json { "react-virtuoso": "^4.14.1", // 虚拟列表(大量节点时) "@tanstack/react-query": "^5.0.0", // 数据获取缓存 "react-layout-kit": "^2.0.0" // 布局工具 } ``` --- ## 九、与现有功能整合清单 ### 9.1 复用现有组件 | 现有组件 | 集成方式 | 功能说明 | |---------|---------|---------| | `image-annotator.tsx` | 作为图片节点的编辑模式 | 完整的图片编辑器(标注、抠图、增强、扩展、调整等) | | `angle-edit-dialog.tsx` | 集成到图片节点操作菜单 | 3D 角度编辑对话框 | | `scene-fusion-view.tsx` | 作为特殊节点类型 | 场景裂变视图组件 | | `qwen-camera-widget.tsx` | 用于 3D 视角调整 | Three.js 3D 相机控件 | | `multimodal-input.tsx` | 作为画布输入组件 | 多模态输入(文本+图片+文件) | | `image-editor.tsx` | 用于流式图片生成 | 简单图片编辑器 | ### 9.2 复用现有 API #### 图片处理 API | 现有 API | 用途 | 说明 | |---------|------|------| | `/api/rmbg` | 图片抠图 | 移除图片背景 | | `/api/enhance` | 变清晰 | 图片高清增强 | | `/api/extend` | 图片扩展 | 向外扩展图片内容 | | `/api/resize` | 尺寸调整 | 调整图片分辨率/比例 | | `/api/angle-edit` | 角度编辑 | 3D 视角调整 | | `/api/scene-fusion` | 场景裂变 | 产品图+背景图融合生成 | | `/api/scene-fusion/config` | 场景裂变配置 | 获取场景裂变模型配置 | | `/api/detect-object` | 物体检测 | 检测图片中的物体 | #### 用户数据 API | 现有 API | 用途 | 说明 | |---------|------|------| | `/api/gallery` | 图片相册 | 用户生成的图片管理 | | `/api/featured` | 精选作品 | 精选作品展示 | | `/api/featured/ranking` | 排行榜 | 作品排行榜 | | `/api/messages` | 消息管理 | 聊天消息 CRUD | | `/api/user/image-quota` | 图片配额 | 用户图片生成配额 | | `/api/user/image-stats` | 图片统计 | 用户图片使用统计 | #### 系统配置 API | 现有 API | 用途 | 说明 | |---------|------|------| | `/api/site-settings` | 网站设置 | 网站名称、Logo 等 | | `/api/nav-links` | 导航链接 | 自定义导航链接 | | `/api/starter-questions` | 启动问题 | 聊天启动问题配置 | | `/api/auth-settings` | 认证设置 | 登录认证配置 | #### 管理后台 API | 现有 API | 用途 | 说明 | |---------|------|------| | `/api/admin/ai-models` | AI 模型管理 | 配置可用的 AI 模型 | | `/api/admin/ai-providers` | AI 提供商管理 | 配置 AI 服务提供商 | | `/api/admin/images` | 图片管理 | 管理用户生成的图片 | | `/api/admin/images/analytics` | 图片分析 | 图片使用数据分析 | | `/api/admin/storage` | 存储配置 | S3/MinIO 存储配置 | | `/api/admin/users` | 用户管理 | 用户列表和管理 | | `/api/admin/users/batch-limit` | 批量限额 | 批量设置用户配额 | | `/api/admin/settings` | 系统设置 | 系统级别配置 | | `/api/admin/tools` | 工具管理 | AI 工具配置 | | `/api/admin/volcano-video-models` | 火山视频模型 | 火山引擎视频模型配置 | #### 定时任务 API | 现有 API | 用途 | 说明 | |---------|------|------| | `/api/jobs/archive-videos` | 视频归档 | 定时归档视频任务 | ### 9.3 复用现有服务 ```typescript // 复用现有的存储服务 import { uploadToStorage } from '@/lib/storage/service'; // 复用现有的 AI 提供商 import { getAIProvider } from '@/lib/ai/providers'; // 复用现有的数据库查询 import { saveGeneratedImage } from '@/lib/db/queries'; ``` --- ## 十、总结 ### 10.1 实施路径 | 阶段 | 内容 | 说明 | |-----|------|------| | **第一阶段** | 环境准备 + 依赖安装 | 克隆参考仓库,安装依赖 | | **第二阶段** | 核心模块移植 | 移植 store、services、types | | **第三阶段** | 页面组件移植 | 移植画布页面和组件 | | **第四阶段** | 深度集成 | 集成我们的图片编辑功能 | | **第五阶段** | UI 适配优化 | 替换 antd 为 Radix UI(可选) | ### 10.2 关键成功因素 1. **完整移植:** 先完整移植功能,确保基础能力可用 2. **分阶段适配:** 逐步适配数据库、认证、存储服务 3. **深度集成:** 将我们现有的图片编辑能力集成进去 4. **保持兼容:** 初期保留 antd,避免大规模重写 ### 10.3 后续扩展方向 - 实时协作(多人同时编辑) - 模板系统(预设画布模板) - 插件系统(自定义节点类型) - 工作流自动化(节点触发规则) --- ## 附录 ### A. 参考资源 - [lobe-chat-pro 源码](https://github.com/vual/lobe-chat-pro) - [Zustand 文档](https://docs.pmnd.rs/zustand/) - [React-RnD 文档](https://github.com/bokuweb/react-rnd) - [Framer Motion 文档](https://www.framer.com/motion/) ### B. 我们项目中相关的现有文件 ``` components/ ├── image-annotator.tsx # 图片标注器(1775行) ├── angle-edit-dialog.tsx # 角度编辑对话框 ├── qwen-camera-widget.tsx # 3D 相机控件 ├── multimodal-input.tsx # 多模态输入 lib/ ├── ai/providers/ # AI 提供商 │ ├── alibaba-image.ts │ ├── gemini-image.ts │ └── ... ├── storage/service.ts # 存储服务 └── db/queries.ts # 数据库查询 app/api/ ├── rmbg/ # 抠图 API ├── enhance/ # 变清晰 API ├── extend/ # 图片扩展 API ├── resize/ # 尺寸调整 API ├── angle-edit/ # 角度编辑 API ├── scene-fusion/ # 场景裂变 API │ └── config/ # 场景裂变配置 ├── detect-object/ # 物体检测 API ├── gallery/ # 图片相册 API ├── featured/ # 精选作品 API │ └── ranking/ # 排行榜 API ├── messages/ # 消息管理 API ├── site-settings/ # 网站设置 API ├── nav-links/ # 导航链接 API ├── starter-questions/ # 启动问题 API ├── auth-settings/ # 认证设置 API ├── user/ │ ├── image-quota/ # 图片配额 API │ └── image-stats/ # 图片统计 API ├── jobs/ │ └── archive-videos/ # 视频归档任务 ├── auth/ │ ├── dingtalk/ # 钉钉登录 │ └── logout/ # 登出 └── admin/ ├── ai-models/ # AI 模型管理 ├── ai-providers/ # AI 提供商管理 ├── images/ # 图片管理 │ └── analytics/ # 图片分析 ├── storage/ # 存储配置 ├── users/ # 用户管理 │ └── batch-limit/ # 批量限额 ├── settings/ # 系统设置 ├── tools/ # 工具管理 ├── volcano-video-models/ # 火山视频模型 └── sync-dingtalk/ # 钉钉同步 ``` ### C. lobe-chat-pro 主要文件位置 ``` src/store/painting/ # 绘图状态管理 src/services/painting/ # 绘图服务 src/types/painting/ # 类型定义 src/app/[variants]/(main)/painting/ # 绘图页面 src/app/[variants]/(main)/image/ # 图片工作区 src/features/Conversation/ # 对话组件 ``` ### D. 移植命令参考 ```bash # 1. 克隆参考仓库 git clone https://github.com/vual/lobe-chat-pro.git ~/lobe-chat-pro-ref # 2. 安装依赖 pnpm add zustand@5.0.4 immer@^10.1.3 react-rnd@^10.5.2 \ react-virtuoso@^4.14.1 react-layout-kit@^2.0.0 \ framer-motion@^12.23.24 antd@^5.27.4 antd-style@^3.7.1 # 3. 创建目录结构 mkdir -p store/painting mkdir -p services/painting mkdir -p types/painting mkdir -p components/canvas mkdir -p app/canvas/[id] mkdir -p app/api/canvas/generate # 4. 复制文件(示例) cp ~/lobe-chat-pro-ref/src/store/painting/* store/painting/ cp ~/lobe-chat-pro-ref/src/services/painting/* services/painting/ cp ~/lobe-chat-pro-ref/src/types/painting/* types/painting/ ```