Files
Genarrative/docs/technical/【前端架构】图片画布编辑器MVP接入方案-2026-06-11.md
T

56 KiB
Raw Blame History

图片画布编辑器 Lovart 化与持久化接入方案

背景

网站需要新增一个面向图片素材的独立 /editor/canvas 画布入口。第一阶段已经提供纯前端画布体验,本轮把它升级为 Lovart 风格的 AI 图片画布:支持更接近专业画布的拖拽、缩放、吸附、工具模式、元数据查看和图片修改结果并排展示,同时补上工程、画布与资源持久化。

V2 边界

  • 主站新增 /editor/canvas 路由,进入独立图片画布编辑器阶段。
  • 主站新增 /project 项目页,从“我的”页项目入口进入,展示当前用户所有图片画布工程;点击项目进入 /editor/canvas?projectid=<projectId>
  • 创作 Tab 顶部提供编辑器入口,入口只负责跳转,不参与玩法创作链路。
  • 编辑器顶部栏采用紧凑高度,项目标题和重命名入口贴近返回项目按钮;右侧复用与主站相同的公共泥点资产入口。顶部总余额优先展示画板按扣费、退回、到账和页面恢复链路刷新的 profileDashboard.walletBalance,充值中心 mudPointBalance 仅用于展开面板的账户明细,不覆盖已刷新的总余额。余额区只展开不限时、每日免费及重置信息,会员周期限时泥点保留在后端 read model 中用于存量兼容和结算但不展示;独立“充值”按钮进入“购买更多泥点”弹窗,“使用详情”进入泥点账单。
  • 编辑器左侧为图片素材栏,可展开 / 收起;移动端优先保持素材栏可折叠。
  • 中央画布支持背景拖拽平移、滚轮缩放、缩放百分比菜单、显示所有元素和固定比例缩放。
  • 画布左下角提供 Lovart 式状态控件:背景色圆点、素材 / 图层入口、小地图开关;小地图显示图层缩略分布和当前视口框,点击小地图执行显示所有元素。
  • 画布 chrome 的边框、hover / 选中态、吸附 / 框选参考线、生成类按钮和通用 active 控件使用陶泥儿暖色主题(以 --platform-accent、陶土橙主按钮和深棕文字为基准),不得回退为黑色或蓝色主题;元素类型自身的识别色可继续保留。
  • 画布中的图片可展示、悬浮显示图片 Resolution 尺寸与边框,点击后在图片上方显示浮动工具栏;浮动工具栏只保留当前可执行的编辑动作,不放调整 / 复制 / 删除 / 查看信息占位按钮。图片右上角素材类型标签、图片信息角标和悬浮尺寸标签在画布缩小时必须按 viewport 反向缩放,保持屏幕可读尺寸;无 assetKind 的素材右上角显示 未知 标签,点击标签弹出独立标签选择菜单并可写回图层 assetKind,不能触发图层选择 / 拖拽事件;图片信息角标使用圆形 i 图标,不使用中括号或花括号样式。图片不再维护独立展示 Size 字段,画布显示宽高统一取 originalWidth/originalHeight(图片信息中的 Resolution)。
  • 默认工具为选择模式;底部工具栏采用 AI 画布工作流工具组:选择、抓手、上传、生成图片、生成视频、生成音乐、生成规范、生成角色形象、生成图标素材、生成 UI 设计图。底部栏不再展示文字工具、形状标注工具和导出工具;上传与生成图片之间、生成音乐与生成规范之间各有一个半图标高度分割线。
  • 鼠标中键拖拽始终平移画布;长按 Space 临时进入抓手模式,松开后恢复原工具。
  • 图片拖拽时显示水平 / 垂直吸附参考线,吸附到其它图层、生成占位框或画板的边缘与中心线;当移动元素接近两个同轴元素形成的等距位置时,支持横向或纵向等距吸附。
  • 生成资源右上角显示元数据按钮,点击打开独立元数据窗口。图片信息页不展示后端组装后的生图 Prompt,也不提供复制 Prompt;只展示该图片生成时用户在面板里提交的输入快照,包括普通生成提示词、规范表单字段、角色设定、图标素材描述、快速编辑提示词、重绘提示词,以及角色规范 / 常规参考图 / 图标规范 / 编辑参考图等参考图卡片,并提供“复制信息”复制当前可见字段。参考图输入快照只保存 refType/refId 行引用,其中 refType="project-resource" 指向 editor_project_resource.resourceIdrefType="asset" 指向 editor_asset.assetId;不得把图片 Data URL、普通 URL 或 objectKey 写入 generationInputs.references。旧数据或上传图片没有输入快照时显示 -,禁止回退展示内部 Prompt。
  • 对生成资源执行重绘时,在右侧创建新的生成结果图层,并自动调整视图显示原图和新图;重绘面板不因提交成功自动关闭,便于连续改提示词。重绘 / 改造输入框只允许从 generationInputs.fields 中恢复用户可见输入快照,例如普通生成提示词、视频描述、音效 prompt、背景音乐 gpt_description_prompt、角色设定、UI 用户输入、图标素材描述、规范表单和宣发素材字段;禁止回退展示资源 prompt / actualPrompt 中的后端拼接 Prompt、固定生成模板或模型默认提示词。没有用户输入快照的旧图层打开改造时保持空输入,等待用户重新填写。
  • 图片生成 / 修改统一经 api-server BFF 接入 VectorEngine。普通生成、生成规范和重绘保留既有 gpt-image-2 路径;图片快速编辑统一打开框选区域 + 单提示词 + 模型选择面板,默认沿用原图模型,不展示参考图或比例 / 尺寸控件;其中生成规范类图片固定 16:92Kgpt-image-2,面板底部用与可编辑面板一致的比例 / 尺寸 / 模型胶囊按钮展示固定参数,但按钮为禁用态,不允许在该面板改比例、尺寸或模型。生成角色形象生成图标素材 支持 nanobanana2gemini-3.1-flash-image-preview)和 gpt-image-2,默认 nanobanana2,并在两类面板之间沿用用户上次选择的模型;两类面板不展示抠图背景色或抠图模型选择;前端用户路径固定提交 screenColor=autosegModel=birefnet,由后端自动决策具体抠图背景色,anime-seg 作为内部保留能力不在用户界面暴露。nanobanana2/v1beta/models/{model}:generateContent,请求体写入 generationConfig.imageConfig.aspectRatio/imageSizegpt-image-2/v1/images/generations/v1/images/edits,请求体按 VectorEngine 文档映射 size。宣发素材三个工作流(游戏首图、详情五图、运营海报)固定使用 gpt-image-2,面板模型胶囊为禁用态,不提供 nanobanana2 入口;前端按 workflow 同时提交 outputSizeaspectRatioimageSize,其中游戏首图为 720x540 / 4:3、详情单图为 720x1280 / 9:16、运营海报为 1280x720 / 16:9;后端收到 kind: "publication-material" 时也强制归一为 gpt-image-2 生成和计费,生成回填图层优先使用生成占位的 originalWidth/originalHeight,即使上游回包尺寸漂移也不得把宣发素材卡片变成随机 1:14:3。纯文本生成走 /api/editor/images/generations,重绘在前端读入当前图层图片 Data URL 后走同一图片生成 BFF,并在原图右侧生成一张新图;普通图层重绘作为 quick-edit 参考图提交,角色图层重绘必须按 kind: "character" 提交,继续套用角色生成器提示词限定、透明 PNG 后处理和角色资产持久化。生成视频/api/editor/videos/generations,前端模型入口仅展示 Seedance 2.0 Fast / Seedance 2.0 / Kling 3.0 / Kling 3.0 Omni,不展示 Veo 入口,默认 Seedance 2.0 Fast;视频参数按当前正式面板支持的比例、时长、清晰度和声音开关提交,且 Seedance Fast 与 Seedance 标准版必须按各自真实模型 ID 独立映射,不得混用。生成结果以视频图层加入画布。纯文本生成入口采用 Lovart 式画布内占位图 + 锚定生成输入框:点击生成图片后以当前视口世界中心为目标,经统一 placement 避让后创建选中的灰色占位框,输入框跟随占位框显示;待生成、生成中和失败后保留的占位图都必须继续支持拖动,生成完成时真实生成图或视频落在最新占位框位置,输入框继续跟随新生成图层;占位图失焦时隐藏高亮边框、左上角生成器名称和右上角原始尺寸,重新聚焦时再显示,且名称 / 尺寸在画布缩小时按 viewport 反向缩放保持屏幕尺寸稳定;点击所有图片 / 视频生成入口并确认请求开始后,必须隐藏对应设置面板,只保留画布内占位图或原图预览,并在预览上显示 Lovart 式生成中遮罩,避免“面板仍占屏”或“预览一起消失”。图片快速编辑和重绘在调用图片 BFF 前必须把当前图层图片源读取为图片 Data URL;视频素材快速编辑走视频生成 BFF,不允许走图片模型;角色动作的 生成动画 仍固定使用 seedance2.0-fast 动作 / 视频模型,角色动作素材的 快速编辑 按当前帧图片走图片编辑。前端不持有 provider 密钥;上游失败或配置缺失时恢复当前生成设置面板展示失败,不创建 mock 成功图。
  • 图片画布抠图分两类:手动去除背景面向用户任意图片,走登录态同源 BFF POST /api/editor/images/background-removals 并转发远端 BiRefNet;编辑器自己生成的标准纯色背景抠图资产在保存源图后统一调用独立 BgFilter 服务 GENARRATIVE_EDITOR_BGFILTER_BASE_URL/remove-background,默认 http://58.87.105.82/bgfilter/remove-background,默认请求超时 180000msBgFilter CPU 推理)。角色形象生成、图标 spritesheet 生成和 UI 设计图素材提取的前端用户路径都固定把 screenColor=auto 注入请求体,但用户可见 generationInputs.fields 不再记录 抠图背景色抠图模型api-server 在组装 prompt 前调用背景决策模块,从 12 个候选色中选择具体 hex,最多重试 3 次,失败后兜底 #CFEFFF。后端仍保留手动 hex 解析能力供内部兼容。最终生图 prompt 和 BgFilter screen_color multipart 字段只接收解析后的具体 hex,不透传 auto。三条 BgFilter 路径还必须固定把默认 segModel=birefnet 传为 seg_model;后端仍保留识别 anime-seg 的内部兼容能力,但前端用户入口不展示也不提交该值。这里的 birefnet 只是 BgFilter 管线内部后端,不等同于手动去背景的独立 BiRefNet 服务。后端在调用 BgFilter 前必须先把带纯色背景 / 绿幕源图写入 OSS;BgFilter 请求失败、返回非成功状态、空图片或非法图片时,以及连续失败达到 GENARRATIVE_EDITOR_BGFILTER_CIRCUIT_FAILURE_THRESHOLD=3 后的 GENARRATIVE_EDITOR_BGFILTER_CIRCUIT_COOLDOWN_SECONDS=300 秒熔断期,api-server 都先调用阿里云通用抠图,只有阿里云失败才用本地 editor_green_screen 按同一 screenColor 兜底去背。角色动作生成的序列帧背景色已与生图统一:前端固定提交 screenColor=auto,后端视觉决策出具体 hex 并把源角色图合成到该背景色后再图生视频;抽帧后逐帧优先阿里云通用抠图,失败降级本地 editor_green_screen(按选定背景色,而非固定 #00FF00)。BiRefNet 手动去背景服务地址为 GENARRATIVE_EDITOR_BACKGROUND_REMOVAL_BASE_URL/remove-background,默认 http://58.87.105.82/remove-backgroundBgFilter 可选访问令牌来自 GENARRATIVE_EDITOR_BGFILTER_TOKEN,未配置时复用 GENARRATIVE_EDITOR_BACKGROUND_REMOVAL_TOKEN,所有令牌都只在服务端注入,前端不持有令牌。api-server 对上游结果做响应字节和图片尺寸上限保护,并先落 OSS / asset object,再返回 imageSrc/objectKey/assetObjectId/taskId;queue 模式下手动去背景进入 SpacetimeDB 外部生成队列,画布任务侧栏只展示服务器任务阶段,生成中才显示耗时,不显示百分比;有项目上下文时前端同时创建去背景生成占位并把 canvasCompletion 交给后端,完成后由后端写入结果图层和最新项目快照。
  • 多产物生成以后端项目快照为唯一画布真相:同一任务的原始产物、抠图 / 透明化结果和拆分结果都要先登记为 editor_project_resource,再通过一次 canvasCompletion 原子写入画布。角色形象、图标 spritesheet 和 UI 素材提取的纯色背景原图不能只留在 OSS;透明后处理结果保持主图层和 generatedLayerId 锚点,原图及其它附属产物从主结果右侧开始错开放置。无项目上下文时不创建项目资源或画布图层。
  • 图片快速编辑面板只保留一个提示词输入框和模型选择,不展示额外参考图或比例 / 尺寸控件;原图 / 原素材作为 /api/editor/images/editssourceImageSrc 直接提交,不作为 referenceImageSrcs。完整图标图集 icon-spritesheet 支持快速编辑,拆分后的单个 icon 不提供该入口,前后端必须使用同一素材类型规则。打开快速编辑时画布必须自动平移缩放,让原素材完整落在可视区上半部分,底部面板固定出现在素材下方且不遮挡内容,竖屏 UI 素材也必须完整展示。快速编辑右侧显示矩形、椭圆、画笔框选工具,但进入时不默认启用;点击工具后显示选中态,再点同一工具取消启用。完成框选后,画布红色细框显示连续序号,提示词可按这些编号填写每个区域怎么改。点击 修改 后仍停留在当前快速编辑面板显示修改中,不创建独立 Quick Edit Generator 画布占位;生成成功后直接用结果覆盖原图图层,失败时保留当前面板并在错误红框中显示具体错误文案。
  • 底部生成类按钮每次点击都必须创建独立的画布生成对象;新建规范、角色形象或图标素材时,只切换当前编辑面板,不得销毁此前尚未生成或已生成后的其它生成对象状态。归档为非当前编辑对象的生成占位仍可拖动、删除和等待异步完成,完成 / 失败回写必须按生成对象 ID 读取最新占位状态,不能使用提交瞬间的旧快照。
  • 画布右上角提供自动隐藏任务侧栏。列表为空且侧栏关闭时只保留图标开关;生成或去背景任务进入时默认打开;用户可手动切换开关状态。
  • 画布底部工具栏 / 面板 Dock 提供“画布 Agent”入口。点击后打开右侧独立 Agent 对话面板;桌面端为右侧窄面板,移动端占满可用宽度。该面板只与右上角任务侧栏互斥;素材 / 图层侧栏允许与 Agent 同时展开,切换左侧栏不得关闭 Agent。Agent 面板不得在当前画布内容下方追加内联内容,也不默认展示大段功能说明文案。
  • 所有会新建画布生成占位的入口必须先创建 draft,再统一经过 ImageCanvasGenerationPlacementModel 计算落点,禁止各入口自行使用当前视口中心裸坐标或原图右侧固定偏移。当前覆盖入口包括 生成图片生成规范生成角色形象生成图标素材生成视频生成UI设计图生成角色动作。placement 模型的避让对象为所有未隐藏画布图层,以及当前 active / inactive generation dialogs 中仍存在的 placeholder;每个避让矩形按 32px 画布世界坐标间距外扩。候选落点以当前视口世界中心为距离目标,优先选择离视口中心最近且不重叠的占位位置;若中心被占用,会按上下左右和环形候选继续寻找。打开生成面板时必须把避让后的 placeholder 写入 openCanvasGenerationDialog(...),并立即调用 centerViewportOnPlacement(...) 居中到新占位中心,保持原 viewport scale 不变;图片快速编辑不属于新建占位入口,提交后覆盖源图。

