7cb36a5c3d
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 3m9s
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 3m39s
CI/CD Pipeline / Validate - Code Quality (pull_request) Failing after 3m43s
CI/CD Pipeline / Validate - Migration (alembic) (pull_request) Successful in 4m0s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 4m3s
CI/CD Pipeline / Validate - Type Check (mypy) (pull_request) Successful in 4m7s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 1m14s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m24s
AI Code Review / AI Code Review (pull_request) Failing after 4m42s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 5m49s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 2m58s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 9m19s
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / CI Gate (pull_request) Failing after 24s
145 lines
5.5 KiB
Python
Executable File
145 lines
5.5 KiB
Python
Executable File
from pydantic import BaseModel, Field
|
||
|
||
|
||
class CreateAssetRequest(BaseModel):
|
||
project_id: str | None = Field(default=None, description="可选,不传时从 library.project_id 自动推导")
|
||
library_id: str = Field(..., min_length=1)
|
||
name: str = Field(..., min_length=1, max_length=100)
|
||
storage_key: str = Field(..., min_length=1, max_length=255)
|
||
mime_type: str = Field(..., min_length=1, max_length=100)
|
||
metadata: dict[str, object] = Field(default_factory=dict)
|
||
file_size: int = Field(default=0, ge=0)
|
||
thumbnail_url: str | None = None
|
||
duration: float | None = Field(default=None, ge=0)
|
||
width: int | None = Field(default=None, ge=0)
|
||
height: int | None = Field(default=None, ge=0)
|
||
fps: float | None = Field(default=None, ge=0)
|
||
codec: str | None = None
|
||
status: str = Field(default="uploading")
|
||
classification_status: str = Field(default="pending")
|
||
quality_score: float | None = Field(default=None, ge=0, le=100)
|
||
uploaded_by_user_id: str = Field(default="", max_length=100)
|
||
|
||
|
||
class UpdateAssetReviewRequest(BaseModel):
|
||
review_status: str = Field(..., pattern="^(pending_review|approved|rejected)$")
|
||
|
||
|
||
class UpdateAssetRequest(BaseModel):
|
||
name: str | None = Field(default=None, min_length=1, max_length=100)
|
||
metadata: dict[str, object] | None = None
|
||
tags: list[str] | None = None
|
||
|
||
|
||
class AssetResponse(BaseModel):
|
||
id: str
|
||
project_id: str
|
||
library_id: str
|
||
name: str
|
||
storage_key: str
|
||
mime_type: str
|
||
metadata: dict[str, object]
|
||
file_size: int
|
||
file_url: str | None = None
|
||
thumbnail_url: str | None = None
|
||
duration: float | None = None
|
||
width: int | None = None
|
||
height: int | None = None
|
||
fps: float | None = None
|
||
codec: str | None = None
|
||
status: str
|
||
classification_status: str
|
||
quality_score: float | None = None
|
||
created_at: str
|
||
uploaded_by_user_id: str
|
||
tag_ids: list[str] = Field(default_factory=list)
|
||
# 片段级余量信息(仅视频素材返回,非视频/无时长记录为 None,前端按可用处理)
|
||
used_duration: float | None = Field(default=None, description="已使用片段时长(秒,历史区间合并去重后)")
|
||
available_duration: float | None = Field(default=None, description="剩余可用时长(秒)= 素材总时长 - 已用时长")
|
||
used_ratio: float | None = Field(default=None, description="已用时长占比(0~1)")
|
||
usable: bool = Field(
|
||
default=True,
|
||
description="是否仍可用于新片段:零重复可切区间耗尽且所有历史区间复用次数" "(use_count)均达上限时为 false",
|
||
)
|
||
|
||
|
||
MAX_BATCH_SIZE = 200
|
||
|
||
|
||
class BatchGetRequest(BaseModel):
|
||
"""批量获取素材详情请求。"""
|
||
|
||
ids: list[str] = Field(..., min_length=1, max_length=MAX_BATCH_SIZE, description="素材 ID 列表")
|
||
|
||
|
||
class BatchDeleteRequest(BaseModel):
|
||
"""批量删除请求(软删除)。"""
|
||
|
||
asset_ids: list[str] = Field(..., min_length=1, max_length=MAX_BATCH_SIZE, description="要删除的素材 ID 列表")
|
||
|
||
|
||
class BatchOperationResponse(BaseModel):
|
||
"""批量操作通用响应。"""
|
||
|
||
success_count: int = Field(..., ge=0, description="成功数量")
|
||
failed_ids: list[str] = Field(default_factory=list, description="失败的 ID 列表")
|
||
failed_details: dict[str, str] = Field(default_factory=dict, description="失败详情 {asset_id: reason}")
|
||
|
||
|
||
class BatchTagRequest(BaseModel):
|
||
"""批量打标签请求。"""
|
||
|
||
asset_ids: list[str] = Field(..., min_length=1, max_length=MAX_BATCH_SIZE, description="素材 ID 列表")
|
||
tag_ids: list[str] = Field(..., min_length=1, max_length=50, description="标签 ID 列表")
|
||
mode: str = Field(default="add", pattern="^(add|replace)$", description="add=添加合并,replace=全量替换")
|
||
|
||
|
||
class BatchClassifyRequest(BaseModel):
|
||
"""批量修改分类请求。"""
|
||
|
||
asset_ids: list[str] = Field(..., min_length=1, max_length=MAX_BATCH_SIZE, description="素材 ID 列表")
|
||
category: str = Field(..., min_length=1, max_length=50, description="内容分类,如 person/scenic/product")
|
||
|
||
|
||
class BatchMarkRequest(BaseModel):
|
||
"""批量设置智能视图标记请求。"""
|
||
|
||
asset_ids: list[str] = Field(..., min_length=1, max_length=MAX_BATCH_SIZE, description="素材 ID 列表")
|
||
smart_view: str = Field(
|
||
..., pattern="^(recommended|caution|high_risk)$", description="智能视图标记:recommended/caution/high_risk"
|
||
)
|
||
|
||
|
||
class ListAssetsResponse(BaseModel):
|
||
items: list[AssetResponse]
|
||
total: int = Field(default=0, ge=0)
|
||
skip: int = Field(default=0, ge=0)
|
||
limit: int = Field(default=100, ge=1)
|
||
|
||
|
||
class SmartMatchRequest(BaseModel):
|
||
"""智能选素材请求。"""
|
||
|
||
library_id: str = Field(..., min_length=1, description="素材库 ID")
|
||
limit: int | None = Field(default=None, ge=1, le=200, description="最大返回数量,不传则返回全部匹配素材")
|
||
kind: str | None = Field(
|
||
default=None,
|
||
pattern="^(video|image|audio)$",
|
||
description="按文件类型过滤,不传则返回所有类型",
|
||
)
|
||
|
||
|
||
class SmartMatchItem(BaseModel):
|
||
"""智能选素材结果条目。"""
|
||
|
||
asset: AssetResponse
|
||
score: float = Field(..., ge=0, le=100, description="综合得分 0-100")
|
||
breakdown: dict[str, float] = Field(default_factory=dict, description="各维度得分明细")
|
||
|
||
|
||
class SmartMatchResponse(BaseModel):
|
||
"""智能选素材响应。"""
|
||
|
||
items: list[SmartMatchItem]
|
||
total_candidates: int = Field(default=0, ge=0, description="参与评分的候选素材总数")
|