主要更新: - 更新代理商端文档,明确项目由品牌方分配流程 - 新增Brief配置详情页(已配置)设计稿 - 完善工作台紧急待办中品牌新任务功能 - 整理Pencil设计文件中代理商端页面顺序 - 新增后端FastAPI框架及核心API - 新增前端Next.js页面和组件库 - 添加.gitignore排除构建和缓存文件 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
86 lines
2.7 KiB
Python
86 lines
2.7 KiB
Python
"""
|
|
规则模型
|
|
违禁词、白名单、竞品
|
|
"""
|
|
from typing import TYPE_CHECKING, Optional
|
|
from sqlalchemy import String, Text, ForeignKey
|
|
from app.models.types import JSONType
|
|
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
|
|
|
from app.models.base import Base, TimestampMixin
|
|
|
|
if TYPE_CHECKING:
|
|
from app.models.tenant import Tenant
|
|
|
|
|
|
class ForbiddenWord(Base, TimestampMixin):
|
|
"""违禁词表"""
|
|
__tablename__ = "forbidden_words"
|
|
|
|
id: Mapped[str] = mapped_column(String(64), primary_key=True)
|
|
tenant_id: Mapped[str] = mapped_column(
|
|
String(64),
|
|
ForeignKey("tenants.id", ondelete="CASCADE"),
|
|
nullable=False,
|
|
index=True,
|
|
)
|
|
|
|
word: Mapped[str] = mapped_column(String(255), nullable=False, index=True)
|
|
category: Mapped[str] = mapped_column(String(100), nullable=False, index=True)
|
|
severity: Mapped[str] = mapped_column(String(50), nullable=False)
|
|
|
|
# 关联
|
|
tenant: Mapped["Tenant"] = relationship("Tenant", back_populates="forbidden_words")
|
|
|
|
def __repr__(self) -> str:
|
|
return f"<ForbiddenWord(word={self.word}, category={self.category})>"
|
|
|
|
|
|
class WhitelistItem(Base, TimestampMixin):
|
|
"""白名单表"""
|
|
__tablename__ = "whitelist_items"
|
|
|
|
id: Mapped[str] = mapped_column(String(64), primary_key=True)
|
|
tenant_id: Mapped[str] = mapped_column(
|
|
String(64),
|
|
ForeignKey("tenants.id", ondelete="CASCADE"),
|
|
nullable=False,
|
|
index=True,
|
|
)
|
|
brand_id: Mapped[str] = mapped_column(String(64), nullable=False, index=True)
|
|
|
|
term: Mapped[str] = mapped_column(String(255), nullable=False, index=True)
|
|
reason: Mapped[str] = mapped_column(Text, nullable=False)
|
|
|
|
# 关联
|
|
tenant: Mapped["Tenant"] = relationship("Tenant", back_populates="whitelist_items")
|
|
|
|
def __repr__(self) -> str:
|
|
return f"<WhitelistItem(term={self.term}, brand_id={self.brand_id})>"
|
|
|
|
|
|
class Competitor(Base, TimestampMixin):
|
|
"""竞品表"""
|
|
__tablename__ = "competitors"
|
|
|
|
id: Mapped[str] = mapped_column(String(64), primary_key=True)
|
|
tenant_id: Mapped[str] = mapped_column(
|
|
String(64),
|
|
ForeignKey("tenants.id", ondelete="CASCADE"),
|
|
nullable=False,
|
|
index=True,
|
|
)
|
|
brand_id: Mapped[str] = mapped_column(String(64), nullable=False, index=True)
|
|
|
|
name: Mapped[str] = mapped_column(String(255), nullable=False)
|
|
logo_url: Mapped[Optional[str]] = mapped_column(String(2048), nullable=True)
|
|
|
|
# 关键词列表 (JSON 数组)
|
|
keywords: Mapped[Optional[list]] = mapped_column(JSONType, nullable=True)
|
|
|
|
# 关联
|
|
tenant: Mapped["Tenant"] = relationship("Tenant", back_populates="competitors")
|
|
|
|
def __repr__(self) -> str:
|
|
return f"<Competitor(name={self.name}, brand_id={self.brand_id})>"
|