智慧医疗大数据可视化系统构建实战:打造现代化医疗数据分析平台(一)

摘要

随着医疗信息化的深入发展,医疗大数据的价值日益凸显。本文将深入探讨如何构建一个专业的智慧医疗大数据可视化系统,涵盖医疗数据采集、患者分析、趋势预测、慢病管理等核心功能。通过实际案例分析和完整的代码实现,帮助开发者掌握医疗领域数据可视化的关键技术和最佳实践,为医疗机构的数字化转型提供技术支撑。

关键词: 智慧医疗、医疗大数据、数据可视化、患者分析、慢病管理


目录

  1. 引言
  2. 智慧医疗可视化系统概述
  3. 系统架构设计
  4. 医疗数据采集与处理
  5. 患者数据可视化分析
  6. 医疗指标监控系统
  7. 慢病管理可视化模块
  8. 地理信息系统集成
  9. 实时数据处理与预警
  10. 用户界面设计与交互
  11. 数据安全与隐私保护
  12. 性能优化与扩展性
  13. 部署与运维
  14. 总结与展望

1. 引言

在数字化医疗时代,医疗机构每天产生海量的数据,包括患者信息、诊疗记录、检验结果、影像数据等。如何有效地分析和利用这些数据,为医疗决策提供支持,成为现代医疗管理的重要课题。

1.1 医疗大数据的挑战

现代医疗机构在数据管理和分析中面临以下主要挑战:

医疗大数据挑战
数据复杂性
实时性要求
隐私保护
决策支持
多源异构数据
数据质量控制
标准化问题
实时监控需求
快速诊断支持
紧急预警
患者隐私保护
数据脱敏处理
合规性要求
临床决策支持
资源配置优化
质量管理提升

1.2 可视化解决方案的价值

医疗大数据可视化在现代医疗管理中的核心价值:

  • 直观展示:将复杂的医疗数据转化为易理解的图表
  • 趋势分析:识别疾病流行趋势和患者健康变化
  • 资源优化:优化医疗资源配置和床位管理
  • 质量监控:实时监控医疗服务质量指标
  • 决策支持:为临床决策和管理决策提供数据支撑

2. 智慧医疗可视化系统概述

2.1 系统功能架构

# 智慧医疗大数据可视化系统
class MedicalDataVisualizationSystem:
    """智慧医疗大数据可视化系统"""
    
    def __init__(self):
        self.modules = self.define_system_modules()
        self.data_sources = self.define_data_sources()
        self.indicators = self.define_medical_indicators()
        self.patient_categories = self.define_patient_categories()
    
    def define_system_modules(self):
        """定义系统功能模块"""
        return {
            "数据采集概况": {
                "描述": "医疗数据采集和统计概览",
                "功能": [
                    "数据采集量统计",
                    "门诊住院人数统计",
                    "各医院数据对比",
                    "实时数据监控"
                ],
                "技术要点": [
                    "多源数据整合",
                    "实时数据更新",
                    "统计图表展示",
                    "地理信息展示"
                ]
            },
            "指标分析": {
                "描述": "医疗质量指标分析和监控",
                "功能": [
                    "医疗质量指标监控",
                    "服务效率分析",
                    "成本效益分析",
                    "同行对比分析"
                ],
                "技术要点": [
                    "指标体系设计",
                    "多维度分析",
                    "趋势预测算法",
                    "异常检测机制"
                ]
            },
            "趋势分析": {
                "描述": "医疗数据趋势分析和预测",
                "功能": [
                    "疾病流行趋势分析",
                    "患者流量预测",
                    "季节性变化分析",
                    "长期趋势预测"
                ],
                "技术要点": [
                    "时间序列分析",
                    "机器学习预测",
                    "统计学方法",
                    "可视化展示"
                ]
            },
            "慢病管理": {
                "描述": "慢性病患者管理和监控",
                "功能": [
                    "慢病患者列表管理",
                    "病情进展跟踪",
                    "用药依从性监控",
                    "健康指标预警"
                ],
                "技术要点": [
                    "患者档案管理",
                    "健康数据追踪",
                    "预警机制设计",
                    "个性化分析"
                ]
            }
        }
    
    def define_data_sources(self):
        """定义数据源"""
        return {
            "HIS系统": {
                "描述": "医院信息系统",
                "数据类型": [
                    "患者基本信息",
                    "门诊记录",
                    "住院记录",
                    "医嘱信息"
                ],
                "更新频率": "实时",
                "数据格式": "结构化数据"
            },
            "LIS系统": {
                "描述": "实验室信息系统",
                "数据类型": [
                    "检验结果",
                    "检验项目",
                    "标本信息",
                    "质控数据"
                ],
                "更新频率": "实时",
                "数据格式": "结构化数据"
            },
            "PACS系统": {
                "描述": "影像归档和通信系统",
                "数据类型": [
                    "医学影像",
                    "影像报告",
                    "检查记录",
                    "设备信息"
                ],
                "更新频率": "实时",
                "数据格式": "非结构化数据"
            },
            "EMR系统": {
                "描述": "电子病历系统",
                "数据类型": [
                    "病历记录",
                    "诊断信息",
                    "治疗方案",
                    "护理记录"
                ],
                "更新频率": "实时",
                "数据格式": "半结构化数据"
            },
            "外部数据": {
                "描述": "外部医疗数据源",
                "数据类型": [
                    "公共卫生数据",
                    "疾控中心数据",
                    "医保数据",
                    "药品信息"
                ],
                "更新频率": "定期",
                "数据格式": "多种格式"
            }
        }
    
    def define_medical_indicators(self):
        """定义医疗指标体系"""
        return {
            "医疗质量指标": {
                "患者安全指标": {
                    "院内感染率": {
                        "计算公式": "院内感染人数 / 住院总人数 × 100%",
                        "目标值": "< 3%",
                        "监控频率": "日",
                        "权重": 0.3
                    },
                    "药物不良反应率": {
                        "计算公式": "药物不良反应人数 / 用药总人数 × 100%",
                        "目标值": "< 1%",
                        "监控频率": "日",
                        "权重": 0.2
                    },
                    "手术并发症率": {
                        "计算公式": "手术并发症人数 / 手术总人数 × 100%",
                        "目标值": "< 2%",
                        "监控频率": "日",
                        "权重": 0.25
                    }
                },
                "医疗效率指标": {
                    "平均住院日": {
                        "计算公式": "总住院天数 / 出院人数",
                        "目标值": "< 10天",
                        "监控频率": "日",
                        "权重": 0.2
                    },
                    "床位使用率": {
                        "计算公式": "实际占用床日数 / 开放床日数 × 100%",
                        "目标值": "85%-95%",
                        "监控频率": "日",
                        "权重": 0.15
                    },
                    "门诊预约率": {
                        "计算公式": "预约门诊人数 / 门诊总人数 × 100%",
                        "目标值": "> 80%",
                        "监控频率": "日",
                        "权重": 0.1
                    }
                }
            },
            "服务质量指标": {
                "患者满意度": {
                    "门诊满意度": {
                        "计算公式": "满意患者数 / 调查患者数 × 100%",
                        "目标值": "> 90%",
                        "监控频率": "月",
                        "权重": 0.3
                    },
                    "住院满意度": {
                        "计算公式": "满意患者数 / 调查患者数 × 100%",
                        "目标值": "> 95%",
                        "监控频率": "月",
                        "权重": 0.3
                    }
                },
                "服务效率": {
                    "平均候诊时间": {
                        "计算公式": "总候诊时间 / 门诊人数",
                        "目标值": "< 30分钟",
                        "监控频率": "日",
                        "权重": 0.2
                    },
                    "检查报告及时率": {
                        "计算公式": "及时出具报告数 / 检查总数 × 100%",
                        "目标值": "> 95%",
                        "监控频率": "日",
                        "权重": 0.2
                    }
                }
            },
            "经济效益指标": {
                "成本控制": {
                    "人均医疗费用": {
                        "计算公式": "总医疗费用 / 患者总数",
                        "目标值": "合理区间",
                        "监控频率": "月",
                        "权重": 0.25
                    },
                    "药占比": {
                        "计算公式": "药品费用 / 医疗总费用 × 100%",
                        "目标值": "< 30%",
                        "监控频率": "月",
                        "权重": 0.25
                    }
                },
                "收益指标": {
                    "医疗收入增长率": {
                        "计算公式": "(本期收入-上期收入) / 上期收入 × 100%",
                        "目标值": "> 5%",
                        "监控频率": "月",
                        "权重": 0.25
                    },
                    "医疗服务收入占比": {
                        "计算公式": "医疗服务收入 / 总收入 × 100%",
                        "目标值": "> 60%",
                        "监控频率": "月",
                        "权重": 0.25
                    }
                }
            }
        }
    
    def define_patient_categories(self):
        """定义患者分类"""
        return {
            "年龄分组": {
                "儿童": "0-14岁",
                "青少年": "15-24岁",
                "青年": "25-44岁",
                "中年": "45-64岁",
                "老年": "65岁以上"
            },
            "疾病分类": {
                "慢性病": [
                    "高血压",
                    "糖尿病",
                    "冠心病",
                    "慢性肾病",
                    "慢性阻塞性肺病"
                ],
                "急性病": [
                    "急性心梗",
                    "急性脑卒中",
                    "急性胰腺炎",
                    "急性阑尾炎"
                ],
                "肿瘤": [
                    "肺癌",
                    "胃癌",
                    "肝癌",
                    "乳腺癌",
                    "结直肠癌"
                ]
            },
            "就诊类型": {
                "门诊": "门诊患者",
                "急诊": "急诊患者",
                "住院": "住院患者",
                "体检": "健康体检"
            },
            "风险等级": {
                "低风险": "健康状况良好",
                "中风险": "存在健康隐患",
                "高风险": "需要重点关注",
                "极高风险": "需要紧急处理"
            }
        }
    
    def calculate_medical_quality_score(self, hospital_data):
        """计算医疗质量评分"""
        total_score = 0
        total_weight = 0
        
        for category, indicators in self.indicators.items():
            for subcategory, sub_indicators in indicators.items():
                for indicator_name, indicator_info in sub_indicators.items():
                    if indicator_name in hospital_data:
                        value = hospital_data[indicator_name]
                        score = self.evaluate_medical_indicator(value, indicator_info)
                        weight = indicator_info['权重']
                        
                        total_score += score * weight
                        total_weight += weight
        
        if total_weight > 0:
            final_score = total_score / total_weight * 100
            return min(100, max(0, final_score))
        
        return 0
    
    def evaluate_medical_indicator(self, value, indicator_info):
        """评估医疗指标"""
        target_value = indicator_info['目标值']
        
        # 简化的评估逻辑,实际应用中需要更复杂的算法
        if self.meets_target(value, target_value):
            return 95
        else:
            # 根据偏离程度计算得分
            return max(60, 95 - abs(self.calculate_deviation(value, target_value)) * 10)
    
    def meets_target(self, value, target_str):
        """检查是否达到目标值"""
        # 简化的目标检查逻辑
        if '<' in target_str:
            threshold = float(target_str.replace('<', '').replace('%', '').strip())
            return value < threshold
        elif '>' in target_str:
            threshold = float(target_str.replace('>', '').replace('%', '').strip())
            return value > threshold
        elif '-' in target_str:
            parts = target_str.replace('%', '').split('-')
            min_val = float(parts[0].strip())
            max_val = float(parts[1].strip())
            return min_val <= value <= max_val
        
        return True
    
    def calculate_deviation(self, value, target_str):
        """计算偏离程度"""
        # 简化的偏离计算逻辑
        if '<' in target_str:
            threshold = float(target_str.replace('<', '').replace('%', '').strip())
            return max(0, value - threshold) / threshold
        elif '>' in target_str:
            threshold = float(target_str.replace('>', '').replace('%', '').strip())
            return max(0, threshold - value) / threshold
        
        return 0
    
    def generate_medical_report(self, hospital_data):
        """生成医疗质量报告"""
        quality_score = self.calculate_medical_quality_score(hospital_data)
        
        return {
            "医院名称": hospital_data.get("name", "未知医院"),
            "评估时间": "2024-07-20",
            "综合评分": quality_score,
            "质量等级": self.get_quality_level(quality_score),
            "关键指标": self.analyze_key_indicators(hospital_data),
            "改进建议": self.generate_improvement_suggestions(hospital_data),
            "风险预警": self.identify_risk_alerts(hospital_data)
        }
    
    def get_quality_level(self, score):
        """获取质量等级"""
        if score >= 90:
            return "优秀"
        elif score >= 80:
            return "良好"
        elif score >= 70:
            return "合格"
        else:
            return "需要改进"
    
    def analyze_key_indicators(self, hospital_data):
        """分析关键指标"""
        key_indicators = {}
        
        # 分析关键医疗指标
        if "院内感染率" in hospital_data:
            key_indicators["患者安全"] = {
                "院内感染率": f"{hospital_data['院内感染率']:.2f}%",
                "状态": "正常" if hospital_data['院内感染率'] < 3 else "需关注"
            }
        
        if "平均住院日" in hospital_data:
            key_indicators["医疗效率"] = {
                "平均住院日": f"{hospital_data['平均住院日']:.1f}天",
                "状态": "正常" if hospital_data['平均住院日'] < 10 else "需优化"
            }
        
        return key_indicators
    
    def generate_improvement_suggestions(self, hospital_data):
        """生成改进建议"""
        suggestions = []
        
        if hospital_data.get("院内感染率", 0) > 3:
            suggestions.append("加强院内感染控制措施,提高手卫生依从性")
        
        if hospital_data.get("平均住院日", 0) > 10:
            suggestions.append("优化诊疗流程,缩短平均住院日")
        
        if hospital_data.get("药占比", 0) > 30:
            suggestions.append("合理用药,控制药占比在合理范围内")
        
        if not suggestions:
            suggestions.append("继续保持良好的医疗质量管理水平")
        
        return suggestions
    
    def identify_risk_alerts(self, hospital_data):
        """识别风险预警"""
        alerts = []
        
        if hospital_data.get("药物不良反应率", 0) > 1:
            alerts.append({
                "级别": "高风险",
                "内容": "药物不良反应率超标",
                "建议": "立即审查用药安全管理制度"
            })
        
        if hospital_data.get("手术并发症率", 0) > 2:
            alerts.append({
                "级别": "中风险",
                "内容": "手术并发症率偏高",
                "建议": "加强手术质量管理和术前评估"
            })
        
        return alerts
    
    def print_system_overview(self):
        """打印系统概述"""
        print("=== 智慧医疗大数据可视化系统概述 ===\n")
        
        print("🏥 系统功能模块:")
        for module_name, module_info in self.modules.items():
            print(f"\n🔹 {module_name}")
            print(f"   描述: {module_info['描述']}")
            print(f"   主要功能:")
            for func in module_info['功能']:
                print(f"     • {func}")
            print(f"   技术要点:")
            for tech in module_info['技术要点']:
                print(f"     ◦ {tech}")
        
        print(f"\n📊 数据源:")
        for source_name, source_info in self.data_sources.items():
            print(f"\n🔸 {source_name}")
            print(f"   描述: {source_info['描述']}")
            print(f"   数据类型: {', '.join(source_info['数据类型'])}")
            print(f"   更新频率: {source_info['更新频率']}")
        
        print(f"\n📈 医疗指标体系:")
        for category, indicators in self.indicators.items():
            print(f"\n🔸 {category}:")
            for subcategory, sub_indicators in indicators.items():
                print(f"   • {subcategory}:")
                for indicator in sub_indicators.keys():
                    print(f"     - {indicator}")

