Merge remote-tracking branch 'origin/codex/editor-asset-library' into codex/editor-asset-library

This commit is contained in:
2026-06-21 14:06:52 +08:00
6 changed files with 10 additions and 10 deletions
@@ -35,7 +35,7 @@
## 2026-06-19 图片画布生成按钮价格统一绑定模型定价配置
- 背景:图片画布的生成图片、生成视频、生成规范、生成角色、生成素材、生成 UI、宣发素材、快速编辑、重绘和音频生成入口都在按钮内显示泥点;如果按钮文案、前端提交和后端校验各自写固定数值,后续调整模型价格会出现展示价、提交价和扣费价不一致。
- 决策:所有画板生成按钮价格必须从 `src/components/image-editor/ImageCanvasGenerationModel.ts` 的模型定价配置函数计算;需要提交 `priceMudPoints` 的视频、角色动画、图标素材、音效和背景音乐也使用同一函数。后端用 `server-rs/crates/api-server/src/editor_generation_config.rs` 的同名语义配置重新计算并校验 / 扣费。当前正式模型均已覆盖定价;画板 UI 统一显示 `nanobanana2`,它代表上游真实模型 `gemini-3.1-flash-image-preview`,历史输入或旧布局中的 `nano-banana` 必须归一到真实模型 ID 后再提交和计费。
- 决策:所有画板生成按钮价格必须从 `src/components/image-editor/ImageCanvasGenerationModel.ts` 的模型定价配置函数计算;需要提交 `priceMudPoints` 的视频、角色动画、图标素材、音效和背景音乐也使用同一函数。后端用 `server-rs/crates/api-server/src/editor_generation_config.rs` 的同名语义配置重新计算并校验 / 扣费。当前正式模型均已覆盖定价:图片类 `nanobanana2`真实模型 `gemini-3.1-flash-image-preview`)为 12`gpt-image-2` 为 20;生成规范固定 `gpt-image-2` 为 5;视频按模型和清晰度分档,`seedance2.0-fast` 为 480p 每秒 10 / 720p 每秒 20`seedance2.0` 为 12 / 24`kling3.0` 为 15 / 30`kling3.0-omni` 为 20 / 40Veo 旧布局兼容价仍为 10 / 20。画板 UI 统一显示 `nanobanana2`,历史输入或旧布局中的 `nano-banana` 必须归一到真实模型 ID 后再提交和计费。
- 影响范围:图片画布生成类面板、生成提交模型、编辑器图片 / 视频 / 音频 BFF、`editor_generation_config` 和 Lovart 生成类面板文档。
- 验证方式:运行 `npm run test -- src/components/image-editor/ImageCanvasGenerationModel.test.ts src/components/image-editor/ImageCanvasQuickEditPanelView.test.tsx src/components/image-editor/useImageCanvasGenerationWorkflow.test.tsx`,并执行 `npm run typecheck``npm run check:encoding``git diff --check`
- 关联文档:`docs/【编辑器】生成类面板Lovart统一改造方案-2026-06-17.md`
@@ -2519,7 +2519,7 @@
## 2026-06-17 图片画布底部生成视频接入 Lovart 面板
- 背景:编辑器画板底部工具栏需要新增 `生成视频`,并和现有 Lovart 式生成类面板、泥点展示、占位图和画布结果图层保持一致。
- 决策:`生成视频` 点击后创建独立视频生成占位和极简面板,提交 `POST /api/editor/videos/generations`;首期前端仅开放 `seedance2.0-fast``seedance2.0``kling3.0``kling3.0-omni`,不展示 Veo 模型入口,默认 `seedance2.0-fast`。后端必须严格区分 Seedance 2.0 Fast 与标准版:`seedance2.0-fast` 映射 `doubao-seedance-2-0-fast-260128``seedance2.0` 映射 `doubao-seedance-2-0-260128`,不得混用;固定文字转视频、`16:9`、标准模式和静音。后端复用 Ark / VectorEngine content generation task 轮询链路,下载视频后持久化到 OSS。生成结果在画布中写入 `mediaType="video"``assetKind="video"`,图片信息弹窗按视频显示为 `视频信息` / `视频类型`。生成类泥点价格统一走 `editor_generation_config`,视频和角色动画均为 480p 每秒 10 泥点、720p 每秒 20 泥点
- 决策:`生成视频` 点击后创建独立视频生成占位和极简面板,提交 `POST /api/editor/videos/generations`;首期前端仅开放 `seedance2.0-fast``seedance2.0``kling3.0``kling3.0-omni`,不展示 Veo 模型入口,默认 `seedance2.0-fast`。后端必须严格区分 Seedance 2.0 Fast 与标准版:`seedance2.0-fast` 映射 `doubao-seedance-2-0-fast-260128``seedance2.0` 映射 `doubao-seedance-2-0-260128`,不得混用;固定文字转视频、`16:9`、标准模式和静音。后端复用 Ark / VectorEngine content generation task 轮询链路,下载视频后持久化到 OSS。生成结果在画布中写入 `mediaType="video"``assetKind="video"`,图片信息弹窗按视频显示为 `视频信息` / `视频类型`。生成类泥点价格统一走 `editor_generation_config`:角色动画固定 `seedance2.0-fast`为 480p 每秒 10 / 720p 每秒 20;生成视频按模型分档,`seedance2.0-fast` 为 10 / 20`seedance2.0` 为 12 / 24`kling3.0` 为 15 / 30`kling3.0-omni` 为 20 / 40Veo 旧布局兼容价为 10 / 20
- 影响范围:图片画布生成工作流、前端 editorProjectClient、`shared-contracts``api-server` 视频生成 BFF、编辑器技术方案和生成类面板方案。
- 验证方式:`npm run test -- src/components/image-editor/ImageCanvasEditorView.test.tsx -t "opens the bottom generate video panel"``npm run test -- src/components/image-editor/ImageCanvasMetadataModalView.test.tsx``npm run test -- src/services/image-editor/editorProjectClient.test.ts``cargo test -p shared-contracts editor_video --manifest-path server-rs/Cargo.toml``cargo test -p api-server editor_video --manifest-path server-rs/Cargo.toml``npm run check:encoding``git diff --check`
- 关联文档:`docs/【编辑器】生成类面板Lovart统一改造方案-2026-06-17.md``docs/technical/【前端架构】图片画布编辑器MVP接入方案-2026-06-11.md`
@@ -128,7 +128,7 @@
当前必须显式覆盖的正式模型定价配置:
- 图片类:`gemini-3.1-flash-image-preview`UI 显示与历史别名统一为 `nanobanana2`)为 12 泥点;`gpt-image-2` 为 20 泥点。
- 规范:`gpt-image-2`
- 规范:`gpt-image-2` 为 5 泥点
- 视频:`seedance2.0-fast` 为 10 / 20 泥点每秒;`seedance2.0` 为 12 / 24 泥点每秒;`kling3.0` 为 15 / 30 泥点每秒;`kling3.0-omni` 为 20 / 40 泥点每秒。兼容旧布局回放的 `veo3.1``veo3.1-fast` 也要保留 10 / 20 泥点每秒定价配置,但前端模型菜单不展示。
- 角色动画:`seedance2.0-fast`
- 音效:`audio1.0`
@@ -41,7 +41,7 @@
- `model`:支持 `gemini-3.1-flash-image-preview`UI 显示 `nanobanana2`)和 `gpt-image-2`,默认 `nanobanana2`
- `aspectRatio`:按 `x:y` 展示,选项跟随模型。
- `imageSize`:按 `0.5K / 1K / 2K` 展示,选项跟随模型。
- `priceMudPoints`固定取编辑器生成计费配置中的 `icon` 档位,首版`12`前端只提交配置值,后端用 `editor_generation_config` 校验,不允许素材生成面板自行写死其它价格。
- `priceMudPoints`按当前模型从编辑器生成计费配置计算;`nanobanana2``12``gpt-image-2` `20`前端只提交配置函数计算值,后端用 `editor_generation_config` 校验,不允许素材生成面板自行写死价格。
- 模型与尺寸选项:
- `nanobanana2`:比例 `1:1 / 2:3 / 3:2 / 9:16 / 16:9`;大小 `0.5K / 1K / 2K`。后端走 `/v1beta/models/{model}:generateContent`,把图标规范图作为 `inline_data`,并把 `aspectRatio` / `imageSize` 写入 `generationConfig.imageConfig``0.5K` 按 VectorEngine 文档传 `"512"`
- `gpt-image-2`:比例 `1:1 / 2:3 / 3:2 / 9:16 / 16:9`;大小 `1K / 2K`。后端走 `/v1/images/edits`,把图标规范图作为 multipart `image`,按 `size` 映射:`1K 1:1 -> 1024x1024``1K 2:3/9:16 -> 1024x1536``1K 3:2/16:9 -> 1536x1024``2K 1:1 -> 2048x2048``2K 3:2/16:9 -> 2048x1152`;文档未列出 `2K` 竖版,`2K 2:3/9:16` 后端回落到 `1024x1536`
@@ -77,4 +77,4 @@
- 默认打开图标素材面板时选中 `nanobanana2 / 1:1 / 1K`;模型切换后,角色和图标素材面板之间沿用上次选择的模型。
- 图标素材生成请求必须带 `model``aspectRatio``imageSize``nanobanana2` 请求体必须包含 `generationConfig.imageConfig.aspectRatio/imageSize``gpt-image-2` 请求必须包含文档映射后的 `size`
- 生成成功后画布出现 spritesheet 图集和按描述命名的多个透明图标素材图层,图层之间不重叠。
- 生成图标素材提交体包含 `priceMudPoints: 12`;若前端传入与后端计费配置不一致的值,后端返回 `priceMudPoints` 校验错误,不继续调用上游生成。
- 生成图标素材提交体包含按模型计算的 `priceMudPoints``nanobanana2` 应为 `12``gpt-image-2` 应为 `20`若前端传入与后端计费配置不一致的值,后端返回 `priceMudPoints` 校验错误,不继续调用上游生成。
@@ -2599,7 +2599,7 @@ describe('ImageCanvasEditorView generation integration', () => {
model: 'gpt-image-2',
provider: 'VectorEngine',
taskId: 'ui-extract-task-1',
priceMudPoints: 12,
priceMudPoints: 20,
});
render(<ImageCanvasEditorView />);
@@ -294,7 +294,7 @@ describe('ImageCanvasGenerationLayerModel', () => {
model: 'gpt-image-2',
provider: 'VectorEngine',
taskId: 'task-icons',
priceMudPoints: 12,
priceMudPoints: 20,
},
iconResults: [
{
@@ -935,7 +935,7 @@ describe('editorProjectClient', () => {
taskId: 'video-task-1',
durationSeconds: 5,
resolution: '480p',
priceMudPoints: 50,
priceMudPoints: 100,
});
const result = await generateEditorVideo({
@@ -946,7 +946,7 @@ describe('editorProjectClient', () => {
resolution: '480p',
mode: 'std',
sound: 'off',
priceMudPoints: 50,
priceMudPoints: 100,
});
expect(result.taskId).toBe('video-task-1');
@@ -963,7 +963,7 @@ describe('editorProjectClient', () => {
resolution: '480p',
mode: 'std',
sound: 'off',
priceMudPoints: 50,
priceMudPoints: 100,
}),
}),
'生成视频失败',