电商主图 / 详情图 — 风格改造实现拆分与接口草案¶
需求定稿:Plan「主图详情风格需求 v2」 文档定位:实现蓝图(Admin / Backend / Canvas)。现行代码以仓库为准;本文描述增量改造。 范围:
/main-image、/detail-image同步;复用main_image/detail_image任务类型;不改/hot-replicate。
一、目标摘要¶
| 维度 | 现网 | 目标 |
|---|---|---|
| 选型 | 品类 → 小类 → 面料 → 材质 | 品类 → 风格 |
| 匹配 | 子类 × 材质 | 品类 × 风格 |
| 页内模式 | 无 | 主图:一键 / 复刻主图;详情:一键 / 复刻详情图 |
| 自定义提示词 | 无 | 产品、材质(预览即拦)、其他可选 |
| 任务类型 | main_image / detail_image |
复用,扩展 params |
二、数据模型¶
2.1 新增:模板风格(对齐材质 CRUD + HotStyle 叶子形态)¶
父级为 品类(非小类)。CRUD 字段对齐 FabricMaterial;图片挂载对齐 HotStyle → template_images。
-- Alembic 迁移(PostgreSQL)
CREATE TABLE product_styles (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
product_category_id UUID NOT NULL REFERENCES product_categories(id) ON DELETE CASCADE,
name VARCHAR(100) NOT NULL,
slug VARCHAR(100) NOT NULL,
description TEXT NULL,
prompt_desc TEXT NULL, -- 可选;C 端自定义「材质」槽优先于本字段
thumbnail_url VARCHAR(500) NULL,
sort_order SMALLINT NOT NULL DEFAULT 0,
is_active BOOLEAN NOT NULL DEFAULT true,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
deleted_at TIMESTAMPTZ NULL,
CONSTRAINT uk_product_styles_category_slug UNIQUE (product_category_id, slug)
);
CREATE INDEX idx_product_styles_category ON product_styles(product_category_id);
| 对齐 | 说明 |
|---|---|
| 材质 CRUD | name / slug / sort_order / status(is_active) / prompt_desc / soft delete |
| HotStyle 图 | 风格下模板图存 template_images,template_type 扩展枚举值 style(或主图/详情仍用 main/detail 挂在模板实体上,见下) |
2.2 模板匹配键改造¶
main_image_templates / detail_image_templates:
| 字段 | 动作 |
|---|---|
product_sub_type_ids |
弃用(保留列可读旧数据;匹配逻辑不再使用) |
fabric_material_ids |
弃用(同上) |
product_category_ids |
新增 JSONB list[str] |
style_ids |
新增 JSONB list[str] |
匹配规则(替换 ImageTemplateMixin._match_image_template):
str(product_category_id) ∈ product_category_ids
AND str(style_id) ∈ style_ids
一风格多套:同一品类×风格可对应多条 main_image_templates / detail_image_templates(无独立「套」表)。
match 仍返回首条(兼容旧调用);C 端改走 list。
| 能力 | 说明 |
|---|---|
| 列表 | GET /api/user/catalog/image-templates?template_type=&product_category_id=&style_id= → 摘要(id / name / thumbnail_url / image_count) |
| 封面 | 摘要 thumbnail_url:Admin 指定优先,否则首图;清空指定封面即回退首图 |
| Word | 可选 image_template_id 写入指定套;create_new_template=true 强制新建套;默认仍追加到首条 |
2.3 WordSession 作用域¶
word_sessions:
| 现字段 | 目标 |
|---|---|
product_sub_type_id |
改为 product_category_id(或新增列,旧列可空废弃) |
fabric_material_id |
改为 style_id |
template_type 仍为 main | detail(replica 不在本次)。
2.4 历史数据¶
- 以新建风格数据为主,不做自动「材质→风格」映射。
- 旧主图/详情模板在未写入
product_category_ids/style_ids前,C 端 match 返回空;Admin 需重新关联后可用。 - 面料/材质表与虚拟影棚等链路 保留不动。
三、Backend 拆分¶
3.1 模块清单¶
| 层 | 路径(拟) | 职责 |
|---|---|---|
| ORM | db/models/product_style.py |
ProductStyle |
| ORM | db/models/image_template.py |
模板新增 JSONB 键;TemplateImage.template_type 按需扩展 |
| Repo | db/repositories/product_style_repository.py |
list_by_category / CRUD |
| Service | core/services/product_style_service.py |
风格 CRUD(对齐 ProductService 材质方法) |
| Service | core/services/image_template_mixin.py |
match 签名改为 category + style |
| Service | core/services/word_upload_service.py |
session key / ensure template 用 category×style |
| Service | core/services/prompt_snippets_assembler.py |
注入自定义三槽 |
| Service | core/services/user_catalog_service.py |
styles-by-category;match 新参 |
| API Admin | api/admin/product_styles.py |
/api/admin/product-styles |
| API Admin | main_image_templates.py / detail_image_templates.py |
/match query 改参;Create/Update body |
| API Admin | word_upload.py |
form 字段改名 |
| API User | api/user/router.py |
catalog styles + match |
| Schema | schemas/admin/product_style.py、template.py |
Create/Update/Out |
| Migration | alembic_backend/versions/... |
表 + JSONB 列 |
| Tests | tests/unit/... |
match、assembler、catalog |
3.2 Admin API 草案¶
风格 CRUD — /api/admin/product-styles¶
| Method | Path | 说明 |
|---|---|---|
| GET | ?product_category_id= |
列表(对齐材质 ?fabric_type_id=) |
| POST | `` | body 见下 |
| PUT | /{style_id} |
更新 |
| DELETE | /{style_id} |
soft delete |
Create body
{
"product_category_id": "<uuid>",
"name": "轻奢",
"slug": "qing-she",
"description": null,
"prompt_desc": null,
"sort_order": 0,
"is_active": true
}
品类配置页:在现有「详情图产品 / 主图产品」相关页增加「关联风格」多选(或风格全局库 + 品类挂载;首版推荐 风格直接归属品类,与 HotStyle 归属小类对称)。
模板 match / CRUD¶
GET /api/admin/main-image-templates/match
GET /api/admin/detail-image-templates/match
| Query(新) | 必填 |
|---|---|
product_category_id |
是 |
style_id |
是 |
Create/Update:
{
"name": "...",
"product_category_ids": ["<category-uuid>"],
"style_ids": ["<style-uuid>"],
"layout_config_json": null,
"is_active": true
}
图片 CRUD 路径不变:/{template_id}/images。
Word 上传¶
Form / query:
| 旧 | 新 |
|---|---|
product_sub_type_id |
product_category_id |
fabric_material_id |
style_id |
template_type |
不变 main | detail |
上传后 _ensure_image_template 按品类×风格创建或命中模板,再挂 TemplateImage。
3.3 User Catalog API 草案¶
| Method | Path | 说明 |
|---|---|---|
| GET | /api/user/catalog/styles?category_id= |
该品类下启用风格(替代 fabric-materials/{sub_type_id} 在主图/详情场景) |
| GET | /api/user/catalog/image-template/match |
见下 |
| GET | /api/user/catalog/image-template/{id}/images |
不变 |
match query(主图/详情)
| 参数 | 说明 |
|---|---|
template_type |
main | detail |
product_category_id |
必填 |
style_id |
必填 |
(product_sub_type_id / fabric_material_id 对 main/detail 不再接受;replica/hot_style 保持现逻辑。)
3.4 任务 params(复用 task_type)¶
main_image / detail_image 的 params_json:
{
"prompt_mode": "snippets_only",
"template_type": "main",
"mode": "auto",
"product_category_id": "<uuid>",
"style_id": "<uuid>",
"image_template_id": "<uuid>",
"custom_product": "纯棉四件套",
"custom_material": "60支长绒棉",
"custom_other": "偏暖色",
"ai_model_id": "<uuid>",
"aspect_ratio": "3:4",
"resolution": "2k",
"input_images": {
"product": ["obj/..."],
"reference": ["obj/..."]
}
}
| 字段 | 规则 |
|---|---|
mode |
auto(一键)| copy(复刻);缺省 auto |
custom_product / custom_material |
预览与生图均必填(后端 preview/generate 校验) |
custom_other |
可选 |
input_images.reference |
mode=copy 时必填 |
不再提交:product_sub_type_id、fabric_material_id(主图/详情新链路)。
3.5 Prompt 组装(snippets_only)¶
改造 prompt_snippets_assembler.py:
- 对每条 shot/
prompt_snippet文本做替换: - 匹配「产品是…」类片段 → 用
custom_product替换(具体正则与参考站对齐,实现时抽apply_custom_prompt_slots) - 「材质是…」→
custom_material - 若 snippet 中无对应槽,则在片段前部补全
产品是{custom_product}、材质是{custom_material}(保证必填语义落到模型输入)。 custom_other非空 → 追加到最终 prompt 末尾(slot=custom_other)。- 保留现有
user_prompt兼容;主图/详情 C 端改走三槽,不再依赖单一user_prompt。
预览接口:缺 custom_product / custom_material → 400 + 中文 message(与 Canvas 前置校验双保险)。
3.6 复刻模式(改造现有任务)¶
- 不新开 task_type。
- Worker / 生图驱动读取
mode=copy时,将input_images.reference与 product 一并传入模型侧(对齐现 hot-replicate 或多图入参惯例;落点在现有 template driver 的 image slots,扩展referenceslot)。 task_profiles(main_image/detail_image)增加可选 image slotreference。
四、Admin 前端拆分¶
| 区域 | 现文件 | 改造 |
|---|---|---|
| 风格库 | 新建 features/product-management 风格面板(对齐 FabricMaterialPanel) |
品类选中 → 风格列表 CRUD |
| 主图/详情模板页 | MainImageTemplatePage |
保持 子类×面料上传逻辑不变 |
| 风格模板图(新增) | StyleImageTemplatePage |
独立入口:品类 → 风格;同风格多行模板套;Word / Prompt&图;「新建套」;Prompt 图「设为封面 / 恢复默认首图」 |
| Drawer 上传 | StyleManageDrawer(复用 Word/Prompt Tab) |
风格链路传 categoryId + styleId + templateId;面料 Drawer 不改 |
| 匹配工具 | templateMatching.ts |
listImageTemplatesForStyleRow(全量)+ match…(首条);原 subtype×fabric 保留 |
| Prompt 测试 | resolveImageTemplate.ts 等 |
main/detail C 端匹配改新键;表单增加自定义三槽(可选同步) |
| API client | shared/api/admin/product.ts 或新建 productStyle.ts |
风格 CRUD |
| 路由 / nav | image-templates/routes.tsx |
新增「主图风格模板」「详情图风格模板」;风格库挂产品管理 |
不做:删除面料全局库(其他功能仍用)。
五、Canvas 前端拆分¶
5.1 页面结构¶
| 页面 | 模式 chips |
|---|---|
MainImageSidePanel |
一键生成 / 复刻主图 |
DetailImageSidePanel |
一键生成 / 复刻详情图 |
共用(建议抽到 components/image-workspace/ 或各自目录共享模块):
GenerationModeTabsCategoryStyleCascade(替代 ProductTypeCascade 小类 + FabricMaterialCascade)CustomPromptFields(产品、材质、其他)ReferenceUploadZone(仅复刻)- 风格弹窗:扩展
ImageTemplateGalleryModal(进场动画 + 再点预览)
5.2 交互细节¶
选品类 → GET /catalog/styles?category_id=
点风格 → GET /catalog/image-templates(套封面宫格,每行 3 格;仅一套也显示)
点某一套 → 打开分镜画廊 → 「使用此模板」写入 image_template_id
换风格 → 清空已选套,需重选
再点图 → 预览大图
复刻 → 显示参考图上传;校验 reference(与一键同一套选型)
预览 Prompt → 本地校验「请选择模板套」+ custom_product/material → previewTaskPrompt
生图 → 同校验 + mode/reference
5.3 params 构建¶
改造:
校验顺序(预览):品类 → 风格 → 已确认模板套 → custom_product → custom_material →(复刻)参考图。
生图:再加产品图、模型、清晰度等现网规则。
5.4 API client¶
listStyles(categoryId)fetchImageTemplatesByStyle({ templateType, productCategoryId, styleId })matchImageTemplate(...)(兼容保留;C 端主路径改 list)
六、实现分期建议¶
| 阶段 | 内容 | 依赖 |
|---|---|---|
| P0-BE | migration + ProductStyle CRUD + match 改键 + catalog styles | — |
| P0-Admin | 风格面板 + 模板页级联 + Word 上传改参 | P0-BE |
| P0-Canvas | 品类→风格 + 弹窗 + 自定义提示词校验 + params | P0-BE |
| P1 | 页内一键/复刻模式 + reference slot + assembler 三槽替换 | P0 |
| P1-Prompt | 后端 preview/generate 强校验;snippets_only 替换/追加 | P1 |
| P2 | Admin Prompt 测试页同步;种子风格数据;旧 JSONB 清理 | — |
七、验收对照(实现侧)¶
- Admin 可按品类 CRUD 风格;Word/图上传绑定品类×风格。
GET .../match?product_category_id&style_id返回首条模板(兼容);GET .../image-templates?...返回同风格多套摘要。- C 端两页:无小类/面料/材质;点风格 → 选套宫格 → 分镜确认后才能预览/生图。
- 模式与参考图按定稿;任务仍为
main_image/detail_image。 - 预览缺产品/材质提示词被拦;组装结果含替换与「其他」追加。
八、明确不改¶
/hot-replicate、HotStyle 模型(爆款仍挂小类)- 虚拟影棚 / 场景替换选型
- 面料类型/材质全局库(非主图详情入口)
- 参考站 Step1 确认弹窗后再 Step2(另立需求)
九、关键文件触点速查¶
Backend
image_template.py · image_template_mixin.py · word_upload_service.py · user_catalog_service.py · prompt_snippets_assembler.py · main_image_templates.py · detail_image_templates.py · word_upload.py · router.py(user)
Admin
MainImageTemplatePage.tsx · FabricManageDrawer.tsx · FabricWordUploadTab.tsx · templateMatching.ts · FabricMaterialPanel.tsx(风格面板范本) · product.ts / 新 API
Canvas
MainImageSidePanel.tsx · DetailImageSidePanel.tsx · build*TaskParams.ts · FabricMaterialCascade.tsx(替换) · ImageTemplateGalleryModal.tsx · productCatalogApi.ts