# 创建系统实例并展示概述
medical_system = MedicalDataVisualizationSystem()
medical_system.print_system_overview()

# 示例:医疗质量评估
sample_hospital = {
    "name": "第一人民医院",
    "院内感染率": 2.5,
    "药物不良反应率": 0.8,
    "手术并发症率": 1.5,
    "平均住院日": 8.5,
    "床位使用率": 88.0,
    "药占比": 28.5
}

report = medical_system.generate_medical_report(sample_hospital)
print(f"\n📋 医疗质量评估报告:")
print(f"   医院名称: {report['医院名称']}")
print(f"   综合评分: {report['综合评分']:.2f}")
print(f"   质量等级: {report['质量等级']}")
print(f"   改进建议: {', '.join(report['改进建议'])}")

2.2 系统特点与优势

特点描述业务价值
多源数据整合整合HIS、LIS、PACS等多个系统数据提供全面的医疗数据视图
实时监控7×24小时实时监控医疗指标及时发现异常,提高响应速度
智能分析基于AI的数据分析和预测提供智能决策支持
个性化展示根据用户角色定制化展示提高信息利用效率
移动端支持支持移动设备访问随时随地查看医疗数据

3. 系统架构设计

3.1 技术架构

数据存储层
数据服务层
业务逻辑层
前端展示层
HIS数据库
LIS数据库
PACS存储
数据仓库
实时数据库
数据接口服务
数据清洗服务
数据同步服务
缓存服务
数据分析引擎
指标计算服务
预警服务
报告生成服务
医生工作站
管理驾驶舱
移动端应用
大屏展示

3.2 数据流架构

数据应用
数据存储
数据处理
数据采集
数据源
实时监控
统计分析
预测分析
报告生成
操作数据库
数据仓库
数据湖
数据清洗
数据转换
数据标准化
数据质量控制
实时采集
批量采集
API接口
HIS系统
LIS系统
PACS系统
EMR系统

4. 医疗数据采集与处理

4.1 数据采集模块

# 医疗数据采集与处理系统
import json
import datetime
from typing import Dict, List, Any
import pandas as pd
import numpy as np

