用户认证: - User 模型(支持邮箱/手机号登录) - 双 Token JWT 认证(accessToken + refreshToken) - 注册/登录/刷新 Token API 组织模型: - Brand(品牌方)、Agency(代理商)、Creator(达人) - 多对多关系:品牌方↔代理商、代理商↔达人 项目与任务: - Project 模型(品牌方发布) - Task 模型(完整审核流程追踪) - Brief 模型(解析后的结构化内容) 文件上传: - 阿里云 OSS 直传签名服务 - 支持分片上传,最大 500MB 数据库迁移: - 003_user_org_project_task.py Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
61 lines
2.1 KiB
Python
61 lines
2.1 KiB
Python
"""
|
|
Brief 模型
|
|
"""
|
|
from typing import TYPE_CHECKING, Optional
|
|
from sqlalchemy import String, Text, ForeignKey
|
|
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
|
|
|
from app.models.base import Base, TimestampMixin
|
|
from app.models.types import JSONType
|
|
|
|
if TYPE_CHECKING:
|
|
from app.models.project import Project
|
|
|
|
|
|
class Brief(Base, TimestampMixin):
|
|
"""Brief 文档表"""
|
|
__tablename__ = "briefs"
|
|
|
|
id: Mapped[str] = mapped_column(String(64), primary_key=True)
|
|
project_id: Mapped[str] = mapped_column(
|
|
String(64),
|
|
ForeignKey("projects.id", ondelete="CASCADE"),
|
|
unique=True,
|
|
nullable=False,
|
|
index=True,
|
|
)
|
|
|
|
# 原始文件
|
|
file_url: Mapped[Optional[str]] = mapped_column(String(2048), nullable=True)
|
|
file_name: Mapped[Optional[str]] = mapped_column(String(255), nullable=True)
|
|
|
|
# 解析后的结构化内容
|
|
# 卖点要求: [{"content": "SPF50+", "required": true}, ...]
|
|
selling_points: Mapped[Optional[list]] = mapped_column(JSONType, nullable=True)
|
|
|
|
# 违禁词: [{"word": "最好", "reason": "绝对化用语"}, ...]
|
|
blacklist_words: Mapped[Optional[list]] = mapped_column(JSONType, nullable=True)
|
|
|
|
# 竞品: ["竞品A", "竞品B", ...]
|
|
competitors: Mapped[Optional[list]] = mapped_column(JSONType, nullable=True)
|
|
|
|
# 品牌调性要求
|
|
brand_tone: Mapped[Optional[str]] = mapped_column(Text, nullable=True)
|
|
|
|
# 时长要求(秒)
|
|
min_duration: Mapped[Optional[int]] = mapped_column(nullable=True)
|
|
max_duration: Mapped[Optional[int]] = mapped_column(nullable=True)
|
|
|
|
# 其他要求(自由文本)
|
|
other_requirements: Mapped[Optional[str]] = mapped_column(Text, nullable=True)
|
|
|
|
# 附件文档(代理商上传的参考资料)
|
|
# [{"id": "af1", "name": "达人拍摄指南.pdf", "url": "...", "size": "1.5MB"}, ...]
|
|
attachments: Mapped[Optional[list]] = mapped_column(JSONType, nullable=True)
|
|
|
|
# 关联
|
|
project: Mapped["Project"] = relationship("Project", back_populates="brief")
|
|
|
|
def __repr__(self) -> str:
|
|
return f"<Brief(id={self.id}, project_id={self.project_id})>"
|