package com.ruoyi.inhospvisit.controller; import com.ruoyi.common.core.service.IConfigService; import com.ruoyi.inhospvisit.api.InhospVisitFacade; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.ObjectProvider; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** * 出入院随访触发端点 —— 从 {@code ruoyi-admin} 的 {@code PatMedInhospController} 迁入。 * *

⚠️ URL 一个都不能变

* 类级路径仍是 {@code /smartor/patinhosp},三个方法级路径逐字照抄: * * 真实前端在仓库外({@code D:\daima\smartor\smartor-web},代理 {@code localhost:8095}), * 改了地址就无法回归。由 {@code sql/_probe/verify_inhospvisit_url_equivalence.py} 把关。 * *

迁入时同步删除

* {@code PatMedInhospController} 里对应这 3 个方法的 * {@code @PostMapping} 与 {@code @ApiOperation} 必须同时删掉 —— * 否则两个类都映射同一路径,Spring 会因 {@code Ambiguous mapping} 直接启动失败。 * *

与原 Controller 的两处差异(等价改写,已登记)

*
    *
  1. 不再注入 {@code ISysConfigService}:{@code visit.early.day} 改由 * {@link InhospVisitTaskService} 内部读(它本来就要用这个值)。 * 原实现是在 Controller 里读好再传进去的,效果一致。
  2. *
  3. {@code active} 只用于"是否做门诊随访"的站点判断(原 L263 的 * {@code if (!active.equals("xh"))}),与原实现同一位置、同一写法。
  4. *
* *

开关如何生效

* 本模块的 {@code InhospVisitAvailabilityInterceptor} 通过 * {@code InhospVisitWebConfig} 挂在这两条精确路径上: *
 * /smartor/patinhosp/dealOutHospInfo
 * /smartor/patinhosp/dealOutHospInfoBySchedule
 * 
* 迁入后"模块自己的端点 + 模块自己的拦截器"终于同处一个模块, * 不再是跨模块注册(那是本次改造期间的一个临时状态)。 *

* ⚠️ {@code /addOperationSubTask} 刻意不挂拦截器:它的实现本次未搬 * (属第二批 {@code ruoyi-othervisit}),挂上会让"还没搬走的端点"也受本开关影响。 */ @Slf4j @Api(description = "出入院随访触发") @RestController @RequestMapping("/smartor/patinhosp") public class InhospVisitController { /** 站点:新华(暂时不做门诊随访) */ private static final String SITE_XH = "xh"; /** 出院随访「通知类任务」提前几天发(原 Controller 从 sys_config 读的就是这个键) */ private static final String VISIT_EARLY_DAY_KEY = "visit.early.day"; @Value("${spring.profiles.active}") private String active; @Autowired private InhospVisitFacade inhospVisitFacade; /** * 参数配置服务(ruoyi-common 的接口,实现在 ruoyi-system)。 *

* ⚠️ 用 {@code ObjectProvider} 惰性取:本模块只依赖 ruoyi-common, * 在独立部署/测试等"容器里没有实现"的场景下不能因此启动失败。 *

* ⚠️ 必须由 Controller 读、不能传给 Service 去读: * 原实现就是"Controller 读好再传进去"(原 L259/L274/L285), * Service 层收的是值。保持这个形状,行为才一致。 */ @Autowired private ObjectProvider configServiceProvider; /** * 出院随访主扫描 + 门诊随访(原 {@code PatMedInhospController#dealOutHospInfo} L256-266)。 *

* 逐行对应: *

     * String config = configService.selectConfigByKey("visit.early.day");
     * //出院表
     * iPatMedInhospService.dealOutHospInfo(config);
     * //门诊表(新华的暂时不做门诊随访)
     * if (!active.equals("xh")) {
     *     iPatMedOuthospService.dealOutpatientInfo();
     * }
     * 
* 搬迁后 {@code config} 由 {@link InhospVisitTaskService} 内部读取。 * 返回类型保持 {@code void}(与前端契约一致),不改出参。 */ @ApiOperation("dealOutHospInfo") @PostMapping("/dealOutHospInfo") public void dealOutHospInfo() { // 原 L259:String config = configService.selectConfigByKey("visit.early.day"); String config = readVisitEarlyDay(); //出院表(含入院宣教 / 药品宣教 / 规则编排 / 手术随访 / 再入院处理) inhospVisitFacade.dealOutHospInfo(config); //门诊表(新华的暂时不做门诊随访) if (!SITE_XH.equals(active)) { inhospVisitFacade.dealOutpatientInfo(); } } /** * 任务组首轮纳入(原 {@code PatMedInhospController#dealOutHospInfoBySchedule} L271-277)。 *

* ⚠️ 实现本次未搬迁(含手术分支与任务组 builder,属第二批范围), * 由门面转发到 smartor 的实现 —— 行为与原 Controller 直接调用完全一致。 */ @ApiOperation("dealOutHospInfoBySchedule") @PostMapping("/dealOutHospInfoBySchedule") public void dealOutHospInfoBySchedule() { // 原 L274:String config = configService.selectConfigByKey("visit.early.day"); inhospVisitFacade.dealOutHospInfoBySchedule(readVisitEarlyDay()); } /** * 手术随访手动触发(原 {@code PatMedInhospController#addOperationSubTask} L282-287)。 *

* ⚠️ 实现本次未搬迁(属第二批 {@code ruoyi-othervisit}), * 由门面转发到 smartor 的实现。 */ @ApiOperation("addOperationSubTask") @PostMapping("/addOperationSubTask") public void addOperationSubTask() { // 原 L285:String config = configService.selectConfigByKey("visit.early.day"); inhospVisitFacade.addOperationSubTask(readVisitEarlyDay()); } /** * 读 {@code sys_config: visit.early.day}。 *

* 对应原 Controller 三处 {@code configService.selectConfigByKey("visit.early.day")}。 * 取不到(没有实现 / 读库异常)时返回 {@code null} 并打 WARN —— * 原实现在这种情况下拿到的也是 {@code null}({@code selectConfigByKey} 查不到即返回 null), * 所以语义一致。 */ private String readVisitEarlyDay() { if (configServiceProvider == null) { return null; } try { IConfigService svc = configServiceProvider.stream().findFirst().orElse(null); if (svc == null) { log.warn("【出入院随访】容器里没有 IConfigService 实现,{} 按未配置(null)处理。", VISIT_EARLY_DAY_KEY); return null; } return svc.selectConfigByKey(VISIT_EARLY_DAY_KEY); } catch (Exception e) { log.warn("【出入院随访】读取 {} 失败,按未配置(null)处理:{}", VISIT_EARLY_DAY_KEY, e.toString()); return null; } } }