class MedicalDataCollector:
    """医疗数据采集器"""
    
    def __init__(self):
        self.data_sources = self.initialize_data_sources()
        self.collection_rules = self.define_collection_rules()
        self.data_quality_rules = self.define_quality_rules()
    
    def initialize_data_sources(self):
        """初始化数据源配置"""
        return {
            "HIS": {
                "connection_type": "database",
                "host": "his.hospital.com",
                "port": 1521,
                "database": "HIS_DB",
                "tables": [
                    "patients",           # 患者信息表
                    "admissions",         # 入院记录表
                    "discharges",         # 出院记录表
                    "outpatient_visits",  # 门诊记录表
                    "medical_orders",     # 医嘱表
                    "medications",        # 用药记录表
                    "procedures",         # 手术记录表
                    "diagnoses"          # 诊断记录表
                ],
                "update_frequency": "real-time",
                "data_retention": "7_years"
            },
            "LIS": {
                "connection_type": "api",
                "endpoint": "https://lis.hospital.com/api/v1",
                "authentication": "oauth2",
                "data_types": [
                    "lab_results",        # 检验结果
                    "lab_orders",         # 检验申请
                    "specimens",          # 标本信息
                    "reference_ranges",   # 参考范围
                    "quality_control"     # 质控数据
                ],
                "update_frequency": "real-time",
                "data_retention": "5_years"
            },
            "PACS": {
                "connection_type": "dicom",
                "server": "pacs.hospital.com",
                "port": 11112,
                "data_types": [
                    "medical_images",     # 医学影像
                    "image_reports",      # 影像报告
                    "study_metadata",     # 检查元数据
                    "series_metadata"     # 序列元数据
                ],
                "update_frequency": "real-time",
                "data_retention": "10_years"
            },
            "EMR": {
                "connection_type": "hl7",
                "endpoint": "emr.hospital.com:8080",
                "message_types": [
                    "ADT",               # 患者管理消息
                    "ORM",               # 医嘱消息
                    "ORU",               # 结果消息
                    "MDM"                # 文档消息
                ],
                "update_frequency": "real-time",
                "data_retention": "永久"
            }
        }
    
    def define_collection_rules(self):
        """定义数据采集规则"""
        return {
            "实时采集规则": {
                "触发条件": [
                    "新患者入院",
                    "检验结果更新",
                    "医嘱下达",
                    "诊断确认"
                ],
                "采集频率": "事件驱动",
                "数据验证": "实时验证",
                "错误处理": "重试机制"
            },
            "批量采集规则": {
                "采集时间": [
                    "每日凌晨2:00",
                    "每周日凌晨1:00",
                    "每月1日凌晨0:00"
                ],
                "采集范围": "全量数据",
                "数据验证": "批量验证",
                "错误处理": "日志记录"
            },
            "增量采集规则": {
                "采集频率": "每小时",
                "时间窗口": "上次采集时间至当前时间",
                "数据验证": "增量验证",
                "冲突处理": "最新数据优先"
            }
        }
    
    def define_quality_rules(self):
        """定义数据质量规则"""
        return {
            "完整性检查": {
                "必填字段检查": [
                    "患者ID",
                    "就诊时间",
                    "诊断代码",
                    "医生ID"
                ],
                "关联性检查": [
                    "患者-就诊记录关联",
                    "医嘱-执行记录关联",
                    "检验申请-结果关联"
                ]
            },
            "准确性检查": {
                "数据格式验证": [
                    "日期格式检查",
                    "数值范围检查",
                    "编码规范检查"
                ],
                "逻辑一致性检查": [
                    "入院时间早于出院时间",
                    "检验时间在合理范围内",
                    "药物剂量在安全范围内"
                ]
            },
            "及时性检查": {
                "数据延迟监控": [
                    "实时数据延迟 < 5分钟",
                    "批量数据延迟 < 1小时",
                    "历史数据完整性"
                ]
            },
            "一致性检查": {
                "跨系统数据一致性": [
                    "患者基本信息一致性",
                    "诊断编码一致性",
                    "时间戳一致性"
                ]
            }
        }
    
    def collect_patient_data(self, patient_id: str, date_range: tuple = None):
        """采集患者数据"""
        try:
            patient_data = {
                "basic_info": self.collect_basic_info(patient_id),
                "medical_history": self.collect_medical_history(patient_id, date_range),
                "lab_results": self.collect_lab_results(patient_id, date_range),
                "medications": self.collect_medications(patient_id, date_range),
                "procedures": self.collect_procedures(patient_id, date_range),
                "images": self.collect_medical_images(patient_id, date_range)
            }
            
            # 数据质量检查
            quality_report = self.validate_data_quality(patient_data)
            
            return {
                "patient_id": patient_id,
                "data": patient_data,
                "quality_report": quality_report,
                "collection_time": datetime.datetime.now().isoformat()
            }
            
        except Exception as e:
            return {
                "patient_id": patient_id,
                "error": str(e),
                "collection_time": datetime.datetime.now().isoformat()
            }
    
    def collect_basic_info(self, patient_id: str):
        """采集患者基本信息"""
        # 模拟从HIS系统采集患者基本信息
        return {
            "patient_id": patient_id,
            "name": "张三",
            "gender": "男",
            "age": 45,
            "birth_date": "1979-03-15",
            "id_number": "110101197903150001",
            "phone": "13800138000",
            "address": "北京市朝阳区",
            "emergency_contact": "李四",
            "emergency_phone": "13900139000",
            "insurance_type": "职工医保",
            "insurance_number": "110101197903150001"
        }
    
    def collect_medical_history(self, patient_id: str, date_range: tuple = None):
        """采集病史信息"""
        # 模拟从EMR系统采集病史信息
        return {
            "chronic_diseases": [
                {
                    "disease_code": "I10",
                    "disease_name": "高血压",
                    "diagnosis_date": "2020-05-15",
                    "severity": "轻度",
                    "status": "稳定"
                },
                {
                    "disease_code": "E11",
                    "disease_name": "2型糖尿病",
                    "diagnosis_date": "2021-08-20",
                    "severity": "中度",
                    "status": "控制中"
                }
            ],
            "allergies": [
                {
                    "allergen": "青霉素",
                    "reaction": "皮疹",
                    "severity": "中度"
                }
            ],
            "family_history": [
                {
                    "relation": "父亲",
                    "disease": "高血压",
                    "age_of_onset": 50
                },
                {
                    "relation": "母亲",
                    "disease": "糖尿病",
                    "age_of_onset": 55
                }
            ],
            "surgical_history": [
                {
                    "procedure": "阑尾切除术",
                    "date": "2015-06-10",
                    "hospital": "第一人民医院"
                }
            ]
        }
    
    def collect_lab_results(self, patient_id: str, date_range: tuple = None):
        """采集检验结果"""
        # 模拟从LIS系统采集检验结果
        return {
            "blood_routine": {
                "test_date": "2024-07-20",
                "results": {
                    "WBC": {"value": 6.5, "unit": "10^9/L", "reference": "3.5-9.5", "status": "正常"},
                    "RBC": {"value": 4.2, "unit": "10^12/L", "reference": "4.3-5.8", "status": "偏低"},
                    "HGB": {"value": 125, "unit": "g/L", "reference": "130-175", "status": "偏低"},
                    "PLT": {"value": 280, "unit": "10^9/L", "reference": "125-350", "status": "正常"}
                }
            },
            "blood_chemistry": {
                "test_date": "2024-07-20",
                "results": {
                    "GLU": {"value": 8.5, "unit": "mmol/L", "reference": "3.9-6.1", "status": "偏高"},
                    "TC": {"value": 5.8, "unit": "mmol/L", "reference": "<5.2", "status": "偏高"},
                    "TG": {"value": 2.1, "unit": "mmol/L", "reference": "<1.7", "status": "偏高"},
                    "HDL": {"value": 1.0, "unit": "mmol/L", "reference": ">1.0", "status": "正常"},
                    "LDL": {"value": 3.8, "unit": "mmol/L", "reference": "<3.4", "status": "偏高"}
                }
            },
            "liver_function": {
                "test_date": "2024-07-20",
                "results": {
                    "ALT": {"value": 35, "unit": "U/L", "reference": "9-50", "status": "正常"},
                    "AST": {"value": 28, "unit": "U/L", "reference": "15-40", "status": "正常"},
                    "TBIL": {"value": 18, "unit": "μmol/L", "reference": "5-21", "status": "正常"}
                }
            }
        }
    
    def collect_medications(self, patient_id: str, date_range: tuple = None):
        """采集用药信息"""
        # 模拟从HIS系统采集用药信息
        return {
            "current_medications": [
                {
                    "medication_name": "氨氯地平片",
                    "dosage": "5mg",
                    "frequency": "每日一次",
                    "route": "口服",
                    "start_date": "2024-01-15",
                    "end_date": None,
                    "prescriber": "李医生",
                    "indication": "高血压"
                },
                {
                    "medication_name": "二甲双胍片",
                    "dosage": "500mg",
                    "frequency": "每日两次",
                    "route": "口服",
                    "start_date": "2024-02-01",
                    "end_date": None,
                    "prescriber": "王医生",
                    "indication": "2型糖尿病"
                }
            ],
            "medication_history": [
                {
                    "medication_name": "阿司匹林肠溶片",
                    "dosage": "100mg",
                    "frequency": "每日一次",
                    "route": "口服",
                    "start_date": "2023-06-01",
                    "end_date": "2024-01-01",
                    "prescriber": "张医生",
                    "indication": "心血管保护",
                    "discontinue_reason": "胃肠道不适"
                }
            ]
        }
    
    def collect_procedures(self, patient_id: str, date_range: tuple = None):
        """采集手术/操作信息"""
        # 模拟从HIS系统采集手术信息
        return {
            "procedures": [
                {
                    "procedure_code": "36.10",
                    "procedure_name": "冠状动脉造影",
                    "date": "2024-06-15",
                    "surgeon": "心内科-刘医生",
                    "anesthesia_type": "局部麻醉",
                    "duration": 45,
                    "complications": "无",
                    "outcome": "成功"
                }
            ],
            "planned_procedures": [
                {
                    "procedure_name": "冠状动脉支架植入术",
                    "planned_date": "2024-08-01",
                    "surgeon": "心内科-刘医生",
                    "preparation_required": [
                        "术前检查",
                        "停用抗凝药物",
                        "禁食12小时"
                    ]
                }
            ]
        }
    
    def collect_medical_images(self, patient_id: str, date_range: tuple = None):
        """采集医学影像信息"""
        # 模拟从PACS系统采集影像信息
        return {
            "studies": [
                {
                    "study_id": "ST001",
                    "modality": "CT",
                    "body_part": "胸部",
                    "study_date": "2024-07-18",
                    "description": "胸部CT平扫+增强",
                    "radiologist": "影像科-陈医生",
                    "report": "双肺纹理清晰,未见明显异常",
                    "images_count": 120,
                    "file_size": "256MB"
                },
                {
                    "study_id": "ST002",
                    "modality": "ECG",
                    "body_part": "心脏",
                    "study_date": "2024-07-20",
                    "description": "12导联心电图",
                    "cardiologist": "心内科-李医生",
                    "report": "窦性心律,心率78次/分,ST段轻度压低",
                    "images_count": 1,
                    "file_size": "2MB"
                }
            ]
        }
    
    def validate_data_quality(self, patient_data: Dict[str, Any]):
        """验证数据质量"""
        quality_report = {
            "overall_score": 0,
            "completeness": self.check_completeness(patient_data),
            "accuracy": self.check_accuracy(patient_data),
            "consistency": self.check_consistency(patient_data),
            "timeliness": self.check_timeliness(patient_data),
            "issues": []
        }
        
        # 计算总体质量评分
        scores = [
            quality_report["completeness"]["score"],
            quality_report["accuracy"]["score"],
            quality_report["consistency"]["score"],
            quality_report["timeliness"]["score"]
        ]
        quality_report["overall_score"] = sum(scores) / len(scores)
        
        return quality_report
    
    def check_completeness(self, patient_data: Dict[str, Any]):
        """检查数据完整性"""
        required_fields = [
            "basic_info.patient_id",
            "basic_info.name",
            "basic_info.gender",
            "basic_info.age"
        ]
        
        missing_fields = []
        for field in required_fields:
            if not self.get_nested_value(patient_data, field):
                missing_fields.append(field)
        
        completeness_score = (len(required_fields) - len(missing_fields)) / len(required_fields) * 100
        
        return {
            "score": completeness_score,
            "missing_fields": missing_fields,
            "total_fields": len(required_fields),
            "complete_fields": len(required_fields) - len(missing_fields)
        }
    
    def check_accuracy(self, patient_data: Dict[str, Any]):
        """检查数据准确性"""
        accuracy_issues = []
        
        # 检查年龄与出生日期的一致性
        if patient_data.get("basic_info"):
            birth_date = patient_data["basic_info"].get("birth_date")
            age = patient_data["basic_info"].get("age")
            
            if birth_date and age:
                calculated_age = self.calculate_age(birth_date)
                if abs(calculated_age - age) > 1:
                    accuracy_issues.append("年龄与出生日期不一致")
        
        # 检查检验结果的合理性
        if patient_data.get("lab_results"):
            lab_results = patient_data["lab_results"]
            for test_type, test_data in lab_results.items():
                if "results" in test_data:
                    for item, result in test_data["results"].items():
                        if result["status"] in ["异常", "危急"]:
                            accuracy_issues.append(f"{item}检验结果异常")
        
        accuracy_score = max(0, 100 - len(accuracy_issues) * 10)
        
        return {
            "score": accuracy_score,
            "issues": accuracy_issues,
            "total_checks": 10,
            "passed_checks": 10 - len(accuracy_issues)
        }
    
    def check_consistency(self, patient_data: Dict[str, Any]):
        """检查数据一致性"""
        consistency_issues = []
        
        # 检查用药与诊断的一致性
        if patient_data.get("medical_history") and patient_data.get("medications"):
            diagnoses = [d["disease_name"] for d in patient_data["medical_history"].get("chronic_diseases", [])]
            medications = patient_data["medications"].get("current_medications", [])
            
            for med in medications:
                indication = med.get("indication", "")
                if indication and indication not in diagnoses:
                    consistency_issues.append(f"用药适应症{indication}与诊断不一致")
        
        consistency_score = max(0, 100 - len(consistency_issues) * 15)
        
        return {
            "score": consistency_score,
            "issues": consistency_issues,
            "total_checks": 5,
            "passed_checks": 5 - len(consistency_issues)
        }
    
    def check_timeliness(self, patient_data: Dict[str, Any]):
        """检查数据及时性"""
        timeliness_issues = []
        current_date = datetime.datetime.now().date()
        
        # 检查检验结果的时效性
        if patient_data.get("lab_results"):
            for test_type, test_data in patient_data["lab_results"].items():
                test_date_str = test_data.get("test_date")
                if test_date_str:
                    test_date = datetime.datetime.strptime(test_date_str, "%Y-%m-%d").date()
                    days_diff = (current_date - test_date).days
                    if days_diff > 30:
                        timeliness_issues.append(f"{test_type}检验结果过期({days_diff}天)")
        
        timeliness_score = max(0, 100 - len(timeliness_issues) * 20)
        
        return {
            "score": timeliness_score,
            "issues": timeliness_issues,
            "total_checks": 3,
            "passed_checks": 3 - len(timeliness_issues)
        }
    
    def get_nested_value(self, data: Dict, path: str):
        """获取嵌套字典的值"""
        keys = path.split('.')
        current = data
        
        for key in keys:
            if isinstance(current, dict) and key in current:
                current = current[key]
            else:
                return None
        
        return current
    
    def calculate_age(self, birth_date_str: str):
        """计算年龄"""
        birth_date = datetime.datetime.strptime(birth_date_str, "%Y-%m-%d").date()
        today = datetime.date.today()
        age = today.year - birth_date.year - ((today.month, today.day) < (birth_date.month, birth_date.day))
        return age
    
    def generate_collection_report(self, collection_results: List[Dict]):
        """生成采集报告"""
        total_patients = len(collection_results)
        successful_collections = len([r for r in collection_results if "data" in r])
        failed_collections = total_patients - successful_collections
        
        quality_scores = []
        for result in collection_results:
            if "data" in result and "quality_report" in result:
                quality_scores.append(result["quality_report"]["overall_score"])
        
        avg_quality_score = sum(quality_scores) / len(quality_scores) if quality_scores else 0
        
        return {
            "collection_summary": {
                "total_patients": total_patients,
                "successful_collections": successful_collections,
                "failed_collections": failed_collections,
                "success_rate": successful_collections / total_patients * 100 if total_patients > 0 else 0
            },
            "quality_summary": {
                "average_quality_score": avg_quality_score,
                "high_quality_count": len([s for s in quality_scores if s >= 90]),
                "medium_quality_count": len([s for s in quality_scores if 70 <= s < 90]),
                "low_quality_count": len([s for s in quality_scores if s < 70])
            },
            "recommendations": self.generate_collection_recommendations(collection_results)
        }
    
    def generate_collection_recommendations(self, collection_results: List[Dict]):
        """生成采集建议"""
        recommendations = []
        
        # 分析失败原因
        failed_results = [r for r in collection_results if "error" in r]
        if failed_results:
            recommendations.append("检查数据源连接状态,解决采集失败问题")
        
        # 分析质量问题
        quality_issues = []
        for result in collection_results:
            if "quality_report" in result:
                quality_report = result["quality_report"]
                if quality_report["overall_score"] < 80:
                    quality_issues.extend(quality_report["issues"])
        
        if quality_issues:
            recommendations.append("改进数据质量控制流程,解决数据质量问题")
        
        if not recommendations:
            recommendations.append("数据采集状态良好,继续保持")
        
        return recommendations

