Files

92 lines
5.9 KiB
Python
Raw Permalink 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": "训练诊断治疗提交表"}