fix(test-round): 测试清单一批 bug 修复 + 团队月限额持久化

后端:
- accounts: 团队级月限额持久化(Team.monthly_credit_limit 三态 + PATCH/GET
  /api/auth/team/settings/,刷新不丢,PMC#12);头像上传 500→502 可读错误;
  设备下线真失效(删并重建 token,旧 token 401)
- assets: 审核类目加 model_portrait,消除三视图"无需审核"误报
- ai/projects/products: 模特已有三视图复用、产品三视图同步回商品库
  (metadata.view=three_view)、真人模特三视图回写

前端:
- 商品图删除判断改用真实图片数;团队成员弹窗禁点外部关闭
- 图片预览骨架铺满占位;平台套图左侧栏折叠改导航同款;收件箱长文换行对齐
- 团队月限额改真落库(乐观更新+失败回滚)

测试:新增 TeamSettingsTests(5 条),accounts 全套 36 tests 通过;前端 build 0 error

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
zyc
2026-06-29 18:50:22 +08:00
co-authored by Claude Opus 4.8
parent ca0c3e2300
commit b0b3ac2348
20 changed files with 476 additions and 57 deletions
+30 -11
View File
@@ -1317,16 +1317,28 @@ def run_base_asset_task(*, task_id: str) -> None:
BaseAssetGroup.Kind.PERSON: Asset.Category.PERSON,
BaseAssetGroup.Kind.SCENE: Asset.Category.SCENE,
}[kind]
# 商品基础资产 = 商品三视图(prompt 即「生成同一件商品的三视图」):名字带「三视图」并打
# metadata.view=three_view + product_id,让商品库的三视图查询(products is_triview / ?product 过滤)
# 能认出并回填——否则视频项目生成的商品三视图同步不回商品库,商品库永远显示「尚未生成」(ZWQ#5)。
is_product = kind == BaseAssetGroup.Kind.PRODUCT
asset_name = f"{project.name}-商品三视图" if is_product else f"{project.name}-{kind}"
asset = _store_generated_media(
team=project.team,
user=user,
project=project,
task=task,
media=media,
name=f"{project.name}-{kind}",
name=asset_name,
category=category,
asset_type=Asset.Type.IMAGE,
)
if is_product:
meta = dict(asset.metadata or {})
meta["view"] = "three_view"
if project.product_id:
meta["product_id"] = str(project.product_id)
asset.metadata = meta
asset.save(update_fields=["metadata", "updated_at"])
# 复用同实体的组:追加候选 + 采用最新(版本=candidate_assets,采用=adopted_asset);无则新建
group = _find_entity_group(project, kind, label, group_id)
if group is None:
@@ -1423,19 +1435,26 @@ def run_triview_task(*, task_id: str) -> None:
group.candidate_assets.add(asset)
group.adopted_asset = asset
group.save(update_fields=["adopted_asset", "updated_at"])
# B 路(期3):视频流程新生成的「角色」立绘 + 三视图成套 → 自动加入模特库(团队级可复用)。
# 幂等:同一立绘只建一次 Model;best-effort,不影响主链路。
# B 路(期3):视频流程新生成的「角色」立绘 + 三视图成套 → 自动加入/更新模特库(团队级可复用)。
# 幂等:同一立绘只建一次 Model;已存在该立绘的 Model(尤其「真人上传」模特,upload 时只建了 portrait、
# 还没 triview)→ 回写 triview_asset,否则模特库永远显示「无三视图」(ZWQ#7:AI 角色能更新、真人上传不更新)。
from apps.assets.models import Model as ModelEntity
portrait = Asset.objects.filter(id=asset_key).first()
if portrait is not None and not ModelEntity.objects.filter(portrait_asset=portrait).exists():
ModelEntity.objects.create(
team=project.team, created_by=user,
name=(portrait.name or f"{project.name}-角色").split("·")[0].strip()[:255] or "角色",
source=ModelEntity.Source.AI,
portrait_asset=portrait, triview_asset=asset,
metadata={"from_project": str(project.id), "auto_enrolled": True},
)
if portrait is not None:
existing_model = ModelEntity.objects.filter(portrait_asset=portrait, is_deleted=False).first()
if existing_model is None:
ModelEntity.objects.create(
team=project.team, created_by=user,
name=(portrait.name or f"{project.name}-角色").split("·")[0].strip()[:255] or "角色",
source=ModelEntity.Source.AI,
portrait_asset=portrait, triview_asset=asset,
metadata={"from_project": str(project.id), "auto_enrolled": True},
)
elif existing_model.triview_asset_id != asset.id:
# 真人上传 / 已有模特补三视图:回写新三视图(应用后模特库即刷新三视图)
existing_model.triview_asset = asset
existing_model.save(update_fields=["triview_asset", "updated_at"])
# 合规(期3):三视图含人脸,视频生成前必须过火山审核 → 事务提交后静默送审(best-effort)
from apps.assets.review import submit_asset_for_review