# 医生患者多对多关系实现说明 ## 一、背景分析 ### 1.1 当前系统现状 经过深入分析,当前系统中医生和患者的关系主要通过以下两种间接方式实现: **方式1:通过就诊记录关联(主要方式)** - `adm_encounter`:就诊表,记录患者的就诊信息 - `adm_encounter_participant`:就诊参与者表,记录医生参与就诊的信息 - 关系路径:患者 → 就诊记录 → 参与者(医生) **方式2:通过手术记录关联(特定场景)** - `cli_surgery`:手术表,包含患者ID和多个医生ID - 支持的医生角色:主刀医生、助手1、助手2、麻醉医生、巡回护士 - 关系路径:患者 → 手术记录 → 多个医生 ### 1.2 存在的问题 1. **缺乏长期医患关系管理** - 无法管理固定的主治医生、签约医生等长期关系 - 每次就诊都需要重新关联医生和患者 2. **查询效率低下** - 需要通过多层关联查询才能获取某医生的所有患者 - 无法快速查询某患者的所有就诊医生 3. **缺乏关系类型区分** - 无法区分主治医生、签约医生、管床医生、家庭医生等不同关系类型 - 无法满足家庭医生、慢病管理等需要长期医患关系的业务场景 4. **无法支持复杂业务需求** - 家庭医生签约服务 - 慢病随访管理 - 患者分组管理 - 医生工作量统计 ## 二、解决方案 ### 2.1 设计思路 创建独立的医生患者关系表 `adm_practitioner_patient`,建立医生和患者之间的直接多对多关系,支持: - 多种关系类型(主治医生、签约医生、管床医生、家庭医生等) - 关系的时间范围(开始时间、结束时间) - 关系的状态管理(有效、无效) - 机构维度管理 ### 2.2 数据库设计 #### 表结构:adm_practitioner_patient | 字段名 | 类型 | 说明 | |--------|------|------| | id | int8 | 主键ID | | practitioner_id | int8 | 医生ID,关联adm_practitioner表 | | patient_id | int8 | 患者ID,关联adm_patient表 | | relationship_type | int4 | 关系类型:1-主治医生,2-签约医生,3-管床医生,4-家庭医生,5-会诊医生,6-随访医生 | | organization_id | int8 | 机构ID,关联adm_organization表 | | start_date | timestamptz | 关系开始时间 | | end_date | timestamptz | 关系结束时间 | | status | int4 | 状态:1-有效,0-无效 | | remark | varchar(500) | 备注信息 | | tenant_id | int4 | 租户ID | | delete_flag | bpchar(1) | 删除标志 | | create_by | varchar(32) | 创建人 | | create_time | timestamptz | 创建时间 | | update_by | varchar(32) | 更新人 | | update_time | timestamptz | 更新时间 | #### 索引设计 - `idx_practitioner_patient_practitioner_id`:按医生ID查询 - `idx_practitioner_patient_patient_id`:按患者ID查询 - `idx_practitioner_patient_org_id`:按机构ID查询 - `idx_practitioner_patient_type`:按关系类型查询 ### 2.3 业务逻辑 #### 1. 创建医患关系 - 检查是否已存在相同的关系 - 如果存在,先终止旧关系 - 创建新的有效关系 - 记录关系开始时间 #### 2. 终止医患关系 - 设置关系结束时间为当前时间 - 更新状态为无效(status=0) #### 3. 查询有效关系 - 查询条件:status=1 且 delete_flag='0' - 支持按医生、患者、机构、关系类型等多维度查询 #### 4. 批量创建关系 - 支持批量创建医患关系 - 适用于科室分组、团队管理等场景 ## 三、功能实现 ### 3.1 后端实现 #### 实体类 - `PractitionerPatient.java`:医生患者关系实体 #### 数据访问层 - `PractitionerPatientMapper.java`:Mapper接口 - `PractitionerPatientMapper.xml`:MyBatis映射文件 #### 业务逻辑层 - `IPractitionerPatientService.java`:Service接口 - `PractitionerPatientServiceImpl.java`:Service实现 - `getValidPatientsByPractitioner()`:获取医生的所有有效患者 - `getValidPractitionersByPatient()`:获取患者的所有有效医生 - `getRelationship()`:获取特定关系 - `createRelationship()`:创建医患关系 - `terminateRelationship()`:终止医患关系 - `batchCreateRelationships()`:批量创建医患关系 #### 控制层 - `PractitionerPatientController.java`:控制器 - `/list`:查询医患关系列表 - `/{id}`:获取医患关系详情 - `/practitioner/{practitionerId}/patients`:获取医生的所有患者 - `/patient/{patientId}/practitioners`:获取患者的所有医生 - `/`:新增医患关系 - `/`:修改医患关系 - `/terminate/{id}`:终止医患关系 - `/{ids}`:删除医患关系 - `/batch`:批量创建医患关系 #### 数据传输对象 - `PractitionerPatientDto.java`:医患关系DTO ### 3.2 前端实现 #### API接口 - `practitionerPatient.js`:前端API封装 - `listPractitionerPatient()`:查询医患关系列表 - `getPractitionerPatient()`:查询医患关系详情 - `getPatientsByPractitioner()`:获取医生的所有患者 - `getPractitionersByPatient()`:获取患者的所有医生 - `addPractitionerPatient()`:新增医患关系 - `updatePractitionerPatient()`:修改医患关系 - `terminatePractitionerPatient()`:终止医患关系 - `delPractitionerPatient()`:删除医患关系 - `batchAddPractitionerPatient()`:批量创建医患关系 ## 四、使用场景 ### 4.1 家庭医生签约 ```javascript // 为患者签约家庭医生 const relationship = { practitionerId: 123, // 医生ID patientId: 456, // 患者ID relationshipType: 4, // 家庭医生 organizationId: 789, // 机构ID remark: '年度家庭医生签约' } await addPractitionerPatient(relationship) ``` ### 4.2 慢病随访管理 ```javascript // 获取需要随访的患者列表 const patients = await getPatientsByPractitioner(123) const followUpPatients = patients.filter(p => p.relationshipType === 6 && // 随访医生 new Date(p.startDate) < new Date() && !p.endDate ) ``` ### 4.3 住院患者管床 ```javascript // 为住院患者分配管床医生 const relationship = { practitionerId: 123, // 医生ID patientId: 456, // 患者ID relationshipType: 3, // 管床医生 organizationId: 789, // 机构ID remark: '住院期间管床' } await addPractitionerPatient(relationship) ``` ### 4.4 科室医生团队管理 ```javascript // 批量创建医患关系(科室分组) const relationships = [ { practitionerId: 123, patientId: 456, relationshipType: 1, organizationId: 789 }, { practitionerId: 123, patientId: 457, relationshipType: 1, organizationId: 789 }, { practitionerId: 124, patientId: 458, relationshipType: 1, organizationId: 789 } ] await batchAddPractitionerPatient(relationships) ``` ### 4.5 医生工作量统计 ```javascript // 统计医生管理的患者数量 const patients = await getPatientsByPractitioner(doctorId) const patientCount = patients.length console.log(`该医生管理了 ${patientCount} 位患者`) // 按关系类型统计 const主治医生Count = patients.filter(p => p.relationshipType === 1).length const签约医生Count = patients.filter(p => p.relationshipType === 2).length const管床医生Count = patients.filter(p => p.relationshipType === 3).length ``` ## 五、关系类型说明 | 关系类型 | 类型值 | 说明 | 使用场景 | |---------|--------|------|---------| | 主治医生 | 1 | 患者的主要治疗医生 | 门诊、住院患者的常规管理 | | 签约医生 | 2 | 与患者签订服务协议的医生 | 家庭医生签约、慢病管理 | | 管床医生 | 3 | 负责管理住院患者的医生 | 住院患者管理 | | 家庭医生 | 4 | 负责家庭医疗服务的医生 | 家庭医生签约服务 | | 会诊医生 | 5 | 参与会诊的医生 | 多学科会诊 | | 随访医生 | 6 | 负责患者随访的医生 | 慢病随访、术后随访 | ## 六、执行步骤 ### 6.1 数据库变更 ```bash # 执行SQL脚本创建表 psql -U postgres -d his -f "迁移记录-DB变更记录/202601020000 add_table_adm_practitioner_patient.sql" ``` ### 6.2 后端部署 1. 将以下文件复制到对应目录: - `PractitionerPatient.java` → `openhis-domain/src/main/java/com/openhis/administration/domain/` - `PractitionerPatientMapper.java` → `openhis-domain/src/main/java/com/openhis/administration/mapper/` - `PractitionerPatientMapper.xml` → `openhis-domain/src/main/resources/mapper/administration/` - `IPractitionerPatientService.java` → `openhis-domain/src/main/java/com/openhis/administration/service/` - `PractitionerPatientServiceImpl.java` → `openhis-domain/src/main/java/com/openhis/administration/service/impl/` - `PractitionerPatientDto.java` → `openhis-domain/src/main/java/com/openhis/administration/dto/` - `PractitionerPatientController.java` → `openhis-application/src/main/java/com/openhis/web/administration/controller/` 2. 重新编译并启动后端服务 ### 6.3 前端部署 1. 将以下文件复制到对应目录: - `practitionerPatient.js` → `openhis-ui-vue3/src/api/administration/` 2. 重新编译并启动前端服务 ## 七、注意事项 1. **数据一致性** - 创建关系前先检查是否已存在相同的关系 - 如果存在,先终止旧关系再创建新关系 2. **时间管理** - 关系开始时间默认为当前时间 - 终止关系时需要设置结束时间 3. **权限控制** - 创建医患关系需要相应权限 - 终止医患关系需要相应权限 4. **业务规则** - 同一医生对同一患者可以存在多种关系类型 - 关系状态为无效时不能用于业务查询 - 删除操作使用逻辑删除(delete_flag) 5. **性能优化** - 已创建合适的索引 - 查询时使用条件过滤(status=1, delete_flag='0') ## 八、后续扩展 1. **医患关系历史记录** - 记录医患关系变更历史 - 支持回溯查看历史关系 2. **医患关系评价** - 患者对医生的评价 - 医生对患者的评价 3. **医患关系可视化** - 医患关系图谱 - 医生患者网络分析 4. **医患关系提醒** - 关系到期提醒 - 随访提醒 - 复诊提醒 5. **数据统计** - 医生工作量统计 - 患者分布统计 - 关系类型统计