package com.ruoyi.othervisit.api; import com.ruoyi.common.core.service.OtherVisitApi; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.ObjectProvider; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; /** * {@link OtherVisitApi} 的本模块实现。 * *

它取代了什么

* 在 {@code ruoyi-othervisit} 建好之前,{@link OtherVisitApi} 只有 smartor 侧的 * 过渡桥接 {@code OtherVisitApiBridge}。手术随访的实现搬进本模块后, * 由本类接管 —— 这正是那个 Bridge 的类注释里预告的"将来动作"。 * *

⚠️ 本类两个方法本次都还委托 smartor(刻意,不是漏做)

* * * * * * * * *
接口方法原实现位置为什么本次不搬
{@link #addOperationSubTask(String)}{@code PatMedInhospServiceImpl#addOperationSubTask} L1247-1316它是手术等级({@code oplevelcode})+ 离院科室/病区维度的扫描, * 属"出院随访里混着的手术分支",且依赖 * {@code ServiceTaskoperMapper}(仍在 smartor)与 * {@code writeInSubTaskForOp}(依赖 {@code ScheduleSubtaskBuilder})。
{@link #dealOutHospInfoBySchedule(String)}同文件 L380-614它的非手术分支与"HIS 自动纳入"、"前端手动勾选"共用 * {@code ScheduleSubtaskBuilder}。搬它得连 builder 一起搬 —— * 那是独立的一次改造。
* *

那本模块搬了什么?

* 手术编码({@code opcode})维度的那条扫描: * {@code PatMedOperationServiceImpl#dealOperationInfo}(原 L107-149)。 * 它的入口不走本接口,而是 {@link OtherVisitFacade#dealOperationInfo()} —— * 调用方是 {@code RyTask#dealOperationInfo}(定时任务),已直接改走门面。 * 之所以不塞进本接口,是因为两者语义不同: * 接口上那两个是"出院/任务组流程里的手术分支",而这条是"手术记录自身的扫描"。 * *

⚠️ 为什么编译期看不到 smartor

* 依赖方向是 smartor → ruoyi-othervisit,反过来会形成 Maven 循环依赖,直接构建失败。 * 所以这里用 {@code ObjectProvider} 在运行时按类型惰性查找 * smartor 侧那个承接实现,并排除本类自己(否则会自己调自己 → {@code StackOverflowError})。 * 取不到就打 WARN 并返回安全值,绝不让定时任务抛异常。 * * @see OtherVisitApi */ @Slf4j @Component public class OtherVisitApiImpl implements OtherVisitApi { /** * smartor 侧的过渡承接({@code com.smartor.service.impl.bridge.OtherVisitApiBridge})。 *

* ⚠️ 类型参数刻意写成 {@link OtherVisitApi} 而不是那个具体类: * 本模块编译期看不到 smartor 的类型(也不允许看到)。 */ @Autowired private ObjectProvider otherVisitApiProvider; /** * 手术随访扫描(手术等级 + 离院科室/病区维度)—— 本次仍委托 smartor。 * * @param config {@code sys_config: visit.early.day} 的值,可能为 null * @return 处理的手术记录数;承接实现不可用时返回 0 */ @Override public int addOperationSubTask(String config) { OtherVisitApi delegate = findExternalDelegate(); if (delegate == null) { log.warn("【手术随访】addOperationSubTask 的 smartor 侧承接实现不可用(未打进应用或未装配),本次跳过。"); return 0; } return delegate.addOperationSubTask(config); } /** * 任务组(appltype=5)首轮纳入 —— 本次仍委托 smartor。 * * @param config {@code sys_config: visit.early.day} * @return 原实现固定返回 1;承接实现不可用时返回 0 */ @Override public int dealOutHospInfoBySchedule(String config) { OtherVisitApi delegate = findExternalDelegate(); if (delegate == null) { log.warn("【手术随访】dealOutHospInfoBySchedule 的 smartor 侧承接实现不可用(未打进应用或未装配),本次跳过。"); return 0; } return delegate.dealOutHospInfoBySchedule(config); } /** * 找 smartor 侧那个承接实现。 *

* ⚠️ 必须排除本类:本类也实现了 {@link OtherVisitApi}, * 若不过滤就会取到自己,形成无限递归。 * ⚠️ 用 {@code stream()} 而不是 {@code getIfAvailable()}: * 后者在存在多个候选时行为不确定,而这里天然有两个候选实现(本类 + smartor 桥接)。 */ private OtherVisitApi findExternalDelegate() { if (otherVisitApiProvider == null) { return null; } try { return otherVisitApiProvider.stream() .filter(api -> api != this) .findFirst() .orElse(null); } catch (Exception e) { log.warn("【手术随访】获取其它随访承接实现失败,按不可用处理:{}", e.toString()); return null; } } }