# 创建数据采集器实例
data_collector = MedicalDataCollector()

# 示例:采集患者数据
patient_ids = ["P001", "P002", "P003"]
collection_results = []

print("=== 医疗数据采集示例 ===\n")

for patient_id in patient_ids:
    print(f"📊 采集患者 {patient_id} 的数据...")
    result = data_collector.collect_patient_data(patient_id)
    collection_results.append(result)
    
    if "data" in result:
        quality_score = result["quality_report"]["overall_score"]
        print(f"   ✅ 采集成功,数据质量评分: {quality_score:.1f}")
    else:
        print(f"   ❌ 采集失败: {result.get('error', '未知错误')}")

# 生成采集报告
print(f"\n📋 数据采集报告:")
report = data_collector.generate_collection_report(collection_results)
print(f"   总患者数: {report['collection_summary']['total_patients']}")
print(f"   成功采集: {report['collection_summary']['successful_collections']}")
print(f"   成功率: {report['collection_summary']['success_rate']:.1f}%")
print(f"   平均质量评分: {report['quality_summary']['average_quality_score']:.1f}")
print(f"   建议: {', '.join(report['recommendations'])}")

5. 患者数据可视化分析

5.1 患者画像分析

/**
 * 患者数据可视化分析模块
 */
class PatientDataAnalyzer {
    constructor() {
        this.charts = new Map();
        this.patientData = [];
        this.analysisConfig = this.initAnalysisConfig();
        this.colorScheme = this.initColorScheme();
    }

    /**
     * 初始化分析配置
     */
    initAnalysisConfig() {
        return {
            ageGroups: [
                { name: '儿童', min: 0, max: 14, color: '#74b9ff' },
                { name: '青少年', min: 15, max: 24, color: '#0984e3' },
                { name: '青年', min: 25, max: 44, color: '#00b894' },
                { name: '中年', min: 45, max: 64, color: '#fdcb6e' },
                { name: '老年', min: 65, max: 120, color: '#e17055' }
            ],
            diseaseCategories: [
                { name: '心血管疾病', code: 'CVD', color: '#e74c3c' },
                { name: '糖尿病', code: 'DM', color: '#f39c12' },
                { name: '呼吸系统疾病', code: 'RD', color: '#3498db' },
                { name: '消化系统疾病', code: 'GD', color: '#2ecc71' },
                { name: '神经系统疾病', code: 'ND', color: '#9b59b6' },
                { name: '肿瘤', code: 'TUMOR', color: '#34495e' }
            ],
            riskLevels: [
                { name: '低风险', threshold: 30, color: '#00ff88' },
                { name: '中风险', threshold: 60, color: '#ffd93d' },
                { name: '高风险', threshold: 80, color: '#ff6b6b' },
                { name: '极高风险', threshold: 100, color: '#c44569' }
            ]
        };
    }

    /**
     * 初始化颜色方案
     */
    initColorScheme() {
        return {
            primary: '#1e3c72',
            secondary: '#2a5298',
            accent: '#00d4ff',
            success: '#00ff88',
            warning: '#ffd93d',
            danger: '#ff6b6b',
            info: '#74b9ff',
            light: '#f8f9fa',
            dark: '#343a40'
        };
    }

    /**
     * 创建患者年龄分布图
     */
    createAgeDistributionChart(containerId, patientData) {
        const container = document.getElementById(containerId);
        if (!container) {
            console.error(`容器不存在: ${containerId}`);
            return null;
        }

        const chart = echarts.init(container);
        
        // 统计年龄分布
        const ageDistribution = this.calculateAgeDistribution(patientData);
        
        const option = {
            backgroundColor: 'transparent',
            title: {
                text: '患者年龄分布',
                left: 'center',
                top: '5%',
                textStyle: {
                    color: '#ffffff',
                    fontSize: 16,
                    fontWeight: 'bold'
                }
            },
            tooltip: {
                trigger: 'item',
                backgroundColor: 'rgba(0, 0, 0, 0.8)',
                borderColor: 'rgba(0, 212, 255, 0.5)',
                textStyle: {
                    color: '#ffffff'
                },
                formatter: function(params) {
                    return `${params.name}<br/>
                            患者数量: ${params.value}人<br/>
                            占比: ${params.percent}%`;
                }
            },
            legend: {
                orient: 'vertical',
                left: 'left',
                top: 'middle',
                textStyle: {
                    color: '#ffffff',
                    fontSize: 12
                }
            },
            series: [{
                name: '年龄分布',
                type: 'pie',
                radius: ['40%', '70%'],
                center: ['60%', '50%'],
                avoidLabelOverlap: false,
                itemStyle: {
                    borderRadius: 8,
                    borderColor: '#fff',
                    borderWidth: 2
                },
                label: {
                    show: false
                },
                emphasis: {
                    label: {
                        show: true,
                        fontSize: '14',
                        fontWeight: 'bold',
                        color: '#ffffff'
                    },
                    itemStyle: {
                        shadowBlur: 10,
                        shadowOffsetX: 0,
                        shadowColor: 'rgba(0, 0, 0, 0.5)'
                    }
                },
                data: ageDistribution.map(item => ({
                    name: item.name,
                    value: item.count,
                    itemStyle: {
                        color: item.color
                    }
                }))
            }]
        };

        chart.setOption(option);
        this.charts.set(containerId, chart);

        return chart;
    }

    /**
     * 创建疾病分布图
     */
    createDiseaseDistributionChart(containerId, patientData) {
        const container = document.getElementById(containerId);
        if (!container) {
            console.error(`容器不存在: ${containerId}`);
            return null;
        }

        const chart = echarts.init(container);
        
        // 统计疾病分布
        const diseaseDistribution = this.calculateDiseaseDistribution(patientData);
        
        const option = {
            backgroundColor: 'transparent',
            title: {
                text: '疾病分布统计',
                left: 'center',
                top: '5%',
                textStyle: {
                    color: '#ffffff',
                    fontSize: 16
                }
            },
            tooltip: {
                trigger: 'axis',
                backgroundColor: 'rgba(0, 0, 0, 0.8)',
                borderColor: 'rgba(0, 212, 255, 0.5)',
                textStyle: {
                    color: '#ffffff'
                },
                axisPointer: {
                    type: 'shadow'
                }
            },
            grid: {
                left: '3%',
                right: '4%',
                bottom: '3%',
                top: '15%',
                containLabel: true
            },
            xAxis: {
                type: 'category',
                data: diseaseDistribution.map(item => item.name),
                axisLine: {
                    lineStyle: {
                        color: 'rgba(255, 255, 255, 0.3)'
                    }
                },
                axisLabel: {
                    color: '#ffffff',
                    rotate: 45
                }
            },
            yAxis: {
                type: 'value',
                name: '患者数量',
                axisLine: {
                    lineStyle: {
                        color: 'rgba(255, 255, 255, 0.3)'
                    }
                },
                axisLabel: {
                    color: '#ffffff'
                },
                splitLine: {
                    lineStyle: {
                        color: 'rgba(255, 255, 255, 0.1)'
                    }
                }
            },
            series: [{
                name: '患者数量',
                type: 'bar',
                barWidth: '60%',
                data: diseaseDistribution.map((item, index) => ({
                    value: item.count,
                    itemStyle: {
                        color: {
                            type: 'linear',
                            x: 0, y: 0, x2: 0, y2: 1,
                            colorStops: [
                                { offset: 0, color: item.color },
                                { offset: 1, color: this.adjustColorOpacity(item.color, 0.6) }
                            ]
                        },
                        borderRadius: [4, 4, 0, 0]
                    }
                }))
            }]
        };

        chart.setOption(option);
        this.charts.set(containerId, chart);

        return chart;
    }

