fix:文明
This commit is contained in:
BIN
server/app/db/__pycache__/base.cpython-313.pyc
Normal file
BIN
server/app/db/__pycache__/base.cpython-313.pyc
Normal file
Binary file not shown.
14
server/app/db/models/__init__.py
Normal file
14
server/app/db/models/__init__.py
Normal file
@@ -0,0 +1,14 @@
|
||||
"""
|
||||
数据库 ORM 模型集合。
|
||||
|
||||
说明:
|
||||
- 该包用于集中定义 SQLAlchemy ORM models,供 Alembic autogenerate 扫描。
|
||||
- 需要在此处导入所有模型,确保 `Base.metadata` 完整。
|
||||
"""
|
||||
|
||||
from app.db.models.content import Content
|
||||
from app.db.models.content_profile import ContentProfile
|
||||
from app.db.models.content_risk_flag import ContentRiskFlag
|
||||
|
||||
__all__ = ["Content", "ContentProfile", "ContentRiskFlag"]
|
||||
|
||||
BIN
server/app/db/models/__pycache__/__init__.cpython-313.pyc
Normal file
BIN
server/app/db/models/__pycache__/__init__.cpython-313.pyc
Normal file
Binary file not shown.
BIN
server/app/db/models/__pycache__/content.cpython-313.pyc
Normal file
BIN
server/app/db/models/__pycache__/content.cpython-313.pyc
Normal file
Binary file not shown.
BIN
server/app/db/models/__pycache__/content_profile.cpython-313.pyc
Normal file
BIN
server/app/db/models/__pycache__/content_profile.cpython-313.pyc
Normal file
Binary file not shown.
Binary file not shown.
70
server/app/db/models/content.py
Normal file
70
server/app/db/models/content.py
Normal file
@@ -0,0 +1,70 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
from sqlalchemy import CheckConstraint, DateTime, Index, Text, func
|
||||
from sqlalchemy.orm import Mapped, mapped_column
|
||||
|
||||
from app.db.base import Base
|
||||
|
||||
|
||||
class Content(Base):
|
||||
"""
|
||||
文案主体表。
|
||||
|
||||
多语言约束:
|
||||
- 当前仅支持 EN / TC(繁体中文)
|
||||
- 至少需要提供 `text_en` 或 `text_tc` 之一
|
||||
"""
|
||||
|
||||
__tablename__ = "contents"
|
||||
|
||||
__table_args__ = (
|
||||
CheckConstraint(
|
||||
"(text_en IS NOT NULL) OR (text_tc IS NOT NULL)",
|
||||
name="chk_contents_text_present",
|
||||
),
|
||||
Index("idx_contents_author_id", "author_id"),
|
||||
Index("idx_contents_template_id", "template_id"),
|
||||
)
|
||||
|
||||
content_id: Mapped[int] = mapped_column(
|
||||
primary_key=True,
|
||||
autoincrement=True,
|
||||
comment="文案唯一 ID(自增;文案微调时保持不变)",
|
||||
)
|
||||
|
||||
text_en: Mapped[str | None] = mapped_column(
|
||||
Text,
|
||||
nullable=True,
|
||||
comment="英文文案(可空;若为空则必须提供 text_tc)",
|
||||
)
|
||||
text_tc: Mapped[str | None] = mapped_column(
|
||||
Text,
|
||||
nullable=True,
|
||||
comment="繁体中文文案(可空;若为空则必须提供 text_en)",
|
||||
)
|
||||
|
||||
author_id: Mapped[str | None] = mapped_column(
|
||||
nullable=True,
|
||||
comment="作者/来源 ID(可空;用于多样性与频控)",
|
||||
)
|
||||
template_id: Mapped[str | None] = mapped_column(
|
||||
nullable=True,
|
||||
comment="模板 ID(可空;用于多样性与频控)",
|
||||
)
|
||||
|
||||
created_at: Mapped[datetime] = mapped_column(
|
||||
DateTime,
|
||||
nullable=False,
|
||||
server_default=func.now(),
|
||||
comment="创建时间",
|
||||
)
|
||||
updated_at: Mapped[datetime] = mapped_column(
|
||||
DateTime,
|
||||
nullable=False,
|
||||
server_default=func.now(),
|
||||
server_onupdate=func.now(),
|
||||
comment="更新时间",
|
||||
)
|
||||
|
||||
95
server/app/db/models/content_profile.py
Normal file
95
server/app/db/models/content_profile.py
Normal file
@@ -0,0 +1,95 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import datetime
|
||||
from typing import Literal, Optional
|
||||
|
||||
from sqlalchemy import (
|
||||
JSON,
|
||||
Boolean,
|
||||
DateTime,
|
||||
Enum,
|
||||
ForeignKey,
|
||||
Index,
|
||||
Numeric,
|
||||
func,
|
||||
)
|
||||
from sqlalchemy.orm import Mapped, mapped_column
|
||||
|
||||
from app.db.base import Base
|
||||
|
||||
ContentStage = Literal["general", "expecting", "parenting", "unknown"]
|
||||
|
||||
|
||||
class ContentProfile(Base):
|
||||
"""
|
||||
内容画像表(Content Profile / Cᵢ)。
|
||||
|
||||
字段语义必须严格对齐:
|
||||
- `设计说明文档/句子文案打分規則.md`
|
||||
"""
|
||||
|
||||
__tablename__ = "content_profiles"
|
||||
|
||||
__table_args__ = (
|
||||
Index("idx_profiles_stage", "stage"),
|
||||
Index("idx_profiles_personalization_power", "personalization_power"),
|
||||
Index("idx_profiles_is_safe_pool", "is_safe_pool"),
|
||||
)
|
||||
|
||||
content_id: Mapped[int] = mapped_column(
|
||||
ForeignKey("contents.content_id", ondelete="CASCADE"),
|
||||
primary_key=True,
|
||||
comment="FK -> contents.content_id",
|
||||
)
|
||||
|
||||
stage: Mapped[ContentStage] = mapped_column(
|
||||
Enum("general", "expecting", "parenting", "unknown", name="content_stage"),
|
||||
nullable=False,
|
||||
server_default="general",
|
||||
comment="母职阶段定位(general/expecting/parenting/unknown)",
|
||||
)
|
||||
|
||||
emotion_score: Mapped[Optional[float]] = mapped_column(
|
||||
Numeric(3, 2),
|
||||
nullable=True,
|
||||
comment="情绪调性 0~1;NULL 表示 general",
|
||||
)
|
||||
|
||||
context_suitability_json: Mapped[dict] = mapped_column(
|
||||
JSON,
|
||||
nullable=False,
|
||||
comment="各 context 的适配度(JSON:0/0.5/1;必须包含 5 个 key)",
|
||||
)
|
||||
need_suitability_json: Mapped[dict] = mapped_column(
|
||||
JSON,
|
||||
nullable=False,
|
||||
comment="各 need 的适配度(JSON:0/0.5/1;必须包含 5 个 key)",
|
||||
)
|
||||
|
||||
personalization_power: Mapped[int] = mapped_column(
|
||||
nullable=False,
|
||||
server_default="0",
|
||||
comment="个性化力度(约定只允许 0/5/10,分别映射 0/0.5/1)",
|
||||
)
|
||||
|
||||
review_confidence: Mapped[Optional[float]] = mapped_column(
|
||||
Numeric(3, 2),
|
||||
nullable=True,
|
||||
comment="标注置信度 0~1;NULL 表示由推荐侧按 0.7 兜底",
|
||||
)
|
||||
|
||||
is_safe_pool: Mapped[bool] = mapped_column(
|
||||
Boolean,
|
||||
nullable=False,
|
||||
server_default="0",
|
||||
comment="是否属于通用安全池(L3 兜底)",
|
||||
)
|
||||
|
||||
updated_at: Mapped[datetime] = mapped_column(
|
||||
DateTime,
|
||||
nullable=False,
|
||||
server_default=func.now(),
|
||||
server_onupdate=func.now(),
|
||||
comment="画像更新时间",
|
||||
)
|
||||
|
||||
51
server/app/db/models/content_risk_flag.py
Normal file
51
server/app/db/models/content_risk_flag.py
Normal file
@@ -0,0 +1,51 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
from sqlalchemy import DateTime, ForeignKey, Index, UniqueConstraint, func
|
||||
from sqlalchemy.orm import Mapped, mapped_column
|
||||
|
||||
from app.db.base import Base
|
||||
|
||||
|
||||
class ContentRiskFlag(Base):
|
||||
"""
|
||||
内容风险标记(risk_flags)关联表。
|
||||
|
||||
命名约束(语义来源:句子文案打分规则):
|
||||
- 仅允许 `unsafe_for_*` / `block_*` / `soft_*` 前缀
|
||||
- 旧 flag(如 `block_stage_unknown`)需在写入/读取层做映射
|
||||
"""
|
||||
|
||||
__tablename__ = "content_risk_flags"
|
||||
|
||||
__table_args__ = (
|
||||
UniqueConstraint("content_id", "flag", name="uniq_content_flag"),
|
||||
Index("idx_flag", "flag"),
|
||||
Index("idx_content_id", "content_id"),
|
||||
)
|
||||
|
||||
id: Mapped[int] = mapped_column(
|
||||
primary_key=True,
|
||||
autoincrement=True,
|
||||
comment="主键",
|
||||
)
|
||||
|
||||
content_id: Mapped[int] = mapped_column(
|
||||
ForeignKey("contents.content_id", ondelete="CASCADE"),
|
||||
nullable=False,
|
||||
comment="FK -> contents.content_id",
|
||||
)
|
||||
|
||||
flag: Mapped[str] = mapped_column(
|
||||
nullable=False,
|
||||
comment="风险标记(unsafe_for_* / block_* / soft_*)",
|
||||
)
|
||||
|
||||
created_at: Mapped[datetime] = mapped_column(
|
||||
DateTime,
|
||||
nullable=False,
|
||||
server_default=func.now(),
|
||||
comment="创建时间",
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user