280 lines
14 KiB
Python
280 lines
14 KiB
Python
from flask_sqlalchemy import SQLAlchemy
|
||
from datetime import datetime
|
||
|
||
db = SQLAlchemy()
|
||
|
||
class Hospital(db.Model):
|
||
__tablename__ = 'hospital'
|
||
|
||
id = db.Column(db.Integer, primary_key=True, autoincrement=True, comment='医院ID')
|
||
name = db.Column(db.String(100), nullable=False, comment='医院名称')
|
||
address = db.Column(db.String(255), nullable=True, comment='医院地址')
|
||
deleted = db.Column(db.Boolean, default=False, comment='逻辑删除标志,True表示已删除')
|
||
created_at = db.Column(db.TIMESTAMP, default=datetime.now, comment='创建时间')
|
||
|
||
def to_dict(self):
|
||
return {
|
||
'id': self.id,
|
||
'name': self.name,
|
||
'address': self.address,
|
||
'deleted': self.deleted,
|
||
'created_at': self.created_at.strftime('%Y-%m-%d %H:%M:%S') if self.created_at else None
|
||
}
|
||
|
||
class Doctor(db.Model):
|
||
__tablename__ = 'doctor'
|
||
|
||
id = db.Column(db.Integer, primary_key=True, autoincrement=True, comment='医生ID')
|
||
phone = db.Column(db.String(20), unique=True, nullable=False, comment='医生电话,唯一且非空')
|
||
name = db.Column(db.String(100), nullable=False, comment='医生姓名')
|
||
password = db.Column(db.String(100), nullable=False, comment='医生密码')
|
||
gender = db.Column(db.Enum('男', '女', '未知'), nullable=False, comment='医生性别')
|
||
created_at = db.Column(db.TIMESTAMP, default=datetime.now, comment='创建时间')
|
||
|
||
def to_dict(self):
|
||
return {
|
||
'id': self.id,
|
||
'phone': self.phone,
|
||
'name': self.name,
|
||
'password': self.password,
|
||
'gender': self.gender,
|
||
'created_at': self.created_at.strftime('%Y-%m-%d %H:%M:%S') if self.created_at else None
|
||
}
|
||
|
||
class Office(db.Model):
|
||
__tablename__ = 'office'
|
||
|
||
id = db.Column(db.Integer, primary_key=True, autoincrement=True, comment='科室ID')
|
||
name = db.Column(db.String(100), nullable=False, comment='科室名称')
|
||
parent_id = db.Column(db.Integer, db.ForeignKey('office.id', ondelete='CASCADE'), nullable=True, comment='上级科室ID')
|
||
hospital_id = db.Column(db.Integer, db.ForeignKey('hospital.id'), nullable=False, comment='所属医院ID')
|
||
created_at = db.Column(db.TIMESTAMP, default=datetime.now, comment='创建时间')
|
||
|
||
# 自引用关系,添加级联删除
|
||
parent = db.relationship('Office', remote_side=[id],
|
||
backref=db.backref('children', lazy='dynamic', cascade='all, delete-orphan'),
|
||
passive_deletes=True)
|
||
# 与医院的关系
|
||
hospital = db.relationship('Hospital', backref=db.backref('offices', lazy='dynamic'))
|
||
|
||
def to_dict(self):
|
||
return {
|
||
'id': self.id,
|
||
'name': self.name,
|
||
'parent_id': self.parent_id,
|
||
'hospital_id': self.hospital_id,
|
||
'created_at': self.created_at.strftime('%Y-%m-%d %H:%M:%S') if self.created_at else None
|
||
}
|
||
|
||
class DoctorOffice(db.Model):
|
||
__tablename__ = 'doctor_office'
|
||
|
||
id = db.Column(db.Integer, primary_key=True, autoincrement=True, comment='关联ID')
|
||
doc_id = db.Column(db.Integer, db.ForeignKey('doctor.id', ondelete='CASCADE'), nullable=False, comment='医生ID')
|
||
off_id = db.Column(db.Integer, db.ForeignKey('office.id', ondelete='CASCADE'), nullable=False, comment='科室ID')
|
||
created_at = db.Column(db.TIMESTAMP, default=datetime.now, comment='创建时间')
|
||
|
||
# 关系
|
||
doctor = db.relationship('Doctor', backref=db.backref('offices', lazy='dynamic', cascade='all, delete-orphan'))
|
||
office = db.relationship('Office', backref=db.backref('doctors', lazy='dynamic', cascade='all, delete-orphan'))
|
||
|
||
def to_dict(self):
|
||
return {
|
||
'id': self.id,
|
||
'doc_id': self.doc_id,
|
||
'off_id': self.off_id,
|
||
'created_at': self.created_at.strftime('%Y-%m-%d %H:%M:%S') if self.created_at else None
|
||
}
|
||
|
||
class DoctorHospital(db.Model):
|
||
__tablename__ = 'doctor_hospital'
|
||
|
||
id = db.Column(db.Integer, primary_key=True, autoincrement=True, comment='关联ID')
|
||
doc_id = db.Column(db.Integer, db.ForeignKey('doctor.id', ondelete='CASCADE'), nullable=False, comment='医生ID')
|
||
hosp_id = db.Column(db.Integer, db.ForeignKey('hospital.id'), nullable=False, comment='医院ID')
|
||
created_at = db.Column(db.TIMESTAMP, default=datetime.now, comment='创建时间')
|
||
|
||
# 关系
|
||
doctor = db.relationship('Doctor', backref=db.backref('hospitals', lazy='dynamic', cascade='all, delete-orphan'))
|
||
hospital = db.relationship('Hospital', backref=db.backref('doctors', lazy='dynamic'))
|
||
|
||
def to_dict(self):
|
||
return {
|
||
'id': self.id,
|
||
'doc_id': self.doc_id,
|
||
'hosp_id': self.hosp_id,
|
||
'created_at': self.created_at.strftime('%Y-%m-%d %H:%M:%S') if self.created_at else None
|
||
}
|
||
|
||
class Patient(db.Model):
|
||
__tablename__ = 'patient'
|
||
|
||
id = db.Column(db.Integer, primary_key=True, autoincrement=True, comment='病人ID')
|
||
name = db.Column(db.String(100), nullable=False, comment='病人姓名')
|
||
gender = db.Column(db.Enum('男', '女', '未知'), nullable=False, comment='病人性别')
|
||
birthday = db.Column(db.String(10), nullable=True, comment='出生日期,格式YYYY-MM-DD')
|
||
created_at = db.Column(db.TIMESTAMP, default=datetime.now, comment='创建时间')
|
||
|
||
def to_dict(self):
|
||
return {
|
||
'id': self.id,
|
||
'name': self.name,
|
||
'gender': self.gender,
|
||
'birthday': self.birthday,
|
||
'created_at': self.created_at.strftime('%Y-%m-%d %H:%M:%S') if self.created_at else None
|
||
}
|
||
|
||
class Case(db.Model):
|
||
__tablename__ = 'case'
|
||
|
||
id = db.Column(db.Integer, primary_key=True, autoincrement=True, comment='病历ID')
|
||
patient_id = db.Column(db.Integer, db.ForeignKey('patient.id', ondelete='CASCADE'), nullable=False, comment='病人ID')
|
||
office_id = db.Column(db.Integer, db.ForeignKey('office.id', ondelete='CASCADE'), nullable=False, comment='科室ID')
|
||
doctor_id = db.Column(db.Integer, db.ForeignKey('doctor.id', ondelete='CASCADE'), nullable=False, comment='医生ID')
|
||
case_date = db.Column(db.Date, nullable=False, comment='就诊日期')
|
||
chief_complaint = db.Column(db.Text, nullable=True, comment='主诉')
|
||
present_illness_history = db.Column(db.Text, nullable=True, comment='现病史')
|
||
past_medical_history = db.Column(db.Text, nullable=True, comment='既往史')
|
||
personal_history = db.Column(db.Text, nullable=True, comment='个人史')
|
||
family_history = db.Column(db.Text, nullable=True, comment='家族史')
|
||
physical_examination = db.Column(db.Text, nullable=True, comment='体格检查')
|
||
diagnosis = db.Column(db.Text, nullable=True, comment='诊断结果')
|
||
treatment_plan = db.Column(db.Text, nullable=True, comment='治疗方案')
|
||
medication_details = db.Column(db.Text, nullable=True, comment='用药详情')
|
||
notes = db.Column(db.Text, nullable=True, comment='备注')
|
||
created_at = db.Column(db.TIMESTAMP, default=datetime.now, comment='创建时间')
|
||
updated_at = db.Column(db.TIMESTAMP, default=datetime.now, onupdate=datetime.now, comment='更新时间')
|
||
|
||
# 关系
|
||
patient = db.relationship('Patient', backref=db.backref('cases', lazy='dynamic', cascade='all, delete-orphan'))
|
||
office = db.relationship('Office', backref=db.backref('cases', lazy='dynamic'))
|
||
doctor = db.relationship('Doctor', backref=db.backref('cases', lazy='dynamic'))
|
||
|
||
def to_dict(self):
|
||
return {
|
||
'id': self.id,
|
||
'patient_id': self.patient_id,
|
||
'office_id': self.office_id,
|
||
'doctor_id': self.doctor_id,
|
||
'case_date': self.case_date.strftime('%Y-%m-%d') if self.case_date else None,
|
||
'chief_complaint': self.chief_complaint,
|
||
'present_illness_history': self.present_illness_history,
|
||
'past_medical_history': self.past_medical_history,
|
||
'personal_history': self.personal_history,
|
||
'family_history': self.family_history,
|
||
'physical_examination': self.physical_examination,
|
||
'diagnosis': self.diagnosis,
|
||
'treatment_plan': self.treatment_plan,
|
||
'medication_details': self.medication_details,
|
||
'notes': self.notes,
|
||
'created_at': self.created_at.strftime('%Y-%m-%d %H:%M:%S') if self.created_at else None,
|
||
'updated_at': self.updated_at.strftime('%Y-%m-%d %H:%M:%S') if self.updated_at else None
|
||
}
|
||
|
||
class Image(db.Model):
|
||
__tablename__ = 'image'
|
||
|
||
id = db.Column(db.Integer, primary_key=True, autoincrement=True, comment='影像ID')
|
||
name = db.Column(db.String(255), nullable=True, comment='影像名称')
|
||
format = db.Column(db.Enum('dicom', 'nii', 'picture'), nullable=False, comment='影像格式')
|
||
type = db.Column(db.Enum('X-ray', 'CT', 'MRI', 'PET', 'US', '其他'), nullable=False, comment='影像类型')
|
||
dim = db.Column(db.Enum('2D', '3D'), nullable=False, default='2D', comment='影像维度')
|
||
patient_id = db.Column(db.Integer, db.ForeignKey('patient.id', ondelete='SET NULL'), nullable=True, comment='病人ID')
|
||
creator_id = db.Column(db.Integer, db.ForeignKey('doctor.id', ondelete='CASCADE'), nullable=False, comment='创建者ID (医生)')
|
||
office_id = db.Column(db.Integer, db.ForeignKey('office.id', ondelete='SET NULL'), nullable=True, comment='科室ID')
|
||
case_id = db.Column(db.Integer, db.ForeignKey('case.id', ondelete='SET NULL'), nullable=True, comment='病历ID')
|
||
note = db.Column(db.Text, nullable=True, comment='备注')
|
||
oss_key = db.Column(db.String(255), nullable=False, unique=True, comment='OSS对象存储键')
|
||
size = db.Column(db.Numeric(10, 2), nullable=False, comment='文件大小(KB)')
|
||
parent_image_id = db.Column(db.Integer, db.ForeignKey('image.id', ondelete='CASCADE'), nullable=True, comment='父影像ID (用于3D影像切片)')
|
||
slice_direction = db.Column(db.Enum('x', 'y', 'z'), nullable=True, comment='3D影像切片方向')
|
||
slice = db.Column(db.Integer, nullable=True, comment='3D影像切片索引')
|
||
slice_x = db.Column(db.Integer, nullable=True, comment='3D影像x方向切片数')
|
||
slice_y = db.Column(db.Integer, nullable=True, comment='3D影像y方向切片数')
|
||
slice_z = db.Column(db.Integer, nullable=True, comment='3D影像z方向切片数')
|
||
created_at = db.Column(db.TIMESTAMP, default=datetime.now, comment='创建时间')
|
||
|
||
# 关系
|
||
patient = db.relationship('Patient', backref=db.backref('images', lazy='dynamic'))
|
||
creator = db.relationship('Doctor', backref=db.backref('created_images', lazy='dynamic'))
|
||
office = db.relationship('Office', backref=db.backref('images', lazy='dynamic'))
|
||
case = db.relationship('Case', backref=db.backref('images', lazy='dynamic'))
|
||
parent_image = db.relationship('Image', remote_side=[id], backref=db.backref('child_images', lazy='dynamic', cascade='all, delete-orphan'))
|
||
|
||
def to_dict(self):
|
||
return {
|
||
'id': self.id,
|
||
'name': self.name,
|
||
'format': self.format,
|
||
'type': self.type,
|
||
'dim': self.dim,
|
||
'patient_id': self.patient_id,
|
||
'creator_id': self.creator_id,
|
||
'office_id': self.office_id,
|
||
'case_id': self.case_id,
|
||
'note': self.note,
|
||
'oss_key': self.oss_key,
|
||
'size': float(self.size) if self.size is not None else None,
|
||
'parent_image_id': self.parent_image_id,
|
||
'slice_direction': self.slice_direction,
|
||
'slice': self.slice,
|
||
'slice_x': self.slice_x,
|
||
'slice_y': self.slice_y,
|
||
'slice_z': self.slice_z,
|
||
'created_at': self.created_at.strftime('%Y-%m-%d %H:%M:%S') if self.created_at else None
|
||
}
|
||
|
||
class ImageBbox(db.Model):
|
||
__tablename__ = 'image_bbox'
|
||
|
||
id = db.Column(db.Integer, primary_key=True, autoincrement=True, comment='边界框标注ID')
|
||
image_id = db.Column(db.Integer, db.ForeignKey('image.id', ondelete='CASCADE'), nullable=False, comment='影像ID')
|
||
creator_id = db.Column(db.Integer, db.ForeignKey('doctor.id', ondelete='CASCADE'), nullable=False, comment='创建者ID (医生)')
|
||
up_left_x = db.Column(db.Integer, nullable=False, comment='左上角X坐标')
|
||
up_left_y = db.Column(db.Integer, nullable=False, comment='左上角Y坐标')
|
||
bottom_right_x = db.Column(db.Integer, nullable=False, comment='右下角X坐标')
|
||
bottom_right_y = db.Column(db.Integer, nullable=False, comment='右下角Y坐标')
|
||
note = db.Column(db.Text, nullable=True, comment='备注')
|
||
created_at = db.Column(db.TIMESTAMP, default=datetime.now, comment='创建时间')
|
||
|
||
# 关系
|
||
image = db.relationship('Image', backref=db.backref('bboxes', lazy='dynamic', cascade='all, delete-orphan'))
|
||
creator = db.relationship('Doctor', backref=db.backref('created_bboxes', lazy='dynamic'))
|
||
|
||
def to_dict(self):
|
||
return {
|
||
'id': self.id,
|
||
'image_id': self.image_id,
|
||
'creator_id': self.creator_id,
|
||
'up_left_x': self.up_left_x,
|
||
'up_left_y': self.up_left_y,
|
||
'bottom_right_x': self.bottom_right_x,
|
||
'bottom_right_y': self.bottom_right_y,
|
||
'note': self.note,
|
||
'created_at': self.created_at.strftime('%Y-%m-%d %H:%M:%S') if self.created_at else None
|
||
}
|
||
|
||
class ImageMask(db.Model):
|
||
__tablename__ = 'image_mask'
|
||
|
||
id = db.Column(db.Integer, primary_key=True, autoincrement=True, comment='掩码标注ID')
|
||
image_id = db.Column(db.Integer, db.ForeignKey('image.id', ondelete='CASCADE'), nullable=False, comment='影像ID')
|
||
creator_id = db.Column(db.Integer, db.ForeignKey('doctor.id', ondelete='CASCADE'), nullable=False, comment='创建者ID (医生)')
|
||
mask_oss_key = db.Column(db.String(255), nullable=False, unique=True, comment='掩码文件OSS键')
|
||
note = db.Column(db.Text, nullable=True, comment='备注')
|
||
created_at = db.Column(db.TIMESTAMP, default=datetime.now, comment='创建时间')
|
||
|
||
# 关系
|
||
image = db.relationship('Image', backref=db.backref('masks', lazy='dynamic', cascade='all, delete-orphan'))
|
||
creator = db.relationship('Doctor', backref=db.backref('created_masks', lazy='dynamic'))
|
||
|
||
def to_dict(self):
|
||
return {
|
||
'id': self.id,
|
||
'image_id': self.image_id,
|
||
'creator_id': self.creator_id,
|
||
'mask_oss_key': self.mask_oss_key,
|
||
'note': self.note,
|
||
'created_at': self.created_at.strftime('%Y-%m-%d %H:%M:%S') if self.created_at else None
|
||
}
|