    /**
     * 创建患者风险评估雷达图
     */
    createRiskAssessmentChart(containerId, patientData) {
        const container = document.getElementById(containerId);
        if (!container) {
            console.error(`容器不存在: ${containerId}`);
            return null;
        }

        const chart = echarts.init(container);
        
        // 计算风险评估数据
        const riskAssessment = this.calculateRiskAssessment(patientData);
        
        const indicators = [
            { name: '年龄风险', max: 100 },
            { name: '疾病风险', max: 100 },
            { name: '用药风险', max: 100 },
            { name: '生活方式风险', max: 100 },
            { name: '遗传风险', max: 100 },
            { name: '环境风险', max: 100 }
        ];

        const option = {
            backgroundColor: 'transparent',
            title: {
                text: '患者风险评估',
                left: 'center',
                top: '5%',
                textStyle: {
                    color: '#ffffff',
                    fontSize: 16
                }
            },
            tooltip: {
                backgroundColor: 'rgba(0, 0, 0, 0.8)',
                borderColor: 'rgba(0, 212, 255, 0.5)',
                textStyle: {
                    color: '#ffffff'
                }
            },
            radar: {
                indicator: indicators,
                center: ['50%', '55%'],
                radius: '70%',
                axisName: {
                    color: '#ffffff',
                    fontSize: 12
                },
                splitLine: {
                    lineStyle: {
                        color: 'rgba(255, 255, 255, 0.2)'
                    }
                },
                axisLine: {
                    lineStyle: {
                        color: 'rgba(255, 255, 255, 0.3)'
                    }
                },
                splitArea: {
                    show: true,
                    areaStyle: {
                        color: [
                            'rgba(0, 255, 136, 0.1)',
                            'rgba(255, 217, 61, 0.1)',
                            'rgba(255, 107, 107, 0.1)',
                            'rgba(196, 69, 105, 0.1)'
                        ]
                    }
                }
            },
            series: [{
                name: '风险评估',
                type: 'radar',
                data: riskAssessment.map(patient => ({
                    value: [
                        patient.ageRisk,
                        patient.diseaseRisk,
                        patient.medicationRisk,
                        patient.lifestyleRisk,
                        patient.geneticRisk,
                        patient.environmentRisk
                    ],
                    name: patient.name,
                    areaStyle: {
                        color: this.getRiskColor(patient.overallRisk),
                        opacity: 0.3
                    },
                    lineStyle: {
                        color: this.getRiskColor(patient.overallRisk),
                        width: 2
                    },
                    symbol: 'circle',
                    symbolSize: 5
                }))
            }]
        };

        chart.setOption(option);
        this.charts.set(containerId, chart);

        return chart;
    }

    /**
     * 创建医疗费用分析图
     */
    createMedicalCostChart(containerId, patientData) {
        const container = document.getElementById(containerId);
        if (!container) {
            console.error(`容器不存在: ${containerId}`);
            return null;
        }

        const chart = echarts.init(container);
        
        // 计算医疗费用数据
        const costData = this.calculateMedicalCosts(patientData);
        
        const option = {
            backgroundColor: 'transparent',
            title: {
                text: '医疗费用构成分析',
                left: 'center',
                top: '5%',
                textStyle: {
                    color: '#ffffff',
                    fontSize: 16
                }
            },
            tooltip: {
                trigger: 'item',
                backgroundColor: 'rgba(0, 0, 0, 0.8)',
                borderColor: 'rgba(0, 212, 255, 0.5)',
                textStyle: {
                    color: '#ffffff'
                },
                formatter: function(params) {
                    return `${params.name}<br/>
                            费用: ¥${params.value.toLocaleString()}<br/>
                            占比: ${params.percent}%`;
                }
            },
            legend: {
                orient: 'vertical',
                left: 'left',
                top: 'middle',
                textStyle: {
                    color: '#ffffff',
                    fontSize: 12
                }
            },
            series: [{
                name: '医疗费用',
                type: 'pie',
                radius: ['30%', '60%'],
                center: ['60%', '50%'],
                roseType: 'area',
                itemStyle: {
                    borderRadius: 5,
                    borderColor: '#fff',
                    borderWidth: 2
                },
                label: {
                    show: true,
                    color: '#ffffff',
                    formatter: '{b}: {c}'
                },
                emphasis: {
                    itemStyle: {
                        shadowBlur: 10,
                        shadowOffsetX: 0,
                        shadowColor: 'rgba(0, 0, 0, 0.5)'
                    }
                },
                data: costData
            }]
        };

        chart.setOption(option);
        this.charts.set(containerId, chart);

        return chart;
    }

    /**
     * 创建就诊趋势图
     */
    createVisitTrendChart(containerId, visitData) {
        const container = document.getElementById(containerId);
        if (!container) {
            console.error(`容器不存在: ${containerId}`);
            return null;
        }

        const chart = echarts.init(container);
        
        const option = {
            backgroundColor: 'transparent',
            title: {
                text: '就诊趋势分析',
                left: 'center',
                top: '5%',
                textStyle: {
                    color: '#ffffff',
                    fontSize: 16
                }
            },
            tooltip: {
                trigger: 'axis',
                backgroundColor: 'rgba(0, 0, 0, 0.8)',
                borderColor: 'rgba(0, 212, 255, 0.5)',
                textStyle: {
                    color: '#ffffff'
                },
                axisPointer: {
                    type: 'cross',
                    label: {
                        backgroundColor: '#6a7985'
                    }
                }
            },
            legend: {
                data: ['门诊', '急诊', '住院'],
                top: '10%',
                textStyle: {
                    color: '#ffffff'
                }
            },
            grid: {
                left: '3%',
                right: '4%',
                bottom: '3%',
                top: '20%',
                containLabel: true
            },
            xAxis: {
                type: 'category',
                boundaryGap: false,
                data: visitData.dates,
                axisLine: {
                    lineStyle: {
                        color: 'rgba(255, 255, 255, 0.3)'
                    }
                },
                axisLabel: {
                    color: '#ffffff'
                }
            },
            yAxis: {
                type: 'value',
                name: '就诊人数',
                axisLine: {
                    lineStyle: {
                        color: 'rgba(255, 255, 255, 0.3)'
                    }
                },
                axisLabel: {
                    color: '#ffffff'
                },
                splitLine: {
                    lineStyle: {
                        color: 'rgba(255, 255, 255, 0.1)'
                    }
                }
            },
            series: [
                {
                    name: '门诊',
                    type: 'line',
                    smooth: true,
                    lineStyle: {
                        color: this.colorScheme.success,
                        width: 3
                    },
                    areaStyle: {
                        color: {
                            type: 'linear',
                            x: 0, y: 0, x2: 0, y2: 1,
                            colorStops: [
                                { offset: 0, color: this.adjustColorOpacity(this.colorScheme.success, 0.8) },
                                { offset: 1, color: this.adjustColorOpacity(this.colorScheme.success, 0.1) }
                            ]
                        }
                    },
                    data: visitData.outpatient
                },
                {
                    name: '急诊',
                    type: 'line',
                    smooth: true,
                    lineStyle: {
                        color: this.colorScheme.warning,
                        width: 3
                    },
                    areaStyle: {
                        color: {
                            type: 'linear',
                            x: 0, y: 0, x2: 0, y2: 1,
                            colorStops: [
                                { offset: 0, color: this.adjustColorOpacity(this.colorScheme.warning, 0.8) },
                                { offset: 1, color: this.adjustColorOpacity(this.colorScheme.warning, 0.1) }
                            ]
                        }
                    },
                    data: visitData.emergency
                },
                {
                    name: '住院',
                    type: 'line',
                    smooth: true,
                    lineStyle: {
                        color: this.colorScheme.danger,
                        width: 3
                    },
                    areaStyle: {
                        color: {
                            type: 'linear',
                            x: 0, y: 0, x2: 0, y2: 1,
                            colorStops: [
                                { offset: 0, color: this.adjustColorOpacity(this.colorScheme.danger, 0.8) },
                                { offset: 1, color: this.adjustColorOpacity(this.colorScheme.danger, 0.1) }
                            ]
                        }
                    },
                    data: visitData.inpatient
                }
            ]
        };

        chart.setOption(option);
        this.charts.set(containerId, chart);

        return chart;
    }

    /**
     * 计算年龄分布
     */
    calculateAgeDistribution(patientData) {
        const distribution = this.analysisConfig.ageGroups.map(group => ({
            name: group.name,
            count: 0,
            color: group.color
        }));

        patientData.forEach(patient => {
            const age = patient.age || 0;
            const group = this.analysisConfig.ageGroups.find(g => age >= g.min && age <= g.max);
            if (group) {
                const index = distribution.findIndex(d => d.name === group.name);
                if (index !== -1) {
                    distribution[index].count++;
                }
            }
        });

        return distribution;
    }

    /**
     * 计算疾病分布
     */
    calculateDiseaseDistribution(patientData) {
        const distribution = this.analysisConfig.diseaseCategories.map(category => ({
            name: category.name,
            count: 0,
            color: category.color
        }));

        patientData.forEach(patient => {
            if (patient.diagnoses) {
                patient.diagnoses.forEach(diagnosis => {
                    const category = this.categorizeDisease(diagnosis);
                    const index = distribution.findIndex(d => d.name === category);
                    if (index !== -1) {
                        distribution[index].count++;
                    }
                });
            }
        });

        return distribution.filter(d => d.count > 0);
    }

    /**
     * 计算风险评估
     */
    calculateRiskAssessment(patientData) {
        return patientData.slice(0, 5).map(patient => ({
            name: patient.name || '患者',
            ageRisk: this.calculateAgeRisk(patient.age),
            diseaseRisk: this.calculateDiseaseRisk(patient.diagnoses),
            medicationRisk: this.calculateMedicationRisk(patient.medications),
            lifestyleRisk: this.calculateLifestyleRisk(patient.lifestyle),
            geneticRisk: this.calculateGeneticRisk(patient.familyHistory),
            environmentRisk: this.calculateEnvironmentRisk(patient.environment),
            overallRisk: this.calculateOverallRisk(patient)
        }));
    }

    /**
     * 计算医疗费用
     */
    calculateMedicalCosts(patientData) {
        const costCategories = [
            { name: '药品费用', value: 0, color: '#e74c3c' },
            { name: '检查费用', value: 0, color: '#3498db' },
            { name: '治疗费用', value: 0, color: '#2ecc71' },
            { name: '手术费用', value: 0, color: '#f39c12' },
            { name: '床位费用', value: 0, color: '#9b59b6' },
            { name: '其他费用', value: 0, color: '#34495e' }
        ];

        // 模拟费用计算
        costCategories[0].value = 125000; // 药品费用
        costCategories[1].value = 85000;  // 检查费用
        costCategories[2].value = 95000;  // 治疗费用
        costCategories[3].value = 180000; // 手术费用
        costCategories[4].value = 45000;  // 床位费用
        costCategories[5].value = 25000;  // 其他费用

        return costCategories.map(category => ({
            name: category.name,
            value: category.value,
            itemStyle: {
                color: category.color
            }
        }));
    }

    /**
     * 疾病分类
     */
    categorizeDisease(diagnosis) {
        const diseaseMap = {
            '高血压': '心血管疾病',
            '冠心病': '心血管疾病',
            '心律失常': '心血管疾病',
            '糖尿病': '糖尿病',
            '肺炎': '呼吸系统疾病',
            '哮喘': '呼吸系统疾病',
            '胃炎': '消化系统疾病',
            '肝炎': '消化系统疾病',
            '脑梗': '神经系统疾病',
            '癫痫': '神经系统疾病',
            '肺癌': '肿瘤',
            '胃癌': '肿瘤'
        };

        return diseaseMap[diagnosis] || '其他疾病';
    }

    /**
     * 计算各种风险评分
     */
    calculateAgeRisk(age) {
        if (age < 18) return 10;
        if (age < 40) return 20;
        if (age < 60) return 40;
        if (age < 80) return 70;
        return 90;
    }

