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:
@@ -231,6 +231,36 @@ class ProjectViewSet(TeamScopedViewSetMixin, ModelViewSet):
|
|||||||
# 列表用轻量序列化(只给列表/仪表盘/侧栏要的字段);详情/写操作用全量 ProjectSerializer
|
# 列表用轻量序列化(只给列表/仪表盘/侧栏要的字段);详情/写操作用全量 ProjectSerializer
|
||||||
return ProjectListSerializer if self.action == "list" else 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):
|
def retrieve(self, request, *args, **kwargs):
|
||||||
# 详情加载(=进入流水线页)时自愈视频片段数:历史项目在「采用前增删分镜」未同步,
|
# 详情加载(=进入流水线页)时自愈视频片段数:历史项目在「采用前增删分镜」未同步,
|
||||||
# 或项目创建固定铺的 4 段从未被收口,会让视频步骤的片段数与故事板/采用版分镜对不上。
|
# 或项目创建固定铺的 4 段从未被收口,会让视频步骤的片段数与故事板/采用版分镜对不上。
|
||||||
@@ -238,10 +268,13 @@ class ProjectViewSet(TeamScopedViewSetMixin, ModelViewSet):
|
|||||||
# 用轻量查询判定 + 同步,再交给 super 做重 prefetch 序列化(避免重查询跑两遍)。
|
# 用轻量查询判定 + 同步,再交给 super 做重 prefetch 序列化(避免重查询跑两遍)。
|
||||||
proj = (
|
proj = (
|
||||||
Project.objects.filter(pk=kwargs.get("pk"), **{self.team_field: self.get_team()})
|
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()
|
.first()
|
||||||
)
|
)
|
||||||
if proj is not None:
|
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:
|
if proj.current_stage == ProjectStage.Stage.VIDEO:
|
||||||
adopted_script = proj.script_versions.filter(is_adopted=True).order_by("-created_at").first()
|
adopted_script = proj.script_versions.filter(is_adopted=True).order_by("-created_at").first()
|
||||||
if adopted_script is not None:
|
if adopted_script is not None:
|
||||||
|
|||||||
Reference in New Issue
Block a user