Files
fastapi/app/models/training.py
T

92 lines
5.9 KiB
Python
Raw Normal View History

from datetime import datetime
from sqlalchemy import BigInteger, DateTime, ForeignKey, Integer, JSON, String, Text, UniqueConstraint
from sqlalchemy.orm import Mapped, mapped_column, relationship
from app.db.base import Base
from app.models.mixins import TimestampMixin
BIGINT_PK = BigInteger().with_variant(Integer, "sqlite")
class TrainingSession(TimestampMixin, Base):
2026-06-03 15:51:46 +08:00
"""训练会话表:保存一次训练的运行状态、Django 用户隔离信息和短期 memory key。"""
__tablename__ = "training_session"
id: Mapped[int] = mapped_column(BIGINT_PK, primary_key=True, autoincrement=True, comment="训练会话ID")
session_code: Mapped[str] = mapped_column(String(64), nullable=False, unique=True, index=True, comment="会话编码")
2026-06-03 15:51:46 +08:00
user_id: Mapped[str] = mapped_column("external_user_id", String(128), nullable=False, index=True, comment="Django用户中心ID")
tenant_id: Mapped[str | None] = mapped_column(String(128), comment="租户或项目ID")
class_id: Mapped[str | None] = mapped_column(String(128), comment="班级或课程ID")
entry_scene: Mapped[str | None] = mapped_column(String(64), comment="入口场景")
case_id: Mapped[int] = mapped_column(ForeignKey("case_base.id"), nullable=False, index=True, comment="病例ID")
training_type: Mapped[str] = mapped_column("case_type", String(30), nullable=False, comment="病例/训练类型")
mode: Mapped[str] = mapped_column("training_mode", String(50), nullable=False, index=True, comment="训练模式")
score_type: Mapped[str] = mapped_column(String(20), default="percentage", comment="分数输出类型")
status: Mapped[str] = mapped_column(String(30), default="created", index=True, comment="会话状态")
started_at: Mapped[datetime | None] = mapped_column(DateTime, comment="开始时间")
inquiry_completed_at: Mapped[datetime | None] = mapped_column(DateTime, comment="问诊完成时间")
completed_at: Mapped[datetime | None] = mapped_column(DateTime, comment="完成时间")
memory_key: Mapped[str | None] = mapped_column(String(128), comment="短期memory key")
metadata_: Mapped[dict | None] = mapped_column("metadata", JSON, comment="扩展数据")
case = relationship("CaseBase")
orders = relationship("SessionOrder", back_populates="session", cascade="all, delete-orphan")
submission = relationship("SessionSubmission", back_populates="session", uselist=False, cascade="all, delete-orphan")
__table_args__ = {"comment": "训练会话表"}
class SessionOrder(Base):
"""训练检查申请表:记录用户在一次训练中申请过的检查/检验项目和固定结果。"""
__tablename__ = "training_order"
id: Mapped[int] = mapped_column(BIGINT_PK, primary_key=True, autoincrement=True, comment="检查申请ID")
session_id: Mapped[int] = mapped_column(ForeignKey("training_session.id"), nullable=False, index=True, comment="训练会话ID")
2026-06-03 15:51:46 +08:00
user_id: Mapped[str] = mapped_column("external_user_id", String(128), nullable=False, index=True, comment="Django用户中心ID")
case_id: Mapped[int] = mapped_column(ForeignKey("case_base.id"), nullable=False, index=True, comment="病例ID")
case_exam_item_id: Mapped[int] = mapped_column("exam_item_id", ForeignKey("case_exam_item.id"), nullable=False, comment="检查项目ID")
item_code: Mapped[str] = mapped_column(String(64), nullable=False, comment="项目编码")
item_name: Mapped[str] = mapped_column(String(128), nullable=False, comment="项目名称")
item_type: Mapped[str] = mapped_column(String(32), nullable=False, comment="项目类型")
result_text: Mapped[str] = mapped_column(Text, nullable=False, comment="检查结果文本")
result_structured: Mapped[dict | None] = mapped_column(JSON, comment="结构化检查结果")
is_key: Mapped[bool] = mapped_column(default=False, comment="是否关键检查")
is_abnormal: Mapped[bool] = mapped_column(default=False, comment="是否异常结果")
ordered_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow, comment="申请时间")
session = relationship("TrainingSession", back_populates="orders")
case = relationship("CaseBase")
exam_item = relationship("CaseExamItem")
__table_args__ = (
UniqueConstraint("session_id", "item_code", name="uk_training_order_session_item"),
{"comment": "训练检查申请表"},
)
class SessionSubmission(TimestampMixin, Base):
"""训练诊断治疗提交表:保存用户最终提交的诊断、治疗、沟通和随访内容。"""
__tablename__ = "training_submission"
id: Mapped[int] = mapped_column(BIGINT_PK, primary_key=True, autoincrement=True, comment="提交记录ID")
session_id: Mapped[int] = mapped_column(ForeignKey("training_session.id"), nullable=False, unique=True, comment="训练会话ID")
2026-06-03 15:51:46 +08:00
user_id: Mapped[str] = mapped_column("external_user_id", String(128), nullable=False, index=True, comment="Django用户中心ID")
primary_diagnosis: Mapped[str | None] = mapped_column(Text, comment="主要诊断")
differential_diagnoses: Mapped[list | None] = mapped_column(JSON, comment="鉴别诊断")
diagnosis_basis: Mapped[str | None] = mapped_column(Text, comment="诊断依据")
treatment_principle: Mapped[str | None] = mapped_column(Text, comment="治疗原则")
treatment_measures: Mapped[str | None] = mapped_column(Text, comment="治疗措施")
risk_plan: Mapped[str | None] = mapped_column(Text, comment="风险预案")
communication: Mapped[str | None] = mapped_column(Text, comment="医患沟通")
follow_up: Mapped[str | None] = mapped_column(Text, comment="随访安排")
diagnosis_submitted_at: Mapped[datetime | None] = mapped_column(DateTime, comment="诊断提交时间")
treatment_submitted_at: Mapped[datetime | None] = mapped_column(DateTime, comment="治疗提交时间")
session = relationship("TrainingSession", back_populates="submission")
__table_args__ = {"comment": "训练诊断治疗提交表"}