    calculateDiseaseRisk(diagnoses) {
        if (!diagnoses || diagnoses.length === 0) return 10;
        return Math.min(90, diagnoses.length * 20 + 30);
    }

    calculateMedicationRisk(medications) {
        if (!medications || medications.length === 0) return 10;
        return Math.min(80, medications.length * 15 + 20);
    }

    calculateLifestyleRisk(lifestyle) {
        // 模拟生活方式风险计算
        return Math.random() * 60 + 20;
    }

    calculateGeneticRisk(familyHistory) {
        if (!familyHistory || familyHistory.length === 0) return 20;
        return Math.min(70, familyHistory.length * 25 + 25);
    }

    calculateEnvironmentRisk(environment) {
        // 模拟环境风险计算
        return Math.random() * 50 + 25;
    }

    calculateOverallRisk(patient) {
        const risks = [
            this.calculateAgeRisk(patient.age),
            this.calculateDiseaseRisk(patient.diagnoses),
            this.calculateMedicationRisk(patient.medications),
            this.calculateLifestyleRisk(patient.lifestyle),
            this.calculateGeneticRisk(patient.familyHistory),
            this.calculateEnvironmentRisk(patient.environment)
        ];
        
        return risks.reduce((sum, risk) => sum + risk, 0) / risks.length;
    }

    /**
     * 获取风险颜色
     */
    getRiskColor(riskScore) {
        if (riskScore < 30) return this.colorScheme.success;
        if (riskScore < 60) return this.colorScheme.warning;
        if (riskScore < 80) return this.colorScheme.danger;
        return '#c44569';
    }

    /**
     * 调整颜色透明度
     */
    adjustColorOpacity(color, opacity) {
        // 简化的颜色透明度调整
        if (color.startsWith('#')) {
            const r = parseInt(color.slice(1, 3), 16);
            const g = parseInt(color.slice(3, 5), 16);
            const b = parseInt(color.slice(5, 7), 16);
            return `rgba(${r}, ${g}, ${b}, ${opacity})`;
        }
        return color;
    }

    /**
     * 调整图表大小
     */
    resize() {
        this.charts.forEach(chart => {
            chart.resize();
        });
    }

    /**
     * 销毁所有图表
     */
    dispose() {
        this.charts.forEach(chart => {
            chart.dispose();
        });
        this.charts.clear();
    }
}

// 创建患者数据分析器实例
const patientAnalyzer = new PatientDataAnalyzer();

// 模拟患者数据
const mockPatientData = [
    {
        id: 'P001',
        name: '张三',
        age: 45,
        gender: '男',
        diagnoses: ['高血压', '糖尿病'],
        medications: ['氨氯地平', '二甲双胍'],
        familyHistory: ['高血压', '糖尿病']
    },
    {
        id: 'P002',
        name: '李四',
        age: 32,
        gender: '女',
        diagnoses: ['哮喘'],
        medications: ['沙丁胺醇'],
        familyHistory: []
    },
    {
        id: 'P003',
        name: '王五',
        age: 68,
        gender: '男',
        diagnoses: ['冠心病', '高血压'],
        medications: ['阿司匹林', '氨氯地平', '阿托伐他汀'],
        familyHistory: ['冠心病']
    }
];

// 模拟就诊趋势数据
const mockVisitData = {
    dates: ['1月', '2月', '3月', '4月', '5月', '6月'],
    outpatient: [1200, 1350, 1180, 1420, 1380, 1500],
    emergency: [180, 220, 160, 240, 200, 190],
    inpatient: [320, 380, 290, 410, 360, 420]
};

// 页面加载完成后创建图表
document.addEventListener('DOMContentLoaded', () => {
    // 创建年龄分布图
    if (document.getElementById('ageDistributionChart')) {
        patientAnalyzer.createAgeDistributionChart('ageDistributionChart', mockPatientData);
    }

    // 创建疾病分布图
    if (document.getElementById('diseaseDistributionChart')) {
        patientAnalyzer.createDiseaseDistributionChart('diseaseDistributionChart', mockPatientData);
    }

    // 创建风险评估图
    if (document.getElementById('riskAssessmentChart')) {
        patientAnalyzer.createRiskAssessmentChart('riskAssessmentChart', mockPatientData);
    }

    // 创建医疗费用图
    if (document.getElementById('medicalCostChart')) {
        patientAnalyzer.createMedicalCostChart('medicalCostChart', mockPatientData);
    }

    // 创建就诊趋势图
    if (document.getElementById('visitTrendChart')) {
        patientAnalyzer.createVisitTrendChart('visitTrendChart', mockVisitData);
    }
});

// 窗口大小变化时调整图表
window.addEventListener('resize', () => {
    patientAnalyzer.resize();
});

6. 医疗指标监控系统

6.1 关键指标监控

# 医疗指标监控系统
import datetime
import json
from typing import Dict, List, Any, Optional
import numpy as np
import pandas as pd

