fix: 视频项目第二步复用商品库已生成的三视图,不再「缺三视图」(ZWQ#5 续2)

商品库三视图走 standalone Asset、视频项目走项目级 BaseAssetGroup,两套存储不互通 →
商品库生成/采用的商品三视图,进视频项目第二步基础资产读不到、显示「缺三视图」。

修:项目详情 retrieve 时惰性单向同步(幂等,沿用 settle_video_completion 同款自愈模式)——
若商品已有 standalone 三视图(metadata.view=three_view + product_id)但项目商品组尚无采用资产,
就 seed 进项目商品 BaseAssetGroup(candidate+adopted)。已在项目内生成过的不覆盖。
依赖上一commit给商品库三视图打的 view=three_view 标记。

projects 测试:基线已有 4 失败 2 错误(环境 provider 未配),本改动无新增回归。需部署生效。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
zyc
2026-06-30 11:47:07 +08:00
co-authored by Claude Opus 4.8
parent 77759678a7
commit 76d59d06fe
+34 -1
View File
@@ -231,6 +231,36 @@ class ProjectViewSet(TeamScopedViewSetMixin, ModelViewSet):
# 列表用轻量序列化(只给列表/仪表盘/侧栏要的字段);详情/写操作用全量 ProjectSerializer
return ProjectListSerializer if self.action == "list" else ProjectSerializer
def _seed_product_triview_group(self, *, project_id, product_id, team):
"""惰性把商品库已有的商品三视图挂进本项目的商品 BaseAssetGroup(幂等)。
商品库走 standalone Asset、视频项目走项目级 BaseAssetGroup,是两套存储;此处做单向复用同步:
进详情时若商品已有 standalone 三视图(metadata.view=three_view + product_id)但项目商品组尚无采用资产,
就 seed 进去 → 第二步基础资产直接显示该三视图,不再「缺三视图」。已在项目内生成过的不覆盖。"""
if not product_id:
return
groups = [
g for g in BaseAssetGroup.objects.filter(project_id=project_id, kind=BaseAssetGroup.Kind.PRODUCT)
if not (g.metadata or {}).get("triview_of")
]
if any(g.adopted_asset_id for g in groups):
return # 项目内已有商品三视图,不覆盖
tri = (
Asset.objects.filter(
team=team, is_deleted=False,
metadata__product_id=str(product_id), metadata__view="three_view",
)
.order_by("-created_at")
.first()
)
if tri is None:
return
group = groups[0] if groups else BaseAssetGroup.objects.create(
project_id=project_id, kind=BaseAssetGroup.Kind.PRODUCT, metadata={}
)
group.candidate_assets.add(tri)
group.adopted_asset = tri
group.save(update_fields=["adopted_asset", "updated_at"])
def retrieve(self, request, *args, **kwargs):
# 详情加载(=进入流水线页)时自愈视频片段数:历史项目在「采用前增删分镜」未同步,
# 或项目创建固定铺的 4 段从未被收口,会让视频步骤的片段数与故事板/采用版分镜对不上。
@@ -238,10 +268,13 @@ class ProjectViewSet(TeamScopedViewSetMixin, ModelViewSet):
# 用轻量查询判定 + 同步,再交给 super 做重 prefetch 序列化(避免重查询跑两遍)。
proj = (
Project.objects.filter(pk=kwargs.get("pk"), **{self.team_field: self.get_team()})
.only("id", "current_stage", "status")
.only("id", "current_stage", "status", "product_id")
.first()
)
if proj is not None:
# 跨库同步:商品在「商品库」生成过三视图(standalone Asset, view=three_view + product_id),
# 但本项目还没商品三视图组 → seed 进项目商品组,让第二步「基础资产」复用、不再「缺三视图」。
self._seed_product_triview_group(project_id=proj.id, product_id=proj.product_id, team=self.get_team())
if proj.current_stage == ProjectStage.Stage.VIDEO:
adopted_script = proj.script_versions.filter(is_adopted=True).order_by("-created_at").first()
if adopted_script is not None: