liusheng
8 天以前 f0a09ee996ab2605869844d6a3d812709e2bf0fa
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
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} 挂到电话模块自己的端点上。
 *
 * <h3>为什么必须逐个精确枚举(不能用前缀)</h3>
 * 电话端点<b>刻意保持原有 URL 不变</b>(外部电话平台的回调地址不能改),因此它散落在两个前缀下:
 * <pre>
 * /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 结果处理
 * </pre>
 * 这两个前缀<b>都不是电话模块独占</b>:
 * <ul>
 *   <li>{@code /smartor/serviceSubtask/**} 下还有 40+ 个随访端点(归 ruoyi-task);</li>
 *   <li>{@code /smartor/shphone/**} 下还有 {@code addOutboundInstance}(归 smartor 的外呼实例配置)。</li>
 * </ul>
 * 用前缀会把别人的端点一起拦掉,所以这里只挂上面这 8 条精确路径。
 * <p>
 * 与之配套:{@code TaskWebConfig} 里把前 6 条(电话自己的)用 {@code excludePathPatterns} 排除掉,
 * 避免"关任务"顺手把电话回调也关了 —— 电话已独立成模块,开关理应各自独立。
 *
 * <h3>新增端点时的约定</h3>
 * 往后本模块若再加端点:默认<b>不</b>加入本清单(回调类端点必须加),
 * 并同步更新 {@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);
    }
}