package com.ruoyi.phone.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* 电话模块的 MVC 配置:把 {@link PhoneAvailabilityInterceptor} 挂到电话模块自己的端点上。
*
*
为什么必须逐个精确枚举(不能用前缀)
* 电话端点刻意保持原有 URL 不变(外部电话平台的回调地址不能改),因此它散落在两个前缀下:
*
* /smartor/serviceSubtask/phoneCallBack 上海:语音识别结果回调
* /smartor/serviceSubtask/phoneCallBackYQ 雨绮:ASR / 静默 / 播放事件回调
* /smartor/serviceSubtask/taskPull 雨绮:任务拉取
* /smartor/serviceSubtask/saveQuestionAnswerPhone 电话:患者问题结果记录
* /smartor/serviceSubtask/recordAcceptshanghai 上海:通话记录回调
* /smartor/serviceSubtask/recordAccept 雨绮:通话记录回调
* /smartor/shphone/getFirstQues 三汇:按号码取首个问题
* /smartor/shphone/processResust 三汇:ASR 结果处理
*
* 这两个前缀都不是电话模块独占:
*
* - {@code /smartor/serviceSubtask/**} 下还有 40+ 个随访端点(归 ruoyi-task);
* - {@code /smartor/shphone/**} 下还有 {@code addOutboundInstance}(归 smartor 的外呼实例配置)。
*
* 用前缀会把别人的端点一起拦掉,所以这里只挂上面这 8 条精确路径。
*
* 与之配套:{@code TaskWebConfig} 里把前 6 条(电话自己的)用 {@code excludePathPatterns} 排除掉,
* 避免"关任务"顺手把电话回调也关了 —— 电话已独立成模块,开关理应各自独立。
*
*
新增端点时的约定
* 往后本模块若再加端点:默认不加入本清单(回调类端点必须加),
* 并同步更新 {@code PhoneSwitchCheck} 里的受保护路径条数断言。
*/
@Configuration
public class PhoneWebConfig implements WebMvcConfigurer {
/**
* 上海:语音识别结果回调
*/
public static final String PHONE_CALLBACK_ENDPOINT = "/smartor/serviceSubtask/phoneCallBack";
/**
* 雨绮:ASR / 静默 / 播放事件回调
*/
public static final String PHONE_CALLBACK_YQ_ENDPOINT = "/smartor/serviceSubtask/phoneCallBackYQ";
/**
* 雨绮:任务拉取
*/
public static final String TASK_PULL_ENDPOINT = "/smartor/serviceSubtask/taskPull";
/**
* 电话:患者问题结果记录
*/
public static final String SAVE_QUESTION_ANSWER_PHONE_ENDPOINT =
"/smartor/serviceSubtask/saveQuestionAnswerPhone";
/**
* 上海:通话记录回调
*/
public static final String RECORD_ACCEPT_SHANGHAI_ENDPOINT =
"/smartor/serviceSubtask/recordAcceptshanghai";
/**
* 雨绮:通话记录回调
*/
public static final String RECORD_ACCEPT_ENDPOINT = "/smartor/serviceSubtask/recordAccept";
/**
* 三汇:按号码取首个问题
*/
public static final String SH_GET_FIRST_QUES_ENDPOINT = "/smartor/shphone/getFirstQues";
/**
* 三汇:ASR 结果处理
*/
public static final String SH_PROCESS_RESUST_ENDPOINT = "/smartor/shphone/processResust";
@Autowired
private PhoneAvailabilityInterceptor phoneAvailabilityInterceptor;
/**
* 供测试/非 Spring 环境直接构造
*/
public PhoneWebConfig() {
}
public PhoneWebConfig(PhoneAvailabilityInterceptor phoneAvailabilityInterceptor) {
this.phoneAvailabilityInterceptor = phoneAvailabilityInterceptor;
}
/**
* 本模块需要"关闭即明确报错"的 URL 路径(供校验脚本/单元测试断言)
*/
public static String[] guardedPathPatterns() {
return new String[]{
PHONE_CALLBACK_ENDPOINT,
PHONE_CALLBACK_YQ_ENDPOINT,
TASK_PULL_ENDPOINT,
SAVE_QUESTION_ANSWER_PHONE_ENDPOINT,
RECORD_ACCEPT_SHANGHAI_ENDPOINT,
RECORD_ACCEPT_ENDPOINT,
SH_GET_FIRST_QUES_ENDPOINT,
SH_PROCESS_RESUST_ENDPOINT,
};
}
/**
* 挂在 {@code /smartor/serviceSubtask/**} 前缀下、但属于电话模块的路径
* (供 {@code TaskWebConfig} 排除,见类注释)。
*/
public static String[] subtaskPathsOwnedByPhone() {
return new String[]{
PHONE_CALLBACK_ENDPOINT,
PHONE_CALLBACK_YQ_ENDPOINT,
TASK_PULL_ENDPOINT,
SAVE_QUESTION_ANSWER_PHONE_ENDPOINT,
RECORD_ACCEPT_SHANGHAI_ENDPOINT,
RECORD_ACCEPT_ENDPOINT,
};
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(phoneAvailabilityInterceptor)
.addPathPatterns(guardedPathPatterns())
// 拦截器本身很轻(只读一个 boolean),order 给个小值让它在业务拦截器之前执行
.order(-100);
}
}