class MedicalIndicatorMonitor:
    """医疗指标监控系统"""
    
    def __init__(self):
        self.indicators = self.define_medical_indicators()
        self.alert_rules = self.define_alert_rules()
        self.monitoring_config = self.define_monitoring_config()
        self.historical_data = {}
        self.current_alerts = []
    
    def define_medical_indicators(self):
        """定义医疗指标"""
        return {
            "患者安全指标": {
                "院内感染率": {
                    "计算公式": "院内感染人数 / 住院总人数 × 100%",
                    "目标值": "< 3%",
                    "预警阈值": "> 2.5%",
                    "危险阈值": "> 4%",
                    "监控频率": "日",
                    "数据源": "HIS",
                    "责任科室": "感控科",
                    "权重": 0.25
                },
                "药物不良反应率": {
                    "计算公式": "药物不良反应人数 / 用药总人数 × 100%",
                    "目标值": "< 1%",
                    "预警阈值": "> 0.8%",
                    "危险阈值": "> 1.5%",
                    "监控频率": "日",
                    "数据源": "HIS+药房系统",
                    "责任科室": "药剂科",
                    "权重": 0.2
                },
                "手术并发症率": {
                    "计算公式": "手术并发症人数 / 手术总人数 × 100%",
                    "目标值": "< 2%",
                    "预警阈值": "> 1.5%",
                    "危险阈值": "> 3%",
                    "监控频率": "日",
                    "数据源": "手术系统",
                    "责任科室": "外科",
                    "权重": 0.25
                },
                "跌倒发生率": {
                    "计算公式": "跌倒事件数 / 住院总人数 × 1000‰",
                    "目标值": "< 3‰",
                    "预警阈值": "> 2.5‰",
                    "危险阈值": "> 4‰",
                    "监控频率": "日",
                    "数据源": "护理系统",
                    "责任科室": "护理部",
                    "权重": 0.15
                },
                "压疮发生率": {
                    "计算公式": "压疮发生人数 / 住院总人数 × 100%",
                    "目标值": "< 1%",
                    "预警阈值": "> 0.8%",
                    "危险阈值": "> 1.5%",
                    "监控频率": "日",
                    "数据源": "护理系统",
                    "责任科室": "护理部",
                    "权重": 0.15
                }
            },
            "医疗质量指标": {
                "平均住院日": {
                    "计算公式": "总住院天数 / 出院人数",
                    "目标值": "< 10天",
                    "预警阈值": "> 12天",
                    "危险阈值": "> 15天",
                    "监控频率": "日",
                    "数据源": "HIS",
                    "责任科室": "医务科",
                    "权重": 0.2
                },
                "床位使用率": {
                    "计算公式": "实际占用床日数 / 开放床日数 × 100%",
                    "目标值": "85%-95%",
                    "预警阈值": "< 80% 或 > 98%",
                    "危险阈值": "< 70% 或 > 100%",
                    "监控频率": "日",
                    "数据源": "HIS",
                    "责任科室": "医务科",
                    "权重": 0.15
                },
                "床位周转次数": {
                    "计算公式": "出院人数 / 平均开放床位数",
                    "目标值": "> 30次/年",
                    "预警阈值": "< 25次/年",
                    "危险阈值": "< 20次/年",
                    "监控频率": "月",
                    "数据源": "HIS",
                    "责任科室": "医务科",
                    "权重": 0.1
                },
                "门诊预约率": {
                    "计算公式": "预约门诊人数 / 门诊总人数 × 100%",
                    "目标值": "> 80%",
                    "预警阈值": "< 70%",
                    "危险阈值": "< 60%",
                    "监控频率": "日",
                    "数据源": "门诊系统",
                    "责任科室": "门诊部",
                    "权重": 0.1
                },
                "检查报告及时率": {
                    "计算公式": "及时出具报告数 / 检查总数 × 100%",
                    "目标值": "> 95%",
                    "预警阈值": "< 90%",
                    "危险阈值": "< 85%",
                    "监控频率": "日",
                    "数据源": "LIS+PACS",
                    "责任科室": "检验科+影像科",
                    "权重": 0.15
                },
                "手术按时开台率": {
                    "计算公式": "按时开台手术数 / 计划手术总数 × 100%",
                    "目标值": "> 90%",
                    "预警阈值": "< 85%",
                    "危险阈值": "< 80%",
                    "监控频率": "日",
                    "数据源": "手术系统",
                    "责任科室": "手术室",
                    "权重": 0.15
                },
                "急诊抢救成功率": {
                    "计算公式": "抢救成功人数 / 抢救总人数 × 100%",
                    "目标值": "> 85%",
                    "预警阈值": "< 80%",
                    "危险阈值": "< 75%",
                    "监控频率": "日",
                    "数据源": "急诊系统",
                    "责任科室": "急诊科",
                    "权重": 0.15
                }
            },
            "服务质量指标": {
                "患者满意度": {
                    "计算公式": "满意患者数 / 调查患者数 × 100%",
                    "目标值": "> 90%",
                    "预警阈值": "< 85%",
                    "危险阈值": "< 80%",
                    "监控频率": "月",
                    "数据源": "满意度调查系统",
                    "责任科室": "客服部",
                    "权重": 0.3
                },
                "投诉处理及时率": {
                    "计算公式": "及时处理投诉数 / 投诉总数 × 100%",
                    "目标值": "> 95%",
                    "预警阈值": "< 90%",
                    "危险阈值": "< 85%",
                    "监控频率": "日",
                    "数据源": "投诉管理系统",
                    "责任科室": "客服部",
                    "权重": 0.2
                },
                "平均候诊时间": {
                    "计算公式": "总候诊时间 / 门诊人数",
                    "目标值": "< 30分钟",
                    "预警阈值": "> 45分钟",
                    "危险阈值": "> 60分钟",
                    "监控频率": "日",
                    "数据源": "门诊系统",
                    "责任科室": "门诊部",
                    "权重": 0.25
                },
                "医生平均接诊时间": {
                    "计算公式": "总接诊时间 / 接诊人数",
                    "目标值": "> 8分钟",
                    "预警阈值": "< 6分钟",
                    "危险阈值": "< 5分钟",
                    "监控频率": "日",
                    "数据源": "门诊系统",
                    "责任科室": "门诊部",
                    "权重": 0.15
                },
                "护理满意度": {
                    "计算公式": "护理满意患者数 / 调查患者数 × 100%",
                    "目标值": "> 95%",
                    "预警阈值": "< 90%",
                    "危险阈值": "< 85%",
                    "监控频率": "月",
                    "数据源": "满意度调查系统",
                    "责任科室": "护理部",
                    "权重": 0.1
                }
            },
            "经济效益指标": {
                "人均医疗费用": {
                    "计算公式": "总医疗费用 / 患者总数",
                    "目标值": "合理区间",
                    "预警阈值": "偏离合理区间20%",
                    "危险阈值": "偏离合理区间40%",
                    "监控频率": "月",
                    "数据源": "财务系统",
                    "责任科室": "财务科",
                    "权重": 0.2
                },
                "药占比": {
                    "计算公式": "药品费用 / 医疗总费用 × 100%",
                    "目标值": "< 30%",
                    "预警阈值": "> 32%",
                    "危险阈值": "> 35%",
                    "监控频率": "月",
                    "数据源": "财务系统+药房系统",
                    "责任科室": "药剂科",
                    "权重": 0.25
                },
                "耗材占比": {
                    "计算公式": "耗材费用 / 医疗总费用 × 100%",
                    "目标值": "< 20%",
                    "预警阈值": "> 22%",
                    "危险阈值": "> 25%",
                    "监控频率": "月",
                    "数据源": "财务系统+物资系统",
                    "责任科室": "设备科",
                    "权重": 0.15
                },
                "医疗收入增长率": {
                    "计算公式": "(本期收入-上期收入) / 上期收入 × 100%",
                    "目标值": "> 5%",
                    "预警阈值": "< 3%",
                    "危险阈值": "< 0%",
                    "监控频率": "月",
                    "数据源": "财务系统",
                    "责任科室": "财务科",
                    "权重": 0.2
                },
                "成本控制率": {
                    "计算公式": "实际成本 / 预算成本 × 100%",
                    "目标值": "95%-105%",
                    "预警阈值": "< 90% 或 > 110%",
                    "危险阈值": "< 85% 或 > 115%",
                    "监控频率": "月",
                    "数据源": "财务系统",
                    "责任科室": "财务科",
                    "权重": 0.2
                }
            }
        }
    
    def define_alert_rules(self):
        """定义预警规则"""
        return {
            "预警级别": {
                "绿色": {
                    "描述": "指标正常",
                    "触发条件": "所有指标在目标范围内",
                    "处理措施": "常规监控",
                    "通知方式": "无需通知",
                    "响应时间": "无",
                    "颜色代码": "#00ff88"
                },
                "黄色": {
                    "描述": "需要关注",
                    "触发条件": "单项指标达到预警阈值",
                    "处理措施": "加强监控,分析原因",
                    "通知方式": "系统提醒",
                    "响应时间": "4小时内",
                    "颜色代码": "#ffd93d"
                },
                "橙色": {
                    "描述": "风险较高",
                    "触发条件": "多项指标达到预警阈值或单项达到危险阈值",
                    "处理措施": "立即分析,制定改进方案",
                    "通知方式": "邮件+短信",
                    "响应时间": "2小时内",
                    "颜色代码": "#ff9f43"
                },
                "红色": {
                    "描述": "高风险",
                    "触发条件": "多项指标达到危险阈值",
                    "处理措施": "紧急处理,启动应急预案",
                    "通知方式": "电话+邮件+短信",
                    "响应时间": "30分钟内",
                    "颜色代码": "#ff6b6b"
                }
            },
            "自动化处理": {
                "数据收集": {
                    "频率": "实时/小时/日/月",
                    "来源": "多系统自动采集",
                    "验证": "数据质量检查",
                    "存储": "时序数据库"
                },
                "指标计算": {
                    "引擎": "实时计算引擎",
                    "规则": "可配置计算规则",
                    "缓存": "计算结果缓存",
                    "更新": "增量更新机制"
                },
                "阈值监控": {
                    "检查": "持续阈值检查",
                    "比较": "多维度比较分析",
                    "趋势": "趋势变化监控",
                    "预测": "异常预测算法"
                },
                "预警触发": {
                    "规则": "多级预警规则",
                    "去重": "重复预警过滤",
                    "升级": "预警级别升级",
                    "记录": "预警历史记录"
                }
            }
        }
    
    def define_monitoring_config(self):
        """定义监控配置"""
        return {
            "监控策略": {
                "实时监控": {
                    "指标": [
                        "院内感染率",
                        "药物不良反应率",
                        "手术并发症率",
                        "床位使用率"
                    ],
                    "频率": "每5分钟",
                    "数据延迟": "< 1分钟",
                    "存储周期": "7天"
                },
                "小时监控": {
                    "指标": [
                        "门诊预约率",
                        "检查报告及时率",
                        "平均候诊时间",
                        "急诊抢救成功率"
                    ],
                    "频率": "每小时",
                    "数据延迟": "< 5分钟",
                    "存储周期": "30天"
                },
                "日度监控": {
                    "指标": [
                        "平均住院日",
                        "手术按时开台率",
                        "投诉处理及时率",
                        "医生平均接诊时间"
                    ],
                    "频率": "每日",
                    "数据延迟": "< 30分钟",
                    "存储周期": "1年"
                },
                "月度监控": {
                    "指标": [
                        "患者满意度",
                        "护理满意度",
                        "药占比",
                        "医疗收入增长率"
                    ],
                    "频率": "每月",
                    "数据延迟": "< 1天",
                    "存储周期": "5年"
                }
            },
            "数据源配置": {
                "HIS系统": {
                    "连接方式": "数据库直连",
                    "更新频率": "实时",
                    "数据表": [
                        "患者信息表",
                        "入出院记录表",
                        "门诊记录表",
                        "医嘱表"
                    ]
                },
                "LIS系统": {
                    "连接方式": "API接口",
                    "更新频率": "实时",
                    "数据接口": [
                        "检验结果接口",
                        "报告状态接口",
                        "质控数据接口"
                    ]
                },
                "财务系统": {
                    "连接方式": "ETL同步",
                    "更新频率": "每日",
                    "数据范围": [
                        "收入数据",
                        "成本数据",
                        "费用明细"
                    ]
                }
            },
            "报告配置": {
                "实时监控报告": {
                    "生成频率": "实时",
                    "包含内容": [
                        "关键指标状态",
                        "异常预警信息",
                        "趋势变化图表"
                    ],
                    "发送对象": ["值班医生", "护士长", "科主任"]
                },
                "日度质量报告": {
                    "生成时间": "每日8:00",
                    "包含内容": [
                        "昨日指标汇总",
                        "异常情况分析",
                        "改进建议"
                    ],
                    "发送对象": ["医务科", "护理部", "质控科"]
                },
                "周度分析报告": {
                    "生成时间": "每周一9:00",
                    "包含内容": [
                        "周度指标趋势",
                        "科室对比分析",
                        "质量改进跟踪"
                    ],
                    "发送对象": ["院领导", "科主任", "护士长"]
                },
                "月度综合报告": {
                    "生成时间": "每月1日",
                    "包含内容": [
                        "月度指标评估",
                        "质量改进成效",
                        "下月工作重点"
                    ],
                    "发送对象": ["院长", "副院长", "质控委员会"]
                }
            }
        }
    
    def calculate_indicator_value(self, indicator_name: str, data: Dict[str, Any]) -> float:
        """计算指标值"""
        calculation_rules = {
            "院内感染率": lambda d: (d.get("院内感染人数", 0) / max(d.get("住院总人数", 1), 1)) * 100,
            "药物不良反应率": lambda d: (d.get("药物不良反应人数", 0) / max(d.get("用药总人数", 1), 1)) * 100,
            "手术并发症率": lambda d: (d.get("手术并发症人数", 0) / max(d.get("手术总人数", 1), 1)) * 100,
            "平均住院日": lambda d: d.get("总住院天数", 0) / max(d.get("出院人数", 1), 1),
            "床位使用率": lambda d: (d.get("实际占用床日数", 0) / max(d.get("开放床日数", 1), 1)) * 100,
            "门诊预约率": lambda d: (d.get("预约门诊人数", 0) / max(d.get("门诊总人数", 1), 1)) * 100,
            "患者满意度": lambda d: (d.get("满意患者数", 0) / max(d.get("调查患者数", 1), 1)) * 100,
            "药占比": lambda d: (d.get("药品费用", 0) / max(d.get("医疗总费用", 1), 1)) * 100,
            "医疗收入增长率": lambda d: ((d.get("本期收入", 0) - d.get("上期收入", 0)) / max(d.get("上期收入", 1), 1)) * 100
        }
        
        if indicator_name in calculation_rules:
            try:
                return calculation_rules[indicator_name](data)
            except Exception as e:
                print(f"计算指标 {indicator_name} 时出错: {e}")
                return 0.0
        else:
            return data.get(indicator_name, 0.0)
    
    def evaluate_indicator(self, indicator_name: str, value: float, category: str) -> Dict[str, Any]:
        """评估指标状态"""
        if category not in self.indicators or indicator_name not in self.indicators[category]:
            return {"status": "unknown", "level": "绿色", "message": "指标未定义"}
        
        indicator_config = self.indicators[category][indicator_name]
        target_value = indicator_config["目标值"]
        warning_threshold = indicator_config["预警阈值"]
        danger_threshold = indicator_config["危险阈值"]
        
        # 判断指标状态
        if self.meets_target(value, target_value):
            return {
                "status": "normal",
                "level": "绿色",
                "message": "指标正常",
                "score": 100
            }
        elif self.exceeds_threshold(value, warning_threshold):
            if self.exceeds_threshold(value, danger_threshold):
                return {
                    "status": "danger",
                    "level": "红色",
                    "message": "指标严重异常",
                    "score": 30
                }
            else:
                return {
                    "status": "warning",
                    "level": "橙色",
                    "message": "指标异常",
                    "score": 60
                }
        else:
            return {
                "status": "attention",
                "level": "黄色",
                "message": "指标需要关注",
                "score": 80
            }
    
    def meets_target(self, value: float, target_str: str) -> bool:
        """检查是否达到目标值"""
        try:
            if '<' in target_str:
                threshold = float(target_str.replace('<', '').replace('%', '').replace('天', '').replace('分钟', '').strip())
                return value < threshold
            elif '>' in target_str:
                threshold = float(target_str.replace('>', '').replace('%', '').replace('天', '').replace('分钟', '').strip())
                return value > threshold
            elif '-' in target_str and '合理区间' not in target_str:
                parts = target_str.replace('%', '').split('-')
                min_val = float(parts[0].strip())
                max_val = float(parts[1].strip())
                return min_val <= value <= max_val
            else:
                return True  # 对于"合理区间"等描述性目标,默认为达标
        except:
            return True
    
    def exceeds_threshold(self, value: float, threshold_str: str) -> bool:
        """检查是否超过阈值"""
        try:
            if '>' in threshold_str:
                threshold = float(threshold_str.replace('>', '').replace('%', '').replace('天', '').replace('分钟', '').strip())
                return value > threshold
            elif '<' in threshold_str:
                threshold = float(threshold_str.replace('<', '').replace('%', '').replace('天', '').replace('分钟', '').strip())
                return value < threshold
            elif '或' in threshold_str:
                # 处理类似 "< 80% 或 > 98%" 的情况
                conditions = threshold_str.split('或')
                return any(self.exceeds_threshold(value, cond.strip()) for cond in conditions)
            elif '偏离合理区间' in threshold_str:
                # 处理偏离百分比的情况
                percentage = float(threshold_str.replace('偏离合理区间', '').replace('%', '').strip())
                # 这里需要根据具体的合理区间来判断,简化处理
                return abs(value - 100) > percentage  # 假设合理区间中心值为100
            else:
                return False
        except:
            return False
    
    def monitor_indicators(self, hospital_data: Dict[str, Any]) -> Dict[str, Any]:
        """监控所有指标"""
        monitoring_result = {
            "监控时间": datetime.datetime.now().isoformat(),
            "医院名称": hospital_data.get("hospital_name", "未知医院"),
            "指标评估": {},
            "总体状态": "绿色",
            "预警信息": [],
            "改进建议": []
        }
        
        all_scores = []
        alert_levels = []
        
        # 遍历所有指标类别
        for category, indicators in self.indicators.items():
            monitoring_result["指标评估"][category] = {}
            
            for indicator_name, indicator_config in indicators.items():
                # 计算指标值
                indicator_value = self.calculate_indicator_value(indicator_name, hospital_data)
                
                # 评估指标状态
                evaluation = self.evaluate_indicator(indicator_name, indicator_value, category)
                
                # 记录评估结果
                monitoring_result["指标评估"][category][indicator_name] = {
                    "当前值": indicator_value,
                    "目标值": indicator_config["目标值"],
                    "状态": evaluation["status"],
                    "级别": evaluation["level"],
                    "消息": evaluation["message"],
                    "评分": evaluation["score"],
                    "责任科室": indicator_config["责任科室"]
                }
                
                all_scores.append(evaluation["score"])
                alert_levels.append(evaluation["level"])
                
                # 生成预警信息
                if evaluation["status"] != "normal":
                    alert = {
                        "指标名称": indicator_name,
                        "指标类别": category,
                        "当前值": indicator_value,
                        "预警级别": evaluation["level"],
                        "预警消息": evaluation["message"],
                        "责任科室": indicator_config["责任科室"],
                        "建议措施": self.get_improvement_suggestion(indicator_name, evaluation["status"])
                    }
                    monitoring_result["预警信息"].append(alert)
        
        # 计算总体评分
        overall_score = sum(all_scores) / len(all_scores) if all_scores else 100
        
        # 确定总体状态
        if "红色" in alert_levels:
            monitoring_result["总体状态"] = "红色"
        elif "橙色" in alert_levels:
            monitoring_result["总体状态"] = "橙色"
        elif "黄色" in alert_levels:
            monitoring_result["总体状态"] = "黄色"
        else:
            monitoring_result["总体状态"] = "绿色"
        
        monitoring_result["总体评分"] = overall_score
        
        # 生成改进建议
        monitoring_result["改进建议"] = self.generate_improvement_recommendations(monitoring_result["预警信息"])
        
        return monitoring_result
    
    def get_improvement_suggestion(self, indicator_name: str, status: str) -> str:
        """获取改进建议"""
        suggestions = {
            "院内感染率": {
                "warning": "加强手卫生管理,完善感控制度",
                "danger": "立即启动感控应急预案,全面排查感染源"
            },
            "药物不良反应率": {
                "warning": "加强用药监测,完善ADR报告制度",
                "danger": "立即审查用药安全,暂停可疑药物使用"
            },
            "手术并发症率": {
                "warning": "加强术前评估,完善手术质量管理",
                "danger": "立即审查手术流程,暂停高风险手术"
            },
            "平均住院日": {
                "warning": "优化诊疗流程,加强出院管理",
                "danger": "全面审查住院必要性,加快床位周转"
            },
            "患者满意度": {
                "warning": "改善服务态度,优化就医流程",
                "danger": "立即整改服务问题,加强患者沟通"
            }
        }
        
        if indicator_name in suggestions and status in suggestions[indicator_name]:
            return suggestions[indicator_name][status]
        else:
            return "请联系相关科室制定改进措施"
    
    def generate_improvement_recommendations(self, alerts: List[Dict[str, Any]]) -> List[str]:
        """生成改进建议"""
        recommendations = []
        
        # 按科室分组预警
        department_alerts = {}
        for alert in alerts:
            dept = alert["责任科室"]
            if dept not in department_alerts:
                department_alerts[dept] = []
            department_alerts[dept].append(alert)
        
        # 为每个科室生成建议
        for dept, dept_alerts in department_alerts.items():
            if len(dept_alerts) > 1:
                recommendations.append(f"{dept}需要重点关注多项指标异常,建议制定综合改进方案")
            else:
                alert = dept_alerts[0]
                recommendations.append(f"{dept}需要关注{alert['指标名称']}{alert['建议措施']}")
        
        # 添加总体建议
        if len(alerts) > 5:
            recommendations.append("多项指标异常,建议启动质量改进专项行动")
        elif len(alerts) == 0:
            recommendations.append("所有指标正常,继续保持良好的医疗质量管理")
        
        return recommendations
    
    def generate_monitoring_report(self, monitoring_result: Dict[str, Any]) -> str:
        """生成监控报告"""
        report = f"""
=== 医疗指标监控报告 ===

监控时间: {monitoring_result['监控时间']}
医院名称: {monitoring_result['医院名称']}
总体状态: {monitoring_result['总体状态']}
总体评分: {monitoring_result['总体评分']:.1f}

=== 指标评估详情 ===
"""
        
        for category, indicators in monitoring_result["指标评估"].items():
            report += f"\n【{category}】\n"
            for indicator_name, result in indicators.items():
                status_icon = {
                    "绿色": "✅",
                    "黄色": "⚠️",
                    "橙色": "🔶",
                    "红色": "❌"
                }.get(result["级别"], "❓")
                
                report += f"  {status_icon} {indicator_name}: {result['当前值']:.2f} (目标: {result['目标值']}) - {result['消息']}\n"
        
        if monitoring_result["预警信息"]:
            report += f"\n=== 预警信息 ===\n"
            for i, alert in enumerate(monitoring_result["预警信息"], 1):
                report += f"{i}. 【{alert['预警级别']}{alert['指标名称']}: {alert['预警消息']}\n"
                report += f"   责任科室: {alert['责任科室']}\n"
                report += f"   建议措施: {alert['建议措施']}\n\n"
        
        if monitoring_result["改进建议"]:
            report += f"=== 改进建议 ===\n"
            for i, suggestion in enumerate(monitoring_result["改进建议"], 1):
                report += f"{i}. {suggestion}\n"
        
        return report
    
    def save_monitoring_data(self, monitoring_result: Dict[str, Any]):
        """保存监控数据"""
        timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
        hospital_name = monitoring_result.get("医院名称", "unknown")
        
        # 保存到历史数据
        if hospital_name not in self.historical_data:
            self.historical_data[hospital_name] = []
        
        self.historical_data[hospital_name].append({
            "timestamp": timestamp,
            "data": monitoring_result
        })
        
        # 保留最近30天的数据
        cutoff_date = datetime.datetime.now() - datetime.timedelta(days=30)
        cutoff_timestamp = cutoff_date.strftime("%Y%m%d_%H%M%S")
        
        self.historical_data[hospital_name] = [
            record for record in self.historical_data[hospital_name]
            if record["timestamp"] >= cutoff_timestamp
        ]
    
    def get_trend_analysis(self, hospital_name: str, indicator_name: str, days: int = 7) -> Dict[str, Any]:
        """获取趋势分析"""
        if hospital_name not in self.historical_data:
            return {"error": "没有历史数据"}
        
        # 获取最近几天的数据
        cutoff_date = datetime.datetime.now() - datetime.timedelta(days=days)
        cutoff_timestamp = cutoff_date.strftime("%Y%m%d_%H%M%S")
        
        recent_data = [
            record for record in self.historical_data[hospital_name]
            if record["timestamp"] >= cutoff_timestamp
        ]
        
        if not recent_data:
            return {"error": "没有足够的历史数据"}
        
        # 提取指标值
        values = []
        timestamps = []
        
        for record in recent_data:
            # 在指标评估中查找指标值
            for category, indicators in record["data"]["指标评估"].items():
                if indicator_name in indicators:
                    values.append(indicators[indicator_name]["当前值"])
                    timestamps.append(record["timestamp"])
                    break
        
        if not values:
            return {"error": f"未找到指标 {indicator_name} 的数据"}
        
        # 计算趋势
        if len(values) >= 2:
            trend = "上升" if values[-1] > values[0] else "下降" if values[-1] < values[0] else "稳定"
            change_rate = ((values[-1] - values[0]) / values[0]) * 100 if values[0] != 0 else 0
        else:
            trend = "稳定"
            change_rate = 0
        
        return {
            "indicator_name": indicator_name,
            "period": f"最近{days}天",
            "data_points": len(values),
            "current_value": values[-1] if values else 0,
            "initial_value": values[0] if values else 0,
            "trend": trend,
            "change_rate": change_rate,
            "values": values,
            "timestamps": timestamps
        }