交互规则

  • 适合视图 的正式语义为“显示画布所有可见元素”,不再回到固定 x/y/scale
  • 右上角缩放控件只展示当前缩放百分比;点击后弹出菜单:放大、缩小、显示画布所有元素、缩放至 50%、缩放至 100%、缩放至 200%。缩放百分比以实际画布 viewport.scale = 0.5 作为显示 100% 的基准,菜单中的 50% / 100% / 200% 分别对应实际 0.25 / 0.5 / 1,工程持久化保存和读取仍使用用户可见缩放语义。
  • 缩放菜单支持 Ctrl/Cmd +Ctrl/Cmd -Shift + 1;快捷键只改变 viewport,不修改工程资源。
  • 右上角提供快捷键入口,点击后打开独立快捷键弹窗;画布不常驻展示说明文案。Windows 快捷键覆盖 Ctrl+Z / Ctrl+Shift+Z 撤销重做、Ctrl+A/C/V/X/D 全选 / 复制 / 粘贴 / 剪切 / 复制一份、Ctrl+0/1/+/- 视图控制、V/H/U/G/Shift+V/M 工具切换、Alt+1/Alt+2/Alt+M 面板切换、Ctrl+] / Ctrl+[ / Ctrl+Shift+] / Ctrl+Shift+[ 层级调整、方向键微移 / Shift+方向键 大步移动、Ctrl+Shift+S 下载画布素材和 F2 重命名项目;快捷键只触发对应画布交互,不绕过既有保存 / 生成 / 上传工作流。
  • 背景色控件只修改编辑器工作区底色,不恢复网格线或棋盘格底纹,也不影响图片本体。
  • 吸附阈值以屏幕像素为准,换算到世界坐标后参与拖拽计算;边缘 / 中心线和等距吸附共用同一阈值。拖拽结束后只保存最终图层或生成占位布局,不保存临时参考线。
  • 项目页封面和画布图片图层必须先渲染项目卡、图层外框、标题、尺寸和操作 chrome;图片换签或解码未完成时,只在图片区域显示轻量加载态,不阻塞外框和文字等低成本信息先出现。
  • 素材量增大时,拖拽吸附热路径不得对所有素材做全量两两配对。边缘 / 中心线吸附保持线性扫描;等距吸附只在跨轴相交且轴向邻近的候选图层之间计算,避免大量远处素材拖慢 pointermove。
  • 画布自动保存使用防抖 + 串行队列:图层拖拽、缩放、资源新增和修改结果创建后延迟保存工程快照;如果上一次 PATCH /api/editor/projects/{projectId} 尚未完成,只保留最新待保存快照,待当前请求结束后再发送下一次保存,避免慢保存请求并发堆积触发发布入口连接限流。手型平移和小地图拖动属于临时 viewport 交互,拖动中只更新画布显示,不触发 serializeCanvasLayout、sessionStorage 项目缓存写入或封面快照上传,pointerup / pointercancel 后再保存最终 viewport。PATCH /api/editor/projects/{projectId} 只返回 { projectId, canvasId, updatedAt } 轻量 ack,不再返回完整 project,前端必须以后续显式读取或生成完成返回的后端快照作为项目真相。
  • 移动端保留同一套状态模型,底部工具栏可横向滚动,侧边栏默认可收起。
  • 项目页卡片默认点击打开工程;hover 项目卡片右下角显示 ... 菜单,菜单承载重命名和删除。选择模式下项目卡片只切换选中态,不进入画布;底部批量工具栏提供全选 / 取消全选、已选数量、批量删除和退出选择模式。

数据与持久化

  • 新增 editor_project 表保存图片画布工程:projectIdownerUserId、标题、创建时间和更新时间;历史 layout 字段暂保留为兼容列,不再作为权威画布数据。
  • 新增 editor_canvas 表保存工程下的画布:canvasIdprojectIdownerUserId、标题、viewport、图层布局 JSON、创建时间和更新时间。当前编辑器使用项目默认画布,后续可扩展为一个 project 下多个 canvas。
  • 新增 editor_asset_folder 表保存账号级素材文件夹:folderIdownerUserId、名称、排序、折叠状态、系统默认标记、创建时间和更新时间。素材文件夹不归属于 project,同一个账号进入任一项目都能看到。
  • 新增 editor_asset 表保存账号级素材:assetIdownerUserIdfolderId、名称、图片读取地址、可选封面 thumbnailSrc、OSS / asset object 引用、图片尺寸、来源类型、prompt、actualPrompt、model、provider、taskId、可选 groupTaskId、可选 groupTaskExpectedAssetCountassetKindgenerationInputsgenerationCostMudPoints、创建时间和更新时间。素材只跟账号走,不跟 project 走;taskId 保留真实生成 / 拆分操作身份,groupTaskId 保存服务端验证后的来源任务,groupTaskExpectedAssetCount 保存该拆分批次完整时应有的素材数;角色、图标、UI 设计图、视频和音频等生成结果的用户可见输入快照随素材保存。
  • 新增 editor_showcase_asseteditor_showcase_asset_likeeditor_showcase_campaign_config 表承接 陶泥儿精选:生成素材默认不公开,用户在素材菜单中提交精选审核后生成独立快照;后台审核通过后先返还 50% 生成成本泥点,但仍需运营手动设置精选分类并开启展示才进入公开精选。公开列表不再读取 editor_project_resource.public_showcase_enabled,而是读取已通过、展示开启且分类合法的精选快照,支持点赞数和首位活动卡。
  • editor_project_resource 表保存工程画布引用过的资源快照:resourceIdprojectIdownerUserId、OSS / asset object 引用、图片尺寸、来源类型、prompt、actualPrompt、model、provider、taskId、sourceResourceId、assetKindgenerationInputs、创建时间和更新时间。上传素材被拖入画布时会复制为 project resource,图层只引用 resourceId;图片、图标和 UI 素材生成 BFF 在请求携带 projectId 时由后端直接创建新 resource,并把 resourceId 随生成响应返回给前端。图片生成请求如果同时携带 canvasCompletion(生成器 dialogId、标题和占位框,或无 dialog 的右侧完成占位),BFF / worker 在生成成功后必须直接读取当前项目布局,优先使用最新 generation-dialog 占位框位置;只有当前布局仍存在对应 generation-dialog 时才插入轻量结果图层、把生成器标记为 idle 并写入 generatedLayerId,沿用后端当前 viewport 保存布局,再返回或刷新最新项目快照;前端只应用该快照刷新显示,不把生成完成态作为本地业务真相,也不在项目加载时根据资源行推断完成态。有项目上下文但后端没有返回项目快照时,前端不得本地补结果图层,只保留当前生成器交互状态等待下一次项目刷新。
  • 项目封面图是画布当前视口栅格化后的静态快照资源,不在项目列表页临时重放 layers + viewport。前端在项目加载后和防抖保存 layout 时生成 320x240 PNG,走私有 OSS / asset object 上传,再创建 editor_project_resource,其中 assetKind="project-cover-snapshot"sourceType="uploaded"/project/creation 最近项目卡只读取最新封面快照资源渲染;没有封面快照时显示普通项目占位,不回退为实时画布组合。
  • 图片、音频、视频和角色动画帧文件本体继续走 OSS / asset object;浏览器读取私有 generated 对象统一经 /api/assets/read-url 换签,签名 URL 可在 session 内复用,但不得作为持久化真相。/api/assets/read-url 属于页面展示层高频后台请求,前端统一在 assetReadUrlService 内做同 key pending 去重、session 缓存和跨组件节流;UI 设计切片、角色动画帧或大量素材恢复时不得绕过该服务并发换签,否则单页可在同一秒内打满发布入口 genarrative_api_rps burst。
  • 登录态上传和生成结果必须先落 OSS / asset object,再向 editor_project_resource / editor_asset 写入轻量 imageSrc: "/<objectKey>"objectKeyassetObjectId;未登录演示态可以在内存里使用 Data URL 预览,但项目、素材库、项目资源和 editor_canvas.layers_json 不得写入 data:image/*data:video/*data:audio/*blob:。旧数据读取时如果已有 objectKeyimageSrc 归一成 /<objectKey>;没有 objectKey 的旧 Data URL 需要走修复上传并回写轻量引用。裁扩在项目上下文中虽然由前端 canvas 本地渲染 PNG,也必须先上传 OSS / asset object 并创建 editor_project_resource,再把带正式 resourceId/objectKey/assetObjectId 的裁扩图层加入画布;不能先把 local-resource-* + Data URL 图层交给项目保存或后续去背景。上传到生成面板参考图槽位的图片必须先创建 editor_project_resource 行;没有当前工程 ID 时才创建账号级 editor_asset 行,随后把对应 resourceIdassetId 写入参考图临时状态,生成请求仍使用临时状态中的图片源或 objectKey
  • 资源表保存资源和素材级元数据;图层位置、层级、分组选中所需 ID 和 groupId 保存在 editor_canvas 的布局 JSON。布局 JSON 是混合数组:普通图层按 layerId/resourceId 保存,生成器占位和生成器对话框按 itemType: "generation-dialog" 保存,不新增单独表。普通图层的新保存不再把 assetKind/generationInputs 写入布局 JSON;刷新时优先从 editor_project_resource 恢复,旧布局中的同名字段只作为兼容兜底。生成器快照必须包含生成器 ID、模式、提示词、参数、参考图、状态、占位框位置和可选 generatedLayerId;角色、图标等纯色抠图生成器的前端用户路径不保存或恢复 screenColor / segModel,同源重绘也不再从 generationInputs.fields 恢复 抠图背景色抠图模型;宣发素材生成器还必须保存并恢复 publicationWorkflowIdpublicationGameInfopublicationReferences,避免刷新后生成卡片字段或参考图丢失。生成器快照中的参考图同样只保存 resourceId/sourceAssetId 行引用和展示所需 label,不保存图片 Data URL、signed URL 或 objectKey;刷新时用 editor_project_resource / editor_asset 行恢复临时生成请求所需图片源。生成成功后仍保存该快照,只是渲染时由 generatedLayerId 锚定到成品图层而不重复显示灰色占位框。generationInputs.references 是用户可见输入快照中的行级索引,只允许保存 { title, label, refType, refId };生成接口所需的图片 Data URL、signed URL 或 objectKey 只存在于提交前的临时参考图状态和请求体字段,不进入资源 / 素材元数据。图层展示尺寸不再作为独立 Size 真相保存,刷新与新建图层均按 ResolutionoriginalWidth/originalHeight)原分辨率显示。图层组第一版是画布内布局语义,不单独建表。
  • 图片类、生成视频和音频结果除作为 editor_project_resource 和画布图层保存外,还要写入账号级 editor_asset 素材库;该写入由生成 BFF 在请求携带 assetFolderId 时完成。角色、图标图集、UI 提取和角色动作等多产物任务把 provider 原始输出及后处理结果分别入库:所有条目沿用 charactericon-spritesheetcharacter-animation 等真实类型,provider 原始输出承载任务模型成本,后处理派生产物阶段成本为 0。后台素材查询以最终产物为父行、每个中间产物为可展开的独立子行,分页只计算父任务;手动重拆图集保留独立 taskId 用于存储隔离和日志排障,通过私有 provenance 从服务端生成账号素材的 source resource、asset object 或 Object Key 取得可信来源任务,并把它写入 groupTaskId,不信任客户端可提交的 resource taskId/assetKind;跨项目复用后仍可通过稳定媒体引用找回来源。没有可信来源的新拆分显式归到自身任务,不走历史资源链回溯。每个手动切片同时写入 groupTaskExpectedAssetCount,全部切片落库后写独立 cohort 完成事实;后台 read model 只让同一根任务的一个已完成拆分批次并入原图集父项,用户后来删除单片不会让批次脱组,部分失败批次和后续重复拆分批次按各自真实任务分页,避免残缺批次抢占根任务、单组无限增长或素材丢失。历史行在项目资源仍存在时兼容回溯,删除项目资源前只固化直接受影响行的真实来源字段,有界展示 ID 不反写数据库。GENARRATIVE_EXTERNAL_GENERATION_MODE=queue 下,画布图片、改图、图标素材、UI 素材提取、角色动作、视频、音效和背景音乐生成都先返回 queueState,前端轮询 /api/runtime/external-generation/jobs/{jobId} 到完成后重新读取项目快照;inline 或无项目上下文时才使用响应中的 resource / asset 快照做本地落画布兜底,不再把同一生成结果二次调用素材创建接口。生成请求失败、inline 完成或 queue 任务终态完成 / 失败后,右上角泥点 chip 必须通过 /profile/dashboard 回读余额,不做本地乐观扣减。生成视频会单独抽取首帧封面写入 thumbnailSrc,素材栏和拖回画布时沿用该封面作为 poster。
  • 生成面板不展示资源名称输入,默认使用原有自动编号;提示词输入保持统一可见边框。内部命名契约仍使用可选 assetLabel,最大 80 字符并在提交时 trim;历史状态或内部调用携带非空名称时,同一个名称必须贯穿 assetLabelcanvasCompletion.title、项目资源、账号素材和本地兜底图层,刷新后不得退回模板名。图标图集与角色动作请求同样兼容该字段,中间原图使用主名称加固定后缀,拆分素材继续按素材描述命名。
  • 画布 Agent 会话按“SpacetimeDB 元数据 + OSS 消息正文”存储:editor_agent_conversation 只保存 conversationId/projectId/ownerUserId/title/messagesObjectKey/deleted/createdAt/updatedAt 等会话元数据;消息正文整体保存为私有 OSS JSON 文档 editor-agent/{conversationId}.json。消息文档单对象上限为 2 MiB,同一会话的消息追加和工具结果回填由 api-server 按 conversationId 串行化,避免“读 OSS → 改消息 → 写 OSS”并发覆盖。前端只通过 api-server BFF 读取和发送会话,不直接读写 SpacetimeDB,也不直接读写 OSS。
  • Agent 消息附件只允许引用当前工程画布资源或账号素材库图片,来源类型为 canvas_resource / library_asset,最多 9 张。附件请求可携带展示用 imageSrc/thumbnailSrc/objectKey/width/height/label,但持久化真相仍以后端校验后的 resource / asset 行和 OSS 对象为准;不得把 Data URL、signed URL 或 blob URL 当作会话长期事实。
  • 前端不直接订阅 SpacetimeDB,统一通过 api-server 的 /api/editor/projects* BFF 读写。
  • 工程刷新恢复可先应用 session 级轻量项目快照缓存,让画布和素材 chrome 尽快显示;缓存快照必须排除 data:* / blob: 内联媒体,且在后端项目快照返回前不得触发自动保存。后端快照回来后覆盖本地缓存显示并恢复正常保存队列。
  • 未登录用户可以使用本地演示态,但不触发工程自动保存;真实图片生成 / 修改需要登录。编辑器 API 请求允许使用 refresh cookie 静默补 access token,但 401 / 403 只在编辑器局部提示登录,不清空整站登录态,也不把后端 requestId 直接作为生图弹窗主文案。

后端接口

  • GET /api/editor/projects/recent:读取当前用户最近编辑的图片画布工程,没有则返回 project: null
  • GET /api/editor/projects:读取当前用户所有图片画布工程,按更新时间倒序返回。
  • POST /api/editor/projects:创建图片画布工程。
  • GET /api/editor/projects/{projectId}:读取指定工程及资源列表。
  • PATCH /api/editor/projects/{projectId}:保存 viewport 与图层布局快照;响应只包含 { projectId, canvasId, updatedAt } ack,不返回完整工程快照。
  • PATCH /api/editor/projects/{projectId}/metadata:重命名指定工程。
  • DELETE /api/editor/projects/{projectId}:删除指定工程,并级联删除默认画布和资源元数据。
  • POST /api/editor/projects/{projectId}/resources:创建画布资源记录,接收上传资源或真实生成资源元数据。
  • GET /api/editor/projects/{projectId}/agent-conversations:读取当前工程的画布 Agent 会话列表,按更新时间倒序返回会话摘要。
  • POST /api/editor/projects/{projectId}/agent-conversations:在当前工程下创建画布 Agent 会话;可选传入标题,默认标题为“新对话”。
  • GET /api/editor/agent-conversations/{conversationId}:读取指定画布 Agent 会话详情,返回会话摘要和 OSS 消息正文中的消息列表。
  • DELETE /api/editor/agent-conversations/{conversationId}:软删除指定画布 Agent 会话,并返回删除后的会话摘要。
  • POST /api/editor/agent-conversations/{conversationId}/messages:发送画布 Agent 消息并返回普通 JSON EditorAgentMessageResponse。请求体包含 clientMessageIdtext 和可选 attachments;文本与附件不可同时为空,同一会话重复 clientMessageId 必须幂等返回或拒绝重复追加。响应包含权威会话摘要、deltaMessages 和可选 errorMessage。LLM / 规划失败写入 role=system、正文以 ERROR 开头的 OSS 消息并放入 deltaMessages,不再重复设置 errorMessage;前端隐藏前缀后显示红色错误气泡。工具失败继续保存工具状态和错误信息。
  • GET /api/editor/assets/library:读取当前账号的素材文件夹和素材。首次读取时自动创建“项目素材”默认文件夹。
  • POST /api/editor/assets/folders:新建素材文件夹。
  • PATCH /api/editor/assets/folders/{folderId}:重命名、折叠 / 展开素材文件夹。
  • DELETE /api/editor/assets/folders/{folderId}:删除素材文件夹;系统默认文件夹不能删除,普通文件夹删除时素材移入默认文件夹。
  • POST /api/editor/assets:批量或单个创建账号级素材,登录态上传必须写入 OSS / asset object 引用和 /<objectKey> 轻量路径,不允许把 Data URL / signed URL 写入素材库。
  • PATCH /api/editor/assets/{assetId}:重命名素材或移动素材到文件夹。
  • DELETE /api/editor/assets/{assetId}:删除素材。已放入画布的 project resource 不被级联删除,避免旧画布丢图。
  • POST /api/editor/images/generations:按提示词调用 VectorEngine 生成图片;普通图片的 provider 回图先留在内存,尺寸变换成功后只上传变换结果,变换失败则只上传 provider 原图,主结果只写一次 OSS 且不额外创建“原始输出”。角色生成可携带 modelscreenColorsegModelaspectRatioimageSizereferenceImageSrcs,生成成功后 api-server 先保存带纯色背景源图,再调用 BgFilter 并传入 screen_color=<screenColor>seg_model=<segModel> 生成透明 PNG。宣发素材携带 kind: "publication-material" 时固定归一为 gpt-image-2,不支持 nanobanana2nanobanana2 参考图作为 inline_data 进入 generateContentgpt-image-2 参考图进入 editsnanobanana2512 / 1024 / 2K 是标量清晰度档位,后端保留 provider 输出几何尺寸,不按 宽x高 解析。普通重绘继续走该接口并把当前图层图片作为参考图;图片快速编辑不走该接口。请求可携带 projectIdassetFolderIdassetKindgenerationInputssourceResourceId,后端生成成功后创建 project resource / 账号素材并在响应中返回 resource / asset 快照。
  • POST /api/editor/images/background-removals:接收当前图片源,校验登录态后由 api-server 解析为图片文件并转发到 BiRefNet 去背景服务;请求可携带 projectIdtargetLayerIdassetFolderIdassetLabelsourceResourceIdcanvasCompletion,有 canvasCompletion 时完成后按生成占位写入结果图层,否则沿用旧的目标图层替换路径;响应返回 imageSrcobjectKeyassetObjectIdwidthheighttaskIdelapsedMsprovider 和可选 project 快照。服务地址由 GENARRATIVE_EDITOR_BACKGROUND_REMOVAL_BASE_URL 配置,令牌只在服务端通过 GENARRATIVE_EDITOR_BACKGROUND_REMOVAL_TOKEN 注入。
  • POST /api/editor/icon-spritesheets/generations:按图标规范图和素材描述数组生成 spritesheet,生成成功后 api-server 先保存带纯色背景 spritesheet 源图,再调用 BgFilter 生成透明 spritesheet。请求支持 modelscreenColorsegModelaspectRatioimageSizepriceMudPointsprojectIdassetFolderIdgenerationInputspriceMudPoints 必须来自编辑器生成计费配置中对应生图模型的尺寸档位(如 nanobanana20.5K / 1K / 2Kgpt-image-21K / 2K),后端用 editor_generation_config 校验后才调用上游;nanobanana2 走原生 generateContent 并写入 generationConfig.imageConfig.aspectRatio/imageSize0.5K"512"gpt-image-2/v1/images/edits。后端保存透明 spritesheet project resource / 账号素材,并随响应返回对应快照。
  • POST /api/editor/ui-designs/assets/extractions:前端把红色框选轮廓绘入本地临时图后,先将该图上传 OSS 并确认 asset object,再以返回的 objectKey 作为参考图入队;Data URL / Blob URL 只允许停留在上传前的浏览器临时态。接口固定 gpt-image-2 和自动决策纯色背景素材提取提示词生成素材 spritesheet,生成成功后 api-server 先保存带纯色背景 spritesheet 源图,再调用 BgFilter 生成透明 spritesheet,并按连通域自动拆分为 素材 1..N,返回结构复用图标 spritesheet 响应。请求必须携带 screenColorsegModelaspectRatio: "1:1"imageSize: "1K" | "2K"priceMudPoints;框选数量不超过 6 个时前端按 1:1·1K 与 gpt-image-2 1K 价格提交,超过 6 个时按 1:1·2K 与 2K 价格提交。后端必须在调用上游前校验比例、尺寸和泥点价格,只允许 1:1 / 1K / 2K。请求可携带 projectIdassetFolderIdgenerationInputsspritesheetLabel,后端保存 spritesheet / 拆分素材并返回对应 resource / asset 快照;前端必须把 spritesheet 原图与拆分素材都加入画布。
  • POST /api/editor/images/edits:按提示词和当前图片的已登记 objectKey / resourceId 调用 VectorEngine edits,返回新的生成图片元数据;图片快速编辑当前只提交 sourceImageSrc,不提交隐藏的 referenceImageSrcs。画布快速编辑必须把源图精确 originalWidth x originalHeight 作为业务目标 size 提交,不能重新映射为近似比例或 1K / 2K 预设;api-server 在 VectorEngine provider 边界把目标尺寸和所有 multipart 参考图临时补齐到 16 的倍数,回图后在内存恢复业务目标尺寸,成功时只上传恢复结果,失败时只上传 provider 原图。无论是否发生尺寸恢复都只创建一个 project resource / 账号素材,不显示重复“原始输出”。16 对齐尺寸不得泄漏到正常完成的最终响应、资源或图层 Resolution;变换失败降级时以实际 provider 原图尺寸为准。本地红框标记图必须先上传再提交 objectKey;请求携带 project / asset 上下文时由后端创建新 resource / asset,前端只消费响应快照。
  • POST /api/editor/videos/generations:按视频描述、模型、比例、时长、分辨率、模式、声音、默认联网搜索标记和泥点价格生成视频。前端可选模型为 seedance2.0-fastseedance2.0kling3.0kling3.0-omni,默认 seedance2.0-fast;后端必须将 seedance2.0-fast 映射到 doubao-seedance-2-0-fast-260128,将 seedance2.0 映射到 doubao-seedance-2-0-260128,两者不得混用。后端允许 6 类比例、4 到 15 秒整数、480p / 720p / 1080p,并拒绝 seedance2.0-fast + 1080psound=on/off 映射 Ark generate_audio=true/false。后端复用 Ark / VectorEngine content generation task 轮询链路,下载最终视频并持久化到 OSS;请求携带 projectId / assetFolderId 时同步创建 project resource / 账号素材并返回 project / asset 快照,基础响应返回 videoSrc、尺寸、prompt、model、provider、taskId、durationSeconds、resolution 和 priceMudPoints
  • POST /api/editor/audios/sound-effects/generationsPOST /api/editor/audios/background-music/generations:按音效 / 背景音乐参数生成音频并持久化到 OSS;请求携带 projectId / assetFolderId 时同步创建 project resource / 账号素材并返回 project / resource / asset 快照,基础响应返回 audioSrc、prompt、model、provider、taskId、duration、歌词和 priceMudPoints

所有写接口都必须校验 Bearer 登录态和 owner;接口只返回当前用户有权读取的工程与资源。

实现约束

  • 前端只维护表现、交互和临时 UI 状态,工程真相以后端 project/resource 快照为准。
  • 示例素材可继续复用 public/creation-type-references/ 下的站内图片;用户上传和后续生成资源必须通过资源记录表达。
  • 不把 hover、dragging、临时吸附线、Space 临时抓手等瞬时 UI 状态写入后端。
  • 不在 UI 中加入大段功能说明,编辑器界面只展示必要的工具、素材和状态信息。
  • 画布 Agent 前端分层固定为:editorAgentClient.ts 负责普通 JSON BFF 请求、鉴权和错误映射;useEditorAgentConversation.ts 负责会话列表、当前会话、消息请求等待态、工具任务状态和客户端取消等待;EditorAgentConversationPanelView.tsx 只负责右侧面板展示与交互。画布 Agent 不新增私有 SSE parser。
  • 不复用或改写 CreativeImageInputPanel 的单图资产编辑语义;/editor/canvas 是独立图片画布工程的画布入口。

验收用例

  • 缩放百分比按钮能打开 Lovart 风格菜单,菜单项能放大、缩小、显示所有元素和缩放到固定比例。
  • 显示画布所有元素 按可见图层外接矩形计算 viewport。
  • 左下角小地图可展示当前图层分布和视口范围,开关按钮可隐藏 / 恢复小地图,背景色菜单可切换白色、浅灰、暖灰和冷蓝工作区底色。
  • 默认选择模式;底部工具栏能切换工具;中键拖拽和 Space 临时抓手都能平移画布。
  • 拖拽图片或生成占位框接近其它图片 / 生成占位框边缘、中心或等距分布位置时显示吸附线,并保存吸附后的最终布局。
  • 生成图片点击后显示画布内 Image Generator 占位框和跟随占位框的生成输入框,生成失败保留占位和输入状态,生成成功后在占位位置创建真实图层,并让输入框继续跟随该生成图。
  • 生成中的占位图聚焦后支持键盘 Delete / Backspace 删除,不新增可见删除按钮;删除后对应异步回写必须按生成器 ID 判空并丢弃,不能把已删除素材重新落回画布。音乐 / 音频生成占位和已生成音频图层同样必须支持键盘删除。
  • 画布常用快捷键必须与右上角快捷键弹窗一致;新增快捷键时应同步更新 ImageCanvasShortcutModel、快捷键 hook 单测和本方案。输入框、文本域和 contenteditable 聚焦时不得触发画布编辑快捷键。
  • 生成器快照刷新后必须恢复;待生成、生成中、失败和已生成后跟随成品图层的生成器都不能因为刷新丢失输入、参数、参考图或占位框位置。宣发素材生成器刷新后必须继续显示正确的卡片类型、游戏名、分类、描述和已绑定参考图。
  • 画布多选语义必须同时覆盖普通图层和仍显示占位框的生成器对象:Shift 点选或框选可把生成器加入当前选择;拖动任一已选图层或生成器时,所有已选普通图层和生成器占位框同步移动;删除 / Backspace / Delete 作用于完整选择集合,移除所有已选图层和生成器对象。生成器对象在选择集合中使用稳定 generation-dialog:<id> 目标 ID,不把生成器伪装成普通图层,也不新增后端表。
  • 生成类入口打开画布内面板时,底部 AI 工具栏必须保持可见;生成规范、角色 / 图标规范来源、角色常规参考图来源这类轻量菜单通过页面级 fixed portal 渲染,不能留在底部工具栏或参考图横向滚动容器内部,避免被局部 overflow 裁切。角色规范和常规参考图来源菜单必须向上弹出;常规参考图点击后先选择“从画布中选择”或“上传图片”,从画布取图时只绑定参考图,不触发普通画布图层选中、聚焦、面板隐藏或拖拽逻辑,绑定后退出画布选择状态。所有生成面板参考图槽位统一为方形图标组件;角色规范槽位只显示规范 logo 和 角色规范 四字,绑定来源标题只保留给可访问名称、悬浮 title 和图片信息。已有参考图槽位只有在 hover / focus 时显示右上角 ×,点击后只解绑对应参考图。角色形象生成面板每次成功绑定角色规范后,在当前编辑器生命周期内缓存为上一张角色规范;再次新建角色形象时自动带入该缓存。图标素材和 UI 设计图面板每次成功绑定图标规范后,同样缓存为上一张图标规范;再次新建需要图标规范的素材时自动带入该缓存。生成规范菜单里的图标规范对象自身只把首行参考图作为可选参考,不要求必须先绑定图标规范。
  • 生成规范类图片面板底部必须以禁用态参数按钮显示 16:9·2Kgpt-image-2,视觉对齐可编辑面板参数控件,提交到 /api/editor/images/generations 时也固定携带这些参数。
  • 快速编辑面板底部只显示模型选择和 修改 按钮;打开时视口聚焦必须预留底部面板空间,面板位于素材下方,不得遮挡原素材,且素材在当前屏幕内完整可见。快速编辑请求只把原图或红框序号标注图作为 sourceImageSrc 直接提交,信息面板输入快照只展示用户填写的快速编辑提示词。
  • 点击生成、生成规范、生成角色形象或生成图标素材后创建的占位图可继续保留;点击画布空白区域让当前图片或占位图失焦时,关闭当前生成面板并移除图片选中样式,但不删除占位图本身。
  • 生成资源显示元数据按钮,元数据窗口展示来源、生成输入快照、model、task、Resolution 和 OSS 引用;生成输入快照只包含用户面板输入和参考图行引用,不包含后端拼接 Prompt,不再展示独立 Size 字段,也不渲染参考图 Data URL 缩略图。
  • 点击底部 Dock 的“画布 Agent”后,右侧独立 Agent 面板打开,任务侧栏被收起;素材 / 图层侧栏保持当前状态并可继续切换。再次点击或点击面板关闭按钮后收起 Agent;打开任务侧栏时 Agent 面板同步关闭。
  • Agent 面板能读取当前工程会话列表;无历史会话时发送第一条消息会先创建“新对话”。支持新建会话、切换会话和删除当前会话;删除必须通过独立确认弹窗完成,不能在面板下方追加确认内容。
  • Agent 输入支持文本消息、附件消息和纯附件消息;附件选择弹窗可在“画布 / 素材库”之间切换,只展示图片类资源,最多选择 9 张。
  • 发送消息后,面板先展示本地用户消息和请求等待态,再应用普通 JSON 响应中的 deltaMessages;客户端取消等待只终止本次 transport 等待,不把已经确认入队的外部生成任务改成停止态。
  • Agent 工具任务完成并懒回填后,消息内缩略图只作纯预览,不显示名称也不点击聚焦图层;前端同时重新读取工程快照和素材库。对话入口触发生成时不创建“即将生成”画布占位,生成完成后由后端 canvasCompletion 落新图层。规划或工具失败时消息内必须保留可回读的失败状态和错误气泡,不能只弹一次性 toast 或返回瞬时 errorMessage
  • 画布 Agent 会话刷新后能从后端恢复会话标题、消息、附件和生成记录;前端不得根据本地临时状态伪造会话持久化结果。
  • 图片选中后的浮动工具栏按钮顺序固定为:快速编辑、分割线、裁扩按钮、去除背景按钮、UI设计图专属提取素材、角色图专属生成动画、分割线、重绘、下载按钮。裁扩通过画布边界拖拉完成,不再展示四边数值输入;默认自由比例,选择固定比例后拖拉边界保持对应比例,完成后在原素材旁边新增裁扩结果图层,扩展区域透明填充。去除背景调用同源 BFF POST /api/editor/images/background-removals,由 api-server 代理远端 BiRefNet 服务并持久化结果;有项目上下文时先在画布创建关闭面板的去背景生成占位,完成后由后端通过 canvasCompletion 把新 project resource 写入该占位并返回快照,无占位上下文时才用新的 project resource 引用替换当前图层。画布任务侧栏按“排队/生成中”和“已完成”分页,生成中排在排队前,生成中耗时从任务开始时间戳实时计算,排队中不计时;进行中任务只显示阶段文本和已用时,不显示百分比;完成态生成任务副标题显示用户提示词并单行截断;点击任务只聚焦对应画布内容,不激活生成面板或改变任务顺序,聚焦时必须预留图片上方工具栏、底部工具栏和可见生成对话框空间。UI设计图的提取素材必须先进入红框素材框选状态,默认启用矩形框选,右侧框选工具与快速编辑统一且可再次点击取消启用态,当前启用工具按钮必须保持高亮。素材提取面板必须在素材下方,使用与生成新素材一致的面板宽度和底部模型 / 按钮样式,提示语显示 使用框选工具框选你希望从画面中提取的素材,并展示按原图坐标准确裁剪的框选区域截图预览、固定模型 gpt-image-2、左下角计划规格 1:1·1K/2K提取 · N泥点 按钮,不显示额外取消按钮;点击素材和面板以外的画布区域即退出 UI 素材提取。至少框选一个区域后才可提交,前端把红色轮廓绘入原图后固定走 gpt-image-2 和自动决策纯色背景素材提取提示词;生成的透明 spritesheet 原图和拆分后的独立素材都作为画布图层保留。
  • 重绘生成资源后,右侧出现新生成结果图层,并自动 fit 原图 + 新图,且重绘面板保持打开。
  • 快速编辑 / 重绘站内 public 示例图、历史 generated 图或 OSS generated 图时,优先复用当前图层已有 objectKey / resourceId / sourceAssetId;只有尚未登记的浏览器本地图片才先上传并取得 objectKey。前端不得再把正式对象下载成 data:image/*;base64,... 后提交,也不得把 Data URL / Blob URL 写入外部生成持久任务 JSON;后端收到引用后统一做 owner 归属校验并签名读取。
  • 快速编辑不保留额外参考图入口;点击修改时只把原图或红框序号标注图作为 /api/editor/images/editssourceImageSrc 提交给后端。
  • 素材文件夹可以新建、折叠、重命名和删除;删除普通文件夹后,其素材移动到“项目素材”。普通上传默认落入“上传素材”文件夹;素材库缺少该文件夹时,前端在首次普通上传前创建一次并复用,拖到指定文件夹或点击指定文件夹上传时仍进入目标文件夹。
  • 上传按钮和拖拽上传都支持多文件;底部工具栏的上传入口选择文件后直接进入“上传素材”并在当前画布视口中心创建画布图层,素材栏文件夹内的上传入口只写入对应素材文件夹、不自动入画布;拖到文件夹或该文件夹内素材时进入目标文件夹;拖到画布时进入“上传素材”并在投放点创建画布图层。上传图片必须在创建占位素材、画布图层和账号级素材记录前先读取原图 Resolution,图层宽高、originalWidth/originalHeight 和素材库 width/height 都使用图片本身尺寸;上传视频同样在创建素材和图层前读取视频 metadata 宽高,保证单层下载或 ZIP 导出的真实视频文件重新导入后仍按文件自身尺寸入画布;仅在无法解析尺寸时才使用对应媒体兜底尺寸。
  • 音频 / 视频素材卡和画布媒体图层必须提供稳定的非文字视觉预览:优先使用 thumbnailSrc / 视频 poster,没有真实首帧或音频封面时使用由媒体类型、素材名和地址派生的确定性视觉底图。视频图层使用原生 <video controls preload="metadata" playsInline> 播放,外层图层仍承接选择和拖拽语义;音频图层播放前继续通过 /api/assets/read-url 换签。画布素材导出按 mediaType 保留真实媒体格式:图片进入 images/,音频 / 视频进入 media/,文件扩展名从响应 MIME、objectKey 或源 URL 推断,不得把音频 / 视频导出成 PNG。
  • 画布素材 ZIP 的 metadata.json 只保存前端信息弹窗和导出文件列表可见的展示快照:项目标题、导出时间、图层标题、文件路径、类型、生成输入、模型显示名、Task 短 ID、Object 显示值、Resolution / 时长和导出错误。导出的生成输入只保留用户实际填写或选择的内容;系统默认兜底提示词、固定工作流提示词、内置图标描述、UI 提取素材固定提示词等内置提示词即使存在于历史 generationInputs,也不得写入导出元数据。不得把 projectIdlayerIdresourceIdsourceAssetIdsourceResourceId、原始 prompt / actualPrompt / provider 或画布坐标、锁定、隐藏等布局状态写入导出元数据;Object 字段仅沿用信息弹窗当前可见值。
  • 生成角色动作 的完成结果按序列帧素材处理:图层主 src 使用 frames[0].imageSrcmediaType 固定为 image-sequenceassetKind 固定为 character-animation,完整帧列表写入 imageSequenceFramespreviewVideoPath 只保留为上游预览视频来源,不作为画布主媒体。下载和 ZIP 导出必须因此得到序列帧 ZIP / frames 目录,不能回退为预览视频或首帧 PNG;后端抽帧后先保存带绿幕帧源图,再走绿幕透明化后处理并落盘透明帧素材。
  • 素材面板支持按素材名、文件夹名、生成信息、模型、任务和媒体类型搜索,并支持选择模式框选,一次选中多个素材,并可批量移动或删除上传素材。
  • 图层面板支持按图层名、生成信息、模型、任务和媒体类型搜索;支持选择多个图层后创建图层组,组名和 groupId 随画布布局保存。
  • 小地图支持拖拽视口框,拖动时画布 viewport 跟随移动;pointermove 更新必须通过 requestAnimationFrame 合帧,结束拖拽时 flush 最后一帧,避免高频 pointermove 直接压垮 React 渲染和项目持久化链路。
  • 鼠标滚轮默认垂直滚动画布视口;按住 Ctrl / Cmd 滚轮才缩放画布,并阻止浏览器页面缩放。缩放比例显示保持现有换算口径,最低可缩小到 5%
  • 工程刷新后能从后端恢复资源、图层布局和 viewport。
  • “我的”页项目入口能进入 /project;项目页能列出工程、重命名 / 删除单个工程、批量选择和批量删除;点击工程后进入 /editor/canvas?projectid=<projectId> 并按 query 加载该工程。

后续扩展点

  • 接入图片生成 / 修改计费、队列进度状态、OSS 落盘和更完整失败审计。
  • 资产库接入:素材栏从用户资产、历史生成图或上传结果读取。
  • 图层模型:引入稳定 layer id、z-index、锁定、隐藏和多选。
  • 图像编辑:继续扩展更精细的局部修改、蒙版、智能抠图与导出能力。