医疗体检管理系统是医疗机构数字化转型的重要基础设施。这个基于Flask框架开发的系统,主要解决传统体检流程中的三大痛点:纸质档案管理混乱、预约排队效率低下、报告查询周期过长。系统面向三类用户群体:体检者(C端用户)、医护人员(B端用户)和机构管理者(Admin),采用模块化设计满足不同角色的差异化需求。
在技术选型上,Python+Flask的组合具有快速迭代优势,特别适合中小型医疗机构的数字化改造。我曾参与过某三甲医院体检中心系统升级项目,发现Flask的轻量级特性使其在医疗场景中展现出独特优势——既不需要像Django那样"全家桶"式部署,又能通过扩展灵活应对医疗行业特有的复杂业务流程。
采用改良版MVC模式,具体分层如下:
python复制# 典型的多模块工厂模式示例
def create_app(config_name):
app = Flask(__name__)
app.config.from_object(config[config_name])
# 初始化各模块
from .auth import auth_bp
from .exam import exam_bp
app.register_blueprint(auth_bp)
app.register_blueprint(exam_bp)
# 数据库初始化
db.init_app(app)
return app
数据库对比选择:
| 特性 | MySQL | PostgreSQL | SQLite |
|---|---|---|---|
| 并发性能 | 优 | 极优 | 差 |
| 医疗数据支持 | 基础ACID | JSONB+GIS | 仅基础功能 |
| 部署复杂度 | 中等 | 较高 | 极简 |
最终选择MySQL 8.0的原因:
安全组件配置:
python复制# 安全配置示例
app.config.update(
SECRET_KEY=os.urandom(32),
SESSION_COOKIE_HTTPONLY=True,
REMEMBER_COOKIE_HTTPONLY=True,
SESSION_COOKIE_SAMESITE='Lax',
PERMANENT_SESSION_LIFETIME=timedelta(minutes=30)
)
体检预约的核心难点在于资源冲突检测,我们设计了基于时间窗的冲突检测算法:
python复制def check_time_slot(doctor_id, start_time, duration):
existing = Appointment.query.filter(
Appointment.doctor_id == doctor_id,
Appointment.status != 'cancelled',
func.TIMESTAMPDIFF(MINUTE, Appointment.start_time, start_time) < duration,
func.TIMESTAMPDIFF(MINUTE, start_time, Appointment.end_time) > 0
).count()
return existing == 0
实际项目中还需要考虑:
报告处理采用生产者-消费者模式:
python复制@app.route('/upload', methods=['POST'])
@login_required
def upload_report():
if 'file' not in request.files:
abort(400)
file = request.files['file']
if file.filename == '':
abort(400)
# 生成文件指纹
file_hash = hashlib.md5(file.read()).hexdigest()
file.seek(0)
# 保存到临时存储
temp_path = os.path.join(current_app.config['UPLOAD_FOLDER'], file_hash)
file.save(temp_path)
# 异步任务处理
process_report.delay(
file_path=temp_path,
user_id=current_user.id,
original_name=file.filename
)
return jsonify({"status": "processing"})
采用分层加密策略:
python复制# 字段加密示例
class User(db.Model):
__tablename__ = 'users'
id = db.Column(db.Integer, primary_key=True)
_id_card = db.Column('id_card', db.LargeBinary, nullable=False)
@property
def id_card(self):
return decrypt(self._id_card)
@id_card.setter
def id_card(self, value):
self._id_card = encrypt(value)
满足医疗行业等保要求:
python复制def log_operation(action, detail=None):
record = OperationLog(
user_id=current_user.id if current_user.is_authenticated else None,
ip_address=request.remote_addr,
user_agent=str(request.user_agent),
action=action,
detail=detail or {},
timestamp=datetime.utcnow()
)
db.session.add(record)
db.session.commit()
关键审计项包括:
医疗系统典型慢查询解决方案:
体检结果分页查询优化:
python复制# 反模式 - 全量查询后分页
reports = Report.query.filter_by(user_id=uid).all()[offset:offset+limit]
# 优化方案 - 数据库层分页
reports = Report.query.filter_by(user_id=uid).order_by(
Report.exam_date.desc()
).paginate(page=page, per_page=per_page)
建立复合索引策略:
sql复制CREATE INDEX idx_exam_composite ON examination_records
(user_id, exam_date DESC, is_abnormal);
采用三级缓存体系:
热点数据:Redis缓存
python复制def get_user_reports(user_id):
cache_key = f"reports:{user_id}"
data = redis.get(cache_key)
if data is None:
data = db.query(...).all()
redis.setex(cache_key, timedelta(hours=1), pickle.dumps(data))
else:
data = pickle.loads(data)
return data
静态资源:CDN加速
列表数据:Memcached集群
生产环境推荐架构:
code复制 +-----------------+
| 阿里云SLB |
+--------+--------+
|
+----------------+-----------------+
| | |
+-----+------+ +-----+------+ +------+-----+
| Gunicorn | | Gunicorn | | Gunicorn |
| Worker*4 | | Worker*4 | | Worker*4 |
+-----+------+ +-----+------+ +------+-----+
| | |
+-----+------+ +-----+------+ +------+-----+
| Redis | | MySQL | | 备份节点 |
| 哨兵集群 | | 主从复制 | | (异地容灾) |
+------------+ +------------+ +------------+
配置Prometheus监控项:
yaml复制- job_name: 'flask_app'
metrics_path: '/metrics'
static_configs:
- targets: ['app1:5000', 'app2:5000']
# 关键指标
metric_relabel_configs:
- source_labels: [__name__]
regex: '(flask_http_request_duration_seconds|flask_exceptions_total|process_resident_memory_bytes)'
action: keep
报警阈值设置:
某次项目中使用Pillow处理DR片时遇到的坑:
16位灰度图像默认会被转为8位
python复制# 错误做法
Image.open('xray.dcm').save('output.jpg')
# 正确做法
image = Image.open('xray.dcm')
image.mode = 'I;16' # 显式指定16位模式
DICOM文件需要特殊处理:
python复制import pydicom
ds = pydicom.dcmread("CT.dcm")
plt.imshow(ds.pixel_array, cmap=plt.cm.bone)
医疗记录必须保证时间准确:
python复制# 配置时区
class Config:
TIMEZONE = 'Asia/Shanghai'
SQLALCHEMY_DATABASE_URI = f"mysql+pymysql://...?timezone=+8:00"
# 时间处理工具函数
def make_aware(dt):
return dt.replace(tzinfo=timezone.utc).astimezone(
timezone(Config.TIMEZONE))
关键原则:
基于现有体检数据的扩展应用:
异常指标趋势预测
python复制from sklearn.ensemble import IsolationForest
clf = IsolationForest(n_estimators=100)
clf.fit(exam_data)
anomalies = clf.predict(new_data)
体检套餐个性化推荐
python复制# 协同过滤算法
from surprise import KNNBasic
algo = KNNBasic()
algo.fit(trainset)
predictions = algo.test(testset)
混合开发建议架构:
code复制Flask REST API
↑
↓ HTTPS
API Gateway
↑
↓
移动端SDK (封装以下能力):
- 扫码登录
- 报告缓存
- 推送服务
- 生物认证
关键集成点: