package com.ruoyi.publicity.config;
import com.ruoyi.common.exception.ServiceException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 宣教模块开关拦截器。
*
* 作用:当开关关闭({@code sys_config} 中 {@code publicity.enabled=false})时,
* 命中宣教生成端点的请求会被立即拦下并抛出 {@link ServiceException},
* 由 RuoYi 的全局异常处理器返回明确的业务错误提示(而不是 404 或静默返回 0)。
*
* 开关值由 {@link PublicitySwitch} 在运行时读取({@code sys_config},10 秒进程内缓存),
* 因此改完参数设置不需要重启,最多 10 秒即生效。
*
* 与 {@code InhospVisitAvailabilityInterceptor} 完全同款(同一套约定与理由)。
*
*
⚠️ 只挂在两个生成端点的精确路径上
* 绝不用 {@code /smartor/publicity/**} 这种前缀:
*
* - {@code /status} 是只读状态查询,模块关掉时恰恰最需要它来排查,
* 所以刻意不挂拦截器;
* - 将来若本模块再添查询类端点,也应默认"可用",只有真正会"生成宣教"的端点才受开关约束。
*
*
* ⚠️ 本拦截器不覆盖定时任务与主流程
* 宣教在主流程里是被 {@code dealOutHospInfo} 经门面调用的(不走 MVC),
* 因此不受本拦截器影响;那一路的开关判断在 {@code PublicityFacade#isEnabled()} 里,
* 关闭时返回 0 并打 WARN,绝不拖垮出入院随访主流程。
*/
@Slf4j
@Component
public class PublicityAvailabilityInterceptor implements HandlerInterceptor {
/**
* 模块被关闭时返回给调用方的错误提示(前端可直接展示)
*/
public static final String DISABLED_MESSAGE =
"宣教功能未启用(参数配置 publicity.enabled=false),该接口不可用;"
+ "注意这与入院宣教自身的业务开关 in.helibrary.switch 是两回事,"
+ "后者需为 \"2\" 入院宣教才会执行";
private final PublicitySwitch publicitySwitch;
public PublicityAvailabilityInterceptor(PublicitySwitch publicitySwitch) {
this.publicitySwitch = publicitySwitch;
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
if (!publicitySwitch.isEnabled()) {
// request 允许为 null(单元测试直接调 preHandle 时不构造请求对象)
String method = request == null ? "-" : request.getMethod();
String uri = request == null ? "-" : request.getRequestURI();
log.warn("【宣教】模块已关闭(参数配置 publicity.enabled=false),拒绝访问 {} {}", method, uri);
throw new ServiceException(DISABLED_MESSAGE);
}
return true;
}
}