# 创建医疗指标监控器实例
indicator_monitor = MedicalIndicatorMonitor()

# 示例:监控医院指标
sample_hospital_data = {
    "hospital_name": "第一人民医院",
    "院内感染人数": 15,
    "住院总人数": 800,
    "药物不良反应人数": 5,
    "用药总人数": 1200,
    "手术并发症人数": 3,
    "手术总人数": 150,
    "总住院天数": 6800,
    "出院人数": 680,
    "实际占用床日数": 720,
    "开放床日数": 800,
    "预约门诊人数": 2400,
    "门诊总人数": 3000,
    "满意患者数": 450,
    "调查患者数": 500,
    "药品费用": 1500000,
    "医疗总费用": 5000000,
    "本期收入": 5200000,
    "上期收入": 5000000
}

print("=== 医疗指标监控示例 ===\n")

# 执行监控
monitoring_result = indicator_monitor.monitor_indicators(sample_hospital_data)

# 生成报告
report = indicator_monitor.generate_monitoring_report(monitoring_result)
print(report)

# 保存监控数据
indicator_monitor.save_monitoring_data(monitoring_result)

# 趋势分析示例
trend_analysis = indicator_monitor.get_trend_analysis("第一人民医院", "院内感染率", 7)
if "error" not in trend_analysis:
    print(f"\n=== 趋势分析 ===")
    print(f"指标: {trend_analysis['indicator_name']}")
    print(f"时间段: {trend_analysis['period']}")
    print(f"趋势: {trend_analysis['trend']}")
    print(f"变化率: {trend_analysis['change_rate']:.2f}%")

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CarlowZJ

我的文章对你有用的话,可以支持

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值