b0f2e4712a
CI/CD Pipeline / Deploy Staging (push) Has been skipped
CI/CD Pipeline / Staging E2E Tests (push) Has been skipped
CI/CD Pipeline / Build Production Runtime Images (push) Has been skipped
CI/CD Pipeline / Deploy Production (push) Has been skipped
CI/CD Pipeline / Production Browser E2E (push) Has been skipped
CI/CD Pipeline / Frontend Lint (push) Failing after 48h55m59s
CI/CD Pipeline / Validate Code Quality And Tests (push) Failing after 48h55m59s
- 新增 Tag 领域实体 + TagModel/AssetTagModel ORM 模型
- Alembic 迁移 030:tags 表 + asset_tags 关联表
- TagRepository 端口 + SQLAlchemy/InMemory 实现
- Asset.tag_ids 多对多关联替代原 JSON tags
- GET /tags / POST /tags / DELETE /tags/{tag_id} 标签 CRUD
- POST /assets/{asset_id}/tags 打标 / DELETE 取消标签
- GET /assets 新增 tag_ids 筛选参数(逗号分隔,取交集)
- 19 个单元测试全部通过
25 lines
604 B
Python
25 lines
604 B
Python
"""标签领域实体。"""
|
|
|
|
from dataclasses import dataclass, field
|
|
from datetime import datetime, timezone
|
|
from uuid import uuid4
|
|
|
|
|
|
@dataclass(slots=True)
|
|
class Tag:
|
|
id: str
|
|
user_id: str
|
|
name: str
|
|
created_at: datetime = field(default_factory=lambda: datetime.now(timezone.utc))
|
|
|
|
@classmethod
|
|
def create(cls, user_id: str, name: str) -> "Tag":
|
|
clean_name = name.strip()
|
|
if not clean_name:
|
|
raise ValueError("标签名称不能为空")
|
|
return cls(
|
|
id=uuid4().hex,
|
|
user_id=user_id,
|
|
name=clean_name,
|
|
)
|