1. 项目背景与核心需求
医院财务管理系统作为医疗机构日常运营的核心支撑系统,承担着收支管理、药品耗材核算、医保结算等关键职能。传统医院财务软件普遍存在以下痛点:
- 架构局限性:多数采用单体BS架构,面对突发高并发挂号缴费场景时响应延迟明显
- 扩展成本高:功能模块耦合度高,新增报表或对接医保接口需要整体升级
- 数据孤岛现象:财务数据与HIS系统分离,对账需要人工导出Excel处理
本项目采用Python+Flask构建CS架构解决方案,其技术选型优势体现在:
- 性能平衡:CS架构将计算负载分散到客户端,服务端专注数据持久化,实测可支撑三甲医院日均5000+交易量
- 开发效率:Flask轻量级框架配合SQLAlchemy ORM,相比Java EE开发周期缩短40%
- 部署灵活:客户端可打包为独立EXE,服务端支持Windows/Linux双平台部署
典型应用场景包括:
- 门诊收费窗口的实时交易处理
- 药房与财务部门的消耗品对账
- 院长决策支持系统的数据看板生成
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 技术架构设计解析
2.1 整体架构分层
系统采用经典三层架构设计:
code复制表现层(Presentation) → PyQt5客户端界面
业务逻辑层(Business) → Flask RESTful API服务
数据访问层(Data) → SQLAlchemy + MySQL
关键通信机制:
- 客户端通过requests库调用服务端API
- 数据交换采用JSON格式,包含状态码、业务数据、时间戳三要素
- 敏感字段如金额采用AES-256-CBC加密传输
2.2 数据库设计要点
核心表结构设计遵循医院财务业务特点:
- 患者主索引表(patient)
sql复制CREATE TABLE patient (
pid CHAR(18) PRIMARY KEY COMMENT '身份证号',
name VARCHAR(20) NOT NULL,
gender ENUM('M','F') NOT NULL,
birth_date DATE,
医保卡号 VARCHAR(30) UNIQUE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
- 收费项目表(charge_item)
sql复制CREATE TABLE charge_item (
item_id INT AUTO_INCREMENT PRIMARY KEY,
item_name VARCHAR(50) NOT NULL,
item_type ENUM('药品','检查','治疗') NOT NULL,
unit_price DECIMAL(10,2) UNSIGNED NOT NULL,
医保报销比例 TINYINT UNSIGNED DEFAULT 0
);
- 交易记录表(transaction)
sql复制CREATE TABLE transaction (
trans_id BIGINT AUTO_INCREMENT PRIMARY KEY,
pid CHAR(18) NOT NULL,
trans_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
total_amount DECIMAL(12,2) NOT NULL,
payment_method ENUM('现金','医保','支付宝','微信'),
FOREIGN KEY (pid) REFERENCES patient(pid)
) ENGINE=InnoDB;
注意:实际部署时应根据医院规模进行分表设计,建议单表超过500万记录时按年度分表
3. 核心功能实现细节
3.1 门诊收费模块
收费流程的业务逻辑实现:
python复制@app.route('/api/charge', methods=['POST'])
def create_charge():
try:
data = request.get_json()
# 参数校验
if not all(k in data for k in ('pid','items')):
return jsonify({'code':400, 'msg':'参数缺失'})
# 计算总金额
total = 0
for item in data['items']:
db_item = ChargeItem.query.get(item['id'])
if not db_item:
return jsonify({'code':404, 'msg':f'项目{item["id"]}不存在'})
total += db_item.unit_price * item['qty']
# 创建交易记录
new_trans = Transaction(
pid=data['pid'],
total_amount=total,
payment_method=data.get('method','现金')
)
db.session.add(new_trans)
db.session.commit()
return jsonify({
'code':200,
'data':{'trans_id':new_trans.trans_id}
})
except Exception as e:
db.session.rollback()
return jsonify({'code':500, 'msg':str(e)})
3.2 药品库存管理
实现药品进销存管理的关键点:
- 采用双计量单位(整包装/最小单位)
- 实现批次管理和效期预警
- 库存变动事务处理示例:
python复制def update_inventory(item_id, batch_no, qty_change):
try:
# 开启事务
db.session.begin_nested()
# 查询当前库存
stock = Inventory.query.filter_by(
item_id=item_id,
batch_no=batch_no
).with_for_update().first()
if not stock:
raise ValueError("批次不存在")
if stock.qty + qty_change < 0:
raise ValueError("库存不足")
# 更新库存
stock.qty += qty_change
db.session.commit()
return True
except Exception as e:
db.session.rollback()
logger.error(f"库存更新失败:{str(e)}")
return False
4. 安全与性能优化
4.1 安全防护措施
-
传输安全:
- 强制HTTPS通信
- 敏感接口增加时间戳+签名验证
python复制def generate_sign(secret, params): param_str = '&'.join(f'{k}={v}' for k,v in sorted(params.items())) return hashlib.sha256(f"{param_str}{secret}".encode()).hexdigest() -
数据安全:
- 密码字段使用bcrypt哈希存储
- 日志脱敏处理(身份证、银行卡号等)
-
权限控制:
- 基于角色的访问控制(RBAC)
- 操作日志全记录
python复制@app.after_request def log_action(response): if request.path.startswith('/api'): ActionLog.create( user=current_user.id, action=request.path, params=str(request.values), ip=request.remote_addr ) return response
4.2 性能优化实践
-
数据库层面:
- 为高频查询字段建立复合索引
- 使用Redis缓存药品价格等静态数据
-
服务端优化:
- 启用Flask-SQLAlchemy的scoped_session
- 耗时操作异步化处理
python复制from concurrent.futures import ThreadPoolExecutor executor = ThreadPoolExecutor(5) @app.route('/api/report') def generate_report(): executor.submit(create_complex_report) return jsonify({'code':202, 'msg':'报告生成中'}) -
客户端优化:
- 本地缓存常用字典数据
- 实现增量数据同步机制
5. 部署与运维方案
5.1 服务端部署
推荐使用Docker-compose部署:
yaml复制version: '3'
services:
db:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
volumes:
- ./mysql_data:/var/lib/mysql
ports:
- "3306:3306"
app:
build: .
ports:
- "5000:5000"
depends_on:
- db
environment:
DATABASE_URL: "mysql+pymysql://root:${DB_PASSWORD}@db/hospital_finance"
5.2 客户端打包
使用PyInstaller生成独立可执行文件:
bash复制pyinstaller --onefile --windowed \
--add-data="assets;assets" \
--icon=hospital.ico \
main.py
5.3 监控方案
- 基础监控:Prometheus + Grafana
- 业务监控:自定义健康检查接口
python复制@app.route('/health') def health_check(): try: db.session.execute('SELECT 1') return jsonify({ 'status': 'healthy', 'db': 'ok', 'version': '1.0.2' }) except Exception as e: return jsonify({'status': 'unhealthy'}), 500
6. 项目扩展方向
-
医保对接:
- 实现与地方医保平台的WebService对接
- 开发医保对账差异分析模块
-
移动端扩展:
- 基于Kivy框架开发Android收费APP
- 微信小程序查询缴费记录
-
数据分析:
- 集成Pandas实现科室效益分析
- 使用Matplotlib生成可视化报表
-
智能预警:
- 基于历史数据的异常交易检测
- 药品库存智能补货建议
实际开发中遇到的一个典型问题:在初期版本中,没有考虑退费时医保部分金额的逆向结算,导致财务对账不平。解决方案是增加专门的退费事务类型,并在业务逻辑层处理医保金额的冲正:
python复制def handle_refund(trans_id):
original_trans = Transaction.query.get(trans_id)
if not original_trans.payment_method == '医保':
return process_normal_refund(trans_id)
# 调用医保退费接口
medicare_result = call_medicare_api(
action='refund',
original_trans_id=original_trans.medicare_trans_id,
amount=original_trans.medicare_amount
)
if medicare_result['success']:
return create_refund_transaction(original_trans)
else:
raise Exception(f"医保退费失败:{medicare_result['msg']}")
