# super/institution 接口说明 ## 接口概述 **接口路径**: `POST super/institution` **功能**: 获取当前医生所在机构可访问的上级医院列表(用于远程诊断申请) **业务场景**: - 下级医院申请远程诊断时,需要选择上级医院 - 返回两类机构:普通远程合作机构 + 特殊远程机构(如专家会诊平台) --- ## 调用链路 ``` Route (route.php) ↓ SuperController::institution_list() ↓ SuperService::getParentInstitution($institution_id) ↓ SuperDao (wrapper层) ↓ InstitutionModel (实际SQL查询) ``` --- ## 核心逻辑流程 ### 1. Controller 层 **文件**: `controller/super/SuperController.php` ```php public function institution_list(SuperService $service) { // 1. 从token获取当前医生信息 $doctor = $service->getUser($this->getToken()); // 2. 根据医生所在机构ID查询可访问的上级机构 $info = $service->getParentInstitution($doctor['institution_id']); // 3. 返回结果 return $this->success($info); } ``` --- ### 2. Service 层 **文件**: `services/super/SuperService.php` ```php public function getParentInstitution($institution) { // 1. 获取该机构配置的远程合作医院ID列表 $hospitanInfo = $this->super->getRemoteIns($institution); $ids = $hospitanInfo; $parent = []; // 2. 获取特殊远程机构(专家会诊平台等,所有机构都可访问) $special = $this->super->getSpecialIns(); // 3. 添加特殊机构到返回列表 foreach ($special as $k => $v) { $s = []; $s['id'] = $v['id']; $s['name'] = $v['hospital_name']; $s['is_special'] = $v['is_special']; // 标记为特殊机构 $parent[] = $s; } // 4. 添加普通远程合作机构(并获取支付类型配置) foreach($ids as $k => $v) { // 查询当前机构与上级机构的支付方式配置 $pay = $this->super->getPayType($institution, $v); if($pay == null) { $pay = '0'; // 默认患者支付 } // 构造查询字段 $pField = [ 'id', 'name', '2 as is_special', // 普通远程机构标记为2 'id as hid', "$pay as pay_type" // 支付类型 ]; // 获取机构详细信息 $parent[] = $this->super->getInstitutionInfo($v, $pField); } return $parent; } ``` **返回数据结构**: ```json [ { "id": "机构ID", "name": "机构名称", "is_special": "1=特殊机构, 2=普通远程机构", "hid": "机构ID(普通远程机构才有)", "pay_type": "支付类型(普通远程机构才有, 0=患者支付, 1=医院挂账)" } ] ``` --- ### 3. Model 层 - SQL 查询 **文件**: `model/institution/InstitutionModel.php` #### 3.1 获取远程合作机构列表 ```php public function getRemoteIns($id) { // 查询 remote_contact 表,获取该机构配置的所有上级机构ID $info = RcontactModel::where('hospital_id', $id) ->column('super_hospital_id'); return $info; } ``` **等价SQL**: ```sql SELECT super_hospital_id FROM remote_contact WHERE hospital_id = :id ``` **涉及表**: `remote_contact` (远程诊断关系表) --- #### 3.2 获取特殊远程机构 ```php public function getSpecialIns() { // 查询 special_remote 表,获取所有启用的特殊机构(按排序) $info = SremoteModel::where('status', 1) ->order('sort asc') ->field('id, name as hospital_name, 1 as is_special') ->select(); return $info; } ``` **等价SQL**: ```sql SELECT id, name as hospital_name, 1 as is_special FROM special_remote WHERE status = 1 ORDER BY sort ASC ``` **涉及表**: `special_remote` (特殊远程机构表) --- #### 3.3 获取支付类型配置 ```php public function getPayType($local, $super) { // 查询下级机构与上级机构的支付方式配置 $type = RcontactModel::where('hospital_id', $local) ->where('super_hospital_id', $super) ->value('pay_type'); return $type; } ``` **等价SQL**: ```sql SELECT pay_type FROM remote_contact WHERE hospital_id = :local AND super_hospital_id = :super ``` **支付类型说明**: - `0` = 患者支付(患者直接支付远程诊断费用) - `1` = 医院挂账(下级医院与上级医院结算,患者不直接支付) --- #### 3.4 获取机构详细信息 ```php public function getInfo($id, $field) { // 根据ID和指定字段查询机构信息 $info = $this->where('id', $id) ->field($field) ->find(); return $info; } ``` **等价SQL**: ```sql SELECT {field} FROM institution WHERE id = :id ``` **涉及表**: `institution` (机构表) --- ## 数据库表结构 ### 1. remote_contact (远程诊断关系表) | 字段名 | 类型 | 说明 | |--------|------|------| | id | int | 主键 | | hospital_id | varchar(32) | 下级医院ID | | hospital_name | varchar(100) | 下级医院名称 | | super_hospital_id | varchar(32) | 上级医院ID | | super_hospital_name | varchar(100) | 上级医院名称 | | **pay_type** | int | **支付类型**: 0=患者支付, 1=医院挂账 | | lower_ratio | int | 下级医院分成比例 (默认35%) | | super_ratio | int | 上级医院分成比例 (默认50%) | | zskk_ratio | int | 平台分成比例 (默认15%) | | status | int | 状态: 1=正常, 0=禁用 | | sort | int | 排序号 | | create_time | datetime | 创建时间 | | update_time | datetime | 更新时间 | **索引**: - `hospital_id_index` (hospital_id) - `super_hospital_id_index` (super_hospital_id) --- ### 2. special_remote (特殊远程机构表) **说明**: 该表在新项目中**尚未创建**,需要补充。 **预期字段**: ```sql CREATE TABLE `special_remote` ( `id` varchar(32) NOT NULL COMMENT '机构ID', `name` varchar(100) NOT NULL COMMENT '机构名称', `status` int DEFAULT 1 COMMENT '状态: 1=启用, 0=禁用', `sort` int DEFAULT 0 COMMENT '排序号', `create_time` datetime DEFAULT CURRENT_TIMESTAMP, `update_time` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`) ) ENGINE=InnoDB COMMENT='特殊远程机构表(专家会诊平台等)'; ``` **特殊机构说明**: - 所有机构都可以访问(不需要在 remote_contact 中配置关系) - 通常是专家会诊平台、知名医院专家团队等 - 支持自定义排序(优先展示) --- ### 3. special_contact (特殊机构联系表) **说明**: 用于配置特殊机构的医生联系方式和费用,该表在新项目中**尚未创建**。 **预期字段**: ```sql CREATE TABLE `special_contact` ( `id` int NOT NULL AUTO_INCREMENT, `sid` varchar(32) COMMENT '特殊机构ID', `did` varchar(32) COMMENT '医生ID', `hid` varchar(32) COMMENT '机构ID', `cost` int DEFAULT 0 COMMENT '费用(分)', `describe` text COMMENT '医生介绍', `status` int DEFAULT 1 COMMENT '状态: 1=启用, 0=禁用', `sort` int DEFAULT 0 COMMENT '排序', `create_time` datetime DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`) ) ENGINE=InnoDB COMMENT='特殊机构联系配置表'; ``` --- ## 业务规则总结 ### 机构类型区分 | 类型 | is_special | 来源表 | 访问权限 | 支付配置 | |------|-----------|--------|---------|---------| | 特殊机构 | 1 | special_remote | 所有机构 | 在 special_contact 中配置 | | 普通远程机构 | 2 | institution | 需配置关系 | 在 remote_contact 中配置 | ### 支付类型说明 - **pay_type = 0 (患者支付)**: - 患者在申请远程诊断时直接支付费用 - 费用分成按比例分配:下级(35%) + 上级(50%) + 平台(15%) - **pay_type = 1 (医院挂账)**: - 患者不直接支付 - 下级医院与上级医院按月或按单结算 - 平台从医院结算中抽成 --- ## Java 实现建议 ### 1. 实体类 #### RemoteContact.java ```java @Data @TableName("remote_contact") public class RemoteContact { @TableId(type = IdType.AUTO) private Integer id; @TableField("hospital_id") private String hospitalId; @TableField("hospital_name") private String hospitalName; @TableField("super_hospital_id") private String superHospitalId; @TableField("super_hospital_name") private String superHospitalName; @TableField("pay_type") private Integer payType; // 0=患者支付, 1=医院挂账 @TableField("lower_ratio") private Integer lowerRatio; @TableField("super_ratio") private Integer superRatio; @TableField("zskk_ratio") private Integer zskkRatio; @TableField("status") private Integer status; @TableField("sort") private Integer sort; @TableField("create_time") private Date createTime; @TableField("update_time") private Date updateTime; } ``` #### SpecialRemote.java (待创建表) ```java @Data @TableName("special_remote") public class SpecialRemote { @TableId(type = IdType.ASSIGN_UUID) private String id; @TableField("name") private String name; @TableField("status") private Integer status; @TableField("sort") private Integer sort; @TableField("create_time") private Date createTime; @TableField("update_time") private Date updateTime; } ``` --- ### 2. DTO #### InstitutionListDTO.java ```java @Data @Schema(description = "上级机构列表项") public class InstitutionListDTO { @Schema(description = "机构ID") private String id; @Schema(description = "机构名称") private String name; @Schema(description = "机构类型: 1=特殊机构, 2=普通远程机构") private Integer isSpecial; @Schema(description = "机构ID(普通远程机构)") private String hid; @Schema(description = "支付类型: 0=患者支付, 1=医院挂账") private Integer payType; } ``` --- ### 3. Service 实现 ```java @Service public class SuperServiceImpl implements SuperService { @Resource private RemoteContactMapper remoteContactMapper; @Resource private SpecialRemoteMapper specialRemoteMapper; @Resource private InstitutionMapper institutionMapper; @Override public List getParentInstitution(String institutionId) { List result = new ArrayList<>(); // 1. 获取特殊远程机构(所有机构都可访问) List specialList = getSpecialInstitutions(); for (SpecialRemote special : specialList) { InstitutionListDTO dto = new InstitutionListDTO(); dto.setId(special.getId()); dto.setName(special.getName()); dto.setIsSpecial(1); // 特殊机构 result.add(dto); } // 2. 获取该机构配置的远程合作机构 List remoteIds = getRemoteInstitutionIds(institutionId); for (String remoteId : remoteIds) { // 查询支付类型 Integer payType = getPayType(institutionId, remoteId); if (payType == null) { payType = 0; // 默认患者支付 } // 查询机构信息 Institution institution = institutionMapper.selectById(remoteId); if (institution != null) { InstitutionListDTO dto = new InstitutionListDTO(); dto.setId(institution.getId()); dto.setName(institution.getName()); dto.setIsSpecial(2); // 普通远程机构 dto.setHid(institution.getId()); dto.setPayType(payType); result.add(dto); } } return result; } /** * 获取特殊远程机构列表 */ private List getSpecialInstitutions() { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.eq(SpecialRemote::getStatus, 1) .orderByAsc(SpecialRemote::getSort); return specialRemoteMapper.selectList(wrapper); } /** * 获取远程合作机构ID列表 */ private List getRemoteInstitutionIds(String institutionId) { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.eq(RemoteContact::getHospitalId, institutionId) .eq(RemoteContact::getStatus, 1); List contacts = remoteContactMapper.selectList(wrapper); return contacts.stream() .map(RemoteContact::getSuperHospitalId) .collect(Collectors.toList()); } /** * 获取支付类型配置 */ private Integer getPayType(String localId, String superId) { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.eq(RemoteContact::getHospitalId, localId) .eq(RemoteContact::getSuperHospitalId, superId); RemoteContact contact = remoteContactMapper.selectOne(wrapper); return contact != null ? contact.getPayType() : null; } } ``` --- ### 4. Controller ```java @RestController @RequestMapping("/api/super") @Tag(name = "上级机构管理", description = "远程诊断相关接口") public class SuperController { @Resource private SuperService superService; @Resource private JwtUtil jwtUtil; @Operation( summary = "获取上级机构列表", description = "获取当前机构可访问的上级医院列表," + "包括特殊远程机构(所有人可见)和配置的远程合作机构" ) @PostMapping("/institution") public RestResult getInstitutionList(HttpServletRequest request) { try { // 1. 从token获取当前机构ID String token = getTokenFromRequest(request); String institutionId = jwtUtil.getCurrentOrgFromToken(token); if (StringUtils.isBlank(institutionId)) { return RestResult.error("无法获取机构信息"); } // 2. 查询可访问的上级机构列表 List list = superService.getParentInstitution(institutionId); return RestResult.ok("查询成功", list); } catch (Exception e) { return RestResult.error("查询失败:" + e.getMessage()); } } private String getTokenFromRequest(HttpServletRequest request) { String token = request.getHeader("Authorization"); if (StringUtils.isBlank(token)) { token = request.getHeader("token"); } return token; } } ``` --- ## 待办事项 ### 1. 数据库表创建 需要创建以下表: ```sql -- 特殊远程机构表 CREATE TABLE `special_remote` ( `id` varchar(32) NOT NULL COMMENT '机构ID', `name` varchar(100) NOT NULL COMMENT '机构名称', `description` text COMMENT '机构描述', `status` int DEFAULT 1 COMMENT '状态: 1=启用, 0=禁用', `sort` int DEFAULT 0 COMMENT '排序号', `create_time` datetime DEFAULT CURRENT_TIMESTAMP, `update_time` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`) ) ENGINE=InnoDB COMMENT='特殊远程机构表'; -- 特殊机构联系表 CREATE TABLE `special_contact` ( `id` int NOT NULL AUTO_INCREMENT, `sid` varchar(32) COMMENT '特殊机构ID', `did` varchar(32) COMMENT '医生ID', `hid` varchar(32) COMMENT '机构ID', `cost` int DEFAULT 0 COMMENT '费用(分)', `describe` text COMMENT '医生介绍', `status` int DEFAULT 1 COMMENT '状态: 1=启用, 0=禁用', `sort` int DEFAULT 0 COMMENT '排序', `create_time` datetime DEFAULT CURRENT_TIMESTAMP, `update_time` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`), KEY `idx_sid` (`sid`), KEY `idx_did` (`did`) ) ENGINE=InnoDB COMMENT='特殊机构联系配置表'; ``` ### 2. Java 代码生成 - [ ] 生成 RemoteContact 相关代码(Entity/Mapper/Service) - [ ] 生成 SpecialRemote 相关代码(Entity/Mapper/Service) - [ ] 生成 SpecialContact 相关代码(Entity/Mapper/Service) - [ ] 创建 SuperController 和 SuperService - [ ] 编写单元测试 ### 3. 功能扩展 - [ ] 支持机构搜索/过滤 - [ ] 支持按检查类型过滤可用机构 - [ ] 添加机构详情查询接口 - [ ] 添加费用试算接口 --- ## 注意事项 1. **权限控制**: 该接口应该限制只有下级医院的医生可以调用 2. **缓存优化**: 机构列表变化不频繁,可以添加缓存(5-10分钟) 3. **数据一致性**: remote_contact 表的 status=1 才是有效关系 4. **支付类型**: 务必正确配置 pay_type,影响费用结算流程 5. **特殊机构**: 特殊机构的排序需要由管理员在后台配置