feat(models): 期1 模特库地基 — Model 顶级实体 + 模特库页 + 审核范围扩展
后端:
- 新增 Model(模特)团队级实体:形象图+三视图+声线(声线尾期),官方模板标签,软删
- Asset.Category 枚举一次加全(model_portrait/tri_view/voice/model_tryon/platform_kit/free_create/storyboard),逐期接线
- 送审范围 person → REVIEW_CATEGORIES{person,tri_view,storyboard}(review.py + adminpanel 队列),图片趴不送审;当前行为不变(forward-compat)
- /api/models/ ModelLibraryViewSet:本团队∪官方模板、官方/我的 tab、真人上传、软删(官方不可删)、跨团队资产引用防越权
- backfill_models 命令把历史成套模特(kind=model + 项目流命名配对)归集成 Model,dry-run 默认
前端:
- 左菜单新增「模特库」顶级入口(person 图标)+ 路由 /models
- 模特库页:全部/官方模板/我的模特 tab + 真人上传 + 模特卡(形象图+三视图缩略+官方标签),仅用 design token
测试:assets 10/10 绿;tsc+build 全绿;无头走查 0 console error(全部5/官方3/我的2,官方标签达标)
基线既有 7 失败(ai/projects provider mock 漂移)零新增
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
1c9143ce61
commit
44e90233ff
@@ -18,13 +18,24 @@ class Asset(TeamOwnedModel):
|
||||
SYSTEM = "system", "System"
|
||||
|
||||
class Category(models.TextChoices):
|
||||
PERSON = "person", "Person"
|
||||
PERSON = "person", "Person" # 视频趴·角色定妆照(送审)
|
||||
SCENE = "scene", "Scene"
|
||||
PRODUCT_IMAGE = "product_image", "Product Image"
|
||||
VIDEO_CLIP = "video_clip", "Video Clip"
|
||||
FINAL_VIDEO = "final_video", "Final Video"
|
||||
UPLOAD = "upload", "Upload"
|
||||
UNCATEGORIZED = "uncategorized", "Uncategorized"
|
||||
# ↓ 模特库 + 资产模型重构(2026-06-20)新增,逐期接线。
|
||||
MODEL_PORTRAIT = "model_portrait", "Model Portrait" # 模特形象图(图片域·不送审)
|
||||
TRI_VIEW = "tri_view", "Tri View" # 三视图(送审)
|
||||
VOICE = "voice", "Voice" # 模特声线(占位·尾期)
|
||||
MODEL_TRYON = "model_tryon", "Model Try-on" # 模特上身图(图片趴·不送审)
|
||||
PLATFORM_KIT = "platform_kit", "Platform Kit" # 平台套图(图片趴)
|
||||
FREE_CREATE = "free_create", "Free Create" # 自由创作(图片趴)
|
||||
STORYBOARD = "storyboard", "Storyboard" # 分镜图(视频趴·送审)
|
||||
|
||||
# 送审范围(火山人像审核):视频趴含人脸 = 角色定妆照 / 三视图 / 分镜图。图片趴(上身图/套图/创作)不送审。
|
||||
REVIEW_CATEGORIES = ("person", "tri_view", "storyboard")
|
||||
|
||||
name = models.CharField(max_length=255)
|
||||
asset_type = models.CharField(max_length=24, choices=Type.choices)
|
||||
@@ -56,6 +67,45 @@ class Asset(TeamOwnedModel):
|
||||
return self.name
|
||||
|
||||
|
||||
class Model(TeamOwnedModel):
|
||||
"""模特(顶级实体 = 模特库)· 团队级、可复用。
|
||||
|
||||
一个完整模特 = 形象图 + 三视图 + 声线(声线尾期做)。图片线(上身图)+ 视频线(角色)都能引用它。
|
||||
来源:官方预制(is_official=True,打「官方模板」标签)/ 商家自建(AI 生成或真人上传)。
|
||||
portrait/triview/voice 指向具体 Asset(复用资产表,不重复存文件)。
|
||||
"""
|
||||
|
||||
class Source(models.TextChoices):
|
||||
AI = "ai", "AI Generated"
|
||||
UPLOAD = "upload", "Upload"
|
||||
|
||||
name = models.CharField(max_length=255)
|
||||
is_official = models.BooleanField(default=False) # 官方模板标签
|
||||
source = models.CharField(max_length=16, choices=Source.choices, default=Source.AI)
|
||||
portrait_asset = models.ForeignKey(
|
||||
Asset, on_delete=models.SET_NULL, null=True, blank=True, related_name="model_as_portrait"
|
||||
)
|
||||
triview_asset = models.ForeignKey(
|
||||
Asset, on_delete=models.SET_NULL, null=True, blank=True, related_name="model_as_triview"
|
||||
)
|
||||
voice_asset = models.ForeignKey( # 声线,尾期接线,先留空
|
||||
Asset, on_delete=models.SET_NULL, null=True, blank=True, related_name="model_as_voice"
|
||||
)
|
||||
description = models.TextField(blank=True)
|
||||
metadata = models.JSONField(default=dict, blank=True)
|
||||
is_deleted = models.BooleanField(default=False)
|
||||
|
||||
class Meta:
|
||||
indexes = [
|
||||
# 模特库默认按团队 + 新→旧;官方模板优先靠前由序列化/查询控制
|
||||
models.Index(fields=["team", "is_official", "-created_at"]),
|
||||
]
|
||||
ordering = ["-created_at"]
|
||||
|
||||
def __str__(self) -> str:
|
||||
return self.name
|
||||
|
||||
|
||||
class AssetReviewGroup(TimeStampedModel):
|
||||
"""一团队一火山人像素材组(真人资产审核统一上传到这里,单组可放 500 万)。"""
|
||||
|
||||
|
||||
Reference in New Issue
Block a user