feat(review): 全站统一「审核盾」徽章 + 灰盾点击手动提交兜底
火山人像审核状态此前三处文案各异(已审核/通过/审核✓…)。统一成一个共享 ReviewBadge: 全色填充盾(无对勾叉)+ 文案 + hover 气泡说明,4 态: 🟢已过审(active) / 🔴未过审(failed) / 🟠审核中(processing,橙盾光扫动画) / ⚪待审核(空) 灰盾(未送审)可点 → 提交审核(兜底,不加固定按钮):后端新增 POST /api/assets/{id}/submit-review/ (团队级,仅送审三类),前端点击乐观置 processing。气泡组件顺带成为全站首个统一 tooltip。 - 后端 submit-review 端点 + 单测(送审类 200 / 非送审类 400) - 共享 components/review-badge.{tsx,css}(盾用 SVG 蒙版填色 + 橙态 rv-sweep 光扫) - 资产库详情弹窗 / 商品详情素材组弹窗 / 视频流程基础资产 三处全换成它(各自接 onSubmit) 验收:assets 16 测绿;tsc+build 绿;无头核对四态(灰可点+气泡/绿已过审/橙审核中不可点)、0 console error Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -141,6 +141,28 @@ class VideoPacksTests(TestCase):
|
||||
self.assertEqual(len(data[0]["clips"]), 1)
|
||||
|
||||
|
||||
class SubmitReviewTests(TestCase):
|
||||
"""手动兜底:灰盾点击 → 提交审核;只对送审类放行,非送审类 400。"""
|
||||
|
||||
def setUp(self):
|
||||
self.user, self.team = _mk_team("usr", "TeamSR")
|
||||
self.client = APIClient()
|
||||
self.client.force_authenticate(self.user)
|
||||
self.person = Asset.objects.create(team=self.team, name="角色", asset_type="image", source="ai_generated", category=Asset.Category.PERSON)
|
||||
self.product = Asset.objects.create(team=self.team, name="商品图", asset_type="image", source="upload", category=Asset.Category.PRODUCT_IMAGE)
|
||||
|
||||
def test_submit_review_person_ok(self):
|
||||
with patch("apps.assets.review.submit_asset_for_review") as sub:
|
||||
res = self.client.post(f"/api/assets/{self.person.id}/submit-review/")
|
||||
self.assertEqual(res.status_code, 200)
|
||||
sub.assert_called_once()
|
||||
self.assertIn("review_status", res.json())
|
||||
|
||||
def test_submit_review_rejects_non_review_category(self):
|
||||
res = self.client.post(f"/api/assets/{self.product.id}/submit-review/")
|
||||
self.assertEqual(res.status_code, 400)
|
||||
|
||||
|
||||
class ReviewScopeTests(TestCase):
|
||||
"""送审范围 = 角色定妆照(person)/ 三视图(tri_view)/ 分镜图(storyboard);图片趴不送审。"""
|
||||
|
||||
|
||||
@@ -116,6 +116,19 @@ class AssetViewSet(TeamScopedViewSetMixin, ModelViewSet):
|
||||
tabs = ["tryon", "kits", "creations", "others"]
|
||||
return Response({t: base.filter(_tab_q(t)).count() for t in tabs})
|
||||
|
||||
@action(detail=True, methods=["post"], url_path="submit-review")
|
||||
def submit_review(self, request, pk=None):
|
||||
"""手动兜底:把单个送审类素材(角色/三视图/分镜)送火山审核 —— 用户点灰盾「待审核」时触发。
|
||||
正常走 on_commit 自动送审;此口给万一漏提交时补提交。非送审类拒绝。"""
|
||||
from apps.assets.review import submit_asset_for_review
|
||||
|
||||
asset = self.get_object() # team-scoped + is_deleted 过滤
|
||||
if asset.category not in Asset.REVIEW_CATEGORIES:
|
||||
return Response({"detail": "该素材无需审核"}, status=status.HTTP_400_BAD_REQUEST)
|
||||
submit_asset_for_review(asset)
|
||||
asset.refresh_from_db()
|
||||
return Response({"review_status": asset.review_status, "review_error": asset.review_error or ""})
|
||||
|
||||
@action(detail=False, methods=["get"], url_path="video-packs")
|
||||
def video_packs(self, request):
|
||||
"""视频成品按「项目素材包」打包:每个项目的已采用视频片段 = 一个包(与「导出全部」同源:
|
||||
|
||||
Reference in New Issue
Block a user